73 integer,
intent(in) :: mnp, mne
74 integer,
intent(in) :: ine_global(3,mne)
75 integer,
intent(in) :: secdim
76 integer,
intent(in) :: mpicomm
77 integer :: istat, memunit
84 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 1')
86 print *,
'1: MPIcomm=', mpicomm
91 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 2')
93 print *,
'2: After initMPI'
96 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 3')
98 print *,
'3: After assignMesh'
101 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 4')
103 print *,
'3: After prePartition'
106 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 5')
108 print *,
'4: After findConnNodes'
112 write(*,*)
"pre-partition"
118 write(*,*)
"Thread",
myrank,
"# local nodes ",
np
119 write(*,*)
"Thread",
myrank,
"# local sides" ,
ns
124 print *,
'4.1: After findConnNodes'
128 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 6')
131 print *,
'5: After runParmetis'
134 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 7')
136 print *,
'Before findGhostNodes'
139 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 8')
142 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 9')
145 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 10')
148 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 11')
151 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 12')
154 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 13')
156 call computeia_ja_posi_nnz
157 call print_memcheck(memunit,
'memcheck_____:'//
' WW3_PDLIB SECTION 14')
161 write(*,*)
"New data after partition"
167 write(*,*)
"Thread",
myrank,
"# local elements ",
ne
168 write(*,*)
"Thread",
myrank,
"# local nodes ",
np
169 write(*,*)
"Thread",
myrank,
"# local sides" ,
ns
170 write(*,*)
"Thread",
myrank,
"# of ghosts",
ng
180 integer,
intent(in) :: TheComm
181 character(*),
intent(in) :: string
182 integer NbProc, eRank
183 integer :: istatus(MPI_STATUS_SIZE)
184 integer ierr, iField(1), iProc
186 CALL mpi_comm_rank(thecomm, erank, ierr)
187 CALL mpi_comm_size(thecomm, nbproc, ierr)
190 IF (erank .eq. 0)
THEN
193 CALL mpi_recv(ifield, 1, mpi_integer, iproc-1, 711, thecomm, istatus, ierr)
195 CALL mpi_send(ifield, 1, mpi_integer, iproc-1, 712, thecomm, ierr)
199 CALL mpi_send(ifield, 1, mpi_integer, 0, 711, thecomm, ierr)
201 CALL mpi_recv(ifield, 1, mpi_integer, 0, 712, thecomm, istatus, ierr)
210 subroutine initmpi(MPIcomm)
215 integer,
intent(in) :: MPIcomm
219 print *,
'2: MPIcomm=', mpicomm
221 if(mpicomm == mpi_comm_null)
then
222 CALL abort(
"A null communicator is not allowed")
226 call mpi_initialized(flag, ierr)
229 if(flag .eqv. .false.)
then
231 print *,
'Before MPI_INIT yowpdlibmain'
235 print *,
'After MPI_INIT yowpdlibmain'
247 end subroutine initmpi
262 integer,
intent(in) :: MNP, MNE
269 if(stat/=0)
CALL abort(
'nodes_global() allocate failure')
309 if(stat/=0)
call parallel_abort(
'np_perProcSum allocation failure')
325 if(
allocated(
iplg))
deallocate(
iplg)
326 allocate(
iplg(
np), stat=stat);
347 integer,
intent(in) :: INE_global(3,ne_global)
348 integer :: i, j, stat
349 type(
t_node),
pointer :: node
366 call node%insertConnNode()
367 call node%insertConnNode()
394 call node%insertConnNode(ine_global(jnext,i))
395 call node%insertConnNode(ine_global(jprev,i))
404 ns =
ns + node%nConnNodes
430 integer,
intent(in) :: MNP
434 integer :: wgtflag, numflag, ndims, nparts, edgecut, ncon
435 integer,
allocatable :: xadj(:), part(:), vwgt(:), adjwgt(:), vtxdist(:), options(:), adjncy(:), iweights(:)
437 real(4),
allocatable :: xyz(:), tpwgts(:), ubvec(:)
438 integer :: IP_glob, itmp
440 logical :: lexist = .false.
444 integer,
allocatable :: node2domain(:)
447 integer :: i, j, stat, ierr
448 type(
t_node),
pointer :: node, nodeNeighbor
454 allocate(adjncy(
ns), stat=stat)
456 allocate(xadj(
np+1), stat=stat)
465 xadj(i+1) = xadj(i) + node%nConnNodes
467 if(node%nConnNodes == 0)
then
468 write(*,*)
"Thread",
myrank,
"global node has no conn nodes", node%id_global
470 do j=1, node%nConnNodes
471 nodeneighbor => node%connNodes(j)
472 adjncy(j + xadj(i) - 1) = nodeneighbor%id_global
473 if(
debugparmetis)
write(710+
myrank,*) i, j, j + xadj(i) - 1, adjncy(j + xadj(i) - 1), nodeneighbor%id_global
500 INQUIRE (
file=
'weights.ww3', exist = lexist )
502 OPEN(100001,
file=
'weights.ww3',form=
'FORMATTED',status=
'unknown')
503 allocate(iweights(
np_global)); iweights = 0
505 read(100001,*) iweights(i)
516 allocate(vwgt(
np*ncon), stat=stat)
522 itmp = max(1,int(real((iweights(
iplg(i))+100))))
537 allocate(adjwgt(
ns), stat=stat)
543 allocate(tpwgts(ncon*
ntasks),stat=stat)
544 if(stat/=0)
call parallel_abort(
'partition: tpwgts allocation failure')
548 allocate(ubvec(ncon),stat=stat)
549 if(stat/=0)
call parallel_abort(
'partition: ubvec allocation failure')
554 allocate(xyz(2*
np),stat=stat)
561 xyz(2*(i-1)+1) = real(
xgrd(1,ip_glob))
562 xyz(2*(i-1)+2) = real(
ygrd(1,ip_glob))
564 write(710+
myrank,*) i,
np, xyz(2*(i-1)+1), xyz(2*(i-1)+2)
571 allocate(part(
np),stat=stat)
575 allocate(vtxdist(
ntasks+1),stat=stat)
576 if(stat/=0)
call parallel_abort(
'partition: vtxdist allocation failure')
579 if(ierr/=mpi_success)
call parallel_abort(
'partition: mpi_allgather',ierr)
586 write(*,*)
"Thread",
myrank,
"has no nodes"
587 write(*,*)
"vtxdist", vtxdist
588 CALL abort(
"Poor initial vertex distribution detected")
621 write(710+
myrank,*) vtxdist, xadj, adjncy, &
625 numflag,ndims,ncon,nparts,tpwgts,ubvec,options, &
632 call scotch_parmetis_v3_partgeomkway(vtxdist, xadj, adjncy, &
636 numflag,ndims,xyz,ncon,nparts,tpwgts,ubvec,options, &
637 edgecut,part,
comm,ref)
641 call parmetis_v3_partgeomkway(vtxdist, xadj, adjncy, &
645 numflag,ndims,xyz,ncon,nparts,tpwgts,ubvec,options, &
654 if(minval(part) == 0)
then
655 part(:) = part(:) + 1
663 allocate(node2domain(
np_global),stat=stat)
664 if(stat/=0)
call parallel_abort(
' node2domain allocation failure')
671 node%domainID = node2domain(node%id_global)
680 if(
allocated(xadj))
deallocate(xadj)
682 if(
allocated(adjncy))
deallocate(adjncy)
684 if(
allocated(part))
deallocate(part)
686 if(
allocated(vwgt))
deallocate(vwgt)
688 if(
allocated(adjwgt))
deallocate(adjwgt)
690 if(
allocated(xyz))
deallocate(xyz)
692 if(
allocated(tpwgts))
deallocate(tpwgts)
694 if(
allocated(ubvec))
deallocate(ubvec)
696 if(
allocated(vtxdist))
deallocate(vtxdist)
698 if(
allocated(node2domain))
deallocate(node2domain)
787 integer :: i, j, stat
788 type(
t_node),
pointer :: node
809 if(
allocated(
iplg))
deallocate(
iplg)
810 allocate(
iplg(
np), stat=stat)
814 if(
allocated(
ipgl))
deallocate(
ipgl)
822 if(node%domainID ==
myrank+1)
then
833 ns =
ns + node%nConnNodes
847 use yownodepool,
only:
t_node,
np,
nodes,
ghosts,
nodes_global,
ng,
ghostlg,
ghostgl,
npa,
np_global,
iplg
849 integer :: i, j, k, stat
850 type(
t_node),
pointer :: node, nodeNeighbor, nodeGhost
852 integer,
save,
allocatable :: ghostTemp(:)
854 print *,
'Passing in findGhostNodes'
870 do j = 1, node%nConnNodes
871 nodeneighbor => node%connNodes(j)
872 if(nodeneighbor%domainID /= node%domainID)
then
879 allocate(ghosttemp(
ng), stat=stat)
886 print *,
'ghostgl is already allocated'
899 secondloop:
do j = 1, node%nConnNodes
900 nodeneighbor => node%connNodes(j)
902 if(nodeneighbor%domainID /= node%domainID)
then
907 if(nodeneighbor%id_global == nodeghost%id_global)
then
916 ghosttemp(
ng) = nodeneighbor%id_global
927 deallocate(ghosttemp)
935 write(*,*)
"double global ghost id in ghostlg(i,j)", i, j
936 stop
"double global ghost id in ghostlg(i,j)"
943 if(
allocated(
iplg))
deallocate(
iplg)
951 if(node%domainID ==
myrank+1)
then
973 integer :: i, stat, itemp
974 type(
t_node),
pointer :: ghost
977 integer,
allocatable :: numberGhostPerNeighborDomainTemp(:)
979 integer,
allocatable :: domainID2NeighborTemp(:)
985 allocate(numberghostperneighbordomaintemp(
ntasks), stat=stat)
986 if(stat/=0)
call parallel_abort(
'numberGhostPerNeighborDomainTemp allocation failure')
987 numberghostperneighbordomaintemp = 0
989 allocate(domainid2neighbortemp(
ntasks), stat=stat)
990 if(stat/=0)
call parallel_abort(
'domainID2NeighborTemp allocation failure')
991 domainid2neighbortemp = 0
1000 numberghostperneighbordomaintemp(ghost%domainID) = numberghostperneighbordomaintemp(ghost%domainID) + 1
1003 if(domainid2neighbortemp(ghost%domainID) /= 0)
then
1010 domainid2neighbortemp(ghost%domainID) = itemp
1017 if(numberghostperneighbordomaintemp(i) /= 0)
then
1020 allocate(
neighbordomains(domainid2neighbortemp(i))%nodesToReceive(numberghostperneighbordomaintemp(i)), stat=stat)
1021 if(stat/=0)
call parallel_abort(
'neighborDomains%ghosts allocation failure')
1028 itemp = domainid2neighbortemp(ghost%domainID)
1034 if(
allocated(numberghostperneighbordomaintemp))
deallocate(numberghostperneighbordomaintemp)
1035 if(
allocated(domainid2neighbortemp))
deallocate(domainid2neighbortemp)
1064 integer :: sendRequest(nConnDomains)
1066 integer :: recvRequest(nConnDomains)
1068 integer :: status(MPI_STATUS_SIZE, nConnDomains);
1071 type(
t_node),
pointer :: node
1074 do i=1, nconndomains
1086 if(ierr/=mpi_success)
then
1087 write(*,*)
"mpi send failure"
1101 if(ierr/=mpi_success)
then
1102 write(*,*)
"mpi send failure"
1115 if(ierr/=mpi_success)
then
1116 write(*,*)
"mpi recv failure"
1121 call mpi_waitall(nconndomains, recvrequest, status, ierr)
1124 do i=1, nconndomains
1127 write(*,
'(i5, a, i5, a, i5,a, i5, a, /)', advance=
'no')
myrank,
" ERROR neighbordomain ",
neighbordomains(i)%domainID, &
1129 " nodes, but we have only ",
np,
" nodes"
1135 do i=1, nconndomains
1149 if(ierr/=mpi_success)
then
1155 call mpi_waitall(nconndomains, recvrequest, status, ierr)
1158 do i=1, nconndomains
1170 " but we don't own this node"
1188 integer,
intent(in) :: INE_global(3,ne_global)
1190 integer :: i, j, k, stat, IP_glob
1191 type(
t_node),
pointer :: node
1199 if (
belongto(ine_global(:,i)))
then
1205 if(
allocated(
ine))
deallocate(
ine)
1206 allocate(
ine(3,
ne), stat=stat)
1213 if (
belongto(ine_global(:,i)))
then
1217 node => nodes_global(ine_global(j,i))
1218 if(node%domainID ==
myrank+1)
then
1219 ine(j,
ne) = node%id
1226 if(node%id_global == ghostlg(k))
then
1228 if(
ine(j,
ne) /= 0)
then
1229 write(*,*)
"will write to INE(j, ne) but there is allready a value", j,
ne,
ine(j,
ne)
1239 if(assigned .eqv. .false.)
then
1240 write(*,*)
"Can't assign global node to INE", node%id_global
1248 if(minval(abs(
ine(:,i))) == 0)
then
1249 write(*,*)
"0 in INE ne=",
ne
1254 if(maxval(
ine) /= npa)
then
1255 write(*,*)
"MAXVAL(INE) /= npa ERROR?"
1259 if(
allocated(
ielg))
deallocate(
ielg)
1260 allocate(
ielg(
ne), stat=stat)
1266 if (
belongto(ine_global(:,i)))
then
1273 if(
allocated(
x))
deallocate(
x)
1274 allocate(
x(npa), stat=stat)
1277 if(
allocated(
y))
deallocate(
y)
1278 allocate(
y(npa), stat=stat)
1281 if(
allocated(
z))
deallocate(
z)
1282 allocate(
z(npa), stat=stat)
1287 x(i) =
xgrd(1,ip_glob)
1288 y(i) =
ygrd(1,ip_glob)
1293 ip_glob = ghostlg(i)
1294 x(np+i) =
xgrd(1,ip_glob)
1295 y(np+i) =
ygrd(1,ip_glob)
1296 z(np+i) =
zb(ip_glob)
1311 integer I1, I2, I3, stat, IE, NI(3)
1312 real :: DXP1, DXP2, DXP3, DYP1, DYP2, DYP3, DBLTMP, TRIA03
1313 logical :: CROSSES_DATELINE
1333 IF (crosses_dateline)
THEN
1334 CALL correct_dx_gt180(dxp1)
1335 CALL correct_dx_gt180(dxp2)
1336 CALL correct_dx_gt180(dxp3)
1345 dbltmp = (dxp3*dyp1 - dyp3*dxp1)*0.5
1350 WRITE(*,*)
'AREA SMALLER ZERO IN PDLIB', ie,
ne,
pdlib_tria(ie)
1373 REAL(rkind),
INTENT(IN) :: RX1, RX2, RX3
1374 LOGICAL,
INTENT(OUT) :: CROSSES_DATELINE
1375 INTEGER :: R1GT180, R2GT180, R3GT180
1376 r1gt180 = merge(1, 0, abs(rx1).GT.180)
1377 r2gt180 = merge(1, 0, abs(rx2).GT.180)
1378 r3gt180 = merge(1, 0, abs(rx3).GT.180)
1382 crosses_dateline = r1gt180+r2gt180+r3gt180 .EQ. 2
1387 subroutine correct_dx_gt180(DXP)
1392 REAL(rkind),
INTENT(INOUT) :: DXP
1393 IF (dxp .le. -180)
THEN
1396 IF (dxp .ge. 180)
THEN
1399 end subroutine correct_dx_gt180
1403 subroutine computeia_ja_posi_nnz
1415 integer IE, J, I, IP, K, IP_J, IP_K, IP_I
1416 integer I1, I2, I3, POS, POS_J, POS_K
1418 integer,
allocatable :: CELLVERTEX(:,:,:), PTABLE(:,:)
1419 integer :: ITMP(npa)
1420 maxmnecon = maxval(pdlib_ccon)
1421 ALLOCATE(cellvertex(npa,maxmnecon,2), stat=istat)
1422 IF (istat/=0)
CALL parallel_abort(
'ComputeIA_JA_POSI_NNZ, allocate error 4')
1424 cellvertex(:,:,:) = 0
1429 chilf(i) = chilf(i)+1
1430 cellvertex(i,chilf(i),1) = ie
1431 cellvertex(i,chilf(i),2) = j
1439 DO i = 1, pdlib_ccon(ip)
1444 ALLOCATE (pdlib_ie_cell(count_max), pdlib_pos_cell(count_max), stat=istat)
1445 IF (istat/=0)
CALL parallel_abort(
'wwm_fluctsplit, allocate error 5a')
1446 ALLOCATE (pdlib_ie_cell2(maxmnecon,npa),
pdlib_pos_cell2(maxmnecon, npa), stat=istat)
1447 IF (istat/=0)
CALL parallel_abort(
'wwm_fluctsplit, allocate error 5b')
1456 DO i = 1, pdlib_ccon(ip)
1458 pdlib_ie_cell(j) = cellvertex(ip,i,1)
1459 pdlib_pos_cell(j) = cellvertex(ip,i,2)
1460 pdlib_ie_cell2(i,ip) = cellvertex(ip,i,1)
1464 deallocate(cellvertex)
1466 ALLOCATE(ptable(count_max,7), stat=istat)
1467 IF (istat/=0)
CALL parallel_abort(
'wwm_fluctsplit, allocate error 6')
1468 ALLOCATE(pdlib_ja_ie(3,3,
ne), stat=istat)
1469 IF (istat/=0)
CALL parallel_abort(
'wwm_fluctsplit, allocate error 6.1')
1474 DO i = 1, pdlib_ccon(ip)
1476 ie = pdlib_ie_cell(j)
1477 pos = pdlib_pos_cell(j)
1484 ELSE IF (pos == 2)
THEN
1492 ip_j =
ine(pos_j,ie)
1493 ip_k =
ine(pos_k,ie)
1513 DO i = 1, pdlib_ccon(ip)
1521 pdlib_nnz = pdlib_nnz + sum(itmp)
1528 ALLOCATE (pdlib_ja(pdlib_nnz), pdlib_ia(npa+1), pdlib_ja_p(pdlib_nnz), stat=istat)
1529 IF (istat/=0)
CALL parallel_abort(
'wwm_fluctsplit, allocate error 6a')
1530 ALLOCATE (pdlib_ia_p(npa+1), pdlib_posi(3,count_max),
pdlib_i_diag(npa), stat=istat)
1531 IF (istat/=0)
CALL parallel_abort(
'wwm_fluctsplit, allocate error 6b')
1545 DO i = 1, pdlib_ccon(ip)
1554 IF (itmp(i) .GT. 0)
THEN
1560 pdlib_ia(ip + 1) = k + 1
1561 pdlib_ia_p(ip + 1) = k
1566 DO i = 1, pdlib_ccon(ip)
1570 DO k = pdlib_ia(ip), pdlib_ia(ip+1) - 1
1571 IF (ip == pdlib_ja(k)) pdlib_posi(1,j) = k
1573 IF (ip_j == pdlib_ja(k)) pdlib_posi(2,j) = k
1574 IF (ip_k == pdlib_ja(k)) pdlib_posi(3,j) = k
1580 DO i = 1, pdlib_ccon(ip)
1582 ie = pdlib_ie_cell(j)
1583 pos = pdlib_pos_cell(j)
1584 i1 = pdlib_posi(1,j)
1585 i2 = pdlib_posi(2,j)
1586 i3 = pdlib_posi(3,j)
1587 pdlib_ja_ie(pos,1,ie) = i1
1588 pdlib_ja_ie(pos,2,ie) = i2
1589 pdlib_ja_ie(pos,3,ie) = i3
1593 end subroutine computeia_ja_posi_nnz