FV3 Bundle
Subset_Define.f90
Go to the documentation of this file.
1 !
2 ! Subset_Define
3 !
4 ! Module containing the subset type definition and routines
5 ! to manipulate it.
6 !
7 !
8 ! CREATION HISTORY:
9 ! Written by: Paul van Delst, 26-May-2011
10 ! paul.vandelst@noaa.gov
11 !
12 
14 
15  ! -----------------
16  ! Environment setup
17  ! -----------------
18  ! Module usage
20  USE sort_utility , ONLY: insertionsort
21  ! Disable implicit typing
22  IMPLICIT NONE
23 
24 
25  ! ------------
26  ! Visibilities
27  ! ------------
28  ! Everything private by default
29  PRIVATE
30  ! Datatypes
31  PUBLIC :: subset_type
32  ! Operators
33  PUBLIC :: OPERATOR(==)
34  ! Procedures
35  PUBLIC :: subset_associated
36  PUBLIC :: subset_destroy
37  PUBLIC :: subset_create
38  PUBLIC :: subset_inspect
39  PUBLIC :: subset_defineversion
40  PUBLIC :: subset_setvalue
41  PUBLIC :: subset_getvalue
42  PUBLIC :: subset_generate
43 
44 
45  ! ---------------------
46  ! Procedure overloading
47  ! ---------------------
48  INTERFACE OPERATOR(==)
49  MODULE PROCEDURE subset_equal
50  END INTERFACE OPERATOR(==)
51 
52 
53  ! -----------------
54  ! Module Parameters
55  ! -----------------
56  CHARACTER(*), PARAMETER :: module_version_id = &
57  '$Id: Subset_Define.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'
58 
59 
60  ! -----------------------------------
61  ! Channel subset data type definition
62  ! -----------------------------------
63  TYPE :: subset_type
64  PRIVATE
65  ! Allocation indicator
66  LOGICAL :: is_allocated = .false.
67  ! Dimensions
68  INTEGER :: n_values = 0
69  ! Subset inforamtion
70  INTEGER, ALLOCATABLE :: number(:)
71  INTEGER, ALLOCATABLE :: index(:)
72  END TYPE subset_type
73 
74 
75 CONTAINS
76 
77 
78 !################################################################################
79 !################################################################################
80 !## ##
81 !## ## PUBLIC MODULE ROUTINES ## ##
82 !## ##
83 !################################################################################
84 !################################################################################
85 
86 !--------------------------------------------------------------------------------
87 !:sdoc+:
88 !
89 ! NAME:
90 ! Subset_Associated
91 !
92 ! PURPOSE:
93 ! Elemental function to test the status of the allocatable components
94 ! of the Subset structure.
95 !
96 ! CALLING SEQUENCE:
97 ! Status = Subset_Associated( Subset )
98 !
99 ! OBJECTS:
100 ! Subset: Structure which is to have its member's
101 ! status tested.
102 ! UNITS: N/A
103 ! TYPE: Subset_type
104 ! DIMENSION: Scalar or any rank
105 ! ATTRIBUTES: INTENT(IN)
106 !
107 ! FUNCTION RESULT:
108 ! Status: The return value is a logical value indicating the
109 ! status of the Subset members.
110 ! .TRUE. - if ANY of the Subset allocatable members
111 ! are in use.
112 ! .FALSE. - if ALL of the Subset allocatable members
113 ! are not in use.
114 ! UNITS: N/A
115 ! TYPE: LOGICAL
116 ! DIMENSION: Same as input
117 !
118 !:sdoc-:
119 !--------------------------------------------------------------------------------
120 
121  ELEMENTAL FUNCTION subset_associated( Subset ) RESULT( Status )
122  TYPE(subset_type), INTENT(IN) :: subset
123  LOGICAL :: status
124  status = subset%Is_Allocated
125  END FUNCTION subset_associated
126 
127 
128 !--------------------------------------------------------------------------------
129 !:sdoc+:
130 !
131 ! NAME:
132 ! Subset_Destroy
133 !
134 ! PURPOSE:
135 ! Elemental subroutine to re-initialize Subset objects.
136 !
137 ! CALLING SEQUENCE:
138 ! CALL Subset_Destroy( Subset )
139 !
140 ! OBJECTS:
141 ! Subset: Re-initialized Subset structure.
142 ! UNITS: N/A
143 ! TYPE: Subset_type
144 ! DIMENSION: Scalar or any rank
145 ! ATTRIBUTES: INTENT(OUT)
146 !
147 !:sdoc-:
148 !--------------------------------------------------------------------------------
149 
150  ELEMENTAL SUBROUTINE subset_destroy( Subset )
151  TYPE(subset_type), INTENT(OUT) :: subset
152  subset%Is_Allocated = .false.
153  subset%n_Values = 0
154  END SUBROUTINE subset_destroy
155 
156 
157 !--------------------------------------------------------------------------------
158 !:sdoc+:
159 !
160 ! NAME:
161 ! Subset_Create
162 !
163 ! PURPOSE:
164 ! Elemental subroutine to create an instance of an Subset object.
165 !
166 ! CALLING SEQUENCE:
167 ! CALL Subset_Create( Subset , &
168 ! n_Values )
169 !
170 ! OBJECTS:
171 ! Subset: Subset object structure.
172 ! UNITS: N/A
173 ! TYPE: Subset_type
174 ! DIMENSION: Scalar or any rank
175 ! ATTRIBUTES: INTENT(OUT)
176 !
177 ! INPUTS:
178 ! n_Values: Number of values in the subset.
179 ! Must be > 0.
180 ! UNITS: N/A
181 ! TYPE: INTEGER
182 ! DIMENSION: Scalar
183 ! ATTRIBUTES: INTENT(IN)
184 !
185 !:sdoc-:
186 !--------------------------------------------------------------------------------
187 
188  ELEMENTAL SUBROUTINE subset_create( &
189  Subset , & ! Output
190  n_Values ) ! Input
191  ! Arguments
192  TYPE(subset_type), INTENT(OUT) :: subset
193  INTEGER , INTENT(IN) :: n_values
194  ! Local variables
195  INTEGER :: alloc_stat
196 
197  ! Check input
198  IF ( n_values < 1 ) RETURN
199 
200  ! Perform the allocation
201  ALLOCATE( subset%Number( n_values ), &
202  subset%Index( n_values ), &
203  stat = alloc_stat )
204  IF ( alloc_stat /= 0 ) RETURN
205 
206 
207  ! Initialise
208  ! ...Dimensions
209  subset%n_Values = n_values
210  ! ...Arrays
211  subset%Number = 0
212  subset%Index = 0
213 
214 
215  ! Set allocation indicator
216  subset%Is_Allocated = .true.
217 
218  END SUBROUTINE subset_create
219 
220 
221 !--------------------------------------------------------------------------------
222 !:sdoc+:
223 !
224 ! NAME:
225 ! Subset_Inspect
226 !
227 ! PURPOSE:
228 ! Subroutine to print the contents of a Subset object to stdout.
229 !
230 ! CALLING SEQUENCE:
231 ! CALL Subset_Inspect( Subset )
232 !
233 ! OBJECTS:
234 ! Subset: Subset object to display.
235 ! UNITS: N/A
236 ! TYPE: Subset_type
237 ! DIMENSION: Scalar
238 ! ATTRIBUTES: INTENT(IN)
239 !
240 !:sdoc-:
241 !--------------------------------------------------------------------------------
242 
243  SUBROUTINE subset_inspect( Subset )
244  TYPE(subset_type), INTENT(IN) :: subset
245  WRITE(*,'(1x,"Subset OBJECT")')
246  ! Dimensions
247  WRITE(*,'(3x,"n_Values:",1x,i0)') subset%n_Values
248  IF ( .NOT. subset_associated(subset) ) RETURN
249  ! Subset info
250  WRITE(*,'(3x,"Number :")')
251  WRITE(*,'(10(1x,i5,:))') subset%Number
252  WRITE(*,'(3x,"Index :")')
253  WRITE(*,'(10(1x,i5,:))') subset%Index
254 
255  END SUBROUTINE subset_inspect
256 
257 
258 !--------------------------------------------------------------------------------
259 !:sdoc+:
260 !
261 ! NAME:
262 ! Subset_DefineVersion
263 !
264 ! PURPOSE:
265 ! Subroutine to return the version information for the
266 ! definition module(s).
267 !
268 ! CALLING SEQUENCE:
269 ! CALL Subset_DefineVersion( Id )
270 !
271 ! OUTPUTS:
272 ! Id: Character string containing the version Id information for
273 ! this module.
274 ! UNITS: N/A
275 ! TYPE: CHARACTER(*)
276 ! DIMENSION: Scalar
277 ! ATTRIBUTES: INTENT(OUT)
278 !
279 !:sdoc-:
280 !--------------------------------------------------------------------------------
281 
282  SUBROUTINE subset_defineversion( Id )
283  CHARACTER(*), INTENT(OUT) :: id
284  id = module_version_id
285  END SUBROUTINE subset_defineversion
286 
287 
288 !--------------------------------------------------------------------------------
289 !:sdoc+:
290 !
291 ! NAME:
292 ! Subset_SetValue
293 !
294 ! PURPOSE:
295 ! Subroutine to set the contents of a Subset object.
296 !
297 ! CALLING SEQUENCE:
298 ! CALL Subset_SetValue( Subset, Number=Number, Index=Index )
299 !
300 ! OBJECTS:
301 ! Subset: Subset object for which values are to be set.
302 ! UNITS: N/A
303 ! TYPE: Subset_type
304 ! DIMENSION: Scalar
305 ! ATTRIBUTES: INTENT(IN OUT)
306 !
307 ! OPTIONAL INPUTS:
308 ! Number: Integer array to which the Number component of the Subset
309 ! object is to be set. The size of the input must match
310 ! the allocated size of the component, otherwise all the
311 ! component number values are set to zero.
312 ! UNITS: N/A
313 ! TYPE: INTEGER
314 ! DIMENSION: Rank-1
315 ! ATTRIBUTES: INTENT(IN), OPTIONAL
316 !
317 ! Index: Integer array to which the Index component of the Subset
318 ! object is to be set. The size of the input must match
319 ! the allocated size of the component, otherwise all the
320 ! component index values are set to zero.
321 ! UNITS: N/A
322 ! TYPE: INTEGER
323 ! DIMENSION: Rank-1
324 ! ATTRIBUTES: INTENT(IN), OPTIONAL
325 !
326 !:sdoc-:
327 !--------------------------------------------------------------------------------
328 
329  SUBROUTINE subset_setvalue( &
330  Subset , & ! Input
331  Number , & ! Optional input
332  Index ) ! Optional input
333  ! Arguments
334  TYPE(subset_type), INTENT(IN OUT) :: subset
335  INTEGER, OPTIONAL, INTENT(IN) :: number(:)
336  INTEGER, OPTIONAL, INTENT(IN) :: index(:)
337 
338  IF ( .NOT. subset_associated(subset) ) RETURN
339 
340  IF ( PRESENT(number) ) THEN
341  IF ( SIZE(number) == subset%n_Values ) THEN
342  subset%Number = number
343  ELSE
344  subset%Number = 0
345  END IF
346  END IF
347 
348  IF ( PRESENT(index) ) THEN
349  IF ( SIZE(index) == subset%n_Values ) THEN
350  subset%Index = index
351  ELSE
352  subset%Index = 0
353  END IF
354  END IF
355 
356  END SUBROUTINE subset_setvalue
357 
358 
359 !--------------------------------------------------------------------------------
360 !:sdoc+:
361 !
362 ! NAME:
363 ! Subset_GetValue
364 !
365 ! PURPOSE:
366 ! Subroutine to get and return the contents of a Subset object.
367 !
368 ! CALLING SEQUENCE:
369 ! CALL Subset_GetValue( Subset, n_Values=n_Values, Number=Number, Index=Index )
370 !
371 ! OBJECTS:
372 ! Subset: Subset object from which values are to be retrieved.
373 ! UNITS: N/A
374 ! TYPE: Subset_type
375 ! DIMENSION: Scalar
376 ! ATTRIBUTES: INTENT(IN)
377 !
378 ! OPTIONAL OUTPUTS:
379 ! n_Values: The dimension of the components of the Subset object.
380 ! UNITS: N/A
381 ! TYPE: INTEGER
382 ! DIMENSION: Scalar
383 ! ATTRIBUTES: INTENT(OUT), OPTIONAL
384 !
385 ! Number: Integer array to which the values of the Number
386 ! component of the Subset object are to be assigned.
387 ! The actual argument must be defined as allocatable.
388 ! UNITS: N/A
389 ! TYPE: INTEGER
390 ! DIMENSION: Rank-1
391 ! ATTRIBUTES: INTENT(OUT), OPTIONAL, ALLOCATABLE
392 !
393 ! Index: Integer array to which the values of the Index
394 ! component of the Subset object are to be assigned.
395 ! The actual argument must be defined as allocatable.
396 ! UNITS: N/A
397 ! TYPE: INTEGER
398 ! DIMENSION: Rank-1
399 ! ATTRIBUTES: INTENT(OUT), OPTIONAL, ALLOCATABLE
400 !:sdoc-:
401 !--------------------------------------------------------------------------------
402 
403  SUBROUTINE subset_getvalue( &
404  Subset , & ! Input
405  n_Values, & ! Optional output
406  Number , & ! Optional output
407  Index ) ! Optional output
408  ! Arguments
409  TYPE(subset_type), INTENT(IN) :: subset
410  INTEGER, OPTIONAL, INTENT(OUT) :: n_values
411  INTEGER, ALLOCATABLE, OPTIONAL, INTENT(OUT) :: number(:)
412  INTEGER, ALLOCATABLE, OPTIONAL, INTENT(OUT) :: index(:)
413  ! Local variables
414  INTEGER :: n
415 
416  n = subset%n_Values
417  IF ( PRESENT(n_values) ) n_values = n
418 
419  IF ( PRESENT(number) ) THEN
420  ALLOCATE(number(n))
421  number = subset%Number
422  END IF
423 
424  IF ( PRESENT(index) ) THEN
425  ALLOCATE(index(n))
426  index = subset%Index
427  END IF
428 
429  END SUBROUTINE subset_getvalue
430 
431 
432 !--------------------------------------------------------------------------------
433 !:sdoc+:
434 !
435 ! NAME:
436 ! Subset_Generate
437 !
438 ! PURPOSE:
439 ! Subroutine to generate the subset indexing and return
440 ! it in a Subset object.
441 !
442 ! CALLING SEQUENCE:
443 ! CALL Subset_Generate( Subset, List, Subset_List )
444 !
445 ! OBJECTS:
446 ! Subset: Subset object to hold the generated subset index
447 ! information
448 ! UNITS: N/A
449 ! TYPE: Subset_type
450 ! DIMENSION: Scalar
451 ! ATTRIBUTES: INTENT(OUT)
452 !
453 ! INPUTS:
454 ! List: Array of values from which a subset is to be extracted.
455 ! UNITS: N/A
456 ! TYPE: INTEGER
457 ! DIMENSION: Rank-1
458 ! ATTRIBUTES: INTENT(IN)
459 !
460 ! Subset_List: Array of values defining the subset.
461 ! UNITS: N/A
462 ! TYPE: INTEGER
463 ! DIMENSION: Rank-1
464 ! ATTRIBUTES: INTENT(IN)
465 !:sdoc-:
466 !--------------------------------------------------------------------------------
467 
468  SUBROUTINE subset_generate( &
469  Subset , & ! Output
470  List , & ! Input
471  Subset_List ) ! Input
472  ! Arguments
473  TYPE(subset_type), INTENT(OUT) :: subset
474  INTEGER , INTENT(IN) :: list(:)
475  INTEGER , INTENT(IN) :: subset_list(:)
476  ! Local variables
477  INTEGER :: sorted_list(size(list))
478  INTEGER :: sorted_subset_list(size(subset_list))
479  INTEGER :: i, n_list
480  INTEGER :: n_subset_list
481  INTEGER :: n_elements
482  INTEGER :: isubset, iextract
483 
484  ! Set up
485  ! ...No list data?
486  n_list = SIZE(list)
487  n_subset_list = SIZE(subset_list)
488  IF ( n_list < 1 .OR. n_subset_list < 1 ) RETURN
489 
490 
491  ! Sort the lists
492  sorted_list = list
493  CALL insertionsort( sorted_list )
494  sorted_subset_list = subset_list
495  CALL insertionsort( sorted_subset_list )
496 
497 
498  ! Count the elements to subset
499  n_elements = count( sorted_subset_list >= sorted_list(1) .AND. &
500  sorted_subset_list <= sorted_list(n_list) )
501  IF ( n_elements == 0 ) RETURN
502 
503 
504  ! Allocate the Subset structure
505  CALL subset_create( subset, n_elements )
506  IF ( .NOT. subset_associated( subset ) ) RETURN
507 
508 
509  ! Define the start points for the search
510  ! ...Determine the starting index in the SUBSET list array
511  isubset = minloc( sorted_subset_list - sorted_list(1), &
512  mask = ( (sorted_subset_list - sorted_list(1)) >= 0 ), &
513  dim = 1 )
514  ! ...Set the starting index in the output. This is always 1.
515  iextract = 1
516 
517 
518  ! Loop over the number of MAIN list elements
519  list_loop: DO i = 1, n_list
520  IF ( sorted_list(i) == sorted_subset_list(isubset) ) THEN ! Is the list element in the subset?
521  subset%Index( iextract ) = i ! Save the index...
522  subset%Number( iextract ) = sorted_list(i) ! ...and number
523  iextract = iextract + 1 ! Increment the extract...
524  isubset = isubset + 1 ! ...and subset indices
525  IF ( isubset > n_subset_list ) EXIT list_loop ! Exit loop if last element found
526  END IF
527  END DO list_loop
528 
529  END SUBROUTINE subset_generate
530 
531 
532 
533 !##################################################################################
534 !##################################################################################
535 !## ##
536 !## ## PRIVATE MODULE ROUTINES ## ##
537 !## ##
538 !##################################################################################
539 !##################################################################################
540 
541 !------------------------------------------------------------------------------
542 !
543 ! NAME:
544 ! Subset_Equal
545 !
546 ! PURPOSE:
547 ! Elemental function to test the equality of two Subset objects.
548 ! Used in OPERATOR(==) interface block.
549 !
550 ! CALLING SEQUENCE:
551 ! is_equal = Subset_Equal( x, y )
552 !
553 ! or
554 !
555 ! IF ( x == y ) THEN
556 ! ...
557 ! END IF
558 !
559 ! OBJECTS:
560 ! x, y: Two Subset objects to be compared.
561 ! UNITS: N/A
562 ! TYPE: Subset_type
563 ! DIMENSION: Scalar or any rank
564 ! ATTRIBUTES: INTENT(IN)
565 !
566 ! FUNCTION RESULT:
567 ! is_equal: Logical value indicating whether the inputs are equal.
568 ! UNITS: N/A
569 ! TYPE: LOGICAL
570 ! DIMENSION: Same as inputs.
571 !
572 !------------------------------------------------------------------------------
573 
574  ELEMENTAL FUNCTION subset_equal( x, y ) RESULT( is_equal )
575  TYPE(subset_type), INTENT(IN) :: x, y
576  LOGICAL :: is_equal
577 
578  ! Set up
579  is_equal = .false.
580 
581  ! Check the object association status
582  IF ( (.NOT. subset_associated(x)) .OR. &
583  (.NOT. subset_associated(y)) ) RETURN
584 
585  ! Check contents
586  ! ...Dimensions
587  IF ( x%n_Values /= y%n_Values ) RETURN
588  ! ...Arrays
589  IF ( all(x%Number == y%Number ) .AND. &
590  all(x%Index == y%Index ) ) &
591  is_equal = .true.
592 
593  END FUNCTION subset_equal
594 
595 END MODULE subset_define
subroutine, public subset_inspect(Subset)
character(*), parameter module_version_id
integer, parameter, public failure
elemental logical function, public subset_associated(Subset)
subroutine, public subset_setvalue(Subset, Number, Index)
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
elemental subroutine, public subset_destroy(Subset)
subroutine, public subset_getvalue(Subset, n_Values, Number, Index)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)
elemental logical function subset_equal(x, y)
subroutine, public subset_defineversion(Id)
subroutine, public subset_generate(Subset, List, Subset_List)
integer, parameter, public success
elemental subroutine, public subset_create(Subset, n_Values)
integer, parameter, public information