source: CPL/oasis3-mct/branches/OASIS3-MCT_2.0_branch/lib/mct/mct/m_AccumulatorComms.F90 @ 4775

Last change on this file since 4775 was 4775, checked in by aclsce, 5 years ago
  • Imported oasis3-mct from Cerfacs svn server (not suppotred anymore).

The version has been extracted from https://oasis3mct.cerfacs.fr/svn/branches/OASIS3-MCT_2.0_branch/oasis3-mct@1818

File size: 24.6 KB
Line 
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
29 module m_AccumulatorComms
30!
31! !USES:
32!
33! No external modules are used in the declaration section of this module.
34
35      implicit none
36
37      private   ! except
38
39! !PUBLIC MEMBER FUNCTIONS:
40!
41! List of communications Methods for the Accumulator class
42
43      public :: gather          ! gather all local vectors to the root
44      public :: scatter         ! scatter from the root to all PEs
45      public :: bcast           ! bcast from root to all PEs
46
47! Definition of interfaces for the communication methods for
48! the Accumulator:
49
50    interface gather ; module procedure &
51              GM_gather_, &
52              GSM_gather_ 
53    end interface
54    interface scatter ; module procedure &
55              GM_scatter_, &
56              GSM_scatter_ 
57    end interface
58    interface bcast  ; module procedure bcast_  ; end interface
59
60! !REVISION HISTORY:
61! 31Oct00 - Jay Larson <larson@mcs.anl.gov> - initial prototype--
62!           These routines were separated from the module m_Accumulator
63! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - Specification of
64!           APIs for the routines GSM_gather_() and GSM_scatter_().
65! 10May01 - Jay Larson <larson@mcs.anl.gov> - Changes in the
66!           comms routine to match the MPI model for collective
67!           communications, and general clean-up of prologues.
68!  9Aug01 - E.T. Ong <eong@mcs.anl.gov> - Added private routine
69!           bcastp_. Used new Accumulator routines initp_ and
70!           initialized_ to simplify the routines.
71!  26Aug02 - E.T. Ong <eong@mcs.anl.gov> - thourough code revision;
72!            no added routines
73!EOP ___________________________________________________________________
74
75  character(len=*),parameter :: myname='MCT::m_AccumulatorComms'
76
77 contains
78
79!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
80!    Math and Computer Science Division, Argonne National Laboratory   !
81!BOP -------------------------------------------------------------------
82!
83! !IROUTINE: GM_gather_ - Gather Accumulator Distributed by a GlobalMap
84!
85! !DESCRIPTION:  {\tt GM\_gather()} takes a distributed (across the
86! communicator associated with the handle {\tt comm}) input
87! {\tt Accumulator} argument {\tt iC} and gathers its data to the
88! {\tt Accumulator} {\tt oC} on the {\tt root}.  The decomposition of
89! {\tt iC} is described by the input {\tt GlobalMap} argument {\tt Gmap}.
90! The success (failure) of this operation is signified by the zero (nonzero)
91! value of the optional output argument {\tt stat}.
92!
93! !INTERFACE:
94
95 subroutine GM_gather_(iC, oC, GMap, root, comm, stat)
96!
97! !USES:
98!
99      use m_stdio
100      use m_die
101      use m_mpif90
102
103      use m_GlobalMap, only : GlobalMap
104      use m_AttrVect, only : AttrVect_clean => clean
105      use m_Accumulator, only : Accumulator
106      use m_Accumulator, only : Accumulator_initialized => initialized
107      use m_Accumulator, only : Accumulator_initv => init
108      use m_AttrVectComms, only : AttrVect_gather => gather
109
110      implicit none
111
112! !INPUT PARAMETERS:
113!
114      type(Accumulator), intent(in)  :: iC
115      type(GlobalMap) ,  intent(in)  :: GMap
116      integer,           intent(in)  :: root
117      integer,           intent(in)  :: comm
118
119! !OUTPUT PARAMETERS:
120!
121      type(Accumulator), intent(out) :: oC
122      integer, optional,intent(out)  :: stat
123
124! !REVISION HISTORY:
125! 13Sep00 - Jay Larson <larson@mcs.anl.gov> - initial prototype
126! 31Oct00 - Jay Larson <larson@mcs.anl.gov> - relocated to the
127!           module m_AccumulatorComms
128! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - renamed GM_gather_
129! 10May01 - Jay Larson <larson@mcs.anl.gov> - revamped comms
130!           model to match MPI comms model, and cleaned up prologue
131!  9Aug01 - E.T. Ong <eong@mcs.anl.gov> - 2nd prototype. Used the
132!           intiialized_ and accumulator init routines.
133!EOP ___________________________________________________________________
134
135 character(len=*),parameter :: myname_=myname//'::GM_gather_'
136 integer :: myID, ier, i
137 logical :: status
138
139        ! Initialize status flag (if present)
140
141  if(present(stat)) stat=0
142
143  call MP_comm_rank(comm, myID, ier)
144  if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
145
146        ! Argument check of iC: kill if iC is not initialized
147        ! on all processes
148
149  status = Accumulator_initialized(iC,die_flag=.true.,source_name=myname_)
150
151        ! NOTE: removed argument check for oC on the root.
152        ! Is there any good way to check if an accumulator is NOT initialized?
153
154        ! Initialize oC from iC. Clean oC%data - we don't want this av.
155
156  if(myID == root) then
157     
158     call Accumulator_initv(oC,iC,lsize=1, &
159                            num_steps=iC%num_steps,steps_done=iC%steps_done)
160     call AttrVect_clean(oC%data)
161
162  endif
163
164       ! Initialize oC%data. Gather distributed iC%data to oC%data on the root
165
166  call AttrVect_gather(iC%data, oC%data, GMap, root, comm, ier)
167
168  if(ier /= 0) then
169    call perr(myname_,'AttrVect_gather(iC%data, oC%data...',ier)
170    if(.not.present(stat)) call die(myname_)
171    stat=ier
172    return
173  endif
174
175        ! Check oC to see if its valid
176 
177  if(myID == root) then
178     status = Accumulator_initialized(oC,die_flag=.true.,source_name=myname_)
179  endif
180
181 end subroutine GM_gather_
182
183!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184!    Math and Computer Science Division, Argonne National Laboratory   !
185!BOP -------------------------------------------------------------------
186!
187! !IROUTINE: GSM_gather_ - Gather Accumulator Distributed by a GlobalSegMap
188!
189! !DESCRIPTION:  This routine takes the distrubuted (on the communcator
190! associated with the handle {\tt comm}) input {\tt Accumulator}
191! argument {\tt iC} gathers it to the the {\tt Accumulator} argument
192! {\tt oC} (valid only on the {\tt root}).  The decompositon of {\tt iC}
193! is contained in the input {\tt GlobalSegMap} argument {\tt GSMap}. 
194! The success (failure) of this operation is signified by the zero
195! (nonzero) returned value of the {\tt INTEGER} flag {\tt stat}.
196!
197! !INTERFACE:
198
199 subroutine GSM_gather_(iC, oC, GSMap, root, comm, stat)
200!
201! !USES:
202!
203      use m_stdio
204      use m_die
205      use m_mpif90
206
207      use m_GlobalSegMap, only : GlobalSegMap
208      use m_AttrVect, only : AttrVect_clean => clean
209      use m_Accumulator, only : Accumulator
210      use m_Accumulator, only : Accumulator_initv => init
211      use m_Accumulator,   only : Accumulator_initialized => initialized
212      use m_AttrVectComms, only : AttrVect_gather => gather
213
214      implicit none
215
216! !INPUT PARAMETERS:
217!
218      type(Accumulator),  intent(in) :: iC
219      type(GlobalSegMap), intent(in) :: GSMap
220      integer,            intent(in) :: root
221      integer,            intent(in) :: comm
222
223! !OUTPUT PARAMETERS:
224!
225      type(Accumulator), intent(out) :: oC
226      integer, optional, intent(out) :: stat
227
228! !REVISION HISTORY:
229!       15Jan01 - Jay Larson <larson@mcs.anl.gov> - API specification.
230!       10May01 - Jay Larson <larson@mcs.anl.gov> - Initial code and
231!                 cleaned up prologue.
232!       09Aug01 - E.T. Ong <eong@mcs.anl.gov> - 2nd prototype. Used the
233!                 intiialized_ and accumulator init routines.
234!EOP ___________________________________________________________________
235
236 character(len=*),parameter :: myname_=myname//'::GSM_gather_'
237 integer :: myID, ier, i
238 logical :: status
239
240        ! Initialize status flag (if present)
241
242  if(present(stat)) stat=0
243
244  call MP_comm_rank(comm, myID, ier)
245  if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
246
247        ! Argument check of iC
248
249  status = Accumulator_initialized(iC,die_flag=.true.,source_name=myname_)
250
251        ! NOTE: removed argument check for oC on the root.
252        ! Is there any good way to check if an accumulator is NOT initialized?
253
254        ! Initialize oC from iC. Clean oC%data - we don't want this av.
255
256  if(myID == root) then
257     call Accumulator_initv(oC,iC,lsize=1, &
258                            num_steps=iC%num_steps,steps_done=iC%steps_done)
259     call AttrVect_clean(oC%data)
260  endif
261
262       ! Gather distributed iC%data to oC%data on the root
263
264  call AttrVect_gather(iC%data, oC%data, GSMap, root, comm, ier)
265 
266  if(ier /= 0) then
267    call perr(myname_,'AttrVect_gather(iC%data, oC%data...',ier)
268    if(.not.present(stat)) call die(myname_)
269    stat=ier
270    return
271  endif
272
273        ! Check oC to see if its valid
274
275  if(myID == root) then
276     status = Accumulator_initialized(oC,die_flag=.true.,source_name=myname_)
277  endif
278 
279
280 end subroutine GSM_gather_
281
282!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
283!    Math and Computer Science Division, Argonne National Laboratory   !
284!BOP -------------------------------------------------------------------
285!
286! !IROUTINE: GM_scatter_ - Scatter an Accumulator using a GlobalMap
287!
288! !DESCRIPTION:  This routine takes the input {\tt Accumulator} argument
289! {\tt iC} (valid only on the {\tt root}), and scatters it to the
290! distributed {\tt Accumulator} argument {\tt oC} on the processes
291! associated with the communicator handle {\tt comm}.  The decompositon
292! used to scatter the data is contained in the input {\tt GlobalMap}
293! argument {\tt GMap}.  The success (failure) of this operation is
294! signified by the zero (nonzero) returned value of the {\tt INTEGER}
295! flag {\tt stat}.
296!
297! !INTERFACE:
298
299 subroutine GM_scatter_(iC, oC, GMap, root, comm, stat)
300!
301! !USES:
302!
303      use m_stdio
304      use m_die
305      use m_mpif90
306
307      use m_GlobalMap,   only : GlobalMap
308      use m_Accumulator, only : Accumulator
309      use m_Accumulator, only : Accumulator_initv => init
310      use m_Accumulator, only : Accumulator_initialized => initialized
311      use m_AttrVect, only : AttrVect_clean => clean
312      use m_AttrVectComms, only : AttrVect_scatter => scatter
313
314      implicit none
315
316! !INPUT PARAMETERS:
317!
318      type(Accumulator), intent(in)  :: iC
319      type(GlobalMap),   intent(in)  :: GMap
320      integer,           intent(in)  :: root
321      integer,           intent(in)  :: comm
322
323! !OUTPUT PARAMETERS:
324!
325      type(Accumulator), intent(out) :: oC
326      integer, optional, intent(out) :: stat
327
328! !REVISION HISTORY:
329!       14Sep00 - Jay Larson <larson@mcs.anl.gov> - initial prototype
330!       31Oct00 - Jay Larson <larson@mcs.anl.gov> - moved from the module
331!                 m_Accumulator to m_AccumulatorComms
332!       15Jan01 - Jay Larson <larson@mcs.anl.gov> - renamed GM_scatter_.
333!       10May01 - Jay Larson <larson@mcs.anl.gov> - revamped code to fit
334!                 MPI-like comms model, and cleaned up prologue.
335!       09Aug01 - E.T. Ong <eong@mcs.anl.gov> - 2nd prototype. Used the 
336!                 initialized_, Accumulator init_, and bcastp_ routines.
337!EOP ___________________________________________________________________
338
339  character(len=*),parameter :: myname_=myname//'::GM_scatter_'
340
341  integer :: myID, ier
342  logical :: status
343
344        ! Initialize status flag (if present)
345
346  if(present(stat)) stat=0
347
348  call MP_comm_rank(comm, myID, ier)
349  if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
350
351        ! Argument check of iC
352
353  if(myID==root) then
354     status = Accumulator_initialized(iC,die_flag=.true.,source_name=myname_)
355  endif
356
357        ! NOTE: removed argument check for oC on all processes.
358        ! Is there any good way to check if an accumulator is NOT initialized?
359
360        ! Copy accumulator from iC to oC
361        ! Clean up oC%data on root.
362
363  if(myID == root) then
364     call Accumulator_initv(oC,iC,lsize=1,num_steps=iC%num_steps, &
365                            steps_done=iC%steps_done)
366     call AttrVect_clean(oC%data)
367  endif
368
369        ! Broadcast oC (except for oC%data)
370
371  call bcastp_(oC, root, comm, stat)
372
373        ! Scatter the AttrVect component of iC
374
375  call AttrVect_scatter(iC%data, oC%data, GMap, root, comm, ier)
376
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
384        ! Check oC to see if its valid
385
386  status = Accumulator_initialized(oC,die_flag=.true.,source_name=myname_)
387
388 end subroutine GM_scatter_
389
390!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
391!    Math and Computer Science Division, Argonne National Laboratory   !
392!BOP -------------------------------------------------------------------
393!
394! !IROUTINE: GSM_scatter_ - Scatter an Accumulator using a GlobalSegMap
395!
396! !DESCRIPTION:  This routine takes the input {\tt Accumulator} argument
397! {\tt iC} (valid only on the {\tt root}), and scatters it to the
398! distributed {\tt Accumulator} argument {\tt oC} on the processes
399! associated with the communicator handle {\tt comm}.  The decompositon
400! used to scatter the data is contained in the input {\tt GlobalSegMap}
401! argument {\tt GSMap}.  The success (failure) of this operation is
402! signified by the zero (nonzero) returned value of the {\tt INTEGER}
403! flag {\tt stat}.
404!
405! !INTERFACE:
406
407 subroutine GSM_scatter_(iC, oC, GSMap, root, comm, stat)
408!
409! !USES:
410!
411      use m_stdio
412      use m_die
413      use m_mpif90
414
415      use m_GlobalSegMap, only : GlobalSegMap
416      use m_Accumulator, only : Accumulator
417      use m_Accumulator, only : Accumulator_initv => init
418      use m_Accumulator, only : Accumulator_initialized => initialized
419      use m_AttrVect, only : AttrVect_clean => clean
420      use m_AttrVectComms, only : AttrVect_scatter => scatter
421
422      implicit none
423
424! !INPUT PARAMETERS:
425!
426      type(Accumulator),  intent(in)  :: iC
427      type(GlobalSegMap), intent(in)  :: GSMap
428      integer,            intent(in)  :: root
429      integer,            intent(in)  :: comm
430
431! !OUTPUT PARAMETERS:
432!
433      type(Accumulator),  intent(out) :: oC
434      integer, optional,  intent(out) :: stat
435
436! !REVISION HISTORY:
437!       15Jan01 - Jay Larson <larson@mcs.anl.gov> - API specification.
438!       10May01 - Jay Larson <larson@mcs.anl.gov> - Initial code/prologue
439!       09Aug01 - E.T. Ong <eong@mcs.anl.gov> 2nd prototype. Used the
440!                 initialized and accumulator init routines.
441!EOP ___________________________________________________________________
442
443  character(len=*),parameter :: myname_=myname//'::GSM_scatter_'
444
445  integer :: myID, ier
446  logical :: status
447
448        ! Initialize status flag (if present)
449
450  if(present(stat)) stat=0
451
452  call MP_comm_rank(comm, myID, ier)
453  if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
454
455        ! Argument check of iC
456
457  if(myID == root) then
458     status = Accumulator_initialized(iC,die_flag=.true.,source_name=myname_)
459  endif
460
461        ! NOTE: removed argument check for oC on all processes.
462        ! Is there any good way to check if an accumulator is NOT initialized?
463 
464        ! Copy accumulator from iC to oC
465        ! Clean up oC%data on root.
466
467  if(myID == root) then
468     call Accumulator_initv(oC,iC,lsize=1,num_steps=iC%num_steps, &
469                            steps_done=iC%steps_done)
470     call AttrVect_clean(oC%data)
471  endif
472
473        ! Broadcast oC (except for oC%data)
474
475  call bcastp_(oC, root, comm, stat)
476
477        ! Scatter the AttrVect component of aC
478
479  call AttrVect_scatter(iC%data, oC%data, GSMap, root, comm, ier)
480
481  if(ier /= 0) then
482    call perr(myname_,'AttrVect_scatter(iC%data, oC%data...',ier)
483    if(.not.present(stat)) call die(myname_)
484    stat=ier
485    return
486  endif
487
488        ! Check oC if its valid
489
490  status = Accumulator_initialized(oC,die_flag=.true.,source_name=myname_)
491 
492
493 end subroutine GSM_scatter_
494
495!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
496!    Math and Computer Science Division, Argonne National Laboratory   !
497!BOP -------------------------------------------------------------------
498!
499! !IROUTINE: bcast_ - Broadcast an Accumulator
500!
501! !DESCRIPTION:  This routine takes the input {\tt Accumulator} argument
502! {\tt aC} (on input valid only on the {\tt root}), and broadcasts it
503! to all the processes associated with the communicator handle
504! {\tt comm}.  The success (failure) of this operation is signified by
505! the zero (nonzero) returned value of the {\tt INTEGER} flag {\tt stat}.
506!
507! !INTERFACE:
508!
509 subroutine bcast_(aC, root, comm, stat)
510
511!
512! !USES:
513!
514      use m_die
515      use m_mpif90
516      use m_AttrVectComms, only : AttrVect_bcast => bcast
517
518      use m_Accumulator, only : Accumulator
519      use m_Accumulator, only : Accumulator_initialized => initialized
520
521      implicit none
522
523! !INPUT PARAMETERS:
524!
525      integer,intent(in) :: root
526      integer,intent(in) :: comm
527
528! !INPUT/OUTPUT PARAMETERS:
529!
530      type(Accumulator), intent(inout) :: aC ! (IN) on root, (OUT) elsewhere
531
532! !OUTPUT PARAMETERS:
533!
534      integer, optional, intent(out)   :: stat
535
536! !REVISION HISTORY:
537!       14Sep00 - Jay Larson <larson@mcs.anl.gov> - initial prototype
538!       31Oct00 - Jay Larson <larson@mcs.anl.gov> - moved from the module
539!                 m_Accumulator to m_AccumulatorComms
540!       09May01 - Jay Larson <larson@mcs.anl.gov> - cleaned up prologue
541!       09Aug01 - E.T. Ong <eong@mcs.anl.gov> - 2nd prototype. Made use of
542!                 bcastp_ routine. Also more argument checks.
543!EOP ___________________________________________________________________
544
545  character(len=*),parameter :: myname_=myname//'::bcast_'
546
547  integer :: myID
548  integer :: ier
549  logical :: status
550
551  if(present(stat)) stat=0
552
553  call MP_comm_rank(comm,myID,ier)
554  if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
555
556        ! Argument check : Kill if the root aC is not initialized,
557        ! or if the non-root aC is initialized
558
559  if(myID == root) then
560     status = Accumulator_initialized(aC,die_flag=.true.,source_name=myname_)
561  endif
562 
563        ! NOTE: removed argument check for aC on all non-root processes.
564        ! Is there any good way to check if an accumulator is NOT initialized?
565 
566  call bcastp_(aC, root, comm, stat)
567
568
569        ! Broadcast the root value of aC%data
570
571  call AttrVect_bcast(aC%data, root, comm, ier)
572
573  if(ier /= 0) then
574    call perr(myname_,'AttrVect_bcast(aC%data)',ier)
575    if(.not.present(stat)) call die(myname_)
576    stat=ier
577    return
578  endif
579
580        ! Check that aC on all processes are initialized
581
582  status = Accumulator_initialized(aC,die_flag=.true.,source_name=myname_)
583
584
585 end subroutine bcast_
586 
587
588!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
589!    Math and Computer Science Division, Argonne National Laboratory   !
590!BOP -------------------------------------------------------------------
591!
592! !IROUTINE: bcastp_ - Broadcast an Accumulator (but Not its Registers)
593!
594! !DESCRIPTION:  This routine broadcasts all components of the accumulator
595!                aC except for aC%data. This is a private routine, only meant
596!                to be used by accumulator scatter and gather routines.
597!                 
598!
599! !INTERFACE:
600!
601 subroutine bcastp_(aC, root, comm, stat)
602
603!
604! !USES:
605!
606      use m_die
607      use m_mpif90
608      use m_AttrVectComms, only : AttrVect_bcast => bcast
609      use m_Accumulator, only : Accumulator
610      use m_Accumulator, only : Accumulator_initp => initp
611      use m_Accumulator, only : Accumulator_nIAttr => nIAttr
612      use m_Accumulator, only : Accumulator_nRAttr => nRAttr
613
614      implicit none
615
616! !INPUT PARAMETERS:
617!
618      integer,intent(in) :: root
619      integer,intent(in) :: comm
620
621! !INPUT/OUTPUT PARAMETERS:
622!
623      type(Accumulator), intent(inout) :: aC ! (IN) on root, (OUT) elsewhere
624
625! !OUTPUT PARAMETERS:
626!
627      integer, optional, intent(out)   :: stat
628
629! !REVISION HISTORY:
630!       09Aug01 - E.T. Ong <eong@mcs.anl.gov> - initial prototype
631!EOP ___________________________________________________________________
632
633  character(len=*),parameter :: myname_=myname//'::bcastp_'
634
635  integer :: myID
636  integer :: ier, i
637  integer :: aC_num_steps, aC_steps_done, aC_nIAttr, aC_nRAttr
638  integer :: FirstiActionIndex, LastiActionIndex
639  integer :: FirstrActionIndex, LastrActionIndex 
640  integer :: AccBuffSize
641  integer :: nIAttr, nRAttr
642  integer, dimension(:), allocatable :: AccBuff, aC_iAction, aC_rAction
643  logical :: status
644
645  if(present(stat)) stat=0
646
647  call MP_comm_rank(comm,myID,ier)
648  if(ier /= 0) call MP_perr_die(myname_,'MP_comm_rank()',ier)
649
650        ! STEP 1: Pack broadcast buffer.
651
652        ! On the root, load up the Accumulator Buffer: Buffer Size =
653        ! num_steps {1} + steps_done {1} + nIAttr {1} + nRAttr {1} +
654        ! iAction {nIAttr} + rAction {nRAttr}
655
656
657  if(myID == root) then
658
659     if(associated(aC%iAction)) then
660        nIAttr = size(aC%iAction)
661     else
662        nIAttr = 0
663     endif
664
665     if(associated(aC%rAction)) then
666        nRAttr = size(aC%rAction)
667     else
668        nRAttr = 0
669     endif
670
671     AccBuffSize = 4+nIAttr+nRAttr
672
673  endif
674
675        ! Use AccBuffSize to initialize AccBuff on all processes
676
677  call MPI_BCAST(AccBuffSize, 1, MP_INTEGER, root, comm, ier)
678
679  if(ier /= 0) call MP_perr_die(myname_,'AttrVect_bcast(AccBuffSize)',ier)
680
681  allocate(AccBuff(AccBuffSize),stat=ier)
682  if(ier /= 0) call MP_perr_die(myname_,"AccBuff allocate",ier)
683
684  if(myID == root) then
685
686        ! load up iC%num_steps and iC%steps_done
687 
688     AccBuff(1) = aC%num_steps
689     AccBuff(2) = aC%steps_done
690
691        ! Load up nIAttr and nRAttr
692
693     AccBuff(3) = nIAttr
694     AccBuff(4) = nRAttr
695
696        ! Load up aC%iAction (pointer copy)
697
698     do i=1,nIAttr
699        AccBuff(4+i) = aC%iAction(i)
700     enddo
701
702        ! Load up aC%rAction (pointer copy)
703
704     do i=1,nRAttr
705        AccBuff(4+nIAttr+i) = aC%rAction(i)
706     enddo
707  endif
708 
709        ! STEP 2: Broadcast
710
711        ! Broadcast the root value of AccBuff
712
713  call MPI_BCAST(AccBuff, AccBuffSize, MP_INTEGER, root, comm, ier)
714
715  if(ier /= 0) call MP_perr_die(myname_,'MPI_bcast(AccBuff...',ier)
716
717
718        ! STEP 3: Unpack broadcast buffer.
719
720        ! On all processes  unload aC_num_steps, aC_steps_done
721        ! aC_nIAttr, and aC_nRAttr from StepBuff
722
723  aC_num_steps  = AccBuff(1)
724  aC_steps_done = AccBuff(2)
725  aC_nIAttr = AccBuff(3)
726  aC_nRAttr = AccBuff(4)
727 
728        ! Unload iC%iAction and iC%rAction
729
730  if(aC_nIAttr > 0) then
731     allocate(aC_iAction(aC_nIAttr),stat=ier)
732     if(ier /= 0) call die(myname_,"allocate aC_iAction",ier)
733     
734     FirstiActionIndex = 5
735     LastiActionIndex = 4+aC_nIAttr       
736     aC_iAction(1:aC_nIAttr) = AccBuff(FirstiActionIndex:LastiActionIndex)
737
738  endif
739
740  if(aC_nRAttr > 0) then
741     allocate(aC_rAction(aC_nRAttr),stat=ier)
742     if(ier /= 0) call die(myname_,"allocate aC_rAction",ier)
743
744     FirstrActionIndex = 5+aC_nIAttr
745     LastrActionIndex = 4+aC_nIAttr+aC_nRAttr
746     aC_rAction(1:aC_nRAttr) = AccBuff(FirstrActionIndex:LastrActionIndex)
747
748  endif
749
750        ! Initialize aC on non-root processes
751
752  if( (aC_nIAttr > 0).and.(aC_nRAttr > 0) ) then
753
754     if(myID /= root) then
755        call Accumulator_initp(aC,iAction=aC_iAction,rAction=aC_rAction, &
756                               num_steps=aC_num_steps, &
757                               steps_done=aC_steps_done)
758     endif
759
760     deallocate(aC_iAction,aC_rAction,stat=ier)
761     if(ier /= 0) call die(myname_,"deallocate aC_iAction...",ier)
762
763  else
764
765     if (aC_nIAttr > 0) then
766        if(myID /= root) then
767           call Accumulator_initp(aC,iAction=aC_iAction, &
768                                  num_steps=aC_num_steps, &
769                                  steps_done=aC_steps_done)
770        endif
771        deallocate(aC_iAction,stat=ier)
772        if(ier /= 0) call die(myname_,"deallocate aC_iAction...",ier)
773     endif
774
775     if (aC_nRAttr > 0) then
776        if(myID /= root) then
777           call Accumulator_initp(aC,rAction=aC_rAction, &
778                                  num_steps=aC_num_steps, &
779                                  steps_done=aC_steps_done)
780        endif
781        deallocate(aC_rAction,stat=ier)
782        if(ier /= 0) call die(myname_,"deallocate aC_iAction...",ier)
783     endif
784
785  endif
786
787  ! Clean up allocated arrays
788
789  deallocate(AccBuff,stat=ier)
790  if(ier /= 0) call die(myname_,"deallocate(AccBuff)",ier)
791
792
793 end subroutine bcastp_
794 
795
796 end module m_AccumulatorComms
797
798
799
800
801
802
803
Note: See TracBrowser for help on using the repository browser.