This subroutine uses a conversion to an integer representation of real numbers to give an order-invariant sum of distributed 3-D arrays that reproduces across domain decomposition. This technique is described in Hallberg & Adcroft, 2014, Parallel Computing, doi:10.1016/j.parco.2014.04.007.
245 real,
dimension(:,:,:),
intent(in) :: array
246 integer,
optional,
intent(in) :: isr
248 integer,
optional,
intent(in) :: ier
250 integer,
optional,
intent(in) :: jsr
252 integer,
optional,
intent(in) :: jer
254 real,
dimension(:),
optional,
intent(out) :: sums
255 type(EFP_type),
optional,
intent(out) :: EFP_sum
256 integer,
optional,
intent(out) :: err
266 integer(kind=8),
dimension(ni) :: ints_sum
267 integer(kind=8),
dimension(ni,size(array,3)) :: ints_sums
268 integer(kind=8) :: prec_error
269 character(len=256) :: mesg
270 integer :: i, j, k, is, ie, js, je, ke, isz, jsz, n
272 if (num_pes() > max_count_prec)
call mom_error(fatal, &
273 "reproducing_sum: Too many processors are being used for the value of "//&
274 "prec. Reduce prec to (2^63-1)/num_PEs.")
276 prec_error = (2_8**62 + (2_8**62 - 1)) / num_pes()
279 is = 1 ; ie =
size(array,1) ; js = 1 ; je =
size(array,2) ; ke =
size(array,3)
280 if (
present(isr))
then
281 if (isr < is)
call mom_error(fatal, &
282 "Value of isr too small in reproducing_sum(_3d).")
285 if (
present(ier))
then
286 if (ier > ie)
call mom_error(fatal, &
287 "Value of ier too large in reproducing_sum(_3d).")
290 if (
present(jsr))
then
291 if (jsr < js)
call mom_error(fatal, &
292 "Value of jsr too small in reproducing_sum(_3d).")
295 if (
present(jer))
then
296 if (jer > je)
call mom_error(fatal, &
297 "Value of jer too large in reproducing_sum(_3d).")
300 jsz = je+1-js; isz = ie+1-is
302 if (
present(sums))
then
303 if (
size(sums) > ke)
call mom_error(fatal,
"Sums is smaller than "//&
304 "the vertical extent of array in reproducing_sum(_3d).")
306 overflow_error = .false. ; nan_error = .false. ; max_mag_term = 0.0
307 if (jsz*isz < max_count_prec)
then
309 do j=js,je ;
do i=is,ie
310 call increment_ints_faster(ints_sums(:,k), array(i,j,k), max_mag_term)
312 call carry_overflow(ints_sums(:,k), prec_error)
314 elseif (isz < max_count_prec)
then
315 do k=1,ke ;
do j=js,je
317 call increment_ints_faster(ints_sums(:,k), array(i,j,k), max_mag_term)
319 call carry_overflow(ints_sums(:,k), prec_error)
322 do k=1,ke ;
do j=js,je ;
do i=is,ie
323 call increment_ints(ints_sums(:,k), &
324 real_to_ints(array(i,j,k), prec_error), prec_error)
325 enddo ;
enddo ;
enddo
327 if (
present(err))
then
329 if (abs(max_mag_term) >= prec_error*pr(1)) err = err+1
330 if (overflow_error) err = err+2
331 if (nan_error) err = err+2
332 if (err > 0)
then ;
do k=1,ke ;
do n=1,ni ; ints_sums(n,k) = 0 ;
enddo ;
enddo ;
endif
334 if (nan_error)
call mom_error(fatal,
"NaN in input field of reproducing_sum(_3d).")
335 if (abs(max_mag_term) >= prec_error*pr(1))
then
336 write(mesg,
'(ES13.5)') max_mag_term
337 call mom_error(fatal,
"Overflow in reproducing_sum(_3d) conversion of "//trim(mesg))
339 if (overflow_error)
call mom_error(fatal,
"Overflow in reproducing_sum(_3d).")
342 call sum_across_pes(ints_sums(:,1:ke), ni*ke)
346 call regularize_ints(ints_sums(:,k))
347 sums(k) = ints_to_real(ints_sums(:,k))
351 if (
present(efp_sum))
then
353 do k=1,ke ;
call increment_ints(efp_sum%v(:), ints_sums(:,k)) ;
enddo
357 do n=1,ni ; ints_sum(n) = 0 ;
enddo
358 do k=1,ke ;
do n=1,ni ; ints_sum(n) = ints_sum(n) + ints_sums(n,k) ;
enddo ;
enddo
359 write(mesg,
'("3D RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:ni)
360 call mom_mesg(mesg, 3)
364 overflow_error = .false. ; nan_error = .false. ; max_mag_term = 0.0
365 if (jsz*isz < max_count_prec)
then
367 do j=js,je ;
do i=is,ie
368 call increment_ints_faster(ints_sum, array(i,j,k), max_mag_term)
370 call carry_overflow(ints_sum, prec_error)
372 elseif (isz < max_count_prec)
then
373 do k=1,ke ;
do j=js,je
375 call increment_ints_faster(ints_sum, array(i,j,k), max_mag_term)
377 call carry_overflow(ints_sum, prec_error)
380 do k=1,ke ;
do j=js,je ;
do i=is,ie
381 call increment_ints(ints_sum, real_to_ints(array(i,j,k), prec_error), &
383 enddo ;
enddo ;
enddo
385 if (
present(err))
then
387 if (abs(max_mag_term) >= prec_error*pr(1)) err = err+1
388 if (overflow_error) err = err+2
389 if (nan_error) err = err+2
390 if (err > 0)
then ;
do n=1,ni ; ints_sum(n) = 0 ;
enddo ;
endif
392 if (nan_error)
call mom_error(fatal,
"NaN in input field of reproducing_sum(_3d).")
393 if (abs(max_mag_term) >= prec_error*pr(1))
then
394 write(mesg,
'(ES13.5)') max_mag_term
395 call mom_error(fatal,
"Overflow in reproducing_sum(_3d) conversion of "//trim(mesg))
397 if (overflow_error)
call mom_error(fatal,
"Overflow in reproducing_sum(_3d).")
400 call sum_across_pes(ints_sum, ni)
402 call regularize_ints(ints_sum)
403 sum = ints_to_real(ints_sum)
405 if (
present(efp_sum)) efp_sum%v(:) = ints_sum(:)
408 write(mesg,
'("3d RS: ", ES24.16, 6 Z17.16)') sum, ints_sum(1:ni)
409 call mom_mesg(mesg, 3)