m_SpatialIntegral.F90 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! Math and Computer Science Division, Argonne National Laboratory !
  3. !-----------------------------------------------------------------------
  4. ! CVS m_SpatialIntegral.F90,v 1.22 2008-05-12 01:59:33 jacob Exp
  5. ! CVS MCT_2_8_0
  6. !BOP -------------------------------------------------------------------
  7. !
  8. ! !MODULE: m_SpatialIntegral - Spatial Integrals and Averages using a GeneralGrid
  9. !
  10. ! !DESCRIPTION: This module provides spatial integration and averaging
  11. ! services for the MCT. For a field $\Phi$ sampled at a point ${\bf x}$
  12. ! in some multidimensional domain $\Omega$, the integral $I$ of
  13. ! $\Phi({\bf x})$ is
  14. ! $$ I = \int_{\Omega} \Phi ({\bf x}) d\Omega .$$
  15. ! The spatial average $A$ of $\Phi({\bf x})$ over $\Omega$ is
  16. ! $$ A = {{ \int_{\Omega} \Phi ({\bf x}) d\Omega} \over
  17. ! { \int_{\Omega} d\Omega} }. $$
  18. ! Since the {\tt AttrVect} represents a discretized field, the integrals
  19. ! above are implemented as:
  20. ! $$ I = \sum_{i=1}^N \Phi_i \Delta \Omega_i $$
  21. ! and
  22. ! $$ A = {{\sum_{i=1}^N \Phi_i \Delta \Omega_i } \over
  23. !{\sum_{i=1}^N \Delta \Omega_i } }, $$
  24. ! where $N$ is the number of physical locations, $\Phi_i$ is the value
  25. ! of the field $\Phi$ at location $i$, and $\Delta \Omega_i$ is the spatial
  26. ! weight (lenghth element, cross-sectional area element, volume element,
  27. ! {\em et cetera}) at location $i$.
  28. !
  29. ! MCT extends the concept of integrals and area/volume averages to include
  30. ! {\em masked} integrals and averages. MCT recognizes both {\em integer}
  31. ! and {\em real} masks. An integer mask $M$ is a vector of integers (one
  32. ! corresponding to each physical location) with each element having value
  33. ! either zero or one. Integer masks are used to include/exclude data from
  34. ! averages or integrals. For example, if one were to compute globally
  35. ! averaged cloud amount over land (but not ocean nor sea-ice), one would
  36. ! assign a $1$ to each location on the land and a $0$ to each non-land
  37. ! location. A {\em real} mask $F$ is a vector of real numbers (one corresponding
  38. ! to each physical location) with each element having value within the
  39. ! closed interval $[0,1]$. .Real masks are used to represent fractional
  40. ! area/volume coverage at a location by a given component model. For
  41. ! example, if one wishes to compute area averages over sea-ice, one must
  42. ! include the ice fraction present at each point. Masked Integrals and
  43. ! averages are represented in the MCT by:
  44. ! $$ I = \sum_{i=1}^N {\prod_{j=1}^J M_i} {\prod_{k=1}^K F_i}
  45. ! \Phi_i \Delta \Omega_i $$
  46. ! and
  47. ! $$ A = {{\sum_{i=1}^N \bigg({\prod_{j=1}^J M_i}\bigg) \bigg( {\prod_{k=1}^K F_i}
  48. ! \bigg) \Phi_i
  49. ! \Delta \Omega_i } \over
  50. !{\sum_{i=1}^N \bigg({\prod_{j=1}^J M_i}\bigg) \bigg( {\prod_{k=1}^K F_i} \bigg)
  51. ! \Delta \Omega_i } }, $$
  52. ! where $J$ is the number of integer masks and $K$ is the number of real masks.
  53. !
  54. ! All of the routines in this module assume field data is stored in an
  55. ! attribute vector ({\tt AttrVect}), and the integration/averaging is performed
  56. ! only on the {\tt REAL} attributes. Physical coordinate grid and mask
  57. ! information is assumed to be stored as attributes in either a
  58. ! {\tt GeneralGrid}, or pre-combined into a single integer mask and a single
  59. ! real mask.
  60. !
  61. ! !INTERFACE:
  62. module m_SpatialIntegral
  63. implicit none
  64. private ! except
  65. ! !PUBLIC MEMBER FUNCTIONS:
  66. public :: SpatialIntegral ! Spatial Integral
  67. public :: SpatialAverage ! Spatial Area Average
  68. public :: MaskedSpatialIntegral ! Masked Spatial Integral
  69. public :: MaskedSpatialAverage ! MaskedSpatial Area Average
  70. public :: PairedSpatialIntegrals ! A Pair of Spatial
  71. ! Integrals
  72. public :: PairedSpatialAverages ! A Pair of Spatial
  73. ! Area Averages
  74. public :: PairedMaskedSpatialIntegrals ! A Pair of Masked
  75. ! Spatial Integrals
  76. public :: PairedMaskedSpatialAverages ! A Pair of Masked
  77. ! Spatial Area Averages
  78. interface SpatialIntegral ; module procedure &
  79. SpatialIntegralRAttrGG_
  80. end interface
  81. interface SpatialAverage ; module procedure &
  82. SpatialAverageRAttrGG_
  83. end interface
  84. interface MaskedSpatialIntegral ; module procedure &
  85. MaskedSpatialIntegralRAttrGG_
  86. end interface
  87. interface MaskedSpatialAverage ; module procedure &
  88. MaskedSpatialAverageRAttrGG_
  89. end interface
  90. interface PairedSpatialIntegrals ; module procedure &
  91. PairedSpatialIntegralRAttrGG_
  92. end interface
  93. interface PairedSpatialAverages ; module procedure &
  94. PairedSpatialAverageRAttrGG_
  95. end interface
  96. interface PairedMaskedSpatialIntegrals ; module procedure &
  97. PairedMaskedIntegralRAttrGG_
  98. end interface
  99. interface PairedMaskedSpatialAverages ; module procedure &
  100. PairedMaskedAverageRAttrGG_
  101. end interface
  102. ! !REVISION HISTORY:
  103. ! 25Oct01 - J.W. Larson <larson@mcs.anl.gov> - Initial version
  104. ! 9May02 - J.W. Larson <larson@mcs.anl.gov> - Massive Refactoring.
  105. ! 10-14Jun02 - J.W. Larson <larson@mcs.anl.gov> - Added Masked methods.
  106. ! 17-18Jun02 - J.W. Larson <larson@mcs.anl.gov> - Added Paired/Masked
  107. ! methods.
  108. ! 18Jun02 - J.W. Larson <larson@mcs.anl.gov> - Renamed module from
  109. ! m_GlobalIntegral to m_SpatialIntegral.
  110. ! 15Jan03 - E.T. Ong <eong@mcs.anl.gov> - Initialized real-only
  111. ! AttrVects using nullfied integer lists. This circuitous
  112. ! hack was required because the compaq compiler does not
  113. ! compile the function AttrVectExportListToChar.
  114. !
  115. !EOP ___________________________________________________________________
  116. character(len=*),parameter :: myname='MCT::m_SpatialIntegral'
  117. contains
  118. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  119. ! Math and Computer Science Division, Argonne National Laboratory !
  120. !BOP -------------------------------------------------------------------
  121. !
  122. ! !IROUTINE: SpatialIntegralRAttrGG_ - Compute spatial integral.
  123. !
  124. ! !DESCRIPTION:
  125. ! This routine computes spatial integrals of the {\tt REAL} attributes
  126. ! of the {\tt REAL} attributes of the input {\tt AttrVect} argument
  127. ! {\tt inAv}. {\tt SpatialIntegralRAttrGG\_()} takes the input
  128. ! {\tt AttrVect} argument {\tt inAv} and computes the spatial
  129. ! integral using weights stored in the {\tt GeneralGrid} argument
  130. ! {\tt GGrid} and identified by the {\tt CHARACTER} tag {\tt WeightTag}.
  131. ! The integral of each {\tt REAL} attribute is returned in the output
  132. ! {\tt AttrVect} argument {\tt outAv}. If {\tt SpatialIntegralRAttrGG\_()}
  133. ! is invoked with the optional {\tt LOGICAL} input argument
  134. ! {\tt SumWeights} set as {\tt .TRUE.}, then the weights are also summed
  135. ! and stored in {\tt outAv} (and can be referenced with the attribute
  136. ! tag defined by the argument{\tt WeightTag}. If
  137. ! {\tt SpatialIntegralRAttrGG\_()} is invoked with the optional {\tt INTEGER}
  138. ! argument {\tt comm} (a Fortran MPI communicator handle), the summation
  139. ! operations for the integral are completed on the local process, then
  140. ! reduced across the communicator, with all processes receiving the result.
  141. !
  142. ! {\bf N.B.: } The local lengths of the {\tt AttrVect} argument {\tt inAv}
  143. ! and the {\tt GeneralGrid} {\tt GGrid} must be equal. That is, there
  144. ! must be a one-to-one correspondence between the field point values stored
  145. ! in {\tt inAv} and the point weights stored in {\tt GGrid}.
  146. !
  147. ! {\bf N.B.: } If {\tt SpatialIntegralRAttrGG\_()} is invoked with the
  148. ! optional {\tt LOGICAL} input argument {\tt SumWeights} set as {\tt .TRUE.},
  149. ! then the value of {\tt WeightTag} must not conflict with any of the
  150. ! {\tt REAL} attribute tags in {\tt inAv}.
  151. !
  152. ! {\bf N.B.: } The output {\tt AttrVect} argument {\tt outAv} is an
  153. ! allocated data structure. The user must deallocate it using the routine
  154. ! {\tt AttrVect\_clean()} when it is no longer needed. Failure to do so
  155. ! will result in a memory leak.
  156. !
  157. ! !INTERFACE:
  158. subroutine SpatialIntegralRAttrGG_(inAv, outAv, GGrid, WeightTag, &
  159. SumWeights, comm)
  160. ! ! USES:
  161. use m_stdio
  162. use m_die
  163. use m_mpif90
  164. use m_realkinds, only : FP
  165. use m_AttrVect, only : AttrVect
  166. use m_AttrVect, only : AttrVect_lsize => lsize
  167. use m_GeneralGrid, only : GeneralGrid
  168. use m_GeneralGrid, only : GeneralGrid_lsize => lsize
  169. use m_GeneralGrid, only : GeneralGrid_indexRA => indexRA
  170. use m_GeneralGrid, only : GeneralGrid_exportRAttr => exportRAttr
  171. use m_SpatialIntegralV, only: SpatialIntegralV
  172. implicit none
  173. ! !INPUT PARAMETERS:
  174. type(AttrVect), intent(IN) :: inAv
  175. type(GeneralGrid), intent(IN) :: GGrid
  176. character(len=*), intent(IN) :: WeightTag
  177. logical, optional, intent(IN) :: SumWeights
  178. integer, optional, intent(IN) :: comm
  179. ! !OUTPUT PARAMETERS:
  180. type(AttrVect), intent(OUT) :: outAv
  181. ! !REVISION HISTORY:
  182. ! 06Feb02 - J.W. Larson <larson@mcs.anl.gov> - initial version
  183. ! 09May02 - J.W. Larson <larson@mcs.anl.gov> - Refactored and
  184. ! renamed SpatialIntegralRAttrGG_().
  185. ! 07Jun02 - J.W. Larson <larson@mcs.anl.gov> - Bug fix and further
  186. ! refactoring.
  187. !EOP ___________________________________________________________________
  188. character(len=*),parameter :: myname_=myname//'::SpatialIntegralRAttrGG_'
  189. integer :: ierr, length
  190. logical :: mySumWeights
  191. real(FP), dimension(:), pointer :: gridWeights
  192. ! Argument Validity Checks
  193. if(AttrVect_lsize(inAv) /= GeneralGrid_lsize(GGrid)) then
  194. ierr = AttrVect_lsize(inAv) - GeneralGrid_lsize(GGrid)
  195. write(stderr,'(3a,i8,a,i8)') myname_, &
  196. ':: inAv / GGrid length mismatch: ', &
  197. ' AttrVect_lsize(inAv) = ',AttrVect_lsize(inAv), &
  198. ' GeneralGrid_lsize(GGrid) = ',GeneralGrid_lsize(GGrid)
  199. call die(myname_)
  200. endif
  201. if(present(SumWeights)) then
  202. mySumWeights = SumWeights
  203. else
  204. mySumWeights = .FALSE.
  205. endif
  206. ! ensure unambiguous pointer association status for gridWeights
  207. nullify(gridWeights)
  208. ! Extract Grid Weights
  209. call GeneralGrid_exportRAttr(GGrid, WeightTag, gridWeights, length)
  210. !
  211. if(present(comm)) then ! do a distributed AllReduce-style integral:
  212. call SpatialIntegralV(inAv, outAv, gridWeights, mySumWeights, &
  213. WeightTag, comm)
  214. else
  215. call SpatialIntegralV(inAv, outAv, gridWeights, mySumWeights, &
  216. WeightTag)
  217. endif
  218. ! Clean up temporary allocated space
  219. deallocate(gridWeights, stat=ierr)
  220. if(ierr /= 0) then
  221. write(stderr,'(2a,i8)') myname_, &
  222. ':: deallocate(gridWeights...failed. ierr=', ierr
  223. call die(myname_)
  224. endif
  225. end subroutine SpatialIntegralRAttrGG_
  226. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  227. ! Math and Computer Science Division, Argonne National Laboratory !
  228. !BOP -------------------------------------------------------------------
  229. !
  230. ! !IROUTINE: SpatialAverageRAttrGG_ - Compute spatial average.
  231. !
  232. ! !DESCRIPTION:
  233. ! This routine computes spatial averages of the {\tt REAL} attributes
  234. ! of the input {\tt AttrVect} argument {\tt inAv}.
  235. ! {\tt SpatialAverageRAttrGG\_()} takes the input {\tt AttrVect} argument
  236. ! {\tt inAv} and computes the spatial average using weights
  237. ! stored in the {\tt GeneralGrid} argument {\tt GGrid} and identified by
  238. ! the {\tt CHARACTER} tag {\tt WeightTag}. The average of each {\tt REAL}
  239. ! attribute is returned in the output {\tt AttrVect} argument {\tt outAv}.
  240. ! If {\tt SpatialAverageRAttrGG\_()} is invoked with the optional {\tt INTEGER}
  241. ! argument {\tt comm} (a Fortran MPI communicator handle), the summation
  242. ! operations for the average are completed on the local process, then
  243. ! reduced across the communicator, with all processes receiving the result.
  244. !
  245. ! {\bf N.B.: } The local lengths of the {\tt AttrVect} argument {\tt inAv}
  246. ! and the {\tt GeneralGrid} {\tt GGrid} must be equal. That is, there
  247. ! must be a one-to-one correspondence between the field point values stored
  248. ! in {\tt inAv} and the point weights stored in {\tt GGrid}.
  249. !
  250. ! {\bf N.B.: } The output {\tt AttrVect} argument {\tt outAv} is an
  251. ! allocated data structure. The user must deallocate it using the routine
  252. ! {\tt AttrVect\_clean()} when it is no longer needed. Failure to do so
  253. ! will result in a memory leak.
  254. !
  255. ! !INTERFACE:
  256. subroutine SpatialAverageRAttrGG_(inAv, outAv, GGrid, WeightTag, comm)
  257. ! ! USES:
  258. use m_realkinds, only : FP
  259. use m_stdio
  260. use m_die
  261. use m_mpif90
  262. use m_AttrVect, only : AttrVect
  263. use m_AttrVect, only : AttrVect_init => init
  264. use m_AttrVect, only : AttrVect_zero => zero
  265. use m_AttrVect, only : AttrVect_clean => clean
  266. use m_AttrVect, only : AttrVect_nRAttr => nRAttr
  267. use m_AttrVect, only : AttrVect_indexRA => indexRA
  268. use m_GeneralGrid, only : GeneralGrid
  269. use m_List, only : List
  270. use m_List, only : List_nullify => nullify
  271. implicit none
  272. ! !INPUT PARAMETERS:
  273. type(AttrVect), intent(IN) :: inAv
  274. type(GeneralGrid), intent(IN) :: GGrid
  275. character(len=*), intent(IN) :: WeightTag
  276. integer, optional, intent(IN) :: comm
  277. ! !OUTPUT PARAMETERS:
  278. type(AttrVect), intent(OUT) :: outAv
  279. ! !REVISION HISTORY:
  280. ! 08Feb02 - J.W. Larson <larson@mcs.anl.gov> - initial version
  281. ! 08May02 - J.W. Larson <larson@mcs.anl.gov> - minor modifications:
  282. ! 1) renamed the routine to GlobalAverageRAttrGG_
  283. ! 2) changed calls to reflect new routine name
  284. ! GlobalIntegralRAttrGG_().
  285. ! 18Jun02 - J.W. Larson <larson@mcs.anl.gov> - Renamed routine to
  286. ! SpatialAverageRAttrGG_().
  287. !EOP ___________________________________________________________________
  288. character(len=*),parameter :: myname_=myname//'::SpatialAverageRAtttrGG_'
  289. type(AttrVect) :: integratedAv
  290. type(List) :: nullIList
  291. integer :: i, ierr, iweight
  292. ! Compute the spatial integral:
  293. if(present(comm)) then
  294. call SpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, WeightTag, &
  295. .TRUE., comm)
  296. else
  297. call SpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, WeightTag, &
  298. .TRUE.)
  299. endif
  300. ! Check value of summed weights (to avoid division by zero):
  301. iweight = AttrVect_indexRA(integratedAv, WeightTag)
  302. if(integratedAv%rAttr(iweight, 1) == 0._FP) then
  303. write(stderr,'(2a)') myname_, &
  304. '::ERROR--Global sum of grid weights is zero.'
  305. call die(myname_)
  306. endif
  307. ! Initialize output AttrVect outAv:
  308. call List_nullify(nullIList)
  309. call AttrVect_init(outAv, iList=nullIList, rList=inAv%rList, lsize=1)
  310. call AttrVect_zero(outAv)
  311. ! Divide by global weight sum to compute spatial averages from
  312. ! spatial integrals.
  313. do i=1,AttrVect_nRAttr(outAv)
  314. outAv%rAttr(i,1) = integratedAv%rAttr(i,1) &
  315. / integratedAv%rAttr(iweight,1)
  316. end do
  317. ! Clean up temporary AttrVect:
  318. call AttrVect_clean(integratedAv)
  319. end subroutine SpatialAverageRAttrGG_
  320. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  321. ! Math and Computer Science Division, Argonne National Laboratory !
  322. !BOP -------------------------------------------------------------------
  323. !
  324. ! !IROUTINE: MaskedSpatialIntegralRAttrGG_ - Masked spatial integral.
  325. !
  326. ! !DESCRIPTION:
  327. ! This routine computes masked spatial integrals of the {\tt REAL}
  328. ! attributes of the input {\tt AttrVect} argument {\tt inAv}, returning
  329. ! the masked integrals in the output {\tt AttrVect} {\tt outAv}. All of
  330. ! the masking data are assumed stored in the input {\tt GeneralGrid}
  331. ! argument {\tt GGrid}. If integer masks are to be used, their integer
  332. ! attribute names in {\tt GGrid} are named as a colon-delimited list
  333. ! in the optional {\tt CHARACTER} input argument {\tt iMaskTags}. Real
  334. ! masks (if desired) are referenced by their real attribute names in
  335. ! {\tt GGrid} are named as a colon-delimited list in the optional
  336. ! {\tt CHARACTER} input argument {\tt rMaskTags}. The user specifies
  337. ! a choice of mask combination method with the input {\tt LOGICAL} argument
  338. ! {\tt UseFastMethod}. If ${\tt UseFastMethod} = {\tt .FALSE.}$ this
  339. ! routine checks each mask entry to ensure that the integer masks contain
  340. ! only ones and zeroes, and that entries in the real masks are all in
  341. ! the closed interval $[0,1]$. If ${\tt UseFastMethod} = {\tt .TRUE.}$,
  342. ! this routine performs direct products of the masks, assuming that the
  343. ! user has validated them in advance. The optional {\tt LOGICAL} input
  344. ! argument {\tt SumWeights} determines whether the masked sum of the spatial
  345. ! weights is computed and returned in {\tt outAv} with the real attribute
  346. ! name supplied in the optional {\tt CHARACTER} input argument
  347. ! {\tt WeightSumTag}. This integral can either be a local (i.e. a global
  348. ! memory space operation), or a global distributed integral. The latter
  349. ! is the case if the optional input {\tt INTEGER} argument {\tt comm} is
  350. ! supplied (which corresponds to a Fortran MPI communicatior handle).
  351. !
  352. ! {\bf N.B.: } The local lengths of the {\tt AttrVect} argument {\tt inAv}
  353. ! and the input {\tt GeneralGrid} {\tt GGrid} must be equal. That is, there
  354. ! must be a one-to-one correspondence between the field point values stored
  355. ! in {\tt inAv} and the point weights stored in {\tt GGrid}.
  356. !
  357. ! {\bf N.B.: } If {\tt SpatialIntegralRAttrV\_()} is invoked with the
  358. ! optional {\tt LOGICAL} input argument {\tt SumWeights} set as {\tt .TRUE.}.
  359. ! In this case, the none of {\tt REAL} attribute tags in {\tt inAv} may be
  360. ! named the same as the string contained in {\tt WeightSumTag}, which is an
  361. ! attribute name reserved for the sum of the weights in the output {\tt AttrVect}
  362. ! {\tt outAv}.
  363. !
  364. ! {\bf N.B.: } The output {\tt AttrVect} argument {\tt outAv} is an
  365. ! allocated data structure. The user must deallocate it using the routine
  366. ! {\tt AttrVect\_clean()} when it is no longer needed. Failure to do so
  367. ! will result in a memory leak.
  368. !
  369. ! !INTERFACE:
  370. subroutine MaskedSpatialIntegralRAttrGG_(inAv, outAv, GGrid, SpatialWeightTag, &
  371. iMaskTags, rMaskTags, UseFastMethod, &
  372. SumWeights, WeightSumTag, comm)
  373. ! ! USES:
  374. use m_stdio
  375. use m_die
  376. use m_mpif90
  377. use m_realkinds, only : FP
  378. use m_String, only : String
  379. use m_String, only : String_toChar => toChar
  380. use m_String, only : String_clean => clean
  381. use m_List, only : List
  382. use m_List, only : List_init => init
  383. use m_List, only : List_clean => clean
  384. use m_List, only : List_nitem => nitem
  385. use m_List, only : List_get => get
  386. use m_AttrVect, only : AttrVect
  387. use m_AttrVect, only : AttrVect_lsize => lsize
  388. use m_GeneralGrid, only : GeneralGrid
  389. use m_GeneralGrid, only : GeneralGrid_lsize => lsize
  390. use m_GeneralGrid, only : GeneralGrid_indexRA => indexRA
  391. use m_GeneralGrid, only : GeneralGrid_exportIAttr => exportIAttr
  392. use m_GeneralGrid, only : GeneralGrid_exportRAttr => exportRAttr
  393. use m_AttrVectReduce, only : AttrVect_GlobalWeightedSumRAttr => &
  394. GlobalWeightedSumRAttr
  395. use m_AttrVectReduce, only : AttrVect_LocalWeightedSumRAttr => &
  396. LocalWeightedSumRAttr
  397. use m_SpatialIntegralV, only : MaskedSpatialIntegralV
  398. implicit none
  399. ! !INPUT PARAMETERS:
  400. type(AttrVect), intent(IN) :: inAv
  401. type(GeneralGrid), intent(IN) :: GGrid
  402. character(len=*), intent(IN) :: SpatialWeightTag
  403. character(len=*), optional, intent(IN) :: iMaskTags
  404. character(len=*), optional, intent(IN) :: rMaskTags
  405. logical, intent(IN) :: UseFastMethod
  406. logical, optional, intent(IN) :: SumWeights
  407. character(len=*), optional, intent(IN) :: WeightSumTag
  408. integer, optional, intent(IN) :: comm
  409. ! !OUTPUT PARAMETERS:
  410. type(AttrVect), intent(OUT) :: outAv
  411. ! !REVISION HISTORY:
  412. ! 11Jun02 - J.W. Larson <larson@mcs.anl.gov> - initial version
  413. !
  414. !EOP ___________________________________________________________________
  415. character(len=*),parameter :: myname_=myname//'::MaskedSpatialIntegralRAttrGG_'
  416. integer :: i, ierr, j, length
  417. logical :: mySumWeights
  418. type(List) :: iMaskList, rMaskList
  419. type(String) :: DummStr
  420. integer, dimension(:), pointer :: iMask, iMaskTemp
  421. real(FP), dimension(:), pointer :: rMask, rMaskTemp
  422. integer :: TempMaskLength
  423. real(FP), dimension(:), pointer :: SpatialWeights
  424. integer :: niM, nrM ! Number of iMasks and rMasks, respectively
  425. ! Argument Validity Checks
  426. if(AttrVect_lsize(inAv) /= GeneralGrid_lsize(GGrid)) then
  427. ierr = AttrVect_lsize(inAv) - GeneralGrid_lsize(GGrid)
  428. write(stderr,'(3a,i8,a,i8)') myname_, &
  429. ':: inAv / GGrid length mismatch: ', &
  430. ' AttrVect_lsize(inAv) = ',AttrVect_lsize(inAv), &
  431. ' GeneralGrid_lsize(GGrid) = ',GeneralGrid_lsize(GGrid)
  432. call die(myname_)
  433. endif
  434. if(present(SumWeights)) then
  435. mySumWeights = SumWeights
  436. if(.not. present(WeightSumTag)) then
  437. write(stderr,'(3a)') myname_,':: FATAL--If the input argument SumWeights=.TRUE.,', &
  438. ' then the argument WeightSumTag must be provided.'
  439. call die(myname_)
  440. endif
  441. else
  442. mySumWeights = .FALSE.
  443. endif
  444. if(present(iMaskTags)) then
  445. call List_init(iMaskList, iMaskTags)
  446. if(List_nitem(iMaskList) == 0) then
  447. write(stderr,'(3a)') myname_,':: ERROR--an INTEGER mask list with', &
  448. 'no valid items was provided.'
  449. call die(myname_)
  450. endif
  451. endif
  452. if(present(rMaskTags)) then
  453. call List_init(rMaskList, rMaskTags)
  454. if(List_nitem(iMaskList) == 0) then
  455. write(stderr,'(3a)') myname_,':: ERROR--an REAL mask list with', &
  456. 'no valid items was provided.'
  457. call die(myname_)
  458. endif
  459. endif
  460. ! Determine the on-processor vector length for use throughout
  461. ! this routine:
  462. length = AttrVect_lsize(inAv)
  463. !==========================================================
  464. ! Extract Spatial Weights from GGrid using SpatialWeightTag
  465. !==========================================================
  466. nullify(SpatialWeights)
  467. call GeneralGrid_exportRAttr(GGrid, SpatialWeightTag, SpatialWeights, &
  468. TempMaskLength)
  469. if(TempMaskLength /= length) then
  470. write(stderr,'(3a,i8,a,i8)') myname_,&
  471. ':: error on return from GeneralGrid_exportRAttr().' , &
  472. 'Returned with SpatialWeights(:) length = ',TempMaskLength, &
  473. ',which conflicts with AttrVect_lsize(inAv) = ',length
  474. call die(myname_)
  475. endif
  476. !==========================================================
  477. ! If the argument iMaskTags is present, create the combined
  478. ! iMask array:
  479. !==========================================================
  480. if(present(iMaskTags)) then ! assemble iMask(:) from all the integer
  481. ! mask attributes stored in GGrid(:)
  482. allocate(iMask(length), iMaskTemp(length), stat=ierr)
  483. if(ierr /= 0) then
  484. write(stderr,'(3a,i8)') myname_,':: allocate(iMask(...) failed,', &
  485. ' ierr=',ierr
  486. call die(myname_)
  487. endif
  488. niM = List_nitem(iMaskList)
  489. do i=1,niM
  490. ! Retrieve current iMask tag, and get this attribute from GGrid:
  491. call List_get(DummStr, i, iMaskList)
  492. call GeneralGrid_exportIAttr(GGrid, String_toChar(DummStr), &
  493. iMaskTemp, TempMaskLength)
  494. call String_clean(DummStr)
  495. if(TempMaskLength /= length) then
  496. write(stderr,'(3a,i8,a,i8)') myname_,&
  497. ':: error on return from GeneralGrid_exportIAttr().' , &
  498. 'Returned with TempMaskLength = ',TempMaskLength, &
  499. ',which conflicts with AttrVect_lsize(inAv) = ',length
  500. call die(myname_)
  501. endif
  502. if(i == 1) then ! first pass--examine iMaskTemp(:) only
  503. if(UseFastMethod) then ! straight copy of iMaskTemp(:)
  504. do j=1,length
  505. iMask(j) = iMaskTemp(j)
  506. end do
  507. else ! go through the entries of iMaskTemp(:) one-by-one
  508. do j=1,length
  509. select case(iMaskTemp(j))
  510. case(0)
  511. iMask(j) = 0
  512. case(1)
  513. iMask(j) = 1
  514. case default
  515. write(stderr,'(3a,i8,a,i8)') myname_, &
  516. ':: FATAL--illegal INTEGER mask entry. Integer mask ', &
  517. 'entries must be 0 or 1. iMask(',j,') = ', iMask(j)
  518. call die(myname_)
  519. end select ! select case(iMaskTemp(j))...
  520. end do ! do j=1,length
  521. endif ! if(UseFastMethod)...
  522. else ! That is, i /= 1 ...
  523. if(UseFastMethod) then ! straight product of iMask(:)
  524. ! and iMaskTemp(:)
  525. do j=1,length
  526. iMask(j) = iMask(j) * iMaskTemp(j)
  527. end do
  528. else ! go through the entries of iMaskTemp(:) one-by-one
  529. do j=1,length
  530. select case(iMaskTemp(j))
  531. case(0) ! zero out iMask(j)
  532. iMask(j) = 0
  533. case(1) ! do nothing
  534. case default
  535. write(stderr,'(3a,i8,a,i8)') myname_, &
  536. ':: FATAL--illegal INTEGER mask entry. Integer mask ', &
  537. 'entries must be 0 or 1. iMask(',j,') = ', iMask(j)
  538. call die(myname_)
  539. end select ! select case(iMaskTemp(j))...
  540. end do ! do j=1,length
  541. endif ! if(UseFastMethod)...
  542. endif ! if(i == 1)...
  543. end do ! do i=1,niM...iMask retrievals
  544. endif ! if(present(iMaskTags))...
  545. !==========================================================
  546. ! If the argument rMaskTags is present, create the combined
  547. ! REAL mask rMask array:
  548. !==========================================================
  549. if(present(rMaskTags)) then ! assemble rMask(:) from all the integer
  550. ! mask attributes stored in GGrid(:)
  551. allocate(rMask(length), rMaskTemp(length), stat=ierr)
  552. if(ierr /= 0) then
  553. write(stderr,'(3a,i8)') myname_,':: allocate(rMask(...) failed,', &
  554. ' ierr=',ierr
  555. call die(myname_)
  556. endif
  557. nrM = List_nitem(rMaskList)
  558. do i=1,nrM
  559. ! Retrieve current rMask tag, and get this attribute from GGrid:
  560. call List_get(DummStr, i, rMaskList)
  561. call GeneralGrid_exportRAttr(GGrid, String_toChar(DummStr), &
  562. rMaskTemp, TempMaskLength)
  563. call String_clean(DummStr)
  564. if(TempMaskLength /= length) then
  565. write(stderr,'(3a,i8,a,i8)') myname_,&
  566. ':: error on return from GeneralGrid_exportRAttr().' , &
  567. 'Returned with TempMaskLength = ',TempMaskLength, &
  568. ',which conflicts with AttrVect_lsize(inAv) = ',length
  569. call die(myname_)
  570. endif
  571. if(i == 1) then ! first pass--examine rMaskTemp(:) only
  572. if(UseFastMethod) then ! straight copy of rMaskTemp(:)
  573. do j=1,length
  574. rMask(j) = rMaskTemp(j)
  575. end do
  576. else ! go through the entries of rMaskTemp(:) one-by-one
  577. ! to ensure they are in the range [0.,1.]
  578. do j=1,length
  579. if((rMaskTemp(j) >= 0.) .or. (rMaskTemp(j) <=1.)) then
  580. rMask(j) = rMaskTemp(j)
  581. else
  582. write(stderr,'(3a,i8,a,i8)') myname_, &
  583. ':: FATAL--illegal REAL mask entry. Real mask ', &
  584. 'entries must be in [0.,1.] rMask(',j,') = ', rMask(j)
  585. call die(myname_)
  586. endif ! if((rMaskTemp(j) >= 0.) .or. (rMaskTemp(j) <=1.))...
  587. end do ! do j=1,length
  588. endif ! if(UseFastMethod)...
  589. else ! That is, i /= 1 ...
  590. if(UseFastMethod) then ! straight product of rMask(:)
  591. ! and rMaskTemp(:)
  592. do j=1,length
  593. rMask(j) = rMask(j) * rMaskTemp(j)
  594. end do
  595. else ! go through the entries of rMaskTemp(:) one-by-one
  596. ! to ensure they are in the range [0.,1.]
  597. do j=1,length
  598. if((rMaskTemp(j) >= 0.) .or. (rMaskTemp(j) <=1.)) then
  599. rMask(j) = rMask(j) * rMaskTemp(j)
  600. else
  601. write(stderr,'(3a,i8,a,i8)') myname_, &
  602. ':: FATAL--illegal REAL mask entry. Real mask ', &
  603. 'entries must be in [0.,1.] rMask(',j,') = ', rMask(j)
  604. call die(myname_)
  605. endif ! if((rMaskTemp(j) >= 0.) .or. (rMaskTemp(j) <=1.))...
  606. end do ! do j=1,length
  607. endif ! if(UseFastMethod)...
  608. endif ! if(i == 1)...
  609. end do ! do i=1,niM...rMask retrievals
  610. endif ! if(present(rMaskTags))...
  611. !==========================================================
  612. ! Now that we have produced single INTEGER and REAL masks,
  613. ! compute the masked weighted sum.
  614. !==========================================================
  615. if(present(rMaskTags)) then ! We have a REAL Mask
  616. if(present(iMaskTags)) then ! and an INTEGER Mask
  617. if(present(comm)) then ! compute distributed AllReduce-style sum:
  618. if(mySumWeights) then ! return the global masked sum of the
  619. ! weights in outAV
  620. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  621. iMask, rMask, UseFastMethod, &
  622. SumWeights, WeightSumTag, comm)
  623. else ! Do not return the masked sum of the weights
  624. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  625. iMask, rMask, UseFastMethod, &
  626. comm=comm)
  627. endif ! if(mySumWeights)...
  628. else ! compute local sum:
  629. if(mySumWeights) then ! return the global masked sum of the
  630. ! weights in outAV
  631. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  632. iMask, rMask, UseFastMethod, &
  633. SumWeights, WeightSumTag)
  634. else ! Do not return the masked sum of the weights
  635. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  636. iMask, rMask, UseFastMethod)
  637. endif ! if(mySumWeights)...
  638. endif ! if(present(comm))...
  639. else ! REAL Mask Only Case...
  640. if(present(comm)) then ! compute distributed AllReduce-style sum:
  641. if(mySumWeights) then ! return the global masked sum of the
  642. ! weights in outAV
  643. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  644. rMask=rMask, &
  645. UseFastMethod=UseFastMethod, &
  646. SumWeights=SumWeights, &
  647. WeightSumTag=WeightSumTag, &
  648. comm=comm)
  649. else ! Do not return the masked sum of the weights
  650. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  651. rMask=rMask, &
  652. UseFastMethod=UseFastMethod, &
  653. comm=comm)
  654. endif ! if(mySumWeights)...
  655. else ! compute local sum:
  656. if(mySumWeights) then ! return the global masked sum of the
  657. ! weights in outAV
  658. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  659. rMask=rMask, &
  660. UseFastMethod=UseFastMethod, &
  661. SumWeights=SumWeights, &
  662. WeightSumTag=WeightSumTag)
  663. else ! Do not return the masked sum of the weights
  664. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  665. rMask=rMask, &
  666. UseFastMethod=UseFastMethod)
  667. endif ! if(mySumWeights)...
  668. endif ! if(present(comm))...
  669. endif
  670. else ! no REAL Mask...
  671. if(present(iMaskTags)) then ! INTEGER Mask Only Case...
  672. if(present(comm)) then ! compute distributed AllReduce-style sum:
  673. if(mySumWeights) then ! return the global masked sum of the
  674. ! weights in outAV
  675. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  676. iMask=iMask, &
  677. UseFastMethod=UseFastMethod, &
  678. SumWeights=SumWeights, &
  679. WeightSumTag=WeightSumTag, &
  680. comm=comm)
  681. else ! Do not return the masked sum of the weights
  682. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  683. iMask=iMask, &
  684. UseFastMethod=UseFastMethod, &
  685. comm=comm)
  686. endif ! if(mySumWeights)...
  687. else ! compute local sum:
  688. if(mySumWeights) then ! return the global masked sum of the
  689. ! weights in outAV
  690. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  691. iMask=iMask, &
  692. UseFastMethod=UseFastMethod, &
  693. SumWeights=SumWeights, &
  694. WeightSumTag=WeightSumTag)
  695. else ! Do not return the masked sum of the weights
  696. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  697. iMask=iMask, &
  698. UseFastMethod=UseFastMethod)
  699. endif ! if(mySumWeights)...
  700. endif ! if(present(comm))...
  701. else ! no INTEGER Mask / no REAL Mask Case...
  702. if(present(comm)) then ! compute distributed AllReduce-style sum:
  703. if(mySumWeights) then ! return the global masked sum of the
  704. ! weights in outAV
  705. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  706. UseFastMethod=UseFastMethod, &
  707. SumWeights=SumWeights, &
  708. WeightSumTag=WeightSumTag, &
  709. comm=comm)
  710. else ! Do not return the masked sum of the weights
  711. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  712. UseFastMethod=UseFastMethod, &
  713. comm=comm)
  714. endif ! if(mySumWeights)...
  715. else ! compute local sum:
  716. if(mySumWeights) then ! return the global masked sum of the
  717. ! weights in outAV
  718. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  719. UseFastMethod=UseFastMethod, &
  720. SumWeights=SumWeights, &
  721. WeightSumTag=WeightSumTag)
  722. else ! Do not return the masked sum of the weights
  723. call MaskedSpatialIntegralV(inAv, outAv, SpatialWeights, &
  724. UseFastMethod=UseFastMethod)
  725. endif ! if(mySumWeights)...
  726. endif ! if(present(comm))...
  727. endif ! if(present(iMaskTags)...
  728. endif ! if(present(rMaskTags)...
  729. !==========================================================
  730. ! The masked spatial integral is now completed.
  731. ! Clean up the the various allocated mask structures.
  732. !==========================================================
  733. if(present(iMaskTags)) then ! clean up iMask and friends...
  734. call List_clean(iMaskList)
  735. deallocate(iMask, iMaskTemp, stat=ierr)
  736. if(ierr /= 0) then
  737. write(stderr,'(3a,i8)') myname_,':: deallocate(iMask(...) failed,', &
  738. ' ierr=',ierr
  739. call die(myname_)
  740. endif
  741. endif
  742. if(present(rMaskTags)) then ! clean up rMask and co...
  743. call List_clean(rMaskList)
  744. deallocate(rMask, rMaskTemp, stat=ierr)
  745. if(ierr /= 0) then
  746. write(stderr,'(3a,i8)') myname_,':: deallocate(rMask(...) failed,', &
  747. ' ierr=',ierr
  748. call die(myname_)
  749. endif
  750. endif
  751. ! Clean up SpatialWeights(:)
  752. deallocate(SpatialWeights, stat=ierr)
  753. if(ierr /= 0) then
  754. write(stderr,'(3a,i8)') myname_,':: deallocate(SpatialWeights(...) failed,', &
  755. ' ierr=',ierr
  756. call die(myname_)
  757. endif
  758. end subroutine MaskedSpatialIntegralRAttrGG_
  759. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  760. ! Math and Computer Science Division, Argonne National Laboratory !
  761. !BOP -------------------------------------------------------------------
  762. !
  763. ! !IROUTINE: MaskedSpatialAverageRAttrGG_ - Masked spatial average.
  764. !
  765. ! !DESCRIPTION:
  766. ! This routine computes masked spatial averages of the {\tt REAL}
  767. ! attributes of the input {\tt AttrVect} argument {\tt inAv}, returning
  768. ! the masked averages in the output {\tt AttrVect} {\tt outAv}. All of
  769. ! the masking data are assumed stored in the input {\tt GeneralGrid}
  770. ! argument {\tt GGrid}. If integer masks are to be used, their integer
  771. ! attribute names in {\tt GGrid} are named as a colon-delimited list
  772. ! in the optional {\tt CHARACTER} input argument {\tt iMaskTags}. Real
  773. ! masks (if desired) are referenced by their real attribute names in
  774. ! {\tt GGrid} are named as a colon-delimited list in the optional
  775. ! {\tt CHARACTER} input argument {\tt rMaskTags}. The user specifies
  776. ! a choice of mask combination method with the input {\tt LOGICAL} argument
  777. ! {\tt UseFastMethod}. If ${\tt UseFastMethod} = {\tt .FALSE.}$ this
  778. ! routine checks each mask entry to ensure that the integer masks contain
  779. ! only ones and zeroes, and that entries in the real masks are all in
  780. ! the closed interval $[0,1]$. If ${\tt UseFastMethod} = {\tt .TRUE.}$,
  781. ! this routine performs direct products of the masks, assuming that the
  782. ! user has validated them in advance. This averaging can either be a
  783. ! local (equivalent to a global memory space operation), or a global
  784. ! distributed integral. The latter is the case if the optional input
  785. ! {\tt INTEGER} argument {\tt comm} is supplied (which corresponds to a
  786. ! Fortran MPI communicatior handle).
  787. !
  788. ! {\bf N.B.: } The local lengths of the {\tt AttrVect} argument {\tt inAv}
  789. ! and the input {\tt GeneralGrid} {\tt GGrid} must be equal. That is,
  790. ! there must be a one-to-one correspondence between the field point values
  791. ! stored in {\tt inAv} and the point weights stored in {\tt GGrid}.
  792. !
  793. ! {\bf N.B.: } The output {\tt AttrVect} argument {\tt outAv} is an
  794. ! allocated data structure. The user must deallocate it using the routine
  795. ! {\tt AttrVect\_clean()} when it is no longer needed. Failure to do so
  796. ! will result in a memory leak.
  797. !
  798. ! !INTERFACE:
  799. subroutine MaskedSpatialAverageRAttrGG_(inAv, outAv, GGrid, SpatialWeightTag, &
  800. iMaskTags, rMaskTags, UseFastMethod, &
  801. comm)
  802. ! ! USES:
  803. use m_realkinds, only : FP
  804. use m_stdio
  805. use m_die
  806. use m_mpif90
  807. use m_AttrVect, only : AttrVect
  808. use m_AttrVect, only : AttrVect_init => init
  809. use m_AttrVect, only : AttrVect_zero => zero
  810. use m_AttrVect, only : AttrVect_clean => clean
  811. use m_AttrVect, only : AttrVect_lsize => lsize
  812. use m_AttrVect, only : AttrVect_indexRA => indexRA
  813. use m_AttrVect, only : AttrVect_nRAttr => nRAttr
  814. use m_GeneralGrid, only : GeneralGrid
  815. use m_GeneralGrid, only : GeneralGrid_lsize => lsize
  816. use m_GeneralGrid, only : GeneralGrid_indexRA => indexRA
  817. use m_List, only : List
  818. use m_List, only : List_nullify => nullify
  819. implicit none
  820. ! !INPUT PARAMETERS:
  821. type(AttrVect), intent(IN) :: inAv
  822. type(GeneralGrid), intent(IN) :: GGrid
  823. character(len=*), intent(IN) :: SpatialWeightTag
  824. character(len=*), optional, intent(IN) :: iMaskTags
  825. character(len=*), optional, intent(IN) :: rMaskTags
  826. logical, intent(IN) :: UseFastMethod
  827. integer, optional, intent(IN) :: comm
  828. ! !OUTPUT PARAMETERS:
  829. type(AttrVect), intent(OUT) :: outAv
  830. ! !REVISION HISTORY:
  831. ! 12Jun02 - J.W. Larson <larson@mcs.anl.gov> - initial version
  832. !
  833. !EOP ___________________________________________________________________
  834. character(len=*),parameter :: myname_=myname//'::MaskedSpatialAverageRAttrGG_'
  835. type(AttrVect) :: integratedAv
  836. type(List) :: nullIList
  837. character*9, parameter :: WeightSumTag = 'WeightSum'
  838. integer :: i, iweight
  839. !================================================================
  840. ! Do the integration using MaskedSpatialIntegralRAttrGG_(), which
  841. ! returns the intermediate integrals (including the masked weight
  842. ! sum) in the AttrVect integratedAv.
  843. !================================================================
  844. if(present(iMaskTags)) then
  845. if(present(rMaskTags)) then ! have both iMasks and rMasks
  846. if(present(comm)) then ! a distributed parallel sum
  847. call MaskedSpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, &
  848. SpatialWeightTag, iMaskTags, &
  849. rMaskTags, UseFastMethod, &
  850. .TRUE., WeightSumTag, comm)
  851. else ! a purely local sum
  852. call MaskedSpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, &
  853. SpatialWeightTag, iMaskTags, &
  854. rMaskTags, UseFastMethod, &
  855. .TRUE., WeightSumTag)
  856. endif ! if(present(comm))...
  857. else ! Only iMasks are in use
  858. if(present(comm)) then ! a distributed parallel sum
  859. call MaskedSpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, &
  860. SpatialWeightTag, iMaskTags, &
  861. UseFastMethod=UseFastMethod, &
  862. SumWeights=.TRUE., &
  863. WeightSumTag=WeightSumTag, &
  864. comm=comm)
  865. else ! a purely local sum
  866. call MaskedSpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, &
  867. SpatialWeightTag, iMaskTags, &
  868. UseFastMethod=UseFastMethod, &
  869. SumWeights=.TRUE., &
  870. WeightSumTag=WeightSumTag)
  871. endif ! if(present(comm))...
  872. endif ! if(present(rMaskTags)...
  873. else ! no iMasks
  874. if(present(rMaskTags)) then ! Only rMasks are in use
  875. if(present(comm)) then ! a distributed parallel sum
  876. call MaskedSpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, &
  877. SpatialWeightTag, &
  878. rMaskTags=rMaskTags, &
  879. UseFastMethod=UseFastMethod, &
  880. SumWeights=.TRUE., &
  881. WeightSumTag=WeightSumTag, &
  882. comm=comm)
  883. else ! a purely local sum
  884. call MaskedSpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, &
  885. SpatialWeightTag, &
  886. rMaskTags=rMaskTags, &
  887. UseFastMethod=UseFastMethod, &
  888. SumWeights=.TRUE., &
  889. WeightSumTag=WeightSumTag)
  890. endif
  891. else ! Neither iMasks nor rMasks are in use
  892. if(present(comm)) then ! a distributed parallel sum
  893. call MaskedSpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, &
  894. SpatialWeightTag, &
  895. UseFastMethod=UseFastMethod, &
  896. SumWeights=.TRUE., &
  897. WeightSumTag=WeightSumTag, &
  898. comm=comm)
  899. else ! a purely local sum
  900. call MaskedSpatialIntegralRAttrGG_(inAv, integratedAv, GGrid, &
  901. SpatialWeightTag, &
  902. UseFastMethod=UseFastMethod, &
  903. SumWeights=.TRUE., &
  904. WeightSumTag=WeightSumTag)
  905. endif ! if(present(comm))...
  906. endif ! if(present(rMaskTags))...
  907. endif ! if(present(iMaskTags))...
  908. !================================================================
  909. ! The masked integrals and masked weight sum now reside in
  910. ! in the AttrVect integratedAv. We now wish to compute the
  911. ! averages by dividing the integtrals by the masked weight sum.
  912. !================================================================
  913. ! Check value of summed weights (to avoid division by zero):
  914. iweight = AttrVect_indexRA(integratedAv, WeightSumTag)
  915. if(integratedAv%rAttr(iweight, 1) == 0._FP) then
  916. write(stderr,'(2a)') myname_, &
  917. '::ERROR--Global sum of grid weights is zero.'
  918. call die(myname_)
  919. endif
  920. ! Initialize output AttrVect outAv:
  921. call List_nullify(nullIList)
  922. call AttrVect_init(outAv, iList=nullIList, rList=inAv%rList, lsize=1)
  923. call AttrVect_zero(outAv)
  924. ! Divide by global weight sum to compute spatial averages from
  925. ! spatial integrals.
  926. do i=1,AttrVect_nRAttr(outAv)
  927. outAv%rAttr(i,1) = integratedAv%rAttr(i,1) &
  928. / integratedAv%rAttr(iweight,1)
  929. end do
  930. ! Clean up temporary AttrVect:
  931. call AttrVect_clean(integratedAv)
  932. end subroutine MaskedSpatialAverageRAttrGG_
  933. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  934. ! Math and Computer Science Division, Argonne National Laboratory !
  935. !BOP -------------------------------------------------------------------
  936. !
  937. ! !IROUTINE: PairedSpatialIntegralRAttrGG_ - Do two spatial integrals at once.
  938. !
  939. ! !DESCRIPTION:
  940. ! This routine computes spatial integrals of the {\tt REAL} attributes
  941. ! of the {\tt REAL} attributes of the input {\tt AttrVect} arguments
  942. ! {\tt inAv1} and {\tt inAv2}, returning the integrals in the output
  943. ! {\tt AttrVect} arguments {\tt outAv1} and {\tt outAv2}, respectively .
  944. ! The integrals of {\tt inAv1} and {\tt inAv2} are computed using
  945. ! spatial weights stored in the input {\tt GeneralGrid} arguments
  946. ! {\tt GGrid1} and {\tt GGrid2}, respectively. The spatial weights in
  947. ! in {\tt GGrid1} and {\tt GGrid2} are identified by the input {\tt CHARACTER}
  948. ! arguments {\tt WeightTag1} and {\tt WeightTag2}, respectively.
  949. ! If {\tt SpatialIntegralRAttrGG\_()} is invoked with the optional
  950. ! {\tt LOGICAL} input argument
  951. ! {\tt SumWeights} set as {\tt .TRUE.}, then the weights are also summed
  952. ! and stored in {\tt outAv1} and {\tt outAv2}, and can be referenced with
  953. ! the attribute tags defined by the arguments {\tt WeightTag1} and
  954. ! {\tt WeightTag2}, respectively. This paired integral is implicitly a
  955. ! distributed operation (the whole motivation for pairing the integrals is
  956. ! to reduce communication latency costs), and the Fortran MPI communicator
  957. ! handle is defined by the input {\tt INTEGER} argument {\tt comm}. The
  958. ! summation is an AllReduce operation, with all processes receiving the
  959. ! global sum.
  960. !
  961. ! {\bf N.B.: } The local lengths of the {\tt AttrVect} argument {\tt inAv1}
  962. ! and the {\tt GeneralGrid} {\tt GGrid1} must be equal. That is, there
  963. ! must be a one-to-one correspondence between the field point values stored
  964. ! in {\tt inAv1} and the point weights stored in {\tt GGrid1}. The same
  965. ! relationship must apply between {\tt inAv2} and {\tt GGrid2}.
  966. !
  967. ! {\bf N.B.: } If {\tt SpatialIntegralRAttrGG\_()} is invoked with the
  968. ! optional {\tt LOGICAL} input argument {\tt SumWeights} set as {\tt .TRUE.},
  969. ! then the value of {\tt WeightTag1} must not conflict with any of the
  970. ! {\tt REAL} attribute tags in {\tt inAv1} and the value of {\tt WeightTag2}
  971. ! must not conflict with any of the {\tt REAL} attribute tags in {\tt inAv2}.
  972. !
  973. ! {\bf N.B.: } The output {\tt AttrVect} arguments {\tt outAv1} and
  974. ! {\tt outAv2} are allocated data structures. The user must deallocate them
  975. ! using the routine {\tt AttrVect\_clean()} when they are no longer needed.
  976. ! Failure to do so will result in a memory leak.
  977. !
  978. ! !INTERFACE:
  979. subroutine PairedSpatialIntegralRAttrGG_(inAv1, outAv1, GGrid1, WeightTag1, &
  980. inAv2, outAv2, GGrid2, WeightTag2, &
  981. SumWeights, comm)
  982. ! ! USES:
  983. use m_stdio
  984. use m_die
  985. use m_mpif90
  986. use m_realkinds, only : FP
  987. use m_AttrVect, only : AttrVect
  988. use m_AttrVect, only : AttrVect_lsize => lsize
  989. use m_AttrVect, only : AttrVect_nRAttr => nRAttr
  990. use m_GeneralGrid, only : GeneralGrid
  991. use m_GeneralGrid, only : GeneralGrid_lsize => lsize
  992. use m_GeneralGrid, only : GeneralGrid_indexRA => indexRA
  993. use m_GeneralGrid, only : GeneralGrid_exportRAttr => exportRAttr
  994. use m_AttrVectReduce, only : AttrVect_LocalWeightedSumRAttr => &
  995. LocalWeightedSumRAttr
  996. use m_SpatialIntegralV, only : PairedSpatialIntegralsV
  997. implicit none
  998. ! !INPUT PARAMETERS:
  999. type(AttrVect), intent(IN) :: inAv1
  1000. type(GeneralGrid), intent(IN) :: GGrid1
  1001. character(len=*), intent(IN) :: WeightTag1
  1002. type(AttrVect), intent(IN) :: inAv2
  1003. type(GeneralGrid), intent(IN) :: GGrid2
  1004. character(len=*), intent(IN) :: WeightTag2
  1005. logical, optional, intent(IN) :: SumWeights
  1006. integer, intent(IN) :: comm
  1007. ! !OUTPUT PARAMETERS:
  1008. type(AttrVect), intent(OUT) :: outAv1
  1009. type(AttrVect), intent(OUT) :: outAv2
  1010. ! !REVISION HISTORY:
  1011. ! 09May02 - J.W. Larson <larson@mcs.anl.gov> - Initial version.
  1012. ! 10Jun02 - J.W. Larson <larson@mcs.anl.gov> - Refactored--now
  1013. ! built on top of PairedIntegralRAttrV_().
  1014. !
  1015. !EOP ___________________________________________________________________
  1016. character(len=*),parameter :: myname_=myname//'::PairedSpatialIntegralRAttrGG_'
  1017. ! Argument Sanity Checks:
  1018. integer :: ierr, length1, length2
  1019. logical :: mySumWeights
  1020. real(FP), dimension(:), pointer :: gridWeights1, gridWeights2
  1021. ! Argument Validity Checks
  1022. if(AttrVect_lsize(inAv1) /= GeneralGrid_lsize(GGrid1)) then
  1023. ierr = AttrVect_lsize(inAv1) - GeneralGrid_lsize(GGrid1)
  1024. write(stderr,'(3a,i8,a,i8)') myname_, &
  1025. ':: inAv1 / GGrid1 length mismatch: ', &
  1026. ' AttrVect_lsize(inAv1) = ',AttrVect_lsize(inAv1), &
  1027. ' GeneralGrid_lsize(GGrid1) = ',GeneralGrid_lsize(GGrid1)
  1028. call die(myname_)
  1029. endif
  1030. if(AttrVect_lsize(inAv2) /= GeneralGrid_lsize(GGrid2)) then
  1031. ierr = AttrVect_lsize(inAv2) - GeneralGrid_lsize(GGrid2)
  1032. write(stderr,'(3a,i8,a,i8)') myname_, &
  1033. ':: inAv2 / GGrid2 length mismatch: ', &
  1034. ' AttrVect_lsize(inAv2) = ',AttrVect_lsize(inAv2), &
  1035. ' GeneralGrid_lsize(GGrid2) = ',GeneralGrid_lsize(GGrid2)
  1036. call die(myname_)
  1037. endif
  1038. ! Are we summing the integration weights for either input
  1039. ! GeneralGrid?
  1040. if(present(SumWeights)) then
  1041. mySumWeights = SumWeights
  1042. else
  1043. mySumWeights = .FALSE.
  1044. endif
  1045. ! ensure unambiguous pointer association status for gridWeights1
  1046. ! and gridWeights2
  1047. nullify(gridWeights1)
  1048. nullify(gridWeights2)
  1049. ! Extract Grid Weights
  1050. call GeneralGrid_exportRAttr(GGrid1, WeightTag1, gridWeights1, length1)
  1051. call GeneralGrid_exportRAttr(GGrid2, WeightTag2, gridWeights2, length2)
  1052. call PairedSpatialIntegralsV(inAv1, outAv1, gridweights1, WeightTag1, &
  1053. inAv2, outAv2, gridweights2, WeightTag2, &
  1054. mySumWeights, comm)
  1055. ! Clean up allocated arrays:
  1056. deallocate(gridWeights1, gridWeights2, stat=ierr)
  1057. if(ierr /= 0) then
  1058. write(stderr,'(2a,i8)') myname_, &
  1059. 'ERROR--deallocate(gridWeights1,...) failed, ierr = ',ierr
  1060. call die(myname_)
  1061. endif
  1062. end subroutine PairedSpatialIntegralRAttrGG_
  1063. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1064. ! Math and Computer Science Division, Argonne National Laboratory !
  1065. !BOP -------------------------------------------------------------------
  1066. !
  1067. ! !IROUTINE: PairedSpatialAverageRAttrGG_ - Do two spatial averages at once.
  1068. !
  1069. ! !DESCRIPTION:
  1070. ! This routine computes spatial averages of the {\tt REAL} attributes
  1071. ! of the {\tt REAL} attributes of the input {\tt AttrVect} arguments
  1072. ! {\tt inAv1} and {\tt inAv2}, returning the integrals in the output
  1073. ! {\tt AttrVect} arguments {\tt outAv1} and {\tt outAv2}, respectively .
  1074. ! The integrals of {\tt inAv1} and {\tt inAv2} are computed using
  1075. ! spatial weights stored in the input {\tt GeneralGrid} arguments
  1076. ! {\tt GGrid1} and {\tt GGrid2}, respectively. The spatial weights in
  1077. ! in {\tt GGrid1} and {\tt GGrid2} are identified by the input {\tt CHARACTER}
  1078. ! arguments {\tt WeightTag1} and {\tt WeightTag2}, respectively.
  1079. ! This paired average is implicitly a
  1080. ! distributed operation (the whole motivation for pairing the averages is
  1081. ! to reduce communication latency costs), and the Fortran MPI communicator
  1082. ! handle is defined by the input {\tt INTEGER} argument {\tt comm}. The
  1083. ! summation is an AllReduce operation, with all processes receiving the
  1084. ! global sum.
  1085. !
  1086. ! {\bf N.B.: } The local lengths of the {\tt AttrVect} argument {\tt inAv1}
  1087. ! and the {\tt GeneralGrid} {\tt GGrid1} must be equal. That is, there
  1088. ! must be a one-to-one correspondence between the field point values stored
  1089. ! in {\tt inAv1} and the point weights stored in {\tt GGrid1}. The same
  1090. ! relationship must apply between {\tt inAv2} and {\tt GGrid2}.
  1091. !
  1092. ! {\bf N.B.: } The output {\tt AttrVect} arguments {\tt outAv1} and
  1093. ! {\tt outAv2} are allocated data structures. The user must deallocate them
  1094. ! using the routine {\tt AttrVect\_clean()} when they are no longer needed.
  1095. ! Failure to do so will result in a memory leak.
  1096. !
  1097. ! !INTERFACE:
  1098. subroutine PairedSpatialAverageRAttrGG_(inAv1, outAv1, GGrid1, WeightTag1, &
  1099. inAv2, outAv2, GGrid2, WeightTag2, &
  1100. comm)
  1101. ! ! USES:
  1102. use m_realkinds, only : FP
  1103. use m_stdio
  1104. use m_die
  1105. use m_mpif90
  1106. use m_AttrVect, only : AttrVect
  1107. use m_AttrVect, only : AttrVect_init => init
  1108. use m_AttrVect, only : AttrVect_zero => zero
  1109. use m_AttrVect, only : AttrVect_clean => clean
  1110. use m_AttrVect, only : AttrVect_lsize => lsize
  1111. use m_AttrVect, only : AttrVect_nRAttr => nRAttr
  1112. use m_AttrVect, only : AttrVect_indexRA => indexRA
  1113. use m_GeneralGrid, only : GeneralGrid
  1114. use m_GeneralGrid, only : GeneralGrid_lsize => lsize
  1115. use m_GeneralGrid, only : GeneralGrid_indexRA => indexRA
  1116. use m_GeneralGrid, only : GeneralGrid_exportRAttr => exportRAttr
  1117. use m_AttrVectReduce, only : AttrVect_LocalWeightedSumRAttr => &
  1118. LocalWeightedSumRAttr
  1119. use m_List, only : List
  1120. use m_List, only : List_nullify => nullify
  1121. implicit none
  1122. ! !INPUT PARAMETERS:
  1123. type(AttrVect), intent(IN) :: inAv1
  1124. type(GeneralGrid), intent(IN) :: GGrid1
  1125. character(len=*), intent(IN) :: WeightTag1
  1126. type(AttrVect), intent(IN) :: inAv2
  1127. type(GeneralGrid), intent(IN) :: GGrid2
  1128. character(len=*), intent(IN) :: WeightTag2
  1129. integer, intent(IN) :: comm
  1130. ! !OUTPUT PARAMETERS:
  1131. type(AttrVect), intent(OUT) :: outAv1
  1132. type(AttrVect), intent(OUT) :: outAv2
  1133. ! !REVISION HISTORY:
  1134. ! 09May02 - J.W. Larson <larson@mcs.anl.gov> - Initial version.
  1135. ! 14Jun02 - J.W. Larson <larson@mcs.anl.gov> - Bug fix to reflect
  1136. ! new interface to PairedSpatialIntegralRAttrGG_().
  1137. !
  1138. !EOP ___________________________________________________________________
  1139. character(len=*),parameter :: myname_=myname//'::PairedSpatialAverageRAttrGG_'
  1140. type(AttrVect) :: integratedAv1, integratedAv2
  1141. type(List) :: nullIList
  1142. integer :: i, ierr, iweight1, iweight2
  1143. ! Compute the spatial integral:
  1144. call PairedSpatialIntegralRAttrGG_(inAv1, integratedAv1, GGrid1, WeightTag1, &
  1145. inAv2, integratedAv2, GGrid2, &
  1146. WeightTag2, .TRUE., comm)
  1147. ! Check value of summed weights (to avoid division by zero):
  1148. iweight1 = AttrVect_indexRA(integratedAv1, WeightTag1)
  1149. if(integratedAv1%rAttr(iweight1, 1) == 0._FP) then
  1150. write(stderr,'(2a)') myname_, &
  1151. '::ERROR--Global sum of grid weights in first integral is zero.'
  1152. call die(myname_)
  1153. endif
  1154. iweight2 = AttrVect_indexRA(integratedAv2, WeightTag2)
  1155. if(integratedAv2%rAttr(iweight2, 1) == 0._FP) then
  1156. write(stderr,'(2a)') myname_, &
  1157. '::ERROR--Global sum of grid weights in second integral is zero.'
  1158. call die(myname_)
  1159. endif
  1160. ! Initialize output AttrVects outAv1 and outAv2:
  1161. call List_nullify(nullIList)
  1162. call AttrVect_init(outAv1, iList=nullIList, rList=inAv1%rList, lsize=1)
  1163. call AttrVect_zero(outAv1)
  1164. call AttrVect_init(outAv2, iList=nullIList, rList=InAv2%rList, lsize=1)
  1165. call AttrVect_zero(outAv2)
  1166. ! Divide by global weight sum to compute spatial averages from
  1167. ! spatial integrals.
  1168. do i=1,AttrVect_nRAttr(outAv1)
  1169. outAv1%rAttr(i,1) = integratedAv1%rAttr(i,1) &
  1170. / integratedAv1%rAttr(iweight1,1)
  1171. end do
  1172. do i=1,AttrVect_nRAttr(outAv2)
  1173. outAv2%rAttr(i,1) = integratedAv2%rAttr(i,1) &
  1174. / integratedAv2%rAttr(iweight2,1)
  1175. end do
  1176. ! Clean up temporary AttrVects:
  1177. call AttrVect_clean(integratedAv1)
  1178. call AttrVect_clean(integratedAv2)
  1179. end subroutine PairedSpatialAverageRAttrGG_
  1180. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1181. ! Math and Computer Science Division, Argonne National Laboratory !
  1182. !BOP -------------------------------------------------------------------
  1183. !
  1184. ! !IROUTINE: PairedMaskedIntegralRAttrGG_ - Do two masked integrals at once.
  1185. !
  1186. ! !DESCRIPTION:
  1187. ! This routine computes a pair of masked spatial integrals of the {\tt REAL}
  1188. ! attributes of the input {\tt AttrVect} arguments {\tt inAv} and
  1189. ! {\tt inAv2}, returning the masked integrals in the output {\tt AttrVect}
  1190. ! {\tt outAv1} and {\tt outAv2}, respectively. All of the spatial weighting
  1191. ! and masking data for each set of integrals are assumed stored in the input
  1192. ! {\tt GeneralGrid} arguments {\tt GGrid} and {\tt GGrid2}. If integer
  1193. ! masks are to be used, their integer attribute names in {\tt GGrid1}
  1194. ! and {\tt GGrid2} are named as a colon-delimited lists in the optional
  1195. ! {\tt CHARACTER} input arguments {\tt iMaskTags1} and {\tt iMaskTags2},
  1196. ! respectively. Real masks (if desired) are referenced by their real
  1197. ! attribute names in {\tt GGrid1} and {\tt GGrid2} are named as
  1198. ! colon-delimited lists in the optional {\tt CHARACTER} input arguments
  1199. ! {\tt rMaskTags1} and {\tt rMaskTags2}, respectively. The user specifies
  1200. ! a choice of mask combination method with the input {\tt LOGICAL} argument
  1201. ! {\tt UseFastMethod}. If ${\tt UseFastMethod} = {\tt .FALSE.}$ this
  1202. ! routine checks each mask entry to ensure that the integer masks contain
  1203. ! only ones and zeroes, and that entries in the real masks are all in
  1204. ! the closed interval $[0,1]$. If ${\tt UseFastMethod} = {\tt .TRUE.}$,
  1205. ! this routine performs direct products of the masks, assuming that the
  1206. ! user has validated them in advance. The optional {\tt LOGICAL} input
  1207. ! argument {\tt SumWeights} determines whether the masked sum of the spatial
  1208. ! weights is computed and returned in {\tt outAv1} and {\tt outAv2} with the
  1209. ! real attribute names supplied in the {\tt CHARACTER} input arguments
  1210. ! {\tt SpatialWeightTag1}, and {\tt SpatialWeightTag2}, respectively.
  1211. ! This paired integral is implicitly a distributed operation (the whole
  1212. ! motivation for pairing the averages is to reduce communication latency
  1213. ! costs), and the Fortran MPI communicator handle is defined by the input
  1214. ! {\tt INTEGER} argument {\tt comm}. The
  1215. ! summation is an AllReduce operation, with all processes receiving the
  1216. ! global sum.
  1217. !
  1218. ! {\bf N.B.: } The local lengths of the {\tt AttrVect} argument {\tt inAv1}
  1219. ! and the {\tt GeneralGrid} {\tt GGrid1} must be equal. That is, there
  1220. ! must be a one-to-one correspondence between the field point values stored
  1221. ! in {\tt inAv1} and the point weights stored in {\tt GGrid1}. The same
  1222. ! relationship must apply between {\tt inAv2} and {\tt GGrid2}.
  1223. !
  1224. ! {\bf N.B.: } If {\tt PairedMaskedIntegralRAttrGG\_()} is invoked with the
  1225. ! optional {\tt LOGICAL} input argument {\tt SumWeights} set as {\tt .TRUE.},
  1226. ! then the value of {\tt SpatialWeightTag1} must not conflict with any of the
  1227. ! {\tt REAL} attribute tags in {\tt inAv1} and the value of
  1228. ! {\tt SpatialWeightTag2} must not conflict with any of the {\tt REAL}
  1229. ! attribute tags in {\tt inAv2}.
  1230. !
  1231. ! {\bf N.B.: } The output {\tt AttrVect} arguments {\tt outAv1} and
  1232. ! {\tt outAv2} are allocated data structures. The user must deallocate them
  1233. ! using the routine {\tt AttrVect\_clean()} when they are no longer needed.
  1234. ! Failure to do so will result in a memory leak.
  1235. !
  1236. ! !INTERFACE:
  1237. subroutine PairedMaskedIntegralRAttrGG_(inAv1, outAv1, GGrid1, &
  1238. SpatialWeightTag1, rMaskTags1, &
  1239. iMaskTags1, inAv2, outAv2, GGrid2, &
  1240. SpatialWeightTag2, rMaskTags2, &
  1241. iMaskTags2, UseFastMethod, &
  1242. SumWeights, comm)
  1243. ! ! USES:
  1244. use m_stdio
  1245. use m_die
  1246. use m_mpif90
  1247. use m_realkinds, only : FP
  1248. use m_AttrVect, only : AttrVect
  1249. use m_AttrVect, only : AttrVect_lsize => lsize
  1250. use m_AttrVect, only : AttrVect_nRAttr => nRAttr
  1251. use m_GeneralGrid, only : GeneralGrid
  1252. use m_GeneralGrid, only : GeneralGrid_lsize => lsize
  1253. use m_GeneralGrid, only : GeneralGrid_indexRA => indexRA
  1254. use m_GeneralGrid, only : GeneralGrid_exportRAttr => exportRAttr
  1255. use m_AttrVectReduce, only : AttrVect_LocalWeightedSumRAttr => &
  1256. LocalWeightedSumRAttr
  1257. implicit none
  1258. ! !INPUT PARAMETERS:
  1259. type(AttrVect), intent(IN) :: inAv1
  1260. type(GeneralGrid), intent(IN) :: GGrid1
  1261. character(len=*), intent(IN) :: SpatialWeightTag1
  1262. character(len=*), optional, intent(IN) :: iMaskTags1
  1263. character(len=*), optional, intent(IN) :: rMaskTags1
  1264. type(AttrVect), intent(IN) :: inAv2
  1265. type(GeneralGrid), intent(IN) :: GGrid2
  1266. character(len=*), intent(IN) :: SpatialWeightTag2
  1267. character(len=*), optional, intent(IN) :: iMaskTags2
  1268. character(len=*), optional, intent(IN) :: rMaskTags2
  1269. logical, intent(IN) :: UseFastMethod
  1270. logical, optional, intent(IN) :: SumWeights
  1271. integer, intent(IN) :: comm
  1272. ! !OUTPUT PARAMETERS:
  1273. type(AttrVect), intent(OUT) :: outAv1
  1274. type(AttrVect), intent(OUT) :: outAv2
  1275. ! !REVISION HISTORY:
  1276. ! 17Jun02 - J.W. Larson <larson@mcs.anl.gov> - Initial version.
  1277. ! 19Jun02 - J.W. Larson <larson@mcs.anl.gov> - Shortened the name
  1278. ! for compatibility with the Portland Group f90 compiler
  1279. !
  1280. !EOP ___________________________________________________________________
  1281. character(len=*),parameter :: myname_ = &
  1282. myname//'::PairedMaskedIntegralRAttrGG_'
  1283. logical :: mySumWeights
  1284. real(FP), dimension(:), pointer :: PairedBuffer, OutPairedBuffer
  1285. integer :: ierr, nRA1, nRA2, PairedBufferLength
  1286. ! Basic Argument Validity Checks:
  1287. if(AttrVect_lsize(inAv1) /= GeneralGrid_lsize(GGrid1)) then
  1288. ierr = AttrVect_lsize(inAv1) - GeneralGrid_lsize(GGrid1)
  1289. write(stderr,'(3a,i8,a,i8)') myname_, &
  1290. ':: inAv1 / GGrid1 length mismatch: ', &
  1291. ' AttrVect_lsize(inAv1) = ',AttrVect_lsize(inAv1), &
  1292. ' GeneralGrid_lsize(GGrid1) = ',GeneralGrid_lsize(GGrid1)
  1293. call die(myname_)
  1294. endif
  1295. if(AttrVect_lsize(inAv2) /= GeneralGrid_lsize(GGrid2)) then
  1296. ierr = AttrVect_lsize(inAv2) - GeneralGrid_lsize(GGrid2)
  1297. write(stderr,'(3a,i8,a,i8)') myname_, &
  1298. ':: inAv2 / GGrid2 length mismatch: ', &
  1299. ' AttrVect_lsize(inAv2) = ',AttrVect_lsize(inAv2), &
  1300. ' GeneralGrid_lsize(GGrid2) = ',GeneralGrid_lsize(GGrid2)
  1301. call die(myname_)
  1302. endif
  1303. ! Are we summing the integration weights for the input
  1304. ! GeneralGrids?
  1305. if(present(SumWeights)) then
  1306. mySumWeights = SumWeights
  1307. else
  1308. mySumWeights = .FALSE.
  1309. endif
  1310. ! Begin by invoking MaskedSpatialIntegralRAttrGG_() for each
  1311. ! AttrVect/GeneralGrid pair. This is done LOCALLY to create
  1312. ! integratedAv1 and integratedAv2, respectively.
  1313. ! Local Masked Integral #1:
  1314. if(present(iMaskTags1)) then
  1315. if(present(rMaskTags1)) then ! both Integer and Real Masking
  1316. call MaskedSpatialIntegralRAttrGG_(inAv1, outAv1, GGrid1, &
  1317. SpatialWeightTag1, iMaskTags1, &
  1318. rMaskTags1, UseFastMethod, &
  1319. mySumWeights, SpatialWeightTag1)
  1320. else ! Integer Masking Only
  1321. call MaskedSpatialIntegralRAttrGG_(inAv1, outAv1, GGrid1, &
  1322. SpatialWeightTag1, &
  1323. iMaskTags=iMaskTags1, &
  1324. UseFastMethod=UseFastMethod, &
  1325. SumWeights=mySumWeights, &
  1326. WeightSumTag=SpatialWeightTag1)
  1327. endif ! if(present(rMaskTags1))...
  1328. else ! No Integer Masking
  1329. if(present(rMaskTags1)) then ! Real Masking Only
  1330. call MaskedSpatialIntegralRAttrGG_(inAv1, outAv1, GGrid1, &
  1331. SpatialWeightTag=SpatialWeightTag1, &
  1332. rMaskTags=rMaskTags1, &
  1333. UseFastMethod=UseFastMethod, &
  1334. SumWeights=mySumWeights, &
  1335. WeightSumTag=SpatialWeightTag1)
  1336. else ! Neither Integer nor Real Masking
  1337. call MaskedSpatialIntegralRAttrGG_(inAv1, outAv1, GGrid1, &
  1338. SpatialWeightTag=SpatialWeightTag1, &
  1339. UseFastMethod=UseFastMethod, &
  1340. SumWeights=mySumWeights, &
  1341. WeightSumTag=SpatialWeightTag1)
  1342. endif ! if(present(rMaskTags1))...
  1343. endif ! if(present(iMaskTags1))...
  1344. ! Local Masked Integral #2:
  1345. if(present(iMaskTags2)) then
  1346. if(present(rMaskTags2)) then ! both Integer and Real Masking
  1347. call MaskedSpatialIntegralRAttrGG_(inAv2, outAv2, GGrid2, &
  1348. SpatialWeightTag2, iMaskTags2, &
  1349. rMaskTags2, UseFastMethod, &
  1350. mySumWeights, SpatialWeightTag2)
  1351. else ! Integer Masking Only
  1352. call MaskedSpatialIntegralRAttrGG_(inAv2, outAv2, GGrid2, &
  1353. SpatialWeightTag2, &
  1354. iMaskTags=iMaskTags2, &
  1355. UseFastMethod=UseFastMethod, &
  1356. SumWeights=mySumWeights, &
  1357. WeightSumTag=SpatialWeightTag2)
  1358. endif ! if(present(rMaskTags2))...
  1359. else ! No Integer Masking
  1360. if(present(rMaskTags2)) then ! Real Masking Only
  1361. call MaskedSpatialIntegralRAttrGG_(inAv2, outAv2, GGrid2, &
  1362. SpatialWeightTag=SpatialWeightTag2, &
  1363. rMaskTags=rMaskTags2, &
  1364. UseFastMethod=UseFastMethod, &
  1365. SumWeights=mySumWeights, &
  1366. WeightSumTag=SpatialWeightTag2)
  1367. else ! Neither Integer nor Real Masking
  1368. call MaskedSpatialIntegralRAttrGG_(inAv2, outAv2, GGrid2, &
  1369. SpatialWeightTag=SpatialWeightTag2, &
  1370. UseFastMethod=UseFastMethod, &
  1371. SumWeights=mySumWeights, &
  1372. WeightSumTag=SpatialWeightTag2)
  1373. endif ! if(present(rMaskTags2))...
  1374. endif ! if(present(iMaskTags2))...
  1375. ! Create the paired buffer for the Global Sum
  1376. nRA1 = AttrVect_nRAttr(outAv1)
  1377. nRA2 = AttrVect_nRAttr(outAv2)
  1378. PairedBufferLength = nRA1 + nRA2
  1379. allocate(PairedBuffer(PairedBufferLength), OutPairedBuffer(PairedBufferLength), &
  1380. stat=ierr)
  1381. if(ierr /= 0) then
  1382. write(stderr,'(2a,i8)') myname_, &
  1383. ':: Fatal error--allocate(PairedBuffer...failed, ierr = ',ierr
  1384. call die(myname_)
  1385. endif
  1386. ! Load the paired buffer
  1387. PairedBuffer(1:nRA1) = outAv1%rAttr(1:nRA1,1)
  1388. PairedBuffer(nRA1+1:PairedBufferLength) = outAv2%rAttr(1:nRA2,1)
  1389. ! Perform the global sum on the paired buffer
  1390. call MPI_AllReduce(PairedBuffer, OutPairedBuffer, PairedBufferLength, &
  1391. MP_Type(PairedBuffer(1)), MP_SUM, comm, ierr)
  1392. if(ierr /= 0) then
  1393. write(stderr,'(2a,i8)') myname_, &
  1394. ':: Fatal Error--MPI_ALLREDUCE() failed with ierror = ',ierr
  1395. call MP_perr_die(myname_,'MPI_ALLREDUCE() failed',ierr)
  1396. endif
  1397. ! Unload OutPairedBuffer into outAv1 and outAv2:
  1398. outAv1%rAttr(1:nRA1,1) = OutPairedBuffer(1:nRA1)
  1399. outAv2%rAttr(1:nRA2,1) = OutPairedBuffer(nRA1+1:PairedBufferLength)
  1400. deallocate(PairedBuffer, OutPairedBuffer, stat=ierr)
  1401. if(ierr /= 0) then
  1402. write(stderr,'(2a,i8)') myname_, &
  1403. ':: Fatal error--deallocate(PairedBuffer...failed, ierr = ',ierr
  1404. call die(myname_)
  1405. endif
  1406. end subroutine PairedMaskedIntegralRAttrGG_
  1407. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1408. ! Math and Computer Science Division, Argonne National Laboratory !
  1409. !BOP -------------------------------------------------------------------
  1410. !
  1411. ! !IROUTINE: PairedMaskedAverageRAttrGG_ - Do two masked averages at once.
  1412. !
  1413. ! !DESCRIPTION:
  1414. ! This routine computes a pair of masked spatial averages of the {\tt REAL}
  1415. ! attributes of the input {\tt AttrVect} arguments {\tt inAv} and
  1416. ! {\tt inAv2}, returning the masked averagess in the output {\tt AttrVect}
  1417. ! {\tt outAv1} and {\tt outAv2}, respectively. All of the spatial weighting
  1418. ! and masking data for each set of averages are assumed stored in the input
  1419. ! {\tt GeneralGrid} arguments {\tt GGrid} and {\tt GGrid2}. If integer
  1420. ! masks are to be used, their integer attribute names in {\tt GGrid1}
  1421. ! and {\tt GGrid2} are named as a colon-delimited lists in the optional
  1422. ! {\tt CHARACTER} input arguments {\tt iMaskTags1} and {\tt iMaskTags2},
  1423. ! respectively. Real masks (if desired) are referenced by their real
  1424. ! attribute names in {\tt GGrid1} and {\tt GGrid2} are named as
  1425. ! colon-delimited lists in the optional {\tt CHARACTER} input arguments
  1426. ! {\tt rMaskTags1} and {\tt rMaskTags2}, respectively. The user specifies
  1427. ! a choice of mask combination method with the input {\tt LOGICAL} argument
  1428. ! {\tt UseFastMethod}. If ${\tt UseFastMethod} = {\tt .FALSE.}$ this
  1429. ! routine checks each mask entry to ensure that the integer masks contain
  1430. ! only ones and zeroes, and that entries in the real masks are all in
  1431. ! the closed interval $[0,1]$. If ${\tt UseFastMethod} = {\tt .TRUE.}$,
  1432. ! this routine performs direct products of the masks, assuming that the
  1433. ! user has validated them in advance. This paired average is implicitly
  1434. ! a distributed operation (the whole motivation for pairing the averages
  1435. ! is to reduce communication latency costs), and the Fortran MPI communicator
  1436. ! handle is defined by the input {\tt INTEGER} argument {\tt comm}. The
  1437. ! summation is an AllReduce operation, with all processes receiving the
  1438. ! global sum.
  1439. !
  1440. ! {\bf N.B.: } The local lengths of the {\tt AttrVect} argument {\tt inAv1}
  1441. ! and the {\tt GeneralGrid} {\tt GGrid1} must be equal. That is, there
  1442. ! must be a one-to-one correspondence between the field point values stored
  1443. ! in {\tt inAv1} and the point weights stored in {\tt GGrid1}. The same
  1444. ! relationship must apply between {\tt inAv2} and {\tt GGrid2}.
  1445. !
  1446. ! {\bf N.B.: } The output {\tt AttrVect} arguments {\tt outAv1} and
  1447. ! {\tt outAv2} are allocated data structures. The user must deallocate them
  1448. ! using the routine {\tt AttrVect\_clean()} when they are no longer needed.
  1449. ! Failure to do so will result in a memory leak.
  1450. !
  1451. ! !INTERFACE:
  1452. subroutine PairedMaskedAverageRAttrGG_(inAv1, outAv1, GGrid1, &
  1453. SpatialWeightTag1, rMaskTags1, &
  1454. iMaskTags1, inAv2, outAv2, GGrid2, &
  1455. SpatialWeightTag2, rMaskTags2, &
  1456. iMaskTags2, UseFastMethod, &
  1457. comm)
  1458. ! ! USES:
  1459. use m_stdio
  1460. use m_die
  1461. use m_mpif90
  1462. use m_realkinds, only : FP
  1463. use m_AttrVect, only : AttrVect
  1464. use m_AttrVect, only : AttrVect_init => init
  1465. use m_AttrVect, only : AttrVect_zero => zero
  1466. use m_AttrVect, only : AttrVect_clean => clean
  1467. use m_AttrVect, only : AttrVect_lsize => lsize
  1468. use m_AttrVect, only : AttrVect_nRAttr => nRAttr
  1469. use m_GeneralGrid, only : GeneralGrid
  1470. use m_GeneralGrid, only : GeneralGrid_lsize => lsize
  1471. use m_GeneralGrid, only : GeneralGrid_indexRA => indexRA
  1472. use m_GeneralGrid, only : GeneralGrid_exportRAttr => exportRAttr
  1473. use m_AttrVectReduce, only : AttrVect_LocalWeightedSumRAttr => &
  1474. LocalWeightedSumRAttr
  1475. use m_List, only : List
  1476. use m_List, only : List_nullify => nullify
  1477. implicit none
  1478. ! !INPUT PARAMETERS:
  1479. type(AttrVect), intent(IN) :: inAv1
  1480. type(GeneralGrid), intent(IN) :: GGrid1
  1481. character(len=*), intent(IN) :: SpatialWeightTag1
  1482. character(len=*), optional, intent(IN) :: iMaskTags1
  1483. character(len=*), optional, intent(IN) :: rMaskTags1
  1484. type(AttrVect), intent(IN) :: inAv2
  1485. type(GeneralGrid), intent(IN) :: GGrid2
  1486. character(len=*), intent(IN) :: SpatialWeightTag2
  1487. character(len=*), optional, intent(IN) :: iMaskTags2
  1488. character(len=*), optional, intent(IN) :: rMaskTags2
  1489. logical, intent(IN) :: UseFastMethod
  1490. integer, intent(IN) :: comm
  1491. ! !OUTPUT PARAMETERS:
  1492. type(AttrVect), intent(OUT) :: outAv1
  1493. type(AttrVect), intent(OUT) :: outAv2
  1494. ! !REVISION HISTORY:
  1495. ! 17Jun02 - J.W. Larson <larson@mcs.anl.gov> - Initial version.
  1496. ! 19Jun02 - J.W. Larson <larson@mcs.anl.gov> - Shortened the name
  1497. ! for compatibility with the Portland Group f90 compiler
  1498. ! 25Jul02 - J.W. Larson E.T. Ong - Bug fix. This routine was
  1499. ! previously doing integrals rather than area averages.
  1500. !
  1501. !EOP ___________________________________________________________________
  1502. character(len=*),parameter :: myname_ = &
  1503. myname//'::PairedMaskedAverageRAttrGG_'
  1504. type(AttrVect) :: LocalIntegral1, LocalIntegral2
  1505. type(List) :: nullIList
  1506. real(FP), dimension(:), pointer :: PairedBuffer, OutPairedBuffer
  1507. integer :: i, ierr, nRA1, nRA2, PairedBufferLength
  1508. real(FP) :: WeightSumInv
  1509. ! Basic Argument Validity Checks:
  1510. if(AttrVect_lsize(inAv1) /= GeneralGrid_lsize(GGrid1)) then
  1511. ierr = AttrVect_lsize(inAv1) - GeneralGrid_lsize(GGrid1)
  1512. write(stderr,'(3a,i8,a,i8)') myname_, &
  1513. ':: inAv1 / GGrid1 length mismatch: ', &
  1514. ' AttrVect_lsize(inAv1) = ',AttrVect_lsize(inAv1), &
  1515. ' GeneralGrid_lsize(GGrid1) = ',GeneralGrid_lsize(GGrid1)
  1516. call die(myname_)
  1517. endif
  1518. if(AttrVect_lsize(inAv2) /= GeneralGrid_lsize(GGrid2)) then
  1519. ierr = AttrVect_lsize(inAv2) - GeneralGrid_lsize(GGrid2)
  1520. write(stderr,'(3a,i8,a,i8)') myname_, &
  1521. ':: inAv2 / GGrid2 length mismatch: ', &
  1522. ' AttrVect_lsize(inAv2) = ',AttrVect_lsize(inAv2), &
  1523. ' GeneralGrid_lsize(GGrid2) = ',GeneralGrid_lsize(GGrid2)
  1524. call die(myname_)
  1525. endif
  1526. ! Begin by invoking MaskedSpatialIntegralRAttrGG_() for each
  1527. ! AttrVect/GeneralGrid pair. This is done LOCALLY to create
  1528. ! LocalIntegral1 and LocalIntegral2, respectively.
  1529. ! Local Masked Integral #1:
  1530. if(present(iMaskTags1)) then
  1531. if(present(rMaskTags1)) then ! both Integer and Real Masking
  1532. call MaskedSpatialIntegralRAttrGG_(inAv1, LocalIntegral1, GGrid1, &
  1533. SpatialWeightTag1, iMaskTags1, &
  1534. rMaskTags1, UseFastMethod, &
  1535. .TRUE., SpatialWeightTag1)
  1536. else ! Integer Masking Only
  1537. call MaskedSpatialIntegralRAttrGG_(inAv1, LocalIntegral1, GGrid1, &
  1538. SpatialWeightTag1, &
  1539. iMaskTags=iMaskTags1, &
  1540. UseFastMethod=UseFastMethod, &
  1541. SumWeights=.TRUE., &
  1542. WeightSumTag=SpatialWeightTag1)
  1543. endif ! if(present(rMaskTags1))...
  1544. else ! No Integer Masking
  1545. if(present(rMaskTags1)) then ! Real Masking Only
  1546. call MaskedSpatialIntegralRAttrGG_(inAv1, LocalIntegral1, GGrid1, &
  1547. SpatialWeightTag=SpatialWeightTag1, &
  1548. rMaskTags=rMaskTags1, &
  1549. UseFastMethod=UseFastMethod, &
  1550. SumWeights=.TRUE., &
  1551. WeightSumTag=SpatialWeightTag1)
  1552. else ! Neither Integer nor Real Masking
  1553. call MaskedSpatialIntegralRAttrGG_(inAv1, LocalIntegral1, GGrid1, &
  1554. SpatialWeightTag=SpatialWeightTag1, &
  1555. UseFastMethod=UseFastMethod, &
  1556. SumWeights=.TRUE., &
  1557. WeightSumTag=SpatialWeightTag1)
  1558. endif ! if(present(rMaskTags1))...
  1559. endif ! if(present(iMaskTags1))...
  1560. ! Local Masked Integral #2:
  1561. if(present(iMaskTags2)) then
  1562. if(present(rMaskTags2)) then ! both Integer and Real Masking
  1563. call MaskedSpatialIntegralRAttrGG_(inAv2, LocalIntegral2, GGrid2, &
  1564. SpatialWeightTag2, iMaskTags2, &
  1565. rMaskTags2, UseFastMethod, &
  1566. .TRUE., SpatialWeightTag2)
  1567. else ! Integer Masking Only
  1568. call MaskedSpatialIntegralRAttrGG_(inAv2, LocalIntegral2, GGrid2, &
  1569. SpatialWeightTag2, &
  1570. iMaskTags=iMaskTags2, &
  1571. UseFastMethod=UseFastMethod, &
  1572. SumWeights=.TRUE., &
  1573. WeightSumTag=SpatialWeightTag2)
  1574. endif ! if(present(rMaskTags2))...
  1575. else ! No Integer Masking
  1576. if(present(rMaskTags2)) then ! Real Masking Only
  1577. call MaskedSpatialIntegralRAttrGG_(inAv2, LocalIntegral2, GGrid2, &
  1578. SpatialWeightTag=SpatialWeightTag2, &
  1579. rMaskTags=rMaskTags2, &
  1580. UseFastMethod=UseFastMethod, &
  1581. SumWeights=.TRUE., &
  1582. WeightSumTag=SpatialWeightTag2)
  1583. else ! Neither Integer nor Real Masking
  1584. call MaskedSpatialIntegralRAttrGG_(inAv2, LocalIntegral2, GGrid2, &
  1585. SpatialWeightTag=SpatialWeightTag2, &
  1586. UseFastMethod=UseFastMethod, &
  1587. SumWeights=.TRUE., &
  1588. WeightSumTag=SpatialWeightTag2)
  1589. endif ! if(present(rMaskTags2))...
  1590. endif ! if(present(iMaskTags2))...
  1591. ! Create the paired buffer for the Global Sum
  1592. nRA1 = AttrVect_nRAttr(LocalIntegral1)
  1593. nRA2 = AttrVect_nRAttr(LocalIntegral2)
  1594. PairedBufferLength = nRA1 + nRA2
  1595. allocate(PairedBuffer(PairedBufferLength), OutPairedBuffer(PairedBufferLength), &
  1596. stat=ierr)
  1597. if(ierr /= 0) then
  1598. write(stderr,'(2a,i8)') myname_, &
  1599. ':: Fatal error--allocate(PairedBuffer...failed, ierr = ',ierr
  1600. call die(myname_)
  1601. endif
  1602. ! Load the paired buffer
  1603. PairedBuffer(1:nRA1) = LocalIntegral1%rAttr(1:nRA1,1)
  1604. PairedBuffer(nRA1+1:PairedBufferLength) = LocalIntegral2%rAttr(1:nRA2,1)
  1605. ! Perform the global sum on the paired buffer
  1606. call MPI_AllReduce(PairedBuffer, OutPairedBuffer, PairedBufferLength, &
  1607. MP_Type(PairedBuffer(1)), MP_SUM, comm, ierr)
  1608. if(ierr /= 0) then
  1609. write(stderr,'(2a,i8)') myname_, &
  1610. ':: Fatal Error--MPI_ALLREDUCE() failed with ierror = ',ierr
  1611. call MP_perr_die(myname_,'MPI_ALLREDUCE() failed',ierr)
  1612. endif
  1613. ! Create outAv1 and outAv2 from inAv1 and inAv2, respectively:
  1614. call List_nullify(nullIList)
  1615. call AttrVect_init(outAv1, iList=nullIList, rList=inAv1%rList, lsize=1)
  1616. call AttrVect_zero(outAv1)
  1617. call AttrVect_init(outAv2, iList=nullIList, rList=inAv2%rList, lsize=1)
  1618. call AttrVect_zero(outAv2)
  1619. ! Unload/rescale OutPairedBuffer into outAv1 and outAv2:
  1620. nRA1 = AttrVect_nRAttr(outAv1)
  1621. nRA2 = AttrVect_nRAttr(outAv2)
  1622. ! First outAv1:
  1623. if(OutPairedBuffer(nRA1+1) /= 0.) then
  1624. WeightSumInv = 1._FP / OutPairedBuffer(nRA1+1) ! Sum of weights on grid1
  1625. ! is the nRA1+1th element in
  1626. ! the paired buffer.
  1627. else
  1628. write(stderr,'(2a)') myname_, &
  1629. ':: FATAL ERROR--Sum of the Weights for integral #1 is zero! Terminating...'
  1630. call die(myname_)
  1631. endif
  1632. ! Rescale global integral to get global average:
  1633. do i=1,nRA1
  1634. outAv1%rAttr(i,1) = WeightSumInv * OutPairedBuffer(i)
  1635. end do
  1636. ! And then outAv2:
  1637. if(OutPairedBuffer(PairedBufferLength) /= 0.) then
  1638. WeightSumInv = 1._FP / OutPairedBuffer(PairedBufferLength) ! Sum of weights on grid2
  1639. ! is the last element in
  1640. ! the paired buffer.
  1641. else
  1642. write(stderr,'(2a)') myname_, &
  1643. ':: FATAL ERROR--Sum of the Weights for integral #2 is zero! Terminating...'
  1644. call die(myname_)
  1645. endif
  1646. ! Rescale global integral to get global average:
  1647. do i=1,nRA2
  1648. outAv2%rAttr(i,1) = WeightSumInv * OutPairedBuffer(i+nRA1+1)
  1649. end do
  1650. ! Clean up allocated structures
  1651. call AttrVect_clean(LocalIntegral1)
  1652. call AttrVect_clean(LocalIntegral2)
  1653. deallocate(PairedBuffer, OutPairedBuffer, stat=ierr)
  1654. if(ierr /= 0) then
  1655. write(stderr,'(2a,i8)') myname_, &
  1656. ':: Fatal error--deallocate(PairedBuffer...failed, ierr = ',ierr
  1657. call die(myname_)
  1658. endif
  1659. end subroutine PairedMaskedAverageRAttrGG_
  1660. end module m_SpatialIntegral