FMS  2024.03
Flexible Modeling System
fms_io_unstructured_get_field_size.inc
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
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.
10 !*
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
14 !* for more details.
15 !*
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 !***********************************************************************
19 !----------
20 !ug support
21 
22 !> @addtogroup fms_io_mod
23 !> @{
24 
25 !>Get the size of the dimensions of a field from a file associated with an
26 !!unstructured mpp domain.
27 subroutine fms_io_unstructured_get_field_size(filename, &
28  fieldname, &
29  field_dimension_sizes, &
30  domain, &
31  field_found)
32 
33  !Inputs/Outputs
34  character(len=*),intent(in) :: filename !<The name of a file.
35  character(len=*),intent(in) :: fieldname !<The name of a field in the input file.
36  integer,dimension(:),intent(inout) :: field_dimension_sizes !<Array of dimension sizes for the inputted field.
37  type(domainug),intent(in) :: domain !<An unstructured mpp domain
38  !! associated with the input file.
39  logical,intent(out),optional :: field_found !<Flag telling if the inputted
40  !! field was found in the inputted file.
41 
42  !Local variables
43  type(domainug),pointer :: io_domain !<Pointer to the unstructured I/O domain.
44  integer(INT_KIND) :: io_domain_npes !<The total number of ranks in an I/O domain pelist.
45  integer(INT_KIND),dimension(:),allocatable :: pelist !<A pelist.
46  integer(INT_KIND) :: funit !<File unit for the inputted file.
47  integer(INT_KIND) :: num_axes !<The total number of axes
48  !! contained in the inputted file.
49  integer(INT_KIND) :: num_fields !<The total number of fields
50  !! contained in the inputted file.
51  integer(INT_KIND) :: num_atts !<The total number of global
52  !! attributes contained in the inputted file.
53  integer(INT_KIND) :: num_time_levels !<The total number of time
54  !! levels contained in the inputted file.
55  type(fieldtype),dimension(max_fields) :: file_fields !<An array of all fields
56  !! contained in the inputted file (max_fields is a module variable).
57  logical(INT_KIND) :: found !<Flag telling if the field was found in the file.
58  character(len=128) :: file_field_name !<Name of a field from the inputted file.
59  integer(INT_KIND) :: file_field_ndim !<Number of dimensions of
60  !! a field from the inputted file.
61  type(axistype),dimension(max_fields) :: file_field_axes !<An array of all axes of
62  !! a field contained in the inputted file (max_fields is a module variable).
63  character(len=128) :: file_axis_name !<Name of an axis from the inputted file.
64  integer(INT_KIND) :: file_axis_size !<Size of an axis from the inputted file.
65  integer(INT_KIND) :: i !<Loop variable.
66  integer(INT_KIND) :: j !<Loop variable.
67 
68  !Point to the I/O domain associated with the inputted unstructured mpp
69  !domain.
70  io_domain => null()
71  io_domain => mpp_get_ug_io_domain(domain)
72 
73  !Get the pelist associated with the I/O domain.
74  io_domain_npes = mpp_get_ug_domain_npes(io_domain)
75  allocate(pelist(io_domain_npes))
76  call mpp_get_ug_domain_pelist(io_domain, &
77  pelist)
78  io_domain => null()
79 
80  !Get the file unit for the inputted file.
81  call fms_io_unstructured_file_unit(filename, &
82  funit, &
83  domain)
84 
85  !Have the root rank of the I/O domain pelist get the size of the dimensions
86  !of the inputted fields from the inputted file.
87  if (mpp_pe() .eq. pelist(1)) then
88 
89  !Get the number of fields and axes contained in the inputted file.
90  call mpp_get_info(funit, &
91  num_axes, &
92  num_fields, &
93  num_atts, &
94  num_time_levels)
95 
96  !Make sure that the number of fields in the file does not exceed the
97  !maximum number allowed per file.
98  !max_fields is a module variable.
99  if (num_fields .gt. max_fields) then
100  call mpp_error(fatal, &
101  "fms_io_unstructured_get_field_size:" &
102  //" the number of fields in the file " &
103  //trim(filename)//" exceeds the maximum number" &
104  //" of fields allowed per file (max_fields)")
105  endif
106 
107  !Read in all fields contained in the inputted file.
108  call mpp_get_fields(funit, &
109  file_fields(1:num_fields))
110 
111  !Check if the inputted field matches one the fields contained in
112  !the inputted file. If it matches, get the size of the field
113  !dimensions.
114  found = .false.
115  field_dimension_sizes = -1
116  do i = 1,num_fields
117  call mpp_get_atts(file_fields(i), &
118  name=file_field_name)
119  if (lowercase(trim(file_field_name)) .eq. &
120  lowercase(trim(fieldname))) then
121  call mpp_get_atts(file_fields(i), &
122  ndim=file_field_ndim)
123  call mpp_get_atts(file_fields(i), &
124  axes=file_field_axes(1:file_field_ndim))
125  do j = 1,file_field_ndim
126  call mpp_get_atts(file_field_axes(j), &
127  len=field_dimension_sizes(j))
128  enddo
129  found = .true.
130  exit
131  endif
132  enddo
133 
134  !If the inputted field does not match any of the fields contained
135  !in the inputted file, then check if it matches any of the axes
136  !contained in the file.
137  if (.not. found) then
138  call mpp_get_axes(funit, &
139  file_field_axes(1:num_axes))
140  do i = 1,num_axes
141  call mpp_get_atts(file_field_axes(i), &
142  name=file_axis_name, &
143  len=file_axis_size)
144  if (lowercase(trim(file_axis_name)) .eq. &
145  lowercase(trim(fieldname))) then
146  field_dimension_sizes(1) = file_axis_size
147  found = .true.
148  exit
149  endif
150  enddo
151  endif
152  endif
153 
154  !Broadcast the flag telling if the inputted field was found in the inputted
155  !file and the field dimension sizes array to all non-root ranks on the
156  !I/O domain pelist.
157  if (mpp_pe() .eq. pelist(1)) then
158  do i = 2,io_domain_npes
159  call mpp_send(found, &
160  pelist(i), &
161  tag=comm_tag_1)
162  call mpp_send(field_dimension_sizes, &
163  size(field_dimension_sizes), &
164  pelist(i), &
165  tag=comm_tag_2)
166  enddo
167  call mpp_sync_self()
168  else
169  call mpp_recv(found, &
170  pelist(1), &
171  block = .false., &
172  tag=comm_tag_1)
173  call mpp_recv(field_dimension_sizes, &
174  size(field_dimension_sizes), &
175  pelist(1), &
176  block = .false., &
177  tag=comm_tag_2)
178  call mpp_sync_self(check=event_recv)
179  endif
180 
181  !If the field_found flag is present, then return the value of the found
182  !flag. It is assumed that this value will be checked by the calling
183  !routine. If the field_found flag is not present and the field was not
184  !found in the file, then throw a fatal error.
185  if (present(field_found)) then
186  field_found = found
187  elseif (.not. found) then
188  call mpp_error(fatal, &
189  "fms_io_unstructured_get_field_size:" &
190  //" the inputted field "//trim(fieldname) &
191  //" was not found in the file "//trim(filename))
192  endif
193 
194  !Deallocate local allocatables.
195  deallocate(pelist)
196 
197  return
199 !> @}
subroutine fms_io_unstructured_get_field_size(filename, fieldname, field_dimension_sizes, domain, field_found)
Get the size of the dimensions of a field from a file associated with an unstructured mpp domain.
subroutine fms_io_unstructured_file_unit(filename, funit, domain)
Find the file unit for an inputted file, searching for its variants. If the file is not found,...
subroutine mpp_get_info(unit, ndim, nvar, natt, ntime)
Get some general information about a file.
Definition: mpp_io_util.inc:33
subroutine mpp_get_fields(unit, variables)
Copy variable information from file (excluding data)
subroutine mpp_get_axes(unit, axes, time_axis)
Copy variable information from file (excluding data)
subroutine mpp_sync_self(pelist, check, request, msg_size, msg_type)
This is to check if current PE's outstanding puts are complete but we can't use shmem_fence because w...
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:407