1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/isimpl.h> 3af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 4d6a7ad0dSToby Isaac #include <petscsf.h> 50c37af3bSToby Isaac #include <petscds.h> 6d6a7ad0dSToby Isaac 70e3d61c9SBarry Smith /* hierarchy routines */ 8d6a7ad0dSToby Isaac 9d6a7ad0dSToby Isaac /*@ 10d6a7ad0dSToby Isaac DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes. 11d6a7ad0dSToby Isaac 1220f4b53cSBarry Smith Not Collective 13d6a7ad0dSToby Isaac 14d6a7ad0dSToby Isaac Input Parameters: 15a1cb98faSBarry Smith + dm - The `DMPLEX` object 16a1cb98faSBarry Smith - ref - The reference tree `DMPLEX` object 17d6a7ad0dSToby Isaac 180b7167a0SToby Isaac Level: intermediate 19d6a7ad0dSToby Isaac 20a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`,`DMPlexGetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()` 21d6a7ad0dSToby Isaac @*/ 22d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 23d71ae5a4SJacob Faibussowitsch { 24d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 25d6a7ad0dSToby Isaac 26d6a7ad0dSToby Isaac PetscFunctionBegin; 27d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28ad540459SPierre Jolivet if (ref) PetscValidHeaderSpecific(ref, DM_CLASSID, 2); 299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ref)); 309566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 31d6a7ad0dSToby Isaac mesh->referenceTree = ref; 323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33d6a7ad0dSToby Isaac } 34d6a7ad0dSToby Isaac 35d6a7ad0dSToby Isaac /*@ 36d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 37d6a7ad0dSToby Isaac 3820f4b53cSBarry Smith Not Collective 39d6a7ad0dSToby Isaac 402fe279fdSBarry Smith Input Parameter: 41a1cb98faSBarry Smith . dm - The `DMPLEX` object 42d6a7ad0dSToby Isaac 432fe279fdSBarry Smith Output Parameter: 44a1cb98faSBarry Smith . ref - The reference tree `DMPLEX` object 45d6a7ad0dSToby Isaac 460b7167a0SToby Isaac Level: intermediate 47d6a7ad0dSToby Isaac 48a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()` 49d6a7ad0dSToby Isaac @*/ 50d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 51d71ae5a4SJacob Faibussowitsch { 52d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 53d6a7ad0dSToby Isaac 54d6a7ad0dSToby Isaac PetscFunctionBegin; 55d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56d6a7ad0dSToby Isaac PetscValidPointer(ref, 2); 57d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59d6a7ad0dSToby Isaac } 60d6a7ad0dSToby Isaac 61d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 62d71ae5a4SJacob Faibussowitsch { 63dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 64dcbd3bf7SToby Isaac 65dcbd3bf7SToby Isaac PetscFunctionBegin; 66dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 67dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 68dcbd3bf7SToby Isaac if (childB) *childB = childA; 693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70dcbd3bf7SToby Isaac } 71dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, &dStart, &dEnd)); 73ad540459SPierre Jolivet if (parent >= dStart && parent <= dEnd) break; 74dcbd3bf7SToby Isaac } 7563a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot perform child symmetry for %" PetscInt_FMT "-cells", dim); 7628b400f6SJacob Faibussowitsch PetscCheck(dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "A vertex has no children"); 77dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 78dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 79dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 80dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 81dcbd3bf7SToby Isaac 829566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, childA, &size)); 839566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, childA, &supp)); 84dcbd3bf7SToby Isaac 85dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 86dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 87dcbd3bf7SToby Isaac PetscInt sParent; 88dcbd3bf7SToby Isaac 89dcbd3bf7SToby Isaac sA = supp[i]; 90dcbd3bf7SToby Isaac if (sA == parent) continue; 919566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, sA, &sParent, NULL)); 92ad540459SPierre Jolivet if (sParent == parent) break; 93dcbd3bf7SToby Isaac } 9408401ef6SPierre Jolivet PetscCheck(i != size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "could not find support in children"); 95dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 96dcbd3bf7SToby Isaac * parentOrientB */ 979566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry_Default(dm, parent, parentOrientA, 0, sA, parentOrientB, &sOrientB, &sB)); 989566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, sA, &sConeSize)); 999566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sA, &coneA)); 1009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sB, &coneB)); 1019566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sA, &oA)); 1029566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sB, &oB)); 103dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 104dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 105dcbd3bf7SToby Isaac if (coneA[i] == childA) { 106dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 107dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 108dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize - (sOrientB + 1) - i) % sConeSize); 109dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 110dcbd3bf7SToby Isaac if (childOrientB) { 111b5a892a1SMatthew G. Knepley DMPolytopeType ct; 112dcbd3bf7SToby Isaac PetscInt oBtrue; 113dcbd3bf7SToby Isaac 1149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, childA, &coneSize)); 115dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 1161dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected a vertex or an edge"); 117b5a892a1SMatthew G. Knepley ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 118dcbd3bf7SToby Isaac /* we may have to flip an edge */ 119b5a892a1SMatthew G. Knepley oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientation(ct, -1, oB[j]); 120b5a892a1SMatthew G. Knepley oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 121b5a892a1SMatthew G. Knepley ABswap = DihedralSwap(coneSize, DMPolytopeConvertNewOrientation_Internal(ct, oA[i]), oBtrue); 122dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 123dcbd3bf7SToby Isaac } 124dcbd3bf7SToby Isaac break; 125dcbd3bf7SToby Isaac } 126dcbd3bf7SToby Isaac } 12708401ef6SPierre Jolivet PetscCheck(i != sConeSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "support cone mismatch"); 1283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 129dcbd3bf7SToby Isaac } 130dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 1319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 132dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 133dcbd3bf7SToby Isaac if (dim == 2) { 134dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 135dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 136dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 137dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 138dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 139dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 140947b95d8SBarry Smith } else { 141dcbd3bf7SToby Isaac ABswapVert = ABswap; 142dcbd3bf7SToby Isaac } 143dcbd3bf7SToby Isaac if (childB) { 144dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 145dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 146dcbd3bf7SToby Isaac const PetscInt *children; 147dcbd3bf7SToby Isaac 148dcbd3bf7SToby Isaac /* count which position the child is in */ 1499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, parent, &numChildren, &children)); 150dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 151dcbd3bf7SToby Isaac p = children[i]; 152dcbd3bf7SToby Isaac if (p == childA) { 153dcbd3bf7SToby Isaac posA = i; 154dcbd3bf7SToby Isaac break; 155dcbd3bf7SToby Isaac } 156dcbd3bf7SToby Isaac } 157dcbd3bf7SToby Isaac if (posA >= coneSize) { 158dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 159dcbd3bf7SToby Isaac * is invariant */ 1601dca8a05SBarry Smith PetscCheck(dim == 2 && posA == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Expected a middle triangle, got something else"); 161dcbd3bf7SToby Isaac *childB = childA; 1629371c9d4SSatish Balay } else { 163dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 164dcbd3bf7SToby Isaac PetscInt posB; 165dcbd3bf7SToby Isaac 166dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize - (ABswapVert + 1) - posA) % coneSize); 167dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 168dcbd3bf7SToby Isaac } 169dcbd3bf7SToby Isaac } 170dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 1713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 172dcbd3bf7SToby Isaac } 173dcbd3bf7SToby Isaac 174dcbd3bf7SToby Isaac /*@ 175dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 176dcbd3bf7SToby Isaac 177dcbd3bf7SToby Isaac Input Parameters: 178a1cb98faSBarry Smith + dm - the reference tree `DMPLEX` object 179dcbd3bf7SToby Isaac . parent - the parent point 180dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 181dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 182dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 183dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 184dcbd3bf7SToby Isaac 185dcbd3bf7SToby Isaac Output Parameters: 18620f4b53cSBarry Smith + childOrientB - if not `NULL`, set to the new orientation for describing the child 18720f4b53cSBarry Smith - childB - if not `NULL`, the new childID for describing the child 188dcbd3bf7SToby Isaac 189dcbd3bf7SToby Isaac Level: developer 190dcbd3bf7SToby Isaac 191a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetReferenceTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetTree()` 192dcbd3bf7SToby Isaac @*/ 193d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 194d71ae5a4SJacob Faibussowitsch { 195dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 196dcbd3bf7SToby Isaac 197dcbd3bf7SToby Isaac PetscFunctionBegin; 198dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19928b400f6SJacob Faibussowitsch PetscCheck(mesh->getchildsymmetry, PETSC_COMM_SELF, PETSC_ERR_SUP, "DMPlexReferenceTreeGetChildSymmetry not implemented"); 2009566063dSJacob Faibussowitsch PetscCall(mesh->getchildsymmetry(dm, parent, parentOrientA, childOrientA, childA, parentOrientB, childOrientB, childB)); 2013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 202dcbd3bf7SToby Isaac } 203dcbd3bf7SToby Isaac 204776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM, PetscSection, PetscInt *, PetscInt *, PetscBool, PetscBool); 205f9f063d4SToby Isaac 206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceTree_SetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 207d71ae5a4SJacob Faibussowitsch { 208f2c1aa1dSLisandro Dalcin PetscFunctionBegin; 2099566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm, parentSection, parents, childIDs, PETSC_TRUE, PETSC_FALSE)); 2103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 211f2c1aa1dSLisandro Dalcin } 212f2c1aa1dSLisandro Dalcin 213d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 214d71ae5a4SJacob Faibussowitsch { 2150e2cc29aSToby Isaac MPI_Comm comm; 2160e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 217da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 218da43764aSToby Isaac DMLabel identity, identityRef; 21910f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 220da43764aSToby Isaac PetscScalar *unionCoords; 221da43764aSToby Isaac IS perm; 222da43764aSToby Isaac 223da43764aSToby Isaac PetscFunctionBegin; 2240e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2259566063dSJacob Faibussowitsch PetscCall(DMGetDimension(K, &dim)); 2269566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd)); 2279566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, labelName, &identity)); 2289566063dSJacob Faibussowitsch PetscCall(DMGetLabel(Kref, labelName, &identityRef)); 2299566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(Kref, &pRefStart, &pRefEnd)); 2309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionSection)); 2319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart))); 232da43764aSToby Isaac /* count points that will go in the union */ 23348a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(PetscSectionSetDof(unionSection, p - pStart, 1)); 234da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 235da43764aSToby Isaac PetscInt q, qSize; 2369566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &q)); 2379566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(identityRef, q, &qSize)); 23848a46eb9SPierre Jolivet if (qSize > 1) PetscCall(PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1)); 239da43764aSToby Isaac } 2409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart, &permvals)); 241da43764aSToby Isaac offset = 0; 242da43764aSToby Isaac /* stratify points in the union by topological dimension */ 243da43764aSToby Isaac for (d = 0; d <= dim; d++) { 244da43764aSToby Isaac PetscInt cStart, cEnd, c; 245da43764aSToby Isaac 2469566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, &cEnd)); 247ad540459SPierre Jolivet for (c = cStart; c < cEnd; c++) permvals[offset++] = c; 248da43764aSToby Isaac 2499566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd)); 250ad540459SPierre Jolivet for (c = cStart; c < cEnd; c++) permvals[offset++] = c + (pEnd - pStart); 251da43764aSToby Isaac } 2529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm)); 2539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(unionSection, perm)); 2549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionSection)); 2559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionSection, &numUnionPoints)); 2569566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numUnionPoints, &coneSizes, dim + 1, &numDimPoints)); 257da43764aSToby Isaac /* count dimension points */ 258da43764aSToby Isaac for (d = 0; d <= dim; d++) { 259da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 2609566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, NULL)); 2619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, cStart - pStart, &cOff)); 262da43764aSToby Isaac if (d < dim) { 2639566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d + 1, &cStart, NULL)); 2649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, cStart - pStart, &cOff2)); 2659371c9d4SSatish Balay } else { 266da43764aSToby Isaac cOff2 = numUnionPoints; 267da43764aSToby Isaac } 268da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 269da43764aSToby Isaac } 2709566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionConeSection)); 2719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionConeSection, 0, numUnionPoints)); 272da43764aSToby Isaac /* count the cones in the union */ 273da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 274da43764aSToby Isaac PetscInt dof, uOff; 275da43764aSToby Isaac 2769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof)); 2779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart, &uOff)); 2789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof)); 279da43764aSToby Isaac coneSizes[uOff] = dof; 280da43764aSToby Isaac } 281da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 282da43764aSToby Isaac PetscInt dof, uDof, uOff; 283da43764aSToby Isaac 2849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof)); 2859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 2869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 287da43764aSToby Isaac if (uDof) { 2889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof)); 289da43764aSToby Isaac coneSizes[uOff] = dof; 290da43764aSToby Isaac } 291da43764aSToby Isaac } 2929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionConeSection)); 2939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionConeSection, &numCones)); 2949566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numCones, &unionCones, numCones, &unionOrientations)); 295da43764aSToby Isaac /* write the cones in the union */ 296da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 297da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 298da43764aSToby Isaac const PetscInt *cone, *orientation; 299da43764aSToby Isaac 3009566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof)); 3019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, p, &cone)); 3029566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, p, &orientation)); 3039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart, &uOff)); 3049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection, uOff, &cOff)); 305da43764aSToby Isaac for (c = 0; c < dof; c++) { 306da43764aSToby Isaac PetscInt e, eOff; 307da43764aSToby Isaac e = cone[c]; 3089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 309da43764aSToby Isaac unionCones[cOff + c] = eOff; 310da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 311da43764aSToby Isaac } 312da43764aSToby Isaac } 313da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 314da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 315da43764aSToby Isaac const PetscInt *cone, *orientation; 316da43764aSToby Isaac 3179566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof)); 3189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(Kref, p, &cone)); 3199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(Kref, p, &orientation)); 3209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 3219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 322da43764aSToby Isaac if (uDof) { 3239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection, uOff, &cOff)); 324da43764aSToby Isaac for (c = 0; c < dof; c++) { 325da43764aSToby Isaac PetscInt e, eOff, eDof; 326da43764aSToby Isaac 327da43764aSToby Isaac e = cone[c]; 3289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart), &eDof)); 329da43764aSToby Isaac if (eDof) { 3309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff)); 3319371c9d4SSatish Balay } else { 3329566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, e, &e)); 3339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 334da43764aSToby Isaac } 335da43764aSToby Isaac unionCones[cOff + c] = eOff; 336da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 337da43764aSToby Isaac } 338da43764aSToby Isaac } 339da43764aSToby Isaac } 340da43764aSToby Isaac /* get the coordinates */ 341da43764aSToby Isaac { 342da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 343da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 344da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 345da43764aSToby Isaac PetscScalar *Kcoords; 346da43764aSToby Isaac 3479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &KcoordsSec)); 3489566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &KcoordsVec)); 3499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(Kref, &KrefCoordsSec)); 3509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(Kref, &KrefCoordsVec)); 351da43764aSToby Isaac 352da43764aSToby Isaac numVerts = numDimPoints[0]; 3539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVerts * dim, &unionCoords)); 3549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &vStart, &vEnd)); 355da43764aSToby Isaac 356da43764aSToby Isaac offset = 0; 357da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 3589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, v - pStart, &vOff)); 3599566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords)); 360ad540459SPierre Jolivet for (d = 0; d < dim; d++) unionCoords[offset * dim + d] = Kcoords[d]; 361da43764aSToby Isaac offset++; 362da43764aSToby Isaac } 3639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(Kref, 0, &vRefStart, &vRefEnd)); 364da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 3659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, v - pRefStart + (pEnd - pStart), &vDof)); 3669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, v - pRefStart + (pEnd - pStart), &vOff)); 3679566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords)); 368da43764aSToby Isaac if (vDof) { 369ad540459SPierre Jolivet for (d = 0; d < dim; d++) unionCoords[offset * dim + d] = Kcoords[d]; 370da43764aSToby Isaac offset++; 371da43764aSToby Isaac } 372da43764aSToby Isaac } 373da43764aSToby Isaac } 3749566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, ref)); 3759566063dSJacob Faibussowitsch PetscCall(DMSetType(*ref, DMPLEX)); 3769566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ref, dim)); 3779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ref, dim, numDimPoints, coneSizes, unionCones, unionOrientations, unionCoords)); 37810f7e118SToby Isaac /* set the tree */ 3799566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &parentSection)); 3809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, numUnionPoints)); 38110f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 38210f7e118SToby Isaac PetscInt uDof, uOff; 38310f7e118SToby Isaac 3849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 3859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 3861baa6e33SBarry Smith if (uDof) PetscCall(PetscSectionSetDof(parentSection, uOff, 1)); 38710f7e118SToby Isaac } 3889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 3899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &parentSize)); 3909566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(parentSize, &parents, parentSize, &childIDs)); 39110f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 39210f7e118SToby Isaac PetscInt uDof, uOff; 39310f7e118SToby Isaac 3949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 3959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 39610f7e118SToby Isaac if (uDof) { 39710f7e118SToby Isaac PetscInt pOff, parent, parentU; 3989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, uOff, &pOff)); 3999566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &parent)); 4009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, parent - pStart, &parentU)); 40110f7e118SToby Isaac parents[pOff] = parentU; 40210f7e118SToby Isaac childIDs[pOff] = uOff; 40310f7e118SToby Isaac } 40410f7e118SToby Isaac } 4059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_SetTree(*ref, parentSection, parents, childIDs)); 4069566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 4079566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs)); 40810f7e118SToby Isaac 409da43764aSToby Isaac /* clean up */ 4109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionSection)); 4119566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionConeSection)); 4129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 4139566063dSJacob Faibussowitsch PetscCall(PetscFree(unionCoords)); 4149566063dSJacob Faibussowitsch PetscCall(PetscFree2(unionCones, unionOrientations)); 4159566063dSJacob Faibussowitsch PetscCall(PetscFree2(coneSizes, numDimPoints)); 4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4170e2cc29aSToby Isaac } 4180e2cc29aSToby Isaac 4190e2cc29aSToby Isaac /*@ 4200e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4210e2cc29aSToby Isaac 422d083f849SBarry Smith Collective 4230e2cc29aSToby Isaac 4240e2cc29aSToby Isaac Input Parameters: 4250e2cc29aSToby Isaac + comm - the MPI communicator 4260e2cc29aSToby Isaac . dim - the spatial dimension 4270e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4280e2cc29aSToby Isaac 4292fe279fdSBarry Smith Output Parameter: 430a1cb98faSBarry Smith . ref - the reference tree `DMPLEX` object 4310e2cc29aSToby Isaac 4320e2cc29aSToby Isaac Level: intermediate 4330e2cc29aSToby Isaac 434db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()` 4350e2cc29aSToby Isaac @*/ 436d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 437d71ae5a4SJacob Faibussowitsch { 4380e2cc29aSToby Isaac DM_Plex *mesh; 4390e2cc29aSToby Isaac DM K, Kref; 4400e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4410e2cc29aSToby Isaac DMLabel identity; 4420e2cc29aSToby Isaac 4430e2cc29aSToby Isaac PetscFunctionBegin; 4440e2cc29aSToby Isaac #if 1 4450e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4460e2cc29aSToby Isaac #endif 4470e2cc29aSToby Isaac /* create a reference element */ 4489566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(comm, DMPolytopeTypeSimpleShape(dim, simplex), &K)); 4499566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(K, "identity")); 4509566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, "identity", &identity)); 4519566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd)); 45248a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMLabelSetValue(identity, p, p)); 4530e2cc29aSToby Isaac /* refine it */ 4549566063dSJacob Faibussowitsch PetscCall(DMRefine(K, comm, &Kref)); 4550e2cc29aSToby Isaac 4560e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4570e2cc29aSToby Isaac * points that appear in both */ 4589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref)); 4590e2cc29aSToby Isaac mesh = (DM_Plex *)(*ref)->data; 4600e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 4619566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 4629566063dSJacob Faibussowitsch PetscCall(DMDestroy(&Kref)); 4633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 464da43764aSToby Isaac } 465da43764aSToby Isaac 466d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 467d71ae5a4SJacob Faibussowitsch { 468878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 469878b19aaSToby Isaac PetscSection childSec, pSec; 470878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 471878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 472878b19aaSToby Isaac 473878b19aaSToby Isaac PetscFunctionBegin; 474878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4759566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 4769566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 477878b19aaSToby Isaac pSec = mesh->parentSection; 4783ba16761SJacob Faibussowitsch if (!pSec) PetscFunctionReturn(PETSC_SUCCESS); 4799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(pSec, &pSize)); 480878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 481878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 482878b19aaSToby Isaac 483878b19aaSToby Isaac parMax = PetscMax(parMax, par + 1); 484878b19aaSToby Isaac parMin = PetscMin(parMin, par); 485878b19aaSToby Isaac } 486878b19aaSToby Isaac if (parMin > parMax) { 487878b19aaSToby Isaac parMin = -1; 488878b19aaSToby Isaac parMax = -1; 489878b19aaSToby Isaac } 4909566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)pSec), &childSec)); 4919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(childSec, parMin, parMax)); 492878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 493878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 494878b19aaSToby Isaac 4959566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(childSec, par, 1)); 496878b19aaSToby Isaac } 4979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(childSec)); 4989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(childSec, &cSize)); 4999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cSize, &children)); 5009566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(parMax - parMin, &offsets)); 5019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pSec, &pStart, &pEnd)); 502878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 503878b19aaSToby Isaac PetscInt dof, off, i; 504878b19aaSToby Isaac 5059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, p, &dof)); 5069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, p, &off)); 507878b19aaSToby Isaac for (i = 0; i < dof; i++) { 508878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 509878b19aaSToby Isaac 5109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, par, &cOff)); 511878b19aaSToby Isaac children[cOff + offsets[par - parMin]++] = p; 512878b19aaSToby Isaac } 513878b19aaSToby Isaac } 514878b19aaSToby Isaac mesh->childSection = childSec; 515878b19aaSToby Isaac mesh->children = children; 5169566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 5173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 518878b19aaSToby Isaac } 519878b19aaSToby Isaac 520d71ae5a4SJacob Faibussowitsch static PetscErrorCode AnchorsFlatten(PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 521d71ae5a4SJacob Faibussowitsch { 5226dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5236dd5a8c8SToby Isaac const PetscInt *vals; 5246dd5a8c8SToby Isaac PetscSection secNew; 5256dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5266dd5a8c8SToby Isaac PetscBool compress; 5276dd5a8c8SToby Isaac 5286dd5a8c8SToby Isaac PetscFunctionBegin; 5299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 5309566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &size)); 5319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &vals)); 5329566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &secNew)); 5339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secNew, pStart, pEnd)); 5346dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5356dd5a8c8SToby Isaac PetscInt dof; 5366dd5a8c8SToby Isaac 5376dd5a8c8SToby Isaac p = vals[i]; 5386dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5406dd5a8c8SToby Isaac if (dof) break; 5416dd5a8c8SToby Isaac } 5426dd5a8c8SToby Isaac if (i == size) { 5439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew)); 5446dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5456dd5a8c8SToby Isaac compress = PETSC_FALSE; 5466dd5a8c8SToby Isaac sizeNew = 0; 5479371c9d4SSatish Balay } else { 5486dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5496dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5506dd5a8c8SToby Isaac PetscInt dof, off; 5516dd5a8c8SToby Isaac 5529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5546dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5556dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5566dd5a8c8SToby Isaac 55748a46eb9SPierre Jolivet if (q >= pStart && q < pEnd) PetscCall(PetscSectionGetDof(section, q, &qDof)); 5581baa6e33SBarry Smith if (qDof) PetscCall(PetscSectionAddDof(secNew, p, qDof)); 55948a46eb9SPierre Jolivet else PetscCall(PetscSectionAddDof(secNew, p, 1)); 5606dd5a8c8SToby Isaac } 5616dd5a8c8SToby Isaac } 5629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew)); 5639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secNew, &sizeNew)); 5649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew, &valsNew)); 5656dd5a8c8SToby Isaac compress = PETSC_FALSE; 5666dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5676dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 5686dd5a8c8SToby Isaac 5699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dofNew)); 5729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &offNew)); 5736dd5a8c8SToby Isaac count = 0; 5746dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5756dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 5766dd5a8c8SToby Isaac 5776dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &qDof)); 5799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &qOff)); 5806dd5a8c8SToby Isaac } 5816dd5a8c8SToby Isaac if (qDof) { 5826dd5a8c8SToby Isaac PetscInt oldCount = count; 5836dd5a8c8SToby Isaac 5846dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 5856dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 5866dd5a8c8SToby Isaac 5876dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 588ad540459SPierre Jolivet if (valsNew[offNew + k] == r) break; 5896dd5a8c8SToby Isaac } 590ad540459SPierre Jolivet if (k == oldCount) valsNew[offNew + count++] = r; 5916dd5a8c8SToby Isaac } 5929371c9d4SSatish Balay } else { 5936dd5a8c8SToby Isaac PetscInt k, oldCount = count; 5946dd5a8c8SToby Isaac 5956dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 596ad540459SPierre Jolivet if (valsNew[offNew + k] == q) break; 5976dd5a8c8SToby Isaac } 598ad540459SPierre Jolivet if (k == oldCount) valsNew[offNew + count++] = q; 5996dd5a8c8SToby Isaac } 6006dd5a8c8SToby Isaac } 6016dd5a8c8SToby Isaac if (count < dofNew) { 6029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secNew, p, count)); 6036dd5a8c8SToby Isaac compress = PETSC_TRUE; 6046dd5a8c8SToby Isaac } 6056dd5a8c8SToby Isaac } 6066dd5a8c8SToby Isaac } 6079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &vals)); 6081c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&anyNew, &globalAnyNew, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)secNew))); 6096dd5a8c8SToby Isaac if (!globalAnyNew) { 6109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew)); 6116dd5a8c8SToby Isaac *sectionNew = NULL; 6126dd5a8c8SToby Isaac *isNew = NULL; 6139371c9d4SSatish Balay } else { 6146dd5a8c8SToby Isaac PetscBool globalCompress; 6156dd5a8c8SToby Isaac 6161c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&compress, &globalCompress, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)secNew))); 6176dd5a8c8SToby Isaac if (compress) { 6186dd5a8c8SToby Isaac PetscSection secComp; 6196dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6206dd5a8c8SToby Isaac 6219566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &secComp)); 6229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secComp, pStart, pEnd)); 6236dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6246dd5a8c8SToby Isaac PetscInt dof; 6256dd5a8c8SToby Isaac 6269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof)); 6279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secComp, p, dof)); 6286dd5a8c8SToby Isaac } 6299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secComp)); 6309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secComp, &sizeNew)); 6319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew, &valsComp)); 6326dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6336dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6346dd5a8c8SToby Isaac 6359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof)); 6369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &off)); 6379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secComp, p, &offNew)); 638ad540459SPierre Jolivet for (j = 0; j < dof; j++) valsComp[offNew + j] = valsNew[off + j]; 6396dd5a8c8SToby Isaac } 6409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew)); 6416dd5a8c8SToby Isaac secNew = secComp; 6429566063dSJacob Faibussowitsch PetscCall(PetscFree(valsNew)); 6436dd5a8c8SToby Isaac valsNew = valsComp; 6446dd5a8c8SToby Isaac } 6459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), sizeNew, valsNew, PETSC_OWN_POINTER, isNew)); 6466dd5a8c8SToby Isaac } 6473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6486dd5a8c8SToby Isaac } 6496dd5a8c8SToby Isaac 650d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 651d71ae5a4SJacob Faibussowitsch { 65266af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 65366af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 65466af876cSToby Isaac PetscSection aSec; 655f9f063d4SToby Isaac DMLabel canonLabel; 65666af876cSToby Isaac IS aIS; 65766af876cSToby Isaac 65866af876cSToby Isaac PetscFunctionBegin; 65966af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 6619566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "canonical", &canonLabel)); 66266af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 66366af876cSToby Isaac PetscInt parent; 66466af876cSToby Isaac 665f9f063d4SToby Isaac if (canonLabel) { 666f9f063d4SToby Isaac PetscInt canon; 667f9f063d4SToby Isaac 6689566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 669f9f063d4SToby Isaac if (p != canon) continue; 670f9f063d4SToby Isaac } 6719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 67266af876cSToby Isaac if (parent != p) { 67366af876cSToby Isaac aMin = PetscMin(aMin, p); 67466af876cSToby Isaac aMax = PetscMax(aMax, p + 1); 67566af876cSToby Isaac } 67666af876cSToby Isaac } 67766af876cSToby Isaac if (aMin > aMax) { 67866af876cSToby Isaac aMin = -1; 67966af876cSToby Isaac aMax = -1; 68066af876cSToby Isaac } 6819566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &aSec)); 6829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(aSec, aMin, aMax)); 68366af876cSToby Isaac for (p = aMin; p < aMax; p++) { 68466af876cSToby Isaac PetscInt parent, ancestor = p; 68566af876cSToby Isaac 686f9f063d4SToby Isaac if (canonLabel) { 687f9f063d4SToby Isaac PetscInt canon; 688f9f063d4SToby Isaac 6899566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 690f9f063d4SToby Isaac if (p != canon) continue; 691f9f063d4SToby Isaac } 6929566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 69366af876cSToby Isaac while (parent != ancestor) { 69466af876cSToby Isaac ancestor = parent; 6959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, ancestor, &parent, NULL)); 69666af876cSToby Isaac } 69766af876cSToby Isaac if (ancestor != p) { 69866af876cSToby Isaac PetscInt closureSize, *closure = NULL; 69966af876cSToby Isaac 7009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 7019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(aSec, p, closureSize)); 7029566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 70366af876cSToby Isaac } 70466af876cSToby Isaac } 7059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(aSec)); 7069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(aSec, &size)); 7079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &anchors)); 70866af876cSToby Isaac for (p = aMin; p < aMax; p++) { 70966af876cSToby Isaac PetscInt parent, ancestor = p; 71066af876cSToby Isaac 711f9f063d4SToby Isaac if (canonLabel) { 712f9f063d4SToby Isaac PetscInt canon; 713f9f063d4SToby Isaac 7149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 715f9f063d4SToby Isaac if (p != canon) continue; 716f9f063d4SToby Isaac } 7179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 71866af876cSToby Isaac while (parent != ancestor) { 71966af876cSToby Isaac ancestor = parent; 7209566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, ancestor, &parent, NULL)); 72166af876cSToby Isaac } 72266af876cSToby Isaac if (ancestor != p) { 72366af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 72466af876cSToby Isaac 7259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 72666af876cSToby Isaac 7279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 728ad540459SPierre Jolivet for (j = 0; j < closureSize; j++) anchors[aOff + j] = closure[2 * j]; 7299566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 73066af876cSToby Isaac } 73166af876cSToby Isaac } 7329566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, anchors, PETSC_OWN_POINTER, &aIS)); 7336dd5a8c8SToby Isaac { 7346dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7356dd5a8c8SToby Isaac IS aISNew = aIS; 7366dd5a8c8SToby Isaac 7379566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aSec)); 7389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aIS)); 7396dd5a8c8SToby Isaac while (aSecNew) { 7409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec)); 7419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS)); 7426dd5a8c8SToby Isaac aSec = aSecNew; 7436dd5a8c8SToby Isaac aIS = aISNew; 7446dd5a8c8SToby Isaac aSecNew = NULL; 7456dd5a8c8SToby Isaac aISNew = NULL; 7469566063dSJacob Faibussowitsch PetscCall(AnchorsFlatten(aSec, aIS, &aSecNew, &aISNew)); 7476dd5a8c8SToby Isaac } 7486dd5a8c8SToby Isaac } 7499566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm, aSec, aIS)); 7509566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec)); 7519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS)); 7523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75366af876cSToby Isaac } 75466af876cSToby Isaac 755d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTrueSupportSize(DM dm, PetscInt p, PetscInt *dof, PetscInt *numTrueSupp) 756d71ae5a4SJacob Faibussowitsch { 7576461c1adSToby Isaac PetscFunctionBegin; 7586461c1adSToby Isaac if (numTrueSupp[p] == -1) { 7596461c1adSToby Isaac PetscInt i, alldof; 7606461c1adSToby Isaac const PetscInt *supp; 7616461c1adSToby Isaac PetscInt count = 0; 7626461c1adSToby Isaac 7639566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &alldof)); 7649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &supp)); 7656461c1adSToby Isaac for (i = 0; i < alldof; i++) { 7666461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 7676461c1adSToby Isaac const PetscInt *cone; 7686461c1adSToby Isaac 7699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &numCones)); 7709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &cone)); 7716461c1adSToby Isaac for (j = 0; j < numCones; j++) { 7726461c1adSToby Isaac if (cone[j] == p) break; 7736461c1adSToby Isaac } 7746461c1adSToby Isaac if (j < numCones) count++; 7756461c1adSToby Isaac } 7766461c1adSToby Isaac numTrueSupp[p] = count; 7776461c1adSToby Isaac } 7786461c1adSToby Isaac *dof = numTrueSupp[p]; 7793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7806461c1adSToby Isaac } 7816461c1adSToby Isaac 782d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 783d71ae5a4SJacob Faibussowitsch { 784776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 785776742edSToby Isaac PetscSection newSupportSection; 786776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 7876461c1adSToby Isaac PetscInt *numTrueSupp; 788776742edSToby Isaac PetscInt *offsets; 789776742edSToby Isaac 790776742edSToby Isaac PetscFunctionBegin; 791776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 792776742edSToby Isaac /* symmetrize the hierarchy */ 7939566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7949566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)), &newSupportSection)); 7959566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 7969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSupportSection, pStart, pEnd)); 7979566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd, &offsets)); 7989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd, &numTrueSupp)); 7996461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 8006461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 801776742edSToby Isaac * parent(q) */ 802776742edSToby Isaac for (d = 0; d <= depth; d++) { 8039566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pStart, &pEnd)); 804776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 805776742edSToby Isaac PetscInt dof, q, qdof, parent; 806776742edSToby Isaac 8079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm, p, &dof, numTrueSupp)); 8089566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, dof)); 809776742edSToby Isaac q = p; 8109566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 811776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 812776742edSToby Isaac q = parent; 813776742edSToby Isaac 8149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm, q, &qdof, numTrueSupp)); 8159566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, qdof)); 8169566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, q, dof)); 8179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 818776742edSToby Isaac } 819776742edSToby Isaac } 820776742edSToby Isaac } 8219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSupportSection)); 8229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSupportSection, &newSize)); 8239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newSize, &newSupports)); 824776742edSToby Isaac for (d = 0; d <= depth; d++) { 8259566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pStart, &pEnd)); 826776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 827776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 828776742edSToby Isaac 8299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 8319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(newSupportSection, p, &newDof)); 8329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, p, &newOff)); 833776742edSToby Isaac for (i = 0; i < dof; i++) { 8346461c1adSToby Isaac PetscInt numCones, j; 8356461c1adSToby Isaac const PetscInt *cone; 8366461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 8376461c1adSToby Isaac 8389566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &numCones)); 8399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &cone)); 8406461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8416461c1adSToby Isaac if (cone[j] == p) break; 8426461c1adSToby Isaac } 8436461c1adSToby Isaac if (j < numCones) newSupports[newOff + offsets[p]++] = q; 844776742edSToby Isaac } 845776742edSToby Isaac 846776742edSToby Isaac q = p; 8479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 848776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 849776742edSToby Isaac q = parent; 8509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, q, &qdof)); 8519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &qoff)); 8529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, q, &newqOff)); 853776742edSToby Isaac for (i = 0; i < qdof; i++) { 8546461c1adSToby Isaac PetscInt numCones, j; 8556461c1adSToby Isaac const PetscInt *cone; 8566461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 8576461c1adSToby Isaac 8589566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, r, &numCones)); 8599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, r, &cone)); 8606461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8616461c1adSToby Isaac if (cone[j] == q) break; 8626461c1adSToby Isaac } 8636461c1adSToby Isaac if (j < numCones) newSupports[newOff + offsets[p]++] = r; 864776742edSToby Isaac } 865776742edSToby Isaac for (i = 0; i < dof; i++) { 8666461c1adSToby Isaac PetscInt numCones, j; 8676461c1adSToby Isaac const PetscInt *cone; 8686461c1adSToby Isaac PetscInt r = mesh->supports[off + i]; 8696461c1adSToby Isaac 8709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, r, &numCones)); 8719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, r, &cone)); 8726461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8736461c1adSToby Isaac if (cone[j] == p) break; 8746461c1adSToby Isaac } 8756461c1adSToby Isaac if (j < numCones) newSupports[newqOff + offsets[q]++] = r; 876776742edSToby Isaac } 8779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 878776742edSToby Isaac } 879776742edSToby Isaac } 880776742edSToby Isaac } 8819566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 882776742edSToby Isaac mesh->supportSection = newSupportSection; 8839566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 884776742edSToby Isaac mesh->supports = newSupports; 8859566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 8869566063dSJacob Faibussowitsch PetscCall(PetscFree(numTrueSupp)); 887776742edSToby Isaac 8883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 889776742edSToby Isaac } 890776742edSToby Isaac 891f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM, PetscSection, PetscSection, Mat); 892f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM, PetscSection, PetscSection, Mat); 893f7c74593SToby Isaac 894d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 895d71ae5a4SJacob Faibussowitsch { 896f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 897f9f063d4SToby Isaac DM refTree; 898f9f063d4SToby Isaac PetscInt size; 899f9f063d4SToby Isaac 900f9f063d4SToby Isaac PetscFunctionBegin; 901f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 902f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 9039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)parentSection)); 9049566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 905f9f063d4SToby Isaac mesh->parentSection = parentSection; 9069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &size)); 907f9f063d4SToby Isaac if (parents != mesh->parents) { 9089566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 9099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->parents)); 9109566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->parents, parents, size)); 911f9f063d4SToby Isaac } 912f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 9139566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 9149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->childIDs)); 9159566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->childIDs, childIDs, size)); 916f9f063d4SToby Isaac } 9179566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 918f9f063d4SToby Isaac if (refTree) { 919f9f063d4SToby Isaac DMLabel canonLabel; 920f9f063d4SToby Isaac 9219566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonLabel)); 922f9f063d4SToby Isaac if (canonLabel) { 923f9f063d4SToby Isaac PetscInt i; 924f9f063d4SToby Isaac 925f9f063d4SToby Isaac for (i = 0; i < size; i++) { 926f9f063d4SToby Isaac PetscInt canon; 9279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon)); 928ad540459SPierre Jolivet if (canon >= 0) mesh->childIDs[i] = canon; 929f9f063d4SToby Isaac } 930f9f063d4SToby Isaac } 931f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 9326e0288c8SStefano Zampini } else { 933f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 934f9f063d4SToby Isaac } 9359566063dSJacob Faibussowitsch PetscCall(DMPlexTreeSymmetrize(dm)); 936f9f063d4SToby Isaac if (computeCanonical) { 937f9f063d4SToby Isaac PetscInt d, dim; 938f9f063d4SToby Isaac 939f9f063d4SToby Isaac /* add the canonical label */ 9409566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9419566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "canonical")); 942f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 943f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 944f9f063d4SToby Isaac const PetscInt *cChildren; 945f9f063d4SToby Isaac 9469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 947f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 9489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, p, &cNumChildren, &cChildren)); 949f9f063d4SToby Isaac if (cNumChildren) { 950f9f063d4SToby Isaac canon = p; 951f9f063d4SToby Isaac break; 952f9f063d4SToby Isaac } 953f9f063d4SToby Isaac } 954f9f063d4SToby Isaac if (canon == -1) continue; 955f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 956f9f063d4SToby Isaac PetscInt numChildren, i; 957f9f063d4SToby Isaac const PetscInt *children; 958f9f063d4SToby Isaac 9599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, p, &numChildren, &children)); 960f9f063d4SToby Isaac if (numChildren) { 96163a3b9bcSJacob Faibussowitsch PetscCheck(numChildren == cNumChildren, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "All parent points in a stratum should have the same number of children: %" PetscInt_FMT " != %" PetscInt_FMT, numChildren, cNumChildren); 9629566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "canonical", p, canon)); 96348a46eb9SPierre Jolivet for (i = 0; i < numChildren; i++) PetscCall(DMSetLabelValue(dm, "canonical", children[i], cChildren[i])); 964f9f063d4SToby Isaac } 965f9f063d4SToby Isaac } 966f9f063d4SToby Isaac } 967f9f063d4SToby Isaac } 9681baa6e33SBarry Smith if (exchangeSupports) PetscCall(DMPlexTreeExchangeSupports(dm)); 969f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 970f7c74593SToby Isaac /* reset anchors */ 9719566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm, NULL, NULL)); 9723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 973f9f063d4SToby Isaac } 974f9f063d4SToby Isaac 9750b7167a0SToby Isaac /*@ 9760b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 977*aaa8cc7dSPierre Jolivet the point-to-point constraints determined by the tree: a point is constrained to the points in the closure of its 9780b7167a0SToby Isaac tree root. 9790b7167a0SToby Isaac 98020f4b53cSBarry Smith Collective 9810b7167a0SToby Isaac 9820b7167a0SToby Isaac Input Parameters: 983a1cb98faSBarry Smith + dm - the `DMPLEX` object 9840b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 9850b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 9860b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 9870b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 9880b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 9890b7167a0SToby Isaac 9900b7167a0SToby Isaac Level: intermediate 9910b7167a0SToby Isaac 992a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 9930b7167a0SToby Isaac @*/ 994d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 995d71ae5a4SJacob Faibussowitsch { 9960b7167a0SToby Isaac PetscFunctionBegin; 9979566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm, parentSection, parents, childIDs, PETSC_FALSE, PETSC_TRUE)); 9983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9990b7167a0SToby Isaac } 10000b7167a0SToby Isaac 1001b2f41788SToby Isaac /*@ 1002b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 100320f4b53cSBarry Smith Collective 1004b2f41788SToby Isaac 1005f899ff85SJose E. Roman Input Parameter: 1006a1cb98faSBarry Smith . dm - the `DMPLEX` object 1007b2f41788SToby Isaac 1008b2f41788SToby Isaac Output Parameters: 1009b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1010b2f41788SToby Isaac offset indexes the parent and childID list 1011b2f41788SToby Isaac . parents - a list of the point parents 1012b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1013b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1014b2f41788SToby Isaac . childSection - the inverse of the parent section 1015b2f41788SToby Isaac - children - a list of the point children 1016b2f41788SToby Isaac 1017b2f41788SToby Isaac Level: intermediate 1018b2f41788SToby Isaac 1019a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`,`DMPlexSetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 1020b2f41788SToby Isaac @*/ 1021d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1022d71ae5a4SJacob Faibussowitsch { 1023b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1024b2f41788SToby Isaac 1025b2f41788SToby Isaac PetscFunctionBegin; 1026b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1027b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1028b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1029b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1030b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1031b2f41788SToby Isaac if (children) *children = mesh->children; 10323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1033b2f41788SToby Isaac } 1034b2f41788SToby Isaac 1035d961a43aSToby Isaac /*@ 1036eaf898f9SPatrick Sanan DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the DAG) 1037d961a43aSToby Isaac 1038d961a43aSToby Isaac Input Parameters: 1039a1cb98faSBarry Smith + dm - the `DMPLEX` object 1040d961a43aSToby Isaac - point - the query point 1041d961a43aSToby Isaac 1042d961a43aSToby Isaac Output Parameters: 104320f4b53cSBarry Smith + parent - if not `NULL`, set to the parent of the point, or the point itself if the point does not have a parent 104420f4b53cSBarry Smith - childID - if not `NULL`, set to the child ID of the point with respect to its parent, or 0 if the point 1045d961a43aSToby Isaac does not have a parent 1046d961a43aSToby Isaac 1047d961a43aSToby Isaac Level: intermediate 1048d961a43aSToby Isaac 1049a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeChildren()` 1050d961a43aSToby Isaac @*/ 1051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1052d71ae5a4SJacob Faibussowitsch { 1053d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1054d961a43aSToby Isaac PetscSection pSec; 1055d961a43aSToby Isaac 1056d961a43aSToby Isaac PetscFunctionBegin; 1057d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1058d961a43aSToby Isaac pSec = mesh->parentSection; 1059d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1060d961a43aSToby Isaac PetscInt dof; 1061d961a43aSToby Isaac 10629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, point, &dof)); 1063d961a43aSToby Isaac if (dof) { 1064d961a43aSToby Isaac PetscInt off; 1065d961a43aSToby Isaac 10669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, point, &off)); 1067d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1068d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 10693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1070d961a43aSToby Isaac } 1071d961a43aSToby Isaac } 1072ad540459SPierre Jolivet if (parent) *parent = point; 1073ad540459SPierre Jolivet if (childID) *childID = 0; 10743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1075d961a43aSToby Isaac } 1076d961a43aSToby Isaac 1077d961a43aSToby Isaac /*@C 1078eaf898f9SPatrick Sanan DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the DAG) 1079d961a43aSToby Isaac 1080d961a43aSToby Isaac Input Parameters: 1081a1cb98faSBarry Smith + dm - the `DMPLEX` object 1082d961a43aSToby Isaac - point - the query point 1083d961a43aSToby Isaac 1084d961a43aSToby Isaac Output Parameters: 108520f4b53cSBarry Smith + numChildren - if not `NULL`, set to the number of children 108620f4b53cSBarry Smith - children - if not `NULL`, set to a list children, or set to `NULL` if the point has no children 1087d961a43aSToby Isaac 1088d961a43aSToby Isaac Level: intermediate 1089d961a43aSToby Isaac 1090a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeParent()` 1091d961a43aSToby Isaac @*/ 1092d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1093d71ae5a4SJacob Faibussowitsch { 1094d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1095d961a43aSToby Isaac PetscSection childSec; 1096d961a43aSToby Isaac PetscInt dof = 0; 1097d961a43aSToby Isaac 1098d961a43aSToby Isaac PetscFunctionBegin; 1099d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1100d961a43aSToby Isaac childSec = mesh->childSection; 110148a46eb9SPierre Jolivet if (childSec && point >= childSec->pStart && point < childSec->pEnd) PetscCall(PetscSectionGetDof(childSec, point, &dof)); 1102d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1103d961a43aSToby Isaac if (children) { 1104d961a43aSToby Isaac if (dof) { 1105d961a43aSToby Isaac PetscInt off; 1106d961a43aSToby Isaac 11079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, point, &off)); 1108d961a43aSToby Isaac *children = &mesh->children[off]; 11099371c9d4SSatish Balay } else { 1110d961a43aSToby Isaac *children = NULL; 1111d961a43aSToby Isaac } 1112d961a43aSToby Isaac } 11133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1114d961a43aSToby Isaac } 11150c37af3bSToby Isaac 1116d71ae5a4SJacob Faibussowitsch static PetscErrorCode EvaluateBasis(PetscSpace space, PetscInt nBasis, PetscInt nFunctionals, PetscInt nComps, PetscInt nPoints, const PetscInt *pointsPerFn, const PetscReal *points, const PetscReal *weights, PetscReal *work, Mat basisAtPoints) 1117d71ae5a4SJacob Faibussowitsch { 111852a3aeb4SToby Isaac PetscInt f, b, p, c, offset, qPoints; 1119b3a4bf2aSToby Isaac 1120b3a4bf2aSToby Isaac PetscFunctionBegin; 11219566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(space, nPoints, points, work, NULL, NULL)); 112252a3aeb4SToby Isaac for (f = 0, offset = 0; f < nFunctionals; f++) { 112352a3aeb4SToby Isaac qPoints = pointsPerFn[f]; 112452a3aeb4SToby Isaac for (b = 0; b < nBasis; b++) { 1125b3a4bf2aSToby Isaac PetscScalar val = 0.; 1126b3a4bf2aSToby Isaac 112752a3aeb4SToby Isaac for (p = 0; p < qPoints; p++) { 1128ad540459SPierre Jolivet for (c = 0; c < nComps; c++) val += work[((offset + p) * nBasis + b) * nComps + c] * weights[(offset + p) * nComps + c]; 112952a3aeb4SToby Isaac } 11309566063dSJacob Faibussowitsch PetscCall(MatSetValue(basisAtPoints, b, f, val, INSERT_VALUES)); 1131b3a4bf2aSToby Isaac } 1132b3a4bf2aSToby Isaac offset += qPoints; 1133b3a4bf2aSToby Isaac } 11349566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(basisAtPoints, MAT_FINAL_ASSEMBLY)); 11359566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(basisAtPoints, MAT_FINAL_ASSEMBLY)); 11363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1137b3a4bf2aSToby Isaac } 1138b3a4bf2aSToby Isaac 1139d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 1140d71ae5a4SJacob Faibussowitsch { 11410c37af3bSToby Isaac PetscDS ds; 11420c37af3bSToby Isaac PetscInt spdim; 11430c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 11440c37af3bSToby Isaac const PetscInt *anchors; 1145f7c74593SToby Isaac PetscSection aSec; 11460c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 11470c37af3bSToby Isaac IS aIS; 11480c37af3bSToby Isaac 11490c37af3bSToby Isaac PetscFunctionBegin; 11509566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11519566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 11529566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 11539566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 11549566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 11559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 11569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &conStart, &conEnd)); 11579566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &spdim)); 11589566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(spdim, &v0, spdim, &v0parent, spdim, &vtmp, spdim * spdim, &J, spdim * spdim, &Jparent, spdim * spdim, &invJparent)); 11590c37af3bSToby Isaac 11600c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 11610dd1b1feSToby Isaac PetscObject disc; 11620dd1b1feSToby Isaac PetscClassId id; 1163b3a4bf2aSToby Isaac PetscSpace bspace; 1164b3a4bf2aSToby Isaac PetscDualSpace dspace; 11659c3cf19fSMatthew G. Knepley PetscInt i, j, k, nPoints, Nc, offset; 116652a3aeb4SToby Isaac PetscInt fSize, maxDof; 1167b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 11681683a169SBarry Smith PetscScalar *scwork; 11691683a169SBarry Smith const PetscScalar *X; 11702c44ad04SToby Isaac PetscInt *sizes, *workIndRow, *workIndCol; 11710c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 11722c44ad04SToby Isaac const PetscInt *numDof = NULL; 1173085f0adfSToby Isaac const PetscInt ***perms = NULL; 1174085f0adfSToby Isaac const PetscScalar ***flips = NULL; 11750c37af3bSToby Isaac 11769566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 11779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &id)); 11780dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1179b3a4bf2aSToby Isaac PetscFE fe = (PetscFE)disc; 1180b3a4bf2aSToby Isaac 11819566063dSJacob Faibussowitsch PetscCall(PetscFEGetBasisSpace(fe, &bspace)); 11829566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dspace)); 11839566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize)); 11849566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc)); 11859371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) { 1186b3a4bf2aSToby Isaac PetscFV fv = (PetscFV)disc; 1187b3a4bf2aSToby Isaac 11889566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc)); 11899566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)fv), &bspace)); 11909566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(bspace, PETSCSPACEPOLYNOMIAL)); 11919566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(bspace, 0, PETSC_DETERMINE)); 11929566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(bspace, Nc)); 11939566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(bspace, spdim)); 11949566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(bspace)); 11959566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv, &dspace)); 11969566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize)); 11979371c9d4SSatish Balay } else SETERRQ(PetscObjectComm(disc), PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 11989566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dspace, &numDof)); 1199ad540459SPierre Jolivet for (i = 0, maxDof = 0; i <= spdim; i++) maxDof = PetscMax(maxDof, numDof[i]); 12009566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dspace, &perms, &flips)); 12010dd1b1feSToby Isaac 12029566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &Amat)); 12039566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Amat, fSize, fSize, fSize, fSize)); 12049566063dSJacob Faibussowitsch PetscCall(MatSetType(Amat, MATSEQDENSE)); 12059566063dSJacob Faibussowitsch PetscCall(MatSetUp(Amat)); 12069566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Bmat)); 12079566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Xmat)); 12080c37af3bSToby Isaac nPoints = 0; 12090c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 121052a3aeb4SToby Isaac PetscInt qPoints, thisNc; 12110c37af3bSToby Isaac PetscQuadrature quad; 12120c37af3bSToby Isaac 12139566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad)); 12149566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &thisNc, &qPoints, NULL, NULL)); 121563a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 12160c37af3bSToby Isaac nPoints += qPoints; 12170c37af3bSToby Isaac } 12189566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(fSize, &sizes, nPoints * Nc, &weights, spdim * nPoints, &pointsRef, spdim * nPoints, &pointsReal, nPoints * fSize * Nc, &work, maxDof, &workIndRow, maxDof, &workIndCol)); 12199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &scwork)); 12200c37af3bSToby Isaac offset = 0; 12210c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12220c37af3bSToby Isaac PetscInt qPoints; 12230c37af3bSToby Isaac const PetscReal *p, *w; 12240c37af3bSToby Isaac PetscQuadrature quad; 12250c37af3bSToby Isaac 12269566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad)); 12279566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &qPoints, &p, &w)); 12289566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(weights + Nc * offset, w, Nc * qPoints)); 12299566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pointsRef + spdim * offset, p, spdim * qPoints)); 1230b3a4bf2aSToby Isaac sizes[i] = qPoints; 12310c37af3bSToby Isaac offset += qPoints; 12320c37af3bSToby Isaac } 12339566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsRef, weights, work, Amat)); 12349566063dSJacob Faibussowitsch PetscCall(MatLUFactor(Amat, NULL, NULL, NULL)); 12350c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 12360c37af3bSToby Isaac PetscInt parent; 12370c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 12380c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 12390c37af3bSToby Isaac 12409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, c, &parent, NULL)); 12410c37af3bSToby Isaac if (parent == c) continue; 12429566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 12430c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12440c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12450c37af3bSToby Isaac PetscInt conDof; 12460c37af3bSToby Isaac 12470c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1248085f0adfSToby Isaac if (numFields) { 12499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof)); 12509371c9d4SSatish Balay } else { 12519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof)); 12520c37af3bSToby Isaac } 12530c37af3bSToby Isaac if (conDof) break; 12540c37af3bSToby Isaac } 12550c37af3bSToby Isaac if (i == closureSize) { 12569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 12570c37af3bSToby Isaac continue; 12580c37af3bSToby Isaac } 12590c37af3bSToby Isaac 12609566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ)); 12619566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent)); 12620c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1263c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 1264c330f8ffSToby Isaac 1265c330f8ffSToby Isaac CoordinatesRefToReal(spdim, spdim, xi0, v0, J, &pointsRef[i * spdim], vtmp); 1266c330f8ffSToby Isaac CoordinatesRealToRef(spdim, spdim, xi0, v0parent, invJparent, vtmp, &pointsReal[i * spdim]); 12670c37af3bSToby Isaac } 12689566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsReal, weights, work, Bmat)); 12699566063dSJacob Faibussowitsch PetscCall(MatMatSolve(Amat, Bmat, Xmat)); 12709566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Xmat, &X)); 12719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP)); 12729566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(closureSize + 1, &childOffsets, closureSizeP + 1, &parentOffsets)); 12730c37af3bSToby Isaac childOffsets[0] = 0; 12740c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12750c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12760c37af3bSToby Isaac PetscInt dof; 12770c37af3bSToby Isaac 1278085f0adfSToby Isaac if (numFields) { 12799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 12809371c9d4SSatish Balay } else { 12819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 12820c37af3bSToby Isaac } 128352a3aeb4SToby Isaac childOffsets[i + 1] = childOffsets[i] + dof; 12840c37af3bSToby Isaac } 12850c37af3bSToby Isaac parentOffsets[0] = 0; 12860c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 12870c37af3bSToby Isaac PetscInt p = closureP[2 * i]; 12880c37af3bSToby Isaac PetscInt dof; 12890c37af3bSToby Isaac 1290085f0adfSToby Isaac if (numFields) { 12919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 12929371c9d4SSatish Balay } else { 12939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 12940c37af3bSToby Isaac } 129552a3aeb4SToby Isaac parentOffsets[i + 1] = parentOffsets[i] + dof; 12960c37af3bSToby Isaac } 12970c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12982c44ad04SToby Isaac PetscInt conDof, conOff, aDof, aOff, nWork; 12990c37af3bSToby Isaac PetscInt p = closure[2 * i]; 13000c37af3bSToby Isaac PetscInt o = closure[2 * i + 1]; 1301085f0adfSToby Isaac const PetscInt *perm; 1302085f0adfSToby Isaac const PetscScalar *flip; 13030c37af3bSToby Isaac 13040c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1305085f0adfSToby Isaac if (numFields) { 13069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof)); 13079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &conOff)); 13089371c9d4SSatish Balay } else { 13099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof)); 13109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &conOff)); 13110c37af3bSToby Isaac } 13120c37af3bSToby Isaac if (!conDof) continue; 1313085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL; 1314085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL; 13159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 13169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 13172c44ad04SToby Isaac nWork = childOffsets[i + 1] - childOffsets[i]; 13180c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 13190c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 13200c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 13210c37af3bSToby Isaac 1322085f0adfSToby Isaac if (numFields) { 13239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aSecDof)); 13249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aSecOff)); 13259371c9d4SSatish Balay } else { 13269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aSecDof)); 13279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aSecOff)); 13280c37af3bSToby Isaac } 13290c37af3bSToby Isaac if (!aSecDof) continue; 13300c37af3bSToby Isaac 13310c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 13320c37af3bSToby Isaac PetscInt q = closureP[2 * j]; 13330c37af3bSToby Isaac PetscInt oq = closureP[2 * j + 1]; 13342c44ad04SToby Isaac 13352c44ad04SToby Isaac if (q == a) { 133652a3aeb4SToby Isaac PetscInt r, s, nWorkP; 1337085f0adfSToby Isaac const PetscInt *permP; 1338085f0adfSToby Isaac const PetscScalar *flipP; 1339085f0adfSToby Isaac 1340085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL; 1341085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL; 13422c44ad04SToby Isaac nWorkP = parentOffsets[j + 1] - parentOffsets[j]; 13432c44ad04SToby Isaac /* get a copy of the child-to-anchor portion of the matrix, and transpose so that rows correspond to the 13441683a169SBarry Smith * child and columns correspond to the anchor: BUT the maxrix returned by MatDenseGetArrayRead() is 13452c44ad04SToby Isaac * column-major, so transpose-transpose = do nothing */ 13462c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1347ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] = X[fSize * (r + childOffsets[i]) + (s + parentOffsets[j])]; 13482c44ad04SToby Isaac } 1349ad540459SPierre Jolivet for (r = 0; r < nWork; r++) workIndRow[perm ? perm[r] : r] = conOff + r; 1350ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) workIndCol[permP ? permP[s] : s] = aSecOff + s; 13512c44ad04SToby Isaac if (flip) { 13522c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1353ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] *= flip[r]; 13542c44ad04SToby Isaac } 13552c44ad04SToby Isaac } 13562c44ad04SToby Isaac if (flipP) { 13572c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1358ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] *= flipP[s]; 13592c44ad04SToby Isaac } 13602c44ad04SToby Isaac } 13619566063dSJacob Faibussowitsch PetscCall(MatSetValues(cMat, nWork, workIndRow, nWorkP, workIndCol, scwork, INSERT_VALUES)); 13622c44ad04SToby Isaac break; 13630c37af3bSToby Isaac } 13640c37af3bSToby Isaac } 13650c37af3bSToby Isaac } 13660c37af3bSToby Isaac } 13679566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Xmat, &X)); 13689566063dSJacob Faibussowitsch PetscCall(PetscFree2(childOffsets, parentOffsets)); 13699566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 13709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP)); 13710c37af3bSToby Isaac } 13729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Amat)); 13739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bmat)); 13749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Xmat)); 13759566063dSJacob Faibussowitsch PetscCall(PetscFree(scwork)); 13769566063dSJacob Faibussowitsch PetscCall(PetscFree7(sizes, weights, pointsRef, pointsReal, work, workIndRow, workIndCol)); 137748a46eb9SPierre Jolivet if (id == PETSCFV_CLASSID) PetscCall(PetscSpaceDestroy(&bspace)); 13780c37af3bSToby Isaac } 13799566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 13809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 13819566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJparent)); 13829566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 13830c37af3bSToby Isaac 13843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13850c37af3bSToby Isaac } 138695a0b26dSToby Isaac 1387d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 1388d71ae5a4SJacob Faibussowitsch { 1389f7c74593SToby Isaac Mat refCmat; 139021968bf8SToby Isaac PetscDS ds; 1391085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 139221968bf8SToby Isaac PetscScalar ***refPointFieldMats; 139321968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 139421968bf8SToby Isaac IS refAnIS; 139521968bf8SToby Isaac const PetscInt *refAnchors; 1396085f0adfSToby Isaac const PetscInt **perms; 1397085f0adfSToby Isaac const PetscScalar **flips; 139895a0b26dSToby Isaac 139995a0b26dSToby Isaac PetscFunctionBegin; 14009566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 14019566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1402085f0adfSToby Isaac maxFields = PetscMax(1, numFields); 14039566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 14049566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 14059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(refAnIS, &refAnchors)); 14069566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 14079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 14089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 14099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldN)); 14109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 14119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 14129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 14139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxAnDof, &cols)); 141495a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 141595a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 141695a0b26dSToby Isaac 14179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 14189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 141995a0b26dSToby Isaac if (!pDof || parent == p) continue; 142095a0b26dSToby Isaac 14219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxFields, &refPointFieldMats[p - pRefStart])); 14229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxFields, &refPointFieldN[p - pRefStart])); 14239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure)); 1424085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1425085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i; 142695a0b26dSToby Isaac 1427085f0adfSToby Isaac if (f < numFields) { 14289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 14299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 14309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips)); 1431085f0adfSToby Isaac } else { 14329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 14339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 14349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(refSection, closureSize, closure, &perms, &flips)); 143595a0b26dSToby Isaac } 143695a0b26dSToby Isaac 1437ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r; 143895a0b26dSToby Isaac numCols = 0; 143995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 144095a0b26dSToby Isaac PetscInt q = closure[2 * i]; 144195a0b26dSToby Isaac PetscInt aDof, aOff, j; 1442085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 144395a0b26dSToby Isaac 1444085f0adfSToby Isaac if (numFields) { 14459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof)); 14469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff)); 14479371c9d4SSatish Balay } else { 14489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof)); 14499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff)); 145095a0b26dSToby Isaac } 145195a0b26dSToby Isaac 1452ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + (perm ? perm[j] : j); 145395a0b26dSToby Isaac } 145495a0b26dSToby Isaac refPointFieldN[p - pRefStart][f] = numCols; 14559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 14569566063dSJacob Faibussowitsch PetscCall(MatGetValues(refCmat, cDof, rows, numCols, cols, refPointFieldMats[p - pRefStart][f])); 1457085f0adfSToby Isaac if (flips) { 1458085f0adfSToby Isaac PetscInt colOff = 0; 1459085f0adfSToby Isaac 1460085f0adfSToby Isaac for (i = 0; i < closureSize; i++) { 1461085f0adfSToby Isaac PetscInt q = closure[2 * i]; 1462085f0adfSToby Isaac PetscInt aDof, aOff, j; 1463085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 1464085f0adfSToby Isaac 1465085f0adfSToby Isaac if (numFields) { 14669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof)); 14679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff)); 14689371c9d4SSatish Balay } else { 14699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof)); 14709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff)); 1471085f0adfSToby Isaac } 1472085f0adfSToby Isaac if (flip) { 1473085f0adfSToby Isaac PetscInt k; 1474085f0adfSToby Isaac for (k = 0; k < cDof; k++) { 1475ad540459SPierre Jolivet for (j = 0; j < aDof; j++) refPointFieldMats[p - pRefStart][f][k * numCols + colOff + j] *= flip[j]; 1476085f0adfSToby Isaac } 1477085f0adfSToby Isaac } 1478085f0adfSToby Isaac colOff += aDof; 1479085f0adfSToby Isaac } 1480085f0adfSToby Isaac } 1481085f0adfSToby Isaac if (numFields) { 14829566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips)); 1483085f0adfSToby Isaac } else { 14849566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(refSection, closureSize, closure, &perms, &flips)); 1485085f0adfSToby Isaac } 148695a0b26dSToby Isaac } 14879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure)); 148895a0b26dSToby Isaac } 148921968bf8SToby Isaac *childrenMats = refPointFieldMats; 149021968bf8SToby Isaac *childrenN = refPointFieldN; 14919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(refAnIS, &refAnchors)); 14929566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 14939566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 14943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 149521968bf8SToby Isaac } 149621968bf8SToby Isaac 1497d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 1498d71ae5a4SJacob Faibussowitsch { 149921968bf8SToby Isaac PetscDS ds; 150021968bf8SToby Isaac PetscInt **refPointFieldN; 150121968bf8SToby Isaac PetscScalar ***refPointFieldMats; 1502085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f; 150321968bf8SToby Isaac PetscSection refConSec; 150421968bf8SToby Isaac 150521968bf8SToby Isaac PetscFunctionBegin; 150621968bf8SToby Isaac refPointFieldN = *childrenN; 150721968bf8SToby Isaac *childrenN = NULL; 150821968bf8SToby Isaac refPointFieldMats = *childrenMats; 150921968bf8SToby Isaac *childrenMats = NULL; 15109566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 15119566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1512367003a6SStefano Zampini maxFields = PetscMax(1, numFields); 15139566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 15149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 151521968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 151621968bf8SToby Isaac PetscInt parent, pDof; 151721968bf8SToby Isaac 15189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 15199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 152021968bf8SToby Isaac if (!pDof || parent == p) continue; 152121968bf8SToby Isaac 1522085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 152321968bf8SToby Isaac PetscInt cDof; 152421968bf8SToby Isaac 1525085f0adfSToby Isaac if (numFields) { 15269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 15279371c9d4SSatish Balay } else { 15289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 152921968bf8SToby Isaac } 153021968bf8SToby Isaac 15319566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 153221968bf8SToby Isaac } 15339566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 15349566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN[p - pRefStart])); 153521968bf8SToby Isaac } 15369566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 15379566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN)); 15383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 153921968bf8SToby Isaac } 154021968bf8SToby Isaac 1541d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 1542d71ae5a4SJacob Faibussowitsch { 154321968bf8SToby Isaac DM refTree; 154421968bf8SToby Isaac PetscDS ds; 154521968bf8SToby Isaac Mat refCmat; 1546085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 154721968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 154821968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 154921968bf8SToby Isaac IS refAnIS, anIS; 155021968bf8SToby Isaac const PetscInt *anchors; 155121968bf8SToby Isaac 155221968bf8SToby Isaac PetscFunctionBegin; 155321968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15549566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 15559566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1556085f0adfSToby Isaac maxFields = PetscMax(1, numFields); 15579566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 15589566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, refTree)); 15599566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 15609566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 15619566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anSec, &anIS)); 15629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anIS, &anchors)); 15639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 15649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(conSec, &conStart, &conEnd)); 15659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 15669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 15679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof * maxAnDof, &pointWork)); 156821968bf8SToby Isaac 156921968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 15709566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 157195a0b26dSToby Isaac 157295a0b26dSToby Isaac /* step 2: compute the preorder */ 15739566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 15749566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &perm, pEnd - pStart, &iperm)); 157595a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 157695a0b26dSToby Isaac perm[p - pStart] = p; 157795a0b26dSToby Isaac iperm[p - pStart] = p - pStart; 157895a0b26dSToby Isaac } 157995a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 158095a0b26dSToby Isaac PetscInt point = perm[p]; 158195a0b26dSToby Isaac PetscInt parent; 158295a0b26dSToby Isaac 15839566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 158495a0b26dSToby Isaac if (parent == point) { 158595a0b26dSToby Isaac p++; 15869371c9d4SSatish Balay } else { 158795a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 158895a0b26dSToby Isaac 15899566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 159095a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 159195a0b26dSToby Isaac PetscInt q = closure[2 * i]; 159295a0b26dSToby Isaac if (iperm[q - pStart] > iperm[point - pStart]) { 159395a0b26dSToby Isaac /* swap */ 159495a0b26dSToby Isaac perm[p] = q; 159595a0b26dSToby Isaac perm[iperm[q - pStart]] = point; 159695a0b26dSToby Isaac iperm[point - pStart] = iperm[q - pStart]; 159795a0b26dSToby Isaac iperm[q - pStart] = p; 159895a0b26dSToby Isaac break; 159995a0b26dSToby Isaac } 160095a0b26dSToby Isaac } 160195a0b26dSToby Isaac size = closureSize; 16029566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1603ad540459SPierre Jolivet if (i == size) p++; 160495a0b26dSToby Isaac } 160595a0b26dSToby Isaac } 160695a0b26dSToby Isaac 160795a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 160895a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 160995a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 161095a0b26dSToby Isaac * values outside of the Mat first. 161195a0b26dSToby Isaac */ 161295a0b26dSToby Isaac { 161395a0b26dSToby Isaac PetscInt nRows, row, nnz; 161495a0b26dSToby Isaac PetscBool done; 1615cd6fc93eSToby Isaac PetscInt secStart, secEnd; 161695a0b26dSToby Isaac const PetscInt *ia, *ja; 161795a0b26dSToby Isaac PetscScalar *vals; 161895a0b26dSToby Isaac 1619cd6fc93eSToby Isaac PetscCall(PetscSectionGetChart(section, &secStart, &secEnd)); 16209566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 162128b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not get RowIJ of constraint matrix"); 162295a0b26dSToby Isaac nnz = ia[nRows]; 162395a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 162495a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 16259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &vals)); 162695a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 162795a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 162895a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 162995a0b26dSToby Isaac 16309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, &childid)); 163195a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 16329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &pointDof)); 163395a0b26dSToby Isaac if (!pointDof) continue; 16349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1635085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1636085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 163795a0b26dSToby Isaac PetscScalar *pointMat; 1638085f0adfSToby Isaac const PetscInt **perms; 1639085f0adfSToby Isaac const PetscScalar **flips; 164095a0b26dSToby Isaac 1641085f0adfSToby Isaac if (numFields) { 16429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, point, f, &cDof)); 16439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, point, f, &cOff)); 16449371c9d4SSatish Balay } else { 16459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &cDof)); 16469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, point, &cOff)); 164795a0b26dSToby Isaac } 164895a0b26dSToby Isaac if (!cDof) continue; 16499566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 16509566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, closureSize, closure, &perms, &flips)); 165195a0b26dSToby Isaac 165295a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 165376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 165495a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 165595a0b26dSToby Isaac if (cDof > 1 && r) { 165663a3b9bcSJacob Faibussowitsch PetscCheck((ia[cOff + r + 1] - ia[cOff + r]) == (ia[cOff + r] - ia[cOff + r - 1]), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two point rows have different nnz: %" PetscInt_FMT " vs. %" PetscInt_FMT, (ia[cOff + r + 1] - ia[cOff + r]), (ia[cOff + r] - ia[cOff + r - 1])); 165795a0b26dSToby Isaac } 165895a0b26dSToby Isaac } 165976bd3646SJed Brown } 166095a0b26dSToby Isaac /* zero rows */ 1661ad540459SPierre Jolivet for (i = ia[cOff]; i < ia[cOff + cDof]; i++) vals[i] = 0.; 166295a0b26dSToby Isaac matOffset = ia[cOff]; 166395a0b26dSToby Isaac numFillCols = ia[cOff + 1] - matOffset; 166495a0b26dSToby Isaac pointMat = refPointFieldMats[childid - pRefStart][f]; 166595a0b26dSToby Isaac numCols = refPointFieldN[childid - pRefStart][f]; 166695a0b26dSToby Isaac offset = 0; 166795a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 166895a0b26dSToby Isaac PetscInt q = closure[2 * i]; 166995a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 1670085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1671085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 167295a0b26dSToby Isaac 167395a0b26dSToby Isaac qConDof = qConOff = 0; 1674cd6fc93eSToby Isaac if (q < secStart || q >= secEnd) continue; 1675085f0adfSToby Isaac if (numFields) { 16769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, q, f, &aDof)); 16779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, q, f, &aOff)); 167895a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, q, f, &qConDof)); 16809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, q, f, &qConOff)); 168195a0b26dSToby Isaac } 16829371c9d4SSatish Balay } else { 16839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &aDof)); 16849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &aOff)); 168595a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, q, &qConDof)); 16879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, q, &qConOff)); 168895a0b26dSToby Isaac } 168995a0b26dSToby Isaac } 169095a0b26dSToby Isaac if (!aDof) continue; 169195a0b26dSToby Isaac if (qConDof) { 169295a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 169395a0b26dSToby Isaac * be filled, thanks to preordering */ 169495a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 169595a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 169695a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 169795a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 169895a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 169995a0b26dSToby Isaac PetscScalar inVal = 0; 170095a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1701085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 170295a0b26dSToby Isaac 1703085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 170495a0b26dSToby Isaac } 170595a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 170695a0b26dSToby Isaac } 170795a0b26dSToby Isaac } 170895a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 170995a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 171095a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 171195a0b26dSToby Isaac for (; k < numFillCols; k++) { 1712ad540459SPierre Jolivet if (ja[matOffset + k] == col) break; 171395a0b26dSToby Isaac } 171463a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, col); 1715ad540459SPierre Jolivet for (r = 0; r < cDof; r++) vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 171695a0b26dSToby Isaac } 17179371c9d4SSatish Balay } else { 171895a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 171995a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 1720ad540459SPierre Jolivet if (ja[matOffset + k] == aOff) break; 172195a0b26dSToby Isaac } 172263a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, aOff); 172395a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1724085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1725085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1726085f0adfSToby Isaac 1727085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 172895a0b26dSToby Isaac } 172995a0b26dSToby Isaac } 173095a0b26dSToby Isaac } 173195a0b26dSToby Isaac offset += aDof; 173295a0b26dSToby Isaac } 1733085f0adfSToby Isaac if (numFields) { 17349566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 1735085f0adfSToby Isaac } else { 17369566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, closureSize, closure, &perms, &flips)); 1737085f0adfSToby Isaac } 173895a0b26dSToby Isaac } 17399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 174095a0b26dSToby Isaac } 174148a46eb9SPierre Jolivet for (row = 0; row < nRows; row++) PetscCall(MatSetValues(cMat, 1, &row, ia[row + 1] - ia[row], &ja[ia[row]], &vals[ia[row]], INSERT_VALUES)); 17429566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 174328b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not restore RowIJ of constraint matrix"); 17449566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 17459566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 17469566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 174795a0b26dSToby Isaac } 174895a0b26dSToby Isaac 174995a0b26dSToby Isaac /* clean up */ 17509566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anIS, &anchors)); 17519566063dSJacob Faibussowitsch PetscCall(PetscFree2(perm, iperm)); 17529566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 17539566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 17543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 175595a0b26dSToby Isaac } 175695a0b26dSToby Isaac 17576f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 17586f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 1759d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTreeRefineCell(DM dm, PetscInt cell, DM *ncdm) 1760d71ae5a4SJacob Faibussowitsch { 17616f5f1567SToby Isaac DM K; 1762420f55faSMatthew G. Knepley PetscMPIInt rank; 17636f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 17646f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 17656f5f1567SToby Isaac PetscInt *Kembedding; 17666f5f1567SToby Isaac PetscInt *cellClosure = NULL, nc; 17676f5f1567SToby Isaac PetscScalar *newVertexCoords; 17686f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 17696f5f1567SToby Isaac PetscSection parentSection; 17706f5f1567SToby Isaac 17716f5f1567SToby Isaac PetscFunctionBegin; 17729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17739566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 17749566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm)); 17759566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ncdm, dim)); 17766f5f1567SToby Isaac 17779566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 17789566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &parentSection)); 17799566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &K)); 17806858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 1781dd400576SPatrick Sanan if (rank == 0) { 17826f5f1567SToby Isaac /* compute the new charts */ 17839566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim + 1, &pNewCount, dim + 1, &pNewStart, dim + 1, &pNewEnd, dim + 1, &pOldStart, dim + 1, &pOldEnd)); 17846f5f1567SToby Isaac offset = 0; 17856f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 17866f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 17876f5f1567SToby Isaac 17886f5f1567SToby Isaac pNewStart[d] = offset; 17899566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pOldStart[d], &pOldEnd[d])); 17909566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 17916f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 17926f5f1567SToby Isaac /* adding the new points */ 17936f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 17946f5f1567SToby Isaac if (!d) { 17956f5f1567SToby Isaac /* removing the cell */ 17966f5f1567SToby Isaac pNewCount[d]--; 17976f5f1567SToby Isaac } 17986f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 17996f5f1567SToby Isaac PetscInt parent; 18009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &parent, NULL)); 18016f5f1567SToby Isaac if (parent == k) { 18026f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 18036f5f1567SToby Isaac pNewCount[d]--; 18046f5f1567SToby Isaac } 18056f5f1567SToby Isaac } 18066f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 18076f5f1567SToby Isaac offset = pNewEnd[d]; 18086f5f1567SToby Isaac } 18091dca8a05SBarry Smith PetscCheck(cell >= pOldStart[0] && cell < pOldEnd[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "%" PetscInt_FMT " not in cell range [%" PetscInt_FMT ", %" PetscInt_FMT ")", cell, pOldStart[0], pOldEnd[0]); 18106f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 18119566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 18126f5f1567SToby Isaac 18139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pNewEnd[dim], &newConeSizes)); 18146f5f1567SToby Isaac { 1815b5a892a1SMatthew G. Knepley DMPolytopeType pct, qct; 18166f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 18176f5f1567SToby Isaac 18189566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &kStart, &kEnd)); 18199566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(kEnd - kStart, &Kembedding, kEnd - kStart, &perm, kEnd - kStart, &iperm, kEnd - kStart, &preOrient)); 18206f5f1567SToby Isaac 18216f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18226f5f1567SToby Isaac perm[k - kStart] = k; 18236f5f1567SToby Isaac iperm[k - kStart] = k - kStart; 18246f5f1567SToby Isaac preOrient[k - kStart] = 0; 18256f5f1567SToby Isaac } 18266f5f1567SToby Isaac 18279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18286f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 18296f5f1567SToby Isaac PetscInt parentOrientA = closureK[2 * j + 1]; 18306f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2 * j + 1]; 18316f5f1567SToby Isaac PetscInt p, q; 18326f5f1567SToby Isaac 18336f5f1567SToby Isaac p = closureK[2 * j]; 18346f5f1567SToby Isaac q = cellClosure[2 * j]; 18359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, p, &pct)); 18369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, q, &qct)); 18376f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 1838ad540459SPierre Jolivet if (q >= pOldStart[d] && q < pOldEnd[d]) Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 18396f5f1567SToby Isaac } 1840b5a892a1SMatthew G. Knepley parentOrientA = DMPolytopeConvertNewOrientation_Internal(pct, parentOrientA); 1841b5a892a1SMatthew G. Knepley parentOrientB = DMPolytopeConvertNewOrientation_Internal(qct, parentOrientB); 18426f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 18436f5f1567SToby Isaac PetscInt numChildren, i; 18446f5f1567SToby Isaac const PetscInt *children; 18456f5f1567SToby Isaac 18469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(K, p, &numChildren, &children)); 18476f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 18486f5f1567SToby Isaac PetscInt kPerm, oPerm; 18496f5f1567SToby Isaac 18506f5f1567SToby Isaac k = children[i]; 18519566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(K, p, parentOrientA, 0, k, parentOrientB, &oPerm, &kPerm)); 18526f5f1567SToby Isaac /* perm = what refTree position I'm in */ 18536f5f1567SToby Isaac perm[kPerm - kStart] = k; 18546f5f1567SToby Isaac /* iperm = who is at this position */ 18556f5f1567SToby Isaac iperm[k - kStart] = kPerm - kStart; 18566f5f1567SToby Isaac preOrient[kPerm - kStart] = oPerm; 18576f5f1567SToby Isaac } 18586f5f1567SToby Isaac } 18596f5f1567SToby Isaac } 18609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18616f5f1567SToby Isaac } 18629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, pNewEnd[dim])); 18636f5f1567SToby Isaac offset = 0; 18646f5f1567SToby Isaac numNewCones = 0; 18656f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18666f5f1567SToby Isaac PetscInt kStart, kEnd, k; 18676f5f1567SToby Isaac PetscInt p; 18686f5f1567SToby Isaac PetscInt size; 18696f5f1567SToby Isaac 18706f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 18716f5f1567SToby Isaac /* skip cell 0 */ 18726f5f1567SToby Isaac if (p == cell) continue; 18736f5f1567SToby Isaac /* old cones to new cones */ 18749566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 18756f5f1567SToby Isaac newConeSizes[offset++] = size; 18766f5f1567SToby Isaac numNewCones += size; 18776f5f1567SToby Isaac } 18786f5f1567SToby Isaac 18799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 18806f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18816f5f1567SToby Isaac PetscInt kParent; 18826f5f1567SToby Isaac 18839566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 18846f5f1567SToby Isaac if (kParent != k) { 18856f5f1567SToby Isaac Kembedding[k] = offset; 18869566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 18876f5f1567SToby Isaac newConeSizes[offset++] = size; 18886f5f1567SToby Isaac numNewCones += size; 188948a46eb9SPierre Jolivet if (kParent != 0) PetscCall(PetscSectionSetDof(parentSection, Kembedding[k], 1)); 18906f5f1567SToby Isaac } 18916f5f1567SToby Isaac } 18926f5f1567SToby Isaac } 18936f5f1567SToby Isaac 18949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 18959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &numPointsWithParents)); 18969566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numNewCones, &newCones, numNewCones, &newOrientations)); 18979566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPointsWithParents, &parents, numPointsWithParents, &childIDs)); 18986f5f1567SToby Isaac 18996f5f1567SToby Isaac /* fill new cones */ 19006f5f1567SToby Isaac offset = 0; 19016f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19026f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 19036f5f1567SToby Isaac PetscInt p; 19046f5f1567SToby Isaac PetscInt size; 19056f5f1567SToby Isaac const PetscInt *cone, *orientation; 19066f5f1567SToby Isaac 19076f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19086f5f1567SToby Isaac /* skip cell 0 */ 19096f5f1567SToby Isaac if (p == cell) continue; 19106f5f1567SToby Isaac /* old cones to new cones */ 19119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 19129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 19139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &orientation)); 19146f5f1567SToby Isaac for (l = 0; l < size; l++) { 19156f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 19166f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 19176f5f1567SToby Isaac } 19186f5f1567SToby Isaac } 19196f5f1567SToby Isaac 19209566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 19216f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19226f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 19236f5f1567SToby Isaac PetscInt preO = preOrient[k]; 19246f5f1567SToby Isaac 19259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 19266f5f1567SToby Isaac if (kParent != k) { 19276f5f1567SToby Isaac /* embed new cones */ 19289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 19299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, kPerm, &cone)); 19309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, kPerm, &orientation)); 19316f5f1567SToby Isaac for (l = 0; l < size; l++) { 19326f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size - (preO + 1) - l) % size); 19336f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 1934b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_NUM_POLYTOPES; 19356f5f1567SToby Isaac 19366f5f1567SToby Isaac q = iperm[cone[m]]; 19376f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 19389566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, q, &lSize)); 1939b5a892a1SMatthew G. Knepley if (lSize == 2) ct = DM_POLYTOPE_SEGMENT; 1940b5a892a1SMatthew G. Knepley else if (lSize == 4) ct = DM_POLYTOPE_QUADRILATERAL; 1941b5a892a1SMatthew G. Knepley oTrue = DMPolytopeConvertNewOrientation_Internal(ct, orientation[m]); 19426f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 19436f5f1567SToby Isaac newO = DihedralCompose(lSize, oTrue, preOrient[q]); 1944b5a892a1SMatthew G. Knepley newOrientations[offset++] = DMPolytopeConvertOldOrientation_Internal(ct, newO); 19456f5f1567SToby Isaac } 19466f5f1567SToby Isaac if (kParent != 0) { 19476f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 19489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, Kembedding[k], &pOffset)); 19496f5f1567SToby Isaac parents[pOffset] = newPoint; 19506f5f1567SToby Isaac childIDs[pOffset] = k; 19516f5f1567SToby Isaac } 19526f5f1567SToby Isaac } 19536f5f1567SToby Isaac } 19546f5f1567SToby Isaac } 19556f5f1567SToby Isaac 19569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * (pNewEnd[dim] - pNewStart[dim]), &newVertexCoords)); 19576f5f1567SToby Isaac 19586f5f1567SToby Isaac /* fill coordinates */ 19596f5f1567SToby Isaac offset = 0; 19606f5f1567SToby Isaac { 1961d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 19626f5f1567SToby Isaac PetscSection vSection; 19636f5f1567SToby Isaac PetscInt v; 19646f5f1567SToby Isaac Vec coords; 19656f5f1567SToby Isaac PetscScalar *coordvals; 19666f5f1567SToby Isaac PetscInt dof, off; 1967c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 19686f5f1567SToby Isaac 196976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1970d90620a3SMatthew G. Knepley PetscInt k; 19719566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, 0, &kStart, &kEnd)); 19726f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19739566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ)); 197463a3b9bcSJacob Faibussowitsch PetscCheck(detJ > 0., PETSC_COMM_SELF, PETSC_ERR_PLIB, "reference tree cell %" PetscInt_FMT " has bad determinant", k); 19756f5f1567SToby Isaac } 1976d90620a3SMatthew G. Knepley } 19779566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ)); 19789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &vSection)); 19799566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coords)); 19809566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19816f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 19829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(vSection, v, &dof)); 19839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, v, &off)); 1984ad540459SPierre Jolivet for (l = 0; l < dof; l++) newVertexCoords[offset++] = coordvals[off + l]; 19856f5f1567SToby Isaac } 19869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 19876f5f1567SToby Isaac 19889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &vSection)); 19899566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &coords)); 19909566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &kStart, &kEnd)); 19926f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 19939bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 19946f5f1567SToby Isaac PetscInt vPerm = perm[v]; 19956f5f1567SToby Isaac PetscInt kParent; 1996c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 19976f5f1567SToby Isaac 19989566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, v, &kParent, NULL)); 19996f5f1567SToby Isaac if (kParent != v) { 20006f5f1567SToby Isaac /* this is a new vertex */ 20019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, vPerm, &off)); 20029bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off + l]); 2003367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord); 20049bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset + l] = newCoord[l]; 20056f5f1567SToby Isaac offset += dim; 20066f5f1567SToby Isaac } 20076f5f1567SToby Isaac } 20089566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 20096f5f1567SToby Isaac } 20106f5f1567SToby Isaac 20116f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 20126f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 20136f5f1567SToby Isaac PetscInt tmp; 20146f5f1567SToby Isaac 20156f5f1567SToby Isaac tmp = pNewCount[d]; 20166f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 20176f5f1567SToby Isaac pNewCount[dim - d] = tmp; 20186f5f1567SToby Isaac } 20196f5f1567SToby Isaac 20209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, pNewCount, newConeSizes, newCones, newOrientations, newVertexCoords)); 20219566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20229566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, parents, childIDs)); 20236f5f1567SToby Isaac 20246f5f1567SToby Isaac /* clean up */ 20259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 20269566063dSJacob Faibussowitsch PetscCall(PetscFree5(pNewCount, pNewStart, pNewEnd, pOldStart, pOldEnd)); 20279566063dSJacob Faibussowitsch PetscCall(PetscFree(newConeSizes)); 20289566063dSJacob Faibussowitsch PetscCall(PetscFree2(newCones, newOrientations)); 20299566063dSJacob Faibussowitsch PetscCall(PetscFree(newVertexCoords)); 20309566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs)); 20319566063dSJacob Faibussowitsch PetscCall(PetscFree4(Kembedding, perm, iperm, preOrient)); 20329371c9d4SSatish Balay } else { 20336f5f1567SToby Isaac PetscInt p, counts[4]; 20346f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 20356f5f1567SToby Isaac Vec coordVec; 20366f5f1567SToby Isaac PetscScalar *coords; 20376f5f1567SToby Isaac 20386f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20396f5f1567SToby Isaac PetscInt dStart, dEnd; 20406f5f1567SToby Isaac 20419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 20426f5f1567SToby Isaac counts[d] = dEnd - dStart; 20436f5f1567SToby Isaac } 20449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &coneSizes)); 204548a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMPlexGetConeSize(dm, p, &coneSizes[p - pStart])); 20469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 20479566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &orientations)); 20489566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordVec)); 20499566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordVec, &coords)); 20506f5f1567SToby Isaac 20519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd)); 20529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 20539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, counts, coneSizes, cones, orientations, NULL)); 20549566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20559566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, NULL, NULL)); 20569566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordVec, &coords)); 20576f5f1567SToby Isaac } 20589566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 20596f5f1567SToby Isaac 20603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20616f5f1567SToby Isaac } 20626ecaa68aSToby Isaac 2063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 2064d71ae5a4SJacob Faibussowitsch { 20656ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 20666ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 20676ecaa68aSToby Isaac PetscSection localCoarse, localFine; 20686ecaa68aSToby Isaac PetscSection aSec, cSec; 20696ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 207046bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 207146bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 207246bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 20736ecaa68aSToby Isaac IS aIS; 20746ecaa68aSToby Isaac const PetscInt *anchors; 20756ecaa68aSToby Isaac Mat cMat; 20764acb8e1eSToby Isaac PetscInt numFields, maxFields; 20776ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 20786ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 20791c58ffc4SToby Isaac PetscInt *maxChildIds; 2080e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 20814acb8e1eSToby Isaac const PetscInt ***perms; 20824acb8e1eSToby Isaac const PetscScalar ***flips; 20836ecaa68aSToby Isaac 20846ecaa68aSToby Isaac PetscFunctionBegin; 20859566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 20869566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 20879566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 20886ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 208989698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 209089698031SToby Isaac const PetscInt *leaves; 20916ecaa68aSToby Isaac 20929566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 209389698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 209489698031SToby Isaac p = leaves ? leaves[l] : l; 20959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 20969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 2097ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 20986ecaa68aSToby Isaac } 20999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 21007cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 210189698031SToby Isaac p = leaves ? leaves[l] : l; 21029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 21039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 2104ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l; 21056ecaa68aSToby Isaac } 21069566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 21079566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 21086ecaa68aSToby Isaac } 21096ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 21109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 2111ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2; 211257168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 211357168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 211446bdb399SToby Isaac 21159566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 21169566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 211746bdb399SToby Isaac 21189566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 21199566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 21209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 212146bdb399SToby Isaac 21229566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 21239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 212446bdb399SToby Isaac 212546bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 21269566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 21279566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootMatricesSec)); 21289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootIndicesSec, pStartC, pEndC)); 21299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootMatricesSec, pStartC, pEndC)); 21309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 2131713c1c5dSToby Isaac maxFields = PetscMax(1, numFields); 21329566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields + 1, &offsets, maxFields + 1, &offsetsCopy, maxFields + 1, &newOffsets, maxFields + 1, &newOffsetsCopy, maxFields + 1, &rowOffsets, maxFields + 1, &numD, maxFields + 1, &numO)); 21339566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxFields + 1, (PetscInt ****)&perms, maxFields + 1, (PetscScalar ****)&flips)); 21349566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)perms, (maxFields + 1) * sizeof(const PetscInt **))); 21359566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)flips, (maxFields + 1) * sizeof(const PetscScalar **))); 213646bdb399SToby Isaac 213746bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 21388d2f55e7SToby Isaac PetscInt dof, matSize = 0; 21396ecaa68aSToby Isaac PetscInt aDof = 0; 21406ecaa68aSToby Isaac PetscInt cDof = 0; 21416ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 21426ecaa68aSToby Isaac PetscInt numRowIndices = 0; 21436ecaa68aSToby Isaac PetscInt numColIndices = 0; 2144f13f9184SToby Isaac PetscInt f; 21456ecaa68aSToby Isaac 21469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 2147ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 214848a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 214948a46eb9SPierre Jolivet if (p >= cStart && p < cEnd) PetscCall(PetscSectionGetDof(cSec, p, &cDof)); 2150f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2151f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 21526ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2153f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 21546ecaa68aSToby Isaac 21559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 215646bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 21576ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 21586ecaa68aSToby Isaac 21599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 21606ecaa68aSToby Isaac numRowIndices += clDof; 21616ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &clDof)); 21636ecaa68aSToby Isaac offsets[f + 1] += clDof; 21646ecaa68aSToby Isaac } 21656ecaa68aSToby Isaac } 21666ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21676ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 21686ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 21696ecaa68aSToby Isaac } 217046bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 21719566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, NULL, NULL, NULL, &numColIndices, NULL, NULL, newOffsets, PETSC_FALSE)); 21729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 21736ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 21746ecaa68aSToby Isaac numColIndices = numRowIndices; 21756ecaa68aSToby Isaac matSize = 0; 21769371c9d4SSatish Balay } else if (numFields) { /* we send one submat for each field: sum their sizes */ 21776ecaa68aSToby Isaac matSize = 0; 21786ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21796ecaa68aSToby Isaac PetscInt numRow, numCol; 21806ecaa68aSToby Isaac 21816ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2182f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 21836ecaa68aSToby Isaac matSize += numRow * numCol; 21846ecaa68aSToby Isaac } 21859371c9d4SSatish Balay } else { 21866ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 21876ecaa68aSToby Isaac } 2188f13f9184SToby Isaac } else if (maxChildId == -1) { 21898d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2190f13f9184SToby Isaac PetscInt aOff, a; 21916ecaa68aSToby Isaac 21929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 21936ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21946ecaa68aSToby Isaac PetscInt fDof; 21956ecaa68aSToby Isaac 21969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 219721968bf8SToby Isaac offsets[f + 1] = fDof; 21986ecaa68aSToby Isaac } 21996ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 22006ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 22016ecaa68aSToby Isaac 22029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, anchor, &aLocalDof)); 22036ecaa68aSToby Isaac numColIndices += aLocalDof; 22046ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22056ecaa68aSToby Isaac PetscInt fDof; 22066ecaa68aSToby Isaac 22079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 220821968bf8SToby Isaac newOffsets[f + 1] += fDof; 22096ecaa68aSToby Isaac } 22106ecaa68aSToby Isaac } 22116ecaa68aSToby Isaac if (numFields) { 22126ecaa68aSToby Isaac matSize = 0; 2213ad540459SPierre Jolivet for (f = 0; f < numFields; f++) matSize += offsets[f + 1] * newOffsets[f + 1]; 22149371c9d4SSatish Balay } else { 22156ecaa68aSToby Isaac matSize = numColIndices * dof; 22166ecaa68aSToby Isaac } 22179371c9d4SSatish Balay } else { /* no children, and no constraints on dofs: just get the global indices */ 22186ecaa68aSToby Isaac numColIndices = dof; 22196ecaa68aSToby Isaac matSize = 0; 22206ecaa68aSToby Isaac } 22218d2f55e7SToby Isaac } 222246bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 22239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootIndicesSec, p, numColIndices ? numColIndices + 2 * numFields : 0)); 22249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootMatricesSec, p, matSize)); 22256ecaa68aSToby Isaac } 22269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootIndicesSec)); 22279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootMatricesSec)); 22286ecaa68aSToby Isaac { 22296ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 22306ecaa68aSToby Isaac 22319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 22329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootMatricesSec, &numRootMatrices)); 22339566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRootIndices, &rootIndices, numRootMatrices, &rootMatrices)); 22346ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22356ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2236f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 22376ecaa68aSToby Isaac PetscInt *pInd; 22386ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22396ecaa68aSToby Isaac PetscScalar *pMat = NULL; 22406ecaa68aSToby Isaac 22419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, p, &numColIndices)); 2242ad540459SPierre Jolivet if (!numColIndices) continue; 2243f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2244f13f9184SToby Isaac offsets[f] = 0; 2245f13f9184SToby Isaac newOffsets[f] = 0; 2246f13f9184SToby Isaac offsetsCopy[f] = 0; 2247f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2248f13f9184SToby Isaac } 22496ecaa68aSToby Isaac numColIndices -= 2 * numFields; 22509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, p, &pIndOff)); 22516ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 22529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootMatricesSec, p, &matSize)); 22536ecaa68aSToby Isaac if (matSize) { 22549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootMatricesSec, p, &pMatOff)); 22556ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 22566ecaa68aSToby Isaac } 22579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 2258ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 22596ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 22606ecaa68aSToby Isaac PetscInt i, j; 22616ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 22626ecaa68aSToby Isaac 22636ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 22646ecaa68aSToby Isaac PetscInt numIndices, *indices; 22659566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 226608401ef6SPierre Jolivet PetscCheck(numIndices == numColIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "mismatching constraint indices calculations"); 2267ad540459SPierre Jolivet for (i = 0; i < numColIndices; i++) pInd[i] = indices[i]; 22686ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 226946bdb399SToby Isaac pInd[numColIndices + i] = offsets[i + 1]; 227046bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i + 1]; 22716ecaa68aSToby Isaac } 22729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 22739371c9d4SSatish Balay } else { 22746ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 22756ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 22766ecaa68aSToby Isaac PetscInt numPoints, *points; 22776ecaa68aSToby Isaac 22789566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices * numRowIndices, MPIU_SCALAR, &pMatIn)); 22796ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 2280ad540459SPierre Jolivet for (j = 0; j < numRowIndices; j++) pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 22816ecaa68aSToby Isaac } 22829566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 22834acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 22849566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 22859566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 22864acb8e1eSToby Isaac } 22876ecaa68aSToby Isaac if (numFields) { 22886ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 22896ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 22906ecaa68aSToby Isaac 22916ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22926ecaa68aSToby Isaac PetscInt fDof; 22936ecaa68aSToby Isaac 22949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &fDof)); 22956ecaa68aSToby Isaac offsets[f + 1] += fDof; 22966ecaa68aSToby Isaac } 22976ecaa68aSToby Isaac } 22986ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22996ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23006ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 23016ecaa68aSToby Isaac } 23026ecaa68aSToby Isaac } 23034acb8e1eSToby Isaac /* TODO : flips here ? */ 23046ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 23059566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, perms, pMatIn, &numPoints, NULL, &points, &pMatModified, newOffsets, PETSC_FALSE)); 23064acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23079566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 23089566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 23094acb8e1eSToby Isaac } 23104acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23119566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23129566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23134acb8e1eSToby Isaac } 23146ecaa68aSToby Isaac if (!numFields) { 2315ad540459SPierre Jolivet for (i = 0; i < numRowIndices * numColIndices; i++) pMat[i] = pMatModified[i]; 23169371c9d4SSatish Balay } else { 2317f13f9184SToby Isaac PetscInt i, j, count; 23186ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 23196ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f + 1]; i++) { 2320ad540459SPierre Jolivet for (j = newOffsets[f]; j < newOffsets[f + 1]; j++, count++) pMat[count] = pMatModified[i * numColIndices + j]; 23216ecaa68aSToby Isaac } 23226ecaa68aSToby Isaac } 23236ecaa68aSToby Isaac } 23249566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatModified)); 23259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 23269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatIn)); 23276ecaa68aSToby Isaac if (numFields) { 232846bdb399SToby Isaac for (f = 0; f < numFields; f++) { 232946bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 233046bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 23316ecaa68aSToby Isaac } 23324acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23334acb8e1eSToby Isaac PetscInt globalOff, c = points[2 * cl]; 23349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23359566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd)); 23366ecaa68aSToby Isaac } 23376ecaa68aSToby Isaac } else { 23384acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23394acb8e1eSToby Isaac PetscInt c = points[2 * cl], globalOff; 23404acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 23414acb8e1eSToby Isaac 23429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23439566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd)); 23446ecaa68aSToby Isaac } 23456ecaa68aSToby Isaac } 23464acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23479566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23489566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23494acb8e1eSToby Isaac } 23509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numPoints, MPIU_SCALAR, &points)); 23516ecaa68aSToby Isaac } 23529371c9d4SSatish Balay } else if (matSize) { 23536ecaa68aSToby Isaac PetscInt cOff; 23546ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 23556ecaa68aSToby Isaac 23566ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 235708401ef6SPierre Jolivet PetscCheck(numRowIndices == dof, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Miscounted dofs"); 23589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 23599566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 23609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &cOff)); 23619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 23629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 23636ecaa68aSToby Isaac if (numFields) { 23646ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23656ecaa68aSToby Isaac PetscInt fDof; 2366f13f9184SToby Isaac 23679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &fDof)); 23686ecaa68aSToby Isaac offsets[f + 1] = fDof; 23696ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23706ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 23719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 23726ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 23736ecaa68aSToby Isaac } 23746ecaa68aSToby Isaac } 23756ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23766ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23776ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 23786ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 23796ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 23806ecaa68aSToby Isaac } 23819566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, -1, NULL, rowIndices)); 23826ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23836ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23859566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, -1, NULL, colIndices)); 23866ecaa68aSToby Isaac } 23879371c9d4SSatish Balay } else { 23889566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, NULL, rowIndices)); 23896ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23906ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23929566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, NULL, colIndices)); 23936ecaa68aSToby Isaac } 23946ecaa68aSToby Isaac } 23956ecaa68aSToby Isaac if (numFields) { 2396f13f9184SToby Isaac PetscInt count, a; 2397f13f9184SToby Isaac 23986ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 23996ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 24006ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 24019566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, iSize, &rowIndices[offsets[f]], jSize, &colIndices[newOffsets[f]], &pMat[count])); 24026ecaa68aSToby Isaac count += iSize * jSize; 240346bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 240446bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 24056ecaa68aSToby Isaac } 24066ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 24076ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 24086ecaa68aSToby Isaac PetscInt gOff; 24099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 24109566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 24116ecaa68aSToby Isaac } 24129371c9d4SSatish Balay } else { 24136ecaa68aSToby Isaac PetscInt a; 24149566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, numRowIndices, rowIndices, numColIndices, colIndices, pMat)); 24156ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 24166ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 24176ecaa68aSToby Isaac PetscInt gOff; 24189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 24199566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, NULL, pInd)); 24206ecaa68aSToby Isaac } 24216ecaa68aSToby Isaac } 24229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 24239566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 24249371c9d4SSatish Balay } else { 24256ecaa68aSToby Isaac PetscInt gOff; 24266ecaa68aSToby Isaac 24279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 24286ecaa68aSToby Isaac if (numFields) { 24296ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24306ecaa68aSToby Isaac PetscInt fDof; 24319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 24326ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 24336ecaa68aSToby Isaac } 24346ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 243546bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 243646bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f + 1]; 24376ecaa68aSToby Isaac } 24389566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 2439367003a6SStefano Zampini } else { 24409566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 24416ecaa68aSToby Isaac } 24426ecaa68aSToby Isaac } 24436ecaa68aSToby Isaac } 24449566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 24456ecaa68aSToby Isaac } 244646bdb399SToby Isaac { 244746bdb399SToby Isaac PetscSF indicesSF, matricesSF; 244846bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 244946bdb399SToby Isaac 24509566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 24519566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafMatricesSec)); 24529566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootIndicesSec, &remoteOffsetsIndices, leafIndicesSec)); 24539566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootMatricesSec, &remoteOffsetsMatrices, leafMatricesSec)); 24549566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootIndicesSec, remoteOffsetsIndices, leafIndicesSec, &indicesSF)); 24559566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootMatricesSec, remoteOffsetsMatrices, leafMatricesSec, &matricesSF)); 24569566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 24579566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsIndices)); 24589566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsMatrices)); 24599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numLeafIndices)); 24609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafMatricesSec, &numLeafMatrices)); 24619566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numLeafIndices, &leafIndices, numLeafMatrices, &leafMatrices)); 24629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24639566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24669566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&matricesSF)); 24679566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 24689566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootIndices, rootMatrices)); 24699566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 24709566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootMatricesSec)); 247146bdb399SToby Isaac } 247246bdb399SToby Isaac /* count to preallocate */ 24739566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 247446bdb399SToby Isaac { 247546bdb399SToby Isaac PetscInt nGlobal; 247646bdb399SToby Isaac PetscInt *dnnz, *onnz; 2477b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2478b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 24791c58ffc4SToby Isaac PetscInt maxDof; 24801c58ffc4SToby Isaac PetscInt *rowIndices; 24811c58ffc4SToby Isaac DM refTree; 24821c58ffc4SToby Isaac PetscInt **refPointFieldN; 24831c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 24841c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 24850eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, maxConDof, maxColumns, leafStart, leafEnd; 24861c58ffc4SToby Isaac PetscScalar *pointWork; 248746bdb399SToby Isaac 24889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalFine, &nGlobal)); 24899566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nGlobal, &dnnz, nGlobal, &onnz)); 24909566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 24919566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 24929566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 24939566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 24949566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 24959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 24969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafIndicesSec, &leafStart, &leafEnd)); 24979566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 24980eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 249946bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 250046bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 250146bdb399SToby Isaac PetscInt matSize; 250221968bf8SToby Isaac PetscInt i; 250346bdb399SToby Isaac 25049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 25059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 2506ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 25079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 250808401ef6SPierre Jolivet PetscCheck(gOff >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I though having global dofs meant a non-negative offset"); 25091dca8a05SBarry Smith PetscCheck(gOff >= rowStart && (gOff + gDof - gcDof) <= rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I thought the row map would constrain the global dofs"); 25109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 25119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 251246bdb399SToby Isaac numColIndices -= 2 * numFields; 251308401ef6SPierre Jolivet PetscCheck(numColIndices > 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "global fine dof with no dofs to interpolate from"); 251446bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 251521968bf8SToby Isaac offsets[0] = 0; 251621968bf8SToby Isaac offsetsCopy[0] = 0; 251721968bf8SToby Isaac newOffsets[0] = 0; 251821968bf8SToby Isaac newOffsetsCopy[0] = 0; 251946bdb399SToby Isaac if (numFields) { 252021968bf8SToby Isaac PetscInt f; 252146bdb399SToby Isaac for (f = 0; f < numFields; f++) { 252246bdb399SToby Isaac PetscInt rowDof; 252346bdb399SToby Isaac 25249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 252521968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 252621968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 252721968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 252821968bf8SToby Isaac numD[f] = 0; 252921968bf8SToby Isaac numO[f] = 0; 253046bdb399SToby Isaac } 25319566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 253246bdb399SToby Isaac for (f = 0; f < numFields; f++) { 253321968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 253421968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 253546bdb399SToby Isaac 253646bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 253746bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 253846bdb399SToby Isaac 253946bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 254021968bf8SToby Isaac numD[f]++; 25419371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 254221968bf8SToby Isaac numO[f]++; 254346bdb399SToby Isaac } 254446bdb399SToby Isaac } 254546bdb399SToby Isaac } 25469371c9d4SSatish Balay } else { 25479566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 254821968bf8SToby Isaac numD[0] = 0; 254921968bf8SToby Isaac numO[0] = 0; 255046bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 255146bdb399SToby Isaac PetscInt gInd = pInd[i]; 255246bdb399SToby Isaac 255346bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 255421968bf8SToby Isaac numD[0]++; 25559371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 255621968bf8SToby Isaac numO[0]++; 255746bdb399SToby Isaac } 255846bdb399SToby Isaac } 255946bdb399SToby Isaac } 25609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 256146bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 256246bdb399SToby Isaac PetscInt childId; 256346bdb399SToby Isaac 256446bdb399SToby Isaac childId = childIds[p - pStartF]; 256521968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 256646bdb399SToby Isaac if (numFields) { 2567b9a5774bSToby Isaac PetscInt f; 2568b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 256921968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 257046bdb399SToby Isaac for (row = 0; row < numRows; row++) { 257121968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 257221968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 257346bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25741dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2575b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25769371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25771dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2578b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25799371c9d4SSatish Balay } else { /* constrained */ 258008401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 258146bdb399SToby Isaac } 258246bdb399SToby Isaac } 258346bdb399SToby Isaac } 25849371c9d4SSatish Balay } else { 2585b9a5774bSToby Isaac PetscInt i; 2586b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 258746bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 258846bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 258946bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25901dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2591b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25929371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25931dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2594b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25959371c9d4SSatish Balay } else { /* constrained */ 259608401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 259746bdb399SToby Isaac } 259846bdb399SToby Isaac } 259946bdb399SToby Isaac } 26009371c9d4SSatish Balay } else { /* interpolate from all */ 260146bdb399SToby Isaac if (numFields) { 2602b9a5774bSToby Isaac PetscInt f; 2603b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 260421968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 260546bdb399SToby Isaac for (row = 0; row < numRows; row++) { 260621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 260746bdb399SToby Isaac if (gIndFine >= 0) { 26081dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2609b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2610b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 261146bdb399SToby Isaac } 261246bdb399SToby Isaac } 261346bdb399SToby Isaac } 26149371c9d4SSatish Balay } else { 2615b9a5774bSToby Isaac PetscInt i; 2616b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 261746bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 261846bdb399SToby Isaac if (gIndFine >= 0) { 26191dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2620b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2621b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 262246bdb399SToby Isaac } 262346bdb399SToby Isaac } 262446bdb399SToby Isaac } 262546bdb399SToby Isaac } 26269371c9d4SSatish Balay } else { /* interpolate from all */ 262746bdb399SToby Isaac if (numFields) { 2628b9a5774bSToby Isaac PetscInt f; 2629b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 263021968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 263146bdb399SToby Isaac for (row = 0; row < numRows; row++) { 263221968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 263346bdb399SToby Isaac if (gIndFine >= 0) { 26341dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2635b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2636b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 263746bdb399SToby Isaac } 263846bdb399SToby Isaac } 263946bdb399SToby Isaac } 26409371c9d4SSatish Balay } else { /* every dof get a full row */ 2641b9a5774bSToby Isaac PetscInt i; 2642b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 264346bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 264446bdb399SToby Isaac if (gIndFine >= 0) { 26451dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2646b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2647b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 264846bdb399SToby Isaac } 264946bdb399SToby Isaac } 265046bdb399SToby Isaac } 265146bdb399SToby Isaac } 265246bdb399SToby Isaac } 26539566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, dnnz, onnz, NULL, NULL)); 26549566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnnz, onnz)); 265521968bf8SToby Isaac 26569566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 26579566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 26589566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 26599566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 26609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 26619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxConDof)); 26629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(leafIndicesSec, &maxColumns)); 26639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConDof * maxColumns, &pointWork)); 26640eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2665e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2666e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2667e44e4e7fSToby Isaac PetscInt matSize; 2668e44e4e7fSToby Isaac PetscInt childId; 2669e44e4e7fSToby Isaac 26709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 26719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 2672ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 2673e44e4e7fSToby Isaac childId = childIds[p - pStartF]; 26749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 26759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 26769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 2677e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2678e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2679e44e4e7fSToby Isaac offsets[0] = 0; 2680e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2681e44e4e7fSToby Isaac newOffsets[0] = 0; 2682e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2683e44e4e7fSToby Isaac rowOffsets[0] = 0; 2684e44e4e7fSToby Isaac if (numFields) { 2685e44e4e7fSToby Isaac PetscInt f; 2686e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2687e44e4e7fSToby Isaac PetscInt rowDof; 2688e44e4e7fSToby Isaac 26899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 2690e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2691e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2692e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2693e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2694e44e4e7fSToby Isaac } 26959566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 26969371c9d4SSatish Balay } else { 26979566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 26981c58ffc4SToby Isaac } 26999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 2700e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2701e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2702e44e4e7fSToby Isaac if (numFields) { 2703e44e4e7fSToby Isaac PetscInt f; 2704e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2705e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 270648a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[offsets[f] + row], pInd[newOffsets[f] + row], 1., INSERT_VALUES)); 270721968bf8SToby Isaac } 27089371c9d4SSatish Balay } else { 2709e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 271048a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[row], pInd[row], 1., INSERT_VALUES)); 2711e44e4e7fSToby Isaac } 27129371c9d4SSatish Balay } else { /* interpolate from all */ 2713e44e4e7fSToby Isaac if (numFields) { 2714e44e4e7fSToby Isaac PetscInt f; 2715e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2716e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2717e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 27189566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], refPointFieldMats[childId - pRefStart][f], INSERT_VALUES)); 2719e44e4e7fSToby Isaac } 27209371c9d4SSatish Balay } else { 27219566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, refPointFieldMats[childId - pRefStart][0], INSERT_VALUES)); 2722e44e4e7fSToby Isaac } 2723e44e4e7fSToby Isaac } 27249371c9d4SSatish Balay } else { /* interpolate from all */ 2725e44e4e7fSToby Isaac PetscInt pMatOff; 2726e44e4e7fSToby Isaac PetscScalar *pMat; 2727e44e4e7fSToby Isaac 27289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafMatricesSec, p, &pMatOff)); 2729e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2730e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2731e44e4e7fSToby Isaac if (numFields) { 2732e44e4e7fSToby Isaac PetscInt f, count; 2733e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2734e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2735e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2736e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2737e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2738e44e4e7fSToby Isaac 27399566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], inMat, INSERT_VALUES)); 2740e44e4e7fSToby Isaac count += numCols * numInRows; 2741e44e4e7fSToby Isaac } 27429371c9d4SSatish Balay } else { 27439566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, pMat, INSERT_VALUES)); 2744e44e4e7fSToby Isaac } 27459371c9d4SSatish Balay } else { /* multiply the incoming matrix by the child interpolation */ 2746e44e4e7fSToby Isaac if (numFields) { 2747e44e4e7fSToby Isaac PetscInt f, count; 2748e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2749e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2750e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2751e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2752e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2753e44e4e7fSToby Isaac PetscInt i, j, k; 275408401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][f] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2755e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2756e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2757e44e4e7fSToby Isaac PetscScalar val = 0.; 2758ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2759e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2760e44e4e7fSToby Isaac } 2761e44e4e7fSToby Isaac } 27629566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], pointWork, INSERT_VALUES)); 2763e44e4e7fSToby Isaac count += numCols * numInRows; 2764e44e4e7fSToby Isaac } 27659371c9d4SSatish Balay } else { /* every dof gets a full row */ 2766e44e4e7fSToby Isaac PetscInt numRows = gDof; 2767e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2768e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2769e44e4e7fSToby Isaac PetscInt i, j, k; 277008401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][0] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2771e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2772e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2773e44e4e7fSToby Isaac PetscScalar val = 0.; 2774ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2775e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2776e44e4e7fSToby Isaac } 2777e44e4e7fSToby Isaac } 27789566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, rowIndices, numCols, pInd, pointWork, INSERT_VALUES)); 2779e44e4e7fSToby Isaac } 2780e44e4e7fSToby Isaac } 2781e44e4e7fSToby Isaac } 2782e44e4e7fSToby Isaac } 27839566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 27849566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 27859566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 2786e44e4e7fSToby Isaac } 27879566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 27889566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 27899566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 27909566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafMatricesSec)); 27919566063dSJacob Faibussowitsch PetscCall(PetscFree2(leafIndices, leafMatrices)); 27929566063dSJacob Faibussowitsch PetscCall(PetscFree2(*(PetscInt ****)&perms, *(PetscScalar ****)&flips)); 27939566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 27949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 27953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27966ecaa68aSToby Isaac } 2797154bca37SToby Isaac 27988d2f55e7SToby Isaac /* 27998d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 28008d2f55e7SToby Isaac * 28018d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 28028d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 28038d2f55e7SToby Isaac * for each fine dof \phi^f_j; 28048d2f55e7SToby Isaac * a_{i,j} = 0; 28058d2f55e7SToby Isaac * for each fine dof \phi^f_k: 28068d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 28078d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 28088d2f55e7SToby Isaac */ 2809d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 2810d71ae5a4SJacob Faibussowitsch { 28118d2f55e7SToby Isaac PetscDS ds; 28128d2f55e7SToby Isaac PetscSection section, cSection; 28138d2f55e7SToby Isaac DMLabel canonical, depth; 28148d2f55e7SToby Isaac Mat cMat, mat; 28158d2f55e7SToby Isaac PetscInt *nnz; 28168d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 28178d2f55e7SToby Isaac PetscInt m, n; 28188d2f55e7SToby Isaac PetscScalar *pointScalar; 28198d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 28208d2f55e7SToby Isaac 28218d2f55e7SToby Isaac PetscFunctionBegin; 28229566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, §ion)); 28239566063dSJacob Faibussowitsch PetscCall(DMGetDimension(refTree, &dim)); 28249566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(dim, &v0, dim, &v0parent, dim, &vtmp, dim * dim, &J, dim * dim, &Jparent, dim * dim, &invJ)); 28259566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim, &pointScalar, dim, &pointRef)); 28269566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 28279566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 28289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numSecFields)); 28299566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical)); 28309566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "depth", &depth)); 28319566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSection, &cMat, NULL)); 28329566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(refTree, &pStart, &pEnd)); 28339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd)); 28349566063dSJacob Faibussowitsch PetscCall(MatGetSize(cMat, &n, &m)); /* the injector has transpose sizes from the constraint matrix */ 28358d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 28369566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 28378d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { /* a point will have non-zeros if it is canonical, it has dofs, and its children have dofs */ 28388d2f55e7SToby Isaac const PetscInt *children; 28398d2f55e7SToby Isaac PetscInt numChildren; 28408d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28418d2f55e7SToby Isaac 28428d2f55e7SToby Isaac if (canonical) { 28438d2f55e7SToby Isaac PetscInt pCanonical; 28449566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28458d2f55e7SToby Isaac if (p != pCanonical) continue; 28468d2f55e7SToby Isaac } 28479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28488d2f55e7SToby Isaac if (!numChildren) continue; 28498d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28508d2f55e7SToby Isaac PetscInt child = children[i]; 28518d2f55e7SToby Isaac PetscInt dof; 28528d2f55e7SToby Isaac 28539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 28548d2f55e7SToby Isaac numChildDof += dof; 28558d2f55e7SToby Isaac } 28569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 28578d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 28588d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 28598d2f55e7SToby Isaac PetscInt selfOff; 28608d2f55e7SToby Isaac 28618d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 28628d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28638d2f55e7SToby Isaac PetscInt child = children[i]; 28648d2f55e7SToby Isaac PetscInt dof; 28658d2f55e7SToby Isaac 28669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 28678d2f55e7SToby Isaac numChildDof += dof; 28688d2f55e7SToby Isaac } 28699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 28709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 28719371c9d4SSatish Balay } else { 28729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 28738d2f55e7SToby Isaac } 2874ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) nnz[selfOff + i] = numChildDof; 28758d2f55e7SToby Isaac } 28768d2f55e7SToby Isaac } 28779566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(PETSC_COMM_SELF, m, n, m, n, -1, nnz, -1, NULL, &mat)); 28789566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 28798d2f55e7SToby Isaac /* Setp 2: compute entries */ 28808d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 28818d2f55e7SToby Isaac const PetscInt *children; 28828d2f55e7SToby Isaac PetscInt numChildren; 28838d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28848d2f55e7SToby Isaac 28858d2f55e7SToby Isaac /* same conditions about when entries occur */ 28868d2f55e7SToby Isaac if (canonical) { 28878d2f55e7SToby Isaac PetscInt pCanonical; 28889566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28898d2f55e7SToby Isaac if (p != pCanonical) continue; 28908d2f55e7SToby Isaac } 28919566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28928d2f55e7SToby Isaac if (!numChildren) continue; 28938d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28948d2f55e7SToby Isaac PetscInt child = children[i]; 28958d2f55e7SToby Isaac PetscInt dof; 28968d2f55e7SToby Isaac 28979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 28988d2f55e7SToby Isaac numChildDof += dof; 28998d2f55e7SToby Isaac } 29009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 29018d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 29028d2f55e7SToby Isaac 29038d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 290459fc6756SToby Isaac PetscInt pI = -1, cI = -1; 290552a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell; 29068d2f55e7SToby Isaac PetscInt cellShapeOff; 29078d2f55e7SToby Isaac PetscObject disc; 29088d2f55e7SToby Isaac PetscDualSpace dsp; 29098d2f55e7SToby Isaac PetscClassId classId; 29108d2f55e7SToby Isaac PetscScalar *pointMat; 29113b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 29128d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 29138d2f55e7SToby Isaac const PetscInt *depthNumDof; 29148d2f55e7SToby Isaac 29158d2f55e7SToby Isaac if (numSecFields) { 29168d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 29178d2f55e7SToby Isaac PetscInt child = children[i]; 29188d2f55e7SToby Isaac PetscInt dof; 29198d2f55e7SToby Isaac 29209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 29218d2f55e7SToby Isaac numChildDof += dof; 29228d2f55e7SToby Isaac } 29239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 29249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 29259371c9d4SSatish Balay } else { 29269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 29278d2f55e7SToby Isaac } 29288d2f55e7SToby Isaac 29293b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 29308d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 29318d2f55e7SToby Isaac parentCell = p; 29329371c9d4SSatish Balay } else { 29338d2f55e7SToby Isaac PetscInt *star = NULL; 29348d2f55e7SToby Isaac PetscInt numStar; 29358d2f55e7SToby Isaac 29368d2f55e7SToby Isaac parentCell = -1; 29379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29388d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 29398d2f55e7SToby Isaac PetscInt c = star[2 * i]; 29408d2f55e7SToby Isaac 29418d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 29428d2f55e7SToby Isaac parentCell = c; 29438d2f55e7SToby Isaac break; 29448d2f55e7SToby Isaac } 29458d2f55e7SToby Isaac } 29469566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29478d2f55e7SToby Isaac } 2948a5b23f4aSJose E. Roman /* determine the offset of p's shape functions within parentCell's shape functions */ 29499566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 29509566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &classId)); 2951c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 29529566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 29539371c9d4SSatish Balay } else if (classId == PETSCFV_CLASSID) { 29549566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace((PetscFV)disc, &dsp)); 29559371c9d4SSatish Balay } else { 29569b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported discretization object"); 2957c5356c36SToby Isaac } 29589566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dsp, &depthNumDof)); 29599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dsp, &Nc)); 29608d2f55e7SToby Isaac { 29618d2f55e7SToby Isaac PetscInt *closure = NULL; 29628d2f55e7SToby Isaac PetscInt numClosure; 29638d2f55e7SToby Isaac 29649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 296559fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) { 29668d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 29678d2f55e7SToby Isaac 29688d2f55e7SToby Isaac pO = closure[2 * i + 1]; 296959fc6756SToby Isaac if (point == p) { 297059fc6756SToby Isaac pI = i; 297159fc6756SToby Isaac break; 297259fc6756SToby Isaac } 29739566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 29748d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 29758d2f55e7SToby Isaac } 29769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 29778d2f55e7SToby Isaac } 29788d2f55e7SToby Isaac 29799566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 29809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 298152a3aeb4SToby Isaac matCols = matRows + numSelfDof; 2982ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) matRows[i] = selfOff + i; 298352a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.; 29843b1c2a6aSToby Isaac { 29853b1c2a6aSToby Isaac PetscInt colOff = 0; 29863b1c2a6aSToby Isaac 29873b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 29883b1c2a6aSToby Isaac PetscInt child = children[i]; 29893b1c2a6aSToby Isaac PetscInt dof, off, j; 29903b1c2a6aSToby Isaac 29913b1c2a6aSToby Isaac if (numSecFields) { 29929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSection, child, f, &dof)); 29939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSection, child, f, &off)); 29949371c9d4SSatish Balay } else { 29959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSection, child, &dof)); 29969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSection, child, &off)); 29973b1c2a6aSToby Isaac } 29983b1c2a6aSToby Isaac 2999ad540459SPierre Jolivet for (j = 0; j < dof; j++) matCols[colOff++] = off + j; 30003b1c2a6aSToby Isaac } 30013b1c2a6aSToby Isaac } 30028d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 30038d2f55e7SToby Isaac PetscFE fe = (PetscFE)disc; 30048d2f55e7SToby Isaac PetscInt fSize; 300559fc6756SToby Isaac const PetscInt ***perms; 300659fc6756SToby Isaac const PetscScalar ***flips; 300759fc6756SToby Isaac const PetscInt *pperms; 300859fc6756SToby Isaac 30099566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dsp)); 30109566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dsp, &fSize)); 30119566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dsp, &perms, &flips)); 301259fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL; 301352a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */ 30148d2f55e7SToby Isaac PetscQuadrature q; 301552a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k; 30168d2f55e7SToby Isaac const PetscReal *points; 30178d2f55e7SToby Isaac const PetscReal *weights; 30188d2f55e7SToby Isaac PetscInt *closure = NULL; 30198d2f55e7SToby Isaac PetscInt numClosure; 302059fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i; 302159fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell; 3022ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent; 30238d2f55e7SToby Isaac 30249566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dsp, parentCellShapeDof, &q)); 30259566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, &thisNc, &numPoints, &points, &weights)); 302663a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 30279566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, numPoints, points, 0, &Tparent)); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 30283b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 30298d2f55e7SToby Isaac PetscInt childCell = -1; 303052a3aeb4SToby Isaac PetscReal *parentValAtPoint; 3031c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 30328d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 30338d2f55e7SToby Isaac const PetscScalar *point; 3034ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild; 30358d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 30368d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 30378d2f55e7SToby Isaac PetscInt d; 30388d2f55e7SToby Isaac 3039ad540459SPierre Jolivet for (d = 0; d < dim; d++) pointScalar[d] = points[dim * j + d]; 30408d2f55e7SToby Isaac point = pointScalar; 30418d2f55e7SToby Isaac #else 30428d2f55e7SToby Isaac point = pointReal; 30438d2f55e7SToby Isaac #endif 30448d2f55e7SToby Isaac 3045ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc]; 30463b1c2a6aSToby Isaac 30473b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 30488d2f55e7SToby Isaac PetscInt child = children[k]; 30498d2f55e7SToby Isaac PetscInt *star = NULL; 30508d2f55e7SToby Isaac PetscInt numStar, s; 30518d2f55e7SToby Isaac 30529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30538d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 30548d2f55e7SToby Isaac PetscInt c = star[2 * s]; 30558d2f55e7SToby Isaac 30568d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 30579566063dSJacob Faibussowitsch PetscCall(DMPlexLocatePoint_Internal(refTree, dim, point, c, &childCell)); 30588d2f55e7SToby Isaac if (childCell >= 0) break; 30598d2f55e7SToby Isaac } 30609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30618d2f55e7SToby Isaac if (childCell >= 0) break; 30628d2f55e7SToby Isaac } 306308401ef6SPierre Jolivet PetscCheck(childCell >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not locate quadrature point"); 30649566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ)); 30659566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent)); 3066c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp); 3067c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef); 30688d2f55e7SToby Isaac 30699566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, 1, pointRef, 0, &Tchild)); 30709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 30713b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3072c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 30738d2f55e7SToby Isaac PetscInt l; 307459fc6756SToby Isaac const PetscInt *cperms; 30758d2f55e7SToby Isaac 30769566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, child, &childDepth)); 30778d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 307859fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) { 30798d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 30808d2f55e7SToby Isaac PetscInt pointDepth; 30818d2f55e7SToby Isaac 30828d2f55e7SToby Isaac childO = closure[2 * l + 1]; 308359fc6756SToby Isaac if (point == child) { 308459fc6756SToby Isaac cI = l; 308559fc6756SToby Isaac break; 308659fc6756SToby Isaac } 30879566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 30888d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 30898d2f55e7SToby Isaac } 30908d2f55e7SToby Isaac if (l == numClosure) { 30918d2f55e7SToby Isaac pointMatOff += childDof; 30928d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 30938d2f55e7SToby Isaac } 309459fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL; 30958d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 309659fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l; 309759fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell; 309852a3aeb4SToby Isaac PetscReal *childValAtPoint; 309952a3aeb4SToby Isaac PetscReal val = 0.; 31008d2f55e7SToby Isaac 3101ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc]; 3102ad540459SPierre Jolivet for (m = 0; m < Nc; m++) val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m]; 310352a3aeb4SToby Isaac 310452a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val; 31058d2f55e7SToby Isaac } 31068d2f55e7SToby Isaac pointMatOff += childDof; 31078d2f55e7SToby Isaac } 31089566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 31099566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tchild)); 31108d2f55e7SToby Isaac } 31119566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tparent)); 31128d2f55e7SToby Isaac } 31139371c9d4SSatish Balay } else { /* just the volume-weighted averages of the children */ 31143b1c2a6aSToby Isaac PetscReal parentVol; 3115bfaa5bdcSToby Isaac PetscInt childCell; 31163b1c2a6aSToby Isaac 31179566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL)); 3118bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) { 311952a3aeb4SToby Isaac PetscInt child = children[i], j; 31203b1c2a6aSToby Isaac PetscReal childVol; 31213b1c2a6aSToby Isaac 31223b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 31239566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL)); 3124ad540459SPierre Jolivet for (j = 0; j < Nc; j++) pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol; 3125bfaa5bdcSToby Isaac childCell++; 31263b1c2a6aSToby Isaac } 31278d2f55e7SToby Isaac } 31283b1c2a6aSToby Isaac /* Insert pointMat into mat */ 31299566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numSelfDof, matRows, numChildDof, matCols, pointMat, INSERT_VALUES)); 31309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 31319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 31328d2f55e7SToby Isaac } 31338d2f55e7SToby Isaac } 31349566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJ)); 31359566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointScalar, pointRef)); 31369566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 31379566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 31388d2f55e7SToby Isaac *inj = mat; 31393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31408d2f55e7SToby Isaac } 31418d2f55e7SToby Isaac 3142d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3143d71ae5a4SJacob Faibussowitsch { 3144f30e825dSToby Isaac PetscDS ds; 3145f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3146f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3147f30e825dSToby Isaac PetscSection refConSec, refSection; 3148f30e825dSToby Isaac 3149f30e825dSToby Isaac PetscFunctionBegin; 31509566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 31519566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 31529566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 31539566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 31549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 31559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 31569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 31579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 31589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &cols)); 3159f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3160f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3161f30e825dSToby Isaac 31629566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 31639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 31649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3165f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3166f30e825dSToby Isaac 31679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFields, &refPointFieldMats[p - pRefStart])); 3168f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 316952a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r; 3170f30e825dSToby Isaac 3171f30e825dSToby Isaac if (numFields > 1) { 31729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 31739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 31749371c9d4SSatish Balay } else { 31759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 31769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 3177f30e825dSToby Isaac } 3178f30e825dSToby Isaac 3179ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r; 3180f30e825dSToby Isaac numCols = 0; 3181f30e825dSToby Isaac { 3182f30e825dSToby Isaac PetscInt aDof, aOff, j; 3183f30e825dSToby Isaac 3184f30e825dSToby Isaac if (numFields > 1) { 31859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, parent, f, &aDof)); 31869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, parent, f, &aOff)); 31879371c9d4SSatish Balay } else { 31889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &aDof)); 31899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, parent, &aOff)); 3190f30e825dSToby Isaac } 3191f30e825dSToby Isaac 3192ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + j; 3193f30e825dSToby Isaac } 31949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 3195f30e825dSToby Isaac /* transpose of constraint matrix */ 31969566063dSJacob Faibussowitsch PetscCall(MatGetValues(inj, numCols, cols, cDof, rows, refPointFieldMats[p - pRefStart][f])); 3197f30e825dSToby Isaac } 3198f30e825dSToby Isaac } 3199f30e825dSToby Isaac *childrenMats = refPointFieldMats; 32009566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 32019566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 32023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3203f30e825dSToby Isaac } 3204f30e825dSToby Isaac 3205d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3206d71ae5a4SJacob Faibussowitsch { 3207f30e825dSToby Isaac PetscDS ds; 3208f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3209f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3210c6154584SToby Isaac PetscSection refConSec, refSection; 3211f30e825dSToby Isaac 3212f30e825dSToby Isaac PetscFunctionBegin; 3213f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3214f30e825dSToby Isaac *childrenMats = NULL; 32159566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 32169566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 32179566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 32189566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 32199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 3220f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3221f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3222f30e825dSToby Isaac 32239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 32249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 32259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3226f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3227f30e825dSToby Isaac 3228f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3229f30e825dSToby Isaac PetscInt cDof; 3230f30e825dSToby Isaac 3231f30e825dSToby Isaac if (numFields > 1) { 32329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 32339371c9d4SSatish Balay } else { 32349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 3235f30e825dSToby Isaac } 3236f30e825dSToby Isaac 32379566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 3238f30e825dSToby Isaac } 32399566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 3240f30e825dSToby Isaac } 32419566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 32423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3243f30e825dSToby Isaac } 3244f30e825dSToby Isaac 3245d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree, Mat *injRef) 3246d71ae5a4SJacob Faibussowitsch { 3247ebf164c7SToby Isaac Mat cMatRef; 32486148253fSToby Isaac PetscObject injRefObj; 32498d2f55e7SToby Isaac 3250154bca37SToby Isaac PetscFunctionBegin; 32519566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, NULL, &cMatRef, NULL)); 32529566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", &injRefObj)); 3253ebf164c7SToby Isaac *injRef = (Mat)injRefObj; 3254ebf164c7SToby Isaac if (!*injRef) { 32559566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorReferenceTree(refTree, injRef)); 32569566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", (PetscObject)*injRef)); 3257ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 32589566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)*injRef)); 3259ebf164c7SToby Isaac } 32603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32616148253fSToby Isaac } 3262f30e825dSToby Isaac 3263d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, const PetscInt *childIds, Vec fineVec, PetscInt numFields, PetscInt *offsets, PetscSection *rootMultiSec, PetscSection *multiLeafSec, PetscInt **gatheredIndices, PetscScalar **gatheredValues) 3264d71ae5a4SJacob Faibussowitsch { 3265c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3266ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3267ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3268c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3269c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3270c921d74cSToby Isaac const PetscInt *rootDegrees; 3271c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3272ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3273ebf164c7SToby Isaac 3274ebf164c7SToby Isaac PetscFunctionBegin; 32759566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 32769566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 32779566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 32789566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 32799566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 32809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafIndicesSec, pStartF, pEndF)); 32819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 32828d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 32837e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 32847e96bdafSToby Isaac const PetscInt *leaves; 32858d2f55e7SToby Isaac 32869566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 32877e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 32887e96bdafSToby Isaac p = leaves ? leaves[l] : l; 32899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 32909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 32918d2f55e7SToby Isaac if ((dof - cdof) > 0) { 32928d2f55e7SToby Isaac numPointsWithDofs++; 3293f30e825dSToby Isaac 32949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &dof)); 32959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafIndicesSec, p, dof + 1)); 32968d2f55e7SToby Isaac } 32978d2f55e7SToby Isaac } 32989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 32999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafIndicesSec)); 33009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numIndices)); 33019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1), &leafInds)); 33029566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(PetscMalloc1(numIndices, &leafVals)); 33037e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 33047e96bdafSToby Isaac p = leaves ? leaves[l] : l; 33059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 33069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 33078d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3308f30e825dSToby Isaac PetscInt off, gOff; 3309f30e825dSToby Isaac PetscInt *pInd; 3310c921d74cSToby Isaac PetscScalar *pVal = NULL; 3311f30e825dSToby Isaac 33127e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3313f30e825dSToby Isaac 33149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3315f30e825dSToby Isaac 3316c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3317c921d74cSToby Isaac if (gatheredValues) { 3318c921d74cSToby Isaac PetscInt i; 3319c921d74cSToby Isaac 3320c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3321c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3322c921d74cSToby Isaac } 33239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 3324f30e825dSToby Isaac 3325f30e825dSToby Isaac offsets[0] = 0; 3326f30e825dSToby Isaac if (numFields) { 3327f30e825dSToby Isaac PetscInt f; 3328f30e825dSToby Isaac 3329f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3330f30e825dSToby Isaac PetscInt fDof; 33319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &fDof)); 3332f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3333f30e825dSToby Isaac } 33349566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 3335367003a6SStefano Zampini } else { 33369566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 3337f30e825dSToby Isaac } 33389566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(VecGetValues(fineVec, dof, pInd, pVal)); 33398d2f55e7SToby Isaac } 33408d2f55e7SToby Isaac } 33419566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 33429566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 33438d2f55e7SToby Isaac } 3344f30e825dSToby Isaac 33459566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 33469566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 33479566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 3348f30e825dSToby Isaac 33496148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 33506148253fSToby Isaac MPI_Datatype threeInt; 33516148253fSToby Isaac PetscMPIInt rank; 33526148253fSToby Isaac PetscInt(*parentNodeAndIdCoarse)[3]; 33536148253fSToby Isaac PetscInt(*parentNodeAndIdFine)[3]; 33546148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 33556148253fSToby Isaac PetscSF pointSF, sfToParents; 33566148253fSToby Isaac const PetscInt *ilocal; 33576148253fSToby Isaac const PetscSFNode *iremote; 33586148253fSToby Isaac PetscSFNode *iremoteToParents; 33596148253fSToby Isaac PetscInt *ilocalToParents; 33606148253fSToby Isaac 33619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)coarse), &rank)); 33629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &threeInt)); 33639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&threeInt)); 33649566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndC - pStartC, &parentNodeAndIdCoarse, pEndF - pStartF, &parentNodeAndIdFine)); 33659566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(coarse, &pointSF)); 33669566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &nleaves, &ilocal, &iremote)); 33676148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 33686148253fSToby Isaac PetscInt parent, childId; 33699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(coarse, p, &parent, &childId)); 33706148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 33716148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 33726148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 33736148253fSToby Isaac if (nleaves > 0) { 33746148253fSToby Isaac PetscInt leaf = -1; 33756148253fSToby Isaac 33766148253fSToby Isaac if (ilocal) { 33779566063dSJacob Faibussowitsch PetscCall(PetscFindInt(parent, nleaves, ilocal, &leaf)); 33789371c9d4SSatish Balay } else { 33796148253fSToby Isaac leaf = p - pStartC; 33806148253fSToby Isaac } 33816148253fSToby Isaac if (leaf >= 0) { 33826148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 33836148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 33846148253fSToby Isaac } 33856148253fSToby Isaac } 33866148253fSToby Isaac } 33876148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 33886148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 33896148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 33906148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 33916148253fSToby Isaac } 33929566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 33939566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 33946148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3395f30e825dSToby Isaac PetscInt dof; 3396f30e825dSToby Isaac 33979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &dof)); 3398f30e825dSToby Isaac if (dof) { 3399f30e825dSToby Isaac PetscInt off; 3400f30e825dSToby Isaac 34019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3402c921d74cSToby Isaac if (gatheredIndices) { 3403c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3404c921d74cSToby Isaac } else if (gatheredValues) { 3405c921d74cSToby Isaac leafVals[off] = (PetscScalar)PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3406c921d74cSToby Isaac } 3407f30e825dSToby Isaac } 3408ad540459SPierre Jolivet if (parentNodeAndIdFine[p - pStartF][0] >= 0) nleavesToParents++; 34096148253fSToby Isaac } 34109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &ilocalToParents)); 34119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &iremoteToParents)); 34126148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 34136148253fSToby Isaac if (parentNodeAndIdFine[p - pStartF][0] >= 0) { 34146148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 34156148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p - pStartF][0]; 34166148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p - pStartF][1]; 34176148253fSToby Isaac nleavesToParents++; 34186148253fSToby Isaac } 34196148253fSToby Isaac } 34209566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)coarse), &sfToParents)); 34219566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfToParents, pEndC - pStartC, nleavesToParents, ilocalToParents, PETSC_OWN_POINTER, iremoteToParents, PETSC_OWN_POINTER)); 34229566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34236148253fSToby Isaac 34246148253fSToby Isaac coarseToFineEmbedded = sfToParents; 34256148253fSToby Isaac 34269566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentNodeAndIdCoarse, parentNodeAndIdFine)); 34279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&threeInt)); 34286148253fSToby Isaac } 3429f30e825dSToby Isaac 34306148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 34316148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 34326148253fSToby Isaac PetscSF sfDofsOnly; 34336148253fSToby Isaac 34346148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 34359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3437ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 34386148253fSToby Isaac } 34399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 34406148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 34419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3443ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = p - pStartC; 34446148253fSToby Isaac } 34459566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly)); 34469566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34479566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 34486148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 34496148253fSToby Isaac } 3450f30e825dSToby Isaac 34516148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 34529566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(coarseToFineEmbedded, &rootDegrees)); 34539566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(coarseToFineEmbedded, &rootDegrees)); 34549566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &multiRootSec)); 34559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(multiRootSec, pStartC, pEndC)); 345648a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionSetDof(multiRootSec, p, rootDegrees[p - pStartC])); 34579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(multiRootSec)); 34589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(multiRootSec, &numMulti)); 34599566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 3460f30e825dSToby Isaac { /* distribute the leaf section */ 3461f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3462f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 34638d2f55e7SToby Isaac 34649566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(coarseToFineEmbedded, &multi)); 34659566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(multi, &multiInv)); 34669566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(multiInv, leafIndicesSec, &remoteOffsets, rootIndicesSec)); 34679566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(multiInv, leafIndicesSec, remoteOffsets, rootIndicesSec, &indicesSF)); 34689566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 34699566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&multiInv)); 34709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 3471c921d74cSToby Isaac if (gatheredIndices) { 34729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootInds)); 34739566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 34749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 3475c921d74cSToby Isaac } 3476c921d74cSToby Isaac if (gatheredValues) { 34779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootVals)); 34789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 34799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 3480c921d74cSToby Isaac } 34819566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 34828d2f55e7SToby Isaac } 34839566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 34849566063dSJacob Faibussowitsch PetscCall(PetscFree(leafInds)); 34859566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVals)); 34869566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 3487c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3488c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3489c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3490c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 34913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3492ebf164c7SToby Isaac } 3493ebf164c7SToby Isaac 3494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3495d71ae5a4SJacob Faibussowitsch { 3496ebf164c7SToby Isaac DM refTree; 3497c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3498ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3499ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3500ebf164c7SToby Isaac PetscSection cSecRef; 3501277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd; 3502ebf164c7SToby Isaac Mat injRef; 3503c921d74cSToby Isaac PetscInt numFields, maxDof; 3504ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3505ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3506ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3507ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3508ebf164c7SToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3509ebf164c7SToby Isaac 3510ebf164c7SToby Isaac PetscFunctionBegin; 3511ebf164c7SToby Isaac 3512ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 35139566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 35149566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 35159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 35169566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 3517ebf164c7SToby Isaac 35189566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 35199566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 35209566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 35219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 35229566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 35239566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 35249566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 35259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 3526ebf164c7SToby Isaac { 3527ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 35289566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 3529ebf164c7SToby Isaac } 3530ebf164c7SToby Isaac 35319566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, childIds, NULL, numFields, offsets, &multiRootSec, &rootIndicesSec, &rootIndices, NULL)); 35328d2f55e7SToby Isaac 35339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &parentIndices)); 3534f30e825dSToby Isaac 3535f30e825dSToby Isaac /* count indices */ 35369566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 35379566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 35389566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 35399566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 35409566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 35419566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(rowEnd - rowStart, &nnzD, rowEnd - rowStart, &nnzO)); 3542f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3543f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 35448d2f55e7SToby Isaac 35459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 35469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3547f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 35489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 35498d2f55e7SToby Isaac 35508d2f55e7SToby Isaac rowOffsets[0] = 0; 3551f30e825dSToby Isaac offsetsCopy[0] = 0; 35528d2f55e7SToby Isaac if (numFields) { 35538d2f55e7SToby Isaac PetscInt f; 35548d2f55e7SToby Isaac 3555f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3556f30e825dSToby Isaac PetscInt fDof; 35579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3558f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 35598d2f55e7SToby Isaac } 35609566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3561367003a6SStefano Zampini } else { 35629566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3563f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 35648d2f55e7SToby Isaac } 3565f30e825dSToby Isaac 35669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 35679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3568f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3569f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3570f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3571f30e825dSToby Isaac const PetscInt *childIndices; 3572f30e825dSToby Isaac 35739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 35749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3575f30e825dSToby Isaac childId = rootIndices[offset++]; 3576f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3577f30e825dSToby Isaac numIndices--; 3578f30e825dSToby Isaac 3579f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3580f30e825dSToby Isaac PetscInt i; 3581f30e825dSToby Isaac 3582f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3583f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3584f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3585f30e825dSToby Isaac if (rowIndex < 0) continue; 358608401ef6SPierre Jolivet PetscCheck(colIndex >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unconstrained fine and constrained coarse"); 3587a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3588f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 35899371c9d4SSatish Balay } else { 3590f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3591f30e825dSToby Isaac } 3592f30e825dSToby Isaac } 35939371c9d4SSatish Balay } else { 3594f30e825dSToby Isaac PetscInt parentId, f, lim; 3595f30e825dSToby Isaac 35969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3597f30e825dSToby Isaac 3598f30e825dSToby Isaac lim = PetscMax(1, numFields); 3599f30e825dSToby Isaac offsets[0] = 0; 36008d2f55e7SToby Isaac if (numFields) { 36018d2f55e7SToby Isaac PetscInt f; 3602f30e825dSToby Isaac 36038d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3604f30e825dSToby Isaac PetscInt fDof; 36059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3606f30e825dSToby Isaac 3607f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 36088d2f55e7SToby Isaac } 36099371c9d4SSatish Balay } else { 3610f30e825dSToby Isaac PetscInt cDof; 3611f30e825dSToby Isaac 36129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3613f30e825dSToby Isaac offsets[1] = cDof; 3614f30e825dSToby Isaac } 3615f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3616f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3617f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3618f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3619f30e825dSToby Isaac 3620f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3621f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3622f30e825dSToby Isaac 3623f30e825dSToby Isaac if (colIndex < 0) continue; 3624f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3625f30e825dSToby Isaac numD++; 36269371c9d4SSatish Balay } else { 3627f30e825dSToby Isaac numO++; 3628f30e825dSToby Isaac } 3629f30e825dSToby Isaac } 3630f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3631f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3632f30e825dSToby Isaac 3633f30e825dSToby Isaac if (rowIndex < 0) continue; 3634f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3635f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 36368d2f55e7SToby Isaac } 36378d2f55e7SToby Isaac } 36388d2f55e7SToby Isaac } 3639f30e825dSToby Isaac } 3640f30e825dSToby Isaac } 3641f30e825dSToby Isaac /* preallocate */ 36429566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, nnzD, nnzO, NULL, NULL)); 36439566063dSJacob Faibussowitsch PetscCall(PetscFree2(nnzD, nnzO)); 3644f30e825dSToby Isaac /* insert values */ 36459566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 3646f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3647f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3648f30e825dSToby Isaac 36499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 36509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3651f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 36529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 3653f30e825dSToby Isaac 3654f30e825dSToby Isaac rowOffsets[0] = 0; 3655f30e825dSToby Isaac offsetsCopy[0] = 0; 36568d2f55e7SToby Isaac if (numFields) { 36578d2f55e7SToby Isaac PetscInt f; 3658f30e825dSToby Isaac 36598d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3660f30e825dSToby Isaac PetscInt fDof; 36619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3662f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3663f30e825dSToby Isaac } 36649566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3665367003a6SStefano Zampini } else { 36669566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3667f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3668f30e825dSToby Isaac } 3669f30e825dSToby Isaac 36709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 36719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3672f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3673f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3674f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3675f30e825dSToby Isaac const PetscInt *childIndices; 3676f30e825dSToby Isaac 36779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 36789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3679f30e825dSToby Isaac childId = rootIndices[offset++]; 3680f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3681f30e825dSToby Isaac numIndices--; 3682f30e825dSToby Isaac 3683f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3684f30e825dSToby Isaac PetscInt i; 3685f30e825dSToby Isaac 368648a46eb9SPierre Jolivet for (i = 0; i < numIndices; i++) PetscCall(MatSetValue(mat, parentIndices[i], childIndices[i], 1., INSERT_VALUES)); 36879371c9d4SSatish Balay } else { 3688f30e825dSToby Isaac PetscInt parentId, f, lim; 36898d2f55e7SToby Isaac 36909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3691f30e825dSToby Isaac 3692f30e825dSToby Isaac lim = PetscMax(1, numFields); 3693f30e825dSToby Isaac offsets[0] = 0; 36948d2f55e7SToby Isaac if (numFields) { 3695f30e825dSToby Isaac PetscInt f; 36968d2f55e7SToby Isaac 3697f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3698f30e825dSToby Isaac PetscInt fDof; 36999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3700f30e825dSToby Isaac 3701f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 37028d2f55e7SToby Isaac } 37039371c9d4SSatish Balay } else { 3704f30e825dSToby Isaac PetscInt cDof; 3705f30e825dSToby Isaac 37069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3707f30e825dSToby Isaac offsets[1] = cDof; 37088d2f55e7SToby Isaac } 3709f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3710f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3711f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3712f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3713f30e825dSToby Isaac 37149566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, rowOffsets[f + 1] - rowOffsets[f], rowIndices, offsets[f + 1] - offsets[f], colIndices, childMat, INSERT_VALUES)); 37158d2f55e7SToby Isaac } 37168d2f55e7SToby Isaac } 37178d2f55e7SToby Isaac } 37188d2f55e7SToby Isaac } 37199566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 37209566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 37219566063dSJacob Faibussowitsch PetscCall(PetscFree(parentIndices)); 37229566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 37239566063dSJacob Faibussowitsch PetscCall(PetscFree(rootIndices)); 37249566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 3725f30e825dSToby Isaac 37269566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 37279566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 37283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3729154bca37SToby Isaac } 373038fc2455SToby Isaac 3731d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 3732d71ae5a4SJacob Faibussowitsch { 373362095d54SToby Isaac PetscSF coarseToFineEmbedded; 373462095d54SToby Isaac PetscSection globalCoarse, globalFine; 373562095d54SToby Isaac PetscSection localCoarse, localFine; 373662095d54SToby Isaac PetscSection aSec, cSec; 373762095d54SToby Isaac PetscSection rootValuesSec; 373862095d54SToby Isaac PetscSection leafValuesSec; 373962095d54SToby Isaac PetscScalar *rootValues, *leafValues; 374062095d54SToby Isaac IS aIS; 374162095d54SToby Isaac const PetscInt *anchors; 374262095d54SToby Isaac Mat cMat; 374362095d54SToby Isaac PetscInt numFields; 3744412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd; 374562095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 374662095d54SToby Isaac PetscInt *maxChildIds; 374762095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 37480eb7e1eaSToby Isaac PetscFV fv = NULL; 37490eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 37500eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 37510eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 37520eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 375362095d54SToby Isaac 3754ebf164c7SToby Isaac PetscFunctionBegin; 37559566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 37569566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 37579566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(coarse, 0, &cellStart, &cellEnd)); 37589566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 37599566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 37609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(coarse, &dim)); 376162095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 3762e4a60869SToby Isaac PetscInt nleaves, l; 3763e4a60869SToby Isaac const PetscInt *leaves; 376462095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 376562095d54SToby Isaac 37669566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 3767e4a60869SToby Isaac 3768e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 3769e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3770e4a60869SToby Isaac 37719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 3773ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 377462095d54SToby Isaac } 37759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 37764833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 3777e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3778e4a60869SToby Isaac 37799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 3781ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l; 378262095d54SToby Isaac } 37839566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 37849566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 378562095d54SToby Isaac } 378662095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 37879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 3788ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2; 37899566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 37909566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 379162095d54SToby Isaac 37929566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 37939566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 379462095d54SToby Isaac 37959566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 37969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 37979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 379862095d54SToby Isaac 37999566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 38009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 380162095d54SToby Isaac 380262095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 38039566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootValuesSec)); 38049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootValuesSec, pStartC, pEndC)); 38059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 380662095d54SToby Isaac { 380762095d54SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 38089566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &newOffsets, maxFields, &newOffsetsCopy, maxFields, &rowOffsets, maxFields, &numD, maxFields, &numO)); 380962095d54SToby Isaac } 38100eb7e1eaSToby Isaac if (grad) { 38110eb7e1eaSToby Isaac PetscInt i; 38120eb7e1eaSToby Isaac 38139566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeom, &cellDM)); 38149566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeom, &cellGeomArray)); 38159566063dSJacob Faibussowitsch PetscCall(VecGetDM(grad, &gradDM)); 38169566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(grad, &gradArray)); 38170eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1, numFields); i++) { 38180eb7e1eaSToby Isaac PetscObject obj; 38190eb7e1eaSToby Isaac PetscClassId id; 38200eb7e1eaSToby Isaac 38219566063dSJacob Faibussowitsch PetscCall(DMGetField(coarse, i, NULL, &obj)); 38229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 38230eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 38240eb7e1eaSToby Isaac fv = (PetscFV)obj; 38259566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numFVcomps)); 38260eb7e1eaSToby Isaac fvField = i; 38270eb7e1eaSToby Isaac break; 38280eb7e1eaSToby Isaac } 38290eb7e1eaSToby Isaac } 38300eb7e1eaSToby Isaac } 383162095d54SToby Isaac 383262095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 383362095d54SToby Isaac PetscInt dof; 383462095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 383562095d54SToby Isaac PetscInt numValues = 0; 383662095d54SToby Isaac 38379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 3838ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 383962095d54SToby Isaac offsets[0] = 0; 384062095d54SToby Isaac newOffsets[0] = 0; 384162095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 384262095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 384362095d54SToby Isaac 38449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 384562095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 384662095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 384762095d54SToby Isaac 38489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 384962095d54SToby Isaac numValues += clDof; 385062095d54SToby Isaac } 38519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 38529371c9d4SSatish Balay } else if (maxChildId == -1) { 38539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &numValues)); 385462095d54SToby Isaac } 385562095d54SToby Isaac /* we will pack the column indices with the field offsets */ 385678b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 38570eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 38580eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 38590eb7e1eaSToby Isaac } 38609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootValuesSec, p, numValues)); 386162095d54SToby Isaac } 38629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootValuesSec)); 386362095d54SToby Isaac { 386462095d54SToby Isaac PetscInt numRootValues; 386562095d54SToby Isaac const PetscScalar *coarseArray; 386662095d54SToby Isaac 38679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootValuesSec, &numRootValues)); 38689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootValues, &rootValues)); 38699566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecCoarseLocal, &coarseArray)); 387062095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 387162095d54SToby Isaac PetscInt numValues; 387262095d54SToby Isaac PetscInt pValOff; 387362095d54SToby Isaac PetscScalar *pVal; 387462095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 387562095d54SToby Isaac 38769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootValuesSec, p, &numValues)); 3877ad540459SPierre Jolivet if (!numValues) continue; 38789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootValuesSec, p, &pValOff)); 387962095d54SToby Isaac pVal = &(rootValues[pValOff]); 388062095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 38810eb7e1eaSToby Isaac PetscInt closureSize = numValues; 38829566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(coarse, NULL, vecCoarseLocal, p, &closureSize, &pVal)); 38830eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 3884193eb951SToby Isaac PetscFVCellGeom *cg; 38856dd00756SToby Isaac PetscScalar *gradVals = NULL; 38860eb7e1eaSToby Isaac PetscInt i; 38870eb7e1eaSToby Isaac 38880eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 38890eb7e1eaSToby Isaac 38909566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(cellDM, p, cellGeomArray, (void *)&cg)); 38910eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 38920eb7e1eaSToby Isaac pVal += dim; 38939566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRead(gradDM, p, gradArray, (void *)&gradVals)); 38940eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 38950eb7e1eaSToby Isaac } 38969371c9d4SSatish Balay } else if (maxChildId == -1) { 389778b7adb5SToby Isaac PetscInt lDof, lOff, i; 389878b7adb5SToby Isaac 38999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &lDof)); 39009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, p, &lOff)); 390178b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 390278b7adb5SToby Isaac } 390378b7adb5SToby Isaac } 39049566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecCoarseLocal, &coarseArray)); 39059566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 390662095d54SToby Isaac } 390762095d54SToby Isaac { 390862095d54SToby Isaac PetscSF valuesSF; 390962095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 391062095d54SToby Isaac 39119566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafValuesSec)); 39129566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootValuesSec, &remoteOffsetsValues, leafValuesSec)); 39139566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootValuesSec, remoteOffsetsValues, leafValuesSec, &valuesSF)); 39149566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 39159566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsValues)); 39169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafValuesSec, &numLeafValues)); 39179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeafValues, &leafValues)); 39189566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 39199566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 39209566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&valuesSF)); 39219566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 39229566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootValuesSec)); 392362095d54SToby Isaac } 39249566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 392562095d54SToby Isaac { 392662095d54SToby Isaac PetscInt maxDof; 392762095d54SToby Isaac PetscInt *rowIndices; 392862095d54SToby Isaac DM refTree; 392962095d54SToby Isaac PetscInt **refPointFieldN; 393062095d54SToby Isaac PetscScalar ***refPointFieldMats; 393162095d54SToby Isaac PetscSection refConSec, refAnSec; 39320eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, leafStart, leafEnd; 393362095d54SToby Isaac PetscScalar *pointWork; 393462095d54SToby Isaac 39359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 39369566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 39379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 39389566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 39399566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(fine, refTree)); 39409566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 39419566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 39429566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 39439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 39449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafValuesSec, &leafStart, &leafEnd)); 39459566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(fine, 0, &cellStart, &cellEnd)); 39460eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 394762095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 394862095d54SToby Isaac PetscInt numValues, pValOff; 394962095d54SToby Isaac PetscInt childId; 395062095d54SToby Isaac const PetscScalar *pVal; 39510eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 395262095d54SToby Isaac 39539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 39549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &lDof)); 39559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 3956ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 39579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 39589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafValuesSec, p, &numValues)); 395962095d54SToby Isaac if (!numValues) continue; 39609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafValuesSec, p, &pValOff)); 396162095d54SToby Isaac pVal = &leafValues[pValOff]; 396262095d54SToby Isaac offsets[0] = 0; 396362095d54SToby Isaac offsetsCopy[0] = 0; 396462095d54SToby Isaac newOffsets[0] = 0; 396562095d54SToby Isaac newOffsetsCopy[0] = 0; 39664833aeb0SToby Isaac childId = cids[p - pStartF]; 396762095d54SToby Isaac if (numFields) { 396862095d54SToby Isaac PetscInt f; 396962095d54SToby Isaac for (f = 0; f < numFields; f++) { 397062095d54SToby Isaac PetscInt rowDof; 397162095d54SToby Isaac 39729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 397362095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 397462095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 397562095d54SToby Isaac /* TODO: closure indices */ 39769f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 397762095d54SToby Isaac } 39789566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 39799371c9d4SSatish Balay } else { 39804833aeb0SToby Isaac offsets[0] = 0; 39814833aeb0SToby Isaac offsets[1] = lDof; 39824833aeb0SToby Isaac newOffsets[0] = 0; 39834833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 39849566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 398562095d54SToby Isaac } 398662095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 39879566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numValues, rowIndices, pVal, INSERT_VALUES)); 398862095d54SToby Isaac } else { 398962095d54SToby Isaac PetscInt f; 399062095d54SToby Isaac 399178b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 399278b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 399378b7adb5SToby Isaac fvGradData = &pVal[numValues]; 399478b7adb5SToby Isaac } 399562095d54SToby Isaac for (f = 0; f < PetscMax(1, numFields); f++) { 399662095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 399762095d54SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 399862095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 399962095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 400062095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 400162095d54SToby Isaac PetscInt i, j; 400262095d54SToby Isaac 4003708c7f19SToby Isaac #if 0 400463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(coarse,"childId %" PetscInt_FMT ", numRows %" PetscInt_FMT ", numCols %" PetscInt_FMT ", refPointFieldN %" PetscInt_FMT " maxDof %" PetscInt_FMT "\n",childId,numRows,numCols,refPointFieldN[childId - pRefStart][f], maxDof)); 4005708c7f19SToby Isaac #endif 400662095d54SToby Isaac for (i = 0; i < numRows; i++) { 400762095d54SToby Isaac PetscScalar val = 0.; 4008ad540459SPierre Jolivet for (j = 0; j < numCols; j++) val += childMat[i * numCols + j] * cVal[j]; 400962095d54SToby Isaac rVal[i] = val; 401062095d54SToby Isaac } 40110eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 40120eb7e1eaSToby Isaac PetscReal centroid[3]; 40130eb7e1eaSToby Isaac PetscScalar diff[3]; 40140eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 40150eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 40160eb7e1eaSToby Isaac 40179566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(fine, p, NULL, centroid, NULL)); 4018ad540459SPierre Jolivet for (i = 0; i < dim; i++) diff[i] = centroid[i] - parentCentroid[i]; 40190eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 40200eb7e1eaSToby Isaac PetscScalar val = 0.; 40210eb7e1eaSToby Isaac 4022ad540459SPierre Jolivet for (j = 0; j < dim; j++) val += gradient[dim * i + j] * diff[j]; 40230eb7e1eaSToby Isaac rVal[i] += val; 40240eb7e1eaSToby Isaac } 40250eb7e1eaSToby Isaac } 40269566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numRows, &rowIndices[offsets[f]], rVal, INSERT_VALUES)); 402762095d54SToby Isaac } 402862095d54SToby Isaac } 402962095d54SToby Isaac } 40309566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 40319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 40329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 403362095d54SToby Isaac } 40349566063dSJacob Faibussowitsch PetscCall(PetscFree(leafValues)); 40359566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafValuesSec)); 40369566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 40379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 40383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4039ebf164c7SToby Isaac } 4040ebf164c7SToby Isaac 4041d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4042d71ae5a4SJacob Faibussowitsch { 4043c921d74cSToby Isaac DM refTree; 4044c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4045c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4046c921d74cSToby Isaac PetscSection localCoarse, localFine; 4047c921d74cSToby Isaac PetscSection cSecRef; 4048c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4049d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4050c921d74cSToby Isaac Mat injRef; 4051c921d74cSToby Isaac PetscInt numFields, maxDof; 4052c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4053c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4054c921d74cSToby Isaac PetscLayout rowMap, colMap; 4055c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4056c921d74cSToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4057c921d74cSToby Isaac 4058ebf164c7SToby Isaac PetscFunctionBegin; 4059c921d74cSToby Isaac 4060c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 40619566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40629566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecCoarse, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40639566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 40649566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(coarse, refTree)); 40659566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 40669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 40679566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 4068c921d74cSToby Isaac 40699566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 40709566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 40719566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 40729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 40739566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 40749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 40759566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 40769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 4077c921d74cSToby Isaac { 4078c921d74cSToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 40799566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 4080c921d74cSToby Isaac } 4081c921d74cSToby Isaac 40829566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, cids, vecFine, numFields, offsets, &multiRootSec, &rootIndicesSec, NULL, &rootValues)); 4083c921d74cSToby Isaac 40849566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxDof, &parentIndices, maxDof, &parentValues)); 4085c921d74cSToby Isaac 4086c921d74cSToby Isaac /* count indices */ 40879566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecFine, &colMap)); 40889566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecCoarse, &rowMap)); 40899566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 40909566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 40919566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 40929566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 4093c921d74cSToby Isaac /* insert values */ 40949566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 4095c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4096c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 409778b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4098c921d74cSToby Isaac 40999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 41009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 4101c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 41029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &dof)); 41039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 4104c921d74cSToby Isaac 4105c921d74cSToby Isaac rowOffsets[0] = 0; 4106c921d74cSToby Isaac offsetsCopy[0] = 0; 4107c921d74cSToby Isaac if (numFields) { 4108c921d74cSToby Isaac PetscInt f; 4109c921d74cSToby Isaac 4110c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4111c921d74cSToby Isaac PetscInt fDof; 41129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 4113c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4114c921d74cSToby Isaac } 41159566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 4116367003a6SStefano Zampini } else { 41179566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 4118c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4119c921d74cSToby Isaac } 4120c921d74cSToby Isaac 41219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 41229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 4123c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 41242f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4125c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4126c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4127c921d74cSToby Isaac const PetscScalar *childValues; 4128c921d74cSToby Isaac 41299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 41309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 4131c921d74cSToby Isaac childId = (PetscInt)PetscRealPart(rootValues[offset++]); 4132c921d74cSToby Isaac childValues = &rootValues[offset]; 4133c921d74cSToby Isaac numIndices--; 4134c921d74cSToby Isaac 4135c921d74cSToby Isaac if (childId == -2) { /* skip */ 4136c921d74cSToby Isaac continue; 4137c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 41382f65e181SToby Isaac PetscInt m; 41392f65e181SToby Isaac 414078b7adb5SToby Isaac contribute = PETSC_TRUE; 41412f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4142beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4143d3bc4906SToby Isaac PetscInt parentId, f, lim; 4144d3bc4906SToby Isaac 414578b7adb5SToby Isaac contribute = PETSC_TRUE; 41469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 4147d3bc4906SToby Isaac 4148d3bc4906SToby Isaac lim = PetscMax(1, numFields); 4149d3bc4906SToby Isaac offsets[0] = 0; 4150d3bc4906SToby Isaac if (numFields) { 4151d3bc4906SToby Isaac PetscInt f; 4152d3bc4906SToby Isaac 4153d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4154d3bc4906SToby Isaac PetscInt fDof; 41559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 4156d3bc4906SToby Isaac 4157d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4158d3bc4906SToby Isaac } 41599371c9d4SSatish Balay } else { 4160d3bc4906SToby Isaac PetscInt cDof; 4161d3bc4906SToby Isaac 41629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 4163d3bc4906SToby Isaac offsets[1] = cDof; 4164d3bc4906SToby Isaac } 4165d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4166d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4167d3bc4906SToby Isaac PetscInt n = offsets[f + 1] - offsets[f]; 4168e328ff09SToby Isaac PetscInt m = rowOffsets[f + 1] - rowOffsets[f]; 4169d3bc4906SToby Isaac PetscInt i, j; 4170d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4171d3bc4906SToby Isaac 4172e328ff09SToby Isaac for (i = 0; i < m; i++) { 4173d3bc4906SToby Isaac PetscScalar val = 0.; 4174ad540459SPierre Jolivet for (j = 0; j < n; j++) val += childMat[n * i + j] * colValues[j]; 4175e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val; 4176d3bc4906SToby Isaac } 4177d3bc4906SToby Isaac } 4178c921d74cSToby Isaac } 4179c921d74cSToby Isaac } 41809566063dSJacob Faibussowitsch if (contribute) PetscCall(VecSetValues(vecCoarse, dof, parentIndices, parentValues, INSERT_VALUES)); 4181c921d74cSToby Isaac } 41829566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 41839566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 41849566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentIndices, parentValues)); 41859566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 41869566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 41879566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 41883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4189ebf164c7SToby Isaac } 4190ebf164c7SToby Isaac 4191ff1f73f7SToby Isaac /*@ 4192ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4193ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4194ff1f73f7SToby Isaac coarsening and refinement at the same time. 4195ff1f73f7SToby Isaac 419620f4b53cSBarry Smith Collective 4197ff1f73f7SToby Isaac 4198ff1f73f7SToby Isaac Input Parameters: 4199a1cb98faSBarry Smith + dmIn - The `DMPLEX` mesh for the input vector 420020f4b53cSBarry Smith . dmOut - The second `DMPLEX` mesh 4201ff1f73f7SToby Isaac . vecIn - The input vector 420220f4b53cSBarry Smith . sfRefine - A star forest indicating points in the mesh `dmIn` (roots in the star forest) that are parents to points in 420320f4b53cSBarry Smith the mesh `dmOut` (leaves in the star forest), i.e. where `dmOut` is more refined than `dmIn` 420420f4b53cSBarry Smith . sfCoarsen - A star forest indicating points in the mesh `dmOut` (roots in the star forest) that are parents to points in 420520f4b53cSBarry Smith the mesh `dmIn` (leaves in the star forest), i.e. where `dmOut` is more coarsened than `dmIn` 420620f4b53cSBarry Smith . cidsRefine - The childIds of the points in `dmOut`. These childIds relate back to the reference tree: childid[j] = k implies 420720f4b53cSBarry Smith that mesh point j of `dmOut` was refined from a point in `dmIn` just as the mesh point k in the reference 420820f4b53cSBarry Smith tree was refined from its parent. childid[j] = -1 indicates that the point j in `dmOut` is exactly 420920f4b53cSBarry Smith equivalent to its root in `dmIn`, so no interpolation is necessary. childid[j] = -2 indicates that this 421020f4b53cSBarry Smith point j in `dmOut` is not a leaf of `sfRefine`. 421120f4b53cSBarry Smith . cidsCoarsen - The childIds of the points in `dmIn`. These childIds relate back to the reference tree: childid[j] = k implies 421220f4b53cSBarry Smith that mesh point j of dmIn coarsens to a point in `dmOut` just as the mesh point k in the reference 421320f4b53cSBarry Smith tree coarsens to its parent. childid[j] = -2 indicates that point j in `dmOut` is not a leaf in `sfCoarsen`. 421420f4b53cSBarry Smith . useBCs - `PETSC_TRUE` indicates that boundary values should be inserted into `vecIn` before transfer. 4215ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4216ff1f73f7SToby Isaac 42172fe279fdSBarry Smith Output Parameter: 42188966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred 421920f4b53cSBarry Smith projection of `vecIn` from `dmIn` to `dmOut`. Note that any field discretized with a `PetscFV` finite volume 4220ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4221ff1f73f7SToby Isaac coarse points to fine points. 4222ff1f73f7SToby Isaac 4223ff1f73f7SToby Isaac Level: developer 4224ff1f73f7SToby Isaac 4225a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSF`, `Vec`, `PetscFV`, `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()`, `PetscFVGetComputeGradients()` 4226ff1f73f7SToby Isaac @*/ 4227d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) 4228d71ae5a4SJacob Faibussowitsch { 422938fc2455SToby Isaac PetscFunctionBegin; 42309566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0)); 4231ff1f73f7SToby Isaac if (sfRefine) { 4232fbfa57b9SToby Isaac Vec vecInLocal; 42330eb7e1eaSToby Isaac DM dmGrad = NULL; 42340eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4235fbfa57b9SToby Isaac 42369566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecInLocal)); 42379566063dSJacob Faibussowitsch PetscCall(VecSet(vecInLocal, 0.0)); 42380eb7e1eaSToby Isaac { 42390eb7e1eaSToby Isaac PetscInt numFields, i; 42400eb7e1eaSToby Isaac 42419566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dmIn, &numFields)); 42420eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 42430eb7e1eaSToby Isaac PetscObject obj; 42440eb7e1eaSToby Isaac PetscClassId classid; 42450eb7e1eaSToby Isaac 42469566063dSJacob Faibussowitsch PetscCall(DMGetField(dmIn, i, NULL, &obj)); 42479566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &classid)); 42480eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 42499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dmIn, (PetscFV)obj, &cellGeom, &faceGeom, &dmGrad)); 42500eb7e1eaSToby Isaac break; 42510eb7e1eaSToby Isaac } 42520eb7e1eaSToby Isaac } 42530eb7e1eaSToby Isaac } 42541baa6e33SBarry Smith if (useBCs) PetscCall(DMPlexInsertBoundaryValues(dmIn, PETSC_TRUE, vecInLocal, time, faceGeom, cellGeom, NULL)); 42559566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42569566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42570eb7e1eaSToby Isaac if (dmGrad) { 42589566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmGrad, &grad)); 42599566063dSJacob Faibussowitsch PetscCall(DMPlexReconstructGradientsFVM(dmIn, vecInLocal, grad)); 42600eb7e1eaSToby Isaac } 42619566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree_Interpolate(dmIn, vecInLocal, dmOut, vecOut, sfRefine, cidsRefine, grad, cellGeom)); 42629566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecInLocal)); 426348a46eb9SPierre Jolivet if (dmGrad) PetscCall(DMRestoreGlobalVector(dmGrad, &grad)); 4264ebf164c7SToby Isaac } 42651baa6e33SBarry Smith if (sfCoarsen) PetscCall(DMPlexTransferVecTree_Inject(dmIn, vecIn, dmOut, vecOut, sfCoarsen, cidsCoarsen)); 42669566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(vecOut)); 42679566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(vecOut)); 42683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 426938fc2455SToby Isaac } 4270