1 !***********************************************************************
2 !* GNU Lesser General Public License
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
22 !> @ingroup fms_io_mod
24 !------------------------------------------------------------------------------
25 !>Store a real axis (x,y,z,...) in a restart object assoicated with an
26 !!unstructured mpp domain.
27 subroutine fms_io_unstructured_register_restart_axis_r1D(fileObj, &
39 type(restart_file_type),intent(inout) :: fileObj !<A restart object.
40 character(len=*),intent(in) :: filename !<A name of a file.
41 character(len=*),intent(in) :: fieldname !<A name for the axis field.
42 real,dimension(:),intent(in),target :: fdata !<Data for the axis.
43 character(len=*),intent(in) :: cartesian !<String indicating which cartesian axis this is (i.e. X, Y, Z).
44 type(domainUG),intent(in),target :: domain !<An unustructured mpp domain.
45 character(len=*),intent(in),optional :: units !<Units for the axis.
46 character(len=*),intent(in),optional :: longname !<A more descriptive name for the axis.
47 integer(INT_KIND),intent(in),optional :: sense !<Positive direction.
48 real,intent(in),optional :: fmin !<Minimum value for this axis.
49 character(len=*),intent(in),optional :: calendar !<Type of calendar (only for time axis.)
52 integer(INT_KIND) :: input_filename_length !<The length of the trimmed input filename.
53 character(len=256) :: tmp_filename !<A character buffer
54 !! used to store various file names.
55 character(len=256) :: filename_suffix !<A string appended
56 !! to the end of the inputted file name.
57 character(len=256) :: mosaic_filename !<The filename returned
58 !! by the get_mosaic_tile_file_ug routine.
59 integer(INT_KIND) :: axis_index !<Index of the inputted
60 !! axis in the fileObj%axes array.
61 type(domainUG),pointer :: io_domain !<Pointer to an unstructured I/O domain.
62 integer(INT_KIND) :: io_domain_npes !<The total number
63 !! of ranks in an I/O domain pelist.
64 integer(INT_KIND),dimension(:),allocatable :: pelist !<A pelist.
65 integer(INT_KIND),dimension(:),allocatable :: fdata_sizes !<Size of the axis
66 !! data for each rank in the I/O domain pelist.
68 !Make sure that the module is initialized.
69 if (.not. module_is_initialized) then
70 call mpp_error(FATAL, &
71 "fms_io_unstructured_register_restart_axis_r1D:" &
72 //" you must first to call fms_io_init.")
75 !All axes must be registered before any fields. Make sure that no
76 !fields have been registered to the restart object.
77 if (associated(fileObj%var)) then
78 call mpp_error(FATAL, &
79 "fms_io_unstructured_register_restart_axis_r1D: " &
80 //" you cannot register any fields before an axis.")
83 !Use this code to make the filename consistent with the
84 !fms_io_unstructured_setup_one_field routine.
85 input_filename_length = len_trim(filename)
86 if (input_filename_length .gt. 128) then
87 call mpp_error(FATAL, &
88 "fms_io_unstructured_register_restart_axis_r1D:" &
89 //" the inputted file name is longer than 128" &
92 if (filename(input_filename_length-2:input_filename_length) .eq. ".nc") then
93 tmp_filename = filename(1:input_filename_length-3)
95 tmp_filename = filename(1:input_filename_length)
98 if (len_trim(filename_appendix) .gt. 0) then
99 filename_suffix = trim(filename_appendix)
101 if (len_trim(filename_suffix) .gt. 0) then
102 tmp_filename = trim(tmp_filename)//"."//trim(filename_suffix)
104 call get_mosaic_tile_file_ug(tmp_filename, &
108 !Make sure that the correct file name was passed in, or set the filename
109 !if this is the first axis/field registered to the restart object.
110 if (.not. allocated(fileObj%axes)) then
111 fileObj%name = trim(mosaic_filename)
113 if (trim(mosaic_filename) .ne. trim(fileObj%name)) then
114 call mpp_error(FATAL, &
115 "fms_io_unstructured_register_restart_axis_r1D:" &
116 //" the inputted file name does not match the" &
117 //" existing file name for this restart object.")
121 !If this is the first axis registered for the restart object, then
122 !allocate the fileObj%axes array. The size of the fileObj%axes array
123 !is determined by the NIDX module parameter.
124 if (.not. allocated(fileObj%axes)) then
125 allocate(fileObj%axes(NIDX))
128 !Determine the index of the inputted axis in the fileObj%axes array from
129 !the inputted cartesian string.
130 select case (trim(cartesian))
142 call mpp_error(FATAL, &
143 "fms_io_unstructured_register_restart_axis_r1D:" &
144 //" an invalid cartesian string was passed in.")
147 !Make sure that data has not already been registered for the inputted
149 if (associated(fileObj%axes(axis_index)%data)) then
150 call mpp_error(FATAL, &
151 "fms_io_unstructured_register_restart_axis_r1D:" &
152 //" the "//trim(cartesian)//" axis for this restart" &
153 //" object has already been defined.")
156 !Make sure that the axis size is consistent for all ranks on the
157 !unstructured I/O domain pelist.
159 io_domain => mpp_get_UG_io_domain(domain)
160 io_domain_npes = mpp_get_UG_domain_npes(io_domain)
161 allocate(pelist(io_domain_npes))
162 call mpp_get_UG_domain_pelist(io_domain, &
164 allocate(fdata_sizes(io_domain_npes))
166 call mpp_gather((/size(fdata)/), &
169 if (mpp_pe() .eq. pelist(1)) then
170 if (maxval(fdata_sizes) .ne. size(fdata) .or. &
171 minval(fdata_sizes) .ne. size(fdata)) then
172 call mpp_error(FATAL, &
173 "fms_io_unstructured_register_restart_axis_r1D:" &
174 //" the "//trim(cartesian)//" axis must be the" &
175 //" the same size for all ranks in the" &
176 //" unstructured I/O domain pelist.")
181 deallocate(fdata_sizes)
183 !Set the name of the axis.
184 fileObj%axes(axis_index)%name = trim(fieldname)
186 !Point to the inputted unstructured domain for the axis.
187 fileObj%axes(axis_index)%domain_ug => domain
189 !Point to the inputted axis data.
190 fileObj%axes(axis_index)%data => fdata
192 !Store the inputted cartesian string. (Why?)
193 fileObj%axes(axis_index)%cartesian = trim(cartesian)
195 !Set the dimension length for the axis to -1 to signify that this is
196 !not a "compressed" axis.
197 fileObj%axes(axis_index)%dimlen = -1
199 !Store the units for the axis.
200 if (present(units)) then
201 fileObj%axes(axis_index)%units = trim(units)
203 fileObj%axes(axis_index)%units = ""
206 !Store the longname for the axis.
207 if (present(longname)) then
208 fileObj%axes(axis_index)%longname = trim(longname)
210 fileObj%axes(axis_index)%longname = ""
213 !Store the "sense" for the axis. Inputs must be for the z-dimension.
214 if (present(sense)) then
215 if (axis_index .ne. ZIDX) then
216 call mpp_error(FATAL, &
217 "fms_io_unstructured_register_restart_axis_r1D:" &
218 //" sense may only be defined for the z-axis.")
220 if (abs(sense) .ne. 1) then
221 call mpp_error(FATAL, &
222 "fms_io_unstructured_register_restart_axis_r1D:" &
223 //" sense may only have the values +/- 1")
225 fileObj%axes(axis_index)%sense = sense
227 fileObj%axes(axis_index)%sense = 0
230 !Store the minimum value allowed for the axis.
231 if (present(fmin)) then
232 fileObj%axes(axis_index)%min = fmin
234 fileObj%axes(axis_index)%min = 0
237 !Store the calendar for the axis. This is only done for the time dimension.
238 if (axis_index .eq. TIDX) then
239 fileObj%axes(axis_index)%calendar = trim(calendar)
243 end subroutine fms_io_unstructured_register_restart_axis_r1D
245 !------------------------------------------------------------------------------
246 !>Store an integer "compressed" axis in a restart object assoicated with an
247 !!unstructured mpp domain.
248 subroutine fms_io_unstructured_register_restart_axis_i1D(fileObj, &
262 type(restart_file_type),intent(inout) :: fileObj !<A restart object.
263 character(len=*),intent(in) :: filename !<A name of a file.
264 character(len=*),intent(in) :: fieldname !<A name for the axis field.
265 integer(INT_KIND),dimension(:),intent(in),target :: fdata !<Data for the axis.
266 character(len=*),intent(in) :: compressed !<"Compressed" string (???)
267 character(len=*),intent(in) :: compressed_axis !<"Compressed" axis string.
268 integer(INT_KIND),intent(in) :: dimlen !<Length of the compressed dimension.
269 type(domainUG),intent(in),target :: domain !<An unustructured mpp domain.
270 character(len=*),intent(in),optional :: dimlen_name !<(???)
271 character(len=*),intent(in),optional :: dimlen_lname !<(???)
272 character(len=*),intent(in),optional :: units !<Units for the axis.
273 character(len=*),intent(in),optional :: longname !<A more descriptive name for the axis.
274 integer(INT_KIND),intent(in),optional :: imin !<Minium value for the dimension.
277 integer(INT_KIND) :: input_filename_length !<The length of the trimmed input filename.
278 character(len=256) :: tmp_filename !<A character buffer
279 !! used to store various file names.
280 character(len=256) :: filename_suffix !<A string appended
281 !! to the end of the inputted file name.
282 character(len=256) :: mosaic_filename !<The filename returned
283 !! by the get_mosaic_tile_file_ug routine.
284 integer(INT_KIND) :: axis_index !<Index of the inputted
285 !! axis in the fileObj%axes array.
286 type(domainUG),pointer :: io_domain !<Pointer to an unstructured I/O domain.
287 integer(INT_KIND) :: io_domain_npes !<The total number
288 !! of ranks in an I/O domain pelist.
289 integer(INT_KIND),dimension(:),allocatable :: pelist !<A pelist.
291 !Make sure that the module is initialized.
292 if (.not. module_is_initialized) then
293 call mpp_error(FATAL, &
294 "fms_io_unstructured_register_restart_axis_i1D:" &
295 //" you must first to call fms_io_init.")
298 !All axes must be registered before any fields. Make sure that no
299 !fields have been registered to the restart object.
300 if (associated(fileObj%var)) then
301 call mpp_error(FATAL, &
302 "fms_io_unstructured_register_restart_axis_i1D:" &
303 //" you cannot register any fields before an axis.")
306 !Use this code to make the filename consistent with the
307 !fms_io_unstructured_setup_one_field routine.
308 input_filename_length = len_trim(filename)
309 if (input_filename_length .gt. 128) then
310 call mpp_error(FATAL, &
311 "fms_io_unstructured_register_restart_axis_i1D:" &
312 //" the inputted file name is longer than 128" &
315 if (filename(input_filename_length-2:input_filename_length) .eq. ".nc") then
316 tmp_filename = filename(1:input_filename_length-3)
318 tmp_filename = filename(1:input_filename_length)
321 if (len_trim(filename_appendix) .gt. 0) then
322 filename_suffix = trim(filename_appendix)
324 if (len_trim(filename_suffix) .gt. 0) then
325 tmp_filename = trim(tmp_filename)//"."//trim(filename_suffix)
327 call get_mosaic_tile_file_ug(tmp_filename, &
331 !Make sure that the correct file name was passed in, or set the filename
332 !if this is the first axis/field registered to the restart object.
333 if (.not. allocated(fileObj%axes)) then
334 fileObj%name = trim(mosaic_filename)
336 if (trim(mosaic_filename) .ne. trim(fileObj%name)) then
337 call mpp_error(FATAL, &
338 "fms_io_unstructured_register_restart_axis_i1D:" &
339 //" the inputted file name does not match the" &
340 //" existing file name for this restart object.")
344 !If this is the first axis registered for the restart object, then
345 !allocate the fileObj%axes array. The size of the fileObj%axes array
346 !is determined by the NIDX module parameter.
347 if (.not. allocated(fileObj%axes)) then
348 allocate(fileObj%axes(NIDX))
351 !Get the index of the inputted axis in the fileObj%axes array from the
352 !inputted compressed_axis string.
353 select case (trim(compressed_axis))
359 call mpp_error(FATAL, &
360 "fms_io_unstructured_register_restart_axis_i1D:" &
361 //" invalid compressed_axis string was passed in.")
364 !Make sure that data has not already been registered for the inputted axis.
365 if (allocated(fileObj%axes(axis_index)%idx)) then
366 call mpp_error(FATAL, &
367 "fms_io_unstructured_register_restart_axis_i1D:" &
368 //" the "//trim(compressed_axis)//" axis for this" &
369 //" restart object has already been defined.")
372 !Set the name of the axis.
373 fileObj%axes(axis_index)%name = trim(fieldname)
375 !Point to the inputted unstructured domain.
376 fileObj%axes(axis_index)%domain_ug => domain
378 !Initialize the number of data elements each rank in an unstructured I/O
379 !domain is responsible for.
381 io_domain => mpp_get_UG_io_domain(domain)
382 io_domain_npes = mpp_get_UG_domain_npes(io_domain)
383 allocate(fileObj%axes(axis_index)%nelems(io_domain_npes))
384 fileObj%axes(axis_index)%nelems = 0
385 fileObj%axes(axis_index)%nelems_for_current_rank = size(fdata)
387 !Gather the sizes of the inputted data arrays for each rank onto the root
388 !rank of the I/O domain pelist.
389 allocate(pelist(io_domain_npes))
390 call mpp_get_UG_domain_pelist(io_domain, &
392 call mpp_gather((/size(fdata)/), &
393 fileObj%axes(axis_index)%nelems, &
396 !Gather the inputted data from each rank onto the root rank of the I/O
398 if (mpp_pe() .eq. pelist(1)) then
399 allocate(fileObj%axes(axis_index)%idx(sum(fileObj%axes(axis_index)%nelems)))
401 !This array for a non-root rank on the I/O domain pelist should never
402 !be used, but is allocated to signify that this axis is defined for
403 !this restart object.
404 allocate(fileObj%axes(axis_index)%idx(1))
405 fileObj%axes(axis_index)%idx = 0
407 call mpp_gather(fdata, &
409 fileObj%axes(axis_index)%idx, &
410 fileObj%axes(axis_index)%nelems, &
413 !Nullify local pointers and deallocate local allocatables.
417 !Set the "compressed" string for the axis.
418 fileObj%axes(axis_index)%compressed = trim(compressed)
420 !Set the dimension length for the axis.
421 fileObj%axes(axis_index)%dimlen = dimlen
423 !Set the dimlen_name (???) for the axis.
424 if (present(dimlen_name)) then
425 fileObj%axes(axis_index)%dimlen_name = trim(dimlen_name)
427 fileObj%axes(axis_index)%dimlen_name = ""
430 !Set the dimlen_lname (???) for the axis.
431 if (present(dimlen_lname)) then
432 fileObj%axes(axis_index)%dimlen_lname = trim(dimlen_lname)
434 fileObj%axes(axis_index)%dimlen_lname = ""
437 !Set the units for the axis.
438 if (present(units)) then
439 fileObj%axes(axis_index)%units = trim(units)
441 fileObj%axes(axis_index)%units = ""
444 !Set the longname for the axis.
445 if (present(longname)) then
446 fileObj%axes(axis_index)%longname = trim(longname)
448 fileObj%axes(axis_index)%longname = ""
451 !Set the minimum value for the axis.
452 if (present(imin)) then
453 fileObj%axes(axis_index)%imin = imin
455 fileObj%axes(axis_index)%imin = 0
459 end subroutine fms_io_unstructured_register_restart_axis_i1D
461 !------------------------------------------------------------------------------
462 !>Store an unlimited axis in a restart object assoicated with an unstructured
464 subroutine fms_io_unstructured_register_restart_axis_u(fileObj, &
472 type(restart_file_type),intent(inout) :: fileObj !<A restart object.
473 character(len=*),intent(in) :: filename !<A name of a file.
474 character(len=*),intent(in) :: fieldname !<A name for the axis field.
475 integer(INT_KIND),intent(in) :: nelems !<Number of elements on the axis for the current rank.
476 type(domainUG),intent(in),target :: domain !<An unustructured mpp domain.
477 character(len=*),intent(in),optional :: units !<Units for the axis.
478 character(len=*),intent(in),optional :: longname !<A more descriptive name for the axis.
481 integer(INT_KIND) :: input_filename_length !<The length of the trimmed input filename.
482 character(len=256) :: tmp_filename !<A character buffer
483 !! used to store various file names.
484 character(len=256) :: filename_suffix !<A string appended
485 !! to the end of the inputted file name.
486 character(len=256) :: mosaic_filename !<The filename returned
487 !! by the get_mosaic_tile_file_ug routine.
488 integer(INT_KIND) :: axis_index !<Index of the inputted
489 !! axis in the fileObj%axes array.
490 type(domainUG),pointer :: io_domain !<Pointer to an unstructured I/O domain.
491 integer(INT_KIND) :: io_domain_npes !<The total number
492 !! of ranks in an I/O domain pelist.
493 integer(INT_KIND),dimension(:),allocatable :: pelist !<A pelist.
495 !Make sure that the module is initialized.
496 if (.not. module_is_initialized) then
497 call mpp_error(FATAL, &
498 "fms_io_unstructured_register_restart_axis_u:" &
499 //" you must first to call fms_io_init.")
502 !All axes must be registered before any fields. Make sure that no
503 !fields have been registered to the restart object.
504 if (associated(fileObj%var)) then
505 call mpp_error(FATAL, &
506 "fms_io_unstructured_register_restart_axis_u:" &
507 //" you cannot register any fields before an axis.")
510 !Use this code to make the filename consistent with the
511 !fms_io_unstructured_setup_one_field routine.
512 input_filename_length = len_trim(filename)
513 if (input_filename_length .gt. 128) then
514 call mpp_error(FATAL, &
515 "fms_io_unstructured_register_restart_axis_u:" &
516 //" the inputted file name is longer than 128" &
519 if (filename(input_filename_length-2:input_filename_length) .eq. ".nc") then
520 tmp_filename = filename(1:input_filename_length-3)
522 tmp_filename = filename(1:input_filename_length)
525 if (len_trim(filename_appendix) .gt. 0) then
526 filename_suffix = trim(filename_appendix)
528 if (len_trim(filename_suffix) .gt. 0) then
529 tmp_filename = trim(tmp_filename)//"."//trim(filename_suffix)
531 call get_mosaic_tile_file_ug(tmp_filename, &
535 !Make sure that the correct file name was passed in, or set the filename
536 !if this is the first axis/field registered to the restart object.
537 if (.not. allocated(fileObj%axes)) then
538 fileObj%name = trim(mosaic_filename)
540 if (trim(mosaic_filename) .ne. trim(fileObj%name)) then
541 call mpp_error(FATAL, &
542 "fms_io_unstructured_register_restart_axis_u:" &
543 //" the inputted file name does not match the" &
544 //" existing file name for this restart object.")
548 !If this is the first axis registered for the restart object, then
549 !allocate the fileObj%axes array. The size of the fileObj%axes array
550 !is determined by the NIDX module parameter.
551 if (.not. allocated(fileObj%axes)) then
552 allocate(fileObj%axes(NIDX))
555 !Get the index of the inputted axis in the fileObj%axes array.
558 !Make sure that data has not already been registered for the inputted axis.
559 if (allocated(fileObj%axes(axis_index)%idx)) then
560 call mpp_error(FATAL, &
561 "fms_io_unstructured_register_restart_axis_u:" &
562 //" the unlimited axis for this restart object" &
563 //" has already been defined.")
566 !Set the name of the axis.
567 fileObj%axes(axis_index)%name = trim(fieldname)
569 !Point to the inputted unstructured domain.
570 fileObj%axes(axis_index)%domain_ug => domain
572 !Initialize the number of data elements each rank in an unstructured I/O
573 !domain is responsible for.
575 io_domain => mpp_get_UG_io_domain(domain)
576 io_domain_npes = mpp_get_UG_domain_npes(io_domain)
577 allocate(fileObj%axes(axis_index)%nelems(io_domain_npes))
578 fileObj%axes(axis_index)%nelems = 0
580 !Gather the inputted number of elements each rank is responsible for onto
581 !the root rank of the I/O domain pelist.
582 allocate(pelist(io_domain_npes))
583 call mpp_get_UG_domain_pelist(io_domain, &
585 call mpp_gather((/nelems/), &
586 fileObj%axes(axis_index)%nelems, &
589 !Nullify local pointers and deallocate local allocatables.
593 !Set the units for the axis.
594 if (present(units)) then
595 fileObj%axes(axis_index)%units = trim(units)
597 fileObj%axes(axis_index)%units = ""
600 !Set the longname for the axis.
601 if (present(longname)) then
602 fileObj%axes(axis_index)%longname = trim(longname)
604 fileObj%axes(axis_index)%longname = ""
608 end subroutine fms_io_unstructured_register_restart_axis_u
610 !------------------------------------------------------------------------------