source: CONFIG_DEVT/IPSLCM6.5_work_ENSEMBLES/oasis3-mct/BLD/build/lib/mctdir/mct/m_Router.F90 @ 5725

Last change on this file since 5725 was 5725, checked in by aclsce, 3 years ago

Added new oasis3-MCT version to be used to handle ensembles simulations with XIOS.

File size: 28.0 KB
Line 
1!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2!    Math and Computer Science Division, Argonne National Laboratory   !
3!-----------------------------------------------------------------------
4! CVS $Id$
5! CVS $Name$
6!BOP -------------------------------------------------------------------
7!
8! !MODULE: m_Router -- Router class
9!
10! !DESCRIPTION:
11! The Router data type contains all the information needed
12! to send an AttrVect between a component on M MPI-processes and a component
13! on N MPI-processes.   This module defines the Router datatype and provides
14! methods to create and destroy one.
15!
16! !INTERFACE:
17
18 module m_Router
19
20      use m_realkinds, only : FP
21      use m_zeit
22
23      implicit none
24
25      private   ! except
26
27! !declare a private pointer structure for the real data
28      type :: rptr
29#ifdef SEQUENCE
30        sequence
31#endif
32        real(FP),dimension(:),pointer :: pr
33      end type
34
35! !declare a private pointer structure for the integer data
36      type :: iptr
37#ifdef SEQUENCE
38        sequence
39#endif
40        integer,dimension(:),pointer :: pi
41      end type
42
43! !PUBLIC TYPES:
44      public :: Router          ! The class data structure
45
46      public :: rptr,iptr       ! pointer types used in Router
47!\end{verbatim}
48!% On return, pe_list is the processor ranks of the other
49!% component to receive from/send to.  num_segs is the
50!% number of segments out of my local AttrVect which must
51!% be sent/received.  (In general, these wont coincide exactly
52!% with the segments used to define the GlobalMap)
53!% seg_start is the start *in the local AttrVect* of each segment
54!%  (start goes from 1 to lsize(GSMap))
55!% and seg_lengths is the length.
56!\begin{verbatim}
57
58    type Router
59#ifdef SEQUENCE
60      sequence
61#endif
62      integer :: comp1id                           ! myid
63      integer :: comp2id                           ! id of second component
64      integer :: nprocs                            ! number of procs to talk to
65      integer :: maxsize                           ! maximum amount of data going to a processor
66      integer :: lAvsize                           ! The local size of AttrVect which can be
67                                                   ! used with this Router in MCT_Send/MCT_Recv
68      integer :: numiatt                           ! Number of integer attributes currently in use
69      integer :: numratt                           ! Number of real attributes currently in use
70      integer,dimension(:),pointer   :: pe_list    ! processor ranks of send/receive in MCT_comm
71      integer,dimension(:),pointer   :: pe_list_loc! processor ranks of send/receive in local comm
72      integer                        :: mpicomm    ! local MPI communicator
73      integer,dimension(:),pointer   :: num_segs   ! number of segments to send/receive
74      integer,dimension(:),pointer   :: locsize    ! total of seg_lengths for a proc
75      integer,dimension(:),pointer   :: permarr    ! possible permutation array
76      integer,dimension(:,:),pointer :: seg_starts ! starting index
77      integer,dimension(:,:),pointer :: seg_lengths! total length
78      type(rptr),dimension(:),pointer :: rp1       ! buffer to hold real data
79      type(iptr),dimension(:),pointer :: ip1       ! buffer to hold integer data
80      integer,dimension(:),pointer   :: ireqs,rreqs  ! buffer for MPI_Requests
81      integer,dimension(:,:),pointer :: istatus,rstatus  ! buffer for MPI_Status
82    end type Router
83
84! !PUBLIC MEMBER FUNCTIONS:
85      public :: init            ! Create a Router
86      public :: clean           ! Destroy a Router
87      public :: print           ! Print info about a Router
88
89
90    interface init  ; module procedure  &
91        initd_, &       ! initialize a Router between two seperate components
92        initp_          ! initialize a Router locally with two GSMaps
93    end interface
94    interface clean ; module procedure clean_ ; end interface
95    interface print ; module procedure print_ ; end interface
96
97! !REVISION HISTORY:
98! 15Jan01 - R. Jacob <jacob@mcs.anl.gov> - initial prototype
99! 08Feb01 - R. Jacob <jacob@mcs.anl.gov> add locsize and maxsize
100!           to Router type
101! 25Sep02 - R. Jacob <jacob@mcs.anl.gov> Remove type string.  Add lAvsize
102! 23Jul03 - R. Jacob <jacob@mcs.anl.gov> Add status and reqs arrays used
103!           in send/recv to the Router datatype.
104! 24Jul03 - R. Jacob <jacob@mcs.anl.gov> Add real and integer buffers
105!           for send/recv to the Router datatype.
106! 22Jan08 - R. Jacob <jacob@mcs.anl.gov> Add ability to handle an unordered
107!           GSMap by creating a new, ordered one and building Router from
108!           that.  Save permutation info in Router datatype.
109!EOP ___________________________________________________________________
110
111  character(len=*),parameter :: myname='MCT::m_Router'
112
113 contains
114
115!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116!    Math and Computer Science Division, Argonne National Laboratory   !
117!BOP -------------------------------------------------------------------
118!
119! !IROUTINE: initd_ - initialize a Router between two seperate components
120!
121! !DESCRIPTION:
122! The routine {\tt initd\_()} exchanges the {\tt GSMap} with the
123! component identified by {\tt othercomp} and then calls {\tt initp\_()}
124! to build a Router {\tt Rout} between them.
125!
126! {\bf N.B.} The  {\tt GSMap} argument must be declared so that the index values
127! on a processor are in ascending order.
128!
129! !INTERFACE:
130
131 subroutine initd_(othercomp,GSMap,mycomm,Rout,name )
132!
133! !USES:
134!
135      use m_GlobalSegMap, only :GlobalSegMap
136      use m_ExchangeMaps,only: MCT_ExGSMap => ExchangeMap
137      use m_mpif90
138      use m_die
139
140      implicit none
141
142! !INPUT PARAMETERS:
143!
144      integer, intent(in)              :: othercomp
145      integer, intent(in)              :: mycomm
146      type(GlobalSegMap),intent(in)    :: GSMap     ! of the calling comp
147      character(len=*), intent(in),optional     :: name
148
149! !OUTPUT PARAMETERS:
150!
151      type(Router), intent(out)        :: Rout
152
153! !REVISION HISTORY:
154! 15Jan01 - R. Jacob <jacob@mcs.anl.gov> - initial prototype
155! 06Feb01 - R. Jacob <jacob@mcs.anl.gov> - Finish initialization
156!           of the Router.  Router now works both ways.
157! 25Apr01 - R. Jacob <jacob@mcs.anl.gov> - Eliminate early
158!           custom code to exchange GSMap components and instead
159!           the more general purpose routine in m_ExchangeMaps.
160!           Use new subroutine OrderedPoints in m_GlobalSegMap
161!           to construct the vector of local and remote GSMaps.
162!           Clean-up code a little.
163! 03May01 - R. Jacob <jacob@mcs.anl.gov> - rename to initd and
164!           move most of code to new initp routine
165!
166!EOP ___________________________________________________________________
167!
168  character(len=*),parameter :: myname_=myname//'::initd_'
169  character(len=40) :: tagname
170
171  type(GlobalSegMap)    :: RGSMap  !  the other GSMap
172  integer ::               ier
173
174!--------------------------begin code-----------------------
175
176!!!!!!!!!!!!!!!!!Exchange of global map data
177
178  if(present(name)) then
179    tagname='01'//name//'ExGSMap'
180
181    call zeit_ci(trim(tagname))
182    call MCT_ExGSMap(GSMap,mycomm,RGSMap,othercomp,ier)
183    if(ier /= 0) call die(myname_,'ExGSMap',ier)
184    call zeit_co(trim(tagname))
185
186!!!!!!!!!!!!!!!!!Begin comparison of globalsegmaps
187
188    call initp_(GSMap,RGSMap, mycomm, Rout,name)
189  else
190    call MCT_ExGSMap(GSMap,mycomm,RGSMap,othercomp,ier)
191    call initp_(GSMap,RGSMap, mycomm, Rout)
192  endif
193
194 end subroutine initd_
195
196!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197!    Math and Computer Science Division, Argonne National Laboratory   !
198!BOP -------------------------------------------------------------------
199!
200! !IROUTINE: initp_ - initialize a Router from two GlobalSegMaps
201!
202! !DESCRIPTION:
203!
204! Given two GlobalSegmentMaps {\tt GSMap} and {\tt RGSMap}, intialize a
205! Router {\tt Rout} between them.  Use local communicator {\tt mycomm}.
206!
207! {\bf N.B.} The two {\tt GSMap} arguments must be declared so that the index values
208! on a processor are in ascending order.
209!
210! !INTERFACE:
211
212 subroutine initp_(inGSMap,inRGSMap,mycomm,Rout,name )
213!
214! !USES:
215!
216      use m_GlobalSegMap,  only :GlobalSegMap
217      use m_GlobalSegMap,  only :ProcessStorage
218      use m_GlobalSegMap,  only :GSMap_comp_id => comp_id
219      use m_GlobalSegMap,  only :GSMap_increasing => increasing
220      use m_GlobalSegMap,  only :GlobalSegMap_copy => copy
221      use m_GlobalSegMap,  only :GlobalSegMap_init => init
222      use m_GlobalSegMap,  only :GlobalSegMap_clean => clean
223      use m_GlobalSegMap,  only :GlobalSegMap_OPoints => OrderedPoints
224      use m_GlobalSegMap,  only :GlobalSegMap_ngseg => ngseg  ! rml
225      use m_GlobalSegMap,  only :GlobalSegMap_nlseg => nlseg  ! rml
226      use m_GlobalSegMap,  only :GlobalSegMap_max_nlseg => max_nlseg  ! rml
227
228      use m_GlobalToLocal, only :GlobalToLocalIndex
229      use m_MCTWorld,      only :MCTWorld
230      use m_MCTWorld,      only :ThisMCTWorld
231
232      use m_Permuter      ,only:Permute
233      use m_MergeSorts    ,only:IndexSet
234      use m_MergeSorts    ,only:IndexSort
235
236      use m_mpif90
237      use m_die
238
239!      use m_zeit
240
241
242      use m_stdio    ! rml
243!      use shr_timer_mod        ! rml timers
244
245      implicit none
246
247! !INPUT PARAMETERS:
248!
249      type(GlobalSegMap), intent(in)    :: inGSMap
250      type(GlobalSegMap), intent(in)    :: inRGSMap
251      integer        ,    intent(in)    :: mycomm
252      character(len=*), intent(in),optional     :: name
253
254! !OUTPUT PARAMETERS:
255!
256      type(Router),      intent(out)    :: Rout
257
258! !REVISION HISTORY:
259! 03May01 - R.L. Jacob <jacob@mcs.anl.gov> - Initial code brought
260!           in from old init routine.
261! 31Jul01 - Jace A Mogill <mogill@cray.com>
262!           Rewrote to reduce number of loops and temp storage
263! 26Apr06 - R. Loy <rloy@mcs.anl.gov> - recode the search through
264!           the remote GSMap to improve efficiency
265! 05Jan07 - R. Loy <rloy@mcs.anl.gov> - improved bound on size of
266!           tmpsegcount and tmpsegstart
267! 15May07 - R. Loy <rloy@mcs.anl.gov> - improved bound on size of
268!           rgs_lb and rgs_ub
269! 25Jan08 - R. Jacob <jacob@mcs.anl.gov> - Dont die if GSMap is not
270!           increasing.  Instead, permute it to increasing and proceed.
271! 07Sep12 - T. Craig <tcraig@ucar.edu> - Replace a double loop with a single
272!           to improve speed for large proc and segment counts.
273! 12Nov16 - P. Worley <worleyph@gmail.com> - eliminate iterations in nested
274!           loop that can be determined to be unnecessary
275!EOP -------------------------------------------------------------------
276
277  character(len=*),parameter :: myname_=myname//'::initp_'
278  integer                            :: ier,i,j,k,m,n
279  integer                            :: mysize,myPid,othercomp
280  integer                            :: mctgrp,mygrp
281  integer                            :: lmaxsize,totallength
282  integer                            :: maxsegcount,count
283  logical, dimension(:), allocatable :: tmppe_list
284  integer, dimension(:,:), pointer   :: tmpsegcount,tmpsegstart
285
286
287  integer :: my_left        ! Left point in local segment (global memory)
288  integer :: my_right       ! Right point in local segment (global memory)
289  integer :: my_leftmost    ! Leftmost point in local segments (global memory)
290  integer :: my_rightmost   ! Rightmost point in local segments (global memory)
291  integer :: r_left         ! Left point in remote segment (global memory)
292  integer :: r_right        ! Right point in remote segment (global memory)
293  integer :: r_leftmost     ! Leftmost point and rightmost point
294  integer :: r_rightmost    !  in remote segments in given process (global memory)
295  integer :: nsegs_overlap  ! Number of segments that overlap between two procs
296
297
298  integer :: ngseg, nlseg
299  integer :: myseg, rseg
300  integer :: rseg_leftbase, rseg_start
301  integer :: prev_right     ! Rightmost local point in previous overlapped segment
302  integer :: local_left, local_right
303  integer,allocatable  :: mygs_lb(:),mygs_ub(:),mygs_len(:),mygs_lstart(:)
304  integer :: r_ngseg
305  integer,allocatable  :: rgs_count(:),rgs_lb(:,:),rgs_ub(:,:)
306  integer,allocatable  :: nsegs_overlap_arr(:)
307
308  integer :: overlap_left, overlap_right, overlap_diff
309
310  integer :: proc, nprocs
311  integer :: feas_proc, feas_nprocs
312  integer,allocatable  :: feas_procs(:), inv_feas_procs(:)
313
314  integer :: max_rgs_count, max_overlap_segs
315  type(GlobalSegMap)    :: GSMap
316  type(GlobalSegMap)    :: RGSMap
317  integer, dimension(:), pointer   :: gpoints
318  integer, dimension(:), pointer   :: permarr
319  integer, dimension(:), pointer   :: rpermarr
320  integer  :: gmapsize
321  character(len=40) :: tagname
322
323
324  integer,save  :: t_initialized=0   ! rml timers
325  integer,save  :: t_loop            ! rml timers
326  integer,save  :: t_loop2            ! rml timers
327  integer,save  :: t_load            ! rml timers
328
329  call MP_comm_rank(mycomm,myPid,ier)
330  if(ier/=0) call MP_perr_die(myname_,'MP_comm_rank',ier)
331
332  nullify(Rout%permarr)
333
334  if(present(name)) then
335    tagname='02'//name//'incheck'
336    call zeit_ci(trim(tagname))
337  endif
338  if (.not. GSMap_increasing(inGSMap)) then
339    if(myPid == 0) call warn(myname_,'GSMap indices not increasing...Will correct')
340    call GlobalSegMap_OPoints(inGSMap,myPid,gpoints)
341    gmapsize=ProcessStorage(inGSMap,myPid)
342    allocate(permarr(gmapsize), stat=ier)
343    if(ier/=0) call die(myname_,'allocate permarr',ier)
344    call IndexSet(permarr)
345    call IndexSort(permarr,gpoints)
346    call Permute(gpoints,permarr,gmapsize)
347    call GlobalSegMap_init(GSMap,gpoints,mycomm,inGSMap%comp_id,gsize=inGSMap%gsize)
348
349    allocate(Rout%permarr(gmapsize),stat=ier)
350    if(ier/=0) call die(myname_,'allocate Router%permarr',ier)
351    Rout%permarr(:)=permarr(:)
352
353    deallocate(gpoints,permarr, stat=ier)
354    if(ier/=0) call die(myname_,'deallocate gpoints,permarr',ier)
355
356  else
357    call GlobalSegMap_copy(inGSMap,GSMap)
358  endif
359
360  if (.not. GSMap_increasing(inRGSMap)) then
361    if(myPid == 0) call warn(myname_,'RGSMap indices not increasing...Will correct')
362    call GlobalSegMap_OPoints(inRGSMap,myPid,gpoints)
363    gmapsize=ProcessStorage(inRGSMap,myPid)
364    allocate(rpermarr(gmapsize), stat=ier)
365    if(ier/=0) call die(myname_,'allocate rpermarr',ier)
366    call IndexSet(rpermarr)
367    call IndexSort(rpermarr,gpoints)
368    call Permute(gpoints,rpermarr,gmapsize)
369
370    call GlobalSegMap_init(RGSMap,gpoints,mycomm,inRGSMap%comp_id,gsize=inRGSMap%gsize)
371
372    deallocate(gpoints,rpermarr, stat=ier)
373    if(ier/=0) call die(myname_,'deallocate gpoints,rpermarr',ier)
374  else
375    call GlobalSegMap_copy(inRGSMap,RGSMap)
376  endif
377  if(present(name)) then
378    call zeit_co(trim(tagname))
379  endif
380
381
382  mysize = ProcessStorage(GSMap,myPid)
383  othercomp = GSMap_comp_id(RGSMap)
384
385
386!.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
387
388
389
390!!
391!! determine the global segments on this processor
392!! just once, so the info be used repeatedly below
393!! same code was used in m_GlobalToLocal - should make a subroutine...
394!!
395  if(present(name)) then
396    tagname='03'//name//'lloop'
397    call zeit_ci(trim(tagname))
398  endif
399
400  ngseg = GlobalSegMap_ngseg(GSMap)
401  nlseg = GlobalSegMap_nlseg(GSMap, myPid)
402
403  allocate( mygs_lb(nlseg), mygs_ub(nlseg), mygs_len(nlseg), &
404            mygs_lstart(nlseg), stat=ier )
405  if(ier/=0) call die(myname_,'allocate mygs',ier)
406
407  n = 0
408  do i=1,ngseg
409    if (GSMap%pe_loc(i) == myPid ) then
410      n=n+1
411      mygs_lb(n)=GSMap%start(i)
412      mygs_ub(n)=GSMap%start(i) + GSMap%length(i) -1
413      mygs_len(n)=GSMap%length(i)
414    endif
415  enddo
416
417  if (n .ne. nlseg) then
418    write(stderr,*) myname_,"mismatch nlseg",n,nlseg
419    call die(myname)
420  endif
421
422  if (nlseg > 0) mygs_lstart(1)=1
423  do i=2,nlseg
424    mygs_lstart(i)=mygs_lstart(i-1)+mygs_len(i-1)
425  enddo
426  if(present(name)) then
427    call zeit_co(trim(tagname))
428  endif
429
430!!
431!! determine the possibly overlapping segments
432!! in RGSMap that are local to each proc
433!!
434  nprocs=ThisMCTWorld%nprocspid(othercomp)
435  r_ngseg = GlobalSegMap_ngseg(RGSMap)
436
437  if (nlseg > 0) then
438    my_leftmost  = mygs_lb(1)
439    my_rightmost = mygs_ub(nlseg)
440
441!!
442!!  count number of potentially overlapping remote segments
443!!  and which and how many processes hold these
444!!
445    if(present(name)) then
446      tagname='04'//name//'rloop'
447      call zeit_ci(trim(tagname))
448    endif
449
450    !! number of potentially overlapping segments in RGSMap local to proc
451    !! and mapping from processes that hold these to actual process id
452    allocate( rgs_count(nprocs), feas_procs(nprocs), &
453              inv_feas_procs(nprocs), stat=ier )
454    if(ier/=0) call die(myname_,'allocate rgs_count, feas_procs',ier)
455
456    rgs_count = 0
457    do i=1,r_ngseg
458      r_left  = RGSMap%start(i)
459      r_right = RGSMap%start(i) + RGSMap%length(i) - 1
460
461      if (.not. (my_rightmost < r_left   .or.          & ! potential overlap
462                 my_leftmost  > r_right       ) ) then
463        proc = RGSMap%pe_loc(i) + 1
464!        if (proc < 1 .or. proc > nprocs) then
465!          write(stderr,*) myname_,"proc pe_loc error",i,proc
466!          call die(myname_,'pe_loc error',0)
467!        endif
468        rgs_count(proc) = rgs_count(proc) + 1
469      endif
470
471    enddo
472
473    feas_nprocs   = 0
474    feas_procs    = -1
475    inv_feas_procs = -1
476    do proc=1,nprocs
477      if (rgs_count(proc) > 0) then
478        feas_nprocs = feas_nprocs + 1
479        feas_procs(feas_nprocs) = proc
480        inv_feas_procs(proc) = feas_nprocs
481      endif
482    enddo
483
484!!
485!!  build list of potentially overlapping remote segments
486!!
487    !! original size of rgs_lb()/ub() was (r_ngseg,nprocs)
488    !! at the cost of looping to compute it (within GlobalSegMap_max_nlseg),
489    !!   reduced size to (r_max_nlseg,nprocs)
490    !! then further reduced to (max_rgs_count,feas_nprocs)
491
492    max_rgs_count=0
493    do proc=1,nprocs
494      max_rgs_count = max( max_rgs_count, rgs_count(proc) )
495    enddo
496
497    allocate( rgs_lb(max_rgs_count,feas_nprocs), &
498              rgs_ub(max_rgs_count,feas_nprocs), &
499              nsegs_overlap_arr(feas_nprocs), stat=ier )
500    if(ier/=0) call die(myname_,'allocate rgs, nsegs',ier)
501
502    !! (note: redefining rgs_count to be indexed as 1:feas_nprocs
503    !!  instead of as 1:nprocs)
504    rgs_count = 0
505    do i=1,r_ngseg
506      r_left  = RGSMap%start(i)
507      r_right = RGSMap%start(i) + RGSMap%length(i) -1
508
509      if (.not. (my_rightmost < r_left   .or.  &     ! potential overlap
510                 my_leftmost  > r_right)     ) then
511        proc = RGSMap%pe_loc(i) + 1
512        feas_proc = inv_feas_procs(proc)
513        rgs_count(feas_proc) = rgs_count(feas_proc) + 1
514        rgs_lb( rgs_count(feas_proc) , feas_proc ) = RGSMap%start(i)
515        rgs_ub( rgs_count(feas_proc) , feas_proc ) = RGSMap%start(i) + RGSMap%length(i) -1
516      endif
517
518    enddo
519
520    deallocate(inv_feas_procs,stat=ier)
521    if(ier/=0) call die(myname_,'deallocate inv_feas_procs',ier)
522
523    if(present(name)) then
524      call zeit_co(trim(tagname))
525    endif
526
527  else
528
529    max_rgs_count = 0
530    feas_nprocs = 0
531
532  endif
533
534!!!!!!!!!!!!!!!!!!
535
536! allocate space for searching
537!   overlap segments to a given remote proc cannot be more than
538!   the max of the local segments and the remote segments
539
540  if(present(name)) then
541    tagname='06'//name//'loop2'
542    call zeit_ci(trim(tagname))
543  endif
544
545  max_overlap_segs = max(nlseg,max_rgs_count)
546
547  allocate(tmpsegcount(feas_nprocs, max_overlap_segs),&
548           tmpsegstart(feas_nprocs, max_overlap_segs),&
549           tmppe_list(feas_nprocs),stat=ier)
550  if(ier/=0)  &
551    call die( myname_,'allocate tmpsegcount etc. size ', &
552              feas_nprocs, ' by ',max_overlap_segs)
553
554  if (feas_nprocs > 0) then
555    tmpsegcount=0
556    tmpsegstart=0
557  endif
558  count =0
559  maxsegcount=0
560
561!!!!!!!!!!!!!!!!!!
562
563  do feas_proc = 1, feas_nprocs
564    nsegs_overlap = 0
565    tmppe_list(feas_proc) = .FALSE.          ! no overlaps with proc yet
566
567    r_leftmost  = rgs_lb(1,feas_proc)
568    r_rightmost = rgs_ub(rgs_count(feas_proc),feas_proc)
569
570    rseg_leftbase = 0
571    do myseg = 1, nlseg                      ! loop over local segs on 'myPID'
572
573      my_left = mygs_lb(myseg)
574      my_right= mygs_ub(myseg)
575
576      ! determine whether any overlap
577      if (.not. (my_right < r_leftmost   .or.  &
578                 my_left  > r_rightmost)       ) then
579
580        rseg_start = rseg_leftbase + 1       ! rseg loop index to start searching from
581
582        ! loop over candidate overlapping remote segs on 'feas_proc'
583        do rseg = rseg_start, rgs_count(feas_proc)
584
585          r_right = rgs_ub(rseg,feas_proc)
586          if (r_right < my_left ) then       ! to the left
587            rseg_leftbase = rseg             ! remember to start to the right of
588                                             !  this for next myseg
589            cycle                            ! try the next remote segment
590          endif
591
592          r_left  = rgs_lb(rseg,feas_proc)
593          if (r_left  > my_right) exit       ! to the right, so no more segments
594                                             !  need to be examined
595
596          ! otherwise, overlaps
597          if (nsegs_overlap == 0) then       ! first overlap w/this proc
598            count = count + 1
599            tmppe_list(feas_proc) = .TRUE.
600            prev_right = -9999
601          else
602            prev_right = local_right
603          endif
604
605          overlap_left=max(my_left, r_left)
606          overlap_right=min(my_right, r_right)
607          overlap_diff= overlap_right - overlap_left
608
609          local_left  = mygs_lstart(myseg) + (overlap_left - my_left)
610          local_right = local_left + overlap_diff
611
612          ! non-contiguous w/prev one
613          if (local_left /= (prev_right+1) ) then
614            nsegs_overlap = nsegs_overlap + 1
615            tmpsegstart(count, nsegs_overlap) = local_left
616          endif
617
618          tmpsegcount(count, nsegs_overlap) = &
619            tmpsegcount(count, nsegs_overlap) + overlap_diff + 1
620
621        enddo
622
623      endif
624
625    enddo
626
627    nsegs_overlap_arr(feas_proc)=nsegs_overlap
628  enddo
629
630  !! pull this out of the loop to vectorize
631  do feas_proc = 1, feas_nprocs
632    maxsegcount=max(maxsegcount,nsegs_overlap_arr(feas_proc))
633  enddo
634
635  if (maxsegcount > max_overlap_segs) &
636    call die( myname_,'overran max_overlap_segs =', &
637              max_overlap_segs, ' count = ',maxsegcount)
638
639!  write(stderr,*) 'max_overlap_segs =', max_overlap_segs, &
640!                  'maxsegcount =',maxsegcount, &
641!                  'mysize =',mysize
642
643
644  deallocate( mygs_lb, mygs_ub, mygs_len, mygs_lstart, stat=ier)
645  if(ier/=0) call die(myname_,'deallocate mygs,nsegs',ier)
646
647  if (nlseg > 0) then
648    deallocate( rgs_count, rgs_lb, rgs_ub, &
649                nsegs_overlap_arr, stat=ier)
650    if(ier/=0) call die(myname_,'deallocate p_rgs, nsegs',ier)
651  endif
652
653!  call shr_timer_stop(t_loop2)    ! rml timers
654  if(present(name)) then
655    call zeit_co(trim(tagname))
656  endif
657
658
659!.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
660
661
662!!!!!!!!!!!!!!!!!!!!end of search through remote GSMap
663
664! start loading up the Router with data
665
666  if(present(name)) then
667    tagname='07'//name//'load'
668    call zeit_ci(trim(tagname))
669  endif
670
671  Rout%comp1id = GSMap_comp_id(GSMap)
672  Rout%comp2id = othercomp
673  Rout%nprocs = count
674  Rout%numiatt = 0
675  Rout%numratt = 0
676
677  allocate(Rout%pe_list(count),Rout%num_segs(count), &
678    Rout%pe_list_loc(count), &
679    Rout%seg_starts(count,maxsegcount), &
680    Rout%seg_lengths(count,maxsegcount), &
681    Rout%locsize(count),stat=ier)
682  if(ier/=0) call die(myname_,'allocate(Rout..)',ier)
683
684  allocate(Rout%istatus(MP_STATUS_SIZE,count), &
685             Rout%rstatus(MP_STATUS_SIZE,count), &
686             Rout%rreqs(count),Rout%ireqs(count),stat=ier)
687  if(ier/=0) call die(myname_,'allocate(status,reqs,...)',ier)
688
689! allocate the number of pointers needed
690  allocate(Rout%ip1(count),stat=ier)
691  if(ier/=0) call die(myname_,'allocate(ip1)',ier)
692
693! allocate the number of pointers needed
694  allocate(Rout%rp1(count),stat=ier)
695  if(ier/=0) call die(myname_,'allocate(rp1)',ier)
696
697  m=0
698  do i=1,feas_nprocs
699    if(tmppe_list(i))then
700      m=m+1
701      ! load processor rank in MCT_comm
702      proc = feas_procs(i)
703      Rout%pe_list(m)=ThisMCTWorld%idGprocid(othercomp,proc-1)
704    endif
705  enddo
706
707  ! translate MCT_comm task ids to task ids in local comm
708  call mpi_comm_group(ThisMCTWorld%MCT_comm, mctgrp, ier)
709  if(ier/=0) call die(myname_,'mpi_comm_group(MCT_comm..)',ier)
710  call mpi_comm_group(myComm, mygrp, ier)
711  if(ier/=0) call die(myname_,'mpi_comm_group(my_comm..)',ier)
712  call mpi_group_translate_ranks(mctgrp, Rout%nprocs, &
713         Rout%pe_list, mygrp, Rout%pe_list_loc, ier)
714  if(ier/=0) call die(myname_,'mpi_group_translate_ranks',ier)
715  Rout%mpicomm=myComm
716
717  lmaxsize=0
718  do i=1,count
719    totallength=0
720    do j=1,maxsegcount
721      if(tmpsegcount(i,j) /= 0) then
722        Rout%num_segs(i)=j
723        Rout%seg_starts(i,j)=tmpsegstart(i,j)
724        Rout%seg_lengths(i,j)=tmpsegcount(i,j)
725        totallength=totallength+Rout%seg_lengths(i,j)
726      endif
727    enddo
728    Rout%locsize(i)=totallength
729    lmaxsize=MAX(lmaxsize,totallength)
730  enddo
731
732  Rout%maxsize=lmaxsize
733  Rout%lAvsize=mysize
734
735  if (nlseg > 0) then
736    deallocate(feas_procs,stat=ier)
737    if(ier/=0) call die(myname_,'deallocate feas_procs',ier)
738  endif
739
740  deallocate(tmpsegstart,tmpsegcount,tmppe_list,stat=ier)
741  if(ier/=0) call die(myname_,'deallocate tmp',ier)
742
743  call GlobalSegMap_clean(RGSMap)
744  call GlobalSegMap_clean(GSMap)
745
746  if(present(name)) then
747    call zeit_co(trim(tagname))
748  endif
749
750 end subroutine initp_
751
752!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
753!    Math and Computer Science Division, Argonne National Laboratory   !
754!BOP -------------------------------------------------------------------
755!
756! !IROUTINE: clean_ - Destroy a Router
757!
758! !DESCRIPTION:
759! Deallocate Router internal data structures and set integer parts to zero.
760!
761! !INTERFACE:
762
763    subroutine clean_(Rout,stat)
764!
765! !USES:
766!
767      use m_die
768
769      implicit none
770
771!INPUT/OUTPUT PARAMETERS:
772      type(Router),      intent(inout) :: Rout
773
774!OUTPUT PARAMETERS:
775      integer, optional, intent(out)   :: stat
776
777! !REVISION HISTORY:
778! 15Jan01 - R. Jacob <jacob@mcs.anl.gov> - initial prototype
779! 08Feb01 - R. Jacob <jacob@mcs.anl.gov> - add code to clean
780!           the maxsize and locsize
781! 01Mar02 - E.T. Ong <eong@mcs.anl.gov> removed the die to prevent
782!           crashes and added stat argument.
783!EOP ___________________________________________________________________
784
785  character(len=*),parameter :: myname_=myname//'::clean_'
786  integer :: ier
787
788  deallocate(Rout%pe_list,Rout%num_segs,Rout%seg_starts, &
789             Rout%pe_list_loc, &
790  Rout%locsize,Rout%seg_lengths,stat=ier)
791  if(present(stat)) then
792     stat=ier
793  else
794     if(ier /= 0) call warn(myname_,'deallocate(Rout%pe_list,...)',ier)
795  endif
796
797  deallocate(Rout%rreqs,Rout%ireqs,Rout%rstatus,&
798   Rout%istatus,stat=ier)
799  if(present(stat)) then
800     stat=ier
801  else
802     if(ier /= 0) call warn(myname_,'deallocate(Rout%rreqs,...)',ier)
803  endif
804
805  deallocate(Rout%ip1,Rout%rp1,stat=ier)
806  if(present(stat)) then
807     stat=ier
808  else
809     if(ier /= 0) call warn(myname_,'deallocate(Rout%ip1,...)',ier)
810  endif
811
812  if(associated(Rout%permarr)) then
813     deallocate(Rout%permarr,stat=ier)
814     if(present(stat)) then
815        stat=ier
816     else
817        if(ier /= 0) call warn(myname_,'deallocate(Rout%ip1,...)',ier)
818     endif
819  endif
820
821  Rout%comp1id = 0
822  Rout%comp2id = 0
823  Rout%nprocs = 0
824  Rout%maxsize = 0
825  Rout%lAvsize = 0
826  Rout%numiatt = 0
827  Rout%numratt = 0
828
829
830 end subroutine clean_
831
832
833!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
834!    Math and Computer Science Division, Argonne National Laboratory   !
835!BOP -------------------------------------------------------------------
836!
837! !IROUTINE: print_ - Print router info
838!
839! !DESCRIPTION:
840! Print out communication info about router on unit number 'lun'
841! e.g. (source,destination,length)
842!
843! !INTERFACE:
844
845    subroutine print_(rout,mycomm,lun)
846!
847! !USES:
848!
849      use m_die
850      use m_mpif90
851
852      implicit none
853
854!INPUT/OUTPUT PARAMETERS:
855      type(Router),      intent(in) :: Rout
856      integer, intent(in)           :: mycomm
857      integer, intent(in)           :: lun
858
859! !REVISION HISTORY:
860! 27Jul07 - R. Loy <rloy@mcs.anl.gov>  initial version
861!EOP ___________________________________________________________________
862
863
864    integer iproc
865    integer myrank
866    integer ier
867    character(len=*),parameter :: myname_=myname//'::print_'
868
869    call MP_comm_rank(mycomm,myrank,ier)
870    if(ier/=0) call MP_perr_die(myname_,'MP_comm_rank',ier)
871
872
873    do iproc=1,rout%nprocs
874      if (rout%num_segs(iproc) > 0) then
875        write(lun,*) myrank,rout%pe_list(iproc),rout%locsize(iproc)
876      endif
877    end do
878
879
880  end subroutine print_
881
882
883 end module m_Router
884
Note: See TracBrowser for help on using the repository browser.