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 | |
---|