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)