1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/isimpl.h> 30c312b8eSJed Brown #include <petscsf.h> 4a9fb6443SMatthew G. Knepley #include <petscds.h> 5cb1e1211SMatthew G Knepley 676185916SToby Isaac /* get adjacencies due to point-to-point constraints that can't be found with DMPlexGetAdjacency() */ 7d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorAdjacencies(DM dm, PetscBool useCone, PetscBool useClosure, PetscSection *anchorSectionAdj, PetscInt *anchorAdj[]) 8d71ae5a4SJacob Faibussowitsch { 976185916SToby Isaac PetscInt pStart, pEnd; 10e101f074SMatthew G. Knepley PetscSection section, sectionGlobal, adjSec, aSec; 1176185916SToby Isaac IS aIS; 1276185916SToby Isaac 1376185916SToby Isaac PetscFunctionBegin; 149566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 159566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 169566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &adjSec)); 179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(adjSec, pStart, pEnd)); 1976185916SToby Isaac 209566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 2176185916SToby Isaac if (aSec) { 2276185916SToby Isaac const PetscInt *anchors; 2376185916SToby Isaac PetscInt p, q, a, aSize, *offsets, aStart, aEnd, *inverse, iSize, *adj, adjSize; 2476185916SToby Isaac PetscInt *tmpAdjP = NULL, *tmpAdjQ = NULL; 2576185916SToby Isaac PetscSection inverseSec; 2676185916SToby Isaac 2776185916SToby Isaac /* invert the constraint-to-anchor map */ 289566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)aSec), &inverseSec)); 299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(inverseSec, pStart, pEnd)); 309566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(aIS, &aSize)); 319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 3276185916SToby Isaac 3376185916SToby Isaac for (p = 0; p < aSize; p++) { 3476185916SToby Isaac PetscInt a = anchors[p]; 3576185916SToby Isaac 369566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(inverseSec, a, 1)); 3776185916SToby Isaac } 389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(inverseSec)); 399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(inverseSec, &iSize)); 409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(iSize, &inverse)); 419566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 4376185916SToby Isaac for (p = aStart; p < aEnd; p++) { 4476185916SToby Isaac PetscInt dof, off; 4576185916SToby Isaac 469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &dof)); 479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &off)); 4876185916SToby Isaac 4976185916SToby Isaac for (q = 0; q < dof; q++) { 5076185916SToby Isaac PetscInt iOff; 5176185916SToby Isaac 5276185916SToby Isaac a = anchors[off + q]; 539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(inverseSec, a, &iOff)); 5476185916SToby Isaac inverse[iOff + offsets[a - pStart]++] = p; 5576185916SToby Isaac } 5676185916SToby Isaac } 579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 589566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 5976185916SToby Isaac 6076185916SToby Isaac /* construct anchorAdj and adjSec 6176185916SToby Isaac * 6276185916SToby Isaac * loop over anchors: 6376185916SToby Isaac * construct anchor adjacency 6476185916SToby Isaac * loop over constrained: 6576185916SToby Isaac * construct constrained adjacency 6676185916SToby Isaac * if not in anchor adjacency, add to dofs 6776185916SToby Isaac * setup adjSec, allocate anchorAdj 6876185916SToby Isaac * loop over anchors: 6976185916SToby Isaac * construct anchor adjacency 7076185916SToby Isaac * loop over constrained: 7176185916SToby Isaac * construct constrained adjacency 7276185916SToby Isaac * if not in anchor adjacency 7376185916SToby Isaac * if not already in list, put in list 7476185916SToby Isaac * sort, unique, reduce dof count 7576185916SToby Isaac * optional: compactify 7676185916SToby Isaac */ 7776185916SToby Isaac for (p = pStart; p < pEnd; p++) { 7876185916SToby Isaac PetscInt iDof, iOff, i, r, s, numAdjP = PETSC_DETERMINE; 7976185916SToby Isaac 809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(inverseSec, p, &iDof)); 8176185916SToby Isaac if (!iDof) continue; 829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(inverseSec, p, &iOff)); 839566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, PETSC_TRUE, &numAdjP, &tmpAdjP)); 8476185916SToby Isaac for (i = 0; i < iDof; i++) { 8576185916SToby Isaac PetscInt iNew = 0, qAdj, qAdjDof, qAdjCDof, numAdjQ = PETSC_DETERMINE; 8676185916SToby Isaac 8776185916SToby Isaac q = inverse[iOff + i]; 889566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, q, useCone, useClosure, PETSC_TRUE, &numAdjQ, &tmpAdjQ)); 8976185916SToby Isaac for (r = 0; r < numAdjQ; r++) { 9076185916SToby Isaac qAdj = tmpAdjQ[r]; 9176185916SToby Isaac if ((qAdj < pStart) || (qAdj >= pEnd)) continue; 9276185916SToby Isaac for (s = 0; s < numAdjP; s++) { 9376185916SToby Isaac if (qAdj == tmpAdjP[s]) break; 9476185916SToby Isaac } 9576185916SToby Isaac if (s < numAdjP) continue; 969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, qAdj, &qAdjDof)); 979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, qAdj, &qAdjCDof)); 9876185916SToby Isaac iNew += qAdjDof - qAdjCDof; 9976185916SToby Isaac } 1009566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(adjSec, p, iNew)); 10176185916SToby Isaac } 10276185916SToby Isaac } 10376185916SToby Isaac 1049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(adjSec)); 1059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(adjSec, &adjSize)); 1069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(adjSize, &adj)); 10776185916SToby Isaac 10876185916SToby Isaac for (p = pStart; p < pEnd; p++) { 10976185916SToby Isaac PetscInt iDof, iOff, i, r, s, aOff, aOffOrig, aDof, numAdjP = PETSC_DETERMINE; 11076185916SToby Isaac 1119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(inverseSec, p, &iDof)); 11276185916SToby Isaac if (!iDof) continue; 1139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(inverseSec, p, &iOff)); 1149566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, PETSC_TRUE, &numAdjP, &tmpAdjP)); 1159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(adjSec, p, &aDof)); 1169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(adjSec, p, &aOff)); 11776185916SToby Isaac aOffOrig = aOff; 11876185916SToby Isaac for (i = 0; i < iDof; i++) { 11976185916SToby Isaac PetscInt qAdj, qAdjDof, qAdjCDof, qAdjOff, nd, numAdjQ = PETSC_DETERMINE; 12076185916SToby Isaac 12176185916SToby Isaac q = inverse[iOff + i]; 1229566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, q, useCone, useClosure, PETSC_TRUE, &numAdjQ, &tmpAdjQ)); 12376185916SToby Isaac for (r = 0; r < numAdjQ; r++) { 12476185916SToby Isaac qAdj = tmpAdjQ[r]; 12576185916SToby Isaac if ((qAdj < pStart) || (qAdj >= pEnd)) continue; 12676185916SToby Isaac for (s = 0; s < numAdjP; s++) { 12776185916SToby Isaac if (qAdj == tmpAdjP[s]) break; 12876185916SToby Isaac } 12976185916SToby Isaac if (s < numAdjP) continue; 1309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, qAdj, &qAdjDof)); 1319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, qAdj, &qAdjCDof)); 1329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, qAdj, &qAdjOff)); 133ad540459SPierre Jolivet for (nd = 0; nd < qAdjDof - qAdjCDof; ++nd) adj[aOff++] = (qAdjOff < 0 ? -(qAdjOff + 1) : qAdjOff) + nd; 13476185916SToby Isaac } 13576185916SToby Isaac } 1368e3a54c0SPierre Jolivet PetscCall(PetscSortRemoveDupsInt(&aDof, PetscSafePointerPlusOffset(adj, aOffOrig))); 1379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(adjSec, p, aDof)); 13876185916SToby Isaac } 13976185916SToby Isaac *anchorAdj = adj; 14076185916SToby Isaac 14176185916SToby Isaac /* clean up */ 1429566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&inverseSec)); 1439566063dSJacob Faibussowitsch PetscCall(PetscFree(inverse)); 1449566063dSJacob Faibussowitsch PetscCall(PetscFree(tmpAdjP)); 1459566063dSJacob Faibussowitsch PetscCall(PetscFree(tmpAdjQ)); 1469371c9d4SSatish Balay } else { 14776185916SToby Isaac *anchorAdj = NULL; 1489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(adjSec)); 14976185916SToby Isaac } 15076185916SToby Isaac *anchorSectionAdj = adjSec; 1513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15276185916SToby Isaac } 15376185916SToby Isaac 154*a38eeca9SJames Wright // Determine if any of the local adjancencies match a leaf and root of the pointSF. 155*a38eeca9SJames Wright // When using isoperiodic boundary conditions, it is possible for periodic (leaf) and donor (root) pairs to be on the same rank. 156*a38eeca9SJames Wright // This check is done to ensure the adjancency in these cases is only counted for one of the mesh points rather than both. 157*a38eeca9SJames Wright static inline PetscErrorCode AdjancencyContainsLeafRootPair(PetscInt num_pairs, const PetscInt leaves[], const PetscInt roots[], PetscInt numAdj, const PetscInt tmpAdj[], PetscInt *num_leaves_found, PetscInt leaves_found[]) 158*a38eeca9SJames Wright { 159*a38eeca9SJames Wright PetscInt root_index = -1, leaf_, num_roots_found = 0; 160*a38eeca9SJames Wright 161*a38eeca9SJames Wright PetscFunctionBeginUser; 162*a38eeca9SJames Wright *num_leaves_found = 0; 163*a38eeca9SJames Wright for (PetscInt q = 0; q < numAdj; q++) { 164*a38eeca9SJames Wright const PetscInt padj = tmpAdj[q]; 165*a38eeca9SJames Wright PetscCall(PetscFindInt(padj, num_pairs, roots, &root_index)); 166*a38eeca9SJames Wright if (root_index >= 0) { 167*a38eeca9SJames Wright leaves_found[num_roots_found] = root_index; // Initially use leaves_found to store pair indices 168*a38eeca9SJames Wright num_roots_found++; 169*a38eeca9SJames Wright break; 170*a38eeca9SJames Wright } 171*a38eeca9SJames Wright } 172*a38eeca9SJames Wright if (num_roots_found == 0) PetscFunctionReturn(PETSC_SUCCESS); 173*a38eeca9SJames Wright 174*a38eeca9SJames Wright for (PetscInt i = 0; i < num_roots_found; i++) { 175*a38eeca9SJames Wright leaf_ = leaves[root_index]; 176*a38eeca9SJames Wright for (PetscInt q = 0; q < numAdj; q++) { 177*a38eeca9SJames Wright if (tmpAdj[q] == leaf_) { 178*a38eeca9SJames Wright leaves_found[*num_leaves_found] = leaf_; 179*a38eeca9SJames Wright (*num_leaves_found)++; 180*a38eeca9SJames Wright continue; 181*a38eeca9SJames Wright } 182*a38eeca9SJames Wright } 183*a38eeca9SJames Wright } 184*a38eeca9SJames Wright 185*a38eeca9SJames Wright PetscCall(PetscIntSortSemiOrdered(*num_leaves_found, leaves_found)); 186*a38eeca9SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 187*a38eeca9SJames Wright } 188*a38eeca9SJames Wright 189d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateAdjacencySection_Static(DM dm, PetscInt bs, PetscSF sfDof, PetscBool useCone, PetscBool useClosure, PetscBool useAnchors, PetscSection *sA, PetscInt **colIdx) 190d71ae5a4SJacob Faibussowitsch { 191cb1e1211SMatthew G Knepley MPI_Comm comm; 192*a38eeca9SJames Wright PetscMPIInt myrank; 193a9fb6443SMatthew G. Knepley PetscBool doCommLocal, doComm, debug = PETSC_FALSE; 194a9fb6443SMatthew G. Knepley PetscSF sf, sfAdj; 195e101f074SMatthew G. Knepley PetscSection section, sectionGlobal, leafSectionAdj, rootSectionAdj, sectionAdj, anchorSectionAdj; 196a9fb6443SMatthew G. Knepley PetscInt nroots, nleaves, l, p, r; 197cb1e1211SMatthew G Knepley const PetscInt *leaves; 198cb1e1211SMatthew G Knepley const PetscSFNode *remotes; 199cb1e1211SMatthew G Knepley PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 200*a38eeca9SJames Wright PetscInt *tmpAdj = NULL, *adj, *rootAdj, *anchorAdj = NULL, *cols, *remoteOffsets, *rootsMyRankPair = NULL, *leavesMyRankPair = NULL; 201*a38eeca9SJames Wright PetscInt adjSize, numMyRankPair = 0; 202cb1e1211SMatthew G Knepley 203cb1e1211SMatthew G Knepley PetscFunctionBegin; 2049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_view_preallocation", &debug, NULL)); 206*a38eeca9SJames Wright PetscCallMPI(MPI_Comm_rank(comm, &myrank)); 2079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 208*a38eeca9SJames Wright PetscCall(DMGetIsoperiodicPointSF_Internal(dm, &sf)); 2099566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 2109566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 2119566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL)); 212*a38eeca9SJames Wright doCommLocal = nroots >= 0 ? PETSC_TRUE : PETSC_FALSE; 2135440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&doCommLocal, &doComm, 1, MPI_C_BOOL, MPI_LAND, comm)); 214cb1e1211SMatthew G Knepley /* Create section for dof adjacency (dof ==> # adj dof) */ 2159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &numDof)); 2179566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &leafSectionAdj)); 2189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSectionAdj, 0, numDof)); 2199566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSectionAdj)); 2209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSectionAdj, 0, numDof)); 2219566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes)); 222*a38eeca9SJames Wright 223*a38eeca9SJames Wright // Store leaf-root pairs if remote.rank is the current rank 224*a38eeca9SJames Wright if (nleaves >= 0) PetscCall(PetscMalloc2(nleaves, &rootsMyRankPair, nleaves, &leavesMyRankPair)); 225*a38eeca9SJames Wright for (PetscInt l = 0; l < nleaves; l++) { 226*a38eeca9SJames Wright if (remotes[l].rank == myrank) { 227*a38eeca9SJames Wright rootsMyRankPair[numMyRankPair] = remotes[l].index; 228*a38eeca9SJames Wright leavesMyRankPair[numMyRankPair] = leaves[l]; 229*a38eeca9SJames Wright numMyRankPair++; 230*a38eeca9SJames Wright } 231*a38eeca9SJames Wright } 232*a38eeca9SJames Wright PetscCall(PetscIntSortSemiOrdered(numMyRankPair, rootsMyRankPair)); 233*a38eeca9SJames Wright PetscCall(PetscIntSortSemiOrdered(numMyRankPair, leavesMyRankPair)); 234*a38eeca9SJames Wright if (debug) { 235*a38eeca9SJames Wright PetscCall(PetscPrintf(comm, "Roots on the same rank:\n")); 236*a38eeca9SJames Wright PetscCall(PetscIntView(numMyRankPair, rootsMyRankPair, NULL)); 237*a38eeca9SJames Wright } 238cb1e1211SMatthew G Knepley /* 239964bf7afSMatthew G. Knepley section - maps points to (# dofs, local dofs) 240964bf7afSMatthew G. Knepley sectionGlobal - maps points to (# dofs, global dofs) 241964bf7afSMatthew G. Knepley leafSectionAdj - maps unowned local dofs to # adj dofs 242964bf7afSMatthew G. Knepley rootSectionAdj - maps owned local dofs to # adj dofs 243964bf7afSMatthew G. Knepley adj - adj global dofs indexed by leafSectionAdj 244964bf7afSMatthew G. Knepley rootAdj - adj global dofs indexed by rootSectionAdj 245964bf7afSMatthew G. Knepley sf - describes shared points across procs 246964bf7afSMatthew G. Knepley sfDof - describes shared dofs across procs 247964bf7afSMatthew G. Knepley sfAdj - describes shared adjacent dofs across procs 248cb1e1211SMatthew G Knepley ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 24976185916SToby Isaac (0). If there are point-to-point constraints, add the adjacencies of constrained points to anchors in anchorAdj 25076185916SToby Isaac (This is done in DMPlexComputeAnchorAdjacencies()) 251cb1e1211SMatthew G Knepley 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 252cb1e1211SMatthew G Knepley Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 253cb1e1211SMatthew G Knepley 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 254cb1e1211SMatthew G Knepley Create sfAdj connecting rootSectionAdj and leafSectionAdj 255cb1e1211SMatthew G Knepley 3. Visit unowned points on interface, write adjacencies to adj 256cb1e1211SMatthew G Knepley Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 257cb1e1211SMatthew G Knepley 4. Visit owned points on interface, write adjacencies to rootAdj 258cb1e1211SMatthew G Knepley Remove redundancy in rootAdj 259cb1e1211SMatthew G Knepley ** The last two traversals use transitive closure 260cb1e1211SMatthew G Knepley 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 261cb1e1211SMatthew G Knepley Allocate memory addressed by sectionAdj (cols) 262cb1e1211SMatthew G Knepley 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 263cb1e1211SMatthew G Knepley ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 264cb1e1211SMatthew G Knepley */ 2659566063dSJacob Faibussowitsch PetscCall(DMPlexComputeAnchorAdjacencies(dm, useCone, useClosure, &anchorSectionAdj, &anchorAdj)); 266cb1e1211SMatthew G Knepley for (l = 0; l < nleaves; ++l) { 26776185916SToby Isaac PetscInt dof, off, d, q, anDof; 26870034214SMatthew G. Knepley PetscInt p = leaves[l], numAdj = PETSC_DETERMINE; 269cb1e1211SMatthew G Knepley 270fb47e2feSMatthew G. Knepley if ((p < pStart) || (p >= pEnd)) continue; 2719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 2729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 2739566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 274cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 275cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 276cb1e1211SMatthew G Knepley PetscInt ndof, ncdof; 277cb1e1211SMatthew G Knepley 278cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 2799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 2809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 28148a46eb9SPierre Jolivet for (d = off; d < off + dof; ++d) PetscCall(PetscSectionAddDof(leafSectionAdj, d, ndof - ncdof)); 282cb1e1211SMatthew G Knepley } 2839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 28476185916SToby Isaac if (anDof) { 28548a46eb9SPierre Jolivet for (d = off; d < off + dof; ++d) PetscCall(PetscSectionAddDof(leafSectionAdj, d, anDof)); 28676185916SToby Isaac } 287cb1e1211SMatthew G Knepley } 2889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSectionAdj)); 289cb1e1211SMatthew G Knepley if (debug) { 2909566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n")); 2919566063dSJacob Faibussowitsch PetscCall(PetscSectionView(leafSectionAdj, NULL)); 292cb1e1211SMatthew G Knepley } 293cb1e1211SMatthew G Knepley /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 29447a6104aSMatthew G. Knepley if (doComm) { 2959566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM)); 2969566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM)); 29769c11d05SVaclav Hapla PetscCall(PetscSectionInvalidateMaxDof_Internal(rootSectionAdj)); 298cb1e1211SMatthew G Knepley } 299cb1e1211SMatthew G Knepley if (debug) { 300145b44c9SPierre Jolivet PetscCall(PetscPrintf(comm, "Adjacency Section for Preallocation on Roots:\n")); 3019566063dSJacob Faibussowitsch PetscCall(PetscSectionView(rootSectionAdj, NULL)); 302cb1e1211SMatthew G Knepley } 303cb1e1211SMatthew G Knepley /* Add in local adjacency sizes for owned dofs on interface (roots) */ 304cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 30576185916SToby Isaac PetscInt numAdj = PETSC_DETERMINE, adof, dof, off, d, q, anDof; 306cb1e1211SMatthew G Knepley 3079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 3089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 309cb1e1211SMatthew G Knepley if (!dof) continue; 3109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off, &adof)); 311cb1e1211SMatthew G Knepley if (adof <= 0) continue; 3129566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 313cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 314cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 315cb1e1211SMatthew G Knepley PetscInt ndof, ncdof; 316cb1e1211SMatthew G Knepley 317cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 3189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 3199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 32048a46eb9SPierre Jolivet for (d = off; d < off + dof; ++d) PetscCall(PetscSectionAddDof(rootSectionAdj, d, ndof - ncdof)); 321cb1e1211SMatthew G Knepley } 3229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 32376185916SToby Isaac if (anDof) { 32448a46eb9SPierre Jolivet for (d = off; d < off + dof; ++d) PetscCall(PetscSectionAddDof(rootSectionAdj, d, anDof)); 32576185916SToby Isaac } 326cb1e1211SMatthew G Knepley } 3279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSectionAdj)); 328cb1e1211SMatthew G Knepley if (debug) { 329145b44c9SPierre Jolivet PetscCall(PetscPrintf(comm, "Adjacency Section for Preallocation on Roots after local additions:\n")); 3309566063dSJacob Faibussowitsch PetscCall(PetscSectionView(rootSectionAdj, NULL)); 331cb1e1211SMatthew G Knepley } 332cb1e1211SMatthew G Knepley /* Create adj SF based on dof SF */ 3339566063dSJacob Faibussowitsch PetscCall(PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets)); 3349566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj)); 3359566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 3366a1a2f7bSJames Wright if (debug) { 3379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjacency SF for Preallocation:\n")); 3389566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfAdj, NULL)); 339cb1e1211SMatthew G Knepley } 340cb1e1211SMatthew G Knepley /* Create leaf adjacency */ 3419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSectionAdj)); 3429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafSectionAdj, &adjSize)); 3439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(adjSize, &adj)); 344cb1e1211SMatthew G Knepley for (l = 0; l < nleaves; ++l) { 34576185916SToby Isaac PetscInt dof, off, d, q, anDof, anOff; 34670034214SMatthew G. Knepley PetscInt p = leaves[l], numAdj = PETSC_DETERMINE; 347cb1e1211SMatthew G Knepley 348fb47e2feSMatthew G. Knepley if ((p < pStart) || (p >= pEnd)) continue; 3499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 3509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 3519566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 3529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 3539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(anchorSectionAdj, p, &anOff)); 354cb1e1211SMatthew G Knepley for (d = off; d < off + dof; ++d) { 355cb1e1211SMatthew G Knepley PetscInt aoff, i = 0; 356cb1e1211SMatthew G Knepley 3579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSectionAdj, d, &aoff)); 358cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 359cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 360cb1e1211SMatthew G Knepley PetscInt ndof, ncdof, ngoff, nd; 361cb1e1211SMatthew G Knepley 362cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 3639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 3649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 3659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, padj, &ngoff)); 366cb1e1211SMatthew G Knepley for (nd = 0; nd < ndof - ncdof; ++nd) { 367cb1e1211SMatthew G Knepley adj[aoff + i] = (ngoff < 0 ? -(ngoff + 1) : ngoff) + nd; 368cb1e1211SMatthew G Knepley ++i; 369cb1e1211SMatthew G Knepley } 370cb1e1211SMatthew G Knepley } 37176185916SToby Isaac for (q = 0; q < anDof; q++) { 37276185916SToby Isaac adj[aoff + i] = anchorAdj[anOff + q]; 37376185916SToby Isaac ++i; 37476185916SToby Isaac } 375cb1e1211SMatthew G Knepley } 376cb1e1211SMatthew G Knepley } 377cb1e1211SMatthew G Knepley /* Debugging */ 378cb1e1211SMatthew G Knepley if (debug) { 3799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Leaf adjacency indices\n")); 3806a1a2f7bSJames Wright PetscCall(PetscSectionArrayView(leafSectionAdj, adj, PETSC_INT, NULL)); 381cb1e1211SMatthew G Knepley } 382543482b8SMatthew G. Knepley /* Gather adjacent indices to root */ 3839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSectionAdj, &adjSize)); 3849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(adjSize, &rootAdj)); 385cb1e1211SMatthew G Knepley for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 38647a6104aSMatthew G. Knepley if (doComm) { 387543482b8SMatthew G. Knepley const PetscInt *indegree; 388543482b8SMatthew G. Knepley PetscInt *remoteadj, radjsize = 0; 389543482b8SMatthew G. Knepley 3909566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sfAdj, &indegree)); 3919566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sfAdj, &indegree)); 392543482b8SMatthew G. Knepley for (p = 0; p < adjSize; ++p) radjsize += indegree[p]; 3939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(radjsize, &remoteadj)); 3949566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sfAdj, MPIU_INT, adj, remoteadj)); 3959566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sfAdj, MPIU_INT, adj, remoteadj)); 3966dba2905SMatthew G. Knepley for (p = 0, l = 0, r = 0; p < adjSize; ++p, l = PetscMax(p, l + indegree[p - 1])) { 397543482b8SMatthew G. Knepley PetscInt s; 3986dba2905SMatthew G. Knepley for (s = 0; s < indegree[p]; ++s, ++r) rootAdj[l + s] = remoteadj[r]; 399543482b8SMatthew G. Knepley } 40063a3b9bcSJacob Faibussowitsch PetscCheck(r == radjsize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistency in communication %" PetscInt_FMT " != %" PetscInt_FMT, r, radjsize); 40163a3b9bcSJacob Faibussowitsch PetscCheck(l == adjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistency in communication %" PetscInt_FMT " != %" PetscInt_FMT, l, adjSize); 4029566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteadj)); 403cb1e1211SMatthew G Knepley } 4049566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfAdj)); 4059566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 406cb1e1211SMatthew G Knepley /* Debugging */ 407cb1e1211SMatthew G Knepley if (debug) { 4089566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Root adjacency indices after gather\n")); 4096a1a2f7bSJames Wright PetscCall(PetscSectionArrayView(rootSectionAdj, rootAdj, PETSC_INT, NULL)); 410cb1e1211SMatthew G Knepley } 411cb1e1211SMatthew G Knepley /* Add in local adjacency indices for owned dofs on interface (roots) */ 412cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 41376185916SToby Isaac PetscInt numAdj = PETSC_DETERMINE, adof, dof, off, d, q, anDof, anOff; 414cb1e1211SMatthew G Knepley 4159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 4169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 417cb1e1211SMatthew G Knepley if (!dof) continue; 4189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off, &adof)); 419cb1e1211SMatthew G Knepley if (adof <= 0) continue; 4209566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 4219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 4229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(anchorSectionAdj, p, &anOff)); 423cb1e1211SMatthew G Knepley for (d = off; d < off + dof; ++d) { 424cb1e1211SMatthew G Knepley PetscInt adof, aoff, i; 425cb1e1211SMatthew G Knepley 4269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, d, &adof)); 4279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSectionAdj, d, &aoff)); 428cb1e1211SMatthew G Knepley i = adof - 1; 42976185916SToby Isaac for (q = 0; q < anDof; q++) { 43076185916SToby Isaac rootAdj[aoff + i] = anchorAdj[anOff + q]; 43176185916SToby Isaac --i; 43276185916SToby Isaac } 433cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 434cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 435cb1e1211SMatthew G Knepley PetscInt ndof, ncdof, ngoff, nd; 436cb1e1211SMatthew G Knepley 437cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 4389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 4399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 4409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, padj, &ngoff)); 441cb1e1211SMatthew G Knepley for (nd = 0; nd < ndof - ncdof; ++nd) { 442cb1e1211SMatthew G Knepley rootAdj[aoff + i] = ngoff < 0 ? -(ngoff + 1) + nd : ngoff + nd; 443cb1e1211SMatthew G Knepley --i; 444cb1e1211SMatthew G Knepley } 445cb1e1211SMatthew G Knepley } 446cb1e1211SMatthew G Knepley } 447cb1e1211SMatthew G Knepley } 448cb1e1211SMatthew G Knepley /* Debugging */ 449cb1e1211SMatthew G Knepley if (debug) { 4506a1a2f7bSJames Wright PetscCall(PetscPrintf(comm, "Adjacency Section for Preallocation on Roots before compression:\n")); 4516a1a2f7bSJames Wright PetscCall(PetscSectionArrayView(rootSectionAdj, rootAdj, PETSC_INT, NULL)); 452cb1e1211SMatthew G Knepley } 453cb1e1211SMatthew G Knepley /* Compress indices */ 4549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSectionAdj)); 455cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 456cb1e1211SMatthew G Knepley PetscInt dof, cdof, off, d; 457cb1e1211SMatthew G Knepley PetscInt adof, aoff; 458cb1e1211SMatthew G Knepley 4599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 4609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 4619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 462cb1e1211SMatthew G Knepley if (!dof) continue; 4639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off, &adof)); 464cb1e1211SMatthew G Knepley if (adof <= 0) continue; 465cb1e1211SMatthew G Knepley for (d = off; d < off + dof - cdof; ++d) { 4669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, d, &adof)); 4679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSectionAdj, d, &aoff)); 4689566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&adof, &rootAdj[aoff])); 4699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootSectionAdj, d, adof)); 470cb1e1211SMatthew G Knepley } 471cb1e1211SMatthew G Knepley } 472cb1e1211SMatthew G Knepley /* Debugging */ 473cb1e1211SMatthew G Knepley if (debug) { 474145b44c9SPierre Jolivet PetscCall(PetscPrintf(comm, "Adjacency Section for Preallocation on Roots after compression:\n")); 4756a1a2f7bSJames Wright PetscCall(PetscSectionArrayView(rootSectionAdj, rootAdj, PETSC_INT, NULL)); 476cb1e1211SMatthew G Knepley } 477cb1e1211SMatthew G Knepley /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 4789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd)); 4799566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, §ionAdj)); 4809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd)); 481*a38eeca9SJames Wright 482*a38eeca9SJames Wright PetscInt *exclude_leaves, num_exclude_leaves, max_adjacency_size = 0; 483*a38eeca9SJames Wright PetscCall(DMPlexGetMaxAdjacencySize_Internal(dm, useAnchors, &max_adjacency_size)); 484*a38eeca9SJames Wright PetscCall(PetscMalloc1(max_adjacency_size, &exclude_leaves)); 485*a38eeca9SJames Wright 486cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 48776185916SToby Isaac PetscInt numAdj = PETSC_DETERMINE, dof, cdof, off, goff, d, q, anDof; 488cb1e1211SMatthew G Knepley PetscBool found = PETSC_TRUE; 489cb1e1211SMatthew G Knepley 4909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 4919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 4929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 4939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff)); 494cb1e1211SMatthew G Knepley for (d = 0; d < dof - cdof; ++d) { 495cb1e1211SMatthew G Knepley PetscInt ldof, rdof; 496cb1e1211SMatthew G Knepley 4979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSectionAdj, off + d, &ldof)); 4989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off + d, &rdof)); 499cb1e1211SMatthew G Knepley if (ldof > 0) { 500cb1e1211SMatthew G Knepley /* We do not own this point */ 501cb1e1211SMatthew G Knepley } else if (rdof > 0) { 5029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sectionAdj, goff + d, rdof)); 503cb1e1211SMatthew G Knepley } else { 504cb1e1211SMatthew G Knepley found = PETSC_FALSE; 505cb1e1211SMatthew G Knepley } 506cb1e1211SMatthew G Knepley } 507cb1e1211SMatthew G Knepley if (found) continue; 5089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff)); 5109566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 511*a38eeca9SJames Wright PetscCall(AdjancencyContainsLeafRootPair(numMyRankPair, leavesMyRankPair, rootsMyRankPair, numAdj, tmpAdj, &num_exclude_leaves, exclude_leaves)); 512cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 513cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 514*a38eeca9SJames Wright PetscInt ndof, ncdof, noff, count; 515cb1e1211SMatthew G Knepley 516cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 5179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 5189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 5199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, padj, &noff)); 520*a38eeca9SJames Wright // If leaf-root pair are both on this rank, only count root 521*a38eeca9SJames Wright PetscCall(PetscFindInt(padj, num_exclude_leaves, exclude_leaves, &count)); 522*a38eeca9SJames Wright if (count >= 0) continue; 52348a46eb9SPierre Jolivet for (d = goff; d < goff + dof - cdof; ++d) PetscCall(PetscSectionAddDof(sectionAdj, d, ndof - ncdof)); 524cb1e1211SMatthew G Knepley } 5259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 52676185916SToby Isaac if (anDof) { 52748a46eb9SPierre Jolivet for (d = goff; d < goff + dof - cdof; ++d) PetscCall(PetscSectionAddDof(sectionAdj, d, anDof)); 52876185916SToby Isaac } 529cb1e1211SMatthew G Knepley } 5309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sectionAdj)); 531cb1e1211SMatthew G Knepley if (debug) { 5329566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjacency Section for Preallocation:\n")); 5339566063dSJacob Faibussowitsch PetscCall(PetscSectionView(sectionAdj, NULL)); 534cb1e1211SMatthew G Knepley } 535cb1e1211SMatthew G Knepley /* Get adjacent indices */ 5369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sectionAdj, &numCols)); 5379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCols, &cols)); 538cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 53976185916SToby Isaac PetscInt numAdj = PETSC_DETERMINE, dof, cdof, off, goff, d, q, anDof, anOff; 540cb1e1211SMatthew G Knepley PetscBool found = PETSC_TRUE; 541cb1e1211SMatthew G Knepley 5429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 5449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff)); 546cb1e1211SMatthew G Knepley for (d = 0; d < dof - cdof; ++d) { 547cb1e1211SMatthew G Knepley PetscInt ldof, rdof; 548cb1e1211SMatthew G Knepley 5499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSectionAdj, off + d, &ldof)); 5509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off + d, &rdof)); 551cb1e1211SMatthew G Knepley if (ldof > 0) { 552cb1e1211SMatthew G Knepley /* We do not own this point */ 553cb1e1211SMatthew G Knepley } else if (rdof > 0) { 554cb1e1211SMatthew G Knepley PetscInt aoff, roff; 555cb1e1211SMatthew G Knepley 5569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, goff + d, &aoff)); 5579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSectionAdj, off + d, &roff)); 5589566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&cols[aoff], &rootAdj[roff], rdof)); 559cb1e1211SMatthew G Knepley } else { 560cb1e1211SMatthew G Knepley found = PETSC_FALSE; 561cb1e1211SMatthew G Knepley } 562cb1e1211SMatthew G Knepley } 563cb1e1211SMatthew G Knepley if (found) continue; 5649566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 565*a38eeca9SJames Wright PetscCall(AdjancencyContainsLeafRootPair(numMyRankPair, leavesMyRankPair, rootsMyRankPair, numAdj, tmpAdj, &num_exclude_leaves, exclude_leaves)); 5669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 5679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(anchorSectionAdj, p, &anOff)); 568cb1e1211SMatthew G Knepley for (d = goff; d < goff + dof - cdof; ++d) { 569cb1e1211SMatthew G Knepley PetscInt adof, aoff, i = 0; 570cb1e1211SMatthew G Knepley 5719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, d, &adof)); 5729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, d, &aoff)); 573cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 574*a38eeca9SJames Wright const PetscInt padj = tmpAdj[q], *ncind; 575*a38eeca9SJames Wright PetscInt ndof, ncdof, ngoff, nd, count; 576cb1e1211SMatthew G Knepley 577cb1e1211SMatthew G Knepley /* Adjacent points may not be in the section chart */ 578cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 5799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 5809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 5819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, padj, &ncind)); 5829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, padj, &ngoff)); 583*a38eeca9SJames Wright // If leaf-root pair are both on this rank, only count root 584*a38eeca9SJames Wright PetscCall(PetscFindInt(padj, num_exclude_leaves, exclude_leaves, &count)); 585*a38eeca9SJames Wright if (count >= 0) continue; 586ad540459SPierre Jolivet for (nd = 0; nd < ndof - ncdof; ++nd, ++i) cols[aoff + i] = ngoff < 0 ? -(ngoff + 1) + nd : ngoff + nd; 587cb1e1211SMatthew G Knepley } 588ad540459SPierre Jolivet for (q = 0; q < anDof; q++, i++) cols[aoff + i] = anchorAdj[anOff + q]; 58963a3b9bcSJacob Faibussowitsch PetscCheck(i == adof, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %" PetscInt_FMT " != %" PetscInt_FMT " for dof %" PetscInt_FMT " (point %" PetscInt_FMT ")", i, adof, d, p); 590cb1e1211SMatthew G Knepley } 591cb1e1211SMatthew G Knepley } 5929566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&anchorSectionAdj)); 5939566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSectionAdj)); 5949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSectionAdj)); 595*a38eeca9SJames Wright PetscCall(PetscFree(exclude_leaves)); 596*a38eeca9SJames Wright PetscCall(PetscFree2(rootsMyRankPair, leavesMyRankPair)); 5979566063dSJacob Faibussowitsch PetscCall(PetscFree(anchorAdj)); 5989566063dSJacob Faibussowitsch PetscCall(PetscFree(rootAdj)); 5999566063dSJacob Faibussowitsch PetscCall(PetscFree(tmpAdj)); 600cb1e1211SMatthew G Knepley /* Debugging */ 601cb1e1211SMatthew G Knepley if (debug) { 6029566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Column indices\n")); 6036a1a2f7bSJames Wright PetscCall(PetscSectionArrayView(sectionAdj, cols, PETSC_INT, NULL)); 604cb1e1211SMatthew G Knepley } 605a9fb6443SMatthew G. Knepley 606a9fb6443SMatthew G. Knepley *sA = sectionAdj; 607a9fb6443SMatthew G. Knepley *colIdx = cols; 6083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 609a9fb6443SMatthew G. Knepley } 610a9fb6443SMatthew G. Knepley 611d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexUpdateAllocation_Static(DM dm, PetscLayout rLayout, PetscInt bs, PetscInt f, PetscSection sectionAdj, const PetscInt cols[], PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[]) 612d71ae5a4SJacob Faibussowitsch { 613e101f074SMatthew G. Knepley PetscSection section; 614a9fb6443SMatthew G. Knepley PetscInt rStart, rEnd, r, pStart, pEnd, p; 615a9fb6443SMatthew G. Knepley 616a9fb6443SMatthew G. Knepley PetscFunctionBegin; 617a9fb6443SMatthew G. Knepley /* This loop needs to change to a loop over points, then field dofs, which means we need to look both sections */ 6189566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, &rEnd)); 6191dca8a05SBarry Smith PetscCheck((rStart % bs) == 0 && (rEnd % bs) == 0, PetscObjectComm((PetscObject)rLayout), PETSC_ERR_ARG_WRONG, "Invalid layout [%" PetscInt_FMT ", %" PetscInt_FMT ") for matrix, must be divisible by block size %" PetscInt_FMT, rStart, rEnd, bs); 620a9fb6443SMatthew G. Knepley if (f >= 0 && bs == 1) { 6219566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 6229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 623a9fb6443SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 624294b7009SMatthew G. Knepley PetscInt rS, rE; 625a9fb6443SMatthew G. Knepley 6269566063dSJacob Faibussowitsch PetscCall(DMGetGlobalFieldOffset_Private(dm, p, f, &rS, &rE)); 627a9fb6443SMatthew G. Knepley for (r = rS; r < rE; ++r) { 628a9fb6443SMatthew G. Knepley PetscInt numCols, cStart, c; 629a9fb6443SMatthew G. Knepley 6309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, r, &numCols)); 6319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, r, &cStart)); 632a9fb6443SMatthew G. Knepley for (c = cStart; c < cStart + numCols; ++c) { 633a9fb6443SMatthew G. Knepley if ((cols[c] >= rStart) && (cols[c] < rEnd)) { 634a9fb6443SMatthew G. Knepley ++dnz[r - rStart]; 635a9fb6443SMatthew G. Knepley if (cols[c] >= r) ++dnzu[r - rStart]; 636a9fb6443SMatthew G. Knepley } else { 637a9fb6443SMatthew G. Knepley ++onz[r - rStart]; 638a9fb6443SMatthew G. Knepley if (cols[c] >= r) ++onzu[r - rStart]; 639a9fb6443SMatthew G. Knepley } 640a9fb6443SMatthew G. Knepley } 641a9fb6443SMatthew G. Knepley } 642a9fb6443SMatthew G. Knepley } 643a9fb6443SMatthew G. Knepley } else { 644cb1e1211SMatthew G Knepley /* Only loop over blocks of rows */ 645cb1e1211SMatthew G Knepley for (r = rStart / bs; r < rEnd / bs; ++r) { 646cb1e1211SMatthew G Knepley const PetscInt row = r * bs; 647cb1e1211SMatthew G Knepley PetscInt numCols, cStart, c; 648cb1e1211SMatthew G Knepley 6499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, row, &numCols)); 6509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, row, &cStart)); 651cb1e1211SMatthew G Knepley for (c = cStart; c < cStart + numCols; ++c) { 652e7bcfa36SMatthew G. Knepley if ((cols[c] >= rStart) && (cols[c] < rEnd)) { 653e7bcfa36SMatthew G. Knepley ++dnz[r - rStart / bs]; 654e7bcfa36SMatthew G. Knepley if (cols[c] >= row) ++dnzu[r - rStart / bs]; 655cb1e1211SMatthew G Knepley } else { 656e7bcfa36SMatthew G. Knepley ++onz[r - rStart / bs]; 657e7bcfa36SMatthew G. Knepley if (cols[c] >= row) ++onzu[r - rStart / bs]; 658cb1e1211SMatthew G Knepley } 659cb1e1211SMatthew G Knepley } 660cb1e1211SMatthew G Knepley } 661a9fb6443SMatthew G. Knepley for (r = 0; r < (rEnd - rStart) / bs; ++r) { 662cb1e1211SMatthew G Knepley dnz[r] /= bs; 663cb1e1211SMatthew G Knepley onz[r] /= bs; 664cb1e1211SMatthew G Knepley dnzu[r] /= bs; 665cb1e1211SMatthew G Knepley onzu[r] /= bs; 666cb1e1211SMatthew G Knepley } 667cb1e1211SMatthew G Knepley } 6683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 669a9fb6443SMatthew G. Knepley } 670a9fb6443SMatthew G. Knepley 671d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexFillMatrix_Static(DM dm, PetscLayout rLayout, PetscInt bs, PetscInt f, PetscSection sectionAdj, const PetscInt cols[], Mat A) 672d71ae5a4SJacob Faibussowitsch { 673e101f074SMatthew G. Knepley PetscSection section; 674a9fb6443SMatthew G. Knepley PetscScalar *values; 675a9fb6443SMatthew G. Knepley PetscInt rStart, rEnd, r, pStart, pEnd, p, len, maxRowLen = 0; 676a9fb6443SMatthew G. Knepley 677a9fb6443SMatthew G. Knepley PetscFunctionBegin; 6789566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, &rEnd)); 679a9fb6443SMatthew G. Knepley for (r = rStart; r < rEnd; ++r) { 6809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, r, &len)); 681a9fb6443SMatthew G. Knepley maxRowLen = PetscMax(maxRowLen, len); 682a9fb6443SMatthew G. Knepley } 6839566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxRowLen, &values)); 684a9fb6443SMatthew G. Knepley if (f >= 0 && bs == 1) { 6859566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 6869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 687a9fb6443SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 688294b7009SMatthew G. Knepley PetscInt rS, rE; 689a9fb6443SMatthew G. Knepley 6909566063dSJacob Faibussowitsch PetscCall(DMGetGlobalFieldOffset_Private(dm, p, f, &rS, &rE)); 691a9fb6443SMatthew G. Knepley for (r = rS; r < rE; ++r) { 6927e01ee02SMatthew G. Knepley PetscInt numCols, cStart; 693a9fb6443SMatthew G. Knepley 6949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, r, &numCols)); 6959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, r, &cStart)); 6969566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES)); 697a9fb6443SMatthew G. Knepley } 698a9fb6443SMatthew G. Knepley } 699a9fb6443SMatthew G. Knepley } else { 700a9fb6443SMatthew G. Knepley for (r = rStart; r < rEnd; ++r) { 701a9fb6443SMatthew G. Knepley PetscInt numCols, cStart; 702a9fb6443SMatthew G. Knepley 7039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, r, &numCols)); 7049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, r, &cStart)); 7059566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES)); 706a9fb6443SMatthew G. Knepley } 707a9fb6443SMatthew G. Knepley } 7089566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 7093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 710a9fb6443SMatthew G. Knepley } 711a9fb6443SMatthew G. Knepley 712cc4c1da9SBarry Smith /*@ 713a1cb98faSBarry Smith DMPlexPreallocateOperator - Calculate the matrix nonzero pattern based upon the information in the `DM`, 714a1cb98faSBarry Smith the `PetscDS` it contains, and the default `PetscSection`. 71525e402d2SMatthew G. Knepley 71625e402d2SMatthew G. Knepley Collective 71725e402d2SMatthew G. Knepley 7184165533cSJose E. Roman Input Parameters: 719a1cb98faSBarry Smith + dm - The `DMPLEX` 72025e402d2SMatthew G. Knepley . bs - The matrix blocksize 72125e402d2SMatthew G. Knepley . dnz - An array to hold the number of nonzeros in the diagonal block 72225e402d2SMatthew G. Knepley . onz - An array to hold the number of nonzeros in the off-diagonal block 72325e402d2SMatthew G. Knepley . dnzu - An array to hold the number of nonzeros in the upper triangle of the diagonal block 72425e402d2SMatthew G. Knepley . onzu - An array to hold the number of nonzeros in the upper triangle of the off-diagonal block 725a1cb98faSBarry Smith - fillMatrix - If `PETSC_TRUE`, fill the matrix with zeros 72625e402d2SMatthew G. Knepley 7274165533cSJose E. Roman Output Parameter: 72825e402d2SMatthew G. Knepley . A - The preallocated matrix 72925e402d2SMatthew G. Knepley 73025e402d2SMatthew G. Knepley Level: advanced 73125e402d2SMatthew G. Knepley 7321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreateMatrix()` 73325e402d2SMatthew G. Knepley @*/ 734d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 735d71ae5a4SJacob Faibussowitsch { 736a9fb6443SMatthew G. Knepley MPI_Comm comm; 737a9fb6443SMatthew G. Knepley MatType mtype; 738a9fb6443SMatthew G. Knepley PetscSF sf, sfDof; 739e101f074SMatthew G. Knepley PetscSection section; 740a9fb6443SMatthew G. Knepley PetscInt *remoteOffsets; 741a9fb6443SMatthew G. Knepley PetscSection sectionAdj[4] = {NULL, NULL, NULL, NULL}; 742a9fb6443SMatthew G. Knepley PetscInt *cols[4] = {NULL, NULL, NULL, NULL}; 743a9fb6443SMatthew G. Knepley PetscBool useCone, useClosure; 7447e01ee02SMatthew G. Knepley PetscInt Nf, f, idx, locRows; 745a9fb6443SMatthew G. Knepley PetscLayout rLayout; 746a9fb6443SMatthew G. Knepley PetscBool isSymBlock, isSymSeqBlock, isSymMPIBlock, debug = PETSC_FALSE; 747a9fb6443SMatthew G. Knepley 748a9fb6443SMatthew G. Knepley PetscFunctionBegin; 749a9fb6443SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 750064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 7514f572ea9SToby Isaac if (dnz) PetscAssertPointer(dnz, 3); 7524f572ea9SToby Isaac if (onz) PetscAssertPointer(onz, 4); 7534f572ea9SToby Isaac if (dnzu) PetscAssertPointer(dnzu, 5); 7544f572ea9SToby Isaac if (onzu) PetscAssertPointer(onzu, 6); 755*a38eeca9SJames Wright PetscCall(DMGetIsoperiodicPointSF_Internal(dm, &sf)); 7569566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 7579566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_view_preallocation", &debug, NULL)); 7589566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 7599566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Preallocate, dm, 0, 0, 0)); 760a9fb6443SMatthew G. Knepley /* Create dof SF based on point SF */ 761a9fb6443SMatthew G. Knepley if (debug) { 762e101f074SMatthew G. Knepley PetscSection section, sectionGlobal; 763a9fb6443SMatthew G. Knepley PetscSF sf; 764a9fb6443SMatthew G. Knepley 765*a38eeca9SJames Wright PetscCall(DMGetIsoperiodicPointSF_Internal(dm, &sf)); 7669566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 7679566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 7689566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Input Section for Preallocation:\n")); 7699566063dSJacob Faibussowitsch PetscCall(PetscSectionView(section, NULL)); 7709566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Input Global Section for Preallocation:\n")); 7719566063dSJacob Faibussowitsch PetscCall(PetscSectionView(sectionGlobal, NULL)); 7729566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Input SF for Preallocation:\n")); 7739566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, NULL)); 774a9fb6443SMatthew G. Knepley } 7759566063dSJacob Faibussowitsch PetscCall(PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets)); 7769566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof)); 7779566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 7786a1a2f7bSJames Wright if (debug) { 7799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Dof SF for Preallocation:\n")); 7809566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfDof, NULL)); 781a9fb6443SMatthew G. Knepley } 782a9fb6443SMatthew G. Knepley /* Create allocation vectors from adjacency graph */ 7839566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &locRows, NULL)); 7849566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &rLayout)); 7859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 7869566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1)); 7879566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout)); 788a9fb6443SMatthew G. Knepley /* There are 4 types of adjacency */ 7899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 790a9fb6443SMatthew G. Knepley if (Nf < 1 || bs > 1) { 7919566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 792a9fb6443SMatthew G. Knepley idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 7939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateAdjacencySection_Static(dm, bs, sfDof, useCone, useClosure, PETSC_TRUE, §ionAdj[idx], &cols[idx])); 7949566063dSJacob Faibussowitsch PetscCall(DMPlexUpdateAllocation_Static(dm, rLayout, bs, -1, sectionAdj[idx], cols[idx], dnz, onz, dnzu, onzu)); 795a9fb6443SMatthew G. Knepley } else { 796a9fb6443SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 7979566063dSJacob Faibussowitsch PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure)); 798a9fb6443SMatthew G. Knepley idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 7999566063dSJacob Faibussowitsch if (!sectionAdj[idx]) PetscCall(DMPlexCreateAdjacencySection_Static(dm, bs, sfDof, useCone, useClosure, PETSC_TRUE, §ionAdj[idx], &cols[idx])); 8009566063dSJacob Faibussowitsch PetscCall(DMPlexUpdateAllocation_Static(dm, rLayout, bs, f, sectionAdj[idx], cols[idx], dnz, onz, dnzu, onzu)); 801a9fb6443SMatthew G. Knepley } 802a9fb6443SMatthew G. Knepley } 8039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfDof)); 804cb1e1211SMatthew G Knepley /* Set matrix pattern */ 8059566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu)); 8069566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 80789545effSMatthew G. Knepley /* Check for symmetric storage */ 8089566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mtype)); 8099566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 8109566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 8119566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 8129566063dSJacob Faibussowitsch if (isSymBlock || isSymSeqBlock || isSymMPIBlock) PetscCall(MatSetOption(A, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE)); 813cb1e1211SMatthew G Knepley /* Fill matrix with zeros */ 814cb1e1211SMatthew G Knepley if (fillMatrix) { 815a9fb6443SMatthew G. Knepley if (Nf < 1 || bs > 1) { 8169566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 817a9fb6443SMatthew G. Knepley idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 8189566063dSJacob Faibussowitsch PetscCall(DMPlexFillMatrix_Static(dm, rLayout, bs, -1, sectionAdj[idx], cols[idx], A)); 819a9fb6443SMatthew G. Knepley } else { 820a9fb6443SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 8219566063dSJacob Faibussowitsch PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure)); 822a9fb6443SMatthew G. Knepley idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 8239566063dSJacob Faibussowitsch PetscCall(DMPlexFillMatrix_Static(dm, rLayout, bs, f, sectionAdj[idx], cols[idx], A)); 824cb1e1211SMatthew G Knepley } 825cb1e1211SMatthew G Knepley } 8269566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 8279566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 828cb1e1211SMatthew G Knepley } 8299566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout)); 8309371c9d4SSatish Balay for (idx = 0; idx < 4; ++idx) { 8319371c9d4SSatish Balay PetscCall(PetscSectionDestroy(§ionAdj[idx])); 8329371c9d4SSatish Balay PetscCall(PetscFree(cols[idx])); 8339371c9d4SSatish Balay } 8349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Preallocate, dm, 0, 0, 0)); 8353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 836cb1e1211SMatthew G Knepley } 837cb1e1211SMatthew G Knepley 838cb1e1211SMatthew G Knepley #if 0 839cb1e1211SMatthew G Knepley PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 840cb1e1211SMatthew G Knepley { 841cb1e1211SMatthew G Knepley PetscInt *tmpClosure,*tmpAdj,*visits; 842cb1e1211SMatthew G Knepley PetscInt c,cStart,cEnd,pStart,pEnd; 843cb1e1211SMatthew G Knepley 844cb1e1211SMatthew G Knepley PetscFunctionBegin; 8459566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8479566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 848cb1e1211SMatthew G Knepley 849e7b80042SMatthew G. Knepley maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)); 850cb1e1211SMatthew G Knepley 8519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 852cb1e1211SMatthew G Knepley npoints = pEnd - pStart; 853cb1e1211SMatthew G Knepley 8549566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxClosureSize,&tmpClosure,npoints,&lvisits,npoints,&visits)); 8559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(lvisits,pEnd-pStart)); 8569566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(visits,pEnd-pStart)); 8579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 858cb1e1211SMatthew G Knepley for (c=cStart; c<cEnd; c++) { 859cb1e1211SMatthew G Knepley PetscInt *support = tmpClosure; 8609566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support)); 861cb1e1211SMatthew G Knepley for (p=0; p<supportSize; p++) lvisits[support[p]]++; 862cb1e1211SMatthew G Knepley } 8639566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM)); 8649566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM)); 8659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits,MPI_REPLACE)); 8669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits)); 867cb1e1211SMatthew G Knepley 8689566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks()); 869cb1e1211SMatthew G Knepley 8709566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxClosureSize*maxClosureSize,&cellmat,npoints,&owner)); 871cb1e1211SMatthew G Knepley for (c=cStart; c<cEnd; c++) { 8729566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(cellmat,maxClosureSize*maxClosureSize)); 873cb1e1211SMatthew G Knepley /* 874cb1e1211SMatthew G Knepley Depth-first walk of transitive closure. 875cb1e1211SMatthew G Knepley At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 876cb1e1211SMatthew G Knepley This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 877cb1e1211SMatthew G Knepley */ 878cb1e1211SMatthew G Knepley } 879cb1e1211SMatthew G Knepley 8809566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM)); 8819566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM)); 8823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 883cb1e1211SMatthew G Knepley } 884cb1e1211SMatthew G Knepley #endif 885