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