31 use mpp_mod,
only :
mpp_error, fatal, warning, note
36 implicit none ;
private
39 public :: mpp_efp_plus, mpp_efp_minus, mpp_efp_to_real, mpp_real_to_efp, mpp_efp_real_diff
40 public ::
operator(+),
operator(-),
assignment(=)
41 public :: mpp_query_efp_overflow_error, mpp_reset_efp_overflow_error
43 integer,
parameter :: NUMBIT = 46
47 integer(i8_kind),
parameter ::
prec=2_8**numbit
48 real(r8_kind),
parameter ::
r_prec=2.0_8**numbit
49 real(r8_kind),
parameter ::
i_prec=1.0_8/(2.0_8**numbit)
54 real(r8_kind),
parameter,
dimension(NUMINT) :: &
56 real(r8_kind),
parameter,
dimension(NUMINT) :: &
59 logical :: overflow_error = .false., nan_error = .false.
82 integer(i8_kind),
dimension(NUMINT) :: v
88 interface operator (+); module
procedure mpp_efp_plus ; end interface
91 interface operator (-); module
procedure mpp_efp_minus ; end interface
94 interface assignment(=); module
procedure mpp_efp_assign ; end interface
103 overflow_check, err)
result(sum)
104 real(r8_kind),
dimension(:,:),
intent(in) :: array
105 integer,
optional,
intent(in) :: isr, ier, jsr, jer
107 logical,
optional,
intent(in) :: reproducing
108 logical,
optional,
intent(in) :: overflow_check
109 integer,
optional,
intent(out) :: err
112 integer(i8_kind),
dimension(NUMINT) :: ints_sum
113 integer(i8_kind) :: ival, prec_error
114 real(r8_kind) :: rsum(1), rs
115 real(r8_kind) :: max_mag_term
116 logical :: repro, over_check
117 character(len=256) :: mesg
118 integer :: i, j, n, is, ie, js, je, sgn
121 "mpp_reproducing_sum: Too many processors are being used for the value of "//&
122 "prec. Reduce prec to (2^63-1)/mpp_npes.")
124 prec_error = (2_8**62 + (2_8**62 - 1)) /
mpp_npes()
126 is = 1 ; ie =
size(array,1) ; js = 1 ; je =
size(array,2 )
127 if (
present(isr))
then
129 "Value of isr too small in mpp_reproducing_sum_2d.")
132 if (
present(ier))
then
134 "Value of ier too large in mpp_reproducing_sum_2d.")
137 if (
present(jsr))
then
139 "Value of jsr too small in mpp_reproducing_sum_2d.")
142 if (
present(jer))
then
144 "Value of jer too large in mpp_reproducing_sum_2d.")
148 repro = .true. ;
if (
present(reproducing)) repro = reproducing
149 over_check = .true. ;
if (
present(overflow_check)) over_check = overflow_check
152 overflow_error = .false. ; nan_error = .false. ; max_mag_term = 0.0
156 do j=js,je ;
do i=is,ie
168 do j=js,je ;
do i=is,ie
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
186 if (
present(err))
then
188 if (overflow_error) &
192 if (err > 0)
then ;
do n=1,
numint ; ints_sum(n) = 0 ;
enddo ;
endif
195 call mpp_error(fatal,
"NaN in input field of mpp_reproducing_sum(_2d), this indicates numerical instability")
197 if (abs(max_mag_term) >= prec_error*pr(1))
then
198 write(mesg,
'(ES13.5)') max_mag_term
199 call mpp_error(fatal,
"Overflow in mpp_reproducing_sum(_2d) conversion of "//trim(mesg))
201 if (overflow_error)
then
202 call mpp_error(fatal,
"Overflow in mpp_reproducing_sum(_2d).")
212 do j=js,je ;
do i=is,ie
213 rsum(1) = rsum(1) + array(i,j);
218 if (
present(err))
then ; err = 0 ;
endif
220 if (
debug .or.
present(efp_sum))
then
221 overflow_error = .false.
222 ints_sum =
real_to_ints(sum, prec_error, overflow_error)
223 if (overflow_error)
then
224 if (
present(err))
then
227 write(mesg,
'(ES13.5)') sum
228 call mpp_error(fatal,
"Repro_sum_2d: Overflow in real_to_ints conversion of "//trim(mesg))
234 if (
present(efp_sum)) efp_sum%v(:) = ints_sum(:)
237 write(mesg,
'("2d RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:
numint)
244 overflow_check, err)
result(sum)
245 real(r4_kind),
dimension(:,:),
intent(in) :: array
246 integer,
optional,
intent(in) :: isr, ier, jsr, jer
248 logical,
optional,
intent(in) :: reproducing
249 logical,
optional,
intent(in) :: overflow_check
250 integer,
optional,
intent(out) :: err
253 real(r8_kind) :: array_r8(size(array,1), size(array,2))
258 overflow_check, err), r4_kind)
271 real(r8_kind),
dimension(:,:,:),
intent(in) :: array
272 integer,
optional,
intent(in) :: isr, ier, jsr, jer
273 real(r8_kind),
dimension(:),
optional,
intent(out) :: sums
275 integer,
optional,
intent(out) :: err
278 real(r8_kind) :: max_mag_term
279 integer(i8_kind),
dimension(NUMINT) :: ints_sum
280 integer(i8_kind),
dimension(NUMINT,size(array,3)) :: ints_sums
281 integer(i8_kind) :: prec_error
282 character(len=256) :: mesg
283 integer :: i, j, k, is, ie, js, je, ke, isz, jsz, n
286 "mpp_reproducing_sum: Too many processors are being used for the value of "//&
287 "prec. Reduce prec to (2^63-1)/mpp_npes.")
289 prec_error = (2_8**62 + (2_8**62 - 1)) /
mpp_npes()
292 is = 1 ; ie =
size(array,1) ; js = 1 ; je =
size(array,2) ; ke =
size(array,3)
293 if (
present(isr))
then
295 "Value of isr too small in mpp_reproducing_sum(_3d).")
298 if (
present(ier))
then
300 "Value of ier too large in mpp_reproducing_sum(_3d).")
303 if (
present(jsr))
then
305 "Value of jsr too small in mpp_reproducing_sum(_3d).")
308 if (
present(jer))
then
310 "Value of jer too large in mpp_reproducing_sum(_3d).")
313 jsz = je+1-js; isz = ie+1-is
315 if (
present(sums))
then
316 if (
size(sums) > ke)
call mpp_error(fatal,
"Sums is smaller than "//&
317 "the vertical extent of array in mpp_reproducing_sum(_3d).")
319 overflow_error = .false. ; nan_error = .false. ; max_mag_term = 0.0
322 do j=js,je ;
do i=is,ie
328 do k=1,ke ;
do j=js,je
335 do k=1,ke ;
do j=js,je ;
do i=is,ie
338 enddo ;
enddo ;
enddo
340 if (
present(err))
then
342 if (abs(max_mag_term) >= prec_error*pr(1)) err = err+1
343 if (overflow_error) err = err+2
344 if (nan_error) err = err+2
345 if (err > 0)
then ;
do k=1,ke ;
do n=1,
numint ; ints_sums(n,k) = 0 ;
enddo ;
enddo ;
endif
348 "NaN in input field of mpp_reproducing_sum(_3d), this indicates numerical instability")
349 if (abs(max_mag_term) >= prec_error*pr(1))
then
350 write(mesg,
'(ES13.5)') max_mag_term
351 call mpp_error(fatal,
"Overflow in mpp_reproducing_sum(_3d) conversion of "//trim(mesg))
353 if (overflow_error)
call mpp_error(fatal,
"Overflow in mpp_reproducing_sum(_3d).")
365 if (
present(efp_sum))
then
367 do k=1,ke ;
call increment_ints(efp_sum%v(:), ints_sums(:,k)) ;
enddo
371 do n=1,
numint ; ints_sum(n) = 0 ;
enddo
372 do k=1,ke ;
do n=1,
numint ; ints_sum(n) = ints_sum(n) + ints_sums(n,k) ;
enddo ;
enddo
373 write(mesg,
'("3D RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:
numint)
378 overflow_error = .false. ; nan_error = .false. ; max_mag_term = 0.0
381 do j=js,je ;
do i=is,ie
387 do k=1,ke ;
do j=js,je
394 do k=1,ke ;
do j=js,je ;
do i=is,ie
397 enddo ;
enddo ;
enddo
399 if (
present(err))
then
401 if (abs(max_mag_term) >= prec_error*pr(1)) err = err+1
402 if (overflow_error) err = err+2
403 if (nan_error) err = err+2
404 if (err > 0)
then ;
do n=1,
numint ; ints_sum(n) = 0 ;
enddo ;
endif
407 "NaN in input field of mpp_reproducing_sum(_3d), this indicates numerical instability")
408 if (abs(max_mag_term) >= prec_error*pr(1))
then
409 write(mesg,
'(ES13.5)') max_mag_term
410 call mpp_error(fatal,
"Overflow in mpp_reproducing_sum(_3d) conversion of "//trim(mesg))
412 if (overflow_error)
call mpp_error(fatal,
"Overflow in mpp_reproducing_sum(_3d).")
420 if (
present(efp_sum)) efp_sum%v(:) = ints_sum(:)
423 write(mesg,
'("3d RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:
numint)
433 real(r8_kind),
intent(in) :: r
434 integer(i8_kind),
optional,
intent(in) :: prec_error
435 logical,
optional,
intent(inout) :: overflow
436 integer(i8_kind),
dimension(NUMINT) :: ints
439 character(len=80) :: mesg
440 integer(i8_kind) :: ival, prec_err
443 prec_err =
prec ;
if (
present(prec_error)) prec_err = prec_error
445 if ((r >= 1e30) .eqv. (r < 1e30))
then ; nan_error = .true. ;
return ;
endif
447 sgn = 1 ;
if (r<0.0) sgn = -1
450 if (
present(overflow))
then
451 if (.not.(rs < prec_err*pr(1))) overflow = .true.
452 if ((r >= 1e30) .eqv. (r < 1e30)) overflow = .true.
453 elseif (.not.(rs < prec_err*pr(1)))
then
454 write(mesg,
'(ES13.5)') r
455 call mpp_error(fatal,
"Overflow in real_to_ints conversion of "//trim(mesg))
459 ival = int(rs*i_pr(i), 8)
468 integer(i8_kind),
dimension(NUMINT),
intent(in) :: ints
474 do i=1,
numint ; r = r + pr(i)*ints(i) ;
enddo
480 integer(i8_kind),
dimension(NUMINT),
intent(inout) :: int_sum
481 integer(i8_kind),
dimension(NUMINT),
intent(in) :: int2
482 integer(i8_kind),
optional,
intent(in) :: prec_error
487 int_sum(i) = int_sum(i) + int2(i)
489 if (int_sum(i) >
prec)
then
490 int_sum(i) = int_sum(i) -
prec
491 int_sum(i-1) = int_sum(i-1) + 1
492 elseif (int_sum(i) < -
prec)
then
493 int_sum(i) = int_sum(i) +
prec
494 int_sum(i-1) = int_sum(i-1) - 1
497 int_sum(1) = int_sum(1) + int2(1)
498 if (
present(prec_error))
then
499 if (abs(int_sum(1)) > prec_error) overflow_error = .true.
501 if (abs(int_sum(1)) >
prec) overflow_error = .true.
510 integer(i8_kind),
dimension(NUMINT),
intent(inout) :: int_sum
511 real(r8_kind),
intent(in) :: r
512 real(r8_kind),
intent(inout) :: max_mag_term
515 integer(i8_kind) :: ival
518 if ((r >= 1e30) .eqv. (r < 1e30))
then ; nan_error = .true. ;
return ;
endif
519 sgn = 1 ;
if (r<0.0) sgn = -1
521 if (rs > abs(max_mag_term)) max_mag_term = r
524 ival = int(rs*i_pr(i), 8)
526 int_sum(i) = int_sum(i) + sgn*ival
533 integer(i8_kind),
dimension(NUMINT),
intent(inout) :: int_sum
534 integer(i8_kind),
intent(in) :: prec_error
536 integer :: i, num_carry
538 do i=
numint,2,-1 ;
if (abs(int_sum(i)) >
prec)
then
539 num_carry = int(int_sum(i) *
i_prec)
540 int_sum(i) = int_sum(i) - num_carry*
prec
541 int_sum(i-1) = int_sum(i-1) + num_carry
543 if (abs(int_sum(1)) > prec_error)
then
544 overflow_error = .true.
552 integer(i8_kind),
dimension(NUMINT),
intent(inout) :: int_sum
555 integer :: i, num_carry
557 do i=
numint,2,-1 ;
if (abs(int_sum(i)) >
prec)
then
558 num_carry = int(int_sum(i) *
i_prec)
559 int_sum(i) = int_sum(i) - num_carry*
prec
560 int_sum(i-1) = int_sum(i-1) + num_carry
566 if (abs(int_sum(i)) > 0)
then
567 if (int_sum(i) < 0) positive = .false.
573 do i=
numint,2,-1 ;
if (int_sum(i) < 0)
then
574 int_sum(i) = int_sum(i) +
prec
575 int_sum(i-1) = int_sum(i-1) - 1
578 do i=
numint,2,-1 ;
if (int_sum(i) > 0)
then
579 int_sum(i) = int_sum(i) -
prec
580 int_sum(i-1) = int_sum(i-1) + 1
586 function mpp_query_efp_overflow_error()
587 logical :: mpp_query_efp_overflow_error
588 mpp_query_efp_overflow_error = overflow_error
589 end function mpp_query_efp_overflow_error
591 subroutine mpp_reset_efp_overflow_error()
592 overflow_error = .false.
593 end subroutine mpp_reset_efp_overflow_error
595 function mpp_efp_plus(EFP1, EFP2)
602 end function mpp_efp_plus
604 function mpp_efp_minus(EFP1, EFP2)
609 do i=1,
numint ; mpp_efp_minus%v(i) = -1*efp2%v(i) ;
enddo
612 end function mpp_efp_minus
617 subroutine mpp_efp_assign(EFP1, EFP2)
622 do i=1,
numint ; efp1%v(i) = efp2%v(i) ;
enddo
623 end subroutine mpp_efp_assign
625 function mpp_efp_to_real(EFP1)
627 real(r8_kind) :: mpp_efp_to_real
631 end function mpp_efp_to_real
633 function mpp_efp_real_diff(EFP1, EFP2)
635 real(r8_kind) :: mpp_efp_real_diff
639 efp_diff = efp1 - efp2
640 mpp_efp_real_diff = mpp_efp_to_real(efp_diff)
642 end function mpp_efp_real_diff
644 function mpp_real_to_efp(val, overflow)
645 real(r8_kind),
intent(in) :: val
646 logical,
optional,
intent(inout) :: overflow
650 character(len=80) :: mesg
652 if (
present(overflow))
then
653 mpp_real_to_efp%v(:) =
real_to_ints(val, overflow=overflow)
658 write(mesg,
'(ES13.5)') val
659 call mpp_error(fatal,
"Overflow in mpp_real_to_efp conversion of "//trim(mesg))
663 end function mpp_real_to_efp
669 integer,
intent(in) :: nval
670 logical,
dimension(:),
optional,
intent(out) :: errors
672 integer(i8_kind),
dimension(NUMINT,nval) :: ints
673 integer(i8_kind) :: prec_error
674 logical :: error_found
675 character(len=256) :: mesg
679 "mpp_efp_list_sum_across_PEs: Too many processors are being used for the value of "//&
680 "prec. Reduce prec to (2^63-1)/mpp_npes.")
682 prec_error = (2_8**62 + (2_8**62 - 1)) /
mpp_npes()
684 overflow_error = .false. ; error_found = .false.
686 do i=1,nval ;
do n=1,
numint ; ints(n,i) = efps(i)%v(n) ;
enddo ;
enddo
690 if (
present(errors)) errors(:) = .false.
692 overflow_error = .false.
694 do n=1,
numint ; efps(i)%v(n) = ints(n,i) ;
enddo
695 if (
present(errors)) errors(i) = overflow_error
696 if (overflow_error)
then
697 write (mesg,
'("mpp_efp_list_sum_across_PEs error at ",i6," val was ",ES13.6, ", prec_error = ",ES13.6)') &
698 i, mpp_efp_to_real(efps(i)), real(prec_error)
701 error_found = error_found .or. overflow_error
703 if (error_found .and. .not.(
present(errors)))
then
704 call mpp_error(fatal,
"Overflow in mpp_efp_list_sum_across_PEs.")
709 end module mpp_efp_mod
integer, parameter max_count_prec
The number of values that can be added together with the current value of prec before there will be r...
subroutine increment_ints_faster(int_sum, r, max_mag_term)
This subroutine increments a number with another, both using the integer representation in real_to_in...
logical debug
Making this true enables debugging output.
subroutine carry_overflow(int_sum, prec_error)
This subroutine handles carrying of the overflow.
real(r8_kind), parameter i_prec
The inverse of prec.
integer(i8_kind) function, dimension(numint) real_to_ints(r, prec_error, overflow)
This function converts a real number to an equivalent representation using several long integers.
real(r8_kind) function mpp_reproducing_sum_r8_2d(array, isr, ier, jsr, jer, EFP_sum, reproducing, overflow_check, err)
Calculates a reproducing sum for a 2D, 8-byte real array.
real(r8_kind), parameter r_prec
A real version of prec.
integer, parameter numint
The number of long integers to use to represent a real number.
integer(i8_kind), parameter prec
The precision of each integer.
real(r8_kind) function mpp_reproducing_sum_r8_3d(array, isr, ier, jsr, jer, sums, EFP_sum, err)
Reproducing sum for 3d arrays of 8-bit reals.
subroutine increment_ints(int_sum, int2, prec_error)
This subroutine increments a number with another, both using the integer representation in real_to_in...
real(r4_kind) function mpp_reproducing_sum_r4_2d(array, isr, ier, jsr, jer, EFP_sum, reproducing, overflow_check, err)
real(r8_kind) function ints_to_real(ints)
This function reverses the conversion in real_to_ints.
subroutine regularize_ints(int_sum)
This subroutine carries the overflow, and then makes sure that all integers are of the same sign as t...
subroutine, public mpp_efp_list_sum_across_pes(EFPs, nval, errors)
This subroutine does a sum across PEs of a list of EFP variables, returning the sums in place,...
This interface uses a conversion to an integer representation of real numbers to give order-invariant...
The Extended Fixed Point (mpp_efp) type provides a public interface for doing sums and taking differe...
integer function mpp_npes()
Returns processor count for current pelist.
integer function mpp_pe()
Returns processor ID.