6 use mom_coms,
only : pe_here, root_pe, num_pes, sum_across_pes
7 use mom_coms,
only : min_across_pes, max_across_pes
13 use iso_fortran_env,
only: error_unit
15 implicit none ;
private
17 public :: chksum0, zchksum
20 public :: mom_checksums_init
24 module procedure chksum_pair_h_2d, chksum_pair_h_3d
29 module procedure chksum_uv_2d, chksum_uv_3d
34 module procedure chksum_u_2d, chksum_u_3d
39 module procedure chksum_v_2d, chksum_v_3d
44 module procedure chksum_pair_b_2d, chksum_pair_b_3d
49 module procedure chksum_h_2d, chksum_h_3d
54 module procedure chksum_b_2d, chksum_b_3d
59 module procedure chksum_b_2d, chksum_b_3d
64 module procedure chksum1d, chksum2d, chksum3d
69 module procedure chk_sum_msg1, chk_sum_msg2, chk_sum_msg3, chk_sum_msg5
74 module procedure is_nan_0d, is_nan_1d, is_nan_2d, is_nan_3d
77 integer,
parameter :: bc_modulus = 1000000000
78 integer,
parameter :: default_shift=0
79 logical :: calculatestatistics=.true.
80 logical :: writechksums=.true.
81 logical :: checkfornans=.true.
87 subroutine chksum0(scalar, mesg, scale, logunit)
88 real,
intent(in) :: scalar
89 character(len=*),
intent(in) :: mesg
90 real,
optional,
intent(in) :: scale
91 integer,
optional,
intent(in) :: logunit
98 if (checkfornans .and.
is_nan(scalar)) &
99 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
101 scaling = 1.0 ;
if (
present(scale)) scaling = scale
102 iounit = error_unit;
if(
present(logunit)) iounit = logunit
104 if (calculatestatistics)
then
105 rs = scaling * scalar
107 call chk_sum_msg(
" scalar:", rs, rs, rs, mesg, iounit)
110 if (.not. writechksums)
return
112 bc = mod(bitcount(abs(scaling * scalar)), bc_modulus)
116 end subroutine chksum0
120 subroutine zchksum(array, mesg, scale, logunit)
121 real,
dimension(:),
intent(in) :: array
122 character(len=*),
intent(in) :: mesg
123 real,
optional,
intent(in) :: scale
124 integer,
optional,
intent(in) :: logunit
126 real,
allocatable,
dimension(:) :: rescaled_array
130 real :: amean, amin, amax
133 if (checkfornans)
then
135 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
138 scaling = 1.0 ;
if (
present(scale)) scaling = scale
139 iounit = error_unit;
if(
present(logunit)) iounit = logunit
141 if (calculatestatistics)
then
142 if (
present(scale))
then
143 allocate(rescaled_array(lbound(array,1):ubound(array,1)))
144 rescaled_array(:) = 0.0
145 do k=1,
size(array, 1)
146 rescaled_array(k) = scale * array(k)
149 call substats(rescaled_array, amean, amin, amax)
150 deallocate(rescaled_array)
152 call substats(array, amean, amin, amax)
156 call chk_sum_msg(
" column:", amean, amin, amax, mesg, iounit)
159 if (.not. writechksums)
return
161 bc0 = subchk(array, scaling)
162 if (is_root_pe())
call chk_sum_msg(
" column:", bc0, mesg, iounit)
166 integer function subchk(array, scale)
167 real,
dimension(:),
intent(in) :: array
168 real,
intent(in) :: scale
171 do k=lbound(array, 1), ubound(array, 1)
172 bc = bitcount(abs(scale * array(k)))
175 subchk=mod(subchk, bc_modulus)
178 subroutine substats(array, aMean, aMin, aMax)
179 real,
dimension(:),
intent(in) :: array
180 real,
intent(out) :: amean, amin, amax
187 do k=lbound(array,1), ubound(array,1)
188 amin = min(amin, array(k))
189 amax = max(amax, array(k))
192 amean = sum(array(:)) / real(n)
193 end subroutine substats
195 end subroutine zchksum
198 subroutine chksum_pair_h_2d(mesg, arrayA, arrayB, HI, haloshift, omit_corners, &
200 character(len=*),
intent(in) :: mesg
202 real,
dimension(HI%isd:,HI%jsd:),
intent(in) :: arrayA
203 real,
dimension(HI%isd:,HI%jsd:),
intent(in) :: arrayB
204 integer,
optional,
intent(in) :: haloshift
205 logical,
optional,
intent(in) :: omit_corners
206 real,
optional,
intent(in) :: scale
207 integer,
optional,
intent(in) :: logunit
209 if (
present(haloshift))
then
210 call chksum_h_2d(arraya,
'x '//mesg, hi, haloshift, omit_corners, &
211 scale=scale, logunit=logunit)
212 call chksum_h_2d(arrayb,
'y '//mesg, hi, haloshift, omit_corners, &
213 scale=scale, logunit=logunit)
215 call chksum_h_2d(arraya,
'x '//mesg, hi, scale=scale, logunit=logunit)
216 call chksum_h_2d(arrayb,
'y '//mesg, hi, scale=scale, logunit=logunit)
219 end subroutine chksum_pair_h_2d
222 subroutine chksum_pair_h_3d(mesg, arrayA, arrayB, HI, haloshift, omit_corners, &
224 character(len=*),
intent(in) :: mesg
226 real,
dimension(HI%isd:,HI%jsd:, :),
intent(in) :: arrayA
227 real,
dimension(HI%isd:,HI%jsd:, :),
intent(in) :: arrayB
228 integer,
optional,
intent(in) :: haloshift
229 logical,
optional,
intent(in) :: omit_corners
230 real,
optional,
intent(in) :: scale
231 integer,
optional,
intent(in) :: logunit
233 if (
present(haloshift))
then
234 call chksum_h_3d(arraya,
'x '//mesg, hi, haloshift, omit_corners, &
235 scale=scale, logunit=logunit)
236 call chksum_h_3d(arrayb,
'y '//mesg, hi, haloshift, omit_corners, &
237 scale=scale, logunit=logunit)
239 call chksum_h_3d(arraya,
'x '//mesg, hi, scale=scale, logunit=logunit)
240 call chksum_h_3d(arrayb,
'y '//mesg, hi, scale=scale, logunit=logunit)
243 end subroutine chksum_pair_h_3d
246 subroutine chksum_h_2d(array, mesg, HI, haloshift, omit_corners, scale, logunit)
248 real,
dimension(HI%isd:,HI%jsd:),
intent(in) :: array
249 character(len=*),
intent(in) :: mesg
250 integer,
optional,
intent(in) :: haloshift
251 logical,
optional,
intent(in) :: omit_corners
252 real,
optional,
intent(in) :: scale
253 integer,
optional,
intent(in) :: logunit
255 real,
allocatable,
dimension(:,:) :: rescaled_array
259 real :: aMean, aMin, aMax
260 integer :: bc0, bcSW, bcSE, bcNW, bcNE, hshift
261 integer :: bcN, bcS, bcE, bcW
262 logical :: do_corners
264 if (checkfornans)
then
265 if (
is_nan(array(hi%isc:hi%iec,hi%jsc:hi%jec))) &
266 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
271 scaling = 1.0 ;
if (
present(scale)) scaling = scale
272 iounit = error_unit;
if(
present(logunit)) iounit = logunit
274 if (calculatestatistics)
then
275 if (
present(scale))
then
276 allocate( rescaled_array(lbound(array,1):ubound(array,1), &
277 lbound(array,2):ubound(array,2)) )
278 rescaled_array(:,:) = 0.0
279 do j=hi%jsc,hi%jec ;
do i=hi%isc,hi%iec
280 rescaled_array(i,j) = scale*array(i,j)
282 call substats(hi, rescaled_array, amean, amin, amax)
283 deallocate(rescaled_array)
285 call substats(hi, array, amean, amin, amax)
289 call chk_sum_msg(
"h-point:", amean, amin, amax, mesg, iounit)
292 if (.not.writechksums)
return
294 hshift = default_shift
295 if (
present(haloshift)) hshift = haloshift
296 if (hshift<0) hshift = hi%ied-hi%iec
298 if ( hi%isc-hshift<hi%isd .or. hi%iec+hshift>hi%ied .or. &
299 hi%jsc-hshift<hi%jsd .or. hi%jec+hshift>hi%jed )
then
300 write(0,*)
'chksum_h_2d: haloshift =',hshift
301 write(0,*)
'chksum_h_2d: isd,isc,iec,ied=',hi%isd,hi%isc,hi%iec,hi%ied
302 write(0,*)
'chksum_h_2d: jsd,jsc,jec,jed=',hi%jsd,hi%jsc,hi%jec,hi%jed
303 call chksum_error(fatal,
'Error in chksum_h_2d '//trim(mesg))
306 bc0 = subchk(array, hi, 0, 0, scaling)
309 if (is_root_pe())
call chk_sum_msg(
"h-point:", bc0, mesg, iounit)
313 do_corners = .true. ;
if (
present(omit_corners)) do_corners = .not.omit_corners
316 bcsw = subchk(array, hi, -hshift, -hshift, scaling)
317 bcse = subchk(array, hi, hshift, -hshift, scaling)
318 bcnw = subchk(array, hi, -hshift, hshift, scaling)
319 bcne = subchk(array, hi, hshift, hshift, scaling)
322 call chk_sum_msg(
"h-point:", bc0, bcsw, bcse, bcnw, bcne, mesg, iounit)
324 bcs = subchk(array, hi, 0, -hshift, scaling)
325 bce = subchk(array, hi, hshift, 0, scaling)
326 bcw = subchk(array, hi, -hshift, 0, scaling)
327 bcn = subchk(array, hi, 0, hshift, scaling)
330 call chk_sum_msg_nsew(
"h-point:", bc0, bcn, bcs, bce, bcw, mesg, iounit)
334 integer function subchk(array, HI, di, dj, scale)
336 real,
dimension(HI%isd:,HI%jsd:),
intent(in) :: array
337 integer,
intent(in) :: di
338 integer,
intent(in) :: dj
339 real,
intent(in) :: scale
342 do j=hi%jsc+dj,hi%jec+dj;
do i=hi%isc+di,hi%iec+di
343 bc = bitcount(abs(scale*array(i,j)))
346 call sum_across_pes(subchk)
347 subchk=mod(subchk, bc_modulus)
350 subroutine substats(HI, array, aMean, aMin, aMax)
352 real,
dimension(HI%isd:,HI%jsd:),
intent(in) :: array
353 real,
intent(out) :: aMean, aMin, aMax
357 amin = array(hi%isc,hi%jsc)
358 amax = array(hi%isc,hi%jsc)
360 do j=hi%jsc,hi%jec ;
do i=hi%isc,hi%iec
361 amin = min(amin, array(i,j))
362 amax = max(amax, array(i,j))
366 call sum_across_pes(n)
367 call min_across_pes(amin)
368 call max_across_pes(amax)
369 amean = amean / real(n)
370 end subroutine substats
372 end subroutine chksum_h_2d
375 subroutine chksum_pair_b_2d(mesg, arrayA, arrayB, HI, haloshift, symmetric, &
376 omit_corners, scale, logunit)
377 character(len=*),
intent(in) :: mesg
379 real,
dimension(HI%isd:,HI%jsd:),
intent(in) :: arrayA
380 real,
dimension(HI%isd:,HI%jsd:),
intent(in) :: arrayB
381 logical,
optional,
intent(in) :: symmetric
383 integer,
optional,
intent(in) :: haloshift
384 logical,
optional,
intent(in) :: omit_corners
385 real,
optional,
intent(in) :: scale
386 integer,
optional,
intent(in) :: logunit
390 sym = .false. ;
if (
present(symmetric)) sym = symmetric
392 if (
present(haloshift))
then
393 call chksum_b_2d(arraya,
'x '//mesg, hi, haloshift, symmetric=sym, &
394 omit_corners=omit_corners, scale=scale, logunit=logunit)
395 call chksum_b_2d(arrayb,
'y '//mesg, hi, haloshift, symmetric=sym, &
396 omit_corners=omit_corners, scale=scale, logunit=logunit)
398 call chksum_b_2d(arraya,
'x '//mesg, hi, symmetric=sym, scale=scale, &
400 call chksum_b_2d(arrayb,
'y '//mesg, hi, symmetric=sym, scale=scale, &
404 end subroutine chksum_pair_b_2d
407 subroutine chksum_pair_b_3d(mesg, arrayA, arrayB, HI, haloshift, symmetric, &
408 omit_corners, scale, logunit)
409 character(len=*),
intent(in) :: mesg
411 real,
dimension(HI%IsdB:,HI%JsdB:, :),
intent(in) :: arrayA
412 real,
dimension(HI%IsdB:,HI%JsdB:, :),
intent(in) :: arrayB
413 integer,
optional,
intent(in) :: haloshift
414 logical,
optional,
intent(in) :: symmetric
416 logical,
optional,
intent(in) :: omit_corners
417 real,
optional,
intent(in) :: scale
418 integer,
optional,
intent(in) :: logunit
422 if (
present(haloshift))
then
423 call chksum_b_3d(arraya,
'x '//mesg, hi, haloshift, symmetric, &
424 omit_corners, scale=scale, logunit=logunit)
425 call chksum_b_3d(arrayb,
'y '//mesg, hi, haloshift, symmetric, &
426 omit_corners, scale=scale, logunit=logunit)
428 call chksum_b_3d(arraya,
'x '//mesg, hi, symmetric=symmetric, scale=scale, &
430 call chksum_b_3d(arrayb,
'y '//mesg, hi, symmetric=symmetric, scale=scale, &
434 end subroutine chksum_pair_b_3d
437 subroutine chksum_b_2d(array, mesg, HI, haloshift, symmetric, omit_corners, &
440 real,
dimension(HI%IsdB:,HI%JsdB:), &
442 character(len=*),
intent(in) :: mesg
443 integer,
optional,
intent(in) :: haloshift
444 logical,
optional,
intent(in) :: symmetric
446 logical,
optional,
intent(in) :: omit_corners
447 real,
optional,
intent(in) :: scale
448 integer,
optional,
intent(in) :: logunit
450 real,
allocatable,
dimension(:,:) :: rescaled_array
453 integer :: i, j, Is, Js
454 real :: aMean, aMin, aMax
455 integer :: bc0, bcSW, bcSE, bcNW, bcNE, hshift
456 integer :: bcN, bcS, bcE, bcW
457 logical :: do_corners, sym, sym_stats
459 if (checkfornans)
then
460 if (
is_nan(array(hi%IscB:hi%IecB,hi%JscB:hi%JecB))) &
461 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
466 scaling = 1.0 ;
if (
present(scale)) scaling = scale
467 iounit = error_unit;
if(
present(logunit)) iounit = logunit
468 sym_stats = .false. ;
if (
present(symmetric)) sym_stats = symmetric
469 if (
present(haloshift))
then ;
if (haloshift > 0) sym_stats = .true. ;
endif
471 if (calculatestatistics)
then
472 if (
present(scale))
then
473 allocate( rescaled_array(lbound(array,1):ubound(array,1), &
474 lbound(array,2):ubound(array,2)) )
475 rescaled_array(:,:) = 0.0
476 is = hi%isc ;
if (sym_stats) is = hi%isc-1
477 js = hi%jsc ;
if (sym_stats) js = hi%jsc-1
478 do j=js,hi%JecB ;
do i=is,hi%IecB
479 rescaled_array(i,j) = scale*array(i,j)
481 call substats(hi, rescaled_array, sym_stats, amean, amin, amax)
482 deallocate(rescaled_array)
484 call substats(hi, array, sym_stats, amean, amin, amax)
487 call chk_sum_msg(
"B-point:", amean, amin, amax, mesg, iounit)
490 if (.not.writechksums)
return
492 hshift = default_shift
493 if (
present(haloshift)) hshift = haloshift
494 if (hshift<0) hshift = hi%ied-hi%iec
496 if ( hi%iscB-hshift<hi%isdB .or. hi%iecB+hshift>hi%iedB .or. &
497 hi%jscB-hshift<hi%jsdB .or. hi%jecB+hshift>hi%jedB )
then
498 write(0,*)
'chksum_B_2d: haloshift =',hshift
499 write(0,*)
'chksum_B_2d: isd,isc,iec,ied=',hi%isdB,hi%iscB,hi%iecB,hi%iedB
500 write(0,*)
'chksum_B_2d: jsd,jsc,jec,jed=',hi%jsdB,hi%jscB,hi%jecB,hi%jedB
501 call chksum_error(fatal,
'Error in chksum_B_2d '//trim(mesg))
504 bc0 = subchk(array, hi, 0, 0, scaling)
506 sym = .false. ;
if (
present(symmetric)) sym = symmetric
508 if ((hshift==0) .and. .not.sym)
then
509 if (is_root_pe())
call chk_sum_msg(
"B-point:", bc0, mesg, iounit)
513 do_corners = .true. ;
if (
present(omit_corners)) do_corners = .not.omit_corners
517 bcsw = subchk(array, hi, -hshift-1, -hshift-1, scaling)
518 bcse = subchk(array, hi, hshift, -hshift-1, scaling)
519 bcnw = subchk(array, hi, -hshift-1, hshift, scaling)
521 bcsw = subchk(array, hi, -hshift, -hshift, scaling)
522 bcse = subchk(array, hi, hshift, -hshift, scaling)
523 bcnw = subchk(array, hi, -hshift, hshift, scaling)
525 bcne = subchk(array, hi, hshift, hshift, scaling)
528 call chk_sum_msg(
"B-point:", bc0, bcsw, bcse, bcnw, bcne, mesg, iounit)
530 bcs = subchk(array, hi, 0, -hshift, scaling)
531 bce = subchk(array, hi, hshift, 0, scaling)
532 bcw = subchk(array, hi, -hshift, 0, scaling)
533 bcn = subchk(array, hi, 0, hshift, scaling)
536 call chk_sum_msg_nsew(
"B-point:", bc0, bcn, bcs, bce, bcw, mesg, iounit)
541 integer function subchk(array, HI, di, dj, scale)
543 real,
dimension(HI%IsdB:,HI%JsdB:),
intent(in) :: array
544 integer,
intent(in) :: di
545 integer,
intent(in) :: dj
546 real,
intent(in) :: scale
550 do j=hi%jsc+dj,hi%jec+dj;
do i=hi%isc+di,hi%iec+di
551 bc = bitcount(abs(scale*array(i,j)))
554 call sum_across_pes(subchk)
555 subchk=mod(subchk, bc_modulus)
558 subroutine substats(HI, array, sym_stats, aMean, aMin, aMax)
560 real,
dimension(HI%IsdB:,HI%JsdB:),
intent(in) :: array
561 logical,
intent(in) :: sym_stats
563 real,
intent(out) :: aMean, aMin, aMax
565 integer :: i, j, n, IsB, JsB
567 isb = hi%isc ;
if (sym_stats) isb = hi%isc-1
568 jsb = hi%jsc ;
if (sym_stats) jsb = hi%jsc-1
570 amin = array(hi%isc,hi%jsc) ; amax = amin
571 do j=jsb,hi%JecB ;
do i=isb,hi%IecB
572 amin = min(amin, array(i,j))
573 amax = max(amax, array(i,j))
577 n = (1 + hi%jec - hi%jsc) * (1 + hi%iec - hi%isc)
578 call sum_across_pes(n)
579 call min_across_pes(amin)
580 call max_across_pes(amax)
581 amean = amean / real(n)
582 end subroutine substats
584 end subroutine chksum_b_2d
587 subroutine chksum_uv_2d(mesg, arrayU, arrayV, HI, haloshift, symmetric, &
588 omit_corners, scale, logunit)
589 character(len=*),
intent(in) :: mesg
591 real,
dimension(HI%IsdB:,HI%jsd:),
intent(in) :: arrayU
592 real,
dimension(HI%isd:,HI%JsdB:),
intent(in) :: arrayV
593 integer,
optional,
intent(in) :: haloshift
594 logical,
optional,
intent(in) :: symmetric
596 logical,
optional,
intent(in) :: omit_corners
597 real,
optional,
intent(in) :: scale
598 integer,
optional,
intent(in) :: logunit
600 if (
present(haloshift))
then
601 call chksum_u_2d(arrayu,
'u '//mesg, hi, haloshift, symmetric, &
602 omit_corners, scale, logunit=logunit)
603 call chksum_v_2d(arrayv,
'v '//mesg, hi, haloshift, symmetric, &
604 omit_corners, scale, logunit=logunit)
606 call chksum_u_2d(arrayu,
'u '//mesg, hi, symmetric=symmetric, &
608 call chksum_v_2d(arrayv,
'v '//mesg, hi, symmetric=symmetric, &
612 end subroutine chksum_uv_2d
615 subroutine chksum_uv_3d(mesg, arrayU, arrayV, HI, haloshift, symmetric, &
616 omit_corners, scale, logunit)
617 character(len=*),
intent(in) :: mesg
619 real,
dimension(HI%IsdB:,HI%jsd:,:),
intent(in) :: arrayU
620 real,
dimension(HI%isd:,HI%JsdB:,:),
intent(in) :: arrayV
621 integer,
optional,
intent(in) :: haloshift
622 logical,
optional,
intent(in) :: symmetric
624 logical,
optional,
intent(in) :: omit_corners
625 real,
optional,
intent(in) :: scale
626 integer,
optional,
intent(in) :: logunit
628 if (
present(haloshift))
then
629 call chksum_u_3d(arrayu,
'u '//mesg, hi, haloshift, symmetric, &
630 omit_corners, scale, logunit=logunit)
631 call chksum_v_3d(arrayv,
'v '//mesg, hi, haloshift, symmetric, &
632 omit_corners, scale, logunit=logunit)
634 call chksum_u_3d(arrayu,
'u '//mesg, hi, symmetric=symmetric, &
636 call chksum_v_3d(arrayv,
'v '//mesg, hi, symmetric=symmetric, &
640 end subroutine chksum_uv_3d
643 subroutine chksum_u_2d(array, mesg, HI, haloshift, symmetric, omit_corners, &
646 real,
dimension(HI%IsdB:,HI%jsd:),
intent(in) :: array
647 character(len=*),
intent(in) :: mesg
648 integer,
optional,
intent(in) :: haloshift
649 logical,
optional,
intent(in) :: symmetric
651 logical,
optional,
intent(in) :: omit_corners
652 real,
optional,
intent(in) :: scale
653 integer,
optional,
intent(in) :: logunit
655 real,
allocatable,
dimension(:,:) :: rescaled_array
659 real :: aMean, aMin, aMax
660 integer :: bc0, bcSW, bcSE, bcNW, bcNE, hshift
661 integer :: bcN, bcS, bcE, bcW
662 logical :: do_corners, sym, sym_stats
664 if (checkfornans)
then
665 if (
is_nan(array(hi%IscB:hi%IecB,hi%jsc:hi%jec))) &
666 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
671 scaling = 1.0 ;
if (
present(scale)) scaling = scale
672 iounit = error_unit;
if(
present(logunit)) iounit = logunit
673 sym_stats = .false. ;
if (
present(symmetric)) sym_stats = symmetric
674 if (
present(haloshift))
then ;
if (haloshift > 0) sym_stats = .true. ;
endif
676 if (calculatestatistics)
then
677 if (
present(scale))
then
678 allocate( rescaled_array(lbound(array,1):ubound(array,1), &
679 lbound(array,2):ubound(array,2)) )
680 rescaled_array(:,:) = 0.0
681 is = hi%isc ;
if (sym_stats) is = hi%isc-1
682 do j=hi%jsc,hi%jec ;
do i=is,hi%IecB
683 rescaled_array(i,j) = scale*array(i,j)
685 call substats(hi, rescaled_array, sym_stats, amean, amin, amax)
686 deallocate(rescaled_array)
688 call substats(hi, array, sym_stats, amean, amin, amax)
692 call chk_sum_msg(
"u-point:", amean, amin, amax, mesg, iounit)
695 if (.not.writechksums)
return
697 hshift = default_shift
698 if (
present(haloshift)) hshift = haloshift
699 if (hshift<0) hshift = hi%iedB-hi%iecB
701 if ( hi%iscB-hshift<hi%isdB .or. hi%iecB+hshift>hi%iedB .or. &
702 hi%jsc-hshift<hi%jsd .or. hi%jec+hshift>hi%jed )
then
703 write(0,*)
'chksum_u_2d: haloshift =',hshift
704 write(0,*)
'chksum_u_2d: isd,isc,iec,ied=',hi%isdB,hi%iscB,hi%iecB,hi%iedB
705 write(0,*)
'chksum_u_2d: jsd,jsc,jec,jed=',hi%jsd,hi%jsc,hi%jec,hi%jed
706 call chksum_error(fatal,
'Error in chksum_u_2d '//trim(mesg))
709 bc0 = subchk(array, hi, 0, 0, scaling)
711 sym = .false. ;
if (
present(symmetric)) sym = symmetric
713 if ((hshift==0) .and. .not.sym)
then
714 if (is_root_pe())
call chk_sum_msg(
"u-point:", bc0, mesg, iounit)
718 do_corners = .true. ;
if (
present(omit_corners)) do_corners = .not.omit_corners
721 bcw = subchk(array, hi, -hshift-1, 0, scaling)
722 if (is_root_pe())
call chk_sum_msg_w(
"u-point:", bc0, bcw, mesg, iounit)
723 elseif (do_corners)
then
725 bcsw = subchk(array, hi, -hshift-1, -hshift, scaling)
726 bcnw = subchk(array, hi, -hshift-1, hshift, scaling)
728 bcsw = subchk(array, hi, -hshift, -hshift, scaling)
729 bcnw = subchk(array, hi, -hshift, hshift, scaling)
731 bcse = subchk(array, hi, hshift, -hshift, scaling)
732 bcne = subchk(array, hi, hshift, hshift, scaling)
735 call chk_sum_msg(
"u-point:", bc0, bcsw, bcse, bcnw, bcne, mesg, iounit)
737 bcs = subchk(array, hi, 0, -hshift, scaling)
738 bce = subchk(array, hi, hshift, 0, scaling)
740 bcw = subchk(array, hi, -hshift-1, 0, scaling)
742 bcw = subchk(array, hi, -hshift, 0, scaling)
744 bcn = subchk(array, hi, 0, hshift, scaling)
747 call chk_sum_msg_nsew(
"u-point:", bc0, bcn, bcs, bce, bcw, mesg, iounit)
752 integer function subchk(array, HI, di, dj, scale)
754 real,
dimension(HI%IsdB:,HI%jsd:),
intent(in) :: array
755 integer,
intent(in) :: di
756 integer,
intent(in) :: dj
757 real,
intent(in) :: scale
761 do j=hi%jsc+dj,hi%jec+dj;
do i=hi%isc+di,hi%iec+di
762 bc = bitcount(abs(scale*array(i,j)))
765 call sum_across_pes(subchk)
766 subchk=mod(subchk, bc_modulus)
769 subroutine substats(HI, array, sym_stats, aMean, aMin, aMax)
771 real,
dimension(HI%IsdB:,HI%jsd:),
intent(in) :: array
772 logical,
intent(in) :: sym_stats
774 real,
intent(out) :: aMean, aMin, aMax
776 integer :: i, j, n, IsB
778 isb = hi%isc ;
if (sym_stats) isb = hi%isc-1
780 amin = array(hi%isc,hi%jsc) ; amax = amin
781 do j=hi%jsc,hi%jec ;
do i=isb,hi%IecB
782 amin = min(amin, array(i,j))
783 amax = max(amax, array(i,j))
787 n = (1 + hi%jec - hi%jsc) * (1 + hi%iec - hi%isc)
788 call sum_across_pes(n)
789 call min_across_pes(amin)
790 call max_across_pes(amax)
791 amean = amean / real(n)
792 end subroutine substats
794 end subroutine chksum_u_2d
797 subroutine chksum_v_2d(array, mesg, HI, haloshift, symmetric, omit_corners, &
800 real,
dimension(HI%isd:,HI%JsdB:),
intent(in) :: array
801 character(len=*),
intent(in) :: mesg
802 integer,
optional,
intent(in) :: haloshift
803 logical,
optional,
intent(in) :: symmetric
805 logical,
optional,
intent(in) :: omit_corners
806 real,
optional,
intent(in) :: scale
807 integer,
optional,
intent(in) :: logunit
809 real,
allocatable,
dimension(:,:) :: rescaled_array
813 real :: aMean, aMin, aMax
814 integer :: bc0, bcSW, bcSE, bcNW, bcNE, hshift
815 integer :: bcN, bcS, bcE, bcW
816 logical :: do_corners, sym, sym_stats
818 if (checkfornans)
then
819 if (
is_nan(array(hi%isc:hi%iec,hi%JscB:hi%JecB))) &
820 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
825 scaling = 1.0 ;
if (
present(scale)) scaling = scale
826 iounit = error_unit;
if(
present(logunit)) iounit = logunit
827 sym_stats = .false. ;
if (
present(symmetric)) sym_stats = symmetric
828 if (
present(haloshift))
then ;
if (haloshift > 0) sym_stats = .true. ;
endif
830 if (calculatestatistics)
then
831 if (
present(scale))
then
832 allocate( rescaled_array(lbound(array,1):ubound(array,1), &
833 lbound(array,2):ubound(array,2)) )
834 rescaled_array(:,:) = 0.0
835 js = hi%jsc ;
if (sym_stats) js = hi%jsc-1
836 do j=js,hi%JecB ;
do i=hi%isc,hi%iec
837 rescaled_array(i,j) = scale*array(i,j)
839 call substats(hi, rescaled_array, sym_stats, amean, amin, amax)
840 deallocate(rescaled_array)
842 call substats(hi, array, sym_stats, amean, amin, amax)
846 call chk_sum_msg(
"v-point:", amean, amin, amax, mesg, iounit)
849 if (.not.writechksums)
return
851 hshift = default_shift
852 if (
present(haloshift)) hshift = haloshift
853 if (hshift<0) hshift = hi%ied-hi%iec
855 if ( hi%isc-hshift<hi%isd .or. hi%iec+hshift>hi%ied .or. &
856 hi%jscB-hshift<hi%jsdB .or. hi%jecB+hshift>hi%jedB )
then
857 write(0,*)
'chksum_v_2d: haloshift =',hshift
858 write(0,*)
'chksum_v_2d: isd,isc,iec,ied=',hi%isd,hi%isc,hi%iec,hi%ied
859 write(0,*)
'chksum_v_2d: jsd,jsc,jec,jed=',hi%jsdB,hi%jscB,hi%jecB,hi%jedB
860 call chksum_error(fatal,
'Error in chksum_v_2d '//trim(mesg))
863 bc0 = subchk(array, hi, 0, 0, scaling)
865 sym = .false. ;
if (
present(symmetric)) sym = symmetric
867 if ((hshift==0) .and. .not.sym)
then
868 if (is_root_pe())
call chk_sum_msg(
"v-point:", bc0, mesg, iounit)
872 do_corners = .true. ;
if (
present(omit_corners)) do_corners = .not.omit_corners
875 bcs = subchk(array, hi, 0, -hshift-1, scaling)
876 if (is_root_pe())
call chk_sum_msg_s(
"v-point:", bc0, bcs, mesg, iounit)
877 elseif (do_corners)
then
879 bcsw = subchk(array, hi, -hshift, -hshift-1, scaling)
880 bcse = subchk(array, hi, hshift, -hshift-1, scaling)
882 bcsw = subchk(array, hi, -hshift, -hshift, scaling)
883 bcse = subchk(array, hi, hshift, -hshift, scaling)
885 bcnw = subchk(array, hi, -hshift, hshift, scaling)
886 bcne = subchk(array, hi, hshift, hshift, scaling)
889 call chk_sum_msg(
"v-point:", bc0, bcsw, bcse, bcnw, bcne, mesg, iounit)
892 bcs = subchk(array, hi, 0, -hshift-1, scaling)
894 bcs = subchk(array, hi, 0, -hshift, scaling)
896 bce = subchk(array, hi, hshift, 0, scaling)
897 bcw = subchk(array, hi, -hshift, 0, scaling)
898 bcn = subchk(array, hi, 0, hshift, scaling)
901 call chk_sum_msg_nsew(
"v-point:", bc0, bcn, bcs, bce, bcw, mesg, iounit)
906 integer function subchk(array, HI, di, dj, scale)
908 real,
dimension(HI%isd:,HI%JsdB:),
intent(in) :: array
909 integer,
intent(in) :: di
910 integer,
intent(in) :: dj
911 real,
intent(in) :: scale
915 do j=hi%jsc+dj,hi%jec+dj;
do i=hi%isc+di,hi%iec+di
916 bc = bitcount(abs(scale*array(i,j)))
919 call sum_across_pes(subchk)
920 subchk=mod(subchk, bc_modulus)
923 subroutine substats(HI, array, sym_stats, aMean, aMin, aMax)
925 real,
dimension(HI%isd:,HI%JsdB:),
intent(in) :: array
926 logical,
intent(in) :: sym_stats
928 real,
intent(out) :: aMean, aMin, aMax
930 integer :: i, j, n, JsB
932 jsb = hi%jsc ;
if (sym_stats) jsb = hi%jsc-1
934 amin = array(hi%isc,hi%jsc) ; amax = amin
935 do j=jsb,hi%JecB ;
do i=hi%isc,hi%iec
936 amin = min(amin, array(i,j))
937 amax = max(amax, array(i,j))
941 n = (1 + hi%jec - hi%jsc) * (1 + hi%iec - hi%isc)
942 call sum_across_pes(n)
943 call min_across_pes(amin)
944 call max_across_pes(amax)
945 amean = amean / real(n)
946 end subroutine substats
948 end subroutine chksum_v_2d
951 subroutine chksum_h_3d(array, mesg, HI, haloshift, omit_corners, scale, logunit)
953 real,
dimension(HI%isd:,HI%jsd:,:),
intent(in) :: array
954 character(len=*),
intent(in) :: mesg
955 integer,
optional,
intent(in) :: haloshift
956 logical,
optional,
intent(in) :: omit_corners
957 real,
optional,
intent(in) :: scale
958 integer,
optional,
intent(in) :: logunit
960 real,
allocatable,
dimension(:,:,:) :: rescaled_array
964 real :: aMean, aMin, aMax
965 integer :: bc0, bcSW, bcSE, bcNW, bcNE, hshift
966 integer :: bcN, bcS, bcE, bcW
967 logical :: do_corners
969 if (checkfornans)
then
970 if (
is_nan(array(hi%isc:hi%iec,hi%jsc:hi%jec,:))) &
971 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
976 scaling = 1.0 ;
if (
present(scale)) scaling = scale
977 iounit = error_unit;
if(
present(logunit)) iounit = logunit
979 if (calculatestatistics)
then
980 if (
present(scale))
then
981 allocate( rescaled_array(lbound(array,1):ubound(array,1), &
982 lbound(array,2):ubound(array,2), &
983 lbound(array,3):ubound(array,3)) )
984 rescaled_array(:,:,:) = 0.0
985 do k=1,
size(array,3) ;
do j=hi%jsc,hi%jec ;
do i=hi%isc,hi%iec
986 rescaled_array(i,j,k) = scale*array(i,j,k)
987 enddo ;
enddo ;
enddo
989 call substats(hi, rescaled_array, amean, amin, amax)
990 deallocate(rescaled_array)
992 call substats(hi, array, amean, amin, amax)
996 call chk_sum_msg(
"h-point:", amean, amin, amax, mesg, iounit)
999 if (.not.writechksums)
return
1001 hshift = default_shift
1002 if (
present(haloshift)) hshift = haloshift
1003 if (hshift<0) hshift = hi%ied-hi%iec
1005 if ( hi%isc-hshift<hi%isd .or. hi%iec+hshift>hi%ied .or. &
1006 hi%jsc-hshift<hi%jsd .or. hi%jec+hshift>hi%jed )
then
1007 write(0,*)
'chksum_h_3d: haloshift =',hshift
1008 write(0,*)
'chksum_h_3d: isd,isc,iec,ied=',hi%isd,hi%isc,hi%iec,hi%ied
1009 write(0,*)
'chksum_h_3d: jsd,jsc,jec,jed=',hi%jsd,hi%jsc,hi%jec,hi%jed
1010 call chksum_error(fatal,
'Error in chksum_h_3d '//trim(mesg))
1013 bc0 = subchk(array, hi, 0, 0, scaling)
1016 if (is_root_pe())
call chk_sum_msg(
"h-point:", bc0, mesg, iounit)
1020 do_corners = .true. ;
if (
present(omit_corners)) do_corners = .not.omit_corners
1022 if (do_corners)
then
1023 bcsw = subchk(array, hi, -hshift, -hshift, scaling)
1024 bcse = subchk(array, hi, hshift, -hshift, scaling)
1025 bcnw = subchk(array, hi, -hshift, hshift, scaling)
1026 bcne = subchk(array, hi, hshift, hshift, scaling)
1029 call chk_sum_msg(
"h-point:", bc0, bcsw, bcse, bcnw, bcne, mesg, iounit)
1031 bcs = subchk(array, hi, 0, -hshift, scaling)
1032 bce = subchk(array, hi, hshift, 0, scaling)
1033 bcw = subchk(array, hi, -hshift, 0, scaling)
1034 bcn = subchk(array, hi, 0, hshift, scaling)
1037 call chk_sum_msg_nsew(
"h-point:", bc0, bcn, bcs, bce, bcw, mesg, iounit)
1042 integer function subchk(array, HI, di, dj, scale)
1044 real,
dimension(HI%isd:,HI%jsd:,:),
intent(in) :: array
1045 integer,
intent(in) :: di
1046 integer,
intent(in) :: dj
1047 real,
intent(in) :: scale
1048 integer :: i, j, k, bc
1050 do k=lbound(array,3),ubound(array,3) ;
do j=hi%jsc+dj,hi%jec+dj ;
do i=hi%isc+di,hi%iec+di
1051 bc = bitcount(abs(scale*array(i,j,k)))
1052 subchk = subchk + bc
1053 enddo ;
enddo ;
enddo
1054 call sum_across_pes(subchk)
1055 subchk=mod(subchk, bc_modulus)
1058 subroutine substats(HI, array, aMean, aMin, aMax)
1060 real,
dimension(HI%isd:,HI%jsd:,:),
intent(in) :: array
1061 real,
intent(out) :: aMean, aMin, aMax
1063 integer :: i, j, k, n
1065 amin = array(hi%isc,hi%jsc,1)
1066 amax = array(hi%isc,hi%jsc,1)
1068 do k=lbound(array,3),ubound(array,3) ;
do j=hi%jsc,hi%jec ;
do i=hi%isc,hi%iec
1069 amin = min(amin, array(i,j,k))
1070 amax = max(amax, array(i,j,k))
1072 enddo ;
enddo ;
enddo
1074 call sum_across_pes(n)
1075 call min_across_pes(amin)
1076 call max_across_pes(amax)
1077 amean = amean / real(n)
1078 end subroutine substats
1080 end subroutine chksum_h_3d
1083 subroutine chksum_b_3d(array, mesg, HI, haloshift, symmetric, omit_corners, &
1086 real,
dimension(HI%IsdB:,HI%JsdB:,:),
intent(in) :: array
1087 character(len=*),
intent(in) :: mesg
1088 integer,
optional,
intent(in) :: haloshift
1089 logical,
optional,
intent(in) :: symmetric
1091 logical,
optional,
intent(in) :: omit_corners
1092 real,
optional,
intent(in) :: scale
1093 integer,
optional,
intent(in) :: logunit
1095 real,
allocatable,
dimension(:,:,:) :: rescaled_array
1098 integer :: i, j, k, Is, Js
1099 real :: aMean, aMin, aMax
1100 integer :: bc0, bcSW, bcSE, bcNW, bcNE, hshift
1101 integer :: bcN, bcS, bcE, bcW
1102 logical :: do_corners, sym, sym_stats
1104 if (checkfornans)
then
1105 if (
is_nan(array(hi%IscB:hi%IecB,hi%JscB:hi%JecB,:))) &
1106 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
1111 scaling = 1.0 ;
if (
present(scale)) scaling = scale
1112 iounit = error_unit;
if(
present(logunit)) iounit = logunit
1113 sym_stats = .false. ;
if (
present(symmetric)) sym_stats = symmetric
1114 if (
present(haloshift))
then ;
if (haloshift > 0) sym_stats = .true. ;
endif
1116 if (calculatestatistics)
then
1117 if (
present(scale))
then
1118 allocate( rescaled_array(lbound(array,1):ubound(array,1), &
1119 lbound(array,2):ubound(array,2), &
1120 lbound(array,3):ubound(array,3)) )
1121 rescaled_array(:,:,:) = 0.0
1122 is = hi%isc ;
if (sym_stats) is = hi%isc-1
1123 js = hi%jsc ;
if (sym_stats) js = hi%jsc-1
1124 do k=1,
size(array,3) ;
do j=js,hi%JecB ;
do i=is,hi%IecB
1125 rescaled_array(i,j,k) = scale*array(i,j,k)
1126 enddo ;
enddo ;
enddo
1127 call substats(hi, rescaled_array, sym_stats, amean, amin, amax)
1128 deallocate(rescaled_array)
1130 call substats(hi, array, sym_stats, amean, amin, amax)
1134 call chk_sum_msg(
"B-point:", amean, amin, amax, mesg, iounit)
1137 if (.not.writechksums)
return
1139 hshift = default_shift
1140 if (
present(haloshift)) hshift = haloshift
1141 if (hshift<0) hshift = hi%ied-hi%iec
1143 if ( hi%isc-hshift<hi%isd .or. hi%iec+hshift>hi%ied .or. &
1144 hi%jsc-hshift<hi%jsd .or. hi%jec+hshift>hi%jed )
then
1145 write(0,*)
'chksum_B_3d: haloshift =',hshift
1146 write(0,*)
'chksum_B_3d: isd,isc,iec,ied=',hi%isd,hi%isc,hi%iec,hi%ied
1147 write(0,*)
'chksum_B_3d: jsd,jsc,jec,jed=',hi%jsd,hi%jsc,hi%jec,hi%jed
1148 call chksum_error(fatal,
'Error in chksum_B_3d '//trim(mesg))
1151 bc0 = subchk(array, hi, 0, 0, scaling)
1153 sym = .false. ;
if (
present(symmetric)) sym = symmetric
1155 if ((hshift==0) .and. .not.sym)
then
1156 if (is_root_pe())
call chk_sum_msg(
"B-point:", bc0, mesg, iounit)
1160 do_corners = .true. ;
if (
present(omit_corners)) do_corners = .not.omit_corners
1162 if (do_corners)
then
1164 bcsw = subchk(array, hi, -hshift-1, -hshift-1, scaling)
1165 bcse = subchk(array, hi, hshift, -hshift-1, scaling)
1166 bcnw = subchk(array, hi, -hshift-1, hshift, scaling)
1168 bcsw = subchk(array, hi, -hshift-1, -hshift-1, scaling)
1169 bcse = subchk(array, hi, hshift, -hshift-1, scaling)
1170 bcnw = subchk(array, hi, -hshift-1, hshift, scaling)
1172 bcne = subchk(array, hi, hshift, hshift, scaling)
1175 call chk_sum_msg(
"B-point:", bc0, bcsw, bcse, bcnw, bcne, mesg, iounit)
1178 bcs = subchk(array, hi, 0, -hshift-1, scaling)
1179 bcw = subchk(array, hi, -hshift-1, 0, scaling)
1181 bcs = subchk(array, hi, 0, -hshift, scaling)
1182 bcw = subchk(array, hi, -hshift, 0, scaling)
1184 bce = subchk(array, hi, hshift, 0, scaling)
1185 bcn = subchk(array, hi, 0, hshift, scaling)
1188 call chk_sum_msg_nsew(
"B-point:", bc0, bcn, bcs, bce, bcw, mesg, iounit)
1193 integer function subchk(array, HI, di, dj, scale)
1195 real,
dimension(HI%IsdB:,HI%JsdB:,:),
intent(in) :: array
1196 integer,
intent(in) :: di
1197 integer,
intent(in) :: dj
1198 real,
intent(in) :: scale
1199 integer :: i, j, k, bc
1202 do k=lbound(array,3),ubound(array,3) ;
do j=hi%jsc+dj,hi%jec+dj ;
do i=hi%isc+di,hi%iec+di
1203 bc = bitcount(abs(scale*array(i,j,k)))
1204 subchk = subchk + bc
1205 enddo ;
enddo ;
enddo
1206 call sum_across_pes(subchk)
1207 subchk=mod(subchk, bc_modulus)
1210 subroutine substats(HI, array, sym_stats, aMean, aMin, aMax)
1212 real,
dimension(HI%IsdB:,HI%JsdB:,:),
intent(in) :: array
1213 logical,
intent(in) :: sym_stats
1215 real,
intent(out) :: aMean, aMin, aMax
1217 integer :: i, j, k, n, IsB, JsB
1219 isb = hi%isc ;
if (sym_stats) isb = hi%isc-1
1220 jsb = hi%jsc ;
if (sym_stats) jsb = hi%jsc-1
1222 amin = array(hi%isc,hi%jsc,1) ; amax = amin
1223 do k=lbound(array,3),ubound(array,3) ;
do j=jsb,hi%JecB ;
do i=isb,hi%IecB
1224 amin = min(amin, array(i,j,k))
1225 amax = max(amax, array(i,j,k))
1226 enddo ;
enddo ;
enddo
1228 n = (1 + hi%jec - hi%jsc) * (1 + hi%iec - hi%isc) *
size(array,3)
1229 call sum_across_pes(n)
1230 call min_across_pes(amin)
1231 call max_across_pes(amax)
1232 amean = amean / real(n)
1233 end subroutine substats
1235 end subroutine chksum_b_3d
1238 subroutine chksum_u_3d(array, mesg, HI, haloshift, symmetric, omit_corners, &
1241 real,
dimension(HI%isdB:,HI%Jsd:,:),
intent(in) :: array
1242 character(len=*),
intent(in) :: mesg
1243 integer,
optional,
intent(in) :: haloshift
1244 logical,
optional,
intent(in) :: symmetric
1246 logical,
optional,
intent(in) :: omit_corners
1247 real,
optional,
intent(in) :: scale
1248 integer,
optional,
intent(in) :: logunit
1250 real,
allocatable,
dimension(:,:,:) :: rescaled_array
1253 integer :: i, j, k, Is
1254 real :: aMean, aMin, aMax
1255 integer :: bc0, bcSW, bcSE, bcNW, bcNE, hshift
1256 integer :: bcN, bcS, bcE, bcW
1257 logical :: do_corners, sym, sym_stats
1259 if (checkfornans)
then
1260 if (
is_nan(array(hi%IscB:hi%IecB,hi%jsc:hi%jec,:))) &
1261 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
1266 scaling = 1.0 ;
if (
present(scale)) scaling = scale
1267 iounit = error_unit;
if(
present(logunit)) iounit = logunit
1268 sym_stats = .false. ;
if (
present(symmetric)) sym_stats = symmetric
1269 if (
present(haloshift))
then ;
if (haloshift > 0) sym_stats = .true. ;
endif
1271 if (calculatestatistics)
then
1272 if (
present(scale))
then
1273 allocate( rescaled_array(lbound(array,1):ubound(array,1), &
1274 lbound(array,2):ubound(array,2), &
1275 lbound(array,3):ubound(array,3)) )
1276 rescaled_array(:,:,:) = 0.0
1277 is = hi%isc ;
if (sym_stats) is = hi%isc-1
1278 do k=1,
size(array,3) ;
do j=hi%jsc,hi%jec ;
do i=is,hi%IecB
1279 rescaled_array(i,j,k) = scale*array(i,j,k)
1280 enddo ;
enddo ;
enddo
1281 call substats(hi, rescaled_array, sym_stats, amean, amin, amax)
1282 deallocate(rescaled_array)
1284 call substats(hi, array, sym_stats, amean, amin, amax)
1287 call chk_sum_msg(
"u-point:", amean, amin, amax, mesg, iounit)
1290 if (.not.writechksums)
return
1292 hshift = default_shift
1293 if (
present(haloshift)) hshift = haloshift
1294 if (hshift<0) hshift = hi%ied-hi%iec
1296 if ( hi%isc-hshift<hi%isd .or. hi%iec+hshift>hi%ied .or. &
1297 hi%jsc-hshift<hi%jsd .or. hi%jec+hshift>hi%jed )
then
1298 write(0,*)
'chksum_u_3d: haloshift =',hshift
1299 write(0,*)
'chksum_u_3d: isd,isc,iec,ied=',hi%isd,hi%isc,hi%iec,hi%ied
1300 write(0,*)
'chksum_u_3d: jsd,jsc,jec,jed=',hi%jsd,hi%jsc,hi%jec,hi%jed
1301 call chksum_error(fatal,
'Error in chksum_u_3d '//trim(mesg))
1304 bc0 = subchk(array, hi, 0, 0, scaling)
1306 sym = .false. ;
if (
present(symmetric)) sym = symmetric
1308 if ((hshift==0) .and. .not.sym)
then
1309 if (is_root_pe())
call chk_sum_msg(
"u-point:", bc0, mesg, iounit)
1313 do_corners = .true. ;
if (
present(omit_corners)) do_corners = .not.omit_corners
1316 bcw = subchk(array, hi, -hshift-1, 0, scaling)
1317 if (is_root_pe())
call chk_sum_msg_w(
"u-point:", bc0, bcw, mesg, iounit)
1318 elseif (do_corners)
then
1320 bcsw = subchk(array, hi, -hshift-1, -hshift, scaling)
1321 bcnw = subchk(array, hi, -hshift-1, hshift, scaling)
1323 bcsw = subchk(array, hi, -hshift, -hshift, scaling)
1324 bcnw = subchk(array, hi, -hshift, hshift, scaling)
1326 bcse = subchk(array, hi, hshift, -hshift, scaling)
1327 bcne = subchk(array, hi, hshift, hshift, scaling)
1330 call chk_sum_msg(
"u-point:", bc0, bcsw, bcse, bcnw, bcne, mesg, iounit)
1332 bcs = subchk(array, hi, 0, -hshift, scaling)
1333 bce = subchk(array, hi, hshift, 0, scaling)
1335 bcw = subchk(array, hi, -hshift-1, 0, scaling)
1337 bcw = subchk(array, hi, -hshift, 0, scaling)
1339 bcn = subchk(array, hi, 0, hshift, scaling)
1342 call chk_sum_msg_nsew(
"u-point:", bc0, bcn, bcs, bce, bcw, mesg, iounit)
1347 integer function subchk(array, HI, di, dj, scale)
1349 real,
dimension(HI%IsdB:,HI%jsd:,:),
intent(in) :: array
1350 integer,
intent(in) :: di
1351 integer,
intent(in) :: dj
1352 real,
intent(in) :: scale
1353 integer :: i, j, k, bc
1356 do k=lbound(array,3),ubound(array,3) ;
do j=hi%jsc+dj,hi%jec+dj ;
do i=hi%isc+di,hi%iec+di
1357 bc = bitcount(abs(scale*array(i,j,k)))
1358 subchk = subchk + bc
1359 enddo ;
enddo ;
enddo
1360 call sum_across_pes(subchk)
1361 subchk=mod(subchk, bc_modulus)
1364 subroutine substats(HI, array, sym_stats, aMean, aMin, aMax)
1366 real,
dimension(HI%IsdB:,HI%jsd:,:),
intent(in) :: array
1367 logical,
intent(in) :: sym_stats
1369 real,
intent(out) :: aMean, aMin, aMax
1371 integer :: i, j, k, n, IsB
1373 isb = hi%isc ;
if (sym_stats) isb = hi%isc-1
1375 amin = array(hi%isc,hi%jsc,1) ; amax = amin
1376 do k=lbound(array,3),ubound(array,3) ;
do j=hi%jsc,hi%jec ;
do i=isb,hi%IecB
1377 amin = min(amin, array(i,j,k))
1378 amax = max(amax, array(i,j,k))
1379 enddo ;
enddo ;
enddo
1382 n = (1 + hi%jec - hi%jsc) * (1 + hi%iec - hi%isc) *
size(array,3)
1383 call sum_across_pes(n)
1384 call min_across_pes(amin)
1385 call max_across_pes(amax)
1386 amean = amean / real(n)
1387 end subroutine substats
1389 end subroutine chksum_u_3d
1392 subroutine chksum_v_3d(array, mesg, HI, haloshift, symmetric, omit_corners, &
1395 real,
dimension(HI%isd:,HI%JsdB:,:),
intent(in) :: array
1396 character(len=*),
intent(in) :: mesg
1397 integer,
optional,
intent(in) :: haloshift
1398 logical,
optional,
intent(in) :: symmetric
1400 logical,
optional,
intent(in) :: omit_corners
1401 real,
optional,
intent(in) :: scale
1402 integer,
optional,
intent(in) :: logunit
1404 real,
allocatable,
dimension(:,:,:) :: rescaled_array
1407 integer :: i, j, k, Js
1408 integer :: bc0, bcSW, bcSE, bcNW, bcNE, hshift
1409 integer :: bcN, bcS, bcE, bcW
1410 real :: aMean, aMin, aMax
1411 logical :: do_corners, sym, sym_stats
1413 if (checkfornans)
then
1414 if (
is_nan(array(hi%isc:hi%iec,hi%JscB:hi%JecB,:))) &
1415 call chksum_error(fatal,
'NaN detected: '//trim(mesg))
1420 scaling = 1.0 ;
if (
present(scale)) scaling = scale
1421 iounit = error_unit;
if(
present(logunit)) iounit = logunit
1422 sym_stats = .false. ;
if (
present(symmetric)) sym_stats = symmetric
1423 if (
present(haloshift))
then ;
if (haloshift > 0) sym_stats = .true. ;
endif
1425 if (calculatestatistics)
then
1426 if (
present(scale))
then
1427 allocate( rescaled_array(lbound(array,1):ubound(array,1), &
1428 lbound(array,2):ubound(array,2), &
1429 lbound(array,3):ubound(array,3)) )
1430 rescaled_array(:,:,:) = 0.0
1431 js = hi%jsc ;
if (sym_stats) js = hi%jsc-1
1432 do k=1,
size(array,3) ;
do j=js,hi%JecB ;
do i=hi%isc,hi%iec
1433 rescaled_array(i,j,k) = scale*array(i,j,k)
1434 enddo ;
enddo ;
enddo
1435 call substats(hi, rescaled_array, sym_stats, amean, amin, amax)
1436 deallocate(rescaled_array)
1438 call substats(hi, array, sym_stats, amean, amin, amax)
1441 call chk_sum_msg(
"v-point:", amean, amin, amax, mesg, iounit)
1444 if (.not.writechksums)
return
1446 hshift = default_shift
1447 if (
present(haloshift)) hshift = haloshift
1448 if (hshift<0) hshift = hi%ied-hi%iec
1450 if ( hi%isc-hshift<hi%isd .or. hi%iec+hshift>hi%ied .or. &
1451 hi%jsc-hshift<hi%jsd .or. hi%jec+hshift>hi%jed )
then
1452 write(0,*)
'chksum_v_3d: haloshift =',hshift
1453 write(0,*)
'chksum_v_3d: isd,isc,iec,ied=',hi%isd,hi%isc,hi%iec,hi%ied
1454 write(0,*)
'chksum_v_3d: jsd,jsc,jec,jed=',hi%jsd,hi%jsc,hi%jec,hi%jed
1455 call chksum_error(fatal,
'Error in chksum_v_3d '//trim(mesg))
1458 bc0 = subchk(array, hi, 0, 0, scaling)
1460 sym = .false. ;
if (
present(symmetric)) sym = symmetric
1462 if ((hshift==0) .and. .not.sym)
then
1463 if (is_root_pe())
call chk_sum_msg(
"v-point:", bc0, mesg, iounit)
1467 do_corners = .true. ;
if (
present(omit_corners)) do_corners = .not.omit_corners
1470 bcs = subchk(array, hi, 0, -hshift-1, scaling)
1471 if (is_root_pe())
call chk_sum_msg_s(
"v-point:", bc0, bcs, mesg, iounit)
1472 elseif (do_corners)
then
1474 bcsw = subchk(array, hi, -hshift, -hshift-1, scaling)
1475 bcse = subchk(array, hi, hshift, -hshift-1, scaling)
1477 bcsw = subchk(array, hi, -hshift, -hshift, scaling)
1478 bcse = subchk(array, hi, hshift, -hshift, scaling)
1480 bcnw = subchk(array, hi, -hshift, hshift, scaling)
1481 bcne = subchk(array, hi, hshift, hshift, scaling)
1484 call chk_sum_msg(
"v-point:", bc0, bcsw, bcse, bcnw, bcne, mesg, iounit)
1487 bcs = subchk(array, hi, 0, -hshift-1, scaling)
1489 bcs = subchk(array, hi, 0, -hshift, scaling)
1491 bce = subchk(array, hi, hshift, 0, scaling)
1492 bcw = subchk(array, hi, -hshift, 0, scaling)
1493 bcn = subchk(array, hi, 0, hshift, scaling)
1496 call chk_sum_msg_nsew(
"v-point:", bc0, bcn, bcs, bce, bcw, mesg, iounit)
1501 integer function subchk(array, HI, di, dj, scale)
1503 real,
dimension(HI%isd:,HI%JsdB:,:),
intent(in) :: array
1504 integer,
intent(in) :: di
1505 integer,
intent(in) :: dj
1506 real,
intent(in) :: scale
1507 integer :: i, j, k, bc
1510 do k=lbound(array,3),ubound(array,3) ;
do j=hi%jsc+dj,hi%jec+dj ;
do i=hi%isc+di,hi%iec+di
1511 bc = bitcount(abs(scale*array(i,j,k)))
1512 subchk = subchk + bc
1513 enddo ;
enddo ;
enddo
1514 call sum_across_pes(subchk)
1515 subchk=mod(subchk, bc_modulus)
1519 subroutine substats(HI, array, sym_stats, aMean, aMin, aMax)
1521 real,
dimension(HI%isd:,HI%JsdB:,:),
intent(in) :: array
1522 logical,
intent(in) :: sym_stats
1524 real,
intent(out) :: aMean, aMin, aMax
1526 integer :: i, j, k, n, JsB
1528 jsb = hi%jsc ;
if (sym_stats) jsb = hi%jsc-1
1530 amin = array(hi%isc,hi%jsc,1) ; amax = amin
1531 do k=lbound(array,3),ubound(array,3) ;
do j=jsb,hi%JecB ;
do i=hi%isc,hi%iec
1532 amin = min(amin, array(i,j,k))
1533 amax = max(amax, array(i,j,k))
1534 enddo ;
enddo ;
enddo
1537 n = (1 + hi%jec - hi%jsc) * (1 + hi%iec - hi%isc) *
size(array,3)
1538 call sum_across_pes(n)
1539 call min_across_pes(amin)
1540 call max_across_pes(amax)
1541 amean = amean / real(n)
1542 end subroutine substats
1544 end subroutine chksum_v_3d
1550 subroutine chksum1d(array, mesg, start_i, end_i, compare_PEs)
1551 real,
dimension(:),
intent(in) :: array
1552 character(len=*),
intent(in) :: mesg
1553 integer,
optional,
intent(in) :: start_i
1554 integer,
optional,
intent(in) :: end_i
1555 logical,
optional,
intent(in) :: compare_PEs
1558 integer :: is, ie, i, bc, sum1, sum_bc
1560 real,
allocatable :: sum_here(:)
1565 is = lbound(array,1) ; ie = ubound(array,1)
1566 if (
present(start_i)) is = start_i
1567 if (
present(end_i)) ie = end_i
1568 compare = .true. ;
if (
present(compare_pes)) compare = compare_pes
1570 sum = 0.0 ; sum_bc = 0
1572 sum = sum + array(i)
1573 bc = bitcount(abs(array(i)))
1574 sum_bc = sum_bc + bc
1577 pe_num = pe_here() + 1 - root_pe() ; npes = num_pes()
1578 allocate(sum_here(npes)) ; sum_here(:) = 0.0 ; sum_here(pe_num) = sum
1579 call sum_across_pes(sum_here,npes)
1582 call sum_across_pes(sum1)
1584 if (.not.compare)
then
1586 do i=1,npes ; sum = sum + sum_here(i) ;
enddo
1588 elseif (is_root_pe())
then
1589 if (sum1 /= npes*sum_bc) &
1590 write(0,
'(A40," bitcounts do not match across PEs: ",I12,1X,I12)') &
1591 mesg, sum1, npes*sum_bc
1592 do i=1,npes ;
if (sum /= sum_here(i))
then
1593 write(0,
'(A40," PE ",i4," sum mismatches root_PE: ",3(ES22.13,1X))') &
1594 mesg, i, sum_here(i), sum, sum_here(i)-sum
1597 deallocate(sum_here)
1600 write(0,
'(A50,1X,ES25.16,1X,I12)') mesg, sum, sum_bc
1602 end subroutine chksum1d
1608 subroutine chksum2d(array, mesg)
1610 real,
dimension(:,:) :: array
1611 character(len=*) :: mesg
1613 integer :: xs,xe,ys,ye,i,j,sum1,bc
1616 xs = lbound(array,1) ; xe = ubound(array,1)
1617 ys = lbound(array,2) ; ye = ubound(array,2)
1619 sum = 0.0 ; sum1 = 0
1620 do i=xs,xe ;
do j=ys,ye
1621 bc = bitcount(abs(array(i,j)))
1624 call sum_across_pes(sum1)
1629 write(0,
'(A50,1X,ES25.16,1X,I12)') mesg, sum, sum1
1633 end subroutine chksum2d
1636 subroutine chksum3d(array, mesg)
1638 real,
dimension(:,:,:) :: array
1639 character(len=*) :: mesg
1641 integer :: xs,xe,ys,ye,zs,ze,i,j,k, bc,sum1
1644 xs = lbound(array,1) ; xe = ubound(array,1)
1645 ys = lbound(array,2) ; ye = ubound(array,2)
1646 zs = lbound(array,3) ; ze = ubound(array,3)
1648 sum = 0.0 ; sum1 = 0
1649 do i=xs,xe ;
do j=ys,ye ;
do k=zs,ze
1650 bc = bitcount(abs(array(i,j,k)))
1652 enddo ;
enddo ;
enddo
1654 call sum_across_pes(sum1)
1658 write(0,
'(A50,1X,ES25.16,1X,I12)') mesg, sum, sum1
1662 end subroutine chksum3d
1665 function is_nan_0d(x)
1666 real,
intent(in) :: x
1667 logical :: is_nan_0d
1671 if (((x < 0.0) .and. (x >= 0.0)) .or. &
1672 (.not.(x < 0.0) .and. .not.(x >= 0.0)))
then
1678 end function is_nan_0d
1681 function is_nan_1d(x, skip_mpp)
1682 real,
dimension(:),
intent(in) :: x
1683 logical,
optional,
intent(in) :: skip_mpp
1685 logical :: is_nan_1d
1691 do i = lbound(x,1), ubound(x,1)
1692 if (is_nan_0d(x(i))) n = n + 1
1695 if (
present(skip_mpp)) call_mpp = .not.skip_mpp
1697 if (call_mpp)
call sum_across_pes(n)
1699 if (n>0) is_nan_1d = .true.
1701 end function is_nan_1d
1704 function is_nan_2d(x)
1705 real,
dimension(:,:),
intent(in) :: x
1706 logical :: is_nan_2d
1711 do j = lbound(x,2), ubound(x,2) ;
do i = lbound(x,1), ubound(x,1)
1712 if (is_nan_0d(x(i,j))) n = n + 1
1714 call sum_across_pes(n)
1716 if (n>0) is_nan_2d = .true.
1718 end function is_nan_2d
1721 function is_nan_3d(x)
1722 real,
dimension(:,:,:),
intent(in) :: x
1723 logical :: is_nan_3d
1725 integer :: i, j, k, n
1728 do k = lbound(x,3), ubound(x,3)
1729 do j = lbound(x,2), ubound(x,2) ;
do i = lbound(x,1), ubound(x,1)
1730 if (is_nan_0d(x(i,j,k))) n = n + 1
1733 call sum_across_pes(n)
1735 if (n>0) is_nan_3d = .true.
1737 end function is_nan_3d
1740 subroutine chk_sum_msg1(fmsg, bc0, mesg, iounit)
1741 character(len=*),
intent(in) :: fmsg
1742 character(len=*),
intent(in) :: mesg
1743 integer,
intent(in) :: bc0
1744 integer,
intent(in) :: iounit
1747 write(iounit,
'(A,1(A,I10,X),A)') fmsg,
" c=", bc0, trim(mesg)
1748 end subroutine chk_sum_msg1
1751 subroutine chk_sum_msg5(fmsg, bc0, bcSW, bcSE, bcNW, bcNE, mesg, iounit)
1752 character(len=*),
intent(in) :: fmsg
1753 character(len=*),
intent(in) :: mesg
1754 integer,
intent(in) :: bc0
1755 integer,
intent(in) :: bcSW
1756 integer,
intent(in) :: bcSE
1757 integer,
intent(in) :: bcNW
1758 integer,
intent(in) :: bcNE
1759 integer,
intent(in) :: iounit
1761 if (is_root_pe())
write(iounit,
'(A,5(A,I10,1X),A)') &
1762 fmsg,
" c=", bc0,
"sw=", bcsw,
"se=", bcse,
"nw=", bcnw,
"ne=", bcne, trim(mesg)
1763 end subroutine chk_sum_msg5
1766 subroutine chk_sum_msg_nsew(fmsg, bc0, bcN, bcS, bcE, bcW, mesg, iounit)
1767 character(len=*),
intent(in) :: fmsg
1768 character(len=*),
intent(in) :: mesg
1769 integer,
intent(in) :: bc0
1770 integer,
intent(in) :: bcN
1771 integer,
intent(in) :: bcS
1772 integer,
intent(in) :: bcE
1773 integer,
intent(in) :: bcW
1774 integer,
intent(in) :: iounit
1776 if (is_root_pe())
write(iounit,
'(A,5(A,I10,1X),A)') &
1777 fmsg,
" c=", bc0,
"N=", bcn,
"S=", bcs,
"E=", bce,
"W=", bcw, trim(mesg)
1778 end subroutine chk_sum_msg_nsew
1781 subroutine chk_sum_msg_s(fmsg, bc0, bcS, mesg, iounit)
1782 character(len=*),
intent(in) :: fmsg
1783 character(len=*),
intent(in) :: mesg
1784 integer,
intent(in) :: bc0
1785 integer,
intent(in) :: bcS
1786 integer,
intent(in) :: iounit
1788 if (is_root_pe())
write(iounit,
'(A,2(A,I10,1X),A)') &
1789 fmsg,
" c=", bc0,
"S=", bcs, trim(mesg)
1790 end subroutine chk_sum_msg_s
1793 subroutine chk_sum_msg_w(fmsg, bc0, bcW, mesg, iounit)
1794 character(len=*),
intent(in) :: fmsg
1795 character(len=*),
intent(in) :: mesg
1796 integer,
intent(in) :: bc0
1797 integer,
intent(in) :: bcW
1798 integer,
intent(in) :: iounit
1800 if (is_root_pe())
write(iounit,
'(A,2(A,I10,1X),A)') &
1801 fmsg,
" c=", bc0,
"W=", bcw, trim(mesg)
1802 end subroutine chk_sum_msg_w
1805 subroutine chk_sum_msg2(fmsg, bc0, bcSW, mesg, iounit)
1806 character(len=*),
intent(in) :: fmsg
1807 character(len=*),
intent(in) :: mesg
1808 integer,
intent(in) :: bc0
1809 integer,
intent(in) :: bcSW
1810 integer,
intent(in) :: iounit
1812 if (is_root_pe())
write(iounit,
'(A,2(A,I9,1X),A)') &
1813 fmsg,
" c=", bc0,
"s/w=", bcsw, trim(mesg)
1814 end subroutine chk_sum_msg2
1817 subroutine chk_sum_msg3(fmsg, aMean, aMin, aMax, mesg, iounit)
1818 character(len=*),
intent(in) :: fmsg
1819 character(len=*),
intent(in) :: mesg
1820 real,
intent(in) :: aMean
1821 real,
intent(in) :: aMin
1822 real,
intent(in) :: aMax
1823 integer,
intent(in) :: iounit
1825 if (is_root_pe())
write(iounit,
'(A,3(A,ES25.16,1X),A)') &
1826 fmsg,
" mean=", amean,
"min=", amin,
"max=", amax, trim(mesg)
1827 end subroutine chk_sum_msg3
1831 subroutine mom_checksums_init(param_file)
1834 #include "version_variable.h"
1835 character(len=40) :: mdl =
"MOM_checksums"
1839 end subroutine mom_checksums_init
1842 subroutine chksum_error(signal, message)
1844 integer,
intent(in) :: signal
1845 character(len=*),
intent(in) :: message
1846 call mom_error(signal, message)
1847 end subroutine chksum_error
1851 integer function bitcount(x)
1855 integer(kind(x)) :: y
1862 do bit = 0, bit_size(y)-1
1863 if (btest(y,bit)) bitcount = bitcount+1
1866 end function bitcount