8 use fms_mod,
only : fms_end, mom_infra_init => fms_init
9 use memutils_mod,
only : print_memuse_stats
10 use mpp_mod,
only : pe_here => mpp_pe, root_pe => mpp_root_pe, num_pes => mpp_npes
11 use mpp_mod,
only : set_pelist => mpp_set_current_pelist, get_pelist => mpp_get_current_pelist
12 use mpp_mod,
only : broadcast => mpp_broadcast
13 use mpp_mod,
only : sum_across_pes => mpp_sum, max_across_pes => mpp_max, min_across_pes => mpp_min
15 implicit none ;
private
17 public :: pe_here, root_pe, num_pes, mom_infra_init, mom_infra_end
18 public :: broadcast, sum_across_pes, min_across_pes, max_across_pes
20 public :: efp_plus, efp_minus, efp_to_real, real_to_efp, efp_real_diff
21 public ::
operator(+),
operator(-),
assignment(=)
22 public :: query_efp_overflow_error, reset_efp_overflow_error
23 public :: set_pelist, get_pelist
27 integer(kind=8),
parameter :: prec=2_8**46
28 real,
parameter :: r_prec=2.0**46
29 real,
parameter :: i_prec=1.0/(2.0**46)
30 integer,
parameter :: max_count_prec=2**(63-46)-1
35 integer,
parameter :: ni=6
37 real,
parameter,
dimension(ni) :: &
38 pr = (/ r_prec**2, r_prec, 1.0, 1.0/r_prec, 1.0/r_prec**2, 1.0/r_prec**3 /)
40 real,
parameter,
dimension(ni) :: &
41 i_pr = (/ 1.0/r_prec**2, 1.0/r_prec, 1.0, r_prec, r_prec**2, r_prec**3 /)
43 real,
parameter :: max_efp_float = pr(1) * (2.**63 - 1.)
48 logical :: overflow_error = .false.
49 logical :: nan_error = .false.
50 logical :: debug = .false.
54 module procedure reproducing_sum_2d, reproducing_sum_3d
60 module procedure reproducing_efp_sum_2d
65 module procedure efp_list_sum_across_pes, efp_val_sum_across_pes
75 integer(kind=8),
dimension(ni) :: v
79 interface operator (+) ; module
procedure EFP_plus ; end interface
81 interface operator (-) ; module
procedure EFP_minus ; end interface
83 interface assignment(=); module
procedure EFP_assign ; end interface
92 function reproducing_efp_sum_2d(array, isr, ier, jsr, jer, overflow_check, err, only_on_PE)
result(EFP_sum)
93 real,
dimension(:,:),
intent(in) :: array
94 integer,
optional,
intent(in) :: isr
96 integer,
optional,
intent(in) :: ier
98 integer,
optional,
intent(in) :: jsr
100 integer,
optional,
intent(in) :: jer
102 logical,
optional,
intent(in) :: overflow_check
106 integer,
optional,
intent(out) :: err
109 logical,
optional,
intent(in) :: only_on_pe
117 integer(kind=8),
dimension(ni) :: ints_sum
118 integer(kind=8) :: ival, prec_error
121 logical :: over_check, do_sum_across_pes
122 character(len=256) :: mesg
123 integer :: i, j, n, is, ie, js, je, sgn
125 if (num_pes() > max_count_prec)
call mom_error(fatal, &
126 "reproducing_sum: Too many processors are being used for the value of "//&
127 "prec. Reduce prec to (2^63-1)/num_PEs.")
129 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
131 is = 1 ; ie =
size(array,1) ; js = 1 ; je =
size(array,2 )
132 if (
present(isr))
then
133 if (isr < is)
call mom_error(fatal,
"Value of isr too small in reproducing_EFP_sum_2d.")
136 if (
present(ier))
then
137 if (ier > ie)
call mom_error(fatal,
"Value of ier too large in reproducing_EFP_sum_2d.")
140 if (
present(jsr))
then
141 if (jsr < js)
call mom_error(fatal,
"Value of jsr too small in reproducing_EFP_sum_2d.")
144 if (
present(jer))
then
145 if (jer > je)
call mom_error(fatal,
"Value of jer too large in reproducing_EFP_sum_2d.")
149 over_check = .true. ;
if (
present(overflow_check)) over_check = overflow_check
150 do_sum_across_pes = .true. ;
if (
present(only_on_pe)) do_sum_across_pes = .not.only_on_pe
152 overflow_error = .false. ; nan_error = .false. ; max_mag_term = 0.0
155 if ((je+1-js)*(ie+1-is) < max_count_prec)
then
156 do j=js,je ;
do i=is,ie
157 call increment_ints_faster(ints_sum, array(i,j), max_mag_term)
159 call carry_overflow(ints_sum, prec_error)
160 elseif ((ie+1-is) < max_count_prec)
then
163 call increment_ints_faster(ints_sum, array(i,j), max_mag_term)
165 call carry_overflow(ints_sum, prec_error)
168 do j=js,je ;
do i=is,ie
169 call increment_ints(ints_sum, real_to_ints(array(i,j), prec_error), &
174 do j=js,je ;
do i=is,ie
175 sgn = 1 ;
if (array(i,j)<0.0) sgn = -1
178 ival = int(rs*i_pr(n), 8)
180 ints_sum(n) = ints_sum(n) + sgn*ival
183 call carry_overflow(ints_sum, prec_error)
186 if (
present(err))
then
188 if (overflow_error) &
192 if (err > 0)
then ;
do n=1,ni ; ints_sum(n) = 0 ;
enddo ;
endif
195 call mom_error(fatal,
"NaN in input field of reproducing_EFP_sum(_2d).")
197 if (abs(max_mag_term) >= prec_error*pr(1))
then
198 write(mesg,
'(ES13.5)') max_mag_term
199 call mom_error(fatal,
"Overflow in reproducing_EFP_sum(_2d) conversion of "//trim(mesg))
201 if (overflow_error)
then
202 call mom_error(fatal,
"Overflow in reproducing_EFP_sum(_2d).")
206 if (do_sum_across_pes)
call sum_across_pes(ints_sum, ni)
208 call regularize_ints(ints_sum)
210 efp_sum%v(:) = ints_sum(:)
212 end function reproducing_efp_sum_2d
218 function reproducing_sum_2d(array, isr, ier, jsr, jer, EFP_sum, reproducing, &
219 overflow_check, err, only_on_PE)
result(sum)
220 real,
dimension(:,:),
intent(in) :: array
221 integer,
optional,
intent(in) :: isr
223 integer,
optional,
intent(in) :: ier
225 integer,
optional,
intent(in) :: jsr
227 integer,
optional,
intent(in) :: jer
229 type(
efp_type),
optional,
intent(out) :: efp_sum
230 logical,
optional,
intent(in) :: reproducing
232 logical,
optional,
intent(in) :: overflow_check
236 integer,
optional,
intent(out) :: err
239 logical,
optional,
intent(in) :: only_on_pe
247 integer(kind=8),
dimension(ni) :: ints_sum
248 integer(kind=8) :: prec_error
250 logical :: repro, do_sum_across_pes
251 character(len=256) :: mesg
253 integer :: i, j, n, is, ie, js, je
255 if (num_pes() > max_count_prec)
call mom_error(fatal, &
256 "reproducing_sum: Too many processors are being used for the value of "//&
257 "prec. Reduce prec to (2^63-1)/num_PEs.")
259 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
261 is = 1 ; ie =
size(array,1) ; js = 1 ; je =
size(array,2 )
262 if (
present(isr))
then
263 if (isr < is)
call mom_error(fatal,
"Value of isr too small in reproducing_sum_2d.")
266 if (
present(ier))
then
267 if (ier > ie)
call mom_error(fatal,
"Value of ier too large in reproducing_sum_2d.")
270 if (
present(jsr))
then
271 if (jsr < js)
call mom_error(fatal,
"Value of jsr too small in reproducing_sum_2d.")
274 if (
present(jer))
then
275 if (jer > je)
call mom_error(fatal,
"Value of jer too large in reproducing_sum_2d.")
279 repro = .true. ;
if (
present(reproducing)) repro = reproducing
280 do_sum_across_pes = .true. ;
if (
present(only_on_pe)) do_sum_across_pes = .not.only_on_pe
283 efp_val = reproducing_efp_sum_2d(array, isr, ier, jsr, jer, overflow_check, err, only_on_pe)
284 sum = ints_to_real(efp_val%v)
285 if (
present(efp_sum)) efp_sum = efp_val
286 if (debug) ints_sum(:) = efp_sum%v(:)
289 do j=js,je ;
do i=is,ie
290 rsum(1) = rsum(1) + array(i,j)
292 if (do_sum_across_pes)
call sum_across_pes(rsum,1)
295 if (
present(err))
then ; err = 0 ;
endif
297 if (debug .or.
present(efp_sum))
then
298 overflow_error = .false.
299 ints_sum = real_to_ints(sum, prec_error, overflow_error)
300 if (overflow_error)
then
301 if (
present(err))
then
304 write(mesg,
'(ES13.5)') sum
305 call mom_error(fatal,
"Repro_sum_2d: Overflow in real_to_ints conversion of "//trim(mesg))
309 if (
present(efp_sum)) efp_sum%v(:) = ints_sum(:)
313 write(mesg,
'("2d RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:ni)
314 call mom_mesg(mesg, 3)
317 end function reproducing_sum_2d
323 function reproducing_sum_3d(array, isr, ier, jsr, jer, sums, EFP_sum, EFP_lay_sums, err, only_on_PE) &
325 real,
dimension(:,:,:),
intent(in) :: array
326 integer,
optional,
intent(in) :: isr
328 integer,
optional,
intent(in) :: ier
330 integer,
optional,
intent(in) :: jsr
332 integer,
optional,
intent(in) :: jer
334 real,
dimension(:),
optional,
intent(out) :: sums
335 type(
efp_type),
optional,
intent(out) :: efp_sum
337 optional,
intent(out) :: efp_lay_sums
338 integer,
optional,
intent(out) :: err
341 logical,
optional,
intent(in) :: only_on_pe
349 real :: val, max_mag_term
350 integer(kind=8),
dimension(ni) :: ints_sum
351 integer(kind=8),
dimension(ni,size(array,3)) :: ints_sums
352 integer(kind=8) :: prec_error
353 character(len=256) :: mesg
354 logical :: do_sum_across_pes
355 integer :: i, j, k, is, ie, js, je, ke, isz, jsz, n
357 if (num_pes() > max_count_prec)
call mom_error(fatal, &
358 "reproducing_sum: Too many processors are being used for the value of "//&
359 "prec. Reduce prec to (2^63-1)/num_PEs.")
361 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
364 is = 1 ; ie =
size(array,1) ; js = 1 ; je =
size(array,2) ; ke =
size(array,3)
365 if (
present(isr))
then
366 if (isr < is)
call mom_error(fatal,
"Value of isr too small in reproducing_sum(_3d).")
369 if (
present(ier))
then
370 if (ier > ie)
call mom_error(fatal,
"Value of ier too large in reproducing_sum(_3d).")
373 if (
present(jsr))
then
374 if (jsr < js)
call mom_error(fatal,
"Value of jsr too small in reproducing_sum(_3d).")
377 if (
present(jer))
then
378 if (jer > je)
call mom_error(fatal,
"Value of jer too large in reproducing_sum(_3d).")
381 jsz = je+1-js; isz = ie+1-is
383 do_sum_across_pes = .true. ;
if (
present(only_on_pe)) do_sum_across_pes = .not.only_on_pe
385 if (
present(sums) .or.
present(efp_lay_sums))
then
386 if (
present(sums))
then ;
if (
size(sums) < ke)
then
387 call mom_error(fatal,
"Sums is smaller than the vertical extent of array in reproducing_sum(_3d).")
389 if (
present(efp_lay_sums))
then ;
if (
size(efp_lay_sums) < ke)
then
390 call mom_error(fatal,
"Sums is smaller than the vertical extent of array in reproducing_sum(_3d).")
393 overflow_error = .false. ; nan_error = .false. ; max_mag_term = 0.0
394 if (jsz*isz < max_count_prec)
then
396 do j=js,je ;
do i=is,ie
397 call increment_ints_faster(ints_sums(:,k), array(i,j,k), max_mag_term)
399 call carry_overflow(ints_sums(:,k), prec_error)
401 elseif (isz < max_count_prec)
then
402 do k=1,ke ;
do j=js,je
404 call increment_ints_faster(ints_sums(:,k), array(i,j,k), max_mag_term)
406 call carry_overflow(ints_sums(:,k), prec_error)
409 do k=1,ke ;
do j=js,je ;
do i=is,ie
410 call increment_ints(ints_sums(:,k), &
411 real_to_ints(array(i,j,k), prec_error), prec_error)
412 enddo ;
enddo ;
enddo
414 if (
present(err))
then
416 if (abs(max_mag_term) >= prec_error*pr(1)) err = err+1
417 if (overflow_error) err = err+2
418 if (nan_error) err = err+2
419 if (err > 0)
then ;
do k=1,ke ;
do n=1,ni ; ints_sums(n,k) = 0 ;
enddo ;
enddo ;
endif
421 if (nan_error)
call mom_error(fatal,
"NaN in input field of reproducing_sum(_3d).")
422 if (abs(max_mag_term) >= prec_error*pr(1))
then
423 write(mesg,
'(ES13.5)') max_mag_term
424 call mom_error(fatal,
"Overflow in reproducing_sum(_3d) conversion of "//trim(mesg))
426 if (overflow_error)
call mom_error(fatal,
"Overflow in reproducing_sum(_3d).")
429 if (do_sum_across_pes)
call sum_across_pes(ints_sums(:,1:ke), ni*ke)
433 call regularize_ints(ints_sums(:,k))
434 val = ints_to_real(ints_sums(:,k))
435 if (
present(sums)) sums(k) = val
438 if (
present(efp_lay_sums))
then ;
do k=1,ke
439 efp_lay_sums(k)%v(:) = ints_sums(:,k)
442 if (
present(efp_sum))
then
444 do k=1,ke ;
call increment_ints(efp_sum%v(:), ints_sums(:,k)) ;
enddo
448 do n=1,ni ; ints_sum(n) = 0 ;
enddo
449 do k=1,ke ;
do n=1,ni ; ints_sum(n) = ints_sum(n) + ints_sums(n,k) ;
enddo ;
enddo
450 write(mesg,
'("3D RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:ni)
451 call mom_mesg(mesg, 3)
455 overflow_error = .false. ; nan_error = .false. ; max_mag_term = 0.0
456 if (jsz*isz < max_count_prec)
then
458 do j=js,je ;
do i=is,ie
459 call increment_ints_faster(ints_sum, array(i,j,k), max_mag_term)
461 call carry_overflow(ints_sum, prec_error)
463 elseif (isz < max_count_prec)
then
464 do k=1,ke ;
do j=js,je
466 call increment_ints_faster(ints_sum, array(i,j,k), max_mag_term)
468 call carry_overflow(ints_sum, prec_error)
471 do k=1,ke ;
do j=js,je ;
do i=is,ie
472 call increment_ints(ints_sum, real_to_ints(array(i,j,k), prec_error), &
474 enddo ;
enddo ;
enddo
476 if (
present(err))
then
478 if (abs(max_mag_term) >= prec_error*pr(1)) err = err+1
479 if (overflow_error) err = err+2
480 if (nan_error) err = err+2
481 if (err > 0)
then ;
do n=1,ni ; ints_sum(n) = 0 ;
enddo ;
endif
483 if (nan_error)
call mom_error(fatal,
"NaN in input field of reproducing_sum(_3d).")
484 if (abs(max_mag_term) >= prec_error*pr(1))
then
485 write(mesg,
'(ES13.5)') max_mag_term
486 call mom_error(fatal,
"Overflow in reproducing_sum(_3d) conversion of "//trim(mesg))
488 if (overflow_error)
call mom_error(fatal,
"Overflow in reproducing_sum(_3d).")
491 if (do_sum_across_pes)
call sum_across_pes(ints_sum, ni)
493 call regularize_ints(ints_sum)
494 sum = ints_to_real(ints_sum)
496 if (
present(efp_sum)) efp_sum%v(:) = ints_sum(:)
499 write(mesg,
'("3d RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:ni)
500 call mom_mesg(mesg, 3)
504 end function reproducing_sum_3d
507 function real_to_ints(r, prec_error, overflow)
result(ints)
508 real,
intent(in) :: r
509 integer(kind=8),
optional,
intent(in) :: prec_error
513 logical,
optional,
intent(inout) :: overflow
515 integer(kind=8),
dimension(ni) :: ints
520 character(len=80) :: mesg
521 integer(kind=8) :: ival, prec_err
524 prec_err = prec ;
if (
present(prec_error)) prec_err = prec_error
526 if ((r >= 1e30) .eqv. (r < 1e30))
then ; nan_error = .true. ;
return ;
endif
528 sgn = 1 ;
if (r<0.0) sgn = -1
531 if (
present(overflow))
then
532 if (.not.(rs < prec_err*pr(1))) overflow = .true.
533 if ((r >= 1e30) .eqv. (r < 1e30)) overflow = .true.
534 elseif (.not.(rs < prec_err*pr(1)))
then
535 write(mesg,
'(ES13.5)') r
536 call mom_error(fatal,
"Overflow in real_to_ints conversion of "//trim(mesg))
540 ival = int(rs*i_pr(i), 8)
545 end function real_to_ints
549 function ints_to_real(ints)
result(r)
550 integer(kind=8),
dimension(ni),
intent(in) :: ints
557 do i=1,ni ; r = r + pr(i)*ints(i) ;
enddo
558 end function ints_to_real
562 subroutine increment_ints(int_sum, int2, prec_error)
563 integer(kind=8),
dimension(ni),
intent(inout) :: int_sum
564 integer(kind=8),
dimension(ni),
intent(in) :: int2
565 integer(kind=8),
optional,
intent(in) :: prec_error
575 int_sum(i) = int_sum(i) + int2(i)
577 if (int_sum(i) > prec)
then
578 int_sum(i) = int_sum(i) - prec
579 int_sum(i-1) = int_sum(i-1) + 1
580 elseif (int_sum(i) < -prec)
then
581 int_sum(i) = int_sum(i) + prec
582 int_sum(i-1) = int_sum(i-1) - 1
585 int_sum(1) = int_sum(1) + int2(1)
586 if (
present(prec_error))
then
587 if (abs(int_sum(1)) > prec_error) overflow_error = .true.
589 if (abs(int_sum(1)) > prec) overflow_error = .true.
592 end subroutine increment_ints
596 subroutine increment_ints_faster(int_sum, r, max_mag_term)
597 integer(kind=8),
dimension(ni),
intent(inout) :: int_sum
598 real,
intent(in) :: r
599 real,
intent(inout) :: max_mag_term
605 integer(kind=8) :: ival
608 if ((r >= 1e30) .eqv. (r < 1e30))
then ; nan_error = .true. ;
return ;
endif
609 sgn = 1 ;
if (r<0.0) sgn = -1
611 if (rs > abs(max_mag_term)) max_mag_term = r
614 if (rs > max_efp_float)
then
615 overflow_error = .true.
620 ival = int(rs*i_pr(i), 8)
622 int_sum(i) = int_sum(i) + sgn*ival
625 end subroutine increment_ints_faster
628 subroutine carry_overflow(int_sum, prec_error)
629 integer(kind=8),
dimension(ni),
intent(inout) :: int_sum
631 integer(kind=8),
intent(in) :: prec_error
637 integer :: i, num_carry
639 do i=ni,2,-1 ;
if (abs(int_sum(i)) >= prec)
then
640 num_carry = int(int_sum(i) * i_prec)
641 int_sum(i) = int_sum(i) - num_carry*prec
642 int_sum(i-1) = int_sum(i-1) + num_carry
644 if (abs(int_sum(1)) > prec_error)
then
645 overflow_error = .true.
648 end subroutine carry_overflow
652 subroutine regularize_ints(int_sum)
653 integer(kind=8),
dimension(ni), &
654 intent(inout) :: int_sum
661 integer :: i, num_carry
663 do i=ni,2,-1 ;
if (abs(int_sum(i)) >= prec)
then
664 num_carry = int(int_sum(i) * i_prec)
665 int_sum(i) = int_sum(i) - num_carry*prec
666 int_sum(i-1) = int_sum(i-1) + num_carry
672 if (abs(int_sum(i)) > 0)
then
673 if (int_sum(i) < 0) positive = .false.
679 do i=ni,2,-1 ;
if (int_sum(i) < 0)
then
680 int_sum(i) = int_sum(i) + prec
681 int_sum(i-1) = int_sum(i-1) - 1
684 do i=ni,2,-1 ;
if (int_sum(i) > 0)
then
685 int_sum(i) = int_sum(i) - prec
686 int_sum(i-1) = int_sum(i-1) + 1
690 end subroutine regularize_ints
693 function query_efp_overflow_error()
694 logical :: query_efp_overflow_error
695 query_efp_overflow_error = overflow_error
696 end function query_efp_overflow_error
699 subroutine reset_efp_overflow_error()
700 overflow_error = .false.
701 end subroutine reset_efp_overflow_error
704 function efp_plus(EFP1, EFP2)
711 call increment_ints(efp_plus%v(:), efp2%v(:))
712 end function efp_plus
715 function efp_minus(EFP1, EFP2)
722 do i=1,ni ; efp_minus%v(i) = -1*efp2%v(i) ;
enddo
724 call increment_ints(efp_minus%v(:), efp1%v(:))
725 end function efp_minus
728 subroutine efp_assign(EFP1, EFP2)
736 do i=1,ni ; efp1%v(i) = efp2%v(i) ;
enddo
737 end subroutine efp_assign
740 function efp_to_real(EFP1)
741 type(
efp_type),
intent(inout) :: efp1
744 call regularize_ints(efp1%v)
745 efp_to_real = ints_to_real(efp1%v)
746 end function efp_to_real
750 function efp_real_diff(EFP1, EFP2)
754 real :: efp_real_diff
758 efp_diff = efp1 - efp2
759 efp_real_diff = efp_to_real(efp_diff)
761 end function efp_real_diff
764 function real_to_efp(val, overflow)
765 real,
intent(in) :: val
766 logical,
optional,
intent(inout) :: overflow
771 character(len=80) :: mesg
773 if (
present(overflow))
then
774 real_to_efp%v(:) = real_to_ints(val, overflow=overflow)
777 real_to_efp%v(:) = real_to_ints(val, overflow=over)
779 write(mesg,
'(ES13.5)') val
780 call mom_error(fatal,
"Overflow in real_to_EFP conversion of "//trim(mesg))
784 end function real_to_efp
788 subroutine efp_list_sum_across_pes(EFPs, nval, errors)
790 intent(inout) :: efps
792 integer,
intent(in) :: nval
793 logical,
dimension(:), &
794 optional,
intent(out) :: errors
799 integer(kind=8),
dimension(ni,nval) :: ints
800 integer(kind=8) :: prec_error
801 logical :: error_found
802 character(len=256) :: mesg
805 if (num_pes() > max_count_prec)
call mom_error(fatal, &
806 "reproducing_sum: Too many processors are being used for the value of "//&
807 "prec. Reduce prec to (2^63-1)/num_PEs.")
809 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
811 overflow_error = .false. ; error_found = .false.
813 do i=1,nval ;
do n=1,ni ; ints(n,i) = efps(i)%v(n) ;
enddo ;
enddo
815 call sum_across_pes(ints(:,:), ni*nval)
817 if (
present(errors)) errors(:) = .false.
819 overflow_error = .false.
820 call carry_overflow(ints(:,i), prec_error)
821 do n=1,ni ; efps(i)%v(n) = ints(n,i) ;
enddo
822 if (
present(errors)) errors(i) = overflow_error
823 if (overflow_error)
then
824 write (mesg,
'("EFP_list_sum_across_PEs error at ",i6," val was ",ES12.6, ", prec_error = ",ES12.6)') &
825 i, efp_to_real(efps(i)), real(prec_error)
826 call mom_error(warning, mesg)
828 error_found = error_found .or. overflow_error
830 if (error_found .and. .not.(
present(errors)))
then
831 call mom_error(fatal,
"Overflow in EFP_list_sum_across_PEs.")
834 end subroutine efp_list_sum_across_pes
838 subroutine efp_val_sum_across_pes(EFP, error)
839 type(
efp_type),
intent(inout) :: EFP
841 logical,
optional,
intent(out) :: error
846 integer(kind=8),
dimension(ni) :: ints
847 integer(kind=8) :: prec_error
848 logical :: error_found
849 character(len=256) :: mesg
852 if (num_pes() > max_count_prec)
call mom_error(fatal, &
853 "reproducing_sum: Too many processors are being used for the value of "//&
854 "prec. Reduce prec to (2^63-1)/num_PEs.")
856 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
858 overflow_error = .false. ; error_found = .false.
860 do n=1,ni ; ints(n) = efp%v(n) ;
enddo
862 call sum_across_pes(ints(:), ni)
864 if (
present(error)) error = .false.
866 overflow_error = .false.
867 call carry_overflow(ints(:), prec_error)
868 do n=1,ni ; efp%v(n) = ints(n) ;
enddo
869 if (
present(error)) error = overflow_error
870 if (overflow_error)
then
871 write (mesg,
'("EFP_val_sum_across_PEs error val was ",ES12.6, ", prec_error = ",ES12.6)') &
872 efp_to_real(efp), real(prec_error)
873 call mom_error(warning, mesg)
875 error_found = error_found .or. overflow_error
877 if (error_found .and. .not.(
present(error)))
then
878 call mom_error(fatal,
"Overflow in EFP_val_sum_across_PEs.")
881 end subroutine efp_val_sum_across_pes
886 subroutine mom_infra_end
887 call print_memuse_stats(
'Memory HiWaterMark', always=.true. )
889 end subroutine mom_infra_end