FMS  2024.03
Flexible Modeling System
compute_global_checksum.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 !> @file
20 !> @brief Routines for calculating variable checksums across pes for the @ref compute_global_checksum interface
21 
22 !> @addtogroup fms_netcdf_domain_io_mod
23 !> @{
24 
25 !> @briefs Calculates a variable's checksum across all ranks in the current pelist.
26 !! @return A hex string containing the checksum.
27 function compute_global_checksum_2d(fileobj, variable_name, variable_data, is_decomposed) &
28  result(chksum)
29 
30  class(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
31  character(len=*), intent(in) :: variable_name !< Variable name.
32  class(*), dimension(:,:), intent(in) :: variable_data !< Data to be checksummed.
33  logical, intent(out) :: is_decomposed !< Flag telling if the variable is decomposed.
34  character(len=32) :: chksum
35 
36  integer :: xdim
37  integer :: ydim
38  type(domain2d), pointer :: io_domain
39  integer :: xpos
40  integer :: ypos
41  integer :: isd
42  integer :: isc
43  integer :: xc_size
44  integer :: jsd
45  integer :: jsc
46  integer :: yc_size
47  logical :: buffer_includes_halos
48  logical :: extra_x
49  logical :: extra_y
50  integer, dimension(2) :: c
51  integer, dimension(2) :: e
52  integer(kind=i4_kind), dimension(:,:), allocatable :: buf_i4_kind
53  integer(kind=i8_kind), dimension(:,:), allocatable :: buf_i8_kind
54  real(kind=r4_kind), dimension(:,:), allocatable :: buf_r4_kind
55  real(kind=r8_kind), dimension(:,:), allocatable :: buf_r8_kind
56  integer(kind=i4_kind) :: fill_i4_kind
57  integer(kind=i8_kind) :: fill_i8_kind
58  real(kind=r4_kind) :: fill_r4_kind
59  real(kind=r8_kind) :: fill_r8_kind
60  integer(kind=i8_kind) :: chksum_val
61 
62  is_decomposed = is_variable_domain_decomposed(fileobj, variable_name, &
63  xindex=xdim, yindex=ydim, &
64  xpos=xpos, ypos=ypos)
65  if (.not. is_decomposed) then
66  chksum = ""
67  return
68  endif
69  io_domain => mpp_get_io_domain(fileobj%domain)
70  call domain_offsets(size(variable_data, xdim), size(variable_data, ydim), fileobj%domain, &
71  xpos, ypos, isd, isc, xc_size, jsd, jsc, &
72  yc_size, buffer_includes_halos, extra_x, extra_y, &
73  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
74  c(:) = 1
75  if (buffer_includes_halos) then
76  !Adjust if the input buffer has room for halos.
77  c(xdim) = isc - isd + 1
78  c(ydim) = jsc - jsd + 1
79  endif
80  e(:) = shape(variable_data)
81  e(xdim) = xc_size
82  e(ydim) = yc_size
83 
84  if (extra_x) then
85  !Adjust sizes since compute domains overlap whe there are non-centered
86  !domain position.
87  e(xdim) = e(xdim) - 1
88  endif
89 
90  if (extra_y) then
91  !Adjust sizes since compute domains overlap whe there are non-centered
92  !domain position.
93  e(ydim) = e(ydim) - 1
94  endif
95 
96  select type (variable_data)
97  type is (integer(kind=i4_kind))
98  call allocate_array(buf_i4_kind, e)
99  call get_array_section(buf_i4_kind, variable_data, c, e)
100  if (get_fill_value(fileobj, variable_name, fill_i4_kind)) then
101  chksum_val = mpp_chksum(buf_i4_kind, mask_val=fill_i4_kind)
102  else
103  chksum_val = mpp_chksum(buf_i4_kind)
104  endif
105  deallocate(buf_i4_kind)
106  type is (integer(kind=i8_kind))
107  call allocate_array(buf_i8_kind, e)
108  call get_array_section(buf_i8_kind, variable_data, c, e)
109  if (get_fill_value(fileobj, variable_name, fill_i8_kind)) then
110  chksum_val = mpp_chksum(buf_i8_kind, mask_val=fill_i8_kind)
111  else
112  chksum_val = mpp_chksum(buf_i8_kind)
113  endif
114  deallocate(buf_i8_kind)
115  type is (real(kind=r4_kind))
116  call allocate_array(buf_r4_kind, e)
117  call get_array_section(buf_r4_kind, variable_data, c, e)
118  if (get_fill_value(fileobj, variable_name, fill_r4_kind)) then
119  chksum_val = mpp_chksum(buf_r4_kind, mask_val=fill_r4_kind)
120  else
121  chksum_val = mpp_chksum(buf_r4_kind)
122  endif
123  deallocate(buf_r4_kind)
124  type is (real(kind=r8_kind))
125  call allocate_array(buf_r8_kind, e)
126  call get_array_section(buf_r8_kind, variable_data, c, e)
127  if (get_fill_value(fileobj, variable_name, fill_r8_kind)) then
128  chksum_val = mpp_chksum(buf_r8_kind, mask_val=fill_r8_kind)
129  else
130  chksum_val = mpp_chksum(buf_r8_kind)
131  endif
132  deallocate(buf_r8_kind)
133  class default
134  call error("unsupported variable type: compute_global_checksum_2d: file: "//trim(fileobj%path)//" variable:"// &
135  & trim(variable_name))
136  end select
137  chksum = ""
138  write(chksum, "(Z16)") chksum_val
139 end function compute_global_checksum_2d
140 
141 
142 !> @briefs Calculates a variable's checksum across all ranks in the current pelist.
143 !! @return A hex string containing the checksum.
144 function compute_global_checksum_3d(fileobj, variable_name, variable_data, is_decomposed) &
145  result(chksum)
146 
147  class(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
148  character(len=*), intent(in) :: variable_name !< Variable name.
149  class(*), dimension(:,:,:), intent(in) :: variable_data !< Data to be checksummed.
150  logical, intent(out) :: is_decomposed !< Flag telling if the variable is decomposed.
151  character(len=32) :: chksum
152 
153  integer :: xdim
154  integer :: ydim
155  type(domain2d), pointer :: io_domain
156  integer :: xpos
157  integer :: ypos
158  integer :: isd
159  integer :: isc
160  integer :: xc_size
161  integer :: jsd
162  integer :: jsc
163  integer :: yc_size
164  logical :: buffer_includes_halos
165  logical :: extra_x
166  logical :: extra_y
167  integer, dimension(3) :: c
168  integer, dimension(3) :: e
169  integer(kind=i4_kind), dimension(:,:,:), allocatable :: buf_i4_kind
170  integer(kind=i8_kind), dimension(:,:,:), allocatable :: buf_i8_kind
171  real(kind=r4_kind), dimension(:,:,:), allocatable :: buf_r4_kind
172  real(kind=r8_kind), dimension(:,:,:), allocatable :: buf_r8_kind
173  integer(kind=i4_kind) :: fill_i4_kind
174  integer(kind=i8_kind) :: fill_i8_kind
175  real(kind=r4_kind) :: fill_r4_kind
176  real(kind=r8_kind) :: fill_r8_kind
177  integer(kind=i8_kind) :: chksum_val
178 
179  is_decomposed = is_variable_domain_decomposed(fileobj, variable_name, &
180  xindex=xdim, yindex=ydim, &
181  xpos=xpos, ypos=ypos)
182  if (.not. is_decomposed) then
183  chksum = ""
184  return
185  endif
186  io_domain => mpp_get_io_domain(fileobj%domain)
187  call domain_offsets(size(variable_data, xdim), size(variable_data, ydim), fileobj%domain, &
188  xpos, ypos, isd, isc, xc_size, jsd, jsc, &
189  yc_size, buffer_includes_halos, extra_x, extra_y, &
190  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
191  c(:) = 1
192  if (buffer_includes_halos) then
193  !Adjust if the input buffer has room for halos.
194  c(xdim) = isc - isd + 1
195  c(ydim) = jsc - jsd + 1
196  endif
197  e(:) = shape(variable_data)
198  e(xdim) = xc_size
199  e(ydim) = yc_size
200 
201  if (extra_x) then
202  !Adjust sizes since compute domains overlap whe there are non-centered
203  !domain position.
204  e(xdim) = e(xdim) - 1
205  endif
206 
207  if (extra_y) then
208  !Adjust sizes since compute domains overlap whe there are non-centered
209  !domain position.
210  e(ydim) = e(ydim) - 1
211  endif
212  select type (variable_data)
213  type is (integer(kind=i4_kind))
214  call allocate_array(buf_i4_kind, e)
215  call get_array_section(buf_i4_kind, variable_data, c, e)
216  if (get_fill_value(fileobj, variable_name, fill_i4_kind)) then
217  chksum_val = mpp_chksum(buf_i4_kind, mask_val=fill_i4_kind)
218  else
219  chksum_val = mpp_chksum(buf_i4_kind)
220  endif
221  deallocate(buf_i4_kind)
222  type is (integer(kind=i8_kind))
223  call allocate_array(buf_i8_kind, e)
224  call get_array_section(buf_i8_kind, variable_data, c, e)
225  if (get_fill_value(fileobj, variable_name, fill_i8_kind)) then
226  chksum_val = mpp_chksum(buf_i8_kind, mask_val=fill_i8_kind)
227  else
228  chksum_val = mpp_chksum(buf_i8_kind)
229  endif
230  deallocate(buf_i8_kind)
231  type is (real(kind=r4_kind))
232  call allocate_array(buf_r4_kind, e)
233  call get_array_section(buf_r4_kind, variable_data, c, e)
234  if (get_fill_value(fileobj, variable_name, fill_r4_kind)) then
235  chksum_val = mpp_chksum(buf_r4_kind, mask_val=fill_r4_kind)
236  else
237  chksum_val = mpp_chksum(buf_r4_kind)
238  endif
239  deallocate(buf_r4_kind)
240  type is (real(kind=r8_kind))
241  call allocate_array(buf_r8_kind, e)
242  call get_array_section(buf_r8_kind, variable_data, c, e)
243  if (get_fill_value(fileobj, variable_name, fill_r8_kind)) then
244  chksum_val = mpp_chksum(buf_r8_kind, mask_val=fill_r8_kind)
245  else
246  chksum_val = mpp_chksum(buf_r8_kind)
247  endif
248  deallocate(buf_r8_kind)
249  class default
250  call error("unsupported variable type: compute_global_checksum_3d: file: "//trim(fileobj%path)//" variable:"// &
251  & trim(variable_name))
252  end select
253  chksum = ""
254  write(chksum, "(Z16)") chksum_val
255 end function compute_global_checksum_3d
256 
257 
258 !> @briefs Calculates a variable's checksum across all ranks in the current pelist.
259 !! @return A hex string containing the checksum.
260 function compute_global_checksum_4d(fileobj, variable_name, variable_data, is_decomposed) &
261  result(chksum)
262 
263  class(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
264  character(len=*), intent(in) :: variable_name !< Variable name.
265  class(*), dimension(:,:,:,:), intent(in) :: variable_data !< Data to be checksummed.
266  logical, intent(out) :: is_decomposed !< Flag telling if the variable is decomposed.
267  character(len=32) :: chksum
268 
269  integer :: xdim
270  integer :: ydim
271  type(domain2d), pointer :: io_domain
272  integer :: xpos
273  integer :: ypos
274  integer :: isd
275  integer :: isc
276  integer :: xc_size
277  integer :: jsd
278  integer :: jsc
279  integer :: yc_size
280  logical :: buffer_includes_halos
281  logical :: extra_x
282  logical :: extra_y
283  integer, dimension(4) :: c
284  integer, dimension(4) :: e
285  integer(kind=i4_kind), dimension(:,:,:,:), allocatable :: buf_i4_kind
286  integer(kind=i8_kind), dimension(:,:,:,:), allocatable :: buf_i8_kind
287  real(kind=r4_kind), dimension(:,:,:,:), allocatable :: buf_r4_kind
288  real(kind=r8_kind), dimension(:,:,:,:), allocatable :: buf_r8_kind
289  integer(kind=i4_kind) :: fill_i4_kind
290  integer(kind=i8_kind) :: fill_i8_kind
291  real(kind=r4_kind) :: fill_r4_kind
292  real(kind=r8_kind) :: fill_r8_kind
293  integer(kind=i8_kind) :: chksum_val
294 
295  is_decomposed = is_variable_domain_decomposed(fileobj, variable_name, &
296  xindex=xdim, yindex=ydim, &
297  xpos=xpos, ypos=ypos)
298  if (.not. is_decomposed) then
299  chksum = ""
300  return
301  endif
302  io_domain => mpp_get_io_domain(fileobj%domain)
303  call domain_offsets(size(variable_data, xdim), size(variable_data, ydim), fileobj%domain, &
304  xpos, ypos, isd, isc, xc_size, jsd, jsc, &
305  yc_size, buffer_includes_halos, extra_x, extra_y, &
306  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
307  c(:) = 1
308  if (buffer_includes_halos) then
309  !Adjust if the input buffer has room for halos.
310  c(xdim) = isc - isd + 1
311  c(ydim) = jsc - jsd + 1
312  endif
313  e(:) = shape(variable_data)
314  e(xdim) = xc_size
315  e(ydim) = yc_size
316 
317  if (extra_x) then
318  !Adjust sizes since compute domains overlap whe there are non-centered
319  !domain position.
320  e(xdim) = e(xdim) - 1
321  endif
322 
323  if (extra_y) then
324  !Adjust sizes since compute domains overlap whe there are non-centered
325  !domain position.
326  e(ydim) = e(ydim) - 1
327  endif
328 
329  select type (variable_data)
330  type is (integer(kind=i4_kind))
331  call allocate_array(buf_i4_kind, e)
332  call get_array_section(buf_i4_kind, variable_data, c, e)
333  if (get_fill_value(fileobj, variable_name, fill_i4_kind)) then
334  chksum_val = mpp_chksum(buf_i4_kind, mask_val=fill_i4_kind)
335  else
336  chksum_val = mpp_chksum(buf_i4_kind)
337  endif
338  deallocate(buf_i4_kind)
339  type is (integer(kind=i8_kind))
340  call allocate_array(buf_i8_kind, e)
341  call get_array_section(buf_i8_kind, variable_data, c, e)
342  if (get_fill_value(fileobj, variable_name, fill_i8_kind)) then
343  chksum_val = mpp_chksum(buf_i8_kind, mask_val=fill_i8_kind)
344  else
345  chksum_val = mpp_chksum(buf_i8_kind)
346  endif
347  deallocate(buf_i8_kind)
348  type is (real(kind=r4_kind))
349  call allocate_array(buf_r4_kind, e)
350  call get_array_section(buf_r4_kind, variable_data, c, e)
351  if (get_fill_value(fileobj, variable_name, fill_r4_kind)) then
352  chksum_val = mpp_chksum(buf_r4_kind, mask_val=fill_r4_kind)
353  else
354  chksum_val = mpp_chksum(buf_r4_kind)
355  endif
356  deallocate(buf_r4_kind)
357  type is (real(kind=r8_kind))
358  call allocate_array(buf_r8_kind, e)
359  call get_array_section(buf_r8_kind, variable_data, c, e)
360  if (get_fill_value(fileobj, variable_name, fill_r8_kind)) then
361  chksum_val = mpp_chksum(buf_r8_kind, mask_val=fill_r8_kind)
362  else
363  chksum_val = mpp_chksum(buf_r8_kind)
364  endif
365  deallocate(buf_r8_kind)
366  class default
367  call error("unsupported variable type: compute_global_checksum_4d: file: "//trim(fileobj%path)//" variable:"// &
368  & trim(variable_name))
369  end select
370  chksum = ""
371  write(chksum, "(Z16)") chksum_val
372 end function compute_global_checksum_4d
373 !> @}
character(len=32) function compute_global_checksum_3d(fileobj, variable_name, variable_data, is_decomposed)
@briefs Calculates a variable's checksum across all ranks in the current pelist.
character(len=32) function compute_global_checksum_4d(fileobj, variable_name, variable_data, is_decomposed)
@briefs Calculates a variable's checksum across all ranks in the current pelist.
character(len=32) function compute_global_checksum_2d(fileobj, variable_name, variable_data, is_decomposed)
@briefs Calculates a variable's checksum across all ranks in the current pelist.
type(domain2d) function, pointer mpp_get_io_domain(domain)
Set user stack size.