Line data Source code
1 : module par_vecsum_mod 2 : 3 : implicit none 4 : private 5 : save 6 : public :: par_vecsum 7 : 8 : contains 9 : !----------------------------------------------------------------------- 10 : !BOP 11 : ! !ROUTINE: par_vecsum --- Calculate vector sum bit-wise consistently 12 : ! 13 : ! !INTERFACE: 14 : !****6***0*********0*********0*********0*********0*********0**********72 15 0 : subroutine par_vecsum(jm, jfirst, jlast, InVector, te0, & 16 : incomm, npryuse, return_sum_in) 17 : !****6***0*********0*********0*********0*********0*********0**********72 18 : ! 19 : ! !USES: 20 : #if defined ( SPMD ) 21 : use parutilitiesmodule, only : parexchangevector 22 : #endif 23 : use shr_kind_mod, only: r8 => shr_kind_r8 24 : 25 : implicit none 26 : 27 : ! !INPUT PARAMETERS: 28 : integer jm ! global latitudes 29 : integer jfirst ! first latitude on this PE 30 : integer jlast ! last latitude on this PE 31 : real (r8) InVector(jm) ! input vector to be summed 32 : integer incomm ! communicator 33 : integer npryuse ! number of subdomains 34 : 35 : logical, optional :: return_sum_in 36 : 37 : ! !OUTPUT PARAMETERS: 38 : real (r8) te0 ! sum of all vector entries 39 : 40 : ! !DESCRIPTION: 41 : ! This subroutine calculates the sum of InVector in a reproducible 42 : ! (sequentialized) fashion which should give bit-wise identical 43 : ! results irrespective of the number of MPI processes. 44 : ! 45 : ! !CALLED FROM: 46 : ! te_map and benergy 47 : ! 48 : ! !REVISION HISTORY: 49 : ! 50 : ! BWS 00.01.15 : Created 51 : ! WS 00.06.02 : Replaced MPI calls with ParExchangeVector; docu. 52 : ! WS 00.08.29 : SPMD instead of MPI_ON 53 : ! AM 01.06.15 : general communicator 54 : ! 55 : !EOP 56 : !--------------------------------------------------------------------- 57 : !BOC 58 : 59 : ! !Local 60 : real(r8), parameter :: D0_0 = 0.0_r8 61 0 : real (r8) tte_all(jm) 62 : integer j 63 : logical :: return_sum 64 : 65 : #if defined ( SPMD ) 66 0 : real (r8) tte_send(npryuse*(jlast-jfirst+1)) 67 0 : integer sendcount(npryuse) 68 0 : integer recvcount(npryuse) 69 : integer ipe, icount 70 : #endif 71 0 : if (present(return_sum_in)) then 72 0 : return_sum = return_sum_in 73 : else 74 : return_sum = .false. 75 : end if 76 : 77 0 : te0 = D0_0 78 : #if defined ( SPMD ) 79 0 : icount=0 80 0 : do ipe=1,npryuse 81 0 : sendcount(ipe) = jlast-jfirst+1 82 0 : do j=jfirst, jlast 83 0 : icount=icount+1 84 0 : tte_send(icount)=InVector(j) 85 : enddo 86 : enddo 87 : call parexchangevector( incomm, sendcount, tte_send, & 88 0 : recvcount, tte_all ) 89 : #else 90 : do j=1, jm 91 : tte_all(j)=InVector(j) 92 : enddo 93 : #endif 94 : 95 0 : te0 = D0_0 96 0 : te0 = te0 + tte_all(1) !in oder to compare to SMP-only 97 0 : te0 = te0 + tte_all(jm) !in oder to compare to SMP-only 98 : 99 0 : do j=2,jm-1 100 0 : te0 = te0 + tte_all(j) 101 : enddo 102 : 103 0 : if (return_sum) InVector(1:jm) = tte_all(1:jm) 104 : 105 0 : return 106 : !EOC 107 : end subroutine par_vecsum 108 : !----------------------------------------------------------------------- 109 : 110 : end module par_vecsum_mod