KTH framework for Nek5000 toolboxes; testing version  0.0.1
pts_redistribute.f
Go to the documentation of this file.
1 !=======================================================================
2 ! Description : Set of rutines to redistribute points between processors
3 ! IMPORTANT!!! This vesion of the code does not take into account
4 ! error code rcode. This shuld be added later.
5 ! IMPORTANT!!! This vesion of the code does not work for number of
6 ! processors bigger than 2*LX1*LY1*LZ1*LELT
7 !=======================================================================
8 ! Adam Peplinski 2021.05.28
9 ! This is a very old version barely touched by me right now due to lack of time.
10 ! For now I just slightly refresh the old stuff and hope for the best.
11 c-----------------------------------------------------------------------
12 ! redistribute points
13 ! I assume findpts aws alleready called and proc array is filled
14 ! IMPORTANT!!! This routine uses scratch arrays in
15 ! scrmg and scrns
16  subroutine pts_rdst(nptimb)
17 
18  implicit none
19 
20  include 'SIZE'
21  include 'INPUT'
22  include 'TSRSD'
23 
24 ! argument list
25  integer nptimb ! allowed point imbalance
26 
27 ! local variables
28  integer il ! loop index
29  integer itmp
30 
31 ! work arrays; I use scratch so be carefull
32  integer libuf, lrbuf, lptn
33  parameter(libuf = 5, lrbuf = 2*ldim, lptn=lx1*ly1*lz1*lelt)
34  integer ibuf(libuf,lptn)
35  real rbuf(lrbuf,lptn)
36  integer mid(lptn)
37  common /scrmg/ ibuf, mid
38  common /scrns/ rbuf
39 
40 ! check size of transfer arrays
41  if(lhis.gt.lptn) then
42  if (nio.eq.0)
43  $ write(6,*) 'Error: pts_rdst; insufficient buffer size'
44  call exitt
45  endif
46 
47 ! adjust point -processor mapping
48 
49 ! IMPORTANT!!!
50 ! Place to use information from rcode(i)
51 
52 ! fill in mid
53  do il=1,tsrs_npts
54  mid(il) = tsrs_proc(il)
55  enddo
56 
57 ! prepare mapping
58  call pts_map_all(mid,lptn,tsrs_npts,tsrs_nptot,nptimb)
59 
60 ! fill in redistribution array
61 ! integer
62  do il=1,tsrs_npts
63  ibuf(1,il) = mid(il)
64  ibuf(2,il) = tsrs_ipts(il)
65  ibuf(3,il) = tsrs_proc(il)
66  ibuf(4,il) = tsrs_elid(il)
67  ibuf(5,il) = tsrs_rcode(il)
68  enddo
69 
70 ! real
71  if (if3d) then
72  do il=1,tsrs_npts
73  itmp = (il-1)*ndim
74  rbuf(1,il) = tsrs_pts(1,il)
75  rbuf(2,il) = tsrs_pts(2,il)
76  rbuf(3,il) = tsrs_pts(3,il)
77  rbuf(4,il) = tsrs_rst(itmp+1)
78  rbuf(5,il) = tsrs_rst(itmp+2)
79  rbuf(6,il) = tsrs_rst(itmp+3)
80  enddo
81  else
82  do il=1,tsrs_npts
83  itmp = (il-1)*ndim
84  rbuf(1,il) = tsrs_pts(1,il)
85  rbuf(2,il) = tsrs_pts(2,il)
86  rbuf(3,il) = tsrs_rst(itmp+1)
87  rbuf(4,il) = tsrs_rst(itmp+2)
88  enddo
89  endif
90 
91 ! redistribute points
92  call pts_transfer(rbuf,lrbuf,ibuf,libuf,lptn,tsrs_npts)
93 
94 ! copy arrays back
95 ! integer
96  do il=1,tsrs_npts
97  tsrs_ipts(il) = ibuf(2,il)
98  tsrs_proc(il) = ibuf(3,il)
99  tsrs_elid(il) = ibuf(4,il)
100  tsrs_rcode(il) = ibuf(5,il)
101  enddo
102 
103 ! real
104  if (if3d) then
105  do il=1,tsrs_npts
106  itmp = (il-1)*ndim
107  tsrs_pts(1,il) = rbuf(1,il)
108  tsrs_pts(2,il) = rbuf(2,il)
109  tsrs_pts(3,il) = rbuf(3,il)
110  tsrs_rst(itmp+1) = rbuf(4,il)
111  tsrs_rst(itmp+2) = rbuf(5,il)
112  tsrs_rst(itmp+3) = rbuf(6,il)
113  enddo
114  else
115  do il=1,tsrs_npts
116  itmp = (il-1)*ndim
117  tsrs_pts(1,il) = rbuf(1,il)
118  tsrs_pts(2,il) = rbuf(2,il)
119  tsrs_rst(itmp+1) = rbuf(3,il)
120  tsrs_rst(itmp+2) = rbuf(4,il)
121  enddo
122  endif
123 
124  return
125  end
126 c-----------------------------------------------------------------------
127 ! redistibute points between processors
128 ! ibuf and rbuf have to be filled in outside this routine
129  subroutine pts_transfer(rbuf,lrbuf,ibuf,libuf,lpts,npts)
130 
131  implicit none
132 
133 ! ! include 'SIZE_DEF' ! missing definitions in include files
134  include 'SIZE'
135 ! ! include 'PARALLEL_DEF'
136  include 'PARALLEL'
137 
138 ! argument list
139  real rbuf(lrbuf,lpts) ! point list
140  integer ibuf(libuf,lpts) ! target proc id; global ordering
141  integer lrbuf, libuf, lpts ! array sizes
142  integer npts ! local number of points
143 
144 ! local variables
145  integer itmp1, itmp2
146 ! required by crystal router
147  integer*8 vl
148 
149 ! timing
150  real ltime1, ltime2, timemaxs, timemins
151 
152 ! functions
153  integer iglmin, iglmax
154  real dnekclock, glmax, glmin
155 
156 ! timing
157  ltime1 = dnekclock()
158 
159 ! send points
160  call fgslib_crystal_tuple_transfer
161  $ (cr_h,npts,lpts,ibuf,libuf,vl,0,rbuf,lrbuf,1)
162 
163 ! statistics after redistribution
164  itmp1 = iglmin(npts,1)
165  itmp2 = iglmax(npts,1)
166 
167 ! timing
168  ltime2 = dnekclock()
169  ltime2 = ltime2 - ltime1
170  timemaxs = glmax(ltime2,1)
171  timemins = glmin(ltime2,1)
172 
173 ! stamp logs
174  if (nio.eq.0) then
175  write(6,*)
176  write(6,*) 'Point redistribution; pts_transfer_min:'
177  write(6,'(A22,I7,I7)') 'New loc pts nr min/max', itmp1, itmp2
178  write(6,'(A22,g13.5,g13.5)') 'Sending time min/max ',
179  $ timemins, timemaxs
180  write(6,*)
181  endif
182 
183  return
184  end
185 c-----------------------------------------------------------------------
186 ! redistibute points between processors
187  subroutine pts_map_all(mid,lpts,npts,npoints,nptimb)
188 
189  implicit none
190 
191 ! ! include 'SIZE_DEF' ! missing definitions in include files
192  include 'SIZE'
193 ! ! include 'PARALLEL_DEF'
194  include 'PARALLEL'
195 
196 ! dummy arrays
197 ! I use nek5000 scratch arrays so be careful
198  integer lptn
199  parameter(lptn=2*lx1*ly1*lz1*lelt)
200  integer npts_plist(lptn) ! list of processors used
201  common /scrvh/ npts_plist
202 
203 ! argument list
204  integer mid(lpts) ! target proc id; global ordering
205  integer lpts ! array size
206  integer npts ! local number of points
207  integer npoints ! global number of points
208  integer nptimb ! allowed point imbalance
209 
210 ! specific common blocks
211  integer nptav, nptmod ! average point number per proc
212  integer nptmax ! max point number per proc
213  common /istat_pts_avm/ nptav, nptmod, nptmax
214 ! global/local counters
215  integer nptgdone, nptgundone ! done/undone points number; global
216  integer nptldone, nptlundone ! done/undone points number; local
217  common /istat_pts_done/ nptgdone, nptgundone, nptldone,
218  $ nptlundone
219 ! to keep track of nodes overflow and free space
220  integer nptover, nptempty, nptshift
221  common /istat_pts_oes/ nptover, nptempty, nptshift
222 
223 ! local variables
224  integer ierr ! error mark
225  integer itmp ! dummy variables
226 
227  integer nptav1 ! local average point number per proc
228  integer nptshift1 ! global number of shifts in all calls
229  integer nloop, nloopmod ! processor loop
230  integer nplist ! number of processors in the list
231  integer ipr, ipt ! loop index
232 
233 ! node status; positive - overflow (points to send)
234 ! negative - empty space
235  integer istatus
236  integer indasg ! number of points asigned to the node
237 
238 ! timing
239  real ltime1, ltime2, timemax, timemin
240 
241 ! functions
242  integer iglsum, iglmin, iglmax
243  real dnekclock, glmax, glmin
244 
245 ! timing
246  ltime1 = dnekclock()
247 
248 ! Generate global point mapping for point redistribution
249 
250 ! Average points per processor; this value has to be
251 ! dependent on nptmod
252 ! This has to be done here as pts_map_set can be called
253 ! number of times
254  nptav = npoints/np
255  nptmod = mod(npoints,np)
256  if (nptmod.gt.0) then
257  nptav1 = nptav + 1
258  else
259  nptav1 = nptav
260  endif
261 ! nptimb must be positive
262  nptimb = abs(nptimb)
263 ! max points per processor
264  nptmax = min(nptav1 + nptimb,lhis)
265 
266  ierr = 0
267  if (nptav1.gt.lhis) ierr = 1
268  ierr=iglsum(ierr,1)
269  if(ierr.gt.0) then
270  if(nio.eq.0) write(6,*)
271  $ 'Error: pts_map_all; wrong nptav'
272  call exitt
273  endif
274 
275 ! There can be more processors than the array size and the
276 ! distribution of points does not gurantee the nodes with
277 ! the highies number of points are located at the beginning
278 ! of the processor list.
279 ! In general additional sorting is necessary.
280 
281 ! Initialise done and undone points number
282 ! This has to be done here as pts_map_set can be called
283 ! number of times.
284 ! global
285  nptgdone = 0
286  nptgundone = npoints
287 ! local
288  nptldone = 0
289  nptlundone = npts
290 
291 ! Is there more processors than the array size
292  nloop = np/lptn + 1
293  nloopmod = mod(np,lptn)
294 
295 ! If processor number is small no sorting is necessary
296  if (nloop.eq.1) then
297  nplist = np
298 
299 ! fill in processor array
300  do ipr=1,nplist
301  npts_plist(ipr) = ipr-1
302  enddo
303 
304 ! mark all processors as undone (negative number of points
305 ! assigned to the node)
306  indasg = -1
307 
308 ! is syncronisatoin necessary?
309  call nekgsync()
310 
311  call pts_map_set(mid,lpts,istatus,indasg,
312  $ npts_plist,lptn,npts,nplist)
313 
314 ! check consistency
315 ! are all points done
316  if (nptgdone.ne.npoints) then
317  if(nio.eq.0) write(6,*)
318  $ 'Error: pts_map_all; not all points redist.'
319  call exitt
320  endif
321 
322 ! is the local number consistent
323  ierr = 0
324  if (nptldone.ne.npts) ierr = 1
325  ierr=iglsum(ierr,1)
326  if(ierr.gt.0) then
327  if(nio.eq.0) write(6,*)
328  $ 'Error: pts_map_all; wrong nptldone'
329  call exitt
330  endif
331 
332 ! is there global overflow
333  if(nptover.ne.0) then
334  if(nio.eq.0) write(6,*)
335  $ 'Error: pts_map_all; global overflow'
336  call exitt
337  endif
338 
339 ! does any node report overflow
340  ierr = 0
341  if (istatus.gt.0) ierr = istatus
342  ierr=iglsum(ierr,1)
343  if(ierr.gt.0) then
344  if(nio.eq.0) write(6,*)
345  $ 'Error: pts_map_all; node overflow'
346  call exitt
347  endif
348 
349 ! get min/max assigned points
350  ipr = iglmin(indasg,1)
351  ipt = iglmax(indasg,1)
352 
353  if(ipr.lt.0) then
354  if(nio.eq.0) write(6,*)
355  $ 'Error: pts_map_all; untuched nodes'
356  call exitt
357  endif
358 
359 ! save number of shifts
360  nptshift1 = nptshift
361 
362  else ! nloop.eq.1
363 ! Big number of processors; sorting necessary
364 
365 ! not done yet
366  if(nio.eq.0) write(6,*)
367  $ 'Error: pts_map_all unsupported option'
368  call exitt
369 
370  endif ! nloop.eq.1
371 
372 ! timing
373  ltime2 = dnekclock()
374  ltime1 = ltime2 - ltime1
375  timemax = glmax(ltime1,1)
376  timemin = glmin(ltime1,1)
377 
378 ! statistics before redistribution
379  ierr = iglmin(npts,1)
380  itmp = iglmax(npts,1)
381 
382 ! stamp logs
383  if (nio.eq.0) then
384  write(6,*)
385  write(6,*) 'Point redistribution; pts_map_all:'
386  write(6,'(A22,I7)') 'Global point nr ', npoints
387  write(6,'(A22,I7)') 'Average point nr ', nptav
388  write(6,'(A22,I7,I7)') 'Old loc pts nr min/max', ierr, itmp
389  write(6,'(A22,I7,I7)') 'Assgn point nr min/max', ipr, ipt
390  write(6,'(A22,I7)') 'Nr of shifted points ', nptshift1
391  write(6,'(A22,g13.5,g13.5)') 'Mapping time min/max ',
392  $ timemin, timemax
393  write(6,*)
394  endif
395 
396  return
397  end
398 c-----------------------------------------------------------------------
399 ! map points to processors on the working processor set
400  subroutine pts_map_set(mid,lpts,istatus,indasg,npts_plist,
401  $ lplist,npts,nplist)
402 
403  implicit none
404 
405 ! ! include 'SIZE_DEF' ! missing definitions in include files
406  include 'SIZE'
407 ! ! include 'PARALLEL_DEF'
408  include 'PARALLEL'
409 
410 ! dummy arrays
411 ! I use nek5000 scratch arrays so be careful
412  integer lptn
413  parameter(lptn=2*lx1*ly1*lz1*lelt)
414  integer npts_node_u(lptn) ! undone point-node distribution
415  integer npts_node_l(lptn) ! local point-node distribution
416  integer npts_node_r(lptn) ! running point-node distribution
417  integer npts_node_g(lptn) ! global point-node distribution
418  integer npts_node_h(lptn) ! hidden point-node distribution
419  common /scrch/ npts_node_u
420  common /screv/ npts_node_l
421  common /ctmp0/ npts_node_r
422  common /ctmp1/ npts_node_g
423  common /scrsf/ npts_node_h
424 
425 ! argument list
426  integer mid(lpts) ! target proc id; global ordering
427  integer lpts ! array size
428  integer istatus ! node status
429  integer indasg ! number of points asigned to the node
430  integer npts_plist(lplist) ! list of processors used
431  integer lplist ! array size
432  integer npts ! local number of points
433  integer nplist ! number of processors in the list
434 
435 ! specific common blocks
436  integer nptav, nptmod ! average point number per proc
437  integer nptmax ! max point number per proc
438  common /istat_pts_avm/ nptav, nptmod, nptmax
439 ! global/local counters
440  integer nptgdone, nptgundone ! done/undone points number; global
441  integer nptldone, nptlundone ! done/undone points number; local
442  common /istat_pts_done/ nptgdone, nptgundone, nptldone,
443  $ nptlundone
444 ! to keep track of nodes overflow and free space
445  integer nptover, nptempty, nptshift
446  common /istat_pts_oes/ nptover, nptempty, nptshift
447 
448 
449 ! local variables
450  integer ierr ! error mark
451  integer itmp, itmp1, itmp2, itmp3, itmp4, itmp5 ! dummy variables
452  integer idummy(2) ! dummy arrays
453 
454  integer nptav1 ! local average point number per proc
455 
456  integer ipr, ipt, ipt2, ipt3 ! loop index
457  integer nodeid, nodeid1 ! poc id
458 
459  integer nptupg, nptupl ! global/local updated points
460 
461 ! functions
462  integer iglsum
463 
464 c$$$! for testing
465 c$$$ integer itl1, itl2
466 c$$$ character*2 str
467 c$$$ character*3 str2
468 c$$$ write(str,'(i2.2)') NID
469 c$$$ str2=str//'p'
470 
471 ! nptav, nptmod, nptmax are set outside this routine, as
472 ! this routine can be executed many times
473 
474 ! Initialise done and undone points number
475 ! Done outside this routine, as this routine can be executed
476 ! many times
477 ! nptgdone, nptgundone, nptldone, nptlundone
478 
479 ! keep track of redistribution; overflows, empty spaces, points
480 ! shifted to other processor
481 ! these variables are specific to given processor set
482  nptover = 0
483  nptempty = 0
484  nptshift = 0
485 
486 ! gather distribution information about all processors in the set
487  call izero(npts_node_l,nplist)
488 ! local loop over points and processors
489  do ipr = 1,nplist
490  do ipt=1,npts
491  if(npts_plist(ipr).eq.mid(ipt))
492  $ npts_node_l(ipr) = npts_node_l(ipr) + 1
493  enddo
494  enddo
495 
496 ! global communication
497  call comm_ivglrsum(npts_node_r,npts_node_l,nplist)
498 
499 ! last node has global sum; broadcast it
500  if (nid.eq.(np-1)) call icopy(npts_node_g,npts_node_r,nplist)
501  call comm_ibcastn(npts_node_g,nplist,np-1)
502 
503 ! remove local numbers from the running sum
504  do ipr = 1, nplist
505  npts_node_r(ipr) = npts_node_r(ipr) - npts_node_l(ipr)
506  enddo
507 
508 ! mark everything as undone
509  call icopy(npts_node_u,npts_node_g,nplist)
510 ! zero hidden array
511  call izero(npts_node_h,nplist)
512 
513 ! extract information
514 ! loop over processors
515  do ipr = 1, nplist
516 
517 ! destination proc id
518  nodeid = npts_plist(ipr)
519 
520 ! destination average number
521  if (nodeid.lt.nptmod) then
522  nptav1 = nptav + 1
523  else
524  nptav1 = nptav
525  endif
526 
527 ! check global number of points
528  if (npts_node_g(ipr).gt.nptmax) then
529 ! too many points; some have to be redistributed
530 
531 ! check how many points are allready placed on the node ipr
532  idummy(1) = 0
533  idummy(2) = 0
534  itmp = 0
535  nptupg = nptmax
536  if (nid.eq.nodeid) then
537  itmp = min(npts_node_l(ipr),nptupg)
538 
539 ! update local variables
540  npts_node_l(ipr) = npts_node_l(ipr) - itmp
541  npts_node_r(ipr) = npts_node_r(ipr) + itmp
542  idummy(1) = itmp
543  idummy(2) = npts_node_r(ipr)
544  endif
545 
546 ! broadcast values and get new number of point to collect
547  call comm_ibcastn(idummy,2,nodeid)
548  itmp = nptupg - idummy(1)
549 
550 ! shift points
551  if (npts_node_r(ipr).ge.idummy(2))
552  $ npts_node_r(ipr) = npts_node_r(ipr) - idummy(1)
553 ! set hidden points
554  npts_node_h(ipr) = npts_node_h(ipr) + idummy(1)
555 
556  nptupl = 0
557  if(itmp.gt.0) then
558 ! check how many local points can be unchanged
559 
560  if(npts_node_l(ipr).gt.0) then
561 ! what point range
562  itmp1 = 1 - npts_node_r(ipr)
563  itmp2 = itmp1 + itmp - 1
564 ! does current node fit into this range
565  itmp1 = max(1,itmp1)
566  itmp2 = min(npts_node_l(ipr),itmp2)
567  if ((itmp1.le.npts_node_l(ipr)).and.
568  $ (itmp2.ge.1)) nptupl = itmp2 - itmp1 + 1
569 
570 ! update local variables
571  npts_node_l(ipr) = npts_node_l(ipr) - nptupl
572  npts_node_r(ipr) = npts_node_r(ipr) + nptupl
573  endif ! npts_node_l(ipr).gt.0
574 
575 ! check consistency
576  ierr = iglsum(nptupl,1)
577  if(ierr.ne.itmp) then
578  if(nio.eq.0) write(6,*)
579  $ 'Error: pts_map_set; wrong nptupl 1'
580  call exitt
581  endif
582 
583  endif ! itmp.gt.0
584 
585 ! add hidden points to the local done
586  if (nid.eq.nodeid) nptupl = nptupl + npts_node_h(ipr)
587 
588 ! initial update done/undone point number; related to this processor
589 ! global
590  nptgdone = nptgdone + nptupg
591  nptgundone = nptgundone - nptupg
592 ! local
593  nptldone = nptldone + nptupl
594  nptlundone = nptlundone - nptupl
595 
596 ! mark processor
597 ! sending - positive, receiving -negative, zeor - done
598  itmp = npts_node_g(ipr) - nptupg
599  npts_node_u(ipr) = itmp
600 ! count overflow/empty/shift
601  nptover = nptover + itmp
602 
603 ! check if threre are some empty places to redistribute points
604 ! count the points
605  nptupg = 0 ! global
606  nptupl = 0 ! local
607  if (nptempty.gt.0) then
608 
609 ! loop over all nodes with smaller id
610  do ipt2=1,ipr-1
611  if(npts_node_u(ipt2).lt.0) then
612 ! how many points
613  itmp2 = - npts_node_u(ipt2)
614  itmp1 = min(itmp2,itmp)
615 
616 ! update mid; local operation
617  if(npts_node_l(ipr).gt.0) then
618 ! what point range
619  itmp2 = npts_node_g(ipr) -
620  $ npts_node_u(ipr) - npts_node_h(ipr) -
621  $ npts_node_r(ipr) + 1
622  itmp3 = itmp2 + itmp1 - 1
623 
624 ! does current node fit into this range
625  itmp2 = max(1,itmp2)
626  itmp3 = min(npts_node_l(ipr),itmp3)
627 
628  if ((itmp2.le.npts_node_l(ipr)).and.
629  $ (itmp3.ge.1)) then
630 ! node id; to send
631  nodeid1 = npts_plist(ipt2)
632 ! count local points
633  itmp4 = 0
634  itmp5 = 0
635  do ipt3 = 1,npts
636  if (mid(ipt3).eq.nodeid) then
637  itmp4 = itmp4 + 1
638  if (itmp4.ge.itmp2.and.
639  $ itmp4.le.itmp3) then
640 ! redirect point
641  mid(ipt3) = nodeid1
642 ! count local points
643  itmp5 = itmp5 + 1
644  endif
645  endif
646  enddo ! ipt3
647 
648 ! update local variables
649  nptupl = nptupl + itmp5
650  npts_node_l(ipr) = npts_node_l(ipr) - itmp5
651  npts_node_l(ipt2)= npts_node_l(ipt2) + itmp5
652  npts_node_r(ipr) = npts_node_r(ipr) + itmp5
653 
654  endif ! npts_node_l(ipr).gt.0
655 
656  endif ! npts_node_l(ipt2).gt.0
657 
658 ! update global variables
659  npts_node_u(ipt2) = npts_node_u(ipt2) + itmp1
660  npts_node_u(ipr) = npts_node_u(ipr) - itmp1
661  itmp = itmp - itmp1
662  nptupg = nptupg + itmp1
663 
664  endif ! npts_node_u(ipt2).lt.0
665 
666  if (itmp.eq.0) goto 100
667  enddo ! ipt2
668 
669  100 continue
670 
671 ! check consistency
672  ierr = iglsum(nptupl,1)
673  if(ierr.ne.nptupg) then
674  if(nio.eq.0) write(6,*)
675  $ 'Error: pts_map_set; wrong nptupl 2'
676  call exitt
677  endif
678 
679 ! final update
680 ! update done/undone point number; related to this processor
681 ! global
682  nptgdone = nptgdone + nptupg
683  nptgundone = nptgundone - nptupg
684 ! local
685  nptldone = nptldone + nptupl
686  nptlundone = nptlundone - nptupl
687 ! count overflow/empty/shift
688  nptempty = nptempty - nptupg
689  nptover = nptover - nptupg
690  nptshift = nptshift + nptupg
691 
692  endif ! nptempty.gt.0
693 
694  else ! npts_node_g(ipr).gt.nptmax
695 ! all directed points can be send to given proc
696 ! check average number of points
697  if (npts_node_g(ipr).gt.nptav1) then
698 ! no more space for points
699 ! do not change mid
700 ! update done/undone point number
701 ! global
702  nptgdone = nptgdone + npts_node_g(ipr)
703  nptgundone = nptgundone - npts_node_g(ipr)
704 ! local
705  nptldone = nptldone + npts_node_l(ipr)
706  nptlundone = nptlundone - npts_node_l(ipr)
707 ! mark processor as done
708 ! sending - positive, receiving - negative, zeor - done
709  npts_node_u(ipr) = 0
710 
711  else ! npts_node_g(ipr).gt.nptav1
712 ! this processor should receive more points
713 
714 ! initial update done/undone point number; related to this processor
715 ! global
716  nptgdone = nptgdone + npts_node_g(ipr)
717  nptgundone = nptgundone - npts_node_g(ipr)
718 ! local
719  nptldone = nptldone + npts_node_l(ipr)
720  nptlundone = nptlundone - npts_node_l(ipr)
721 
722 ! mark processor
723 ! sending - positive, receiving - negative, zero - done
724  itmp = nptav1 - npts_node_g(ipr)
725  npts_node_u(ipr) = - itmp
726 ! count overflow/empty/shift
727  nptempty = nptempty + itmp
728 
729 ! check if threre are any points to redistribute
730 ! count the points
731  nptupg = 0 ! global
732  nptupl = 0 ! local
733  if (nptover.gt.0) then
734 
735 ! loop over all nodes with smaller id
736  do ipt2=1,ipr - 1
737  if(npts_node_u(ipt2).gt.0) then
738 ! how many points
739  itmp2 = npts_node_u(ipt2)
740  itmp1 = min(itmp2,itmp)
741 
742 ! update mid; local operation
743  if(npts_node_l(ipt2).gt.0) then
744 ! what point range
745  itmp2 = npts_node_g(ipt2) -
746  $ npts_node_u(ipt2) - npts_node_h(ipt2) -
747  $ npts_node_r(ipt2) + 1
748  itmp3 = itmp2 + itmp1 - 1
749 
750 ! does current node fit into this range
751  itmp2 = max(1,itmp2)
752  itmp3 = min(npts_node_l(ipt2),itmp3)
753  if ((itmp2.le.npts_node_l(ipt2)).and.
754  $ (itmp3.ge.1)) then
755 ! node id
756  nodeid1 = npts_plist(ipt2)
757 ! count local points
758  itmp4 = 0
759  itmp5 = 0
760  do ipt3 = 1,npts
761  if (mid(ipt3).eq.nodeid1) then
762  itmp4 = itmp4 + 1
763  if (itmp4.ge.itmp2.and.
764  $ itmp4.le.itmp3) then
765 ! redirect point
766  mid(ipt3) = nodeid
767 ! count local points
768  itmp5 = itmp5 + 1
769  endif
770  endif
771  enddo ! ipt3
772 
773 ! update local variables
774  nptupl = nptupl + itmp5
775  npts_node_l(ipr) = npts_node_l(ipr)
776  $ + itmp5
777  npts_node_l(ipt2)= npts_node_l(ipt2)
778  $ - itmp5
779  npts_node_r(ipt2)= npts_node_r(ipt2)
780  $ + itmp5
781 
782  endif ! npts_node_l(ipt2).gt.0
783 
784  endif ! npts_node_l(ipt2).gt.0
785 
786 ! update global variables
787  npts_node_u(ipt2) = npts_node_u(ipt2) - itmp1
788  npts_node_u(ipr) = npts_node_u(ipr) + itmp1
789  itmp = itmp - itmp1
790  nptupg = nptupg + itmp1
791 
792  endif ! npts_node_u(ipt2).gt.0
793 
794  if (itmp.eq.0) goto 200
795  enddo ! ipt2
796 
797  200 continue
798 
799 ! check consistency
800  ierr = iglsum(nptupl,1)
801  if(ierr.ne.nptupg) then
802  if(nio.eq.0) write(6,*)
803  $ 'Error: pts_map_set; wrong nptupl 3'
804  call exitt
805  endif
806 
807 ! final update
808 ! update done/undone point number; related to this processor
809 ! global
810  nptgdone = nptgdone + nptupg
811  nptgundone = nptgundone - nptupg
812 ! local
813  nptldone = nptldone + nptupl
814  nptlundone = nptlundone - nptupl
815 ! count overflow/empty/shift
816  nptempty = nptempty - nptupg
817  nptover = nptover - nptupg
818  nptshift = nptshift + nptupg
819 
820  endif ! nptover.gt.0
821 
822  endif ! npts_node_g(ipr).gt.nptav1
823 
824  endif ! npts_node_g(ipr).gt.nptmax
825  enddo ! ipr
826 
827 ! set node status
828  do ipr =1,nplist
829  if (nid.eq.npts_plist(ipr)) then
830  istatus = npts_node_u(ipr)
831  indasg = npts_node_g(ipr)
832  go to 300
833  endif
834  enddo
835 
836  300 continue
837 
838  return
839  end
840 c-----------------------------------------------------------------------
void exitt()
Definition: comm_mpi.f:604
subroutine nekgsync()
Definition: comm_mpi.f:502
subroutine comm_ibcastn(buf, nl, sid)
Broadcast integer array from specified process.
Definition: comm_mpi_tool.f:45
subroutine comm_ivglrsum(out, in, nl)
Global MPI scan for integer array.
Definition: comm_mpi_tool.f:17
subroutine icopy(a, b, n)
Definition: math.f:289
subroutine izero(a, n)
Definition: math.f:215
subroutine pts_map_set(mid, lpts, istatus, indasg, npts_plist, lplist, npts, nplist)
subroutine pts_map_all(mid, lpts, npts, npoints, nptimb)
subroutine pts_rdst(nptimb)
subroutine pts_transfer(rbuf, lrbuf, ibuf, libuf, lpts, npts)