Line data Source code
1 : module cam_grid_support
2 : use shr_kind_mod, only: r8=>shr_kind_r8, r4=>shr_kind_r4, max_chars=>shr_kind_cl
3 : use shr_kind_mod, only: i8=>shr_kind_i8, i4=>shr_kind_i4
4 : use shr_sys_mod, only: shr_sys_flush
5 : use pio, only: iMap=>PIO_OFFSET_KIND, var_desc_t
6 : use cam_abortutils, only: endrun
7 : use cam_logfile, only: iulog
8 : use spmd_utils, only: masterproc
9 : use cam_pio_utils, only: cam_pio_handle_error
10 : use cam_map_utils, only: cam_filemap_t
11 :
12 : implicit none
13 : private
14 :
15 : public iMap
16 :
17 : integer, parameter, public :: max_hcoordname_len = 16
18 : integer, parameter, public :: maxsplitfiles = 2
19 :
20 : type, public :: vardesc_ptr_t
21 : type(var_desc_t), pointer :: p => NULL()
22 : end type vardesc_ptr_t
23 : !---------------------------------------------------------------------------
24 : !
25 : ! horiz_coord_t: Information for horizontal dimension attributes
26 : !
27 : !---------------------------------------------------------------------------
28 : type, public :: horiz_coord_t
29 : private
30 : character(len=max_hcoordname_len) :: name = '' ! coordinate name
31 : character(len=max_hcoordname_len) :: dimname = '' ! dimension name
32 : ! NB: If dimname is blank, it is assumed to be name
33 : integer :: dimsize = 0 ! global size of dimension
34 : character(len=max_chars) :: long_name = '' ! 'long_name' attribute
35 : character(len=max_chars) :: units = '' ! 'units' attribute
36 : real(r8), pointer :: values(:) => NULL() ! dim values (local if map)
37 : integer(iMap), pointer :: map(:) => NULL() ! map (dof) for dist. coord
38 : logical :: latitude ! .false. means longitude
39 : real(r8), pointer :: bnds(:,:) => NULL() ! bounds, if present
40 : type(vardesc_ptr_t) :: vardesc(maxsplitfiles) ! If we are to write coord
41 : type(vardesc_ptr_t) :: bndsvdesc(maxsplitfiles) ! If we are to write bounds
42 : contains
43 : procedure :: get_coord_len => horiz_coord_len
44 : procedure :: num_elem => horiz_coord_num_elem
45 : procedure :: global_size => horiz_coord_find_size
46 : procedure :: get_coord_name => horiz_coord_name
47 : procedure :: get_dim_name => horiz_coord_dim_name
48 : procedure :: get_long_name => horiz_coord_long_name
49 : procedure :: get_units => horiz_coord_units
50 : procedure :: write_attr => write_horiz_coord_attr
51 : procedure :: write_var => write_horiz_coord_var
52 : end type horiz_coord_t
53 :
54 : !---------------------------------------------------------------------------
55 : !
56 : ! cam_grid_attribute_t: Auxiliary quantity for a CAM grid
57 : !
58 : !---------------------------------------------------------------------------
59 : type, abstract :: cam_grid_attribute_t
60 : character(len=max_hcoordname_len) :: name = '' ! attribute name
61 : character(len=max_chars) :: long_name = '' ! attribute long_name
62 : type(vardesc_ptr_t) :: vardesc(maxsplitfiles)
63 : ! We aren't going to use this until we sort out PGI issues
64 : class(cam_grid_attribute_t), pointer :: next => NULL()
65 : contains
66 : procedure :: cam_grid_attr_init
67 : procedure(write_cam_grid_attr), deferred :: write_attr
68 : procedure(write_cam_grid_attr), deferred :: write_val
69 : procedure(print_attr_spec), deferred :: print_attr
70 : procedure :: print_attr_base
71 : end type cam_grid_attribute_t
72 :
73 : !---------------------------------------------------------------------------
74 : !
75 : ! cam_grid_attribute_0d_int_t: Global integral attribute
76 : !
77 : !---------------------------------------------------------------------------
78 : type, extends(cam_grid_attribute_t) :: cam_grid_attribute_0d_int_t
79 : integer :: ival
80 : contains
81 : procedure :: cam_grid_attr_init_0d_int
82 : procedure :: write_attr => write_cam_grid_attr_0d_int
83 : procedure :: write_val => write_cam_grid_val_0d_int
84 : procedure :: print_attr => print_attr_0d_int
85 : end type cam_grid_attribute_0d_int_t
86 :
87 : !---------------------------------------------------------------------------
88 : !
89 : ! cam_grid_attribute_0d_char_t: Global string attribute
90 : !
91 : !---------------------------------------------------------------------------
92 : type, extends(cam_grid_attribute_t) :: cam_grid_attribute_0d_char_t
93 : character(len=max_chars) :: val
94 : contains
95 : procedure :: cam_grid_attr_init_0d_char
96 : procedure :: write_attr => write_cam_grid_attr_0d_char
97 : procedure :: write_val => write_cam_grid_val_0d_char
98 : procedure :: print_attr => print_attr_0d_char
99 : end type cam_grid_attribute_0d_char_t
100 :
101 : !---------------------------------------------------------------------------
102 : !
103 : ! cam_grid_attribute_1d_int_t: 1-d integer attribute
104 : !
105 : !---------------------------------------------------------------------------
106 : type, extends(cam_grid_attribute_t) :: cam_grid_attribute_1d_int_t
107 : character(len=max_hcoordname_len) :: dimname ! attribute dimension
108 : integer :: dimsize ! Global array/map size
109 : integer, pointer :: values(:) => NULL()
110 : integer(iMap), pointer :: map(:) => NULL() ! map (dof) for I/O
111 : contains
112 : procedure :: cam_grid_attr_init_1d_int
113 : procedure :: write_attr => write_cam_grid_attr_1d_int
114 : procedure :: write_val => write_cam_grid_val_1d_int
115 : procedure :: print_attr => print_attr_1d_int
116 : end type cam_grid_attribute_1d_int_t
117 :
118 : !---------------------------------------------------------------------------
119 : !
120 : ! cam_grid_attribute_1d_r8_t: 1-d real*8 attribute
121 : !
122 : !---------------------------------------------------------------------------
123 : type, extends(cam_grid_attribute_t) :: cam_grid_attribute_1d_r8_t
124 : character(len=max_hcoordname_len) :: dimname ! attribute dimension
125 : integer :: dimsize ! Global array/map size
126 : real(r8), pointer :: values(:) => NULL()
127 : integer(iMap), pointer :: map(:) => NULL() ! map (dof) for I/O
128 : contains
129 : procedure :: cam_grid_attr_init_1d_r8
130 : procedure :: write_attr => write_cam_grid_attr_1d_r8
131 : procedure :: write_val => write_cam_grid_val_1d_r8
132 : procedure :: print_attr => print_attr_1d_r8
133 : end type cam_grid_attribute_1d_r8_t
134 :
135 : !---------------------------------------------------------------------------
136 : !
137 : ! cam_grid_attr_ptr_t: linked list of CAM grid attributes
138 : !
139 : !---------------------------------------------------------------------------
140 : type :: cam_grid_attr_ptr_t
141 : private
142 : class(cam_grid_attribute_t), pointer :: attr => NULL()
143 : type(cam_grid_attr_ptr_t), pointer :: next => NULL()
144 : contains
145 : private
146 : procedure, public :: initialize => initializeAttrPtr
147 : procedure, public :: getAttr => getAttrPtrAttr
148 : procedure, public :: getNext => getAttrPtrNext
149 : procedure, public :: setNext => setAttrPtrNext
150 : end type cam_grid_attr_ptr_t
151 :
152 : !---------------------------------------------------------------------------
153 : !
154 : ! cam_grid_t: Information for a CAM grid (defined by a dycore)
155 : !
156 : !---------------------------------------------------------------------------
157 : type :: cam_grid_t
158 : character(len=max_hcoordname_len) :: name = '' ! grid name
159 : integer :: id ! e.g., dyn_decomp
160 : type(horiz_coord_t), pointer :: lat_coord => NULL() ! Latitude coord
161 : type(horiz_coord_t), pointer :: lon_coord => NULL() ! Longitude coord
162 : logical :: unstructured ! Is this needed?
163 : logical :: block_indexed ! .false. for lon/lat
164 : logical :: attrs_defined(2) = .false.
165 : logical :: zonal_grid = .false.
166 : type(cam_filemap_t), pointer :: map => null() ! global dim map (dof)
167 : type(cam_grid_attr_ptr_t), pointer :: attributes => NULL()
168 : contains
169 : procedure :: print_cam_grid
170 : procedure :: is_unstructured => cam_grid_unstructured
171 : procedure :: is_block_indexed => cam_grid_block_indexed
172 : procedure :: is_zonal_grid => cam_grid_zonal_grid
173 : procedure :: coord_lengths => cam_grid_get_dims
174 : procedure :: coord_names => cam_grid_coord_names
175 : procedure :: dim_names => cam_grid_dim_names
176 : procedure :: num_elem => cam_grid_local_size
177 : procedure :: set_map => cam_grid_set_map
178 : procedure :: get_patch_mask => cam_grid_get_patch_mask
179 : procedure :: get_lon_lat => cam_grid_get_lon_lat
180 : procedure :: find_src_dims => cam_grid_find_src_dims
181 : procedure :: find_dest_dims => cam_grid_find_dest_dims
182 : procedure :: find_dimids => cam_grid_find_dimids
183 : procedure :: get_decomp => cam_grid_get_pio_decomp
184 : procedure :: read_darray_2d_int => cam_grid_read_darray_2d_int
185 : procedure :: read_darray_3d_int => cam_grid_read_darray_3d_int
186 : procedure :: read_darray_2d_double => cam_grid_read_darray_2d_double
187 : procedure :: read_darray_3d_double => cam_grid_read_darray_3d_double
188 : procedure :: read_darray_2d_real => cam_grid_read_darray_2d_real
189 : procedure :: read_darray_3d_real => cam_grid_read_darray_3d_real
190 : procedure :: write_darray_2d_int => cam_grid_write_darray_2d_int
191 : procedure :: write_darray_3d_int => cam_grid_write_darray_3d_int
192 : procedure :: write_darray_2d_double => cam_grid_write_darray_2d_double
193 : procedure :: write_darray_3d_double => cam_grid_write_darray_3d_double
194 : procedure :: write_darray_2d_real => cam_grid_write_darray_2d_real
195 : procedure :: write_darray_3d_real => cam_grid_write_darray_3d_real
196 : end type cam_grid_t
197 :
198 : !---------------------------------------------------------------------------
199 : !
200 : ! cam_grid_patch_t: Information for a patch of a CAM grid
201 : !
202 : !---------------------------------------------------------------------------
203 : type, public :: cam_grid_patch_t
204 : private
205 : integer :: grid_id = -1 ! grid containing patch points
206 : integer :: global_size = 0 ! var patch dim size
207 : integer :: global_lat_size = 0 ! lat patch dim size
208 : integer :: global_lon_size = 0 ! lon patch dim size
209 : integer :: num_points = 0 ! task-local size
210 : real(r8) :: lon_range(2)
211 : real(r8) :: lat_range(2)
212 : logical :: collected_columns ! Output unstructured
213 : type(cam_filemap_t), pointer :: mask => null() ! map for active pts
214 : integer(iMap), pointer :: latmap(:) => null() ! map for patch coords
215 : integer(iMap), pointer :: lonmap(:) => null() ! map for patch coords
216 : real(r8), pointer :: lonvals(:) => null() ! For collected output
217 : real(r8), pointer :: latvals(:) => null() ! For collected output
218 : contains
219 : procedure :: gridid => cam_grid_patch_get_id
220 : procedure :: get_axis_names => cam_grid_patch_get_axis_names
221 : procedure :: get_coord_long_name => cam_grid_patch_get_coord_long_name
222 : procedure :: get_coord_units => cam_grid_patch_get_coord_units
223 : procedure :: set_patch => cam_grid_patch_set_patch
224 : procedure :: get_decomp => cam_grid_patch_get_decomp
225 : procedure :: compact => cam_grid_patch_compact
226 : procedure :: active_cols => cam_grid_patch_get_active_cols
227 : procedure :: write_coord_vals => cam_grid_patch_write_vals
228 : procedure :: grid_index => cam_grid_patch_get_grid_index
229 : procedure :: deallocate => cam_grid_patch_deallocate
230 : !!XXgoldyXX: PGI workaround?
231 : ! COMPILER_BUG(goldy, 2014-11-28, pgi <= 14.9); Commented code should work
232 : ! procedure :: global_size_map => cam_grid_patch_get_global_size_map
233 : ! procedure :: global_size_axes => cam_grid_patch_get_global_size_axes
234 : ! generic :: get_global_size => global_size_map, global_size_axes
235 : procedure :: cam_grid_patch_get_global_size_map
236 : procedure :: cam_grid_patch_get_global_size_axes
237 : generic :: get_global_size => cam_grid_patch_get_global_size_map, cam_grid_patch_get_global_size_axes
238 : end type cam_grid_patch_t
239 :
240 : !---------------------------------------------------------------------------
241 : !
242 : ! cam_grid_header_info_t: Hold NetCDF dimension information for a CAM grid
243 : !
244 : !---------------------------------------------------------------------------
245 : type, public :: cam_grid_header_info_t
246 : private
247 : integer :: grid_id = -1 ! e.g., dyn_decomp
248 : integer, allocatable :: hdims(:) ! horizontal dimension ids
249 : type(var_desc_t), pointer :: lon_varid => NULL() ! lon coord variable
250 : type(var_desc_t), pointer :: lat_varid => NULL() ! lat coord variable
251 : contains
252 : procedure :: get_gridid => cam_grid_header_info_get_gridid
253 : procedure :: set_gridid => cam_grid_header_info_set_gridid
254 : procedure :: set_hdims => cam_grid_header_info_set_hdims
255 : procedure :: num_hdims => cam_grid_header_info_num_hdims
256 : procedure :: get_hdimid => cam_grid_header_info_hdim
257 : !!XXgoldyXX: Maybe replace this with horiz_coords for patches?
258 : procedure :: set_varids => cam_grid_header_info_set_varids
259 : procedure :: get_lon_varid => cam_grid_header_info_lon_varid
260 : procedure :: get_lat_varid => cam_grid_header_info_lat_varid
261 : procedure :: deallocate => cam_grid_header_info_deallocate
262 : end type cam_grid_header_info_t
263 :
264 : !---------------------------------------------------------------------------
265 : !
266 : ! END: types BEGIN: interfaces for types
267 : !
268 : !---------------------------------------------------------------------------
269 :
270 : ! Abstract interface for write_attr procedure of cam_grid_attribute_t class
271 : ! NB: This will not compile on some pre-13 Intel compilers
272 : ! (fails on 12.1.0.233 on Frankfurt, passes on 13.0.1.117 on Yellowstone)
273 : abstract interface
274 : subroutine write_cam_grid_attr(attr, File, file_index)
275 : use pio, only: file_desc_t
276 : import :: cam_grid_attribute_t
277 : ! Dummy arguments
278 : class(cam_grid_attribute_t), intent(inout) :: attr
279 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
280 : integer, optional, intent(in) :: file_index
281 : end subroutine write_cam_grid_attr
282 : end interface
283 :
284 : ! Abstract interface for print_attr procedure of cam_grid_attribute_t class
285 : abstract interface
286 : subroutine print_attr_spec(this)
287 : import :: cam_grid_attribute_t
288 : ! Dummy arguments
289 : class(cam_grid_attribute_t), intent(in) :: this
290 : end subroutine print_attr_spec
291 : end interface
292 :
293 : !! Grid variables
294 : integer, parameter :: maxhgrids = 16 ! arbitrary limit
295 : integer, save :: registeredhgrids = 0
296 : type(cam_grid_t), save :: cam_grids(maxhgrids)
297 :
298 : public :: horiz_coord_create
299 :
300 : ! Setup and I/O functions for grids rely on the grid's ID, not its index.
301 : public :: cam_grid_register, cam_grid_attribute_register
302 : public :: cam_grid_attribute_copy
303 : public :: cam_grid_write_attr, cam_grid_write_var
304 : public :: cam_grid_read_dist_array, cam_grid_write_dist_array
305 : ! Access functions for grids rely on the grid's ID or name, not its index.
306 : public :: cam_grid_dimensions, cam_grid_num_grids
307 : public :: cam_grid_check ! T/F if grid ID exists
308 : public :: cam_grid_id ! Grid ID (decomp) or -1 if error
309 : public :: cam_grid_get_local_size
310 : public :: cam_grid_get_file_dimids
311 : public :: cam_grid_get_decomp
312 : public :: cam_grid_get_gcid
313 : public :: cam_grid_get_array_bounds
314 : public :: cam_grid_get_coord_names, cam_grid_get_dim_names
315 : public :: cam_grid_has_blocksize, cam_grid_get_block_count
316 : public :: cam_grid_get_latvals, cam_grid_get_lonvals
317 : public :: cam_grid_get_coords
318 : public :: cam_grid_is_unstructured, cam_grid_is_block_indexed
319 : public :: cam_grid_attr_exists
320 : public :: cam_grid_is_zonal
321 : ! Functions for dealing with patch masks
322 : public :: cam_grid_compute_patch
323 : ! Functions for dealing with grid areas
324 : public :: cam_grid_get_areawt
325 :
326 : interface cam_grid_attribute_register
327 : module procedure add_cam_grid_attribute_0d_int
328 : module procedure add_cam_grid_attribute_0d_char
329 : module procedure add_cam_grid_attribute_1d_int
330 : module procedure add_cam_grid_attribute_1d_r8
331 : end interface
332 :
333 : interface cam_grid_dimensions
334 : module procedure cam_grid_dimensions_id
335 : module procedure cam_grid_dimensions_name
336 : end interface
337 :
338 : interface cam_grid_get_dim_names
339 : module procedure cam_grid_get_dim_names_id
340 : module procedure cam_grid_get_dim_names_name
341 : end interface
342 :
343 : interface cam_grid_read_dist_array
344 : module procedure cam_grid_read_dist_array_2d_int
345 : module procedure cam_grid_read_dist_array_3d_int
346 : module procedure cam_grid_read_dist_array_2d_double
347 : module procedure cam_grid_read_dist_array_3d_double
348 : module procedure cam_grid_read_dist_array_2d_real
349 : module procedure cam_grid_read_dist_array_3d_real
350 : end interface
351 :
352 : interface cam_grid_write_dist_array
353 : module procedure cam_grid_write_dist_array_2d_int
354 : module procedure cam_grid_write_dist_array_3d_int
355 : module procedure cam_grid_write_dist_array_2d_double
356 : module procedure cam_grid_write_dist_array_3d_double
357 : module procedure cam_grid_write_dist_array_2d_real
358 : module procedure cam_grid_write_dist_array_3d_real
359 : end interface
360 :
361 : ! Private interfaces
362 : interface get_cam_grid_index
363 : module procedure get_cam_grid_index_char ! For lookup by name
364 : module procedure get_cam_grid_index_int ! For lookup by ID
365 : end interface
366 :
367 : contains
368 :
369 : !!#######################################################################
370 : !!
371 : !! Horizontal coordinate functions
372 : !!
373 : !!#######################################################################
374 :
375 13824 : integer function horiz_coord_find_size(this, dimname) result(dimsize)
376 : ! Dummy arguments
377 : class(horiz_coord_t), intent(in) :: this
378 : character(len=*), intent(in) :: dimname
379 :
380 13824 : dimsize = -1
381 13824 : if (len_trim(this%dimname) == 0) then
382 0 : if(trim(dimname) == trim(this%name)) then
383 0 : dimsize = this%dimsize
384 : end if
385 : else
386 13824 : if(trim(dimname) == trim(this%dimname)) then
387 13824 : dimsize = this%dimsize
388 : end if
389 : end if
390 :
391 13824 : end function horiz_coord_find_size
392 :
393 0 : integer function horiz_coord_num_elem(this)
394 : ! Dummy arguments
395 : class(horiz_coord_t), intent(in) :: this
396 :
397 0 : if (associated(this%values)) then
398 0 : horiz_coord_num_elem = size(this%values)
399 : else
400 : horiz_coord_num_elem = 0
401 : end if
402 :
403 0 : end function horiz_coord_num_elem
404 :
405 923904 : subroutine horiz_coord_len(this, clen)
406 : ! Dummy arguments
407 : class(horiz_coord_t), intent(in) :: this
408 : integer, intent(out) :: clen
409 :
410 923904 : clen = this%dimsize
411 923904 : end subroutine horiz_coord_len
412 :
413 0 : subroutine horiz_coord_name(this, name)
414 : ! Dummy arguments
415 : class(horiz_coord_t), intent(in) :: this
416 : character(len=*), intent(out) :: name
417 :
418 0 : if (len(name) < len_trim(this%name)) then
419 0 : call endrun('horiz_coord_name: input name too short')
420 : end if
421 0 : name = trim(this%name)
422 0 : end subroutine horiz_coord_name
423 :
424 2176512 : subroutine horiz_coord_dim_name(this, dimname)
425 : ! Dummy arguments
426 : class(horiz_coord_t), intent(in) :: this
427 : character(len=*), intent(out) :: dimname
428 :
429 2176512 : if (len_trim(this%dimname) > 0) then
430 : ! We have a separate dimension name (e.g., ncol)
431 2176512 : if (len(dimname) < len_trim(this%dimname)) then
432 0 : call endrun('horiz_coord_dimname: input name too short')
433 : end if
434 2176512 : dimname = trim(this%dimname)
435 : else
436 : ! No dimension name so we use the coordinate's name
437 : ! i.e., The dimension name is the same as the coordinate variable
438 0 : if (len(dimname) < len_trim(this%name)) then
439 0 : call endrun('horiz_coord_dimname: input name too short')
440 : end if
441 0 : dimname = trim(this%name)
442 : end if
443 2176512 : end subroutine horiz_coord_dim_name
444 :
445 0 : subroutine horiz_coord_long_name(this, name)
446 :
447 : ! Dummy arguments
448 : class(horiz_coord_t), intent(in) :: this
449 : character(len=*), intent(out) :: name
450 :
451 0 : if (len(name) < len_trim(this%long_name)) then
452 0 : call endrun('horiz_coord_long_name: input name too short')
453 : else
454 0 : name = trim(this%long_name)
455 : end if
456 :
457 0 : end subroutine horiz_coord_long_name
458 :
459 0 : subroutine horiz_coord_units(this, units)
460 :
461 : ! Dummy arguments
462 : class(horiz_coord_t), intent(in) :: this
463 : character(len=*), intent(out) :: units
464 :
465 0 : if (len(units) < len_trim(this%units)) then
466 0 : call endrun('horiz_coord_units: input units too short')
467 : else
468 0 : units = trim(this%units)
469 : end if
470 :
471 0 : end subroutine horiz_coord_units
472 :
473 13824 : function horiz_coord_create(name, dimname, dimsize, long_name, units, &
474 13824 : lbound, ubound, values, map, bnds) result(newcoord)
475 :
476 : ! Dummy arguments
477 : character(len=*), intent(in) :: name
478 : character(len=*), intent(in) :: dimname
479 : integer, intent(in) :: dimsize
480 : character(len=*), intent(in) :: long_name
481 : character(len=*), intent(in) :: units
482 : ! NB: Sure, pointers would have made sense but . . . PGI
483 : integer, intent(in) :: lbound
484 : integer, intent(in) :: ubound
485 : real(r8), intent(in) :: values(lbound:ubound)
486 : integer(iMap), intent(in), optional :: map(ubound-lbound+1)
487 : real(r8), intent(in), optional :: bnds(2,lbound:ubound)
488 : type(horiz_coord_t), pointer :: newcoord
489 :
490 69120 : allocate(newcoord)
491 :
492 13824 : newcoord%name = trim(name)
493 13824 : newcoord%dimname = trim(dimname)
494 13824 : newcoord%dimsize = dimsize
495 13824 : newcoord%long_name = trim(long_name)
496 13824 : newcoord%units = trim(units)
497 : ! Figure out if this is a latitude or a longitude using CF standard
498 : ! http://cfconventions.org/Data/cf-conventions/cf-conventions-1.6/build/cf-conventions.html#latitude-coordinate
499 : ! http://cfconventions.org/Data/cf-conventions/cf-conventions-1.6/build/cf-conventions.html#longitude-coordinate
500 : if ( (trim(units) == 'degrees_north') .or. &
501 : (trim(units) == 'degree_north') .or. &
502 : (trim(units) == 'degree_N') .or. &
503 : (trim(units) == 'degrees_N') .or. &
504 13824 : (trim(units) == 'degreeN') .or. &
505 : (trim(units) == 'degreesN')) then
506 6912 : newcoord%latitude = .true.
507 : else if ((trim(units) == 'degrees_east') .or. &
508 : (trim(units) == 'degree_east') .or. &
509 : (trim(units) == 'degree_E') .or. &
510 : (trim(units) == 'degrees_E') .or. &
511 6912 : (trim(units) == 'degreeE') .or. &
512 : (trim(units) == 'degreesE')) then
513 6912 : newcoord%latitude = .false.
514 : else
515 0 : call endrun("horiz_coord_create: unsupported units: '"//trim(units)//"'")
516 : end if
517 41472 : allocate(newcoord%values(lbound:ubound))
518 13824 : if (ubound >= lbound) then
519 1119168 : newcoord%values(:) = values(:)
520 : end if
521 :
522 13824 : if (present(map)) then
523 1119168 : if (ANY(map < 0)) then
524 0 : call endrun("horiz_coord_create "//trim(name)//": map vals < 0")
525 : end if
526 41472 : allocate(newcoord%map(ubound - lbound + 1))
527 13824 : if (ubound >= lbound) then
528 1119168 : newcoord%map(:) = map(:)
529 : end if
530 : else
531 0 : nullify(newcoord%map)
532 : end if
533 :
534 13824 : if (present(bnds)) then
535 0 : allocate(newcoord%bnds(2, lbound:ubound))
536 0 : if (ubound >= lbound) then
537 0 : newcoord%bnds = bnds
538 : end if
539 : else
540 13824 : nullify(newcoord%bnds)
541 : end if
542 :
543 27648 : end function horiz_coord_create
544 :
545 : !---------------------------------------------------------------------------
546 : !
547 : ! write_horiz_coord_attr
548 : !
549 : ! Write the dimension and coordinate attributes for a horizontal grid
550 : ! coordinate.
551 : !
552 : !---------------------------------------------------------------------------
553 :
554 24576 : subroutine write_horiz_coord_attr(this, File, dimid_out, file_index)
555 : use pio, only: file_desc_t, pio_put_att, pio_noerr, pio_double
556 : use pio, only: pio_bcast_error, pio_seterrorhandling, pio_inq_varid
557 : use cam_pio_utils, only: cam_pio_def_dim, cam_pio_def_var
558 :
559 : ! Dummy arguments
560 : class(horiz_coord_t), intent(inout) :: this
561 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
562 : integer, optional, intent(out) :: dimid_out
563 : integer, optional, intent(in) :: file_index
564 :
565 : ! Local variables
566 : type(var_desc_t) :: vardesc
567 : character(len=max_hcoordname_len) :: dimname
568 : integer :: dimid ! PIO dimension ID
569 : integer :: bnds_dimid ! PIO dim ID for bounds
570 : integer :: err_handling
571 : integer :: ierr
572 : integer :: file_index_loc
573 :
574 : ! We will handle errors for this routine
575 24576 : call pio_seterrorhandling(File, PIO_BCAST_ERROR,err_handling)
576 :
577 24576 : if (present(file_index)) then
578 24576 : file_index_loc = file_index
579 : else
580 : file_index_loc = 1
581 : end if
582 :
583 : ! Make sure the dimension exists in the file
584 24576 : call this%get_dim_name(dimname)
585 : call cam_pio_def_dim(File, trim(dimname), this%dimsize, dimid, &
586 24576 : existOK=.true.)
587 : ! Should we define the variable?
588 24576 : ierr = pio_inq_varid(File, trim(this%name), vardesc)
589 24576 : if (ierr /= PIO_NOERR) then
590 : ! Variable not already defined, it is up to us to define the variable
591 24576 : if (associated(this%vardesc(file_index_loc)%p)) then
592 : ! This should not happen (i.e., internal error)
593 0 : call endrun('write_horiz_coord_attr: vardesc already allocated for '//trim(dimname))
594 : end if
595 24576 : allocate(this%vardesc(file_index_loc)%p)
596 : call cam_pio_def_var(File, trim(this%name), pio_double, &
597 49152 : (/ dimid /), this%vardesc(file_index_loc)%p, existOK=.false.)
598 : ! long_name
599 24576 : ierr=pio_put_att(File, this%vardesc(file_index_loc)%p, 'long_name', trim(this%long_name))
600 24576 : call cam_pio_handle_error(ierr, 'Error writing "long_name" attr in write_horiz_coord_attr')
601 : ! units
602 24576 : ierr=pio_put_att(File, this%vardesc(file_index_loc)%p, 'units', trim(this%units))
603 24576 : call cam_pio_handle_error(ierr, 'Error writing "units" attr in write_horiz_coord_attr')
604 : ! Take care of bounds if they exist
605 24576 : if (associated(this%bnds)) then
606 0 : allocate(this%bndsvdesc(file_index_loc)%p)
607 0 : ierr=pio_put_att(File, this%vardesc(file_index_loc)%p, 'bounds', trim(this%name)//'_bnds')
608 0 : call cam_pio_handle_error(ierr, 'Error writing "'//trim(this%name)//'_bnds" attr in write_horiz_coord_attr')
609 0 : call cam_pio_def_dim(File, 'nbnd', 2, bnds_dimid, existOK=.true.)
610 : call cam_pio_def_var(File, trim(this%name)//'_bnds', pio_double, &
611 0 : (/ bnds_dimid, dimid /), this%bndsvdesc(file_index_loc)%p, existOK=.false.)
612 0 : call cam_pio_handle_error(ierr, 'Error defining "'//trim(this%name)//'bnds" in write_horiz_coord_attr')
613 : ! long_name
614 0 : ierr=pio_put_att(File, this%bndsvdesc(file_index_loc)%p, 'long_name', trim(this%name)//' bounds')
615 0 : call cam_pio_handle_error(ierr, 'Error writing bounds "long_name" attr in write_horiz_coord_attr')
616 : ! units
617 0 : ierr=pio_put_att(File, this%bndsvdesc(file_index_loc)%p, 'units', trim(this%units))
618 0 : call cam_pio_handle_error(ierr, 'Error writing bounds "units" attr in write_horiz_coord_attr')
619 : end if ! There are bounds for this coordinate
620 : end if ! We define the variable
621 :
622 24576 : if (present(dimid_out)) then
623 24576 : dimid_out = dimid
624 : end if
625 :
626 : ! Back to old error handling
627 24576 : call pio_seterrorhandling(File, err_handling)
628 :
629 24576 : end subroutine write_horiz_coord_attr
630 :
631 : !---------------------------------------------------------------------------
632 : !
633 : ! write_horiz_coord_var
634 : !
635 : ! Write the coordinate values for this coordinate
636 : !
637 : !---------------------------------------------------------------------------
638 :
639 24576 : subroutine write_horiz_coord_var(this, File, file_index)
640 24576 : use cam_pio_utils, only: cam_pio_get_decomp
641 : use pio, only: file_desc_t, pio_double, iosystem_desc_t
642 : use pio, only: pio_put_var, pio_write_darray
643 : use pio, only: pio_bcast_error, pio_seterrorhandling
644 : !!XXgoldyXX: HACK to get around circular dependencies. Fix this!!
645 : !!XXgoldyXX: The issue is cam_pio_utils depending on stuff in this module
646 : use pio, only: pio_initdecomp, io_desc_t, pio_freedecomp, pio_syncfile
647 : use cam_instance, only: atm_id
648 : use shr_pio_mod, only: shr_pio_getiosys
649 : !!XXgoldyXX: End of this part of the hack
650 :
651 : ! Dummy arguments
652 : class(horiz_coord_t), intent(inout) :: this
653 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
654 : integer, optional, intent(in) :: file_index
655 :
656 : ! Local variables
657 : character(len=120) :: errormsg
658 : integer :: ierr
659 : integer :: ldims(1)
660 : integer :: fdims(1)
661 : integer :: err_handling
662 : type(io_desc_t) :: iodesc
663 : integer :: file_index_loc
664 : !!XXgoldyXX: HACK to get around circular dependencies. Fix this!!
665 : type(iosystem_desc_t), pointer :: piosys
666 : !!XXgoldyXX: End of this part of the hack
667 :
668 24576 : if (present(file_index)) then
669 18432 : file_index_loc = file_index
670 : else
671 : file_index_loc = 1
672 : end if
673 :
674 : ! Check to make sure we are supposed to write this var
675 24576 : if (associated(this%vardesc(file_index_loc)%p)) then
676 : ! We will handle errors for this routine
677 24576 : call pio_seterrorhandling(File, PIO_BCAST_ERROR,err_handling)
678 :
679 : ! Write out the values for this dimension variable
680 24576 : if (associated(this%map)) then
681 : ! This is a distributed variable, use pio_write_darray
682 : #if 0
683 : ldims(1) = this%num_elem()
684 : call this%get_coord_len(fdims(1))
685 : allocate(iodesc)
686 : call cam_pio_get_decomp(iodesc, ldims, fdims, PIO_DOUBLE, this%map)
687 : call pio_write_darray(File, this%vardesc(file_index_loc)%p, iodesc, this%values, ierr)
688 : nullify(iodesc) ! CAM PIO system takes over memory management of iodesc
689 : #else
690 : !!XXgoldyXX: HACK to get around circular dependencies. Fix this!!
691 24576 : piosys => shr_pio_getiosys(atm_id)
692 : call pio_initdecomp(piosys, pio_double, (/this%dimsize/), this%map, &
693 49152 : iodesc)
694 24576 : call pio_write_darray(File, this%vardesc(file_index_loc)%p, iodesc, this%values, ierr)
695 :
696 24576 : call pio_syncfile(File)
697 24576 : call pio_freedecomp(File, iodesc)
698 : ! Take care of bounds if they exist
699 24576 : if (associated(this%bnds) .and. associated(this%bndsvdesc(file_index_loc)%p)) then
700 : call pio_initdecomp(piosys, pio_double, (/2, this%dimsize/), &
701 0 : this%map, iodesc)
702 0 : call pio_write_darray(File, this%bndsvdesc(file_index_loc)%p, iodesc, this%bnds, ierr)
703 0 : call pio_syncfile(File)
704 0 : call pio_freedecomp(File, iodesc)
705 : end if
706 : #endif
707 : !!XXgoldyXX: End of this part of the hack
708 : else
709 : ! This is a local variable, pio_put_var should work fine
710 0 : ierr = pio_put_var(File, this%vardesc(file_index_loc)%p, this%values)
711 : ! Take care of bounds if they exist
712 0 : if (associated(this%bnds) .and. associated(this%bndsvdesc(file_index_loc)%p)) then
713 0 : ierr = pio_put_var(File, this%bndsvdesc(file_index_loc)%p, this%bnds)
714 : end if
715 : end if
716 24576 : write(errormsg, *) 'Error writing variable values for ',trim(this%name),&
717 49152 : ' in write_horiz_coord_var'
718 24576 : call cam_pio_handle_error(ierr, errormsg)
719 :
720 : ! Back to old error handling
721 24576 : call pio_seterrorhandling(File, err_handling)
722 :
723 : ! We are done with this variable descriptor, reset for next file
724 24576 : deallocate(this%vardesc(file_index_loc)%p)
725 24576 : nullify(this%vardesc(file_index_loc)%p)
726 : ! Same with the bounds descriptor
727 24576 : if (associated(this%bndsvdesc(file_index_loc)%p)) then
728 0 : deallocate(this%bndsvdesc(file_index_loc)%p)
729 0 : nullify(this%bndsvdesc(file_index_loc)%p)
730 : end if
731 : end if ! Do we write the variable?
732 :
733 24576 : end subroutine write_horiz_coord_var
734 :
735 : !!#######################################################################
736 : !!
737 : !! CAM grid functions
738 : !!
739 : !!#######################################################################
740 :
741 213319008 : integer function get_cam_grid_index_char(gridname)
742 : ! Dummy arguments
743 : character(len=*), intent(in) :: gridname
744 : ! Local variables
745 : integer :: i
746 :
747 213319008 : get_cam_grid_index_char = -1
748 952919136 : do i = 1, registeredhgrids
749 952919136 : if(trim(gridname) == trim(cam_grids(i)%name)) then
750 213312096 : get_cam_grid_index_char = i
751 213312096 : exit
752 : end if
753 : end do
754 :
755 24576 : end function get_cam_grid_index_char
756 :
757 72772272 : integer function get_cam_grid_index_int(gridid)
758 : ! Dummy arguments
759 : integer, intent(in) :: gridid
760 : ! Local variables
761 : integer :: i
762 :
763 72772272 : get_cam_grid_index_int = -1
764 323436216 : do i = 1, registeredhgrids
765 323436216 : if(gridid == cam_grids(i)%id) then
766 : get_cam_grid_index_int = i
767 : exit
768 : end if
769 : end do
770 :
771 72772272 : end function get_cam_grid_index_int
772 :
773 30720 : subroutine find_cam_grid_attr(gridind, name, attr)
774 : ! Dummy arguments
775 : integer, intent(in) :: gridind
776 : character(len=*), intent(in) :: name
777 : class(cam_grid_attribute_t), pointer, intent(out) :: attr
778 : ! Local variable
779 : type(cam_grid_attr_ptr_t), pointer :: attrPtr
780 :
781 30720 : nullify(attr)
782 30720 : attrPtr => cam_grids(gridind)%attributes
783 72960 : do while (associated(attrPtr))
784 : !!XXgoldyXX: Is this not working in PGI?
785 : ! attr => attrPtr%getAttr()
786 45312 : attr => attrPtr%attr
787 72960 : if (trim(name) == trim(attr%name)) then
788 : exit
789 : else
790 : !!XXgoldyXX: Is this not working in PGI?
791 : ! attrPtr => attrPtr%getNext()
792 42240 : attrPtr => attrPtr%next
793 42240 : nullify(attr)
794 : end if
795 : end do
796 30720 : return ! attr should be NULL if not found
797 : end subroutine find_cam_grid_attr
798 :
799 1536 : logical function cam_grid_attr_exists(gridname, name)
800 : ! Dummy arguments
801 : character(len=*), intent(in) :: gridname
802 : character(len=*), intent(in) :: name
803 : ! Local variables
804 : class(cam_grid_attribute_t), pointer :: attr
805 : integer :: gridind
806 :
807 1536 : gridind = get_cam_grid_index(trim(gridname))
808 1536 : if (gridind > 0) then
809 1536 : call find_cam_grid_attr(gridind, name, attr)
810 1536 : cam_grid_attr_exists = associated(attr)
811 1536 : nullify(attr)
812 : else
813 0 : call endrun('cam_grid_attr_exists: Bad grid name, "'//trim(gridname)//'"')
814 : end if
815 1536 : end function cam_grid_attr_exists
816 :
817 : integer function num_cam_grid_attrs(gridind)
818 : ! Dummy arguments
819 : integer, intent(in) :: gridind
820 :
821 : ! Local variables
822 : class(cam_grid_attr_ptr_t), pointer :: attrPtr
823 :
824 : num_cam_grid_attrs = 0
825 : attrPtr => cam_grids(gridind)%attributes
826 : do while (associated(attrPtr))
827 : num_cam_grid_attrs = num_cam_grid_attrs + 1
828 : !!XXgoldyXX: Is this not working in PGI?
829 : ! attrPtr => attrPtr%getNext()
830 : attrPtr => attrPtr%next
831 : end do
832 : end function num_cam_grid_attrs
833 :
834 6912 : subroutine cam_grid_register(name, id, lat_coord, lon_coord, map, &
835 : unstruct, block_indexed, zonal_grid, src_in, dest_in)
836 : ! Dummy arguments
837 : character(len=*), intent(in) :: name
838 : integer, intent(in) :: id
839 : type(horiz_coord_t), pointer, intent(in) :: lat_coord
840 : type(horiz_coord_t), pointer, intent(in) :: lon_coord
841 : integer(iMap), pointer, intent(in) :: map(:,:)
842 : logical, optional, intent(in) :: unstruct
843 : logical, optional, intent(in) :: block_indexed
844 : logical, optional, intent(in) :: zonal_grid
845 : integer, optional, intent(in) :: src_in(2)
846 : integer, optional, intent(in) :: dest_in(2)
847 :
848 : ! Local variables
849 : character(len=max_hcoordname_len) :: latdimname, londimname
850 : character(len=120) :: errormsg
851 : integer :: i
852 : integer :: src(2), dest(2)
853 : character(len=*), parameter :: subname = 'CAM_GRID_REGISTER'
854 :
855 : ! For a values grid, we do not allow multiple calls
856 6912 : if (get_cam_grid_index(trim(name)) > 0) then
857 0 : call endrun(trim(subname)//': Grid, '//trim(name)//', already exists')
858 6912 : else if (get_cam_grid_index(id) > 0) then
859 0 : i = get_cam_grid_index(id)
860 0 : write(errormsg, '(4a,i5,3a)') trim(subname), ': Attempt to add grid, ', &
861 0 : trim(name), ' with id = ', id, ', however, grid ', &
862 0 : trim(cam_grids(i)%name), ' already has that ID'
863 0 : call endrun(trim(errormsg))
864 6912 : else if (registeredhgrids >= maxhgrids) then
865 0 : call endrun(trim(subname)//": Too many grids")
866 : else
867 6912 : registeredhgrids = registeredhgrids + 1
868 6912 : cam_grids(registeredhgrids)%name = trim(name)
869 6912 : cam_grids(registeredhgrids)%id = id
870 : ! Quick sanity checks to make sure these aren't mixed up
871 6912 : if (.not. lat_coord%latitude) then
872 0 : call endrun(subname//': lat_coord is not a latitude coordinate')
873 : end if
874 6912 : if (lon_coord%latitude) then
875 0 : call endrun(subname//': lon_coord is not a longitude coordinate')
876 : end if
877 6912 : cam_grids(registeredhgrids)%lat_coord => lat_coord
878 6912 : cam_grids(registeredhgrids)%lon_coord => lon_coord
879 6912 : call lat_coord%get_dim_name(latdimname)
880 6912 : call lon_coord%get_dim_name(londimname)
881 6912 : if (present(unstruct)) then
882 6912 : cam_grids(registeredhgrids)%unstructured = unstruct
883 : else
884 0 : if (trim(latdimname) == trim(londimname)) then
885 0 : cam_grids(registeredhgrids)%unstructured = .true.
886 : else
887 0 : cam_grids(registeredhgrids)%unstructured = .false.
888 : end if
889 : end if
890 6912 : if (present(block_indexed)) then
891 6912 : cam_grids(registeredhgrids)%block_indexed = block_indexed
892 : else
893 0 : cam_grids(registeredhgrids)%block_indexed = cam_grids(registeredhgrids)%unstructured
894 : end if
895 6912 : if (present(zonal_grid)) then
896 : ! Check the size of the longitude coordinate
897 0 : call lon_coord%get_coord_len(i)
898 0 : if (i /= 1) then
899 0 : call endrun(subname//': lon_coord is not of size 1 for a zonal grid')
900 : end if
901 0 : cam_grids(registeredhgrids)%zonal_grid = zonal_grid
902 : else
903 6912 : cam_grids(registeredhgrids)%zonal_grid = .false.
904 : end if
905 6912 : if (associated(cam_grids(registeredhgrids)%map)) then
906 0 : call endrun(trim(subname)//": new grid map should not be associated")
907 : end if
908 6912 : if (present(src_in)) then
909 0 : src = src_in
910 : else
911 6912 : src(1) = 1
912 6912 : src(2) = -1
913 : end if
914 6912 : if (present(dest_in)) then
915 0 : dest = dest_in
916 : else
917 6912 : dest(1) = 1
918 6912 : if (cam_grids(registeredhgrids)%unstructured) then
919 6912 : dest(2) = 0
920 : else
921 0 : dest(2) = 2
922 : end if
923 : end if
924 76032 : allocate(cam_grids(registeredhgrids)%map)
925 : call cam_grids(registeredhgrids)%map%init(map, &
926 6912 : cam_grids(registeredhgrids)%unstructured, src, dest)
927 6912 : call cam_grids(registeredhgrids)%print_cam_grid()
928 : end if
929 :
930 6912 : end subroutine cam_grid_register
931 :
932 6912 : subroutine print_cam_grid(this)
933 : class(cam_grid_t) :: this
934 :
935 : type(cam_grid_attr_ptr_t), pointer :: attrPtr
936 : class(cam_grid_attribute_t), pointer :: attr
937 6912 : if (masterproc) then
938 9 : write(iulog, '(3a,i4,4a,3(a,l2))') 'Grid: ', trim(this%name), &
939 9 : ', ID = ', this%id, &
940 9 : ', lat coord = ', trim(this%lat_coord%name), &
941 9 : ', lon coord = ', trim(this%lon_coord%name), &
942 9 : ', unstruct = ', this%unstructured, &
943 9 : ', block_ind = ', this%block_indexed, &
944 18 : ', zonal_grid = ', this%zonal_grid
945 9 : attrPtr => this%attributes
946 9 : do while (associated(attrPtr))
947 : !!XXgoldyXX: Is this not working in PGI?
948 : ! attr => attrPtr%getAttr()
949 0 : attr => attrPtr%attr
950 0 : call attr%print_attr()
951 : !!XXgoldyXX: Is this not working in PGI?
952 : ! attrPtr => attrPtr%getNext()
953 0 : attrPtr => attrPtr%next
954 : end do
955 : end if
956 6912 : end subroutine print_cam_grid
957 :
958 464640 : integer function cam_grid_num_grids()
959 464640 : cam_grid_num_grids = registeredhgrids
960 464640 : end function cam_grid_num_grids
961 :
962 : ! Return .true. iff id represents a valid CAM grid
963 458496 : logical function cam_grid_check(id)
964 : ! Dummy argument
965 : integer, intent(in) :: id
966 :
967 : cam_grid_check = ((get_cam_grid_index(id) > 0) .and. &
968 458496 : (get_cam_grid_index(id) <= cam_grid_num_grids()))
969 458496 : end function cam_grid_check
970 :
971 213279072 : integer function cam_grid_id(name)
972 : ! Dummy argument
973 : character(len=*), intent(in) :: name
974 :
975 : ! Local variable
976 : integer :: index
977 :
978 213279072 : index = get_cam_grid_index(name)
979 213279072 : if (index > 0) then
980 213279072 : cam_grid_id = cam_grids(index)%id
981 : else
982 : cam_grid_id = -1
983 : end if
984 :
985 213279072 : end function cam_grid_id
986 :
987 : ! Return the size of a local array for grid, ID.
988 : ! With no optional argument, return the basic 2D array size
989 : ! nlev represents levels or the total column size (product(mdims))
990 0 : integer function cam_grid_get_local_size(id, nlev)
991 :
992 : ! Dummy arguments
993 : integer, intent(in) :: id
994 : integer, optional, intent(in) :: nlev
995 :
996 : ! Local variables
997 : integer :: gridid
998 : character(len=128) :: errormsg
999 :
1000 0 : gridid = get_cam_grid_index(id)
1001 0 : if (gridid > 0) then
1002 0 : cam_grid_get_local_size = cam_grids(gridid)%num_elem()
1003 0 : if (present(nlev)) then
1004 0 : cam_grid_get_local_size = cam_grid_get_local_size * nlev
1005 : end if
1006 : else
1007 0 : write(errormsg, *) 'cam_grid_get_local_size: Bad grid ID, ', id
1008 0 : call endrun(errormsg)
1009 : end if
1010 :
1011 0 : end function cam_grid_get_local_size
1012 :
1013 : ! Given some array information, find the dimension NetCDF IDs on <File> for this grid
1014 1536 : subroutine cam_grid_get_file_dimids(id, File, dimids)
1015 : use pio, only: file_desc_t
1016 :
1017 : ! Dummy arguments
1018 : integer, intent(in) :: id
1019 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1020 : integer, intent(out) :: dimids(:)
1021 :
1022 : ! Local variables
1023 : integer :: gridid
1024 : character(len=128) :: errormsg
1025 :
1026 1536 : gridid = get_cam_grid_index(id)
1027 1536 : if (gridid > 0) then
1028 1536 : call cam_grids(gridid)%find_dimids(File, dimids)
1029 : else
1030 0 : write(errormsg, *) 'cam_grid_get_file_dimids: Bad grid ID, ', id
1031 0 : call endrun(errormsg)
1032 : end if
1033 :
1034 1536 : end subroutine cam_grid_get_file_dimids
1035 :
1036 : ! Given some array information, find or compute a PIO decomposition
1037 272640 : subroutine cam_grid_get_decomp(id, field_lens, file_lens, dtype, iodesc, &
1038 272640 : field_dnames, file_dnames)
1039 : use pio, only: io_desc_t
1040 :
1041 : ! Dummy arguments
1042 : integer, intent(in) :: id
1043 : integer, intent(in) :: field_lens(:) ! Array dim sizes
1044 : integer, intent(in) :: file_lens(:) ! File dim sizes
1045 : integer, intent(in) :: dtype
1046 : type(io_desc_t), pointer, intent(out) :: iodesc
1047 : character(len=*), optional, intent(in) :: field_dnames(:)
1048 : character(len=*), optional, intent(in) :: file_dnames(:)
1049 :
1050 : ! Local variables
1051 : integer :: gridid
1052 : character(len=128) :: errormsg
1053 :
1054 272640 : gridid = get_cam_grid_index(id)
1055 272640 : if (gridid > 0) then
1056 0 : call cam_grids(gridid)%get_decomp(field_lens, file_lens, dtype, iodesc, &
1057 575232 : field_dnames, file_dnames)
1058 : else
1059 0 : write(errormsg, *) 'cam_grid_get_decomp: Bad grid ID, ', id
1060 0 : call endrun(errormsg)
1061 : end if
1062 :
1063 272640 : end subroutine cam_grid_get_decomp
1064 :
1065 : !---------------------------------------------------------------------------
1066 : !
1067 : ! cam_grid_read_dist_array_2d_int
1068 : !
1069 : ! Interface function for the grid%read_darray_2d_int method
1070 : !
1071 : !---------------------------------------------------------------------------
1072 768 : subroutine cam_grid_read_dist_array_2d_int(File, id, adims, fdims, hbuf, varid)
1073 : use pio, only: file_desc_t
1074 :
1075 : ! Dummy arguments
1076 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1077 : integer, intent(in) :: id
1078 : integer, intent(in) :: adims(:)
1079 : integer, intent(in) :: fdims(:)
1080 : integer, intent(out) :: hbuf(:,:)
1081 : type(var_desc_t), intent(inout) :: varid
1082 :
1083 : ! Local variable
1084 : integer :: gridid
1085 : character(len=120) :: errormsg
1086 :
1087 768 : gridid = get_cam_grid_index(id)
1088 768 : if (gridid > 0) then
1089 768 : call cam_grids(gridid)%read_darray_2d_int(File, adims, fdims, hbuf, varid)
1090 : else
1091 0 : write(errormsg, *) 'cam_grid_read_dist_array_2d_int: Bad grid ID, ', id
1092 0 : call endrun(errormsg)
1093 : end if
1094 :
1095 768 : end subroutine cam_grid_read_dist_array_2d_int
1096 :
1097 : !---------------------------------------------------------------------------
1098 : !
1099 : ! cam_grid_read_dist_array_3d_int
1100 : !
1101 : ! Interface function for the grid%read_darray_2d_ method
1102 : !
1103 : !---------------------------------------------------------------------------
1104 0 : subroutine cam_grid_read_dist_array_3d_int(File, id, adims, fdims, hbuf, varid)
1105 : use pio, only: file_desc_t
1106 :
1107 : ! Dummy arguments
1108 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1109 : integer, intent(in) :: id
1110 : integer, intent(in) :: adims(:)
1111 : integer, intent(in) :: fdims(:)
1112 : integer, intent(out) :: hbuf(:,:,:)
1113 : type(var_desc_t), intent(inout) :: varid
1114 :
1115 : ! Local variable
1116 : integer :: gridid
1117 : character(len=120) :: errormsg
1118 :
1119 0 : gridid = get_cam_grid_index(id)
1120 0 : if (gridid > 0) then
1121 0 : call cam_grids(gridid)%read_darray_3d_int(File, adims, fdims, hbuf, varid)
1122 : else
1123 0 : write(errormsg, *) 'cam_grid_read_dist_array_3d_int: Bad grid ID, ', id
1124 0 : call endrun(errormsg)
1125 : end if
1126 :
1127 0 : end subroutine cam_grid_read_dist_array_3d_int
1128 :
1129 : !---------------------------------------------------------------------------
1130 : !
1131 : ! cam_grid_read_dist_array_2d_double
1132 : !
1133 : ! Interface function for the grid%read_darray_2d_double method
1134 : !
1135 : !---------------------------------------------------------------------------
1136 19968 : subroutine cam_grid_read_dist_array_2d_double(File, id, adims, fdims, hbuf, varid)
1137 : use pio, only: file_desc_t
1138 :
1139 : ! Dummy arguments
1140 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1141 : integer, intent(in) :: id
1142 : integer, intent(in) :: adims(:)
1143 : integer, intent(in) :: fdims(:)
1144 : real(r8), intent(out) :: hbuf(:,:)
1145 : type(var_desc_t), intent(inout) :: varid
1146 :
1147 : ! Local variable
1148 : integer :: gridid
1149 : character(len=120) :: errormsg
1150 :
1151 19968 : gridid = get_cam_grid_index(id)
1152 19968 : if (gridid > 0) then
1153 19968 : call cam_grids(gridid)%read_darray_2d_double(File, adims, fdims, hbuf, varid)
1154 : else
1155 0 : write(errormsg, *) 'cam_grid_read_dist_array_2d_double: Bad grid ID, ', id
1156 0 : call endrun(errormsg)
1157 : end if
1158 :
1159 19968 : end subroutine cam_grid_read_dist_array_2d_double
1160 :
1161 : !---------------------------------------------------------------------------
1162 : !
1163 : ! cam_grid_read_dist_array_3d_double
1164 : !
1165 : ! Interface function for the grid%read_darray_3d_double method
1166 : !
1167 : !---------------------------------------------------------------------------
1168 83712 : subroutine cam_grid_read_dist_array_3d_double(File, id, adims, fdims, hbuf, varid)
1169 : use pio, only: file_desc_t
1170 :
1171 : ! Dummy arguments
1172 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1173 : integer, intent(in) :: id
1174 : integer, intent(in) :: adims(:)
1175 : integer, intent(in) :: fdims(:)
1176 : real(r8), intent(out) :: hbuf(:,:,:)
1177 : type(var_desc_t), intent(inout) :: varid
1178 :
1179 : ! Local variable
1180 : integer :: gridid
1181 : character(len=120) :: errormsg
1182 :
1183 83712 : gridid = get_cam_grid_index(id)
1184 83712 : if (gridid > 0) then
1185 83712 : call cam_grids(gridid)%read_darray_3d_double(File, adims, fdims, hbuf, varid)
1186 : else
1187 0 : write(errormsg, *) 'cam_grid_read_dist_array_3d_double: Bad grid ID, ', id
1188 0 : call endrun(errormsg)
1189 : end if
1190 :
1191 83712 : end subroutine cam_grid_read_dist_array_3d_double
1192 :
1193 : !---------------------------------------------------------------------------
1194 : !
1195 : ! cam_grid_read_dist_array_2d_real
1196 : !
1197 : ! Interface function for the grid%read_darray_2d_real method
1198 : !
1199 : !---------------------------------------------------------------------------
1200 0 : subroutine cam_grid_read_dist_array_2d_real(File, id, adims, fdims, hbuf, varid)
1201 : use pio, only: file_desc_t
1202 :
1203 : ! Dummy arguments
1204 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1205 : integer, intent(in) :: id
1206 : integer, intent(in) :: adims(:)
1207 : integer, intent(in) :: fdims(:)
1208 : real(r4), intent(out) :: hbuf(:,:)
1209 : type(var_desc_t), intent(inout) :: varid
1210 :
1211 : ! Local variable
1212 : integer :: gridid
1213 : character(len=120) :: errormsg
1214 :
1215 0 : gridid = get_cam_grid_index(id)
1216 0 : if (gridid > 0) then
1217 0 : call cam_grids(gridid)%read_darray_2d_real(File, adims, fdims, hbuf, varid)
1218 : else
1219 0 : write(errormsg, *) 'cam_grid_read_dist_array_2d_real: Bad grid ID, ', id
1220 0 : call endrun(errormsg)
1221 : end if
1222 :
1223 0 : end subroutine cam_grid_read_dist_array_2d_real
1224 :
1225 : !---------------------------------------------------------------------------
1226 : !
1227 : ! cam_grid_read_dist_array_3d_real
1228 : !
1229 : ! Interface function for the grid%read_darray_3d_real method
1230 : !
1231 : !---------------------------------------------------------------------------
1232 0 : subroutine cam_grid_read_dist_array_3d_real(File, id, adims, fdims, hbuf, varid)
1233 : use pio, only: file_desc_t
1234 :
1235 : ! Dummy arguments
1236 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1237 : integer, intent(in) :: id
1238 : integer, intent(in) :: adims(:)
1239 : integer, intent(in) :: fdims(:)
1240 : real(r4), intent(out) :: hbuf(:,:,:)
1241 : type(var_desc_t), intent(inout) :: varid
1242 :
1243 : ! Local variable
1244 : integer :: gridid
1245 : character(len=120) :: errormsg
1246 :
1247 0 : gridid = get_cam_grid_index(id)
1248 0 : if (gridid > 0) then
1249 0 : call cam_grids(gridid)%read_darray_3d_real(File, adims, fdims, hbuf, varid)
1250 : else
1251 0 : write(errormsg, *) 'cam_grid_read_dist_array_3d_real: Bad grid ID, ', id
1252 0 : call endrun(errormsg)
1253 : end if
1254 :
1255 0 : end subroutine cam_grid_read_dist_array_3d_real
1256 :
1257 : !---------------------------------------------------------------------------
1258 : !
1259 : ! cam_grid_write_dist_array_2d_int
1260 : !
1261 : ! Interface function for the grid%write_darray_2d_int method
1262 : !
1263 : !---------------------------------------------------------------------------
1264 1536 : subroutine cam_grid_write_dist_array_2d_int(File, id, adims, fdims, hbuf, varid)
1265 : use pio, only: file_desc_t
1266 :
1267 : ! Dummy arguments
1268 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1269 : integer, intent(in) :: id
1270 : integer, intent(in) :: adims(:)
1271 : integer, intent(in) :: fdims(:)
1272 : integer, intent(in) :: hbuf(:,:)
1273 : type(var_desc_t), intent(inout) :: varid
1274 :
1275 : ! Local variable
1276 : integer :: gridid
1277 : character(len=120) :: errormsg
1278 :
1279 1536 : gridid = get_cam_grid_index(id)
1280 1536 : if (gridid > 0) then
1281 1536 : call cam_grids(gridid)%write_darray_2d_int(File, adims, fdims, hbuf, varid)
1282 : else
1283 0 : write(errormsg, *) 'cam_grid_write_dist_array_2d_int: Bad grid ID, ', id
1284 0 : call endrun(errormsg)
1285 : end if
1286 :
1287 1536 : end subroutine cam_grid_write_dist_array_2d_int
1288 :
1289 : !---------------------------------------------------------------------------
1290 : !
1291 : ! cam_grid_write_dist_array_3d_int
1292 : !
1293 : ! Interface function for the grid%write_darray_3d_int method
1294 : !
1295 : !---------------------------------------------------------------------------
1296 0 : subroutine cam_grid_write_dist_array_3d_int(File, id, adims, fdims, hbuf, varid)
1297 : use pio, only: file_desc_t
1298 :
1299 : ! Dummy arguments
1300 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1301 : integer, intent(in) :: id
1302 : integer, intent(in) :: adims(:)
1303 : integer, intent(in) :: fdims(:)
1304 : integer, intent(in) :: hbuf(:,:,:)
1305 : type(var_desc_t), intent(inout) :: varid
1306 :
1307 : ! Local variable
1308 : integer :: gridid
1309 : character(len=120) :: errormsg
1310 :
1311 0 : gridid = get_cam_grid_index(id)
1312 0 : if (gridid > 0) then
1313 0 : call cam_grids(gridid)%write_darray_3d_int(File, adims, fdims, hbuf, varid)
1314 : else
1315 0 : write(errormsg, *) 'cam_grid_write_dist_array_3d_int: Bad grid ID, ', id
1316 0 : call endrun(errormsg)
1317 : end if
1318 :
1319 0 : end subroutine cam_grid_write_dist_array_3d_int
1320 :
1321 : !---------------------------------------------------------------------------
1322 : !
1323 : ! cam_grid_write_dist_array_2d_double
1324 : !
1325 : ! Interface function for the grid%write_darray_2d_double method
1326 : !
1327 : !---------------------------------------------------------------------------
1328 39936 : subroutine cam_grid_write_dist_array_2d_double(File, id, adims, fdims, hbuf, varid)
1329 : use pio, only: file_desc_t
1330 :
1331 : ! Dummy arguments
1332 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1333 : integer, intent(in) :: id
1334 : integer, intent(in) :: adims(:)
1335 : integer, intent(in) :: fdims(:)
1336 : real(r8), intent(in) :: hbuf(:,:)
1337 : type(var_desc_t), intent(inout) :: varid
1338 :
1339 : ! Local variable
1340 : integer :: gridid
1341 : character(len=120) :: errormsg
1342 :
1343 39936 : gridid = get_cam_grid_index(id)
1344 39936 : if (gridid > 0) then
1345 39936 : call cam_grids(gridid)%write_darray_2d_double(File, adims, fdims, hbuf, varid)
1346 : else
1347 0 : write(errormsg, *) 'cam_grid_write_dist_array_2d_double: Bad grid ID, ', id
1348 0 : call endrun(errormsg)
1349 : end if
1350 :
1351 39936 : end subroutine cam_grid_write_dist_array_2d_double
1352 :
1353 : !---------------------------------------------------------------------------
1354 : !
1355 : ! cam_grid_write_dist_array_3d_double
1356 : !
1357 : ! Interface function for the grid%write_darray_3d_double method
1358 : !
1359 : !---------------------------------------------------------------------------
1360 167424 : subroutine cam_grid_write_dist_array_3d_double(File, id, adims, fdims, hbuf, varid)
1361 : use pio, only: file_desc_t
1362 :
1363 : ! Dummy arguments
1364 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1365 : integer, intent(in) :: id
1366 : integer, intent(in) :: adims(:)
1367 : integer, intent(in) :: fdims(:)
1368 : real(r8), intent(in) :: hbuf(:,:,:)
1369 : type(var_desc_t), intent(inout) :: varid
1370 :
1371 : ! Local variable
1372 : integer :: gridid
1373 : character(len=120) :: errormsg
1374 :
1375 167424 : gridid = get_cam_grid_index(id)
1376 167424 : if (gridid > 0) then
1377 167424 : call cam_grids(gridid)%write_darray_3d_double(File, adims, fdims, hbuf, varid)
1378 : else
1379 0 : write(errormsg, *) 'cam_grid_write_dist_array_3d_double: Bad grid ID, ', id
1380 0 : call endrun(errormsg)
1381 : end if
1382 :
1383 167424 : end subroutine cam_grid_write_dist_array_3d_double
1384 :
1385 : !---------------------------------------------------------------------------
1386 : !
1387 : ! cam_grid_write_dist_array_2d_real
1388 : !
1389 : ! Interface function for the grid%write_darray_2d_real method
1390 : !
1391 : !---------------------------------------------------------------------------
1392 1211904 : subroutine cam_grid_write_dist_array_2d_real(File, id, adims, fdims, hbuf, varid)
1393 : use pio, only: file_desc_t
1394 :
1395 : ! Dummy arguments
1396 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1397 : integer, intent(in) :: id
1398 : integer, intent(in) :: adims(:)
1399 : integer, intent(in) :: fdims(:)
1400 : real(r4), intent(in) :: hbuf(:,:)
1401 : type(var_desc_t), intent(inout) :: varid
1402 :
1403 : ! Local variable
1404 : integer :: gridid
1405 : character(len=120) :: errormsg
1406 :
1407 1211904 : gridid = get_cam_grid_index(id)
1408 1211904 : if (gridid > 0) then
1409 1211904 : call cam_grids(gridid)%write_darray_2d_real(File, adims, fdims, hbuf, varid)
1410 : else
1411 0 : write(errormsg, *) 'cam_grid_write_dist_array_2d_real: Bad grid ID, ', id
1412 0 : call endrun(errormsg)
1413 : end if
1414 :
1415 1211904 : end subroutine cam_grid_write_dist_array_2d_real
1416 :
1417 : !---------------------------------------------------------------------------
1418 : !
1419 : ! cam_grid_write_dist_array_3d_real
1420 : !
1421 : ! Interface function for the grid%write_darray_3d_real method
1422 : !
1423 : !---------------------------------------------------------------------------
1424 695808 : subroutine cam_grid_write_dist_array_3d_real(File, id, adims, fdims, hbuf, varid)
1425 : use pio, only: file_desc_t
1426 :
1427 : ! Dummy arguments
1428 : type(file_desc_t), intent(inout) :: File ! PIO file handle
1429 : integer, intent(in) :: id
1430 : integer, intent(in) :: adims(:)
1431 : integer, intent(in) :: fdims(:)
1432 : real(r4), intent(in) :: hbuf(:,:,:)
1433 : type(var_desc_t), intent(inout) :: varid
1434 :
1435 : ! Local variable
1436 : integer :: gridid
1437 : character(len=120) :: errormsg
1438 :
1439 695808 : gridid = get_cam_grid_index(id)
1440 695808 : if (gridid > 0) then
1441 695808 : call cam_grids(gridid)%write_darray_3d_real(File, adims, fdims, hbuf, varid)
1442 : else
1443 0 : write(errormsg, *) 'cam_grid_write_dist_array_3d_real: Bad grid ID, ', id
1444 0 : call endrun(errormsg)
1445 : end if
1446 :
1447 695808 : end subroutine cam_grid_write_dist_array_3d_real
1448 :
1449 2304 : subroutine cam_grid_get_gcid(id, gcid)
1450 :
1451 : ! Dummy arguments
1452 : integer, intent(in) :: id
1453 : integer(iMap), pointer :: gcid(:)
1454 :
1455 : ! Local variables
1456 : integer :: gridid
1457 : integer :: fieldbounds(2,2)
1458 : integer :: fieldlens(2)
1459 : integer :: filelens(2)
1460 : type(cam_filemap_t), pointer :: map
1461 :
1462 2304 : gridid = get_cam_grid_index(id)
1463 2304 : if (gridid > 0) then
1464 2304 : map => cam_grids(gridid)%map
1465 2304 : call cam_grids(gridid)%coord_lengths(filelens)
1466 2304 : call map%array_bounds(fieldbounds)
1467 6912 : fieldlens(:) = fieldbounds(:,2) - fieldbounds(:,1) + 1
1468 2304 : call map%get_filemap(fieldlens, filelens, gcid)
1469 : else
1470 0 : call endrun('cam_grid_get_gcid: Bad grid ID')
1471 : end if
1472 2304 : end subroutine cam_grid_get_gcid
1473 :
1474 5372160 : subroutine cam_grid_get_array_bounds(id, dims)
1475 :
1476 : ! Dummy arguments
1477 : integer, intent(in) :: id
1478 : integer, intent(inout) :: dims(:,:)
1479 :
1480 : ! Local variables
1481 : integer :: gridid
1482 5372160 : gridid = get_cam_grid_index(id)
1483 5372160 : if (gridid > 0) then
1484 5372160 : if (.not. associated(cam_grids(gridid)%map)) then
1485 0 : call endrun('cam_grid_get_array_bounds: Grid, '//trim(cam_grids(gridid)%name)//', has no map')
1486 : else
1487 5372160 : call cam_grids(gridid)%map%array_bounds(dims)
1488 : end if
1489 : else
1490 0 : call endrun('cam_grid_get_array_bounds: Bad grid ID')
1491 : end if
1492 :
1493 5372160 : end subroutine cam_grid_get_array_bounds
1494 :
1495 : !---------------------------------------------------------------------------
1496 : !
1497 : ! cam_grid_get_coord_names: Return the names of the grid axes
1498 : !
1499 : !---------------------------------------------------------------------------
1500 0 : subroutine cam_grid_get_coord_names(id, lon_name, lat_name)
1501 :
1502 : ! Dummy arguments
1503 : integer, intent(in) :: id
1504 : character(len=*), intent(out) :: lon_name
1505 : character(len=*), intent(out) :: lat_name
1506 :
1507 : ! Local variables
1508 : integer :: gridid
1509 0 : gridid = get_cam_grid_index(id)
1510 0 : if (gridid > 0) then
1511 0 : call cam_grids(gridid)%coord_names(lon_name, lat_name)
1512 : else
1513 0 : call endrun('cam_grid_get_coord_names: Bad grid ID')
1514 : end if
1515 :
1516 0 : end subroutine cam_grid_get_coord_names
1517 :
1518 : !---------------------------------------------------------------------------
1519 : !
1520 : ! cam_grid_get_dim_names: Return the names of the grid axes dimensions.
1521 : ! Note that these may be the same
1522 : !
1523 : !---------------------------------------------------------------------------
1524 183552 : subroutine cam_grid_get_dim_names_id(id, name1, name2)
1525 :
1526 : ! Dummy arguments
1527 : integer, intent(in) :: id
1528 : character(len=*), intent(out) :: name1
1529 : character(len=*), intent(out) :: name2
1530 :
1531 : ! Local variables
1532 : integer :: gridid
1533 183552 : gridid = get_cam_grid_index(id)
1534 183552 : if (gridid > 0) then
1535 183552 : call cam_grids(gridid)%dim_names(name1, name2)
1536 : else
1537 0 : call endrun('cam_grid_get_dim_names_id: Bad grid ID')
1538 : end if
1539 :
1540 183552 : end subroutine cam_grid_get_dim_names_id
1541 :
1542 0 : subroutine cam_grid_get_dim_names_name(gridname, name1, name2)
1543 :
1544 : ! Dummy arguments
1545 : character(len=*), intent(in) :: gridname
1546 : character(len=*), intent(out) :: name1
1547 : character(len=*), intent(out) :: name2
1548 :
1549 : ! Local variables
1550 : integer :: gridind
1551 : character(len=120) :: errormsg
1552 :
1553 0 : gridind = get_cam_grid_index(trim(gridname))
1554 0 : if (gridind < 0) then
1555 0 : write(errormsg, *) 'No CAM grid with name = ', trim(gridname)
1556 0 : call endrun('cam_grid_get_dim_names_name: '//errormsg)
1557 : else
1558 0 : call cam_grids(gridind)%dim_names(name1, name2)
1559 : end if
1560 :
1561 0 : end subroutine cam_grid_get_dim_names_name
1562 :
1563 0 : logical function cam_grid_has_blocksize(id)
1564 :
1565 : ! Dummy arguments
1566 : integer, intent(in) :: id
1567 :
1568 : ! Local variables
1569 : integer :: gridid
1570 0 : gridid = get_cam_grid_index(id)
1571 0 : if (gridid > 0) then
1572 0 : if (.not. associated(cam_grids(gridid)%map)) then
1573 0 : call endrun('cam_grid_has_blocksize: Grid, '//trim(cam_grids(gridid)%name)//', has no map')
1574 : else
1575 0 : cam_grid_has_blocksize = cam_grids(gridid)%map%has_blocksize()
1576 : end if
1577 : else
1578 0 : call endrun('cam_grid_has_blocksize: Bad grid ID')
1579 : end if
1580 0 : end function cam_grid_has_blocksize
1581 :
1582 : ! Return the number of active columns in the block specified by block_id
1583 52563888 : integer function cam_grid_get_block_count(id, block_id) result(ncol)
1584 :
1585 : ! Dummy arguments
1586 : integer, intent(in) :: id
1587 : integer, intent(in) :: block_id
1588 :
1589 : ! Local variables
1590 : integer :: gridid
1591 52563888 : gridid = get_cam_grid_index(id)
1592 52563888 : if (gridid > 0) then
1593 52563888 : if (.not. associated(cam_grids(gridid)%map)) then
1594 0 : call endrun('cam_grid_get_block_count: Grid, '//trim(cam_grids(gridid)%name)//', has no map')
1595 : else
1596 52563888 : ncol = cam_grids(gridid)%map%blocksize(block_id)
1597 : end if
1598 : else
1599 0 : call endrun('cam_grid_get_block_count: Bad grid ID')
1600 : end if
1601 52563888 : end function cam_grid_get_block_count
1602 :
1603 768 : function cam_grid_get_latvals(id) result(latvals)
1604 :
1605 : ! Dummy argument
1606 : integer, intent(in) :: id
1607 : real(r8), pointer :: latvals(:)
1608 :
1609 : ! Local variables
1610 : integer :: gridid
1611 768 : gridid = get_cam_grid_index(id)
1612 768 : if (gridid > 0) then
1613 768 : if (.not. associated(cam_grids(gridid)%lat_coord%values)) then
1614 0 : nullify(latvals)
1615 : else
1616 768 : latvals => cam_grids(gridid)%lat_coord%values
1617 : end if
1618 : else
1619 0 : call endrun('cam_grid_get_latvals: Bad grid ID')
1620 : end if
1621 768 : end function cam_grid_get_latvals
1622 :
1623 768 : function cam_grid_get_lonvals(id) result(lonvals)
1624 :
1625 : ! Dummy arguments
1626 : integer, intent(in) :: id
1627 : real(r8), pointer :: lonvals(:)
1628 :
1629 : ! Local variables
1630 : integer :: gridid
1631 768 : gridid = get_cam_grid_index(id)
1632 768 : if (gridid > 0) then
1633 768 : if (.not. associated(cam_grids(gridid)%lon_coord%values)) then
1634 0 : nullify(lonvals)
1635 : else
1636 768 : lonvals => cam_grids(gridid)%lon_coord%values
1637 : end if
1638 : else
1639 0 : call endrun('cam_grid_get_lonvals: Bad grid ID')
1640 : end if
1641 768 : end function cam_grid_get_lonvals
1642 :
1643 0 : function cam_grid_get_areawt(id) result(wtvals)
1644 :
1645 : ! Dummy argument
1646 : integer, intent(in) :: id
1647 : real(r8), pointer :: wtvals(:)
1648 :
1649 : ! Local variables
1650 : character(len=max_chars) :: wtname
1651 : integer :: gridind
1652 : class(cam_grid_attribute_t), pointer :: attrptr
1653 : character(len=120) :: errormsg
1654 :
1655 0 : nullify(attrptr)
1656 0 : gridind = get_cam_grid_index(id)
1657 0 : if (gridind > 0) then
1658 0 : select case(trim(cam_grids(gridind)%name))
1659 : case('GLL')
1660 0 : wtname='area_weight_gll'
1661 : case('FV')
1662 0 : wtname='gw'
1663 : case('INI')
1664 0 : wtname='area_weight_ini'
1665 : case('physgrid')
1666 0 : wtname='areawt'
1667 : case('FVM')
1668 0 : wtname='area_weight_fvm'
1669 : case('mpas_cell')
1670 0 : wtname='area_weight_mpas'
1671 : case default
1672 0 : call endrun('cam_grid_get_areawt: Invalid gridname:'//trim(cam_grids(gridind)%name))
1673 : end select
1674 :
1675 0 : call find_cam_grid_attr(gridind, trim(wtname), attrptr)
1676 0 : if (.not.associated(attrptr)) then
1677 : write(errormsg, '(4a)') &
1678 0 : 'cam_grid_get_areawt: error retrieving weight attribute ', trim(wtname), &
1679 0 : ' for cam grid ', cam_grids(gridind)%name
1680 0 : call endrun(errormsg)
1681 : else
1682 0 : call attrptr%print_attr()
1683 : select type(attrptr)
1684 : type is (cam_grid_attribute_1d_r8_t)
1685 0 : wtvals => attrptr%values
1686 : class default
1687 0 : call endrun('cam_grid_get_areawt: wt attribute is not a real datatype')
1688 : end select
1689 : end if
1690 : end if
1691 :
1692 0 : end function cam_grid_get_areawt
1693 :
1694 : ! Find the longitude and latitude of a range of map entries
1695 : ! beg and end are the range of the first source index. blk is a block or chunk index
1696 0 : subroutine cam_grid_get_coords(id, beg, end, blk, lon, lat)
1697 :
1698 : ! Dummy arguments
1699 : integer, intent(in) :: id
1700 : integer, intent(in) :: beg
1701 : integer, intent(in) :: end
1702 : integer, intent(in) :: blk
1703 : real(r8), intent(inout) :: lon(:)
1704 : real(r8), intent(inout) :: lat(:)
1705 :
1706 : ! Local variables
1707 : integer :: gridid
1708 : integer :: i
1709 0 : gridid = get_cam_grid_index(id)
1710 0 : if (gridid > 0) then
1711 0 : do i = beg, end
1712 0 : if (cam_grids(gridid)%is_unstructured()) then
1713 0 : call endrun('cam_grid_get_coords: Not implemented')
1714 : else
1715 0 : call endrun('cam_grid_get_coords: Not implemented')
1716 : end if
1717 : end do
1718 : else
1719 0 : call endrun('cam_grid_get_coords: Bad grid ID')
1720 : end if
1721 0 : end subroutine cam_grid_get_coords
1722 :
1723 0 : logical function cam_grid_is_unstructured(id) result(unstruct)
1724 :
1725 : ! Dummy arguments
1726 : integer, intent(in) :: id
1727 :
1728 : ! Local variables
1729 : integer :: gridid
1730 0 : gridid = get_cam_grid_index(id)
1731 0 : if (gridid > 0) then
1732 0 : unstruct = cam_grids(gridid)%is_unstructured()
1733 : else
1734 0 : call endrun('cam_grid_is_unstructured: Bad grid ID')
1735 : end if
1736 0 : end function cam_grid_is_unstructured
1737 :
1738 5372160 : logical function cam_grid_is_block_indexed(id) result(block_indexed)
1739 :
1740 : ! Dummy arguments
1741 : integer, intent(in) :: id
1742 :
1743 : ! Local variables
1744 : integer :: gridid
1745 5372160 : gridid = get_cam_grid_index(id)
1746 5372160 : if (gridid > 0) then
1747 5372160 : block_indexed = cam_grids(gridid)%is_block_indexed()
1748 : else
1749 0 : call endrun('s: Bad grid ID')
1750 : end if
1751 5372160 : end function cam_grid_is_block_indexed
1752 :
1753 5372160 : logical function cam_grid_is_zonal(id) result(zonal)
1754 :
1755 : ! Dummy arguments
1756 : integer, intent(in) :: id
1757 :
1758 : ! Local variables
1759 : integer :: gridid
1760 5372160 : gridid = get_cam_grid_index(id)
1761 5372160 : if (gridid > 0) then
1762 5372160 : zonal = cam_grids(gridid)%is_zonal_grid()
1763 : else
1764 0 : call endrun('s: Bad grid ID')
1765 : end if
1766 5372160 : end function cam_grid_is_zonal
1767 :
1768 : ! Compute or update a grid patch mask
1769 0 : subroutine cam_grid_compute_patch(id, patch, lonl, lonu, latl, latu, cco)
1770 :
1771 : ! Dummy arguments
1772 : integer, intent(in) :: id
1773 : type(cam_grid_patch_t), intent(inout) :: patch
1774 : real(r8), intent(in) :: lonl
1775 : real(r8), intent(in) :: lonu
1776 : real(r8), intent(in) :: latl
1777 : real(r8), intent(in) :: latu
1778 : logical, intent(in) :: cco ! Collect columns?
1779 :
1780 : ! Local variables
1781 : integer :: gridid
1782 :
1783 0 : gridid = get_cam_grid_index(id)
1784 0 : if (gridid > 0) then
1785 0 : call cam_grids(gridid)%get_patch_mask(lonl, lonu, latl, latu, patch, cco)
1786 : else
1787 0 : call endrun('cam_grid_compute_patch: Bad grid ID')
1788 : end if
1789 :
1790 0 : end subroutine cam_grid_compute_patch
1791 :
1792 : !!#######################################################################
1793 : !!
1794 : !! CAM grid attribute functions
1795 : !!
1796 : !!#######################################################################
1797 :
1798 0 : subroutine cam_grid_attr_init(this, name, long_name, next)
1799 : ! Dummy arguments
1800 : class(cam_grid_attribute_t) :: this
1801 : character(len=*), intent(in) :: name
1802 : character(len=*), intent(in) :: long_name
1803 : class(cam_grid_attribute_t), pointer :: next
1804 :
1805 0 : this%name = trim(name)
1806 0 : this%long_name = trim(long_name)
1807 0 : this%next => next
1808 0 : end subroutine cam_grid_attr_init
1809 :
1810 26112 : subroutine print_attr_base(this)
1811 : ! Dummy arguments
1812 : class(cam_grid_attribute_t), intent(in) :: this
1813 26112 : if (masterproc) then
1814 34 : write(iulog, '(5a)') 'Attribute: ', trim(this%name), ", long name = '", &
1815 68 : trim(this%long_name), "'"
1816 : end if
1817 26112 : end subroutine print_attr_base
1818 :
1819 9216 : subroutine cam_grid_attr_init_0d_int(this, name, long_name, val)
1820 : ! Dummy arguments
1821 : class(cam_grid_attribute_0d_int_t) :: this
1822 : character(len=*), intent(in) :: name
1823 : character(len=*), intent(in) :: long_name
1824 : integer, intent(in) :: val
1825 :
1826 : ! call this%cam_grid_attr_init(name, '')
1827 9216 : this%name = trim(name)
1828 9216 : this%long_name = trim(long_name)
1829 9216 : this%ival = val
1830 9216 : end subroutine cam_grid_attr_init_0d_int
1831 :
1832 12288 : subroutine print_attr_0d_int(this)
1833 : ! Dummy arguments
1834 : class(cam_grid_attribute_0d_int_t), intent(in) :: this
1835 :
1836 12288 : call this%print_attr_base()
1837 12288 : if (masterproc) then
1838 16 : write(iulog, *) ' value = ', this%ival
1839 : end if
1840 12288 : end subroutine print_attr_0d_int
1841 :
1842 0 : subroutine cam_grid_attr_init_0d_char(this, name, long_name, val)
1843 : ! Dummy arguments
1844 : class(cam_grid_attribute_0d_char_t) :: this
1845 : character(len=*), intent(in) :: name
1846 : character(len=*), intent(in) :: long_name
1847 : character(len=*), intent(in) :: val
1848 :
1849 : ! call this%cam_grid_attr_init(name, '')
1850 0 : this%name = trim(name)
1851 0 : this%long_name = trim(long_name)
1852 0 : this%val = trim(val)
1853 0 : end subroutine cam_grid_attr_init_0d_char
1854 :
1855 0 : subroutine print_attr_0d_char(this)
1856 : ! Dummy arguments
1857 : class(cam_grid_attribute_0d_char_t), intent(in) :: this
1858 :
1859 0 : call this%print_attr_base()
1860 0 : if (masterproc) then
1861 0 : write(iulog, *) ' value = ', trim(this%val)
1862 : end if
1863 0 : end subroutine print_attr_0d_char
1864 :
1865 0 : subroutine cam_grid_attr_init_1d_int(this, name, long_name, dimname, &
1866 0 : dimsize, values, map)
1867 : ! Dummy arguments
1868 : class(cam_grid_attribute_1d_int_t) :: this
1869 : character(len=*), intent(in) :: name
1870 : character(len=*), intent(in) :: long_name
1871 : character(len=*), intent(in) :: dimname
1872 : integer, intent(in) :: dimsize
1873 : integer, target, intent(in) :: values(:)
1874 : integer(iMap), optional, target, intent(in) :: map(:)
1875 :
1876 : ! call this%cam_grid_attr_init(trim(name), trim(long_name))
1877 0 : if (len_trim(name) > max_hcoordname_len) then
1878 0 : call endrun('cam_grid_attr_1d_int: name too long')
1879 : end if
1880 0 : this%name = trim(name)
1881 0 : if (len_trim(long_name) > max_chars) then
1882 0 : call endrun('cam_grid_attr_1d_int: long_name too long')
1883 : end if
1884 0 : this%long_name = trim(long_name)
1885 :
1886 0 : if (len_trim(dimname) > max_hcoordname_len) then
1887 0 : call endrun('cam_grid_attr_1d_int: dimname too long')
1888 : end if
1889 0 : this%dimname = trim(dimname)
1890 0 : this%dimsize = dimsize
1891 0 : this%values => values
1892 : ! Fill in the optional map
1893 0 : if (present(map)) then
1894 0 : allocate(this%map(size(map)))
1895 0 : this%map(:) = map(:)
1896 : else
1897 0 : nullify(this%map)
1898 : end if
1899 0 : end subroutine cam_grid_attr_init_1d_int
1900 :
1901 13824 : subroutine cam_grid_attr_init_1d_r8(this, name, long_name, dimname, &
1902 13824 : dimsize, values, map)
1903 : ! Dummy arguments
1904 : class(cam_grid_attribute_1d_r8_t) :: this
1905 : character(len=*), intent(in) :: name
1906 : character(len=*), intent(in) :: long_name
1907 : character(len=*), intent(in) :: dimname
1908 : integer, intent(in) :: dimsize
1909 : real(r8), target, intent(in) :: values(:)
1910 : integer(iMap), optional, target, intent(in) :: map(:)
1911 :
1912 : ! call this%cam_grid_attr_init(trim(name), trim(long_name), next)
1913 13824 : this%name = trim(name)
1914 13824 : this%long_name = trim(long_name)
1915 :
1916 13824 : this%dimname = trim(dimname)
1917 13824 : this%dimsize = dimsize
1918 13824 : this%values => values
1919 : ! Fill in the optional map
1920 13824 : if (present(map)) then
1921 41472 : allocate(this%map(size(map)))
1922 1119168 : this%map(:) = map(:)
1923 : else
1924 0 : nullify(this%map)
1925 : end if
1926 13824 : end subroutine cam_grid_attr_init_1d_r8
1927 :
1928 0 : subroutine print_attr_1d_int(this)
1929 : ! Dummy arguments
1930 : class(cam_grid_attribute_1d_int_t), intent(in) :: this
1931 0 : call this%print_attr_base()
1932 0 : if (masterproc) then
1933 0 : write(iulog, *) ' dimname = ', trim(this%dimname)
1934 : end if
1935 0 : end subroutine print_attr_1d_int
1936 :
1937 13824 : subroutine print_attr_1d_r8(this)
1938 : ! Dummy arguments
1939 : class(cam_grid_attribute_1d_r8_t), intent(in) :: this
1940 13824 : call this%print_attr_base()
1941 13824 : if (masterproc) then
1942 18 : write(iulog, *) ' dimname = ', trim(this%dimname)
1943 : end if
1944 13824 : end subroutine print_attr_1d_r8
1945 :
1946 26112 : subroutine insert_grid_attribute(gridind, attr)
1947 : integer, intent(in) :: gridind
1948 : class(cam_grid_attribute_t), pointer :: attr
1949 :
1950 : ! Push a new attribute onto the grid
1951 : type(cam_grid_attr_ptr_t), pointer :: attrPtr
1952 :
1953 26112 : allocate(attrPtr)
1954 26112 : call attrPtr%initialize(attr)
1955 26112 : call attrPtr%setNext(cam_grids(gridind)%attributes)
1956 26112 : cam_grids(gridind)%attributes => attrPtr
1957 26112 : call attrPtr%attr%print_attr()
1958 26112 : end subroutine insert_grid_attribute
1959 :
1960 9216 : subroutine add_cam_grid_attribute_0d_int(gridname, name, long_name, val)
1961 : ! Dummy arguments
1962 : character(len=*), intent(in) :: gridname
1963 : character(len=*), intent(in) :: name
1964 : character(len=*), intent(in) :: long_name
1965 : integer, intent(in) :: val
1966 :
1967 : ! Local variables
1968 : type(cam_grid_attribute_0d_int_t), pointer :: attr
1969 : class(cam_grid_attribute_t), pointer :: attptr
1970 : character(len=120) :: errormsg
1971 : integer :: gridind
1972 :
1973 9216 : gridind = get_cam_grid_index(trim(gridname))
1974 9216 : if (gridind > 0) then
1975 9216 : call find_cam_grid_attr(gridind, trim(name), attptr)
1976 9216 : if (associated(attptr)) then
1977 : ! Attribute found, can't add it again!
1978 : write(errormsg, '(4a)') &
1979 0 : 'add_cam_grid_attribute_0d_int: attribute ', trim(name), &
1980 0 : ' already exists for ', cam_grids(gridind)%name
1981 0 : call endrun(errormsg)
1982 : else
1983 : ! Need a new attribute.
1984 27648 : allocate(attr)
1985 9216 : call attr%cam_grid_attr_init_0d_int(trim(name), trim(long_name), val)
1986 9216 : attptr => attr
1987 9216 : call insert_grid_attribute(gridind, attptr)
1988 : end if
1989 : else
1990 0 : write(errormsg, '(3a)') 'add_cam_grid_attribute_0d_int: grid ', &
1991 0 : trim(gridname), ' was not found'
1992 0 : call endrun(errormsg)
1993 : end if
1994 : ! call cam_grids(gridind)%print_cam_grid()
1995 9216 : end subroutine add_cam_grid_attribute_0d_int
1996 :
1997 0 : subroutine add_cam_grid_attribute_0d_char(gridname, name, val)
1998 : ! Dummy arguments
1999 : character(len=*), intent(in) :: gridname
2000 : character(len=*), intent(in) :: name
2001 : character(len=*), intent(in) :: val
2002 :
2003 : ! Local variables
2004 : type(cam_grid_attribute_0d_char_t), pointer :: attr
2005 : class(cam_grid_attribute_t), pointer :: attptr
2006 : character(len=120) :: errormsg
2007 : integer :: gridind
2008 :
2009 0 : gridind = get_cam_grid_index(trim(gridname))
2010 0 : if (gridind > 0) then
2011 0 : call find_cam_grid_attr(gridind, trim(name), attptr)
2012 0 : if (associated(attptr)) then
2013 : ! Attribute found, can't add it again!
2014 : write(errormsg, '(4a)') &
2015 0 : 'add_cam_grid_attribute_0d_char: attribute ', trim(name), &
2016 0 : ' already exists for ', cam_grids(gridind)%name
2017 0 : call endrun(errormsg)
2018 : else
2019 : ! Need a new attribute.
2020 0 : allocate(attr)
2021 0 : call attr%cam_grid_attr_init_0d_char(trim(name), '', val)
2022 0 : attptr => attr
2023 0 : call insert_grid_attribute(gridind, attptr)
2024 : end if
2025 : else
2026 0 : write(errormsg, '(3a)') 'add_cam_grid_attribute_0d_char: grid ', &
2027 0 : trim(gridname), ' was not found'
2028 0 : call endrun(errormsg)
2029 : end if
2030 : ! call cam_grids(gridind)%print_cam_grid()
2031 0 : end subroutine add_cam_grid_attribute_0d_char
2032 :
2033 0 : subroutine add_cam_grid_attribute_1d_int(gridname, name, long_name, &
2034 0 : dimname, values, map)
2035 : ! Dummy arguments
2036 : character(len=*), intent(in) :: gridname
2037 : character(len=*), intent(in) :: name
2038 : character(len=*), intent(in) :: long_name
2039 : character(len=*), intent(in) :: dimname
2040 : integer, intent(in), target :: values(:)
2041 : integer(iMap), intent(in), target, optional :: map(:)
2042 :
2043 : ! Local variables
2044 : type(cam_grid_attribute_1d_int_t), pointer :: attr
2045 : class(cam_grid_attribute_t), pointer :: attptr
2046 : character(len=120) :: errormsg
2047 : integer :: gridind
2048 : integer :: dimsize
2049 :
2050 0 : nullify(attr)
2051 0 : nullify(attptr)
2052 0 : gridind = get_cam_grid_index(trim(gridname))
2053 0 : if (gridind > 0) then
2054 0 : call find_cam_grid_attr(gridind, trim(name), attptr)
2055 0 : if (associated(attptr)) then
2056 : ! Attribute found, can't add it again!
2057 : write(errormsg, '(4a)') &
2058 0 : 'add_cam_grid_attribute_1d_int: attribute ', trim(name), &
2059 0 : ' already exists for ', cam_grids(gridind)%name
2060 0 : call endrun(errormsg)
2061 : else
2062 : ! Need a new attribute.
2063 0 : dimsize = cam_grids(gridind)%lat_coord%global_size(trim(dimname))
2064 0 : if (dimsize < 1) then
2065 0 : dimsize = cam_grids(gridind)%lon_coord%global_size(trim(dimname))
2066 : end if
2067 0 : if (dimsize < 1) then
2068 0 : write(errormsg, *) 'add_cam_grid_attribute_1d_int: attribute ', &
2069 0 : 'dimension ', trim(dimname), ' for ', trim(name), ', not found'
2070 0 : call endrun(errormsg)
2071 : end if
2072 0 : allocate(attr)
2073 : call attr%cam_grid_attr_init_1d_int(trim(name), trim(long_name), &
2074 0 : trim(dimname), dimsize, values, map)
2075 0 : attptr => attr
2076 0 : call insert_grid_attribute(gridind, attptr)
2077 : end if
2078 : else
2079 0 : write(errormsg, '(3a)') 'add_cam_grid_attribute_1d_int: grid ', &
2080 0 : trim(gridname), ' was not found'
2081 0 : call endrun(errormsg)
2082 : end if
2083 : ! call cam_grids(gridind)%print_cam_grid()
2084 0 : end subroutine add_cam_grid_attribute_1d_int
2085 :
2086 13824 : subroutine add_cam_grid_attribute_1d_r8(gridname, name, long_name, &
2087 13824 : dimname, values, map)
2088 : ! Dummy arguments
2089 : character(len=*), intent(in) :: gridname
2090 : character(len=*), intent(in) :: name
2091 : character(len=*), intent(in) :: long_name
2092 : character(len=*), intent(in) :: dimname
2093 : real(r8), intent(in), target :: values(:)
2094 : integer(iMap), intent(in), target, optional :: map(:)
2095 :
2096 : ! Local variables
2097 : type(cam_grid_attribute_1d_r8_t), pointer :: attr
2098 : class(cam_grid_attribute_t), pointer :: attptr
2099 : character(len=120) :: errormsg
2100 : integer :: gridind
2101 : integer :: dimsize
2102 :
2103 13824 : gridind = get_cam_grid_index(trim(gridname))
2104 13824 : if (gridind > 0) then
2105 13824 : call find_cam_grid_attr(gridind, trim(name), attptr)
2106 13824 : if (associated(attptr)) then
2107 : ! Attribute found, can't add it again!
2108 : write(errormsg, '(4a)') &
2109 0 : 'add_cam_grid_attribute_1d_r8: attribute ', trim(name), &
2110 0 : ' already exists for ', cam_grids(gridind)%name
2111 0 : call endrun(errormsg)
2112 : else
2113 : ! Need a new attribute.
2114 13824 : dimsize = cam_grids(gridind)%lat_coord%global_size(trim(dimname))
2115 13824 : if (dimsize < 1) then
2116 0 : dimsize = cam_grids(gridind)%lon_coord%global_size(trim(dimname))
2117 : end if
2118 13824 : if (dimsize < 1) then
2119 0 : write(errormsg, *) 'add_cam_grid_attribute_1d_r8: attribute ', &
2120 0 : 'dimension ', trim(dimname), ' for ', trim(name), ', not found'
2121 0 : call endrun(errormsg)
2122 : end if
2123 41472 : allocate(attr)
2124 : call attr%cam_grid_attr_init_1d_r8(trim(name), trim(long_name), &
2125 13824 : trim(dimname), dimsize, values, map)
2126 13824 : attptr => attr
2127 13824 : call insert_grid_attribute(gridind, attptr)
2128 : end if
2129 : else
2130 0 : write(errormsg, '(3a)') 'add_cam_grid_attribute_1d_r8: grid ', &
2131 0 : trim(gridname), ' was not found'
2132 0 : call endrun(errormsg)
2133 : end if
2134 : ! call cam_grids(gridind)%print_cam_grid()
2135 13824 : end subroutine add_cam_grid_attribute_1d_r8
2136 :
2137 : !!#######################################################################
2138 : !!
2139 : !! CAM grid attribute pointer (list node) functions
2140 : !!
2141 : !!#######################################################################
2142 :
2143 26112 : subroutine initializeAttrPtr(this, attr)
2144 : ! Dummy arguments
2145 : class(cam_grid_attr_ptr_t) :: this
2146 : class(cam_grid_attribute_t), target :: attr
2147 :
2148 26112 : if (associated(this%next)) then
2149 0 : if (masterproc) then
2150 0 : write(iulog, *) 'WARNING: Overwriting attr pointer for cam_grid_attr_ptr_t'
2151 : end if
2152 : end if
2153 26112 : this%attr => attr
2154 26112 : end subroutine initializeAttrPtr
2155 :
2156 0 : function getAttrPtrAttr(this)
2157 : ! Dummy variable
2158 : class(cam_grid_attr_ptr_t) :: this
2159 : class(cam_grid_attribute_t), pointer :: getAttrPtrAttr
2160 :
2161 0 : getAttrPtrAttr => this%attr
2162 0 : end function getAttrPtrAttr
2163 :
2164 0 : function getAttrPtrNext(this)
2165 : ! Dummy arguments
2166 : class(cam_grid_attr_ptr_t) :: this
2167 : type(cam_grid_attr_ptr_t), pointer :: getAttrPtrNext
2168 :
2169 0 : getAttrPtrNext => this%next
2170 0 : end function getAttrPtrNext
2171 :
2172 26112 : subroutine setAttrPtrNext(this, next)
2173 : ! Dummy arguments
2174 : class(cam_grid_attr_ptr_t) :: this
2175 : type(cam_grid_attr_ptr_t), pointer :: next
2176 :
2177 26112 : if (associated(this%next)) then
2178 0 : if (masterproc) then
2179 0 : write(iulog, *) 'WARNING: Overwriting next pointer for cam_grid_attr_ptr_t'
2180 : end if
2181 : end if
2182 26112 : this%next => next
2183 26112 : end subroutine setAttrPtrNext
2184 :
2185 : !---------------------------------------------------------------------------
2186 : !
2187 : ! write_cam_grid_attr_0d_int
2188 : !
2189 : ! Write a grid attribute
2190 : !
2191 : !---------------------------------------------------------------------------
2192 :
2193 24576 : subroutine write_cam_grid_attr_0d_int(attr, File, file_index)
2194 : use pio, only: file_desc_t, pio_put_att, pio_noerr, pio_int, &
2195 : pio_inq_att, PIO_GLOBAL
2196 : use cam_pio_utils, only: cam_pio_def_var
2197 :
2198 : ! Dummy arguments
2199 : class(cam_grid_attribute_0d_int_t), intent(inout) :: attr
2200 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
2201 : integer, optional, intent(in) :: file_index
2202 :
2203 : ! Local variables
2204 : integer :: attrtype
2205 : integer(imap) :: attrlen
2206 : integer :: ierr
2207 : integer :: file_index_loc
2208 :
2209 24576 : if (present(file_index)) then
2210 24576 : file_index_loc = file_index
2211 : else
2212 : file_index_loc = 1
2213 : end if
2214 :
2215 : ! Since more than one grid can share an attribute, assume that if the
2216 : ! vardesc is associated, that grid defined the attribute
2217 24576 : if (.not. associated(attr%vardesc(file_index_loc)%p)) then
2218 24576 : if (len_trim(attr%long_name) > 0) then
2219 : ! This 0d attribute is a scalar variable with a long_name attribute
2220 : ! First, define the variable
2221 0 : allocate(attr%vardesc(file_index_loc)%p)
2222 : call cam_pio_def_var(File, trim(attr%name), pio_int, attr%vardesc(file_index_loc)%p, &
2223 0 : existOK=.false.)
2224 0 : ierr=pio_put_att(File, attr%vardesc(file_index_loc)%p, 'long_name', trim(attr%long_name))
2225 0 : call cam_pio_handle_error(ierr, 'Error writing "long_name" attr in write_cam_grid_attr_0d_int')
2226 : else
2227 : ! This 0d attribute is a global attribute
2228 : ! Check to see if the attribute already exists in the file
2229 24576 : ierr = pio_inq_att(File, PIO_GLOBAL, attr%name, attrtype, attrlen)
2230 24576 : if (ierr /= PIO_NOERR) then
2231 : ! Time to define the attribute
2232 21504 : ierr = pio_put_att(File, PIO_GLOBAL, trim(attr%name), attr%ival)
2233 21504 : call cam_pio_handle_error(ierr, 'Unable to define attribute in write_cam_grid_attr_0d_int')
2234 : end if
2235 : end if
2236 : end if
2237 :
2238 24576 : end subroutine write_cam_grid_attr_0d_int
2239 :
2240 : !---------------------------------------------------------------------------
2241 : !
2242 : ! write_cam_grid_attr_0d_char
2243 : !
2244 : ! Write a grid attribute
2245 : !
2246 : !---------------------------------------------------------------------------
2247 :
2248 0 : subroutine write_cam_grid_attr_0d_char(attr, File, file_index)
2249 24576 : use pio, only: file_desc_t, pio_put_att, pio_noerr, &
2250 : pio_inq_att, PIO_GLOBAL
2251 :
2252 : ! Dummy arguments
2253 : class(cam_grid_attribute_0d_char_t), intent(inout) :: attr
2254 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
2255 : integer, optional, intent(in) :: file_index
2256 :
2257 : ! Local variables
2258 : integer :: attrtype
2259 : integer(imap) :: attrlen
2260 : integer :: ierr
2261 : integer :: file_index_loc
2262 :
2263 0 : if (present(file_index)) then
2264 0 : file_index_loc = file_index
2265 : else
2266 : file_index_loc = 1
2267 : end if
2268 :
2269 : ! Since more than one grid can share an attribute, assume that if the
2270 : ! vardesc is associated, that grid defined the attribute
2271 0 : if (.not. associated(attr%vardesc(file_index_loc)%p)) then
2272 : ! The 0d char attributes are global attribues
2273 : ! Check to see if the attribute already exists in the file
2274 0 : ierr = pio_inq_att(File, PIO_GLOBAL, attr%name, attrtype, attrlen)
2275 0 : if (ierr /= PIO_NOERR) then
2276 : ! Time to define the variable
2277 0 : ierr = pio_put_att(File, PIO_GLOBAL, trim(attr%name), attr%val)
2278 0 : call cam_pio_handle_error(ierr, 'Unable to define attribute in write_cam_grid_attr_0d_char')
2279 : end if
2280 : end if
2281 :
2282 0 : end subroutine write_cam_grid_attr_0d_char
2283 :
2284 : !---------------------------------------------------------------------------
2285 : !
2286 : ! write_cam_grid_attr_1d_int
2287 : !
2288 : ! Write a grid attribute
2289 : !
2290 : !---------------------------------------------------------------------------
2291 :
2292 0 : subroutine write_cam_grid_attr_1d_int(attr, File, file_index)
2293 : use pio, only: file_desc_t, pio_put_att, pio_noerr
2294 : use pio, only: pio_inq_dimid, pio_int
2295 : use cam_pio_utils, only: cam_pio_def_var, cam_pio_closefile
2296 :
2297 : ! Dummy arguments
2298 : class(cam_grid_attribute_1d_int_t), intent(inout) :: attr
2299 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
2300 : integer, optional, intent(in) :: file_index
2301 :
2302 : ! Local variables
2303 : integer :: dimid ! PIO dimension ID
2304 : character(len=120) :: errormsg
2305 : integer :: ierr
2306 : integer :: file_index_loc
2307 :
2308 0 : if (present(file_index)) then
2309 0 : file_index_loc = file_index
2310 : else
2311 : file_index_loc = 1
2312 : end if
2313 :
2314 : ! Since more than one grid can share an attribute, assume that if the
2315 : ! vardesc is associated, that grid defined the attribute
2316 0 : if (.not. associated(attr%vardesc(file_index_loc)%p)) then
2317 : ! Check to see if the dimension already exists in the file
2318 0 : ierr = pio_inq_dimid(File, trim(attr%dimname), dimid)
2319 0 : if (ierr /= PIO_NOERR) then
2320 : ! The dimension has not yet been defined. This is an error
2321 : ! NB: It should have been defined as part of a coordinate
2322 0 : write(errormsg, *) 'write_cam_grid_attr_1d_int: dimension, ', &
2323 0 : trim(attr%dimname), ', does not exist'
2324 0 : call cam_pio_closefile(File)
2325 0 : call endrun(errormsg)
2326 : end if
2327 : ! Time to define the variable
2328 0 : allocate(attr%vardesc(file_index_loc)%p)
2329 : call cam_pio_def_var(File, trim(attr%name), pio_int, (/dimid/), &
2330 0 : attr%vardesc(file_index_loc)%p, existOK=.false.)
2331 0 : ierr = pio_put_att(File, attr%vardesc(file_index_loc)%p, 'long_name', trim(attr%long_name))
2332 0 : call cam_pio_handle_error(ierr, 'Error writing "long_name" attr in write_cam_grid_attr_1d_int')
2333 : end if
2334 :
2335 0 : end subroutine write_cam_grid_attr_1d_int
2336 :
2337 : !---------------------------------------------------------------------------
2338 : !
2339 : ! write_cam_grid_attr_1d_r8
2340 : !
2341 : ! Write a grid attribute
2342 : !
2343 : !---------------------------------------------------------------------------
2344 :
2345 24576 : subroutine write_cam_grid_attr_1d_r8(attr, File, file_index)
2346 0 : use pio, only: file_desc_t, pio_put_att, pio_noerr, pio_double, &
2347 : pio_inq_dimid
2348 : use cam_pio_utils, only: cam_pio_def_var, cam_pio_closefile
2349 :
2350 : ! Dummy arguments
2351 : class(cam_grid_attribute_1d_r8_t), intent(inout) :: attr
2352 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
2353 : integer, optional, intent(in) :: file_index
2354 :
2355 : ! Local variables
2356 : integer :: dimid ! PIO dimension ID
2357 : character(len=120) :: errormsg
2358 : integer :: ierr
2359 : integer :: file_index_loc
2360 :
2361 24576 : if (present(file_index)) then
2362 24576 : file_index_loc = file_index
2363 : else
2364 : file_index_loc = 1
2365 : end if
2366 :
2367 : ! Since more than one grid can share an attribute, assume that if the
2368 : ! vardesc is associated, that grid defined the attribute
2369 24576 : if (.not. associated(attr%vardesc(file_index_loc)%p)) then
2370 : ! Check to see if the dimension already exists in the file
2371 24576 : ierr = pio_inq_dimid(File, trim(attr%dimname), dimid)
2372 24576 : if (ierr /= PIO_NOERR) then
2373 : ! The dimension has not yet been defined. This is an error
2374 : ! NB: It should have been defined as part of a coordinate
2375 0 : write(errormsg, *) 'write_cam_grid_attr_1d_r8: dimension, ', &
2376 0 : trim(attr%dimname), ', does not exist'
2377 0 : call cam_pio_closefile(File)
2378 0 : call endrun(errormsg)
2379 : end if
2380 : ! Time to define the variable
2381 24576 : allocate(attr%vardesc(file_index_loc)%p)
2382 : call cam_pio_def_var(File, trim(attr%name), pio_double, (/dimid/), &
2383 49152 : attr%vardesc(file_index_loc)%p, existOK=.false.)
2384 : ! long_name
2385 24576 : ierr = pio_put_att(File, attr%vardesc(file_index_loc)%p, 'long_name', trim(attr%long_name))
2386 24576 : call cam_pio_handle_error(ierr, 'Error writing "long_name" attr in write_cam_grid_attr_1d_r8')
2387 : end if
2388 :
2389 24576 : end subroutine write_cam_grid_attr_1d_r8
2390 :
2391 : !---------------------------------------------------------------------------
2392 : !
2393 : ! cam_grid_attribute_copy
2394 : !
2395 : ! Copy an attribute from a source grid to a destination grid
2396 : !
2397 : !---------------------------------------------------------------------------
2398 3072 : subroutine cam_grid_attribute_copy(src_grid, dest_grid, attribute_name)
2399 : ! Dummy arguments
2400 : character(len=*), intent(in) :: src_grid
2401 : character(len=*), intent(in) :: dest_grid
2402 : character(len=*), intent(in) :: attribute_name
2403 :
2404 : ! Local variables
2405 : character(len=120) :: errormsg
2406 : integer :: src_ind, dest_ind
2407 : class(cam_grid_attribute_t), pointer :: attr
2408 :
2409 : ! Find the source and destination grid indices
2410 3072 : src_ind = get_cam_grid_index(trim(src_grid))
2411 3072 : dest_ind = get_cam_grid_index(trim(dest_grid))
2412 :
2413 3072 : call find_cam_grid_attr(dest_ind, trim(attribute_name), attr)
2414 3072 : if (associated(attr)) then
2415 : ! Attribute found, can't add it again!
2416 0 : write(errormsg, '(4a)') 'CAM_GRID_ATTRIBUTE_COPY: attribute ', &
2417 0 : trim(attribute_name),' already exists for ',cam_grids(dest_ind)%name
2418 0 : call endrun(errormsg)
2419 : else
2420 3072 : call find_cam_grid_attr(src_ind, trim(attribute_name), attr)
2421 3072 : if (associated(attr)) then
2422 : ! Copy the attribute
2423 3072 : call insert_grid_attribute(dest_ind, attr)
2424 : else
2425 0 : write(errormsg, '(4a)') ": Did not find attribute, '", &
2426 0 : trim(attribute_name), "' in ", cam_grids(src_ind)%name
2427 0 : call endrun("CAM_GRID_ATTRIBUTE_COPY"//errormsg)
2428 : end if
2429 : end if
2430 :
2431 24576 : end subroutine cam_grid_attribute_copy
2432 :
2433 : !---------------------------------------------------------------------------
2434 : !
2435 : ! cam_grid_write_attr
2436 : !
2437 : ! Write the dimension and coordinate attributes for the horizontal history
2438 : ! coordinates.
2439 : !
2440 : !---------------------------------------------------------------------------
2441 12288 : subroutine cam_grid_write_attr(File, grid_id, header_info, file_index)
2442 : use pio, only: file_desc_t, PIO_BCAST_ERROR, pio_seterrorhandling
2443 :
2444 : ! Dummy arguments
2445 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
2446 : integer, intent(in) :: grid_id
2447 : type(cam_grid_header_info_t), intent(inout) :: header_info
2448 : integer, optional, intent(in) :: file_index
2449 :
2450 : ! Local variables
2451 : integer :: gridind
2452 : class(cam_grid_attribute_t), pointer :: attr
2453 : type(cam_grid_attr_ptr_t), pointer :: attrPtr
2454 : integer :: dimids(2)
2455 : integer :: err_handling
2456 : integer :: file_index_loc
2457 :
2458 12288 : if (present(file_index)) then
2459 9216 : file_index_loc = file_index
2460 : else
2461 3072 : file_index_loc = 1
2462 : end if
2463 :
2464 12288 : gridind = get_cam_grid_index(grid_id)
2465 : !! Fill this in to make sure history finds grid
2466 12288 : header_info%grid_id = grid_id
2467 :
2468 12288 : if (allocated(header_info%hdims)) then
2469 4608 : deallocate(header_info%hdims)
2470 : end if
2471 :
2472 12288 : if (associated(header_info%lon_varid)) then
2473 : ! This could be a sign of bad memory management
2474 0 : call endrun('CAM_GRID_WRITE_ATTR: lon_varid should be NULL')
2475 : end if
2476 12288 : if (associated(header_info%lat_varid)) then
2477 : ! This could be a sign of bad memory management
2478 0 : call endrun('CAM_GRID_WRITE_ATTR: lat_varid should be NULL')
2479 : end if
2480 :
2481 : ! Only write this grid if not already defined
2482 12288 : if (cam_grids(gridind)%attrs_defined(file_index_loc)) then
2483 : ! We need to fill out the hdims info for this grid
2484 0 : call cam_grids(gridind)%find_dimids(File, dimids)
2485 0 : if (dimids(2) < 0) then
2486 0 : allocate(header_info%hdims(1))
2487 0 : header_info%hdims(1) = dimids(1)
2488 : else
2489 0 : allocate(header_info%hdims(2))
2490 0 : header_info%hdims(1:2) = dimids(1:2)
2491 : end if
2492 : else
2493 : ! Write the horizontal coord attributes first so that we have the dims
2494 12288 : call cam_grids(gridind)%lat_coord%write_attr(File, dimids(2), file_index=file_index_loc)
2495 12288 : call cam_grids(gridind)%lon_coord%write_attr(File, dimids(1), file_index=file_index_loc)
2496 :
2497 12288 : if (dimids(2) == dimids(1)) then
2498 12288 : allocate(header_info%hdims(1))
2499 : else
2500 0 : allocate(header_info%hdims(2))
2501 0 : header_info%hdims(2) = dimids(2)
2502 : end if
2503 12288 : header_info%hdims(1) = dimids(1)
2504 :
2505 : ! We will handle errors for this routine
2506 12288 : call pio_seterrorhandling(File, PIO_BCAST_ERROR,err_handling)
2507 :
2508 12288 : attrPtr => cam_grids(gridind)%attributes
2509 61440 : do while (associated(attrPtr))
2510 : !!XXgoldyXX: Is this not working in PGI?
2511 : ! attr => attrPtr%getAttr()
2512 49152 : attr => attrPtr%attr
2513 49152 : call attr%write_attr(File, file_index=file_index_loc)
2514 : !!XXgoldyXX: Is this not working in PGI?
2515 : ! attrPtr => attrPtr%getNext()
2516 49152 : attrPtr => attrPtr%next
2517 : end do
2518 :
2519 : ! Back to previous I/O error handling
2520 12288 : call pio_seterrorhandling(File, err_handling)
2521 12288 : cam_grids(gridind)%attrs_defined(file_index_loc) = .true.
2522 : end if
2523 :
2524 12288 : end subroutine cam_grid_write_attr
2525 :
2526 24576 : subroutine write_cam_grid_val_0d_int(attr, File, file_index)
2527 : use pio, only: file_desc_t, pio_put_var
2528 :
2529 : ! Dummy arguments
2530 : class(cam_grid_attribute_0d_int_t), intent(inout) :: attr
2531 : type(file_desc_t), intent(inout) :: File
2532 : integer, optional, intent(in) :: file_index
2533 :
2534 : ! Local variables
2535 : integer :: ierr
2536 : integer :: file_index_loc
2537 :
2538 24576 : if (present(file_index)) then
2539 24576 : file_index_loc = file_index
2540 : else
2541 : file_index_loc = 1
2542 : end if
2543 :
2544 : ! We only write this var if it is a variable
2545 24576 : if (associated(attr%vardesc(file_index_loc)%p)) then
2546 0 : ierr = pio_put_var(File, attr%vardesc(file_index_loc)%p, attr%ival)
2547 0 : call cam_pio_handle_error(ierr, 'Error writing value in write_cam_grid_val_0d_int')
2548 0 : deallocate(attr%vardesc(file_index_loc)%p)
2549 0 : nullify(attr%vardesc(file_index_loc)%p)
2550 : end if
2551 :
2552 24576 : end subroutine write_cam_grid_val_0d_int
2553 :
2554 0 : subroutine write_cam_grid_val_0d_char(attr, File, file_index)
2555 : use pio, only: file_desc_t
2556 :
2557 : ! Dummy arguments
2558 : class(cam_grid_attribute_0d_char_t), intent(inout) :: attr
2559 : type(file_desc_t), intent(inout) :: File
2560 : integer, optional, intent(in) :: file_index
2561 :
2562 : ! This subroutine is a stub because global attributes are written
2563 : ! in define mode
2564 0 : return
2565 : end subroutine write_cam_grid_val_0d_char
2566 :
2567 0 : subroutine write_cam_grid_val_1d_int(attr, File, file_index)
2568 : use pio, only: file_desc_t, pio_put_var, pio_int, &
2569 : pio_write_darray, io_desc_t, pio_freedecomp
2570 : use cam_pio_utils, only: cam_pio_newdecomp
2571 :
2572 : ! Dummy arguments
2573 : class(cam_grid_attribute_1d_int_t), intent(inout) :: attr
2574 : type(file_desc_t), intent(inout) :: File
2575 : integer, optional, intent(in) :: file_index
2576 :
2577 : ! Local variables
2578 : integer :: ierr
2579 : type(io_desc_t), pointer :: iodesc
2580 : integer :: file_index_loc
2581 :
2582 0 : if (present(file_index)) then
2583 0 : file_index_loc = file_index
2584 : else
2585 : file_index_loc = 1
2586 : end if
2587 :
2588 0 : nullify(iodesc)
2589 : ! Since more than one grid can share an attribute, assume that if the
2590 : ! vardesc is not associated, another grid write the values
2591 0 : if (associated(attr%vardesc(file_index_loc)%p)) then
2592 : ! Write out the values for this dimension variable
2593 0 : if (associated(attr%map)) then
2594 : ! This is a distributed variable, use pio_write_darray
2595 0 : allocate(iodesc)
2596 0 : call cam_pio_newdecomp(iodesc, (/attr%dimsize/), attr%map, pio_int)
2597 0 : call pio_write_darray(File, attr%vardesc(file_index_loc)%p, iodesc, attr%values, ierr)
2598 0 : call pio_freedecomp(File, iodesc)
2599 0 : deallocate(iodesc)
2600 : nullify(iodesc)
2601 : else
2602 : ! This is a local variable, pio_put_var should work fine
2603 0 : ierr = pio_put_var(File, attr%vardesc(file_index_loc)%p, attr%values)
2604 : end if
2605 0 : call cam_pio_handle_error(ierr, 'Error writing variable values in write_cam_grid_val_1d_int')
2606 0 : deallocate(attr%vardesc(file_index_loc)%p)
2607 0 : nullify(attr%vardesc(file_index_loc)%p)
2608 : end if
2609 :
2610 0 : end subroutine write_cam_grid_val_1d_int
2611 :
2612 24576 : subroutine write_cam_grid_val_1d_r8(attr, File, file_index)
2613 0 : use pio, only: file_desc_t, pio_put_var, pio_double, &
2614 : pio_write_darray, io_desc_t, pio_freedecomp
2615 : use cam_pio_utils, only: cam_pio_newdecomp
2616 :
2617 : ! Dummy arguments
2618 : class(cam_grid_attribute_1d_r8_t), intent(inout) :: attr
2619 : type(file_desc_t), intent(inout) :: File
2620 : integer, optional, intent(in) :: file_index
2621 :
2622 : ! Local variables
2623 : integer :: ierr
2624 : type(io_desc_t), pointer :: iodesc
2625 : integer :: file_index_loc
2626 :
2627 24576 : if (present(file_index)) then
2628 24576 : file_index_loc = file_index
2629 : else
2630 : file_index_loc = 1
2631 : end if
2632 :
2633 24576 : nullify(iodesc)
2634 : ! Since more than one grid can share an attribute, assume that if the
2635 : ! vardesc is not associated, another grid write the values
2636 24576 : if (associated(attr%vardesc(file_index_loc)%p)) then
2637 : ! Write out the values for this dimension variable
2638 24576 : if (associated(attr%map)) then
2639 : ! This is a distributed variable, use pio_write_darray
2640 24576 : allocate(iodesc)
2641 49152 : call cam_pio_newdecomp(iodesc, (/attr%dimsize/), attr%map, pio_double)
2642 24576 : call pio_write_darray(File, attr%vardesc(file_index_loc)%p, iodesc, attr%values, ierr)
2643 24576 : call pio_freedecomp(File, iodesc)
2644 24576 : deallocate(iodesc)
2645 : nullify(iodesc)
2646 : else
2647 : ! This is a local variable, pio_put_var should work fine
2648 0 : ierr = pio_put_var(File, attr%vardesc(file_index_loc)%p, attr%values)
2649 : end if
2650 24576 : call cam_pio_handle_error(ierr, 'Error writing variable values in write_cam_grid_val_1d_r8')
2651 24576 : deallocate(attr%vardesc(file_index_loc)%p)
2652 24576 : nullify(attr%vardesc(file_index_loc)%p)
2653 : end if
2654 :
2655 24576 : end subroutine write_cam_grid_val_1d_r8
2656 :
2657 12288 : subroutine cam_grid_write_var(File, grid_id, file_index)
2658 24576 : use pio, only: file_desc_t, pio_bcast_error, pio_seterrorhandling
2659 :
2660 : ! Dummy arguments
2661 : type(file_desc_t), intent(inout) :: File ! PIO file Handle
2662 : integer, intent(in) :: grid_id
2663 : integer, optional, intent(in) :: file_index
2664 :
2665 : ! Local variables
2666 : integer :: gridind
2667 : integer :: err_handling
2668 : class(cam_grid_attribute_t), pointer :: attr
2669 : type(cam_grid_attr_ptr_t), pointer :: attrPtr
2670 : integer :: file_index_loc
2671 :
2672 12288 : if (present(file_index)) then
2673 9216 : file_index_loc = file_index
2674 : else
2675 3072 : file_index_loc = 1
2676 : end if
2677 12288 : gridind = get_cam_grid_index(grid_id)
2678 : ! Only write if not already done
2679 12288 : if (cam_grids(gridind)%attrs_defined(file_index_loc)) then
2680 : ! Write the horizontal coorinate values
2681 12288 : call cam_grids(gridind)%lon_coord%write_var(File, file_index)
2682 12288 : call cam_grids(gridind)%lat_coord%write_var(File, file_index)
2683 :
2684 : ! We will handle errors for this routine
2685 12288 : call pio_seterrorhandling(File, PIO_BCAST_ERROR,err_handling)
2686 :
2687 : ! Write out the variable values for each grid attribute
2688 12288 : attrPtr => cam_grids(gridind)%attributes
2689 61440 : do while (associated(attrPtr))
2690 : !!XXgoldyXX: Is this not working in PGI?
2691 : ! attr => attrPtr%getAttr()
2692 49152 : attr => attrPtr%attr
2693 49152 : call attr%write_val(File, file_index=file_index_loc)
2694 : !!XXgoldyXX: Is this not working in PGI?
2695 : ! attrPtr => attrPtr%getNext()
2696 49152 : attrPtr => attrPtr%next
2697 : end do
2698 :
2699 : ! Back to previous I/O error handling
2700 12288 : call pio_seterrorhandling(File, err_handling)
2701 :
2702 12288 : cam_grids(gridind)%attrs_defined(file_index_loc) = .false.
2703 : end if
2704 :
2705 12288 : end subroutine cam_grid_write_var
2706 :
2707 5372160 : logical function cam_grid_block_indexed(this)
2708 : class(cam_grid_t) :: this
2709 :
2710 5372160 : cam_grid_block_indexed = this%block_indexed
2711 5372160 : end function cam_grid_block_indexed
2712 :
2713 5372160 : logical function cam_grid_zonal_grid(this)
2714 : class(cam_grid_t) :: this
2715 :
2716 5372160 : cam_grid_zonal_grid = this%zonal_grid
2717 5372160 : end function cam_grid_zonal_grid
2718 :
2719 923904 : logical function cam_grid_unstructured(this)
2720 : class(cam_grid_t) :: this
2721 :
2722 923904 : cam_grid_unstructured = this%unstructured
2723 923904 : end function cam_grid_unstructured
2724 :
2725 : !---------------------------------------------------------------------------
2726 : !
2727 : ! cam_grid_get_dims: Return the dimensions of the grid
2728 : ! For lon/lat grids, this is (nlon, nlat)
2729 : ! For unstructured grids, this is (ncols, 1)
2730 : !
2731 : !---------------------------------------------------------------------------
2732 923904 : subroutine cam_grid_get_dims(this, dims)
2733 : ! Dummy arguments
2734 : class(cam_grid_t) :: this
2735 : integer, intent(inout) :: dims(2)
2736 :
2737 923904 : if (this%is_unstructured()) then
2738 923904 : call this%lon_coord%get_coord_len(dims(1))
2739 923904 : dims(2) = 1
2740 : else
2741 0 : call this%lon_coord%get_coord_len(dims(1))
2742 0 : call this%lat_coord%get_coord_len(dims(2))
2743 : end if
2744 :
2745 923904 : end subroutine cam_grid_get_dims
2746 :
2747 : !---------------------------------------------------------------------------
2748 : !
2749 : ! cam_grid_coord_names: Return the names of the grid axes
2750 : !
2751 : !---------------------------------------------------------------------------
2752 0 : subroutine cam_grid_coord_names(this, lon_name, lat_name)
2753 : ! Dummy arguments
2754 : class(cam_grid_t) :: this
2755 : character(len=*), intent(out) :: lon_name
2756 : character(len=*), intent(out) :: lat_name
2757 :
2758 0 : call this%lon_coord%get_coord_name(lon_name)
2759 0 : call this%lat_coord%get_coord_name(lat_name)
2760 :
2761 0 : end subroutine cam_grid_coord_names
2762 :
2763 : !---------------------------------------------------------------------------
2764 : !
2765 : ! cam_grid_dim_names: Return the names of the dimensions of the grid axes.
2766 : ! Note that these may be the same
2767 : !
2768 : !---------------------------------------------------------------------------
2769 1069056 : subroutine cam_grid_dim_names(this, name1, name2)
2770 : ! Dummy arguments
2771 : class(cam_grid_t) :: this
2772 : character(len=*), intent(out) :: name1
2773 : character(len=*), intent(out) :: name2
2774 :
2775 1069056 : call this%lon_coord%get_dim_name(name1)
2776 1069056 : call this%lat_coord%get_dim_name(name2)
2777 :
2778 1069056 : end subroutine cam_grid_dim_names
2779 :
2780 : !---------------------------------------------------------------------------
2781 : !
2782 : ! cam_grid_dimensions_id: Return the dimensions of the grid
2783 : ! For lon/lat grids, this is (nlon, nlat)
2784 : ! For unstructured grids, this is (ncols, 1)
2785 : !
2786 : !---------------------------------------------------------------------------
2787 919296 : subroutine cam_grid_dimensions_id(gridid, dims, rank)
2788 : ! Dummy arguments
2789 : integer, intent(in) :: gridid
2790 : integer, intent(inout) :: dims(2)
2791 : integer, optional, intent(out) :: rank
2792 :
2793 : ! Local variables
2794 : integer :: index
2795 : character(len=max_hcoordname_len) :: dname1, dname2
2796 : character(len=120) :: errormsg
2797 :
2798 919296 : index = get_cam_grid_index(gridid)
2799 919296 : if (index < 0) then
2800 0 : write(errormsg, *) 'No CAM grid with ID =', gridid
2801 0 : call endrun(errormsg)
2802 : else
2803 919296 : call cam_grids(index)%coord_lengths(dims)
2804 : end if
2805 919296 : if (present(rank)) then
2806 641280 : call cam_grids(index)%dim_names(dname1, dname2)
2807 641280 : if (trim(dname1) == trim(dname2)) then
2808 641280 : rank = 1
2809 : else
2810 0 : rank = 2
2811 : end if
2812 : end if
2813 :
2814 919296 : end subroutine cam_grid_dimensions_id
2815 :
2816 : !---------------------------------------------------------------------------
2817 : !
2818 : ! cam_grid_dimensions_name: Return the dimensions of the grid
2819 : ! For lon/lat grids, this is (nlon, nlat)
2820 : ! For unstructured grids, this is (ncols, 1)
2821 : !
2822 : !---------------------------------------------------------------------------
2823 2304 : subroutine cam_grid_dimensions_name(gridname, dims, rank)
2824 : ! Dummy arguments
2825 : character(len=*), intent(in) :: gridname
2826 : integer, intent(inout) :: dims(2)
2827 : integer, optional, intent(out) :: rank
2828 :
2829 : ! Local variables
2830 : integer :: gridind
2831 : character(len=max_hcoordname_len) :: dname1, dname2
2832 : character(len=120) :: errormsg
2833 :
2834 2304 : gridind = get_cam_grid_index(trim(gridname))
2835 2304 : if (gridind < 0) then
2836 0 : write(errormsg, *) 'No CAM grid with name = ', trim(gridname)
2837 0 : call endrun(errormsg)
2838 : else
2839 2304 : call cam_grids(gridind)%coord_lengths(dims)
2840 : end if
2841 2304 : if (present(rank)) then
2842 0 : call cam_grids(gridind)%dim_names(dname1, dname2)
2843 0 : if (trim(dname1) == trim(dname2)) then
2844 0 : rank = 1
2845 : else
2846 0 : rank = 2
2847 : end if
2848 : end if
2849 :
2850 2304 : end subroutine cam_grid_dimensions_name
2851 :
2852 : !---------------------------------------------------------------------------
2853 : !
2854 : ! cam_grid_set_map: Set a grid's distribution map
2855 : ! This maps the local grid elements to global file order
2856 : !
2857 : !---------------------------------------------------------------------------
2858 0 : subroutine cam_grid_set_map(this, map, src, dest)
2859 : use spmd_utils, only: mpi_sum, mpi_integer, mpicom
2860 : ! Dummy arguments
2861 : class(cam_grid_t) :: this
2862 : integer(iMap), pointer :: map(:,:)
2863 : integer, intent(in) :: src(2) ! decomp info
2864 : integer, intent(in) :: dest(2) ! Standard dim(s) in file
2865 :
2866 : ! Local variables
2867 : integer :: dims(2)
2868 : integer :: dstrt, dend
2869 : integer :: gridlen, gridloc, ierr
2870 :
2871 : ! Check to make sure the map meets our needs
2872 0 : call this%coord_lengths(dims)
2873 0 : dend = size(map, 1)
2874 : ! We always have to have one source and one destination
2875 0 : if (dest(2) > 0) then
2876 0 : dstrt = dend - 1
2877 : else
2878 : dstrt = dend
2879 : end if
2880 0 : if ((src(2) /= 0) .and. (dstrt < 3)) then
2881 0 : call endrun('cam_grid_set_map: src & dest too large for map')
2882 0 : else if (dstrt < 2) then
2883 0 : call endrun('cam_grid_set_map: dest too large for map')
2884 : ! No else needed
2885 : end if
2886 0 : if (dstrt == dend) then
2887 0 : gridloc = count(map(dend,:) /= 0)
2888 : else
2889 0 : gridloc = count((map(dstrt,:) /= 0) .and. (map(dend,:) /= 0))
2890 : end if
2891 0 : call MPI_Allreduce(gridloc, gridlen, 1, MPI_INTEGER, MPI_SUM, mpicom, ierr)
2892 0 : if (gridlen /= product(dims)) then
2893 0 : call endrun('cam_grid_set_map: Bad map size for '//trim(this%name))
2894 : else
2895 0 : if (.not. associated(this%map)) then
2896 0 : allocate(this%map)
2897 : end if
2898 0 : call this%map%init(map, this%unstructured, src, dest)
2899 : end if
2900 0 : end subroutine cam_grid_set_map
2901 :
2902 : !---------------------------------------------------------------------------
2903 : !
2904 : ! cam_grid_local_size: return the local size of a 2D array on this grid
2905 : !
2906 : !---------------------------------------------------------------------------
2907 0 : integer function cam_grid_local_size(this)
2908 :
2909 : ! Dummy argument
2910 : class(cam_grid_t) :: this
2911 :
2912 : ! Local variable
2913 : character(len=128) :: errormsg
2914 :
2915 0 : if (.not. associated(this%map)) then
2916 0 : write(errormsg, *) 'Grid, '//trim(this%name)//', has no map'
2917 0 : call endrun('cam_grid_local_size: '//trim(errormsg))
2918 : else
2919 0 : cam_grid_local_size = this%map%num_elem()
2920 : end if
2921 :
2922 0 : end function cam_grid_local_size
2923 :
2924 : !---------------------------------------------------------------------------
2925 : !
2926 : ! cam_grid_get_lon_lat: Find the latitude and longitude for a given
2927 : ! grid map index. Note if point is not mapped
2928 : !
2929 : !---------------------------------------------------------------------------
2930 0 : subroutine cam_grid_get_lon_lat(this, index, lon, lat, isMapped)
2931 :
2932 : ! Dummy arguments
2933 : class(cam_grid_t) :: this
2934 : integer, intent(in) :: index
2935 : real(r8), intent(out) :: lon
2936 : real(r8), intent(out) :: lat
2937 : logical, intent(out) :: isMapped
2938 :
2939 : ! Local variables
2940 : integer :: latindex, lonindex
2941 : character(len=*), parameter :: subname = "cam_grid_get_lon_lat"
2942 :
2943 0 : if (this%block_indexed) then
2944 0 : lonindex = index
2945 0 : latindex = index
2946 0 : isMapped = this%map%is_mapped(index)
2947 : else
2948 0 : call this%map%coord_vals(index, lonindex, latindex, isMapped)
2949 : end if
2950 :
2951 : !!XXgoldyXX: May be able to relax all the checks
2952 0 : if ( (latindex < LBOUND(this%lat_coord%values, 1)) .or. &
2953 : (latindex > UBOUND(this%lat_coord%values, 1))) then
2954 0 : call endrun(trim(subname)//": index out of range for latvals")
2955 : else
2956 0 : lat = this%lat_coord%values(latindex)
2957 : end if
2958 :
2959 0 : if ( (lonindex < LBOUND(this%lon_coord%values, 1)) .or. &
2960 : (lonindex > UBOUND(this%lon_coord%values, 1))) then
2961 0 : call endrun(trim(subname)//": index out of range for lonvals")
2962 : else
2963 0 : lon = this%lon_coord%values(lonindex)
2964 : end if
2965 :
2966 0 : end subroutine cam_grid_get_lon_lat
2967 :
2968 : !---------------------------------------------------------------------------
2969 : !
2970 : ! cam_grid_find_src_dims: Find the correct src array dims for this grid
2971 : !
2972 : !---------------------------------------------------------------------------
2973 121344 : subroutine cam_grid_find_src_dims(this, field_dnames, src_out)
2974 : ! Dummy arguments
2975 : class(cam_grid_t) :: this
2976 : character(len=*), intent(in) :: field_dnames(:)
2977 : integer, pointer :: src_out(:)
2978 :
2979 : ! Local variables
2980 : integer :: i, j
2981 : integer :: num_coords
2982 : character(len=max_hcoordname_len) :: coord_dimnames(2)
2983 :
2984 121344 : call this%dim_names(coord_dimnames(1), coord_dimnames(2))
2985 121344 : if (associated(src_out)) then
2986 0 : deallocate(src_out)
2987 : nullify(src_out)
2988 : end if
2989 121344 : if (trim(coord_dimnames(1)) == trim(coord_dimnames(2))) then
2990 : num_coords = 1
2991 : else
2992 0 : num_coords = 2
2993 : end if
2994 121344 : allocate(src_out(2)) ! Currently, all cases have two source dims
2995 242688 : do i = 1, num_coords
2996 485376 : do j = 1, size(field_dnames)
2997 364032 : if (trim(field_dnames(j)) == trim(coord_dimnames(i))) then
2998 121344 : src_out(i) = j
2999 : end if
3000 : end do
3001 : end do
3002 121344 : if (num_coords < 2) then
3003 121344 : src_out(2) = -1 ! Assume a block structure for unstructured grids
3004 : end if
3005 :
3006 121344 : end subroutine cam_grid_find_src_dims
3007 :
3008 : !---------------------------------------------------------------------------
3009 : !
3010 : ! cam_grid_find_dest_dims: Find the correct file array dims for this grid
3011 : !
3012 : !---------------------------------------------------------------------------
3013 121344 : subroutine cam_grid_find_dest_dims(this, file_dnames, dest_out)
3014 : ! Dummy arguments
3015 : class(cam_grid_t) :: this
3016 : character(len=*), intent(in) :: file_dnames(:)
3017 : integer, pointer :: dest_out(:)
3018 :
3019 : ! Local variables
3020 : integer :: i, j
3021 : integer :: num_coords
3022 : character(len=max_hcoordname_len) :: coord_dimnames(2)
3023 :
3024 121344 : call this%dim_names(coord_dimnames(1), coord_dimnames(2))
3025 121344 : if (associated(dest_out)) then
3026 0 : deallocate(dest_out)
3027 : nullify(dest_out)
3028 : end if
3029 121344 : if (trim(coord_dimnames(1)) == trim(coord_dimnames(2))) then
3030 : num_coords = 1
3031 : else
3032 0 : num_coords = 2
3033 : end if
3034 364032 : allocate(dest_out(num_coords))
3035 242688 : dest_out = 0
3036 242688 : do i = 1, num_coords
3037 485376 : do j = 1, size(file_dnames)
3038 364032 : if (trim(file_dnames(j)) == trim(coord_dimnames(i))) then
3039 121344 : dest_out(i) = j
3040 : end if
3041 : end do
3042 : end do
3043 :
3044 121344 : end subroutine cam_grid_find_dest_dims
3045 :
3046 : !---------------------------------------------------------------------------
3047 : !
3048 : ! cam_grid_get_pio_decomp: Find or create a PIO decomp on this grid
3049 : !
3050 : !---------------------------------------------------------------------------
3051 272640 : subroutine cam_grid_get_pio_decomp(this, field_lens, file_lens, dtype, &
3052 272640 : iodesc, field_dnames, file_dnames)
3053 : use pio, only: io_desc_t
3054 : use cam_pio_utils, only: cam_pio_get_decomp, calc_permutation
3055 :
3056 : ! Dummy arguments
3057 : class(cam_grid_t) :: this
3058 : integer, intent(in) :: field_lens(:)
3059 : integer, intent(in) :: file_lens(:)
3060 : integer, intent(in) :: dtype
3061 : type(io_desc_t), pointer, intent(out) :: iodesc
3062 : character(len=*), optional, intent(in) :: field_dnames(:)
3063 : character(len=*), optional, intent(in) :: file_dnames(:)
3064 :
3065 : ! Local variables
3066 272640 : integer, pointer :: src_in(:)
3067 272640 : integer, pointer :: dest_in(:)
3068 272640 : integer, allocatable :: permutation(:)
3069 : logical :: is_perm
3070 : character(len=128) :: errormsg
3071 :
3072 272640 : nullify(src_in)
3073 272640 : nullify(dest_in)
3074 272640 : is_perm = .false.
3075 272640 : if (.not. associated(this%map)) then
3076 0 : write(errormsg, *) 'Grid, '//trim(this%name)//', has no map'
3077 0 : call endrun('cam_grid_get_pio_decomp: '//trim(errormsg))
3078 : else
3079 272640 : if (present(field_dnames)) then
3080 121344 : call this%find_src_dims(field_dnames, src_in)
3081 : end if
3082 272640 : if (present(file_dnames)) then
3083 121344 : call this%find_dest_dims(file_dnames, dest_in)
3084 : end if
3085 272640 : if (present(file_dnames) .and. present(field_dnames)) then
3086 : ! This only works if the arrays are the same size
3087 121344 : if (size(file_dnames) == size(field_dnames)) then
3088 364032 : allocate(permutation(size(file_dnames)))
3089 121344 : call calc_permutation(file_dnames, field_dnames, permutation, is_perm)
3090 : end if
3091 : end if
3092 : ! Call cam_pio_get_decomp with the appropriate options
3093 272640 : if (present(field_dnames) .and. present(file_dnames)) then
3094 121344 : if (is_perm) then
3095 : call cam_pio_get_decomp(iodesc, field_lens, file_lens, dtype, &
3096 : this%map, field_dist_in=src_in, file_dist_in=dest_in, &
3097 0 : permute=permutation)
3098 : else
3099 : call cam_pio_get_decomp(iodesc, field_lens, file_lens, dtype, &
3100 121344 : this%map, field_dist_in=src_in, file_dist_in=dest_in)
3101 : end if
3102 151296 : else if (present(field_dnames)) then
3103 : call cam_pio_get_decomp(iodesc, field_lens, file_lens, dtype, &
3104 0 : this%map, field_dist_in=src_in)
3105 151296 : else if (present(file_dnames)) then
3106 : call cam_pio_get_decomp(iodesc, field_lens, file_lens, dtype, &
3107 0 : this%map, file_dist_in=dest_in)
3108 : else
3109 151296 : call cam_pio_get_decomp(iodesc, field_lens, file_lens, dtype, this%map)
3110 : end if
3111 : end if
3112 272640 : if (associated(src_in)) then
3113 121344 : deallocate(src_in)
3114 : nullify(src_in)
3115 : end if
3116 272640 : if (associated(dest_in)) then
3117 121344 : deallocate(dest_in)
3118 : nullify(dest_in)
3119 : end if
3120 272640 : if (allocated(permutation)) then
3121 121344 : deallocate(permutation)
3122 : end if
3123 :
3124 545280 : end subroutine cam_grid_get_pio_decomp
3125 :
3126 : !-------------------------------------------------------------------------------
3127 : !
3128 : ! cam_grid_find_dimids: Find the dimension NetCDF IDs on <File> for this grid
3129 : !
3130 : !-------------------------------------------------------------------------------
3131 1536 : subroutine cam_grid_find_dimids(this, File, dimids)
3132 272640 : use pio, only: file_desc_t, pio_noerr, pio_inq_dimid
3133 : use pio, only: pio_seterrorhandling, pio_bcast_error
3134 :
3135 : ! Dummy arguments
3136 : class(cam_grid_t) :: this
3137 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3138 : integer, intent(out) :: dimids(:)
3139 :
3140 : ! Local vaariables
3141 : integer :: ierr
3142 : integer :: err_handling
3143 : character(len=max_hcoordname_len) :: dimname1, dimname2
3144 :
3145 : ! We will handle errors for this routine
3146 1536 : call pio_seterrorhandling(File, PIO_BCAST_ERROR,err_handling)
3147 :
3148 1536 : call this%dim_names(dimname1, dimname2)
3149 1536 : if (size(dimids) < 1) then
3150 0 : call endrun('CAM_GRID_FIND_DIMIDS: dimids must have positive size')
3151 : end if
3152 6144 : dimids = -1
3153 : ! Check the first dimension
3154 1536 : ierr = pio_inq_dimid(File, trim(dimname1), dimids(1))
3155 1536 : if(ierr /= PIO_NOERR) then
3156 0 : call endrun('CAM_GRID_FIND_DIMIDS: '//trim(this%name)//' dimension, '//trim(dimname1)//', does not exist on file')
3157 : end if
3158 1536 : if (trim(dimname1) /= trim(dimname2)) then
3159 : ! Structured grid, find second dimid
3160 0 : if (size(dimids) < 2) then
3161 0 : call endrun('CAM_GRID_FIND_DIMIDS: dimids too small for '//trim(this%name))
3162 : end if
3163 0 : ierr = pio_inq_dimid(File, trim(dimname2), dimids(2))
3164 0 : if(ierr /= PIO_NOERR) then
3165 0 : call endrun('CAM_GRID_FIND_DIMIDS: '//trim(this%name)//' dimension, '//trim(dimname2)//', does not exist on file')
3166 : end if
3167 : end if
3168 :
3169 : ! Back to whatever error handling was running before this routine
3170 1536 : call pio_seterrorhandling(File, err_handling)
3171 :
3172 1536 : end subroutine cam_grid_find_dimids
3173 :
3174 : !---------------------------------------------------------------------------
3175 : !
3176 : ! cam_grid_read_darray_2d_int: Read a variable defined on this grid
3177 : !
3178 : !---------------------------------------------------------------------------
3179 768 : subroutine cam_grid_read_darray_2d_int(this, File, adims, fdims, hbuf, varid)
3180 : use pio, only: file_desc_t, io_desc_t, pio_read_darray, PIO_INT
3181 : use cam_pio_utils, only: cam_pio_get_decomp
3182 :
3183 : ! Dummy arguments
3184 : class(cam_grid_t) :: this
3185 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3186 : integer, intent(in) :: adims(:)
3187 : integer, intent(in) :: fdims(:)
3188 : integer, intent(out) :: hbuf(:,:)
3189 : type(var_desc_t), intent(inout) :: varid
3190 :
3191 : ! Local variables
3192 : type(io_desc_t), pointer :: iodesc
3193 : integer :: ierr
3194 :
3195 768 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_INT, this%map)
3196 768 : call pio_read_darray(File, varid, iodesc, hbuf, ierr)
3197 768 : call cam_pio_handle_error(ierr, 'cam_grid_read_darray_2d_int: Error reading variable')
3198 768 : end subroutine cam_grid_read_darray_2d_int
3199 :
3200 : !---------------------------------------------------------------------------
3201 : !
3202 : ! cam_grid_read_darray_3d_int: Read a variable defined on this grid
3203 : !
3204 : !---------------------------------------------------------------------------
3205 0 : subroutine cam_grid_read_darray_3d_int(this, File, adims, fdims, hbuf, varid)
3206 768 : use pio, only: file_desc_t, io_desc_t, pio_read_darray, PIO_INT
3207 : use cam_pio_utils, only: cam_pio_get_decomp
3208 :
3209 : ! Dummy arguments
3210 : class(cam_grid_t) :: this
3211 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3212 : integer, intent(in) :: adims(:)
3213 : integer, intent(in) :: fdims(:)
3214 : integer, intent(out) :: hbuf(:,:,:)
3215 : type(var_desc_t), intent(inout) :: varid
3216 :
3217 : ! Local variables
3218 : type(io_desc_t), pointer :: iodesc
3219 : integer :: ierr
3220 :
3221 0 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_INT, this%map)
3222 0 : call pio_read_darray(File, varid, iodesc, hbuf, ierr)
3223 0 : call cam_pio_handle_error(ierr, 'cam_grid_read_darray_3d_int: Error reading variable')
3224 0 : end subroutine cam_grid_read_darray_3d_int
3225 :
3226 : !---------------------------------------------------------------------------
3227 : !
3228 : ! cam_grid_read_darray_2d_double: Read a variable defined on this grid
3229 : !
3230 : !---------------------------------------------------------------------------
3231 19968 : subroutine cam_grid_read_darray_2d_double(this, File, adims, fdims, hbuf, varid)
3232 0 : use pio, only: file_desc_t, io_desc_t, pio_read_darray
3233 : use pio, only: PIO_DOUBLE
3234 : use cam_pio_utils, only: cam_pio_get_decomp
3235 :
3236 : ! Dummy arguments
3237 : class(cam_grid_t) :: this
3238 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3239 : integer, intent(in) :: adims(:)
3240 : integer, intent(in) :: fdims(:)
3241 : real(r8), intent(out) :: hbuf(:,:)
3242 : type(var_desc_t), intent(inout) :: varid
3243 :
3244 : ! Local variables
3245 : type(io_desc_t), pointer :: iodesc
3246 : integer :: ierr
3247 :
3248 19968 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_DOUBLE, this%map)
3249 19968 : call pio_read_darray(File, varid, iodesc, hbuf, ierr)
3250 19968 : call cam_pio_handle_error(ierr, 'cam_grid_read_darray_2d_double: Error reading variable')
3251 19968 : end subroutine cam_grid_read_darray_2d_double
3252 :
3253 : !---------------------------------------------------------------------------
3254 : !
3255 : ! cam_grid_read_darray_3d_double: Read a variable defined on this grid
3256 : !
3257 : !---------------------------------------------------------------------------
3258 83712 : subroutine cam_grid_read_darray_3d_double(this, File, adims, fdims, hbuf, varid)
3259 19968 : use pio, only: file_desc_t, io_desc_t, pio_read_darray
3260 : use pio, only: PIO_DOUBLE
3261 : use cam_pio_utils, only: cam_pio_get_decomp
3262 :
3263 : ! Dummy arguments
3264 : class(cam_grid_t) :: this
3265 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3266 : integer, intent(in) :: adims(:)
3267 : integer, intent(in) :: fdims(:)
3268 : real(r8), intent(out) :: hbuf(:,:,:)
3269 : type(var_desc_t), intent(inout) :: varid
3270 :
3271 : ! Local variables
3272 : type(io_desc_t), pointer :: iodesc
3273 : integer :: ierr
3274 :
3275 83712 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_DOUBLE, this%map)
3276 83712 : call pio_read_darray(File, varid, iodesc, hbuf, ierr)
3277 83712 : call cam_pio_handle_error(ierr, 'cam_grid_read_darray_3d_double: Error reading variable')
3278 83712 : end subroutine cam_grid_read_darray_3d_double
3279 :
3280 : !---------------------------------------------------------------------------
3281 : !
3282 : ! cam_grid_read_darray_2d_real: Read a variable defined on this grid
3283 : !
3284 : !---------------------------------------------------------------------------
3285 0 : subroutine cam_grid_read_darray_2d_real(this, File, adims, fdims, hbuf, varid)
3286 83712 : use pio, only: file_desc_t, io_desc_t, pio_read_darray
3287 : use pio, only: PIO_REAL
3288 : use cam_pio_utils, only: cam_pio_get_decomp
3289 :
3290 : ! Dummy arguments
3291 : class(cam_grid_t) :: this
3292 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3293 : integer, intent(in) :: adims(:)
3294 : integer, intent(in) :: fdims(:)
3295 : real(r4), intent(out) :: hbuf(:,:)
3296 : type(var_desc_t), intent(inout) :: varid
3297 :
3298 : ! Local variables
3299 : type(io_desc_t), pointer :: iodesc
3300 : integer :: ierr
3301 :
3302 0 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_REAL, this%map)
3303 0 : call pio_read_darray(File, varid, iodesc, hbuf, ierr)
3304 0 : call cam_pio_handle_error(ierr, 'cam_grid_read_darray_2d_real: Error reading variable')
3305 0 : end subroutine cam_grid_read_darray_2d_real
3306 :
3307 : !---------------------------------------------------------------------------
3308 : !
3309 : ! cam_grid_read_darray_3d_real: Read a variable defined on this grid
3310 : !
3311 : !---------------------------------------------------------------------------
3312 0 : subroutine cam_grid_read_darray_3d_real(this, File, adims, fdims, hbuf, varid)
3313 0 : use pio, only: file_desc_t, io_desc_t, pio_read_darray
3314 : use pio, only: PIO_REAL
3315 : use cam_pio_utils, only: cam_pio_get_decomp
3316 :
3317 : ! Dummy arguments
3318 : class(cam_grid_t) :: this
3319 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3320 : integer, intent(in) :: adims(:)
3321 : integer, intent(in) :: fdims(:)
3322 : real(r4), intent(out) :: hbuf(:,:,:)
3323 : type(var_desc_t), intent(inout) :: varid
3324 :
3325 : ! Local variables
3326 : type(io_desc_t), pointer :: iodesc
3327 : integer :: ierr
3328 :
3329 0 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_REAL, this%map)
3330 0 : call pio_read_darray(File, varid, iodesc, hbuf, ierr)
3331 0 : call cam_pio_handle_error(ierr, 'cam_grid_read_darray_2d_: Error reading variable')
3332 0 : end subroutine cam_grid_read_darray_3d_real
3333 :
3334 : !---------------------------------------------------------------------------
3335 : !
3336 : ! cam_grid_write_darray_2d_int: Write a variable defined on this grid
3337 : !
3338 : !---------------------------------------------------------------------------
3339 1536 : subroutine cam_grid_write_darray_2d_int(this, File, adims, fdims, hbuf, varid)
3340 0 : use pio, only: file_desc_t, io_desc_t
3341 : use pio, only: pio_write_darray, PIO_INT
3342 :
3343 : use cam_pio_utils, only: cam_pio_get_decomp
3344 :
3345 : ! Dummy arguments
3346 : class(cam_grid_t) :: this
3347 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3348 : integer, intent(in) :: adims(:)
3349 : integer, intent(in) :: fdims(:)
3350 : integer, intent(in) :: hbuf(:,:)
3351 : type(var_desc_t), intent(inout) :: varid
3352 :
3353 : ! Local variables
3354 : type(io_desc_t), pointer :: iodesc
3355 : integer :: ierr
3356 :
3357 1536 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_INT, this%map)
3358 1536 : call pio_write_darray(File, varid, iodesc, hbuf, ierr)
3359 1536 : call cam_pio_handle_error(ierr, 'cam_grid_write_darray_2d_int: Error writing variable')
3360 1536 : end subroutine cam_grid_write_darray_2d_int
3361 :
3362 : !---------------------------------------------------------------------------
3363 : !
3364 : ! cam_grid_write_darray_3d_int: Write a variable defined on this grid
3365 : !
3366 : !---------------------------------------------------------------------------
3367 0 : subroutine cam_grid_write_darray_3d_int(this, File, adims, fdims, hbuf, varid)
3368 1536 : use pio, only: file_desc_t, io_desc_t
3369 : use pio, only: pio_write_darray, PIO_INT
3370 : use cam_pio_utils, only: cam_pio_get_decomp
3371 :
3372 : ! Dummy arguments
3373 : class(cam_grid_t) :: this
3374 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3375 : integer, intent(in) :: adims(:)
3376 : integer, intent(in) :: fdims(:)
3377 : integer, intent(in) :: hbuf(:,:,:)
3378 : type(var_desc_t), intent(inout) :: varid
3379 :
3380 : ! Local variables
3381 : type(io_desc_t), pointer :: iodesc
3382 : integer :: ierr
3383 :
3384 0 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_INT, this%map)
3385 0 : call pio_write_darray(File, varid, iodesc, hbuf, ierr)
3386 0 : call cam_pio_handle_error(ierr, 'cam_grid_write_darray_3d_int: Error writing variable')
3387 0 : end subroutine cam_grid_write_darray_3d_int
3388 :
3389 : !---------------------------------------------------------------------------
3390 : !
3391 : ! cam_grid_write_darray_2d_double: Write a variable defined on this grid
3392 : !
3393 : !---------------------------------------------------------------------------
3394 39936 : subroutine cam_grid_write_darray_2d_double(this, File, adims, fdims, hbuf, varid)
3395 0 : use pio, only: file_desc_t, io_desc_t
3396 : use pio, only: pio_write_darray, PIO_DOUBLE
3397 : use cam_pio_utils, only: cam_pio_get_decomp
3398 :
3399 : ! Dummy arguments
3400 : class(cam_grid_t) :: this
3401 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3402 : integer, intent(in) :: adims(:)
3403 : integer, intent(in) :: fdims(:)
3404 : real(r8), intent(in) :: hbuf(:,:)
3405 : type(var_desc_t), intent(inout) :: varid
3406 :
3407 : ! Local variables
3408 : type(io_desc_t), pointer :: iodesc
3409 : integer :: ierr
3410 :
3411 39936 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_DOUBLE, this%map)
3412 39936 : call pio_write_darray(File, varid, iodesc, hbuf, ierr)
3413 39936 : call cam_pio_handle_error(ierr, 'cam_grid_write_darray_2d_double: Error writing variable')
3414 39936 : end subroutine cam_grid_write_darray_2d_double
3415 :
3416 : !---------------------------------------------------------------------------
3417 : !
3418 : ! cam_grid_write_darray_3d_double: Write a variable defined on this grid
3419 : !
3420 : !---------------------------------------------------------------------------
3421 167424 : subroutine cam_grid_write_darray_3d_double(this, File, adims, fdims, hbuf, varid)
3422 39936 : use pio, only: file_desc_t, io_desc_t
3423 : use pio, only: pio_write_darray, PIO_DOUBLE
3424 : use cam_pio_utils, only: cam_pio_get_decomp
3425 :
3426 : ! Dummy arguments
3427 : class(cam_grid_t) :: this
3428 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3429 : integer, intent(in) :: adims(:)
3430 : integer, intent(in) :: fdims(:)
3431 : real(r8), intent(in) :: hbuf(:,:,:)
3432 : type(var_desc_t), intent(inout) :: varid
3433 :
3434 : ! Local variables
3435 : type(io_desc_t), pointer :: iodesc
3436 : integer :: ierr
3437 :
3438 167424 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_DOUBLE, this%map)
3439 167424 : call pio_write_darray(File, varid, iodesc, hbuf, ierr)
3440 167424 : call cam_pio_handle_error(ierr, 'cam_grid_write_darray_3d_double: Error writing variable')
3441 :
3442 167424 : end subroutine cam_grid_write_darray_3d_double
3443 :
3444 : !---------------------------------------------------------------------------
3445 : !
3446 : ! cam_grid_write_darray_2d_real: Write a variable defined on this grid
3447 : !
3448 : !---------------------------------------------------------------------------
3449 1211904 : subroutine cam_grid_write_darray_2d_real(this, File, adims, fdims, hbuf, varid)
3450 167424 : use pio, only: file_desc_t, io_desc_t
3451 : use pio, only: pio_write_darray, PIO_REAL
3452 : use cam_pio_utils, only: cam_pio_get_decomp
3453 :
3454 : ! Dummy arguments
3455 : class(cam_grid_t) :: this
3456 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3457 : integer, intent(in) :: adims(:)
3458 : integer, intent(in) :: fdims(:)
3459 : real(r4), intent(in) :: hbuf(:,:)
3460 : type(var_desc_t), intent(inout) :: varid
3461 :
3462 : ! Local variables
3463 : type(io_desc_t), pointer :: iodesc
3464 : integer :: ierr
3465 :
3466 1211904 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_REAL, this%map)
3467 1211904 : call pio_write_darray(File, varid, iodesc, hbuf, ierr)
3468 1211904 : call cam_pio_handle_error(ierr, 'cam_grid_write_darray_2d_real: Error writing variable')
3469 1211904 : end subroutine cam_grid_write_darray_2d_real
3470 :
3471 : !---------------------------------------------------------------------------
3472 : !
3473 : ! cam_grid_write_darray_3d_real: Write a variable defined on this grid
3474 : !
3475 : !---------------------------------------------------------------------------
3476 695808 : subroutine cam_grid_write_darray_3d_real(this, File, adims, fdims, hbuf, varid)
3477 1211904 : use pio, only: file_desc_t, io_desc_t
3478 : use pio, only: pio_write_darray, PIO_REAL
3479 : use cam_pio_utils, only: cam_pio_get_decomp
3480 :
3481 : ! Dummy arguments
3482 : class(cam_grid_t) :: this
3483 : type(file_desc_t), intent(inout) :: File ! PIO file handle
3484 : integer, intent(in) :: adims(:)
3485 : integer, intent(in) :: fdims(:)
3486 : real(r4), intent(in) :: hbuf(:,:,:)
3487 : type(var_desc_t), intent(inout) :: varid
3488 :
3489 : ! Local variables
3490 : type(io_desc_t), pointer :: iodesc
3491 : integer :: ierr
3492 :
3493 695808 : nullify(iodesc)
3494 695808 : call cam_pio_get_decomp(iodesc, adims, fdims, PIO_REAL, this%map)
3495 695808 : call pio_write_darray(File, varid, iodesc, hbuf, ierr)
3496 695808 : call cam_pio_handle_error(ierr, 'cam_grid_write_darray_3d_real: Error writing variable')
3497 695808 : end subroutine cam_grid_write_darray_3d_real
3498 :
3499 : !---------------------------------------------------------------------------
3500 : !
3501 : ! cam_grid_get_patch_mask: Compute a map which is defined for locations
3502 : ! within the input patch.
3503 : !
3504 : !---------------------------------------------------------------------------
3505 0 : subroutine cam_grid_get_patch_mask(this, lonl, lonu, latl, latu, patch, cco)
3506 695808 : use spmd_utils, only: mpi_min, mpi_max, mpi_real8, mpicom
3507 : use physconst, only: pi
3508 :
3509 : ! Dummy arguments
3510 : class(cam_grid_t) :: this
3511 : real(r8), intent(in) :: lonl, lonu ! Longitude bounds
3512 : real(r8), intent(in) :: latl, latu ! Latitude bounds
3513 : type(cam_grid_patch_t), intent(inout) :: patch
3514 : logical, intent(in) :: cco ! Collect columns?
3515 :
3516 : ! Local arguments
3517 : real(r8) :: mindist, minlondist
3518 : real(r8) :: dist, temp1, temp2 ! Test distance calc
3519 : real(r8) :: londeg, latdeg
3520 : real(r8) :: lon, lat
3521 : real(r8) :: londeg_min, latdeg_min
3522 : real(r8) :: lonmin, lonmax, latmin, latmax
3523 : integer :: minind ! Location of closest point
3524 : integer :: mapind ! Grid map index
3525 : integer :: latind, lonind
3526 : integer :: ierr ! For MPI calls
3527 : integer :: dims(2) ! Global dim sizes
3528 : integer :: gridloc ! local size of grid
3529 : logical :: unstructured ! grid type
3530 : logical :: findClosest ! .false. == patch output
3531 : logical :: isMapped ! .true. iff point in map
3532 :
3533 : real(r8), parameter :: maxangle = pi / 4.0_r8
3534 : real(r8), parameter :: deg2rad = pi / 180.0_r8
3535 : real(r8), parameter :: maxtol = 0.99999_r8 ! max cos value
3536 : real(r8), parameter :: maxlat = pi * maxtol / 2.0_r8
3537 : character(len=*), parameter :: subname = 'cam_grid_get_patch_mask'
3538 :
3539 0 : if (.not. associated(this%map)) then
3540 0 : call endrun('cam_grid_get_patch_mask: Grid, '//trim(this%name)//', has no map')
3541 : end if
3542 0 : gridloc = this%map%num_elem()
3543 0 : unstructured = this%is_unstructured()
3544 0 : call this%coord_lengths(dims)
3545 0 : if (associated(patch%mask)) then
3546 0 : if (patch%mask%num_elem() /= gridloc) then
3547 : ! The mask needs to be the same size as the map
3548 0 : call endrun(subname//': mask is incorrect size')
3549 : ! No else, just needed a check
3550 : ! In particular, we are not zeroing the mask since multiple calls with
3551 : ! the same mask can be used for collected-column output
3552 : ! NB: Compacting the mask must be done after all calls (for a
3553 : ! particular mask) to this function.
3554 : end if
3555 0 : if (patch%collected_columns .neqv. cco) then
3556 0 : call endrun(subname//': collected_column mismatch')
3557 : end if
3558 : else
3559 0 : if (associated(patch%latmap)) then
3560 0 : call endrun(subname//': unallocated patch has latmap')
3561 : end if
3562 0 : if (associated(patch%lonmap)) then
3563 0 : call endrun(subname//': unallocated patch has lonmap')
3564 : end if
3565 0 : call patch%set_patch(lonl, lonu, latl, latu, cco, this%id, this%map)
3566 0 : if (patch%mask%num_elem() /= gridloc) then
3567 : ! Basic check to make sure the copy worked
3568 0 : call endrun(subname//': grid map is invalid')
3569 : end if
3570 0 : call patch%mask%clear()
3571 : ! Set up the lat/lon maps
3572 0 : if (cco) then
3573 : ! For collected column output, we need to collect coordinates and values
3574 0 : allocate(patch%latmap(patch%mask%num_elem()))
3575 0 : patch%latmap = 0
3576 0 : allocate(patch%latvals(patch%mask%num_elem()))
3577 0 : patch%latvals = 91.0_r8
3578 0 : allocate(patch%lonmap(patch%mask%num_elem()))
3579 0 : patch%lonmap = 0
3580 0 : allocate(patch%lonvals(patch%mask%num_elem()))
3581 0 : patch%lonvals = 361.0_r8
3582 : else
3583 0 : if (associated(this%lat_coord%values)) then
3584 0 : allocate(patch%latmap(LBOUND(this%lat_coord%values, 1):UBOUND(this%lat_coord%values, 1)))
3585 0 : patch%latmap = 0
3586 : else
3587 0 : nullify(patch%latmap)
3588 : end if
3589 0 : if (associated(this%lon_coord%values)) then
3590 0 : allocate(patch%lonmap(LBOUND(this%lon_coord%values, 1):UBOUND(this%lon_coord%values, 1)))
3591 0 : patch%lonmap = 0
3592 : else
3593 0 : nullify(patch%lonmap)
3594 : end if
3595 : end if
3596 : end if
3597 :
3598 : ! We have to iterate through each grid point to check
3599 : ! We have four cases, structured vs. unstructured grid *
3600 : ! patch area vs. closest column
3601 : ! Note that a 1-d patch 'area' is not allowed for unstructured grids
3602 0 : findClosest = .false.
3603 : ! Make sure our search items are in order
3604 0 : lonmin = min(lonl, lonu)
3605 0 : lonmax = max(lonl, lonu)
3606 0 : latmin = min(latl, latu)
3607 0 : latmax = max(latl, latu)
3608 0 : if (lonl == lonu) then
3609 0 : if (latl == latu) then
3610 : findClosest = .true.
3611 0 : else if (unstructured) then
3612 0 : call endrun(subname//': 1-D patch (lon) not allowed for unstructured grids')
3613 : else
3614 : ! Find closest lon line to lonu
3615 : ! This is a lat lon grid so it should have coordinate axes
3616 0 : lonmin = 365.0_r8
3617 0 : mindist = 365.0_r8
3618 0 : if (associated(this%lon_coord%values)) then
3619 0 : do lonind = LBOUND(this%lon_coord%values, 1), UBOUND(this%lon_coord%values, 1)
3620 0 : dist = abs(this%lon_coord%values(lonind) - lonu)
3621 0 : if (dist < mindist) then
3622 0 : lonmin = this%lon_coord%values(lonind)
3623 0 : mindist = dist
3624 : end if
3625 : end do
3626 : end if
3627 : ! Get the global minimum
3628 0 : dist = mindist
3629 0 : call MPI_allreduce(dist, mindist, 1, mpi_real8, mpi_min, mpicom, ierr)
3630 0 : if (dist == mindist) then
3631 : ! We have a ringer so use only that longitude
3632 : lonmax = lonmin
3633 : else
3634 : ! We don't have a minimum dist so count no points
3635 0 : lonmax = lonmin - 1.0_r8
3636 : end if
3637 : end if
3638 0 : else if (latl == latu) then
3639 0 : if (unstructured) then
3640 0 : call endrun(subname//': 1-D patch (lat) not allowed for unstructured grids')
3641 : else
3642 : ! Find closest lat line to latu
3643 : ! This is a lat lon grid so it should have coordinate axes
3644 0 : latmin = 91.0_r8
3645 0 : mindist = 181.0_r8
3646 0 : if (associated(this%lat_coord%values)) then
3647 0 : do latind = LBOUND(this%lat_coord%values, 1), UBOUND(this%lat_coord%values, 1)
3648 0 : dist = abs(this%lat_coord%values(latind) - latl)
3649 0 : if (dist < mindist) then
3650 0 : latmin = this%lat_coord%values(latind)
3651 0 : mindist = dist
3652 : end if
3653 : end do
3654 : end if
3655 : ! Get the global minimum
3656 0 : dist = mindist
3657 0 : call MPI_allreduce(dist, mindist, 1, mpi_real8, mpi_min, mpicom, ierr)
3658 0 : if (dist == mindist) then
3659 : ! We have a ringer so use only that latitude
3660 : latmax = latmin
3661 : else
3662 : ! We don't have a minimum dist so count no points
3663 0 : latmax = latmin - 1.0_r8
3664 : end if
3665 : end if
3666 : end if
3667 :
3668 : ! Convert to radians
3669 0 : lonmin = lonmin * deg2rad
3670 0 : lonmax = lonmax * deg2rad
3671 0 : latmin = latmin * deg2rad
3672 0 : latmax = latmax * deg2rad
3673 : ! Loop through all the local grid elements and find the closest match
3674 : ! (or all matches depending on the value of findClosest)
3675 0 : minind = -1
3676 0 : londeg_min = 361.0_r8
3677 0 : latdeg_min = 91.0_r8
3678 0 : mindist = 2.0_r8 * pi
3679 :
3680 0 : do mapind = 1, patch%mask%num_elem()
3681 0 : call this%get_lon_lat(mapind, londeg, latdeg, isMapped)
3682 0 : if (isMapped) then
3683 0 : lon = londeg * deg2rad
3684 0 : lat = latdeg * deg2rad
3685 0 : if (findClosest) then
3686 : ! Use the Spherical Law of Cosines to find the great-circle distance.
3687 : ! Might as well use the unit sphere since we just want differences
3688 0 : if ( (abs(lat - latmin) <= maxangle) .and. &
3689 : (abs(lon - lonmin) <= maxangle)) then
3690 : ! maxangle could be pi but why waste all those trig functions?
3691 0 : if ((lat == latmin) .and. (lon == lonmin)) then
3692 0 : dist = 0.0_r8
3693 : else
3694 : temp1 = (sin(latmin) * sin(lat)) + &
3695 0 : (cos(latmin) * cos(lat) * cos(lon - lonmin))
3696 0 : if (temp1 > maxtol) then
3697 : ! Use haversine formula
3698 0 : temp1 = sin(latmin - lat)
3699 0 : temp2 = sin((lonmin - lon) / 2.0_r8)
3700 0 : dist = 2.0_r8 * asin((temp1*temp1) + (cos(latmin)*cos(lat)*temp2*temp2))
3701 : else
3702 0 : dist = acos(temp1)
3703 : end if
3704 : end if
3705 0 : if ( (dist < mindist) .or. &
3706 : ((dist == mindist) .and. &
3707 : (abs(lon - lonmin) < abs(londeg_min*deg2rad - lonmin)))) then
3708 0 : minind = mapind
3709 0 : mindist = dist
3710 0 : londeg_min = londeg
3711 0 : latdeg_min = latdeg
3712 : end if
3713 : end if
3714 : else
3715 : if ( (latmin <= lat) .and. (lat <= latmax) .and. &
3716 0 : (lonmin <= lon) .and. (lon <= lonmax)) then
3717 0 : if (patch%mask%num_elem() >= mapind) then
3718 0 : if (.not. patch%mask%is_mapped(mapind)) then
3719 0 : call patch%mask%copy_elem(this%map, mapind)
3720 0 : patch%num_points = patch%num_points + 1
3721 0 : if (cco) then
3722 0 : if (patch%num_points > size(patch%latvals, 1)) then
3723 0 : call endrun(subname//': Number of cols larger than mask!?')
3724 : end if
3725 0 : call this%map%coord_dests(mapind, lonind, latind)
3726 0 : if (latind > 0) then
3727 : ! Grid is structured, get unique index
3728 0 : lonind = lonind + (latind * dims(1))
3729 : end if
3730 0 : patch%latmap(patch%num_points) = lonind
3731 0 : patch%latvals(patch%num_points) = latdeg
3732 0 : patch%lonmap(patch%num_points) = lonind
3733 0 : patch%lonvals(patch%num_points) = londeg
3734 0 : else if ((this%block_indexed) .or. unstructured) then
3735 0 : call this%map%coord_dests(mapind, lonind, latind)
3736 0 : if (latind == 0) then
3737 0 : latind = lonind
3738 : end if
3739 0 : if (associated(patch%latmap)) then
3740 0 : patch%latmap(mapind) = latind
3741 : end if
3742 0 : if (associated(patch%lonmap)) then
3743 0 : patch%lonmap(mapind) = lonind
3744 : end if
3745 : else
3746 0 : call this%map%coord_vals(mapind, lonind, latind)
3747 0 : if (associated(patch%latmap)) then
3748 0 : patch%latmap(latind) = latind
3749 : end if
3750 0 : if (associated(patch%lonmap)) then
3751 0 : patch%lonmap(lonind) = lonind
3752 : end if
3753 : end if
3754 : ! else do nothing, we already found this point
3755 : end if
3756 : else
3757 0 : call endrun(subname//': PE has patch points but mask too small')
3758 : end if
3759 : end if
3760 : end if ! findClosest
3761 : end if ! isMapped
3762 : end do
3763 0 : if (findClosest) then
3764 : ! We need to find the minimum mindist and use only that value
3765 0 : dist = mindist
3766 0 : call MPI_allreduce(dist, mindist, 1, mpi_real8, mpi_min, mpicom, ierr)
3767 : ! Special case for pole points
3768 0 : if (latdeg_min > 90.0_r8) then
3769 0 : temp1 = 0.0_r8
3770 : else
3771 0 : temp1 = abs(latdeg_min*deg2rad)
3772 : end if
3773 0 : call MPI_allreduce(temp1, lat, 1, mpi_real8, mpi_max, mpicom, ierr)
3774 0 : if ((abs(latmin) > maxlat) .or. (lat > maxlat)) then
3775 0 : if (dist == mindist) then
3776 : ! Only distance winners can compete
3777 0 : lon = abs(londeg_min - lonl)
3778 : else
3779 0 : lon = 361.0_r8
3780 : end if
3781 0 : call MPI_allreduce(lon, minlondist, 1, mpi_real8, mpi_min, mpicom, ierr)
3782 : ! Kill the losers
3783 0 : if (lon /= minlondist) then
3784 0 : dist = dist + 1.0_r8
3785 : end if
3786 : end if
3787 : ! Now, only task(s) which have real minimum distance should set their mask
3788 : ! minind test allows for no match
3789 0 : if (dist == mindist) then
3790 0 : if (minind < 0) then
3791 0 : call endrun("cam_grid_get_patch_mask: No closest point found!!")
3792 : else
3793 0 : if (patch%mask%num_elem() >= minind) then
3794 0 : if (.not. patch%mask%is_mapped(minind)) then
3795 0 : call patch%mask%copy_elem(this%map, minind)
3796 0 : patch%num_points = patch%num_points + 1
3797 0 : if (cco) then
3798 0 : if (patch%num_points > size(patch%latvals, 1)) then
3799 0 : call endrun(subname//': Number of columns larger than mask!?')
3800 : end if
3801 0 : call this%map%coord_dests(minind, lonind, latind)
3802 0 : if (latind > 0) then
3803 : ! Grid is structured, get unique index
3804 0 : lonind = lonind + (latind * dims(1))
3805 : end if
3806 0 : patch%latmap(patch%num_points) = lonind
3807 0 : patch%latvals(patch%num_points) = latdeg_min
3808 0 : patch%lonmap(patch%num_points) = lonind
3809 0 : patch%lonvals(patch%num_points) = londeg_min
3810 0 : else if ((this%block_indexed) .or. unstructured) then
3811 0 : call this%map%coord_dests(minind, lonind, latind)
3812 0 : if (latind == 0) then
3813 0 : latind = lonind
3814 : end if
3815 0 : if (associated(patch%latmap)) then
3816 0 : patch%latmap(minind) = latind
3817 : end if
3818 0 : if (associated(patch%lonmap)) then
3819 0 : patch%lonmap(minind) = lonind
3820 : end if
3821 : else
3822 0 : call this%map%coord_vals(minind, lonind, latind)
3823 0 : if (associated(patch%latmap)) then
3824 0 : patch%latmap(latind) = latind
3825 : end if
3826 0 : if (associated(patch%lonmap)) then
3827 0 : patch%lonmap(lonind) = lonind
3828 : end if
3829 : end if
3830 : ! else do nothing, we already found this point
3831 : end if
3832 : else
3833 0 : call endrun(subname//': PE has patch closest point but mask too small')
3834 : end if
3835 : end if
3836 : end if
3837 : end if ! findClosest
3838 :
3839 0 : end subroutine cam_grid_get_patch_mask
3840 :
3841 : !---------------------------------------------------------------------------
3842 : !
3843 : ! Grid Patch functions
3844 : !
3845 : !---------------------------------------------------------------------------
3846 :
3847 0 : integer function cam_grid_patch_get_id(this) result(id)
3848 :
3849 : ! Dummy argument
3850 : class(cam_grid_patch_t) :: this
3851 :
3852 0 : id = this%grid_id
3853 0 : end function cam_grid_patch_get_id
3854 :
3855 0 : subroutine cam_grid_patch_get_global_size_map(this, gsize)
3856 :
3857 : ! Dummy arguments
3858 : class(cam_grid_patch_t), intent(in) :: this
3859 : integer, intent(out) :: gsize
3860 :
3861 0 : gsize = this%global_size
3862 :
3863 0 : end subroutine cam_grid_patch_get_global_size_map
3864 :
3865 0 : subroutine cam_grid_patch_get_global_size_axes(this, latsize, lonsize)
3866 :
3867 : ! Dummy arguments
3868 : class(cam_grid_patch_t), intent(in) :: this
3869 : integer, intent(out) :: latsize
3870 : integer, intent(out) :: lonsize
3871 :
3872 0 : latsize = this%global_lat_size
3873 0 : lonsize = this%global_lon_size
3874 :
3875 0 : end subroutine cam_grid_patch_get_global_size_axes
3876 :
3877 : ! cam_grid_patch_get_axis_names
3878 : ! Collect or compute unique names for the latitude and longitude axes
3879 : ! If the grid is unstructured or col_output is .true., the column
3880 : ! dimension name is also generated (e.g., ncol)
3881 0 : subroutine cam_grid_patch_get_axis_names(this, lat_name, lon_name, &
3882 : col_name, col_output)
3883 :
3884 : ! Dummy arguments
3885 : class(cam_grid_patch_t) :: this
3886 : character(len=*), intent(out) :: lat_name
3887 : character(len=*), intent(out) :: lon_name
3888 : character(len=*), intent(out) :: col_name
3889 : logical, intent(in) :: col_output
3890 :
3891 : ! Local variable
3892 : integer :: index
3893 : character(len=120) :: errormsg
3894 : character(len=max_hcoordname_len) :: grid_name
3895 : logical :: unstruct
3896 :
3897 0 : if (cam_grid_check(this%grid_id)) then
3898 0 : index = this%grid_index()
3899 0 : unstruct = cam_grids(index)%is_unstructured()
3900 : ! Get coordinate and dim names
3901 0 : call cam_grids(index)%lat_coord%get_coord_name(lat_name)
3902 0 : call cam_grids(index)%lon_coord%get_coord_name(lon_name)
3903 0 : grid_name = cam_grids(index)%name
3904 0 : if (col_output .or. unstruct) then
3905 : ! In this case, we are using collect_column_output on a lat/lon grid
3906 0 : col_name = 'ncol_'//trim(grid_name)
3907 0 : lat_name = trim(lat_name)//'_'//trim(grid_name)
3908 0 : lon_name = trim(lon_name)//'_'//trim(grid_name)
3909 : else
3910 : ! Separate patch output for a lat/lon grid
3911 0 : col_name = ''
3912 0 : lat_name = trim(lat_name)//'_'//trim(grid_name)
3913 0 : lon_name = trim(lon_name)//'_'//trim(grid_name)
3914 : end if
3915 : else
3916 0 : write(errormsg, *) 'Bad grid ID:', this%grid_id
3917 0 : call endrun('cam_grid_patch_get_axis_names: '//errormsg)
3918 : end if
3919 :
3920 0 : end subroutine cam_grid_patch_get_axis_names
3921 :
3922 0 : subroutine cam_grid_patch_get_coord_long_name(this, axis, name)
3923 :
3924 : ! Dummy arguments
3925 : class(cam_grid_patch_t) :: this
3926 : character(len=*), intent(in) :: axis
3927 : character(len=*), intent(out) :: name
3928 :
3929 : ! Local variable
3930 : character(len=120) :: errormsg
3931 : integer :: index
3932 :
3933 0 : if (cam_grid_check(this%grid_id)) then
3934 0 : index = this%grid_index()
3935 0 : if (trim(axis) == 'lat') then
3936 0 : call cam_grids(index)%lat_coord%get_long_name(name)
3937 0 : else if (trim(axis) == 'lon') then
3938 0 : call cam_grids(index)%lon_coord%get_long_name(name)
3939 : else
3940 0 : write(errormsg, *) 'Bad axis name:', axis
3941 0 : call endrun('cam_grid_patch_get_coord_long_name: '//errormsg)
3942 : end if
3943 : else
3944 0 : write(errormsg, *) 'Bad grid ID:', this%grid_id
3945 0 : call endrun('cam_grid_patch_get_coord_long_name: '//errormsg)
3946 : end if
3947 :
3948 0 : end subroutine cam_grid_patch_get_coord_long_name
3949 :
3950 0 : subroutine cam_grid_patch_get_coord_units(this, axis, units)
3951 :
3952 : ! Dummy arguments
3953 : class(cam_grid_patch_t) :: this
3954 : character(len=*), intent(in) :: axis
3955 : character(len=*), intent(out) :: units
3956 :
3957 : ! Local variable
3958 : character(len=120) :: errormsg
3959 : integer :: index
3960 :
3961 0 : if (cam_grid_check(this%grid_id)) then
3962 0 : index = this%grid_index()
3963 0 : if (trim(axis) == 'lat') then
3964 0 : call cam_grids(index)%lat_coord%get_units(units)
3965 0 : else if (trim(axis) == 'lon') then
3966 0 : call cam_grids(index)%lon_coord%get_units(units)
3967 : else
3968 0 : write(errormsg, *) 'Bad axis name:', axis
3969 0 : call endrun('cam_grid_patch_get_coord_units: '//errormsg)
3970 : end if
3971 : else
3972 0 : write(errormsg, *) 'Bad grid ID:', this%grid_id
3973 0 : call endrun('cam_grid_patch_get_coord_units: '//errormsg)
3974 : end if
3975 :
3976 0 : end subroutine cam_grid_patch_get_coord_units
3977 :
3978 0 : subroutine cam_grid_patch_set_patch(this, lonl, lonu, latl, latu, cco, id, map)
3979 :
3980 : ! Dummy arguments
3981 : class(cam_grid_patch_t) :: this
3982 : real(r8), intent(in) :: lonl, lonu ! Longitude bounds
3983 : real(r8), intent(in) :: latl, latu ! Latitude bounds
3984 : logical, intent(in) :: cco ! Collect columns?
3985 : integer, intent(in) :: id
3986 : type(cam_filemap_t), intent(in) :: map
3987 :
3988 0 : this%grid_id = id
3989 0 : this%lon_range(1) = lonl
3990 0 : this%lon_range(2) = lonu
3991 0 : this%lat_range(1) = latl
3992 0 : this%lat_range(2) = latu
3993 0 : this%collected_columns = cco
3994 0 : if (.not. associated(this%mask)) then
3995 0 : allocate(this%mask)
3996 : end if
3997 0 : call this%mask%copy(map)
3998 0 : call this%mask%new_index()
3999 :
4000 0 : end subroutine cam_grid_patch_set_patch
4001 :
4002 0 : subroutine cam_grid_patch_get_decomp(this, field_lens, file_lens, dtype, &
4003 0 : iodesc, file_dest_in)
4004 : use pio, only: io_desc_t
4005 : use cam_pio_utils, only: cam_pio_get_decomp
4006 :
4007 : ! Dummy arguments
4008 : class(cam_grid_patch_t) :: this
4009 : integer, intent(in) :: field_lens(:)
4010 : integer, intent(in) :: file_lens(:)
4011 : integer, intent(in) :: dtype
4012 : type(io_desc_t), pointer, intent(out) :: iodesc
4013 : integer, optional, intent(in) :: file_dest_in(:)
4014 :
4015 : call cam_pio_get_decomp(iodesc, field_lens, file_lens, dtype, this%mask, &
4016 0 : file_dist_in=file_dest_in)
4017 :
4018 0 : end subroutine cam_grid_patch_get_decomp
4019 :
4020 0 : subroutine cam_grid_patch_compact(this, collected_output)
4021 :
4022 : ! Dummy arguments
4023 : class(cam_grid_patch_t) :: this
4024 : logical, optional, intent(in) :: collected_output
4025 :
4026 : ! Local variables
4027 : integer :: index ! Our grid's index
4028 : logical :: dups_ok
4029 :
4030 0 : index = this%grid_index()
4031 0 : if (index > 0) then
4032 0 : dups_ok = cam_grids(index)%is_unstructured()
4033 : else
4034 : ! This is probably an error condition but someone else will catch it first
4035 0 : dups_ok = .false.
4036 : end if
4037 0 : if (present(collected_output)) then
4038 0 : dups_ok = dups_ok .or. collected_output
4039 : end if
4040 : call this%mask%compact(this%lonmap, this%latmap, &
4041 : num_lons=this%global_lon_size, num_lats=this%global_lat_size, &
4042 : num_mapped=this%global_size, columnize=collected_output, &
4043 0 : dups_ok_in=dups_ok)
4044 :
4045 0 : end subroutine cam_grid_patch_compact
4046 :
4047 0 : subroutine cam_grid_patch_get_active_cols(this, lchnk, active, srcdim_in)
4048 :
4049 : ! Dummy arguments
4050 : class(cam_grid_patch_t) :: this
4051 : integer, intent(in) :: lchnk
4052 : logical, intent(out) :: active(:)
4053 : integer, optional, intent(in) :: srcdim_in
4054 :
4055 0 : if (.not. associated(this%mask)) then
4056 0 : call endrun('cam_grid_patch_get_active_cols: No mask')
4057 : else
4058 0 : call this%mask%active_cols(lchnk, active, srcdim_in)
4059 : end if
4060 :
4061 0 : end subroutine cam_grid_patch_get_active_cols
4062 :
4063 : ! cam_grid_patch_write_vals: Write lat and lon coord values to File
4064 0 : subroutine cam_grid_patch_write_vals(this, File, header_info)
4065 : use pio, only: file_desc_t, io_desc_t
4066 : use pio, only: pio_write_darray, PIO_DOUBLE
4067 : use pio, only: pio_initdecomp, pio_freedecomp
4068 : use cam_pio_utils, only: cam_pio_handle_error, pio_subsystem
4069 :
4070 : ! Dummy arguments
4071 : class(cam_grid_patch_t) :: this
4072 : type(file_desc_t), intent(inout) :: File ! PIO file handle
4073 : type(cam_grid_header_info_t), intent(inout) :: header_info
4074 :
4075 : ! Local variables
4076 : type(io_desc_t) :: iodesc
4077 : type(var_desc_t), pointer :: vdesc
4078 0 : real(r8), pointer :: coord_p(:)
4079 0 : real(r8), pointer :: coord(:)
4080 0 : integer(iMap), pointer :: map(:)
4081 : integer :: field_lens(1)
4082 : integer :: file_lens(1)
4083 : integer :: ierr
4084 :
4085 0 : nullify(vdesc)
4086 0 : nullify(coord_p)
4087 0 : nullify(coord)
4088 0 : nullify(map)
4089 0 : if (this%grid_id /= header_info%get_gridid()) then
4090 0 : call endrun('CAM_GRID_PATCH_WRITE_VALS: Grid id mismatch')
4091 : end if
4092 : ! Write out lon
4093 0 : if (associated(this%lonmap)) then
4094 0 : field_lens(1) = size(this%lonmap, 1)
4095 0 : map => this%lonmap
4096 : else
4097 0 : field_lens(1) = 0
4098 0 : allocate(map(0))
4099 : end if
4100 0 : file_lens(1) = this%global_lon_size
4101 : !! XXgoldyXX: Think about caching these decomps
4102 0 : call pio_initdecomp(pio_subsystem, pio_double, file_lens, map, iodesc)
4103 0 : if (associated(this%lonvals)) then
4104 0 : coord => this%lonvals
4105 : else
4106 0 : coord_p => cam_grid_get_lonvals(this%grid_id)
4107 0 : if (associated(coord_p)) then
4108 0 : coord => coord_p
4109 : else
4110 0 : allocate(coord(0))
4111 : end if
4112 : end if
4113 0 : vdesc => header_info%get_lon_varid()
4114 0 : call pio_write_darray(File, vdesc, iodesc, coord, ierr)
4115 0 : call cam_pio_handle_error(ierr, 'cam_grid_patch_write_vals: Error writing longitude')
4116 0 : if (.not. associated(this%lonmap)) then
4117 0 : deallocate(map)
4118 : nullify(map)
4119 : end if
4120 0 : if (.not. (associated(coord_p) .or. associated(this%lonvals))) then
4121 0 : deallocate(coord)
4122 : nullify(coord)
4123 : end if
4124 0 : call pio_freedecomp(File, iodesc)
4125 : ! Write out lat
4126 0 : if (associated(this%latmap)) then
4127 0 : field_lens(1) = size(this%latmap, 1)
4128 0 : map => this%latmap
4129 : else
4130 0 : field_lens(1) = 0
4131 0 : allocate(map(0))
4132 : end if
4133 0 : file_lens(1) = this%global_lat_size
4134 : !! XXgoldyXX: Think about caching these decomps
4135 0 : call pio_initdecomp(pio_subsystem, pio_double, file_lens, map, iodesc)
4136 :
4137 0 : if (associated(this%latvals)) then
4138 0 : coord => this%latvals
4139 : else
4140 0 : coord_p => cam_grid_get_latvals(this%grid_id)
4141 0 : if (associated(coord_p)) then
4142 0 : coord => coord_p
4143 : else
4144 0 : allocate(coord(0))
4145 : end if
4146 : end if
4147 0 : vdesc => header_info%get_lat_varid()
4148 0 : call pio_write_darray(File, vdesc, iodesc, coord, ierr)
4149 0 : call cam_pio_handle_error(ierr, 'cam_grid_patch_write_vals: Error writing latitude')
4150 0 : if (.not. associated(this%latmap)) then
4151 0 : deallocate(map)
4152 : nullify(map)
4153 : end if
4154 0 : if (.not. (associated(coord_p) .or. associated(this%latvals))) then
4155 0 : deallocate(coord)
4156 : nullify(coord)
4157 : end if
4158 0 : call pio_freedecomp(File, iodesc)
4159 :
4160 0 : end subroutine cam_grid_patch_write_vals
4161 :
4162 0 : integer function cam_grid_patch_get_grid_index(this) result(index)
4163 : ! Dummy argument
4164 : class(cam_grid_patch_t) :: this
4165 :
4166 : ! Local variable
4167 : integer :: i
4168 :
4169 0 : index = -1
4170 : ! Find the grid index associated with our grid_id which is a decomp
4171 0 : do i = 1, cam_grid_num_grids()
4172 0 : if (cam_grids(i)%id == this%grid_id) then
4173 : index = i
4174 : exit
4175 : end if
4176 : end do
4177 :
4178 0 : end function cam_grid_patch_get_grid_index
4179 :
4180 0 : subroutine cam_grid_patch_deallocate(this)
4181 : ! Dummy argument
4182 : class(cam_grid_patch_t) :: this
4183 :
4184 0 : if (associated(this%mask)) then
4185 0 : deallocate(this%mask)
4186 0 : nullify(this%mask)
4187 : end if
4188 :
4189 0 : end subroutine cam_grid_patch_deallocate
4190 :
4191 1907712 : integer function cam_grid_header_info_get_gridid(this) result(id)
4192 : ! Dummy argument
4193 : class(cam_grid_header_info_t) :: this
4194 :
4195 1907712 : id = this%grid_id
4196 :
4197 1907712 : end function cam_grid_header_info_get_gridid
4198 :
4199 0 : subroutine cam_grid_header_info_set_gridid(this, id)
4200 : ! Dummy argument
4201 : class(cam_grid_header_info_t) :: this
4202 : integer, intent(in) :: id
4203 :
4204 0 : this%grid_id = id
4205 :
4206 0 : end subroutine cam_grid_header_info_set_gridid
4207 :
4208 0 : subroutine cam_grid_header_info_set_hdims(this, hdim1, hdim2)
4209 : ! Dummy arguments
4210 : class(cam_grid_header_info_t) :: this
4211 : integer, intent(in) :: hdim1
4212 : integer, optional, intent(in) :: hdim2
4213 :
4214 : ! Local variables
4215 : integer :: hdsize
4216 :
4217 0 : if (present(hdim2)) then
4218 : hdsize = 2
4219 : else
4220 0 : hdsize = 1
4221 : end if
4222 :
4223 0 : if (allocated(this%hdims)) then
4224 : ! This can happen, for instance on opening a new version of the file
4225 0 : if (size(this%hdims) /= hdsize) then
4226 0 : call endrun('cam_grid_header_info_set_hdims: hdims is wrong size')
4227 : end if
4228 : else
4229 0 : allocate(this%hdims(hdsize))
4230 : end if
4231 0 : this%hdims(1) = hdim1
4232 0 : if (present(hdim2)) then
4233 0 : this%hdims(2) = hdim2
4234 : end if
4235 :
4236 0 : end subroutine cam_grid_header_info_set_hdims
4237 :
4238 1909248 : integer function cam_grid_header_info_num_hdims(this) result(num)
4239 : ! Dummy argument
4240 : class(cam_grid_header_info_t) :: this
4241 :
4242 1909248 : if (allocated(this%hdims)) then
4243 1909248 : num = size(this%hdims)
4244 : else
4245 : num = 0
4246 : end if
4247 :
4248 1909248 : end function cam_grid_header_info_num_hdims
4249 :
4250 1910784 : integer function cam_grid_header_info_hdim(this, index) result(id)
4251 : ! Dummy arguments
4252 : class(cam_grid_header_info_t) :: this
4253 : integer, intent(in) :: index
4254 :
4255 : ! Local variable
4256 : character(len=120) :: errormsg
4257 :
4258 1910784 : if (allocated(this%hdims)) then
4259 1910784 : if ((index >= 1) .and. (index <= size(this%hdims))) then
4260 1910784 : id = this%hdims(index)
4261 : else
4262 0 : write(errormsg, '(a,i0,a)') 'Index out of range, (',index,')'
4263 0 : call endrun('cam_grid_header_info_hdim: '//errormsg)
4264 : end if
4265 : else
4266 0 : write(errormsg, '(a)') 'No hdims allocated'
4267 0 : call endrun('cam_grid_header_info_hdim: '//errormsg)
4268 : end if
4269 :
4270 1910784 : end function cam_grid_header_info_hdim
4271 :
4272 0 : subroutine cam_grid_header_info_set_varids(this, lon_varid, lat_varid)
4273 :
4274 : ! Dummy arguments
4275 : class(cam_grid_header_info_t) :: this
4276 : type(var_desc_t), pointer :: lon_varid
4277 : type(var_desc_t), pointer :: lat_varid
4278 :
4279 0 : if (associated(this%lon_varid)) then
4280 0 : deallocate(this%lon_varid)
4281 0 : nullify(this%lon_varid)
4282 : end if
4283 0 : this%lon_varid => lon_varid
4284 0 : if (associated(this%lat_varid)) then
4285 0 : deallocate(this%lat_varid)
4286 0 : nullify(this%lat_varid)
4287 : end if
4288 0 : this%lat_varid => lat_varid
4289 :
4290 0 : end subroutine cam_grid_header_info_set_varids
4291 :
4292 0 : function cam_grid_header_info_lon_varid(this) result(id)
4293 :
4294 : ! Dummy arguments
4295 : class(cam_grid_header_info_t) :: this
4296 : type(var_desc_t), pointer :: id
4297 :
4298 0 : id => this%lon_varid
4299 :
4300 0 : end function cam_grid_header_info_lon_varid
4301 :
4302 0 : function cam_grid_header_info_lat_varid(this) result(id)
4303 :
4304 : ! Dummy arguments
4305 : class(cam_grid_header_info_t) :: this
4306 : type(var_desc_t), pointer :: id
4307 :
4308 0 : id => this%lat_varid
4309 :
4310 0 : end function cam_grid_header_info_lat_varid
4311 :
4312 4608 : subroutine cam_grid_header_info_deallocate(this)
4313 : ! Dummy argument
4314 : class(cam_grid_header_info_t) :: this
4315 :
4316 4608 : this%grid_id = -1
4317 4608 : if (allocated(this%hdims)) then
4318 4608 : deallocate(this%hdims)
4319 : end if
4320 4608 : if (associated(this%lon_varid)) then
4321 0 : deallocate(this%lon_varid)
4322 0 : nullify(this%lon_varid)
4323 : end if
4324 4608 : if (associated(this%lat_varid)) then
4325 0 : deallocate(this%lat_varid)
4326 0 : nullify(this%lat_varid)
4327 : end if
4328 :
4329 4608 : end subroutine cam_grid_header_info_deallocate
4330 :
4331 0 : end module cam_grid_support
|