24 use fms_mod
, only : fms_end, mom_infra_init => fms_init
25 use memutils_mod
, only : print_memuse_stats
26 use mpp_mod
, only : pe_here => mpp_pe, root_pe => mpp_root_pe, num_pes => mpp_npes
27 use mpp_mod
, only : set_pelist => mpp_set_current_pelist, get_pelist => mpp_get_current_pelist
28 use mpp_mod
, only : broadcast => mpp_broadcast
29 use mpp_mod
, only : sum_across_pes => mpp_sum, min_across_pes => mpp_min
30 use mpp_mod
, only : max_across_pes => mpp_max
32 implicit none ;
private 34 public :: pe_here, root_pe, num_pes, mom_infra_init,
mom_infra_end 35 public :: broadcast, sum_across_pes, min_across_pes, max_across_pes
38 public ::
operator(+),
operator(-),
assignment(=)
40 public :: set_pelist, get_pelist
44 integer(kind=8),
parameter ::
prec=2_8**46
46 real,
parameter ::
i_prec=1.0/(2.0**46)
52 integer,
parameter ::
ni=6
54 real,
parameter,
dimension(ni) :: &
56 real,
parameter,
dimension(ni) :: &
69 integer(kind=8),
dimension(ni) :: v
72 interface operator (+); module
procedure efp_plus ; end interface
73 interface operator (-); module
procedure efp_minus ; end interface
74 interface assignment(=); module
procedure efp_assign ; end interface
79 overflow_check, err)
result(sum)
80 real,
dimension(:,:),
intent(in) :: array
81 integer,
optional,
intent(in) :: isr, ier, jsr, jer
82 type(
efp_type),
optional,
intent(out) :: EFP_sum
83 logical,
optional,
intent(in) :: reproducing
84 logical,
optional,
intent(in) :: overflow_check
85 integer,
optional,
intent(out) :: err
92 integer(kind=8),
dimension(ni) :: ints_sum
93 integer(kind=8) :: ival, prec_error
96 logical :: repro, over_check
97 character(len=256) :: mesg
98 integer :: i, j, n, is, ie, js, je, sgn
101 "reproducing_sum: Too many processors are being used for the value of "//&
102 "prec. Reduce prec to (2^63-1)/num_PEs.")
104 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
106 is = 1 ; ie =
size(array,1) ; js = 1 ; je =
size(array,2 )
107 if (
present(isr))
then 109 "Value of isr too small in reproducing_sum_2d.")
112 if (
present(ier))
then 114 "Value of ier too large in reproducing_sum_2d.")
117 if (
present(jsr))
then 119 "Value of jsr too small in reproducing_sum_2d.")
122 if (
present(jer))
then 124 "Value of jer too large in reproducing_sum_2d.")
128 repro = .true. ;
if (
present(reproducing)) repro = reproducing
129 over_check = .true. ;
if (
present(overflow_check)) over_check = overflow_check
136 do j=js,je ;
do i=is,ie
148 do j=js,je ;
do i=is,ie
154 do j=js,je ;
do i=is,ie
155 sgn = 1 ;
if (array(i,j)<0.0) sgn = -1
158 ival = int(rs*
i_pr(n), 8)
160 ints_sum(n) = ints_sum(n) + sgn*ival
166 if (
present(err))
then 172 if (err > 0)
then ;
do n=1,
ni ; ints_sum(n) = 0 ;
enddo ;
endif 175 call mom_error(fatal,
"NaN in input field of reproducing_sum(_2d).")
177 if (abs(max_mag_term) >= prec_error*
pr(1))
then 178 write(mesg,
'(ES13.5)') max_mag_term
179 call mom_error(fatal,
"Overflow in reproducing_sum(_2d) conversion of "//trim(mesg))
182 call mom_error(fatal,
"Overflow in reproducing_sum(_2d).")
186 call sum_across_pes(ints_sum,
ni)
192 do j=js,je ;
do i=is,ie
193 rsum(1) = rsum(1) + array(i,j);
195 call sum_across_pes(rsum,1)
198 if (
present(err))
then ; err = 0 ;
endif 200 if (
debug .or.
present(efp_sum))
then 204 if (
present(err))
then 207 write(mesg,
'(ES13.5)') sum
208 call mom_error(fatal,
"Repro_sum_2d: Overflow in real_to_ints conversion of "//trim(mesg))
214 if (
present(efp_sum)) efp_sum%v(:) = ints_sum(:)
217 write(mesg,
'("2d RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:
ni)
225 real,
dimension(:,:,:),
intent(in) :: array
226 integer,
optional,
intent(in) :: isr, ier, jsr, jer
227 real,
dimension(:),
optional,
intent(out) :: sums
228 type(
efp_type),
optional,
intent(out) :: EFP_sum
229 integer,
optional,
intent(out) :: err
237 integer(kind=8),
dimension(ni) :: ints_sum
238 integer(kind=8),
dimension(ni,size(array,3)) :: ints_sums
239 integer(kind=8) :: prec_error
240 character(len=256) :: mesg
241 integer :: i, j, k, is, ie, js, je, ke, isz, jsz, n
244 "reproducing_sum: Too many processors are being used for the value of "//&
245 "prec. Reduce prec to (2^63-1)/num_PEs.")
247 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
250 is = 1 ; ie =
size(array,1) ; js = 1 ; je =
size(array,2) ; ke =
size(array,3)
251 if (
present(isr))
then 253 "Value of isr too small in reproducing_sum(_3d).")
256 if (
present(ier))
then 258 "Value of ier too large in reproducing_sum(_3d).")
261 if (
present(jsr))
then 263 "Value of jsr too small in reproducing_sum(_3d).")
266 if (
present(jer))
then 268 "Value of jer too large in reproducing_sum(_3d).")
271 jsz = je+1-js; isz = ie+1-is
273 if (
present(sums))
then 274 if (
size(sums) > ke)
call mom_error(fatal,
"Sums is smaller than "//&
275 "the vertical extent of array in reproducing_sum(_3d).")
280 do j=js,je ;
do i=is,ie
286 do k=1,ke ;
do j=js,je
293 do k=1,ke ;
do j=js,je ;
do i=is,ie
296 enddo ;
enddo ;
enddo 298 if (
present(err))
then 300 if (abs(max_mag_term) >= prec_error*
pr(1)) err = err+1
303 if (err > 0)
then ;
do k=1,ke ;
do n=1,
ni ; ints_sums(n,k) = 0 ;
enddo ;
enddo ;
endif 306 if (abs(max_mag_term) >= prec_error*
pr(1))
then 307 write(mesg,
'(ES13.5)') max_mag_term
308 call mom_error(fatal,
"Overflow in reproducing_sum(_3d) conversion of "//trim(mesg))
313 call sum_across_pes(ints_sums(:,1:ke),
ni*ke)
322 if (
present(efp_sum))
then 324 do k=1,ke ;
call increment_ints(efp_sum%v(:), ints_sums(:,k)) ;
enddo 328 do n=1,
ni ; ints_sum(n) = 0 ;
enddo 329 do k=1,ke ;
do n=1,
ni ; ints_sum(n) = ints_sum(n) + ints_sums(n,k) ;
enddo ;
enddo 330 write(mesg,
'("3D RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:
ni)
338 do j=js,je ;
do i=is,ie
344 do k=1,ke ;
do j=js,je
351 do k=1,ke ;
do j=js,je ;
do i=is,ie
354 enddo ;
enddo ;
enddo 356 if (
present(err))
then 358 if (abs(max_mag_term) >= prec_error*
pr(1)) err = err+1
361 if (err > 0)
then ;
do n=1,
ni ; ints_sum(n) = 0 ;
enddo ;
endif 364 if (abs(max_mag_term) >= prec_error*
pr(1))
then 365 write(mesg,
'(ES13.5)') max_mag_term
366 call mom_error(fatal,
"Overflow in reproducing_sum(_3d) conversion of "//trim(mesg))
371 call sum_across_pes(ints_sum,
ni)
376 if (
present(efp_sum)) efp_sum%v(:) = ints_sum(:)
379 write(mesg,
'("3d RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:
ni)
386 function real_to_ints(r, prec_error, overflow)
result(ints)
387 real,
intent(in) :: r
388 integer(kind=8),
optional,
intent(in) :: prec_error
389 logical,
optional,
intent(inout) :: overflow
390 integer(kind=8),
dimension(ni) :: ints
395 character(len=80) :: mesg
396 integer(kind=8) :: ival, prec_err
399 prec_err =
prec ;
if (
present(prec_error)) prec_err = prec_error
401 if ((r >= 1e30) .eqv. (r < 1e30))
then ;
nan_error = .true. ;
return ;
endif 403 sgn = 1 ;
if (r<0.0) sgn = -1
406 if (
present(overflow))
then 407 if (.not.(rs < prec_err*
pr(1))) overflow = .true.
408 if ((r >= 1e30) .eqv. (r < 1e30)) overflow = .true.
409 elseif (.not.(rs < prec_err*
pr(1)))
then 410 write(mesg,
'(ES13.5)') r
411 call mom_error(fatal,
"Overflow in real_to_ints conversion of "//trim(mesg))
415 ival = int(rs*
i_pr(i), 8)
423 integer(kind=8),
dimension(ni),
intent(in) :: ints
430 do i=1,
ni ; r = r +
pr(i)*ints(i) ;
enddo 434 integer(kind=8),
dimension(ni),
intent(inout) :: int_sum
435 integer(kind=8),
dimension(ni),
intent(in) :: int2
436 integer(kind=8),
optional,
intent(in) :: prec_error
443 int_sum(i) = int_sum(i) + int2(i)
445 if (int_sum(i) >
prec)
then 446 int_sum(i) = int_sum(i) -
prec 447 int_sum(i-1) = int_sum(i-1) + 1
448 elseif (int_sum(i) < -
prec)
then 449 int_sum(i) = int_sum(i) +
prec 450 int_sum(i-1) = int_sum(i-1) - 1
453 int_sum(1) = int_sum(1) + int2(1)
454 if (
present(prec_error))
then 463 integer(kind=8),
dimension(ni),
intent(inout) :: int_sum
464 real,
intent(in) :: r
465 real,
intent(inout) :: max_mag_term
471 integer(kind=8) :: ival
474 if ((r >= 1e30) .eqv. (r < 1e30))
then ;
nan_error = .true. ;
return ;
endif 475 sgn = 1 ;
if (r<0.0) sgn = -1
477 if (rs > abs(max_mag_term)) max_mag_term = r
480 ival = int(rs*
i_pr(i), 8)
482 int_sum(i) = int_sum(i) + sgn*ival
488 integer(kind=8),
dimension(ni),
intent(inout) :: int_sum
489 integer(kind=8),
intent(in) :: prec_error
492 integer :: i, num_carry
494 do i=
ni,2,-1 ;
if (abs(int_sum(i)) >
prec)
then 495 num_carry = int(int_sum(i) *
i_prec)
496 int_sum(i) = int_sum(i) - num_carry*
prec 497 int_sum(i-1) = int_sum(i-1) + num_carry
499 if (abs(int_sum(1)) > prec_error)
then 506 integer(kind=8),
dimension(ni),
intent(inout) :: int_sum
511 integer :: i, num_carry
513 do i=
ni,2,-1 ;
if (abs(int_sum(i)) >
prec)
then 514 num_carry = int(int_sum(i) *
i_prec)
515 int_sum(i) = int_sum(i) - num_carry*
prec 516 int_sum(i-1) = int_sum(i-1) + num_carry
522 if (abs(int_sum(i)) > 0)
then 523 if (int_sum(i) < 0) positive = .false.
529 do i=
ni,2,-1 ;
if (int_sum(i) < 0)
then 530 int_sum(i) = int_sum(i) +
prec 531 int_sum(i-1) = int_sum(i-1) - 1
534 do i=
ni,2,-1 ;
if (int_sum(i) > 0)
then 535 int_sum(i) = int_sum(i) -
prec 536 int_sum(i-1) = int_sum(i-1) + 1
543 logical :: query_EFP_overflow_error
553 type(
efp_type),
intent(in) :: EFP1, EFP2
562 type(
efp_type),
intent(in) :: EFP1, EFP2
565 do i=1,
ni ; efp_minus%v(i) = -1*efp2%v(i) ;
enddo 578 do i=1,
ni ; efp1%v(i) = efp2%v(i) ;
enddo 591 real :: EFP_real_diff
595 efp_diff = efp1 - efp2
601 real,
intent(in) :: val
602 logical,
optional,
intent(inout) :: overflow
606 character(len=80) :: mesg
608 if (
present(overflow))
then 614 write(mesg,
'(ES13.5)') val
615 call mom_error(fatal,
"Overflow in real_to_EFP conversion of "//trim(mesg))
622 type(
efp_type),
dimension(:),
intent(inout) :: EFPs
623 integer,
intent(in) :: nval
624 logical,
dimension(:),
optional,
intent(out) :: errors
629 integer(kind=8),
dimension(ni,nval) :: ints
630 integer(kind=8) :: prec_error
631 logical :: error_found
632 character(len=256) :: mesg
636 "reproducing_sum: Too many processors are being used for the value of "//&
637 "prec. Reduce prec to (2^63-1)/num_PEs.")
639 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
643 do i=1,nval ;
do n=1,
ni ; ints(n,i) = efps(i)%v(n) ;
enddo ;
enddo 645 call sum_across_pes(ints(:,:),
ni*nval)
647 if (
present(errors)) errors(:) = .false.
651 do n=1,
ni ; efps(i)%v(n) = ints(n,i) ;
enddo 654 write (mesg,
'("EFP_list_sum_across_PEs error at ",i6," val was ",ES12.6, ", prec_error = ",ES12.6)') &
660 if (error_found .and. .not.(
present(errors)))
then 661 call mom_error(fatal,
"Overflow in EFP_list_sum_across_PEs.")
670 call print_memuse_stats(
'Memory HiWaterMark', always=.true. )
subroutine, public efp_list_sum_across_pes(EFPs, nval, errors)
real, dimension(ni), parameter pr
real function reproducing_sum_2d(array, isr, ier, jsr, jer, EFP_sum, reproducing, overflow_check, err)
subroutine, public reset_efp_overflow_error()
type(efp_type) function, public real_to_efp(val, overflow)
type(efp_type) function, public efp_minus(EFP1, EFP2)
subroutine efp_assign(EFP1, EFP2)
logical function, public query_efp_overflow_error()
real function reproducing_sum_3d(array, isr, ier, jsr, jer, sums, EFP_sum, err)
subroutine increment_ints(int_sum, int2, prec_error)
subroutine increment_ints_faster(int_sum, r, max_mag_term)
real function ints_to_real(ints)
subroutine carry_overflow(int_sum, prec_error)
integer, parameter max_count_prec
subroutine, public mom_mesg(message, verb, all_print)
real, dimension(ni), parameter i_pr
integer(kind=8) function, dimension(ni) real_to_ints(r, prec_error, overflow)
integer(kind=8), parameter prec
subroutine regularize_ints(int_sum)
real function, public efp_to_real(EFP1)
subroutine, public mom_infra_end
subroutine, public mom_error(level, message, all_print)
real function, public efp_real_diff(EFP1, EFP2)
type(efp_type) function, public efp_plus(EFP1, EFP2)