m_AccumulatorComms.F90 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! Math and Computer Science Division, Argonne National Laboratory !
  3. !-----------------------------------------------------------------------
  4. ! CVS m_AccumulatorComms.F90,v 1.12 2004-04-21 22:16:31 jacob Exp
  5. ! CVS MCT_2_8_0
  6. !BOP -------------------------------------------------------------------
  7. !
  8. ! !MODULE: m_AccumulatorComms - MPI Communication Methods for the Accumulator
  9. !
  10. !
  11. ! !DESCRIPTION:
  12. !
  13. ! This module contains communications methods for the {\tt Accumulator}
  14. ! datatype (see {\tt m\_Accumulator} for details). MCT's communications
  15. ! are implemented in terms of the Message Passing Interface (MPI) standard,
  16. ! and we have as best as possible, made the interfaces to these routines
  17. ! appear as similar as possible to the corresponding MPI routines. For the
  18. ! { \tt Accumulator}, we currently support only the following collective
  19. ! operations: broadcast, gather, and scatter. The gather and scatter
  20. ! operations rely on domain decomposition descriptors that are defined
  21. ! elsewhere in MCT: the {\tt GlobalMap}, which is a one-dimensional
  22. ! decomposition (see the MCT module {\tt m\_GlobalMap} for more details);
  23. ! and the {\tt GlobalSegMap}, which is a segmented decomposition capable
  24. ! of supporting multidimensional domain decompositions (see the MCT module
  25. ! {\tt m\_GlobalSegMap} for more details).
  26. !
  27. ! !INTERFACE:
  28. module m_AccumulatorComms
  29. !
  30. ! !USES:
  31. !
  32. ! No external modules are used in the declaration section of this module.
  33. implicit none
  34. private ! except
  35. ! !PUBLIC MEMBER FUNCTIONS:
  36. !
  37. ! List of communications Methods for the Accumulator class
  38. public :: gather ! gather all local vectors to the root
  39. public :: scatter ! scatter from the root to all PEs
  40. public :: bcast ! bcast from root to all PEs
  41. ! Definition of interfaces for the communication methods for
  42. ! the Accumulator:
  43. interface gather ; module procedure &
  44. GM_gather_, &
  45. GSM_gather_
  46. end interface
  47. interface scatter ; module procedure &
  48. GM_scatter_, &
  49. GSM_scatter_
  50. end interface
  51. interface bcast ; module procedure bcast_ ; end interface
  52. ! !REVISION HISTORY:
  53. ! 31Oct00 - Jay Larson <larson@mcs.anl.gov> - initial prototype--
  54. ! These routines were separated from the module m_Accumulator
  55. ! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - Specification of
  56. ! APIs for the routines GSM_gather_() and GSM_scatter_().
  57. ! 10May01 - Jay Larson <larson@mcs.anl.gov> - Changes in the
  58. ! comms routine to match the MPI model for collective
  59. ! communications, and general clean-up of prologues.
  60. ! 9Aug01 - E.T. Ong <eong@mcs.anl.gov> - Added private routine
  61. ! bcastp_. Used new Accumulator routines initp_ and
  62. ! initialized_ to simplify the routines.
  63. ! 26Aug02 - E.T. Ong <eong@mcs.anl.gov> - thourough code revision;
  64. ! no added routines
  65. !EOP ___________________________________________________________________
  66. character(len=*),parameter :: myname='MCT::m_AccumulatorComms'
  67. contains
  68. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  69. ! Math and Computer Science Division, Argonne National Laboratory !
  70. !BOP -------------------------------------------------------------------
  71. !
  72. ! !IROUTINE: GM_gather_ - Gather Accumulator Distributed by a GlobalMap
  73. !
  74. ! !DESCRIPTION: {\tt GM\_gather()} takes a distributed (across the
  75. ! communicator associated with the handle {\tt comm}) input
  76. ! {\tt Accumulator} argument {\tt iC} and gathers its data to the
  77. ! {\tt Accumulator} {\tt oC} on the {\tt root}. The decomposition of
  78. ! {\tt iC} is described by the input {\tt GlobalMap} argument {\tt Gmap}.
  79. ! The success (failure) of this operation is signified by the zero (nonzero)
  80. ! value of the optional output argument {\tt stat}.
  81. !
  82. ! !INTERFACE:
  83. subroutine GM_gather_(iC, oC, GMap, root, comm, stat)
  84. !
  85. ! !USES:
  86. !
  87. use m_stdio
  88. use m_die
  89. use m_mpif90
  90. use m_GlobalMap, only : GlobalMap
  91. use m_AttrVect, only : AttrVect_clean => clean
  92. use m_Accumulator, only : Accumulator
  93. use m_Accumulator, only : Accumulator_initialized => initialized
  94. use m_Accumulator, only : Accumulator_initv => init
  95. use m_AttrVectComms, only : AttrVect_gather => gather
  96. implicit none
  97. ! !INPUT PARAMETERS:
  98. !
  99. type(Accumulator), intent(in) :: iC
  100. type(GlobalMap) , intent(in) :: GMap
  101. integer, intent(in) :: root
  102. integer, intent(in) :: comm
  103. ! !OUTPUT PARAMETERS:
  104. !
  105. type(Accumulator), intent(out) :: oC
  106. integer, optional,intent(out) :: stat
  107. ! !REVISION HISTORY:
  108. ! 13Sep00 - Jay Larson <larson@mcs.anl.gov> - initial prototype
  109. ! 31Oct00 - Jay Larson <larson@mcs.anl.gov> - relocated to the
  110. ! module m_AccumulatorComms
  111. ! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - renamed GM_gather_
  112. ! 10May01 - Jay Larson <larson@mcs.anl.gov> - revamped comms
  113. ! model to match MPI comms model, and cleaned up prologue
  114. ! 9Aug01 - E.T. Ong <eong@mcs.anl.gov> - 2nd prototype. Used the
  115. ! intiialized_ and accumulator init routines.
  116. !EOP ___________________________________________________________________
  117. character(len=*),parameter :: myname_=myname//'::GM_gather_'
  118. integer :: myID, ier, i
  119. logical :: status
  120. ! Initialize status flag (if present)
  121. if(present(stat)) stat=0
  122. call MP_comm_rank(comm, myID, ier)
  123. if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
  124. ! Argument check of iC: kill if iC is not initialized
  125. ! on all processes
  126. status = Accumulator_initialized(iC,die_flag=.true.,source_name=myname_)
  127. ! NOTE: removed argument check for oC on the root.
  128. ! Is there any good way to check if an accumulator is NOT initialized?
  129. ! Initialize oC from iC. Clean oC%data - we don't want this av.
  130. if(myID == root) then
  131. call Accumulator_initv(oC,iC,lsize=1, &
  132. num_steps=iC%num_steps,steps_done=iC%steps_done)
  133. call AttrVect_clean(oC%data)
  134. endif
  135. ! Initialize oC%data. Gather distributed iC%data to oC%data on the root
  136. call AttrVect_gather(iC%data, oC%data, GMap, root, comm, ier)
  137. if(ier /= 0) then
  138. call perr(myname_,'AttrVect_gather(iC%data, oC%data...',ier)
  139. if(.not.present(stat)) call die(myname_)
  140. stat=ier
  141. return
  142. endif
  143. ! Check oC to see if its valid
  144. if(myID == root) then
  145. status = Accumulator_initialized(oC,die_flag=.true.,source_name=myname_)
  146. endif
  147. end subroutine GM_gather_
  148. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  149. ! Math and Computer Science Division, Argonne National Laboratory !
  150. !BOP -------------------------------------------------------------------
  151. !
  152. ! !IROUTINE: GSM_gather_ - Gather Accumulator Distributed by a GlobalSegMap
  153. !
  154. ! !DESCRIPTION: This routine takes the distrubuted (on the communcator
  155. ! associated with the handle {\tt comm}) input {\tt Accumulator}
  156. ! argument {\tt iC} gathers it to the the {\tt Accumulator} argument
  157. ! {\tt oC} (valid only on the {\tt root}). The decompositon of {\tt iC}
  158. ! is contained in the input {\tt GlobalSegMap} argument {\tt GSMap}.
  159. ! The success (failure) of this operation is signified by the zero
  160. ! (nonzero) returned value of the {\tt INTEGER} flag {\tt stat}.
  161. !
  162. ! !INTERFACE:
  163. subroutine GSM_gather_(iC, oC, GSMap, root, comm, stat)
  164. !
  165. ! !USES:
  166. !
  167. use m_stdio
  168. use m_die
  169. use m_mpif90
  170. use m_GlobalSegMap, only : GlobalSegMap
  171. use m_AttrVect, only : AttrVect_clean => clean
  172. use m_Accumulator, only : Accumulator
  173. use m_Accumulator, only : Accumulator_initv => init
  174. use m_Accumulator, only : Accumulator_initialized => initialized
  175. use m_AttrVectComms, only : AttrVect_gather => gather
  176. implicit none
  177. ! !INPUT PARAMETERS:
  178. !
  179. type(Accumulator), intent(in) :: iC
  180. type(GlobalSegMap), intent(in) :: GSMap
  181. integer, intent(in) :: root
  182. integer, intent(in) :: comm
  183. ! !OUTPUT PARAMETERS:
  184. !
  185. type(Accumulator), intent(out) :: oC
  186. integer, optional, intent(out) :: stat
  187. ! !REVISION HISTORY:
  188. ! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - API specification.
  189. ! 10May01 - Jay Larson <larson@mcs.anl.gov> - Initial code and
  190. ! cleaned up prologue.
  191. ! 09Aug01 - E.T. Ong <eong@mcs.anl.gov> - 2nd prototype. Used the
  192. ! intiialized_ and accumulator init routines.
  193. !EOP ___________________________________________________________________
  194. character(len=*),parameter :: myname_=myname//'::GSM_gather_'
  195. integer :: myID, ier, i
  196. logical :: status
  197. ! Initialize status flag (if present)
  198. if(present(stat)) stat=0
  199. call MP_comm_rank(comm, myID, ier)
  200. if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
  201. ! Argument check of iC
  202. status = Accumulator_initialized(iC,die_flag=.true.,source_name=myname_)
  203. ! NOTE: removed argument check for oC on the root.
  204. ! Is there any good way to check if an accumulator is NOT initialized?
  205. ! Initialize oC from iC. Clean oC%data - we don't want this av.
  206. if(myID == root) then
  207. call Accumulator_initv(oC,iC,lsize=1, &
  208. num_steps=iC%num_steps,steps_done=iC%steps_done)
  209. call AttrVect_clean(oC%data)
  210. endif
  211. ! Gather distributed iC%data to oC%data on the root
  212. call AttrVect_gather(iC%data, oC%data, GSMap, root, comm, ier)
  213. if(ier /= 0) then
  214. call perr(myname_,'AttrVect_gather(iC%data, oC%data...',ier)
  215. if(.not.present(stat)) call die(myname_)
  216. stat=ier
  217. return
  218. endif
  219. ! Check oC to see if its valid
  220. if(myID == root) then
  221. status = Accumulator_initialized(oC,die_flag=.true.,source_name=myname_)
  222. endif
  223. end subroutine GSM_gather_
  224. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  225. ! Math and Computer Science Division, Argonne National Laboratory !
  226. !BOP -------------------------------------------------------------------
  227. !
  228. ! !IROUTINE: GM_scatter_ - Scatter an Accumulator using a GlobalMap
  229. !
  230. ! !DESCRIPTION: This routine takes the input {\tt Accumulator} argument
  231. ! {\tt iC} (valid only on the {\tt root}), and scatters it to the
  232. ! distributed {\tt Accumulator} argument {\tt oC} on the processes
  233. ! associated with the communicator handle {\tt comm}. The decompositon
  234. ! used to scatter the data is contained in the input {\tt GlobalMap}
  235. ! argument {\tt GMap}. The success (failure) of this operation is
  236. ! signified by the zero (nonzero) returned value of the {\tt INTEGER}
  237. ! flag {\tt stat}.
  238. !
  239. ! !INTERFACE:
  240. subroutine GM_scatter_(iC, oC, GMap, root, comm, stat)
  241. !
  242. ! !USES:
  243. !
  244. use m_stdio
  245. use m_die
  246. use m_mpif90
  247. use m_GlobalMap, only : GlobalMap
  248. use m_Accumulator, only : Accumulator
  249. use m_Accumulator, only : Accumulator_initv => init
  250. use m_Accumulator, only : Accumulator_initialized => initialized
  251. use m_AttrVect, only : AttrVect_clean => clean
  252. use m_AttrVectComms, only : AttrVect_scatter => scatter
  253. implicit none
  254. ! !INPUT PARAMETERS:
  255. !
  256. type(Accumulator), intent(in) :: iC
  257. type(GlobalMap), intent(in) :: GMap
  258. integer, intent(in) :: root
  259. integer, intent(in) :: comm
  260. ! !OUTPUT PARAMETERS:
  261. !
  262. type(Accumulator), intent(out) :: oC
  263. integer, optional, intent(out) :: stat
  264. ! !REVISION HISTORY:
  265. ! 14Sep00 - Jay Larson <larson@mcs.anl.gov> - initial prototype
  266. ! 31Oct00 - Jay Larson <larson@mcs.anl.gov> - moved from the module
  267. ! m_Accumulator to m_AccumulatorComms
  268. ! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - renamed GM_scatter_.
  269. ! 10May01 - Jay Larson <larson@mcs.anl.gov> - revamped code to fit
  270. ! MPI-like comms model, and cleaned up prologue.
  271. ! 09Aug01 - E.T. Ong <eong@mcs.anl.gov> - 2nd prototype. Used the
  272. ! initialized_, Accumulator init_, and bcastp_ routines.
  273. !EOP ___________________________________________________________________
  274. character(len=*),parameter :: myname_=myname//'::GM_scatter_'
  275. integer :: myID, ier
  276. logical :: status
  277. ! Initialize status flag (if present)
  278. if(present(stat)) stat=0
  279. call MP_comm_rank(comm, myID, ier)
  280. if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
  281. ! Argument check of iC
  282. if(myID==root) then
  283. status = Accumulator_initialized(iC,die_flag=.true.,source_name=myname_)
  284. endif
  285. ! NOTE: removed argument check for oC on all processes.
  286. ! Is there any good way to check if an accumulator is NOT initialized?
  287. ! Copy accumulator from iC to oC
  288. ! Clean up oC%data on root.
  289. if(myID == root) then
  290. call Accumulator_initv(oC,iC,lsize=1,num_steps=iC%num_steps, &
  291. steps_done=iC%steps_done)
  292. call AttrVect_clean(oC%data)
  293. endif
  294. ! Broadcast oC (except for oC%data)
  295. call bcastp_(oC, root, comm, stat)
  296. ! Scatter the AttrVect component of iC
  297. call AttrVect_scatter(iC%data, oC%data, GMap, root, comm, ier)
  298. if(ier /= 0) then
  299. call perr(myname_,'AttrVect_scatter(iC%data, oC%data...',ier)
  300. if(.not.present(stat)) call die(myname_)
  301. stat=ier
  302. return
  303. endif
  304. ! Check oC to see if its valid
  305. status = Accumulator_initialized(oC,die_flag=.true.,source_name=myname_)
  306. end subroutine GM_scatter_
  307. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  308. ! Math and Computer Science Division, Argonne National Laboratory !
  309. !BOP -------------------------------------------------------------------
  310. !
  311. ! !IROUTINE: GSM_scatter_ - Scatter an Accumulator using a GlobalSegMap
  312. !
  313. ! !DESCRIPTION: This routine takes the input {\tt Accumulator} argument
  314. ! {\tt iC} (valid only on the {\tt root}), and scatters it to the
  315. ! distributed {\tt Accumulator} argument {\tt oC} on the processes
  316. ! associated with the communicator handle {\tt comm}. The decompositon
  317. ! used to scatter the data is contained in the input {\tt GlobalSegMap}
  318. ! argument {\tt GSMap}. The success (failure) of this operation is
  319. ! signified by the zero (nonzero) returned value of the {\tt INTEGER}
  320. ! flag {\tt stat}.
  321. !
  322. ! !INTERFACE:
  323. subroutine GSM_scatter_(iC, oC, GSMap, root, comm, stat)
  324. !
  325. ! !USES:
  326. !
  327. use m_stdio
  328. use m_die
  329. use m_mpif90
  330. use m_GlobalSegMap, only : GlobalSegMap
  331. use m_Accumulator, only : Accumulator
  332. use m_Accumulator, only : Accumulator_initv => init
  333. use m_Accumulator, only : Accumulator_initialized => initialized
  334. use m_AttrVect, only : AttrVect_clean => clean
  335. use m_AttrVectComms, only : AttrVect_scatter => scatter
  336. implicit none
  337. ! !INPUT PARAMETERS:
  338. !
  339. type(Accumulator), intent(in) :: iC
  340. type(GlobalSegMap), intent(in) :: GSMap
  341. integer, intent(in) :: root
  342. integer, intent(in) :: comm
  343. ! !OUTPUT PARAMETERS:
  344. !
  345. type(Accumulator), intent(out) :: oC
  346. integer, optional, intent(out) :: stat
  347. ! !REVISION HISTORY:
  348. ! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - API specification.
  349. ! 10May01 - Jay Larson <larson@mcs.anl.gov> - Initial code/prologue
  350. ! 09Aug01 - E.T. Ong <eong@mcs.anl.gov> 2nd prototype. Used the
  351. ! initialized and accumulator init routines.
  352. !EOP ___________________________________________________________________
  353. character(len=*),parameter :: myname_=myname//'::GSM_scatter_'
  354. integer :: myID, ier
  355. logical :: status
  356. ! Initialize status flag (if present)
  357. if(present(stat)) stat=0
  358. call MP_comm_rank(comm, myID, ier)
  359. if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
  360. ! Argument check of iC
  361. if(myID == root) then
  362. status = Accumulator_initialized(iC,die_flag=.true.,source_name=myname_)
  363. endif
  364. ! NOTE: removed argument check for oC on all processes.
  365. ! Is there any good way to check if an accumulator is NOT initialized?
  366. ! Copy accumulator from iC to oC
  367. ! Clean up oC%data on root.
  368. if(myID == root) then
  369. call Accumulator_initv(oC,iC,lsize=1,num_steps=iC%num_steps, &
  370. steps_done=iC%steps_done)
  371. call AttrVect_clean(oC%data)
  372. endif
  373. ! Broadcast oC (except for oC%data)
  374. call bcastp_(oC, root, comm, stat)
  375. ! Scatter the AttrVect component of aC
  376. call AttrVect_scatter(iC%data, oC%data, GSMap, root, comm, ier)
  377. if(ier /= 0) then
  378. call perr(myname_,'AttrVect_scatter(iC%data, oC%data...',ier)
  379. if(.not.present(stat)) call die(myname_)
  380. stat=ier
  381. return
  382. endif
  383. ! Check oC if its valid
  384. status = Accumulator_initialized(oC,die_flag=.true.,source_name=myname_)
  385. end subroutine GSM_scatter_
  386. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  387. ! Math and Computer Science Division, Argonne National Laboratory !
  388. !BOP -------------------------------------------------------------------
  389. !
  390. ! !IROUTINE: bcast_ - Broadcast an Accumulator
  391. !
  392. ! !DESCRIPTION: This routine takes the input {\tt Accumulator} argument
  393. ! {\tt aC} (on input valid only on the {\tt root}), and broadcasts it
  394. ! to all the processes associated with the communicator handle
  395. ! {\tt comm}. The success (failure) of this operation is signified by
  396. ! the zero (nonzero) returned value of the {\tt INTEGER} flag {\tt stat}.
  397. !
  398. ! !INTERFACE:
  399. !
  400. subroutine bcast_(aC, root, comm, stat)
  401. !
  402. ! !USES:
  403. !
  404. use m_die
  405. use m_mpif90
  406. use m_AttrVectComms, only : AttrVect_bcast => bcast
  407. use m_Accumulator, only : Accumulator
  408. use m_Accumulator, only : Accumulator_initialized => initialized
  409. implicit none
  410. ! !INPUT PARAMETERS:
  411. !
  412. integer,intent(in) :: root
  413. integer,intent(in) :: comm
  414. ! !INPUT/OUTPUT PARAMETERS:
  415. !
  416. type(Accumulator), intent(inout) :: aC ! (IN) on root, (OUT) elsewhere
  417. ! !OUTPUT PARAMETERS:
  418. !
  419. integer, optional, intent(out) :: stat
  420. ! !REVISION HISTORY:
  421. ! 14Sep00 - Jay Larson <larson@mcs.anl.gov> - initial prototype
  422. ! 31Oct00 - Jay Larson <larson@mcs.anl.gov> - moved from the module
  423. ! m_Accumulator to m_AccumulatorComms
  424. ! 09May01 - Jay Larson <larson@mcs.anl.gov> - cleaned up prologue
  425. ! 09Aug01 - E.T. Ong <eong@mcs.anl.gov> - 2nd prototype. Made use of
  426. ! bcastp_ routine. Also more argument checks.
  427. !EOP ___________________________________________________________________
  428. character(len=*),parameter :: myname_=myname//'::bcast_'
  429. integer :: myID
  430. integer :: ier
  431. logical :: status
  432. if(present(stat)) stat=0
  433. call MP_comm_rank(comm,myID,ier)
  434. if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
  435. ! Argument check : Kill if the root aC is not initialized,
  436. ! or if the non-root aC is initialized
  437. if(myID == root) then
  438. status = Accumulator_initialized(aC,die_flag=.true.,source_name=myname_)
  439. endif
  440. ! NOTE: removed argument check for aC on all non-root processes.
  441. ! Is there any good way to check if an accumulator is NOT initialized?
  442. call bcastp_(aC, root, comm, stat)
  443. ! Broadcast the root value of aC%data
  444. call AttrVect_bcast(aC%data, root, comm, ier)
  445. if(ier /= 0) then
  446. call perr(myname_,'AttrVect_bcast(aC%data)',ier)
  447. if(.not.present(stat)) call die(myname_)
  448. stat=ier
  449. return
  450. endif
  451. ! Check that aC on all processes are initialized
  452. status = Accumulator_initialized(aC,die_flag=.true.,source_name=myname_)
  453. end subroutine bcast_
  454. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  455. ! Math and Computer Science Division, Argonne National Laboratory !
  456. !BOP -------------------------------------------------------------------
  457. !
  458. ! !IROUTINE: bcastp_ - Broadcast an Accumulator (but Not its Registers)
  459. !
  460. ! !DESCRIPTION: This routine broadcasts all components of the accumulator
  461. ! aC except for aC%data. This is a private routine, only meant
  462. ! to be used by accumulator scatter and gather routines.
  463. !
  464. !
  465. ! !INTERFACE:
  466. !
  467. subroutine bcastp_(aC, root, comm, stat)
  468. !
  469. ! !USES:
  470. !
  471. use m_die
  472. use m_mpif90
  473. use m_AttrVectComms, only : AttrVect_bcast => bcast
  474. use m_Accumulator, only : Accumulator
  475. use m_Accumulator, only : Accumulator_initp => initp
  476. use m_Accumulator, only : Accumulator_nIAttr => nIAttr
  477. use m_Accumulator, only : Accumulator_nRAttr => nRAttr
  478. implicit none
  479. ! !INPUT PARAMETERS:
  480. !
  481. integer,intent(in) :: root
  482. integer,intent(in) :: comm
  483. ! !INPUT/OUTPUT PARAMETERS:
  484. !
  485. type(Accumulator), intent(inout) :: aC ! (IN) on root, (OUT) elsewhere
  486. ! !OUTPUT PARAMETERS:
  487. !
  488. integer, optional, intent(out) :: stat
  489. ! !REVISION HISTORY:
  490. ! 09Aug01 - E.T. Ong <eong@mcs.anl.gov> - initial prototype
  491. !EOP ___________________________________________________________________
  492. character(len=*),parameter :: myname_=myname//'::bcastp_'
  493. integer :: myID
  494. integer :: ier, i
  495. integer :: aC_num_steps, aC_steps_done, aC_nIAttr, aC_nRAttr
  496. integer :: FirstiActionIndex, LastiActionIndex
  497. integer :: FirstrActionIndex, LastrActionIndex
  498. integer :: AccBuffSize
  499. integer :: nIAttr, nRAttr
  500. integer, dimension(:), allocatable :: AccBuff, aC_iAction, aC_rAction
  501. logical :: status
  502. if(present(stat)) stat=0
  503. call MP_comm_rank(comm,myID,ier)
  504. if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
  505. ! STEP 1: Pack broadcast buffer.
  506. ! On the root, load up the Accumulator Buffer: Buffer Size =
  507. ! num_steps {1} + steps_done {1} + nIAttr {1} + nRAttr {1} +
  508. ! iAction {nIAttr} + rAction {nRAttr}
  509. if(myID == root) then
  510. if(associated(aC%iAction)) then
  511. nIAttr = size(aC%iAction)
  512. else
  513. nIAttr = 0
  514. endif
  515. if(associated(aC%rAction)) then
  516. nRAttr = size(aC%rAction)
  517. else
  518. nRAttr = 0
  519. endif
  520. AccBuffSize = 4+nIAttr+nRAttr
  521. endif
  522. ! Use AccBuffSize to initialize AccBuff on all processes
  523. call MPI_BCAST(AccBuffSize, 1, MP_INTEGER, root, comm, ier)
  524. if(ier /= 0) call MP_perr_die(myname_,'AttrVect_bcast(AccBuffSize)',ier)
  525. allocate(AccBuff(AccBuffSize),stat=ier)
  526. if(ier /= 0) call MP_perr_die(myname_,"AccBuff allocate",ier)
  527. if(myID == root) then
  528. ! load up iC%num_steps and iC%steps_done
  529. AccBuff(1) = aC%num_steps
  530. AccBuff(2) = aC%steps_done
  531. ! Load up nIAttr and nRAttr
  532. AccBuff(3) = nIAttr
  533. AccBuff(4) = nRAttr
  534. ! Load up aC%iAction (pointer copy)
  535. do i=1,nIAttr
  536. AccBuff(4+i) = aC%iAction(i)
  537. enddo
  538. ! Load up aC%rAction (pointer copy)
  539. do i=1,nRAttr
  540. AccBuff(4+nIAttr+i) = aC%rAction(i)
  541. enddo
  542. endif
  543. ! STEP 2: Broadcast
  544. ! Broadcast the root value of AccBuff
  545. call MPI_BCAST(AccBuff, AccBuffSize, MP_INTEGER, root, comm, ier)
  546. if(ier /= 0) call MP_perr_die(myname_,'MPI_bcast(AccBuff...',ier)
  547. ! STEP 3: Unpack broadcast buffer.
  548. ! On all processes unload aC_num_steps, aC_steps_done
  549. ! aC_nIAttr, and aC_nRAttr from StepBuff
  550. aC_num_steps = AccBuff(1)
  551. aC_steps_done = AccBuff(2)
  552. aC_nIAttr = AccBuff(3)
  553. aC_nRAttr = AccBuff(4)
  554. ! Unload iC%iAction and iC%rAction
  555. if(aC_nIAttr > 0) then
  556. allocate(aC_iAction(aC_nIAttr),stat=ier)
  557. if(ier /= 0) call die(myname_,"allocate aC_iAction",ier)
  558. FirstiActionIndex = 5
  559. LastiActionIndex = 4+aC_nIAttr
  560. aC_iAction(1:aC_nIAttr) = AccBuff(FirstiActionIndex:LastiActionIndex)
  561. endif
  562. if(aC_nRAttr > 0) then
  563. allocate(aC_rAction(aC_nRAttr),stat=ier)
  564. if(ier /= 0) call die(myname_,"allocate aC_rAction",ier)
  565. FirstrActionIndex = 5+aC_nIAttr
  566. LastrActionIndex = 4+aC_nIAttr+aC_nRAttr
  567. aC_rAction(1:aC_nRAttr) = AccBuff(FirstrActionIndex:LastrActionIndex)
  568. endif
  569. ! Initialize aC on non-root processes
  570. if( (aC_nIAttr > 0).and.(aC_nRAttr > 0) ) then
  571. if(myID /= root) then
  572. call Accumulator_initp(aC,iAction=aC_iAction,rAction=aC_rAction, &
  573. num_steps=aC_num_steps, &
  574. steps_done=aC_steps_done)
  575. endif
  576. deallocate(aC_iAction,aC_rAction,stat=ier)
  577. if(ier /= 0) call die(myname_,"deallocate aC_iAction...",ier)
  578. else
  579. if (aC_nIAttr > 0) then
  580. if(myID /= root) then
  581. call Accumulator_initp(aC,iAction=aC_iAction, &
  582. num_steps=aC_num_steps, &
  583. steps_done=aC_steps_done)
  584. endif
  585. deallocate(aC_iAction,stat=ier)
  586. if(ier /= 0) call die(myname_,"deallocate aC_iAction...",ier)
  587. endif
  588. if (aC_nRAttr > 0) then
  589. if(myID /= root) then
  590. call Accumulator_initp(aC,rAction=aC_rAction, &
  591. num_steps=aC_num_steps, &
  592. steps_done=aC_steps_done)
  593. endif
  594. deallocate(aC_rAction,stat=ier)
  595. if(ier /= 0) call die(myname_,"deallocate aC_iAction...",ier)
  596. endif
  597. endif
  598. ! Clean up allocated arrays
  599. deallocate(AccBuff,stat=ier)
  600. if(ier /= 0) call die(myname_,"deallocate(AccBuff)",ier)
  601. end subroutine bcastp_
  602. end module m_AccumulatorComms