16 integer,
parameter ::
dp = kind(1.0d0)
48 integer,
allocatable :: core_halo_index(:)
51 integer,
allocatable :: nodeinpart(:)
62 character(len=100) :: pname
77 integer :: totalnodes2
80 integer :: globalpartmin
83 integer :: globalpartmax
86 integer :: globalpartextent
89 integer,
allocatable :: localpartmin(:)
92 integer,
allocatable :: localpartmax(:)
95 integer,
allocatable :: localpartextent(:)
98 integer,
allocatable :: order(:)
101 integer,
allocatable :: reorder(:)
109 integer :: nx, ny, nz
112 integer,
allocatable :: nnodesinpart(:)
115 integer,
allocatable :: nnodesinpartall(:)
152 integer,
intent(in) :: pnum, hsize
159 allocate(sg%core_halo_index(hsize))
169 if (
allocated(sg%core_halo_index))
deallocate(sg%core_halo_index)
170 if (
allocated(sg%nodeInPart))
deallocate(sg%nodeInPart)
183 character(len=*),
intent(in) :: pname
184 integer,
intent(in) :: np, nnodes, nnodes2
186 integer :: nprocs, avgparts
187 integer :: i, it, last, nleft
194 gp%totalProcs = nprocs
196 gp%totalNodes = nnodes
197 gp%totalNodes2 = nnodes2
201 gp%globalPartMax = np
202 gp%globalPartExtent = gp%globalPartMax - gp%globalPartMin + 1
204 allocate(gp%localPartMin(nprocs))
205 allocate(gp%localPartMax(nprocs))
206 allocate(gp%localPartExtent(nprocs))
209 avgparts = int(gp%totalParts / nprocs)
211 gp%localPartExtent(i) = avgparts
214 nleft = gp%totalParts - nprocs * avgparts
215 if (nleft .gt. 0)
then
217 gp%localPartExtent(i) = gp%localPartExtent(i) + 1
221 gp%localPartMin(1) = 1
222 gp%localPartMax(1) = gp%localPartExtent(1)
224 gp%localPartMin(i) = gp%localPartMax(i-1) + 1
225 gp%localPartMax(i) = gp%localPartMin(i) + gp%localPartExtent(i) - 1
228 gp%nparts = gp%localPartExtent(gp%myRank+1)
230 allocate(gp%nnodesInPart(np))
231 allocate(gp%nnodesInPartAll(np))
232 allocate(gp%sgraph(np))
235 allocate(gp%order(nnodes))
236 allocate(gp%reorder(nnodes))
244 write(*,*)
"total procs = ", gp%totalProcs
245 write(*,*)
"total nodes = ", gp%totalNodes
246 write(*,*)
"total nodes2 = ", gp%totalNodes2
247 write(*,*)
"total parts = ", gp%totalParts
248 write(*,*)
"local parts = ", gp%nparts
250 write(*,*)
"globalPartMin = ", gp%globalPartMin, &
251 " globalPartMax = ", gp%globalPartMax, &
252 " globalPartExtent = ", gp%globalPartExtent
255 write(*,*)
"rank = ", i-1, &
256 " localPartMin = ", gp%localPartMin(i), &
257 " localPartMax = ", gp%localPartMax(i), &
258 " localPartExtent = ", gp%localPartExtent(i)
274 if (
allocated(gp%localPartMin))
deallocate(gp%localPartMin)
275 if (
allocated(gp%localPartMax))
deallocate(gp%localPartMax)
276 if (
allocated(gp%localPartExtent))
deallocate(gp%localPartExtent)
278 if (
allocated(gp%order))
deallocate(gp%order)
279 if (
allocated(gp%reorder))
deallocate(gp%reorder)
281 if(
allocated(gp%nnodesInPart))
deallocate(gp%nnodesInPart)
282 if(
allocated(gp%nnodesInPartAll))
deallocate(gp%nnodesInPartAll)
284 if (
allocated(gp%sgraph))
then
285 do i = 1, gp%totalParts
288 deallocate(gp%sgraph)
301 if (gp%myRank .ne. 0)
return
306 write(*,*)
"Graph partitioning:"
309 write(*,*)
"name = ", gp%pname
310 write(*,*)
"totalProcs = ", gp%totalProcs
311 write(*,*)
"totalParts = ", gp%totalParts
312 write(*,*)
"totalNodes = ", gp%totalNodes
313 write(*,*)
"totalNodes2 = ", gp%totalNodes2
315 write(*,*)
"globalPartMin = ", gp%globalPartMin, &
316 " globalPartMax = ", gp%globalPartMax, &
317 " globalPartExtent = ", gp%globalPartExtent
321 write(*,*)
"local parts = ", gp%nparts
322 do i = 1, gp%totalProcs
323 write(*,*)
"rank = ", i-1,
" localPartMin = ", gp%localPartMin(i), &
324 " localPartMax = ", gp%localPartMax(i), &
325 " localPartExtent = ", gp%localPartExtent(i)
330 write(*,*)
"Number of iterations = ", gp%maxIter
331 write(*,*)
"SP2 sequence = ", (gp%pp(i),i=1,gp%maxIter)
332 write(*,*)
"mineval = ", gp%mineval ,
"maxeval = ", gp%maxeval
337 write(*,*)
"part = ", i,
" hsize = ", gp%sgraph(i)%hsize, &
338 " lsize = ", gp%sgraph(i)%lsize, &
339 " llsize = ", gp%sgraph(i)%llsize
341 write(*,*)
"Number of core nodes in part = ", gp%nnodesInPart(i)
342 write(*,*)
"nodeInPart = ", &
343 (gp%sgraph(i)%nodeInPart(j), j=1,gp%nnodesInPart(i))
346 write(*,*)
"core_halo_index = ", &
347 (gp%sgraph(i)%core_halo_index(j), j=1,gp%sgraph(i)%lsize)
362 integer,
intent(in) :: nodesperpart, nnodes
364 integer :: i, j, it, np, psize
365 character(len=100) :: pname
368 if (nnodes.le.nodesperpart)
then
371 np = ceiling(real(nnodes) / real(nodesperpart))
373 pname =
'("equalParts")'
382 do i = 1, gp%totalParts
384 if ((i * nodesperpart) .le. nnodes)
then
387 psize = nnodes - (nodesperpart * (i-1))
389 allocate(gp%sgraph(i)%nodeInPart(psize))
391 it = (i-1) * nodesperpart + j-1;
392 gp%sgraph(i)%nodeInPart(j) = it
394 gp%nnodesInPart(i) = psize
395 gp%nnodesInPartAll(i) = psize
404 integer :: timevector(8)
406 call date_and_time(values=timevector)
407 mls = timevector(5)*60*60*1000 + timevector(6)*60*1000 + &
408 timevector(7)*1000 + timevector(8)
423 integer,
intent(in) :: nnodes, nparts
424 integer,
allocatable,
intent(inout) :: whichparts(:)
425 integer,
optional,
intent(in) :: verb
426 integer :: i, cnt, part, j, it, psize, cut, cutold, ac, nac
427 integer :: mdim, nodesperpart,tobedistributed,sumsizes,rem
428 character(len=100) :: pname
431 if(
present(verb))
then
433 write(*,*)
"Setting partitioning in prg_setPartition..."
434 if(verb >= 2) writeout = .true.
438 pname =
'("setPartition")'
446 do i = 1, gp%totalParts
448 psize = int(sum(whichparts, mask=(whichparts==i))/i)
449 allocate(gp%sgraph(i)%nodeInPart(psize))
455 gp%sgraph(i)%nodeInPart(cnt) = j - 1
458 gp%nnodesInPart(i) = psize
459 gp%nnodesInPartAll(i) = psize
475 integer,
intent(in) :: nnodes, nparts
476 integer,
allocatable,
intent(inout) :: whichparts_guess_saved(:)
477 integer,
optional,
intent(in) :: verb
478 integer :: i, cnt, part, j, it, psize, cut, cutold, ac, nac
479 integer :: mdim, nodesperpart,tobedistributed,sumsizes,rem
480 integer,
allocatable :: whichparts(:)
481 integer,
allocatable :: graph(:,:),degs(:)
482 real(kind(1.0)),
allocatable :: row(:)
483 real(
dp) :: bal,sumdegs, mlsi
484 real(
dp),
allocatable,
intent (in) :: coords(:,:)
485 character(len=100) :: pname
486 type (bml_matrix_t),
intent(in) :: g_bml
489 if(
present(verb))
then
491 write(*,*)
"Doing SEDACS type of partitioning ..."
492 if(verb >= 2) writeout = .true.
499 if(.not.
allocated(whichparts_guess_saved))
then
500 nodesperpart = int(nnodes/nparts)
501 rem = nnodes - nodesperpart*nparts
502 tobedistributed = rem
504 pname =
'("equalParts")'
509 do i = 1, gp%totalParts
511 if (sumsizes .le. nnodes - nodesperpart)
then
512 psize = nodesperpart + min(tobedistributed,1)
513 tobedistributed = max(tobedistributed - 1,0)
515 psize = nnodes - sumsizes
517 write(*,*)i,psize,sumsizes
518 allocate(gp%sgraph(i)%nodeInPart(psize))
521 gp%sgraph(i)%nodeInPart(j) = it
523 sumsizes = sumsizes + psize
524 gp%nnodesInPart(i) = psize
525 gp%nnodesInPartAll(i) = psize
529 allocate(whichparts_guess_saved(nnodes))
531 allocate(whichparts(nnodes))
532 whichparts = whichparts_guess_saved
538 mdim = bml_get_m(g_bml)
539 allocate(graph(nnodes,mdim))
540 allocate(degs(nnodes))
541 allocate(row(nnodes))
545 call bml_get_row(g_bml,i,row)
547 if(row(j) .ge. 0.5)
then
548 degs(i) = degs(i) + 1
559 if(writeout)
write(*,*)
"Iter, Cut, RelCut, and Bal",0,cut, cut/sumdegs,bal
571 if(writeout)
write(*,*)
"Iter, Cut, RelCut, and Bal",i,cut, cut/sumdegs,bal
572 if(cut >= cutold)
then
582 pname =
'("sedacsPartition")'
590 do i = 1, gp%totalParts
592 psize = int(sum(whichparts, mask=(whichparts==i))/i)
593 allocate(gp%sgraph(i)%nodeInPart(psize))
599 gp%sgraph(i)%nodeInPart(cnt) = j - 1
602 gp%nnodesInPart(i) = psize
603 gp%nnodesInPartAll(i) = psize
607 whichparts_guess_saved = whichparts
608 deallocate(whichparts)
628 integer,
allocatable :: cutsI(:,:)
629 integer,
intent(in) :: nnodes,nparts
630 integer,
allocatable,
intent(inout) :: graph(:,:),degs(:)
631 integer,
allocatable,
intent(inout) :: whichParts(:)
633 real(kind(1.0)),
allocatable :: row(:)
634 type(bml_matrix_t) :: adj
635 integer :: i,j,deg,ind,ii,origCut,newCut, sumDeltaCut,ac,nac,newCut1
636 integer :: origCutI,newCutI,origCutJ,newCutJ
637 integer :: partIndexI, partIndexII,partIndexJ,k,cut,cutOld,newPartIndex,inDefect,discon
638 integer,
allocatable :: momentI(:),momentsI(:,:),partSizes(:)
639 real(dp),
allocatable,
intent (in) :: coords(:,:)
640 logical :: disconnected, conditionToFlip,actualize
643 allocate(cutsi(nnodes,nparts))
660 partindexii = whichparts(ind)
664 cutsi(i,partindexii) = cutsi(i,partindexii) - 1
670 allocate(row(nnodes))
671 allocate(partsizes(nparts))
675 partindexi = whichparts(i)
676 partsizes(partindexi) = partsizes(partindexi) + 1
688 call bml_get_row(adj,i,row)
689 if(cutsi(i,whichparts(i)) > 0)
then
693 if((whichparts(i) .ne. whichparts(j)))
then
698 partindexi = whichparts(i)
699 partindexj = whichparts(j)
700 origcuti = cutsi(i,partindexi)
701 origcutj = cutsi(j,partindexj)
703 newcuti = cutsi(i,partindexj)
705 if(newcuti < degs(i))
then
706 newcutj = cutsi(j,partindexi)
707 if(newcutj < degs(j))
then
710 origcut = origcuti + origcutj
711 newcut = newcuti + newcutj
713 if((newcut <= origcut))
then
717 whichparts(i) = partindexj
718 whichparts(j) = partindexi
727 cutsi(ind,partindexj) = cutsi(ind,partindexj) - 1
728 cutsi(ind,partindexi) = cutsi(ind,partindexi) + 1
733 cutsi(ind,partindexi) = cutsi(ind,partindexi) - 1
734 cutsi(ind,partindexj) = cutsi(ind,partindexj) + 1
744 elseif(whichparts(i) .eq. whichparts(j))
then
748 partindexi = whichparts(i)
749 partindexj = whichparts(j)
751 origcut = cutsi(i,partindexi)
752 origcut = origcut + cutsi(j,partindexj)
755 indefect = minloc(partsizes,dim=1)
757 newpartindex = indefect
759 newcut = cutsi(i,newpartindex)
760 newcut = newcut + cutsi(j,partindexj)
762 newcut1 = cutsi(i,partindexi)
763 newcut1 = newcut1 + cutsi(j,newpartindex)
765 if(newcut < origcut)
then
766 whichparts(i) = newpartindex
767 whichparts(j) = partindexj
768 if(newpartindex .ne.partindexj)
then
769 partsizes(newpartindex) = partsizes(newpartindex) + 1
770 partsizes(partindexj) = partsizes(partindexj) - 1
773 elseif(newcut1 < origcut)
then
774 whichparts(i) = partindexi
775 whichparts(j) = newpartindex
776 if(newpartindex .ne. partindexi)
then
777 partsizes(newpartindex) = partsizes(newpartindex) + 1
778 partsizes(partindexj) = partsizes(partindexj) - 1
782 whichparts(i) = partindexi
783 whichparts(j) = partindexj
795 deallocate(partsizes)
811 integer,
allocatable,
intent(in) :: whichParts(:)
812 integer,
allocatable :: partsSizes(:)
813 integer :: np, i, nnodes
814 real(dp),
intent(out) :: bal
816 allocate(partssizes(np))
817 nnodes =
size(whichparts)
826 if(whichparts(i) > np)
then
827 write(*,*)
"!!!ERROR: Part index",whichparts(i),&
828 "is larger than the total number of parts,",np
831 partssizes(whichparts(i)) = partssizes(whichparts(i)) + 1
835 bal = real(maxval(partssizes))/real(minval(partssizes))
836 deallocate(partssizes)
846 type (graph_partitioning_t),
intent(in) :: gp
847 integer,
allocatable,
intent(out) :: whichParts(:)
848 integer,
intent(in) :: nnodes
849 integer :: i,j,k,kk,partIndex
851 if(.not.
allocated(whichparts))
allocate(whichparts(nnodes))
859 do i = 1,gp%totalParts
860 do j = 1,gp%nnodesInPart(i)
861 k = gp%sgraph(i)%nodeInPart(j)
881 integer,
allocatable,
intent(in) :: whichParts(:)
882 integer,
intent(out) :: cut
883 integer :: nnodes,i,j,partIndexI,partIndexJ,k,kk
885 integer,
allocatable,
intent(in) :: graph(:,:),degs(:)
888 nnodes =
size(whichparts)
892 partindexi = whichparts(i)
896 partindexj = whichparts(ind)
897 if(int(partindexi - partindexj) .ne. 0)
then
916 integer,
intent(in) :: nodesperpart, nnodes, ngroup
917 integer,
intent(in) :: hindex(2,ngroup)
919 integer :: i, j, k, ll, np, psize, ind, ptotal
920 character(len=100) :: pname
923 np = ceiling(real(ngroup) / real(nodesperpart))
924 write(pname,
'("equalGroupParts")')
933 do i = 1, gp%totalParts
937 if ((i * nodesperpart) .le. ngroup)
then
940 psize = ngroup - (nodesperpart * (i-1))
944 ind = (i-1)*nodesperpart
947 ptotal = ptotal + hindex(2, ind+j) - hindex(1, ind+j) + 1
949 gp%nnodesInPart(i) = ptotal
950 gp%nnodesInPartAll(i) = ptotal
953 allocate(gp%sgraph(i)%nodeInPart(ptotal))
956 do k = hindex(1, ind+j), hindex(2, ind+j)
957 gp%sgraph(i)%nodeInPart(ll) = k-1
978 character(len=*),
intent(in) :: partfile
989 character(len=*),
intent(in) :: partFile
990 type (graph_partitioning_t),
intent(inout) :: gp
993 integer :: totalNodes, totalParts
994 integer :: i, j, ip, pnode
995 character(len=100) :: pname
998 open(unit=pfile, status=
'old', file=partfile)
1000 read(pfile, *) pname
1001 read(pfile, *) totalnodes, totalparts
1006 read(pfile, *) (gp%nnodesInPartAll(i), i=1,gp%totalParts)
1007 do i = 1, gp%totalParts
1008 gp%nnodesInPart(i) = gp%nnodesInPartAll(i)
1012 do i = 1, gp%totalParts
1015 allocate(gp%sgraph(i)%nodeInPart(gp%nnodesInPart(i)))
1016 read(pfile, *) (gp%sgraph(i)%nodeInPart(j),j=1,gp%nnodesInPart(i))
1017 do j = 1, gp%nnodesInPart(i)
1018 gp%sgraph(i)%nodeInPart(j) = gp%sgraph(i)%nodeInPart(j) + 1
1034 real(
dp),
allocatable :: slocal(:), sglobal(:)
1040 allocate(slocal(gp%maxIter))
1041 allocate(sglobal(gp%maxIter))
1042 do i = 1, gp%maxIter
1043 slocal(i) = gp%vv(i)
1046 do i = 1, gp%maxIter
1047 gp%vv(i) = sglobal(i)
1049 deallocate(slocal, sglobal)
1054 do i = 1, gp%maxIter
1055 gp%vv(i) = sqrt(gp%vv(i))
1060 write(*,*)
"prg_fnormGraph:"
1061 do i = 1, gp%maxIter
1062 write(*,*)
"iter = ", i,
" fnorm = ", gp%vv(i)
subroutine prg_get_parts_indices(gp, nnodes, whichParts)
Get part indices.
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 prg_get_balancing(whichParts, np, bal)
Get balancing.
subroutine, public prg_filepartition(gp, partFile)
Read graph partitions from a file, based on number of rows/orbitals.
subroutine do_flips_precomp(whichParts, coords, graph, adj, degs, nnodes, nparts, bal)
subroutine prg_readpart(gp, partFile)
Read parts (core) from part file.
subroutine, public prg_destroygraphpartitioning(gp)
Destroy graph partitioning.
subroutine, public prg_sedacspartition(gp, coords, whichParts_guess_saved, g_bml, nparts, nnodes, verb)
Create a partitioning based on node flips (as implemented in SEDACS - with several changes)
subroutine prg_get_graphcut(whichParts, degs, graph, cut)
Get graph cut.
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_setpartition(gp, whichParts, nparts, nnodes, verb)
Create a partitioning based on an input assignment of atoms to parts.
real(8) function time2milliseconds()
subroutine, public prg_printgraphpartitioning(gp)
Print graph partitioning structure data.
subroutine, public sumrealparallel(sendBuf, recvBuf, icount)
integer function, public printrank()
integer function, public getnranks()
integer function, public getmyrank()