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 } 1369566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&aDof, &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; 15176185916SToby Isaac PetscFunctionReturn(0); 15276185916SToby Isaac } 15376185916SToby Isaac 154d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateAdjacencySection_Static(DM dm, PetscInt bs, PetscSF sfDof, PetscBool useCone, PetscBool useClosure, PetscBool useAnchors, PetscSection *sA, PetscInt **colIdx) 155d71ae5a4SJacob Faibussowitsch { 156cb1e1211SMatthew G Knepley MPI_Comm comm; 157a9fb6443SMatthew G. Knepley PetscMPIInt size; 158a9fb6443SMatthew G. Knepley PetscBool doCommLocal, doComm, debug = PETSC_FALSE; 159a9fb6443SMatthew G. Knepley PetscSF sf, sfAdj; 160e101f074SMatthew G. Knepley PetscSection section, sectionGlobal, leafSectionAdj, rootSectionAdj, sectionAdj, anchorSectionAdj; 161a9fb6443SMatthew G. Knepley PetscInt nroots, nleaves, l, p, r; 162cb1e1211SMatthew G Knepley const PetscInt *leaves; 163cb1e1211SMatthew G Knepley const PetscSFNode *remotes; 164cb1e1211SMatthew G Knepley PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 1658821704fSMatthew G. Knepley PetscInt *tmpAdj = NULL, *adj, *rootAdj, *anchorAdj = NULL, *cols, *remoteOffsets; 16670034214SMatthew G. Knepley PetscInt adjSize; 167cb1e1211SMatthew G Knepley 168cb1e1211SMatthew G Knepley PetscFunctionBegin; 1699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1709566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_view_preallocation", &debug, NULL)); 1719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1729566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1739566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 1749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1759566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 1769566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL)); 17747a6104aSMatthew G. Knepley doCommLocal = (size > 1) && (nroots >= 0) ? PETSC_TRUE : PETSC_FALSE; 1781c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&doCommLocal, &doComm, 1, MPIU_BOOL, MPI_LAND, comm)); 179cb1e1211SMatthew G Knepley /* Create section for dof adjacency (dof ==> # adj dof) */ 1809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &numDof)); 1829566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &leafSectionAdj)); 1839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSectionAdj, 0, numDof)); 1849566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSectionAdj)); 1859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSectionAdj, 0, numDof)); 186cb1e1211SMatthew G Knepley /* Fill in the ghost dofs on the interface */ 1879566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes)); 188cb1e1211SMatthew G Knepley /* 189964bf7afSMatthew G. Knepley section - maps points to (# dofs, local dofs) 190964bf7afSMatthew G. Knepley sectionGlobal - maps points to (# dofs, global dofs) 191964bf7afSMatthew G. Knepley leafSectionAdj - maps unowned local dofs to # adj dofs 192964bf7afSMatthew G. Knepley rootSectionAdj - maps owned local dofs to # adj dofs 193964bf7afSMatthew G. Knepley adj - adj global dofs indexed by leafSectionAdj 194964bf7afSMatthew G. Knepley rootAdj - adj global dofs indexed by rootSectionAdj 195964bf7afSMatthew G. Knepley sf - describes shared points across procs 196964bf7afSMatthew G. Knepley sfDof - describes shared dofs across procs 197964bf7afSMatthew G. Knepley sfAdj - describes shared adjacent dofs across procs 198cb1e1211SMatthew G Knepley ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 19976185916SToby Isaac (0). If there are point-to-point constraints, add the adjacencies of constrained points to anchors in anchorAdj 20076185916SToby Isaac (This is done in DMPlexComputeAnchorAdjacencies()) 201cb1e1211SMatthew G Knepley 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 202cb1e1211SMatthew G Knepley Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 203cb1e1211SMatthew G Knepley 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 204cb1e1211SMatthew G Knepley Create sfAdj connecting rootSectionAdj and leafSectionAdj 205cb1e1211SMatthew G Knepley 3. Visit unowned points on interface, write adjacencies to adj 206cb1e1211SMatthew G Knepley Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 207cb1e1211SMatthew G Knepley 4. Visit owned points on interface, write adjacencies to rootAdj 208cb1e1211SMatthew G Knepley Remove redundancy in rootAdj 209cb1e1211SMatthew G Knepley ** The last two traversals use transitive closure 210cb1e1211SMatthew G Knepley 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 211cb1e1211SMatthew G Knepley Allocate memory addressed by sectionAdj (cols) 212cb1e1211SMatthew G Knepley 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 213cb1e1211SMatthew G Knepley ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 214cb1e1211SMatthew G Knepley */ 2159566063dSJacob Faibussowitsch PetscCall(DMPlexComputeAnchorAdjacencies(dm, useCone, useClosure, &anchorSectionAdj, &anchorAdj)); 216cb1e1211SMatthew G Knepley for (l = 0; l < nleaves; ++l) { 21776185916SToby Isaac PetscInt dof, off, d, q, anDof; 21870034214SMatthew G. Knepley PetscInt p = leaves[l], numAdj = PETSC_DETERMINE; 219cb1e1211SMatthew G Knepley 220fb47e2feSMatthew G. Knepley if ((p < pStart) || (p >= pEnd)) continue; 2219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 2229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 224cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 225cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 226cb1e1211SMatthew G Knepley PetscInt ndof, ncdof; 227cb1e1211SMatthew G Knepley 228cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 2299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 2309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 23148a46eb9SPierre Jolivet for (d = off; d < off + dof; ++d) PetscCall(PetscSectionAddDof(leafSectionAdj, d, ndof - ncdof)); 232cb1e1211SMatthew G Knepley } 2339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 23476185916SToby Isaac if (anDof) { 23548a46eb9SPierre Jolivet for (d = off; d < off + dof; ++d) PetscCall(PetscSectionAddDof(leafSectionAdj, d, anDof)); 23676185916SToby Isaac } 237cb1e1211SMatthew G Knepley } 2389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSectionAdj)); 239cb1e1211SMatthew G Knepley if (debug) { 2409566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n")); 2419566063dSJacob Faibussowitsch PetscCall(PetscSectionView(leafSectionAdj, NULL)); 242cb1e1211SMatthew G Knepley } 243cb1e1211SMatthew G Knepley /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 24447a6104aSMatthew G. Knepley if (doComm) { 2459566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM)); 2469566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM)); 24769c11d05SVaclav Hapla PetscCall(PetscSectionInvalidateMaxDof_Internal(rootSectionAdj)); 248cb1e1211SMatthew G Knepley } 249cb1e1211SMatthew G Knepley if (debug) { 2509566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n")); 2519566063dSJacob Faibussowitsch PetscCall(PetscSectionView(rootSectionAdj, NULL)); 252cb1e1211SMatthew G Knepley } 253cb1e1211SMatthew G Knepley /* Add in local adjacency sizes for owned dofs on interface (roots) */ 254cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 25576185916SToby Isaac PetscInt numAdj = PETSC_DETERMINE, adof, dof, off, d, q, anDof; 256cb1e1211SMatthew G Knepley 2579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 2589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 259cb1e1211SMatthew G Knepley if (!dof) continue; 2609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off, &adof)); 261cb1e1211SMatthew G Knepley if (adof <= 0) continue; 2629566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 263cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 264cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 265cb1e1211SMatthew G Knepley PetscInt ndof, ncdof; 266cb1e1211SMatthew G Knepley 267cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 2689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 2699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 27048a46eb9SPierre Jolivet for (d = off; d < off + dof; ++d) PetscCall(PetscSectionAddDof(rootSectionAdj, d, ndof - ncdof)); 271cb1e1211SMatthew G Knepley } 2729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 27376185916SToby Isaac if (anDof) { 27448a46eb9SPierre Jolivet for (d = off; d < off + dof; ++d) PetscCall(PetscSectionAddDof(rootSectionAdj, d, anDof)); 27576185916SToby Isaac } 276cb1e1211SMatthew G Knepley } 2779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSectionAdj)); 278cb1e1211SMatthew G Knepley if (debug) { 2799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n")); 2809566063dSJacob Faibussowitsch PetscCall(PetscSectionView(rootSectionAdj, NULL)); 281cb1e1211SMatthew G Knepley } 282cb1e1211SMatthew G Knepley /* Create adj SF based on dof SF */ 2839566063dSJacob Faibussowitsch PetscCall(PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets)); 2849566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj)); 2859566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 2866cded2eaSMatthew G. Knepley if (debug && size > 1) { 2879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjacency SF for Preallocation:\n")); 2889566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfAdj, NULL)); 289cb1e1211SMatthew G Knepley } 290cb1e1211SMatthew G Knepley /* Create leaf adjacency */ 2919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSectionAdj)); 2929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafSectionAdj, &adjSize)); 2939566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(adjSize, &adj)); 294cb1e1211SMatthew G Knepley for (l = 0; l < nleaves; ++l) { 29576185916SToby Isaac PetscInt dof, off, d, q, anDof, anOff; 29670034214SMatthew G. Knepley PetscInt p = leaves[l], numAdj = PETSC_DETERMINE; 297cb1e1211SMatthew G Knepley 298fb47e2feSMatthew G. Knepley if ((p < pStart) || (p >= pEnd)) continue; 2999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 3009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 3019566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 3029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 3039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(anchorSectionAdj, p, &anOff)); 304cb1e1211SMatthew G Knepley for (d = off; d < off + dof; ++d) { 305cb1e1211SMatthew G Knepley PetscInt aoff, i = 0; 306cb1e1211SMatthew G Knepley 3079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSectionAdj, d, &aoff)); 308cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 309cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 310cb1e1211SMatthew G Knepley PetscInt ndof, ncdof, ngoff, nd; 311cb1e1211SMatthew G Knepley 312cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 3139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 3149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 3159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, padj, &ngoff)); 316cb1e1211SMatthew G Knepley for (nd = 0; nd < ndof - ncdof; ++nd) { 317cb1e1211SMatthew G Knepley adj[aoff + i] = (ngoff < 0 ? -(ngoff + 1) : ngoff) + nd; 318cb1e1211SMatthew G Knepley ++i; 319cb1e1211SMatthew G Knepley } 320cb1e1211SMatthew G Knepley } 32176185916SToby Isaac for (q = 0; q < anDof; q++) { 32276185916SToby Isaac adj[aoff + i] = anchorAdj[anOff + q]; 32376185916SToby Isaac ++i; 32476185916SToby Isaac } 325cb1e1211SMatthew G Knepley } 326cb1e1211SMatthew G Knepley } 327cb1e1211SMatthew G Knepley /* Debugging */ 328cb1e1211SMatthew G Knepley if (debug) { 329cb1e1211SMatthew G Knepley IS tmp; 3309566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Leaf adjacency indices\n")); 3319566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp)); 3329566063dSJacob Faibussowitsch PetscCall(ISView(tmp, NULL)); 3339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 334cb1e1211SMatthew G Knepley } 335543482b8SMatthew G. Knepley /* Gather adjacent indices to root */ 3369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSectionAdj, &adjSize)); 3379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(adjSize, &rootAdj)); 338cb1e1211SMatthew G Knepley for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 33947a6104aSMatthew G. Knepley if (doComm) { 340543482b8SMatthew G. Knepley const PetscInt *indegree; 341543482b8SMatthew G. Knepley PetscInt *remoteadj, radjsize = 0; 342543482b8SMatthew G. Knepley 3439566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sfAdj, &indegree)); 3449566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sfAdj, &indegree)); 345543482b8SMatthew G. Knepley for (p = 0; p < adjSize; ++p) radjsize += indegree[p]; 3469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(radjsize, &remoteadj)); 3479566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sfAdj, MPIU_INT, adj, remoteadj)); 3489566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sfAdj, MPIU_INT, adj, remoteadj)); 3496dba2905SMatthew G. Knepley for (p = 0, l = 0, r = 0; p < adjSize; ++p, l = PetscMax(p, l + indegree[p - 1])) { 350543482b8SMatthew G. Knepley PetscInt s; 3516dba2905SMatthew G. Knepley for (s = 0; s < indegree[p]; ++s, ++r) rootAdj[l + s] = remoteadj[r]; 352543482b8SMatthew G. Knepley } 35363a3b9bcSJacob Faibussowitsch PetscCheck(r == radjsize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistency in communication %" PetscInt_FMT " != %" PetscInt_FMT, r, radjsize); 35463a3b9bcSJacob Faibussowitsch PetscCheck(l == adjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistency in communication %" PetscInt_FMT " != %" PetscInt_FMT, l, adjSize); 3559566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteadj)); 356cb1e1211SMatthew G Knepley } 3579566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfAdj)); 3589566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 359cb1e1211SMatthew G Knepley /* Debugging */ 360cb1e1211SMatthew G Knepley if (debug) { 361cb1e1211SMatthew G Knepley IS tmp; 3629566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Root adjacency indices after gather\n")); 3639566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp)); 3649566063dSJacob Faibussowitsch PetscCall(ISView(tmp, NULL)); 3659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 366cb1e1211SMatthew G Knepley } 367cb1e1211SMatthew G Knepley /* Add in local adjacency indices for owned dofs on interface (roots) */ 368cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 36976185916SToby Isaac PetscInt numAdj = PETSC_DETERMINE, adof, dof, off, d, q, anDof, anOff; 370cb1e1211SMatthew G Knepley 3719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 3729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 373cb1e1211SMatthew G Knepley if (!dof) continue; 3749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off, &adof)); 375cb1e1211SMatthew G Knepley if (adof <= 0) continue; 3769566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 3779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 3789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(anchorSectionAdj, p, &anOff)); 379cb1e1211SMatthew G Knepley for (d = off; d < off + dof; ++d) { 380cb1e1211SMatthew G Knepley PetscInt adof, aoff, i; 381cb1e1211SMatthew G Knepley 3829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, d, &adof)); 3839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSectionAdj, d, &aoff)); 384cb1e1211SMatthew G Knepley i = adof - 1; 38576185916SToby Isaac for (q = 0; q < anDof; q++) { 38676185916SToby Isaac rootAdj[aoff + i] = anchorAdj[anOff + q]; 38776185916SToby Isaac --i; 38876185916SToby Isaac } 389cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 390cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 391cb1e1211SMatthew G Knepley PetscInt ndof, ncdof, ngoff, nd; 392cb1e1211SMatthew G Knepley 393cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 3949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 3959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 3969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, padj, &ngoff)); 397cb1e1211SMatthew G Knepley for (nd = 0; nd < ndof - ncdof; ++nd) { 398cb1e1211SMatthew G Knepley rootAdj[aoff + i] = ngoff < 0 ? -(ngoff + 1) + nd : ngoff + nd; 399cb1e1211SMatthew G Knepley --i; 400cb1e1211SMatthew G Knepley } 401cb1e1211SMatthew G Knepley } 402cb1e1211SMatthew G Knepley } 403cb1e1211SMatthew G Knepley } 404cb1e1211SMatthew G Knepley /* Debugging */ 405cb1e1211SMatthew G Knepley if (debug) { 406cb1e1211SMatthew G Knepley IS tmp; 4079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Root adjacency indices\n")); 4089566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp)); 4099566063dSJacob Faibussowitsch PetscCall(ISView(tmp, NULL)); 4109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 411cb1e1211SMatthew G Knepley } 412cb1e1211SMatthew G Knepley /* Compress indices */ 4139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSectionAdj)); 414cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 415cb1e1211SMatthew G Knepley PetscInt dof, cdof, off, d; 416cb1e1211SMatthew G Knepley PetscInt adof, aoff; 417cb1e1211SMatthew G Knepley 4189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 4199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 4209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 421cb1e1211SMatthew G Knepley if (!dof) continue; 4229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off, &adof)); 423cb1e1211SMatthew G Knepley if (adof <= 0) continue; 424cb1e1211SMatthew G Knepley for (d = off; d < off + dof - cdof; ++d) { 4259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, d, &adof)); 4269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSectionAdj, d, &aoff)); 4279566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&adof, &rootAdj[aoff])); 4289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootSectionAdj, d, adof)); 429cb1e1211SMatthew G Knepley } 430cb1e1211SMatthew G Knepley } 431cb1e1211SMatthew G Knepley /* Debugging */ 432cb1e1211SMatthew G Knepley if (debug) { 433cb1e1211SMatthew G Knepley IS tmp; 4349566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n")); 4359566063dSJacob Faibussowitsch PetscCall(PetscSectionView(rootSectionAdj, NULL)); 4369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Root adjacency indices after compression\n")); 4379566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp)); 4389566063dSJacob Faibussowitsch PetscCall(ISView(tmp, NULL)); 4399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 440cb1e1211SMatthew G Knepley } 441cb1e1211SMatthew G Knepley /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 4429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd)); 4439566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, §ionAdj)); 4449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd)); 445cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 44676185916SToby Isaac PetscInt numAdj = PETSC_DETERMINE, dof, cdof, off, goff, d, q, anDof; 447cb1e1211SMatthew G Knepley PetscBool found = PETSC_TRUE; 448cb1e1211SMatthew G Knepley 4499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 4509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 4519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 4529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff)); 453cb1e1211SMatthew G Knepley for (d = 0; d < dof - cdof; ++d) { 454cb1e1211SMatthew G Knepley PetscInt ldof, rdof; 455cb1e1211SMatthew G Knepley 4569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSectionAdj, off + d, &ldof)); 4579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off + d, &rdof)); 458cb1e1211SMatthew G Knepley if (ldof > 0) { 459cb1e1211SMatthew G Knepley /* We do not own this point */ 460cb1e1211SMatthew G Knepley } else if (rdof > 0) { 4619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sectionAdj, goff + d, rdof)); 462cb1e1211SMatthew G Knepley } else { 463cb1e1211SMatthew G Knepley found = PETSC_FALSE; 464cb1e1211SMatthew G Knepley } 465cb1e1211SMatthew G Knepley } 466cb1e1211SMatthew G Knepley if (found) continue; 4679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 4689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff)); 4699566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 470cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 471cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 472cb1e1211SMatthew G Knepley PetscInt ndof, ncdof, noff; 473cb1e1211SMatthew G Knepley 474cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 4759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 4769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 4779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, padj, &noff)); 47848a46eb9SPierre Jolivet for (d = goff; d < goff + dof - cdof; ++d) PetscCall(PetscSectionAddDof(sectionAdj, d, ndof - ncdof)); 479cb1e1211SMatthew G Knepley } 4809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 48176185916SToby Isaac if (anDof) { 48248a46eb9SPierre Jolivet for (d = goff; d < goff + dof - cdof; ++d) PetscCall(PetscSectionAddDof(sectionAdj, d, anDof)); 48376185916SToby Isaac } 484cb1e1211SMatthew G Knepley } 4859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sectionAdj)); 486cb1e1211SMatthew G Knepley if (debug) { 4879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Adjacency Section for Preallocation:\n")); 4889566063dSJacob Faibussowitsch PetscCall(PetscSectionView(sectionAdj, NULL)); 489cb1e1211SMatthew G Knepley } 490cb1e1211SMatthew G Knepley /* Get adjacent indices */ 4919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sectionAdj, &numCols)); 4929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCols, &cols)); 493cb1e1211SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 49476185916SToby Isaac PetscInt numAdj = PETSC_DETERMINE, dof, cdof, off, goff, d, q, anDof, anOff; 495cb1e1211SMatthew G Knepley PetscBool found = PETSC_TRUE; 496cb1e1211SMatthew G Knepley 4979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 4989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 4999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff)); 501cb1e1211SMatthew G Knepley for (d = 0; d < dof - cdof; ++d) { 502cb1e1211SMatthew G Knepley PetscInt ldof, rdof; 503cb1e1211SMatthew G Knepley 5049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSectionAdj, off + d, &ldof)); 5059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSectionAdj, off + d, &rdof)); 506cb1e1211SMatthew G Knepley if (ldof > 0) { 507cb1e1211SMatthew G Knepley /* We do not own this point */ 508cb1e1211SMatthew G Knepley } else if (rdof > 0) { 509cb1e1211SMatthew G Knepley PetscInt aoff, roff; 510cb1e1211SMatthew G Knepley 5119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, goff + d, &aoff)); 5129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSectionAdj, off + d, &roff)); 5139566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&cols[aoff], &rootAdj[roff], rdof)); 514cb1e1211SMatthew G Knepley } else { 515cb1e1211SMatthew G Knepley found = PETSC_FALSE; 516cb1e1211SMatthew G Knepley } 517cb1e1211SMatthew G Knepley } 518cb1e1211SMatthew G Knepley if (found) continue; 5199566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj)); 5209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSectionAdj, p, &anDof)); 5219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(anchorSectionAdj, p, &anOff)); 522cb1e1211SMatthew G Knepley for (d = goff; d < goff + dof - cdof; ++d) { 523cb1e1211SMatthew G Knepley PetscInt adof, aoff, i = 0; 524cb1e1211SMatthew G Knepley 5259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, d, &adof)); 5269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, d, &aoff)); 527cb1e1211SMatthew G Knepley for (q = 0; q < numAdj; ++q) { 528cb1e1211SMatthew G Knepley const PetscInt padj = tmpAdj[q]; 529cb1e1211SMatthew G Knepley PetscInt ndof, ncdof, ngoff, nd; 530cb1e1211SMatthew G Knepley const PetscInt *ncind; 531cb1e1211SMatthew G Knepley 532cb1e1211SMatthew G Knepley /* Adjacent points may not be in the section chart */ 533cb1e1211SMatthew G Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 5349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, padj, &ndof)); 5359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, padj, &ncdof)); 5369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, padj, &ncind)); 5379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, padj, &ngoff)); 538ad540459SPierre Jolivet for (nd = 0; nd < ndof - ncdof; ++nd, ++i) cols[aoff + i] = ngoff < 0 ? -(ngoff + 1) + nd : ngoff + nd; 539cb1e1211SMatthew G Knepley } 540ad540459SPierre Jolivet for (q = 0; q < anDof; q++, i++) cols[aoff + i] = anchorAdj[anOff + q]; 54163a3b9bcSJacob 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); 542cb1e1211SMatthew G Knepley } 543cb1e1211SMatthew G Knepley } 5449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&anchorSectionAdj)); 5459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSectionAdj)); 5469566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSectionAdj)); 5479566063dSJacob Faibussowitsch PetscCall(PetscFree(anchorAdj)); 5489566063dSJacob Faibussowitsch PetscCall(PetscFree(rootAdj)); 5499566063dSJacob Faibussowitsch PetscCall(PetscFree(tmpAdj)); 550cb1e1211SMatthew G Knepley /* Debugging */ 551cb1e1211SMatthew G Knepley if (debug) { 552cb1e1211SMatthew G Knepley IS tmp; 5539566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Column indices\n")); 5549566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp)); 5559566063dSJacob Faibussowitsch PetscCall(ISView(tmp, NULL)); 5569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 557cb1e1211SMatthew G Knepley } 558a9fb6443SMatthew G. Knepley 559a9fb6443SMatthew G. Knepley *sA = sectionAdj; 560a9fb6443SMatthew G. Knepley *colIdx = cols; 561a9fb6443SMatthew G. Knepley PetscFunctionReturn(0); 562a9fb6443SMatthew G. Knepley } 563a9fb6443SMatthew G. Knepley 564d71ae5a4SJacob 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[]) 565d71ae5a4SJacob Faibussowitsch { 566e101f074SMatthew G. Knepley PetscSection section; 567a9fb6443SMatthew G. Knepley PetscInt rStart, rEnd, r, pStart, pEnd, p; 568a9fb6443SMatthew G. Knepley 569a9fb6443SMatthew G. Knepley PetscFunctionBegin; 570a9fb6443SMatthew G. Knepley /* This loop needs to change to a loop over points, then field dofs, which means we need to look both sections */ 5719566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, &rEnd)); 5721dca8a05SBarry 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); 573a9fb6443SMatthew G. Knepley if (f >= 0 && bs == 1) { 5749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 5759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 576a9fb6443SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 577294b7009SMatthew G. Knepley PetscInt rS, rE; 578a9fb6443SMatthew G. Knepley 5799566063dSJacob Faibussowitsch PetscCall(DMGetGlobalFieldOffset_Private(dm, p, f, &rS, &rE)); 580a9fb6443SMatthew G. Knepley for (r = rS; r < rE; ++r) { 581a9fb6443SMatthew G. Knepley PetscInt numCols, cStart, c; 582a9fb6443SMatthew G. Knepley 5839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, r, &numCols)); 5849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, r, &cStart)); 585a9fb6443SMatthew G. Knepley for (c = cStart; c < cStart + numCols; ++c) { 586a9fb6443SMatthew G. Knepley if ((cols[c] >= rStart) && (cols[c] < rEnd)) { 587a9fb6443SMatthew G. Knepley ++dnz[r - rStart]; 588a9fb6443SMatthew G. Knepley if (cols[c] >= r) ++dnzu[r - rStart]; 589a9fb6443SMatthew G. Knepley } else { 590a9fb6443SMatthew G. Knepley ++onz[r - rStart]; 591a9fb6443SMatthew G. Knepley if (cols[c] >= r) ++onzu[r - rStart]; 592a9fb6443SMatthew G. Knepley } 593a9fb6443SMatthew G. Knepley } 594a9fb6443SMatthew G. Knepley } 595a9fb6443SMatthew G. Knepley } 596a9fb6443SMatthew G. Knepley } else { 597cb1e1211SMatthew G Knepley /* Only loop over blocks of rows */ 598cb1e1211SMatthew G Knepley for (r = rStart / bs; r < rEnd / bs; ++r) { 599cb1e1211SMatthew G Knepley const PetscInt row = r * bs; 600cb1e1211SMatthew G Knepley PetscInt numCols, cStart, c; 601cb1e1211SMatthew G Knepley 6029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, row, &numCols)); 6039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, row, &cStart)); 604cb1e1211SMatthew G Knepley for (c = cStart; c < cStart + numCols; ++c) { 605e7bcfa36SMatthew G. Knepley if ((cols[c] >= rStart) && (cols[c] < rEnd)) { 606e7bcfa36SMatthew G. Knepley ++dnz[r - rStart / bs]; 607e7bcfa36SMatthew G. Knepley if (cols[c] >= row) ++dnzu[r - rStart / bs]; 608cb1e1211SMatthew G Knepley } else { 609e7bcfa36SMatthew G. Knepley ++onz[r - rStart / bs]; 610e7bcfa36SMatthew G. Knepley if (cols[c] >= row) ++onzu[r - rStart / bs]; 611cb1e1211SMatthew G Knepley } 612cb1e1211SMatthew G Knepley } 613cb1e1211SMatthew G Knepley } 614a9fb6443SMatthew G. Knepley for (r = 0; r < (rEnd - rStart) / bs; ++r) { 615cb1e1211SMatthew G Knepley dnz[r] /= bs; 616cb1e1211SMatthew G Knepley onz[r] /= bs; 617cb1e1211SMatthew G Knepley dnzu[r] /= bs; 618cb1e1211SMatthew G Knepley onzu[r] /= bs; 619cb1e1211SMatthew G Knepley } 620cb1e1211SMatthew G Knepley } 621a9fb6443SMatthew G. Knepley PetscFunctionReturn(0); 622a9fb6443SMatthew G. Knepley } 623a9fb6443SMatthew G. Knepley 624d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexFillMatrix_Static(DM dm, PetscLayout rLayout, PetscInt bs, PetscInt f, PetscSection sectionAdj, const PetscInt cols[], Mat A) 625d71ae5a4SJacob Faibussowitsch { 626e101f074SMatthew G. Knepley PetscSection section; 627a9fb6443SMatthew G. Knepley PetscScalar *values; 628a9fb6443SMatthew G. Knepley PetscInt rStart, rEnd, r, pStart, pEnd, p, len, maxRowLen = 0; 629a9fb6443SMatthew G. Knepley 630a9fb6443SMatthew G. Knepley PetscFunctionBegin; 6319566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, &rEnd)); 632a9fb6443SMatthew G. Knepley for (r = rStart; r < rEnd; ++r) { 6339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, r, &len)); 634a9fb6443SMatthew G. Knepley maxRowLen = PetscMax(maxRowLen, len); 635a9fb6443SMatthew G. Knepley } 6369566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxRowLen, &values)); 637a9fb6443SMatthew G. Knepley if (f >= 0 && bs == 1) { 6389566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 6399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 640a9fb6443SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 641294b7009SMatthew G. Knepley PetscInt rS, rE; 642a9fb6443SMatthew G. Knepley 6439566063dSJacob Faibussowitsch PetscCall(DMGetGlobalFieldOffset_Private(dm, p, f, &rS, &rE)); 644a9fb6443SMatthew G. Knepley for (r = rS; r < rE; ++r) { 6457e01ee02SMatthew G. Knepley PetscInt numCols, cStart; 646a9fb6443SMatthew G. Knepley 6479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, r, &numCols)); 6489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, r, &cStart)); 6499566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES)); 650a9fb6443SMatthew G. Knepley } 651a9fb6443SMatthew G. Knepley } 652a9fb6443SMatthew G. Knepley } else { 653a9fb6443SMatthew G. Knepley for (r = rStart; r < rEnd; ++r) { 654a9fb6443SMatthew G. Knepley PetscInt numCols, cStart; 655a9fb6443SMatthew G. Knepley 6569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionAdj, r, &numCols)); 6579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionAdj, r, &cStart)); 6589566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES)); 659a9fb6443SMatthew G. Knepley } 660a9fb6443SMatthew G. Knepley } 6619566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 662a9fb6443SMatthew G. Knepley PetscFunctionReturn(0); 663a9fb6443SMatthew G. Knepley } 664a9fb6443SMatthew G. Knepley 66525e402d2SMatthew G. Knepley /*@C 666*a1cb98faSBarry Smith DMPlexPreallocateOperator - Calculate the matrix nonzero pattern based upon the information in the `DM`, 667*a1cb98faSBarry Smith the `PetscDS` it contains, and the default `PetscSection`. 66825e402d2SMatthew G. Knepley 66925e402d2SMatthew G. Knepley Collective 67025e402d2SMatthew G. Knepley 6714165533cSJose E. Roman Input Parameters: 672*a1cb98faSBarry Smith + dm - The `DMPLEX` 67325e402d2SMatthew G. Knepley . bs - The matrix blocksize 67425e402d2SMatthew G. Knepley . dnz - An array to hold the number of nonzeros in the diagonal block 67525e402d2SMatthew G. Knepley . onz - An array to hold the number of nonzeros in the off-diagonal block 67625e402d2SMatthew G. Knepley . dnzu - An array to hold the number of nonzeros in the upper triangle of the diagonal block 67725e402d2SMatthew G. Knepley . onzu - An array to hold the number of nonzeros in the upper triangle of the off-diagonal block 678*a1cb98faSBarry Smith - fillMatrix - If `PETSC_TRUE`, fill the matrix with zeros 67925e402d2SMatthew G. Knepley 6804165533cSJose E. Roman Output Parameter: 68125e402d2SMatthew G. Knepley . A - The preallocated matrix 68225e402d2SMatthew G. Knepley 68325e402d2SMatthew G. Knepley Level: advanced 68425e402d2SMatthew G. Knepley 685*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreateMatrix()` 68625e402d2SMatthew G. Knepley @*/ 687d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 688d71ae5a4SJacob Faibussowitsch { 689a9fb6443SMatthew G. Knepley MPI_Comm comm; 690a9fb6443SMatthew G. Knepley PetscDS prob; 691a9fb6443SMatthew G. Knepley MatType mtype; 692a9fb6443SMatthew G. Knepley PetscSF sf, sfDof; 693e101f074SMatthew G. Knepley PetscSection section; 694a9fb6443SMatthew G. Knepley PetscInt *remoteOffsets; 695a9fb6443SMatthew G. Knepley PetscSection sectionAdj[4] = {NULL, NULL, NULL, NULL}; 696a9fb6443SMatthew G. Knepley PetscInt *cols[4] = {NULL, NULL, NULL, NULL}; 697a9fb6443SMatthew G. Knepley PetscBool useCone, useClosure; 6987e01ee02SMatthew G. Knepley PetscInt Nf, f, idx, locRows; 699a9fb6443SMatthew G. Knepley PetscLayout rLayout; 700a9fb6443SMatthew G. Knepley PetscBool isSymBlock, isSymSeqBlock, isSymMPIBlock, debug = PETSC_FALSE; 7016cded2eaSMatthew G. Knepley PetscMPIInt size; 702a9fb6443SMatthew G. Knepley 703a9fb6443SMatthew G. Knepley PetscFunctionBegin; 704a9fb6443SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 705064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 706dadcf809SJacob Faibussowitsch if (dnz) PetscValidIntPointer(dnz, 3); 707dadcf809SJacob Faibussowitsch if (onz) PetscValidIntPointer(onz, 4); 708dadcf809SJacob Faibussowitsch if (dnzu) PetscValidIntPointer(dnzu, 5); 709dadcf809SJacob Faibussowitsch if (onzu) PetscValidIntPointer(onzu, 6); 7109566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 7119566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 7129566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 7139566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_view_preallocation", &debug, NULL)); 7149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 7159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7169566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Preallocate, dm, 0, 0, 0)); 717a9fb6443SMatthew G. Knepley /* Create dof SF based on point SF */ 718a9fb6443SMatthew G. Knepley if (debug) { 719e101f074SMatthew G. Knepley PetscSection section, sectionGlobal; 720a9fb6443SMatthew G. Knepley PetscSF sf; 721a9fb6443SMatthew G. Knepley 7229566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 7239566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 7249566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 7259566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Input Section for Preallocation:\n")); 7269566063dSJacob Faibussowitsch PetscCall(PetscSectionView(section, NULL)); 7279566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Input Global Section for Preallocation:\n")); 7289566063dSJacob Faibussowitsch PetscCall(PetscSectionView(sectionGlobal, NULL)); 7296cded2eaSMatthew G. Knepley if (size > 1) { 7309566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Input SF for Preallocation:\n")); 7319566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, NULL)); 732a9fb6443SMatthew G. Knepley } 7336cded2eaSMatthew G. Knepley } 7349566063dSJacob Faibussowitsch PetscCall(PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets)); 7359566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof)); 7369566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 7376cded2eaSMatthew G. Knepley if (debug && size > 1) { 7389566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Dof SF for Preallocation:\n")); 7399566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfDof, NULL)); 740a9fb6443SMatthew G. Knepley } 741a9fb6443SMatthew G. Knepley /* Create allocation vectors from adjacency graph */ 7429566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &locRows, NULL)); 7439566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &rLayout)); 7449566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 7459566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1)); 7469566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout)); 747a9fb6443SMatthew G. Knepley /* There are 4 types of adjacency */ 7489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 749a9fb6443SMatthew G. Knepley if (Nf < 1 || bs > 1) { 7509566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 751a9fb6443SMatthew G. Knepley idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 7529566063dSJacob Faibussowitsch PetscCall(DMPlexCreateAdjacencySection_Static(dm, bs, sfDof, useCone, useClosure, PETSC_TRUE, §ionAdj[idx], &cols[idx])); 7539566063dSJacob Faibussowitsch PetscCall(DMPlexUpdateAllocation_Static(dm, rLayout, bs, -1, sectionAdj[idx], cols[idx], dnz, onz, dnzu, onzu)); 754a9fb6443SMatthew G. Knepley } else { 755a9fb6443SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 7569566063dSJacob Faibussowitsch PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure)); 757a9fb6443SMatthew G. Knepley idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 7589566063dSJacob Faibussowitsch if (!sectionAdj[idx]) PetscCall(DMPlexCreateAdjacencySection_Static(dm, bs, sfDof, useCone, useClosure, PETSC_TRUE, §ionAdj[idx], &cols[idx])); 7599566063dSJacob Faibussowitsch PetscCall(DMPlexUpdateAllocation_Static(dm, rLayout, bs, f, sectionAdj[idx], cols[idx], dnz, onz, dnzu, onzu)); 760a9fb6443SMatthew G. Knepley } 761a9fb6443SMatthew G. Knepley } 7629566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfDof)); 763cb1e1211SMatthew G Knepley /* Set matrix pattern */ 7649566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu)); 7659566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 76689545effSMatthew G. Knepley /* Check for symmetric storage */ 7679566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mtype)); 7689566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 7699566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 7709566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 7719566063dSJacob Faibussowitsch if (isSymBlock || isSymSeqBlock || isSymMPIBlock) PetscCall(MatSetOption(A, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE)); 772cb1e1211SMatthew G Knepley /* Fill matrix with zeros */ 773cb1e1211SMatthew G Knepley if (fillMatrix) { 774a9fb6443SMatthew G. Knepley if (Nf < 1 || bs > 1) { 7759566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 776a9fb6443SMatthew G. Knepley idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 7779566063dSJacob Faibussowitsch PetscCall(DMPlexFillMatrix_Static(dm, rLayout, bs, -1, sectionAdj[idx], cols[idx], A)); 778a9fb6443SMatthew G. Knepley } else { 779a9fb6443SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 7809566063dSJacob Faibussowitsch PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure)); 781a9fb6443SMatthew G. Knepley idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 7829566063dSJacob Faibussowitsch PetscCall(DMPlexFillMatrix_Static(dm, rLayout, bs, f, sectionAdj[idx], cols[idx], A)); 783cb1e1211SMatthew G Knepley } 784cb1e1211SMatthew G Knepley } 7859566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 7869566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 787cb1e1211SMatthew G Knepley } 7889566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout)); 7899371c9d4SSatish Balay for (idx = 0; idx < 4; ++idx) { 7909371c9d4SSatish Balay PetscCall(PetscSectionDestroy(§ionAdj[idx])); 7919371c9d4SSatish Balay PetscCall(PetscFree(cols[idx])); 7929371c9d4SSatish Balay } 7939566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Preallocate, dm, 0, 0, 0)); 794cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 795cb1e1211SMatthew G Knepley } 796cb1e1211SMatthew G Knepley 797cb1e1211SMatthew G Knepley #if 0 798cb1e1211SMatthew 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) 799cb1e1211SMatthew G Knepley { 800cb1e1211SMatthew G Knepley PetscInt *tmpClosure,*tmpAdj,*visits; 801cb1e1211SMatthew G Knepley PetscInt c,cStart,cEnd,pStart,pEnd; 802cb1e1211SMatthew G Knepley 803cb1e1211SMatthew G Knepley PetscFunctionBegin; 8049566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8069566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 807cb1e1211SMatthew G Knepley 808e7b80042SMatthew G. Knepley maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)); 809cb1e1211SMatthew G Knepley 8109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 811cb1e1211SMatthew G Knepley npoints = pEnd - pStart; 812cb1e1211SMatthew G Knepley 8139566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxClosureSize,&tmpClosure,npoints,&lvisits,npoints,&visits)); 8149566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(lvisits,pEnd-pStart)); 8159566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(visits,pEnd-pStart)); 8169566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 817cb1e1211SMatthew G Knepley for (c=cStart; c<cEnd; c++) { 818cb1e1211SMatthew G Knepley PetscInt *support = tmpClosure; 8199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support)); 820cb1e1211SMatthew G Knepley for (p=0; p<supportSize; p++) lvisits[support[p]]++; 821cb1e1211SMatthew G Knepley } 8229566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM)); 8239566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM)); 8249566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits,MPI_REPLACE)); 8259566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits)); 826cb1e1211SMatthew G Knepley 8279566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks()); 828cb1e1211SMatthew G Knepley 8299566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxClosureSize*maxClosureSize,&cellmat,npoints,&owner)); 830cb1e1211SMatthew G Knepley for (c=cStart; c<cEnd; c++) { 8319566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(cellmat,maxClosureSize*maxClosureSize)); 832cb1e1211SMatthew G Knepley /* 833cb1e1211SMatthew G Knepley Depth-first walk of transitive closure. 834cb1e1211SMatthew 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. 835cb1e1211SMatthew G Knepley This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 836cb1e1211SMatthew G Knepley */ 837cb1e1211SMatthew G Knepley } 838cb1e1211SMatthew G Knepley 8399566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM)); 8409566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM)); 841cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 842cb1e1211SMatthew G Knepley } 843cb1e1211SMatthew G Knepley #endif 844