PROGRESS  master
prg_graph_mod.F90
Go to the documentation of this file.
1 
3 !
4 !
5 
7 
8  use bml
10  use omp_lib
11 
12  implicit none
13 
14  private !Everything is private by default
15 
16  integer, parameter :: dp = kind(1.0d0)
17 
18  public :: subgraph_t
19  public :: graph_partitioning_t
20  public :: prg_initsubgraph
21  public :: prg_destroysubgraph
25  public :: prg_equalpartition
26  public :: prg_equalgrouppartition
27  public :: prg_filepartition
28  public :: prg_fnormgraph
29 
32 
34  integer :: part
35 
37  integer :: hsize
38 
40  integer :: lsize
41 
43  integer :: llsize
44 
46  integer, allocatable :: core_halo_index(:)
47 
49  integer, allocatable :: nodeinpart(:)
50 
52  ! real(dp) :: vvx(100)
53 
54  end type subgraph_t
55 
58 
60  character(len=100) :: pname
61 
63  integer :: myrank
64 
66  integer :: totalprocs
67 
69  integer :: totalparts
70 
72  integer :: totalnodes
73 
75  integer :: totalnodes2
76 
78  integer :: globalpartmin
79 
81  integer :: globalpartmax
82 
84  integer :: globalpartextent
85 
87  integer, allocatable :: localpartmin(:)
88 
90  integer, allocatable :: localpartmax(:)
91 
93  integer, allocatable :: localpartextent(:)
94 
96  integer, allocatable :: order(:)
97 
99  integer, allocatable :: reorder(:)
100 
102  integer :: nparts
103 
105  integer, allocatable :: nnodesinpart(:)
106 
108  integer, allocatable :: nnodesinpartall(:)
109 
111  integer :: pp(100)
112 
114  integer :: maxiter
115 
117  real(dp) :: ehomo
118 
120  real(dp) :: elumo
121 
123  real(dp) :: mineval
124 
126  real(dp) :: maxeval
127 
129  real(dp) :: vv(100)
130 
132  type (subgraph_t), allocatable :: sgraph(:)
133 
134  end type graph_partitioning_t
135 
136 contains
137 
142  subroutine prg_initsubgraph(sg, pnum, hsize)
143 
144  type (subgraph_t), intent(inout) :: sg
145  integer, intent(in) :: pnum, hsize
146 
147  sg%part = pnum
148  sg%hsize = hsize
149  sg%lsize = 0
150  sg%llsize = 0
151 
152  allocate(sg%core_halo_index(hsize))
153 
154  end subroutine prg_initsubgraph
155 
158  subroutine prg_destroysubgraph(sg)
159 
160  type (subgraph_t), intent(inout) :: sg
161 
162  if (allocated(sg%core_halo_index) .eqv. .true.) &
163  deallocate(sg%core_halo_index)
164  if (allocated(sg%nodeInPart) .eqv. .true.) deallocate(sg%nodeInPart)
165 
166  end subroutine prg_destroysubgraph
167 
174  subroutine prg_initgraphpartitioning(gp, pname, np, nnodes, nnodes2)
175 
176  type (graph_partitioning_t), intent(inout) :: gp
177  character(len=*), intent(in) :: pname
178  integer, intent(in) :: np, nnodes, nnodes2
179 
180  integer :: nprocs, avgparts
181  integer :: i, it, last, nleft
182 
183  nprocs = getnranks()
184  gp%myRank = getmyrank()
185 
186  !! Global
187  gp%pname = pname
188  gp%totalProcs = nprocs
189  gp%totalParts = np
190  gp%totalNodes = nnodes
191  gp%totalNodes2 = nnodes2
192 
193  !! Global bounds
194  gp%globalPartMin = 1
195  gp%globalPartMax = np
196  gp%globalPartExtent = gp%globalPartMax - gp%globalPartMin + 1
197 
198  allocate(gp%localPartMin(nprocs))
199  allocate(gp%localPartMax(nprocs))
200  allocate(gp%localPartExtent(nprocs))
201 
202  ! Distribute parts evenly among ranks
203  avgparts = gp%totalParts / nprocs
204  do i = 1, nprocs
205  gp%localPartExtent(i) = avgparts
206  enddo
207 
208  nleft = gp%totalParts - nprocs * avgparts
209  if (nleft .gt. 0) then
210  do i = 1, nleft
211  gp%localPartExtent(i) = gp%localPartExtent(i) + 1
212  enddo
213  endif
214 
215  gp%localPartMin(1) = 1
216  gp%localPartMax(1) = gp%localPartExtent(1)
217  do i = 2, nprocs
218  gp%localPartMin(i) = gp%localPartMax(i-1) + 1
219  gp%localPartMax(i) = gp%localPartMin(i) + gp%localPartExtent(i) - 1
220  enddo
221 
222  gp%nparts = gp%localPartExtent(gp%myRank+1)
223 
224  allocate(gp%nnodesInPart(np))
225  allocate(gp%nnodesInPartAll(np))
226  allocate(gp%sgraph(np))
227 
228  !! For reordering
229  allocate(gp%order(nnodes))
230  allocate(gp%reorder(nnodes))
231 
232  gp%maxIter = 0
233  gp%mineval = 0.0_dp
234  gp%maxeval = 0.0_dp
235 
236  if (printrank() .eq. 1) then
237  write(*,*)
238  write(*,*) "total procs = ", gp%totalProcs
239  write(*,*) "total nodes = ", gp%totalNodes
240  write(*,*) "total nodes2 = ", gp%totalNodes2
241  write(*,*) "total parts = ", gp%totalParts
242  write(*,*) "local parts = ", gp%nparts
243  write(*,*)
244  write(*,*) "globalPartMin = ", gp%globalPartMin, &
245  " globalPartMax = ", gp%globalPartMax, &
246  " globalPartExtent = ", gp%globalPartExtent
247 
248  do i = 1, nprocs
249  write(*,*) "rank = ", i-1, &
250  " localPartMin = ", gp%localPartMin(i), &
251  " localPartMax = ", gp%localPartMax(i), &
252  " localPartExtent = ", gp%localPartExtent(i)
253  enddo
254 
255  write(*,*)
256  endif
257 
258  end subroutine prg_initgraphpartitioning
259 
263 
264  type (graph_partitioning_t), intent(inout) :: gp
265 
266  integer :: i
267 
268  if (allocated(gp%localPartMin))deallocate(gp%localPartMin)
269  if (allocated(gp%localPartMax))deallocate(gp%localPartMax)
270  if (allocated(gp%localPartExtent))deallocate(gp%localPartExtent)
271 
272  if (allocated(gp%order))deallocate(gp%order)
273  if (allocated(gp%reorder))deallocate(gp%reorder)
274 
275  if(allocated(gp%nnodesInPart)) deallocate(gp%nnodesInPart)
276  if(allocated(gp%nnodesInPartAll))deallocate(gp%nnodesInPartAll)
277 
278  if (allocated(gp%sgraph)) then
279  do i = 1, gp%totalParts
280  call prg_destroysubgraph(gp%sgraph(i))
281  enddo
282  deallocate(gp%sgraph)
283  endif
284 
285  end subroutine prg_destroygraphpartitioning
286 
290 
291  type (graph_partitioning_t), intent(in) :: gp
292 
293  integer :: i, j
294 
295  if (gp%myRank .ne. 0) return
296 
297  ! Global data
298  write(*,*) ""
299  write(*,*) ""
300  write(*,*) "Graph partitioning:"
301  write(*,*) ""
302 
303  write(*,*) "name = ", gp%pname
304  write(*,*) "totalProcs = ", gp%totalProcs
305  write(*,*) "totalParts = ", gp%totalParts
306  write(*,*) "totalNodes = ", gp%totalNodes
307  write(*,*) "totalNodes2 = ", gp%totalNodes2
308  write(*,*) ""
309  write(*,*) "globalPartMin = ", gp%globalPartMin, &
310  " globalPartMax = ", gp%globalPartMax, &
311  " globalPartExtent = ", gp%globalPartExtent
312  write(*,*) ""
313 
314  ! Local data
315  write(*,*) "local parts = ", gp%nparts
316  do i = 1, gp%totalProcs
317  write(*,*) "rank = ", i-1, " localPartMin = ", gp%localPartMin(i), &
318  " localPartMax = ", gp%localPartMax(i), &
319  " localPartExtent = ", gp%localPartExtent(i)
320  enddo
321  write(*,*) ""
322 
323  ! SP2 data
324  write(*,*) "Number of iterations = ", gp%maxIter
325  write(*,*) "SP2 sequence = ", (gp%pp(i),i=1,gp%maxIter)
326  write(*,*) "mineval = ", gp%mineval , "maxeval = ", gp%maxeval
327  write(*,*) ""
328 
329  ! For each subgraph
330  do i = 1, gp%nparts
331  write(*,*) "part = ", i, " hsize = ", gp%sgraph(i)%hsize, &
332  " lsize = ", gp%sgraph(i)%lsize, &
333  " llsize = ", gp%sgraph(i)%llsize
334  write(*,*) ""
335  write(*,*) "Number of core nodes in part = ", gp%nnodesInPart(i)
336  write(*,*) "nodeInPart = ", &
337  (gp%sgraph(i)%nodeInPart(j), j=1,gp%nnodesInPart(i))
338  write(*,*) ""
339 
340  write(*,*) "core_halo_index = ", &
341  (gp%sgraph(i)%core_halo_index(j), j=1,gp%sgraph(i)%lsize)
342  write(*,*) ""
343 
344  enddo
345 
346  end subroutine prg_printgraphpartitioning
347 
352  subroutine prg_equalpartition(gp, nodesPerPart, nnodes)
353 
354  type (graph_partitioning_t), intent(inout) :: gp
355  integer, intent(in) :: nodesperpart, nnodes
356 
357  integer :: i, j, it, np, psize
358  character(len=100) :: pname
359 
360  !! Init graph partitioning
361  np = ceiling(real(nnodes) / real(nodesperpart))
362  write(pname, '("equalParts")')
364  call prg_initgraphpartitioning(gp, pname, np, nnodes, nnodes)
365 
366  !! Assign node ids (mapped to orbitals as rows) to each node in each
367  !! partition
368  !$omp parallel do default(none) private(i) &
369  !$omp private(it,j,psize) &
370  !$omp shared(gp,nnodes,nodesPerPart)
371  do i = 1, gp%totalParts
372  call prg_initsubgraph(gp%sgraph(i), i, nnodes)
373  if ((i * nodesperpart) .le. nnodes) then
374  psize = nodesperpart
375  else
376  psize = nnodes - (nodesperpart * (i-1))
377  endif
378  allocate(gp%sgraph(i)%nodeInPart(psize))
379  do j = 1, psize
380  it = (i-1) * nodesperpart + j-1;
381  gp%sgraph(i)%nodeInPart(j) = it
382  enddo
383  gp%nnodesInPart(i) = psize
384  gp%nnodesInPartAll(i) = psize
385  enddo
386  !$omp end parallel do
387 
388  end subroutine prg_equalpartition
389 
396  subroutine prg_equalgrouppartition(gp, hindex, ngroup, nodesPerPart, nnodes)
397 
398  type (graph_partitioning_t), intent(inout) :: gp
399  integer, intent(in) :: nodesperpart, nnodes, ngroup
400  integer, intent(in) :: hindex(2,ngroup)
401 
402  integer :: i, j, k, ll, np, psize, ind, ptotal
403  character(len=100) :: pname
404 
405  !! Init graph partitioning
406  np = ceiling(real(ngroup) / real(nodesperpart))
407  write(pname, '("equalGroupParts")')
409  call prg_initgraphpartitioning(gp, pname, np, ngroup, nnodes)
410 
411  !! Assign node ids (mapped to orbitals as rows) to each node in each
412  !! partition
413  !$omp parallel do default(none) &
414  !$omp private(i, j, k, ll, ind, psize, ptotal) &
415  !$omp shared(gp, hindex, nnodes, ngroup, nodesPerPart)
416  do i = 1, gp%totalParts
417  call prg_initsubgraph(gp%sgraph(i), i, nnodes)
418 
419  !! Figure out number of groups in part
420  if ((i * nodesperpart) .le. ngroup) then
421  psize = nodesperpart
422  else
423  psize = ngroup - (nodesperpart * (i-1))
424  endif
425 
426  !! Figure out total nodes/rows in part
427  ind = (i-1)*nodesperpart
428  ptotal = 0
429  do j = 1, psize
430  ptotal = ptotal + hindex(2, ind+j) - hindex(1, ind+j) + 1
431  enddo
432  gp%nnodesInPart(i) = ptotal
433  gp%nnodesInPartAll(i) = ptotal
434 
435  !! Enumerate all nodes in part
436  allocate(gp%sgraph(i)%nodeInPart(ptotal))
437  ll = 1
438  do j = 1, psize
439  do k = hindex(1, ind+j), hindex(2, ind+j)
440  gp%sgraph(i)%nodeInPart(ll) = k-1
441  ll = ll + 1
442  enddo
443  enddo
444  enddo
445  !$omp end parallel do
446 
447  ! do i = 1, gp%totalParts
448  ! write(*,*) "part ", i, ": ", gp%nnodesInPart(i), " nodes"
449  ! write(*,*) " ", &
450  ! (gp%sgraph(i)%nodeInPart(ll),ll = 1, gp%nnodesInPart(i))
451  ! enddo
452 
453  end subroutine prg_equalgrouppartition
454 
458  subroutine prg_filepartition(gp, partFile)
459 
460  type (graph_partitioning_t), intent(inout) :: gp
461  character(len=*), intent(in) :: partfile
462 
463  call prg_readpart(gp, partfile)
464 
465  end subroutine prg_filepartition
466 
470  subroutine prg_readpart(gp, partFile)
471 
472  character(len=*), intent(in) :: partFile
473  type (graph_partitioning_t), intent(inout) :: gp
474 
475  integer :: pfile
476  integer :: totalNodes, totalParts
477  integer :: i, j, ip, pnode
478  character(len=100) :: pname
479 
480  pfile = 10
481  open(unit=pfile, status='old', file=partfile)
482 
483  read(pfile, *) pname
484  read(pfile, *) totalnodes, totalparts
485 
486  call prg_initgraphpartitioning(gp, pname, totalparts, totalnodes, totalnodes)
487 
488  !! Read in part sizes
489  read(pfile, *) (gp%nnodesInPartAll(i), i=1,gp%totalParts)
490  do i = 1, gp%totalParts
491  gp%nnodesInPart(i) = gp%nnodesInPartAll(i)
492  enddo
493 
494  !! Read in nodes for each part
495  do i = 1, gp%totalParts
496  read(pfile, *) ip
497  call prg_initsubgraph(gp%sgraph(i), i, totalnodes)
498  allocate(gp%sgraph(i)%nodeInPart(gp%nnodesInPart(i)))
499  read(pfile, *) (gp%sgraph(i)%nodeInPart(j),j=1,gp%nnodesInPart(i))
500  do j = 1, gp%nnodesInPart(i)
501  gp%sgraph(i)%nodeInPart(j) = gp%sgraph(i)%nodeInPart(j) + 1
502  enddo
503  enddo
504 
505  close(pfile)
506 
507  end subroutine prg_readpart
508 
511  subroutine prg_fnormgraph(gp)
512 
513  type(graph_partitioning_t), intent(inout) :: gp
514 
515  integer :: i, j
516 #ifdef DO_MPI
517  real(dp), allocatable :: slocal(:), sglobal(:)
518 #endif
519 
520 #ifdef DO_MPI
521  ! Sum traces from all parts on all ranks
522  if (getnranks() .gt. 1) then
523  allocate(slocal(gp%maxIter))
524  allocate(sglobal(gp%maxIter))
525  do i = 1, gp%maxIter
526  slocal(i) = gp%vv(i)
527  enddo
528  call sumrealparallel(slocal, sglobal, gp%maxIter);
529  do i = 1, gp%maxIter
530  gp%vv(i) = sglobal(i)
531  enddo
532  deallocate(slocal, sglobal)
533  endif
534 #endif
535 
536  !! Take sqrt for fnorm per iter
537  do i = 1, gp%maxIter
538  gp%vv(i) = sqrt(gp%vv(i))
539  enddo
540 
541  if (printrank() .eq. 1) then
542  write(*,*)
543  write(*,*) "prg_fnormGraph:"
544  do i = 1, gp%maxIter
545  write(*,*) "iter = ", i, " fnorm = ", gp%vv(i)
546  enddo
547  endif
548 
549  end subroutine prg_fnormgraph
550 
551 end module prg_graph_mod
The graph module.
integer, parameter dp
subroutine, public prg_initgraphpartitioning(gp, pname, np, nnodes, nnodes2)
Initialize graph partitioning.
subroutine, public prg_equalpartition(gp, nodesPerPart, nnodes)
Create equal graph partitions, based on number of rows/orbitals.
subroutine, public prg_initsubgraph(sg, pnum, hsize)
Initialize subgraph.
subroutine, public prg_filepartition(gp, partFile)
Read graph partitions from a file, based on number of rows/orbitals.
subroutine prg_readpart(gp, partFile)
Read parts (core) from part file.
subroutine, public prg_destroygraphpartitioning(gp)
Destroy graph partitioning.
subroutine, public prg_destroysubgraph(sg)
Destroy subgraph.
subroutine, public prg_fnormgraph(gp)
Accumulate trace norm across all subgraphs.
subroutine, public prg_equalgrouppartition(gp, hindex, ngroup, nodesPerPart, nnodes)
Create equal group graph partitions, based on number of atoms/groups.
subroutine, public prg_printgraphpartitioning(gp)
Print graph partitioning structure data.
The parallel module.
subroutine, public sumrealparallel(sendBuf, recvBuf, icount)
integer function, public printrank()
integer function, public getnranks()
integer function, public getmyrank()