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 977aaa8cc7dSPierre 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)); 1559*c77c71ffSToby Isaac PetscCall(DMSetLocalSection(refTree, NULL)); 1560*c77c71ffSToby Isaac PetscCall(DMSetDefaultConstraints(refTree, NULL, NULL, NULL)); 15619566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 15629566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 15639566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anSec, &anIS)); 15649566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anIS, &anchors)); 15659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 15669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(conSec, &conStart, &conEnd)); 15679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 15689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 15699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof * maxAnDof, &pointWork)); 157021968bf8SToby Isaac 157121968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 15729566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 157395a0b26dSToby Isaac 157495a0b26dSToby Isaac /* step 2: compute the preorder */ 15759566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 15769566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &perm, pEnd - pStart, &iperm)); 157795a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 157895a0b26dSToby Isaac perm[p - pStart] = p; 157995a0b26dSToby Isaac iperm[p - pStart] = p - pStart; 158095a0b26dSToby Isaac } 158195a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 158295a0b26dSToby Isaac PetscInt point = perm[p]; 158395a0b26dSToby Isaac PetscInt parent; 158495a0b26dSToby Isaac 15859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 158695a0b26dSToby Isaac if (parent == point) { 158795a0b26dSToby Isaac p++; 15889371c9d4SSatish Balay } else { 158995a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 159095a0b26dSToby Isaac 15919566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 159295a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 159395a0b26dSToby Isaac PetscInt q = closure[2 * i]; 159495a0b26dSToby Isaac if (iperm[q - pStart] > iperm[point - pStart]) { 159595a0b26dSToby Isaac /* swap */ 159695a0b26dSToby Isaac perm[p] = q; 159795a0b26dSToby Isaac perm[iperm[q - pStart]] = point; 159895a0b26dSToby Isaac iperm[point - pStart] = iperm[q - pStart]; 159995a0b26dSToby Isaac iperm[q - pStart] = p; 160095a0b26dSToby Isaac break; 160195a0b26dSToby Isaac } 160295a0b26dSToby Isaac } 160395a0b26dSToby Isaac size = closureSize; 16049566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1605ad540459SPierre Jolivet if (i == size) p++; 160695a0b26dSToby Isaac } 160795a0b26dSToby Isaac } 160895a0b26dSToby Isaac 160995a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 161095a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 161195a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 161295a0b26dSToby Isaac * values outside of the Mat first. 161395a0b26dSToby Isaac */ 161495a0b26dSToby Isaac { 161595a0b26dSToby Isaac PetscInt nRows, row, nnz; 161695a0b26dSToby Isaac PetscBool done; 1617cd6fc93eSToby Isaac PetscInt secStart, secEnd; 161895a0b26dSToby Isaac const PetscInt *ia, *ja; 161995a0b26dSToby Isaac PetscScalar *vals; 162095a0b26dSToby Isaac 1621cd6fc93eSToby Isaac PetscCall(PetscSectionGetChart(section, &secStart, &secEnd)); 16229566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 162328b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not get RowIJ of constraint matrix"); 162495a0b26dSToby Isaac nnz = ia[nRows]; 162595a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 162695a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 16279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &vals)); 162895a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 162995a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 163095a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 163195a0b26dSToby Isaac 16329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, &childid)); 163395a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 16349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &pointDof)); 163595a0b26dSToby Isaac if (!pointDof) continue; 16369566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1637085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1638085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 163995a0b26dSToby Isaac PetscScalar *pointMat; 1640085f0adfSToby Isaac const PetscInt **perms; 1641085f0adfSToby Isaac const PetscScalar **flips; 164295a0b26dSToby Isaac 1643085f0adfSToby Isaac if (numFields) { 16449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, point, f, &cDof)); 16459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, point, f, &cOff)); 16469371c9d4SSatish Balay } else { 16479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &cDof)); 16489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, point, &cOff)); 164995a0b26dSToby Isaac } 165095a0b26dSToby Isaac if (!cDof) continue; 16519566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 16529566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, closureSize, closure, &perms, &flips)); 165395a0b26dSToby Isaac 165495a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 165576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 165695a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 165795a0b26dSToby Isaac if (cDof > 1 && r) { 165863a3b9bcSJacob 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])); 165995a0b26dSToby Isaac } 166095a0b26dSToby Isaac } 166176bd3646SJed Brown } 166295a0b26dSToby Isaac /* zero rows */ 1663ad540459SPierre Jolivet for (i = ia[cOff]; i < ia[cOff + cDof]; i++) vals[i] = 0.; 166495a0b26dSToby Isaac matOffset = ia[cOff]; 166595a0b26dSToby Isaac numFillCols = ia[cOff + 1] - matOffset; 166695a0b26dSToby Isaac pointMat = refPointFieldMats[childid - pRefStart][f]; 166795a0b26dSToby Isaac numCols = refPointFieldN[childid - pRefStart][f]; 166895a0b26dSToby Isaac offset = 0; 166995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 167095a0b26dSToby Isaac PetscInt q = closure[2 * i]; 167195a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 1672085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1673085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 167495a0b26dSToby Isaac 167595a0b26dSToby Isaac qConDof = qConOff = 0; 1676cd6fc93eSToby Isaac if (q < secStart || q >= secEnd) continue; 1677085f0adfSToby Isaac if (numFields) { 16789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, q, f, &aDof)); 16799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, q, f, &aOff)); 168095a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, q, f, &qConDof)); 16829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, q, f, &qConOff)); 168395a0b26dSToby Isaac } 16849371c9d4SSatish Balay } else { 16859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &aDof)); 16869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &aOff)); 168795a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, q, &qConDof)); 16899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, q, &qConOff)); 169095a0b26dSToby Isaac } 169195a0b26dSToby Isaac } 169295a0b26dSToby Isaac if (!aDof) continue; 169395a0b26dSToby Isaac if (qConDof) { 169495a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 169595a0b26dSToby Isaac * be filled, thanks to preordering */ 169695a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 169795a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 169895a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 169995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 170095a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 170195a0b26dSToby Isaac PetscScalar inVal = 0; 170295a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1703085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 170495a0b26dSToby Isaac 1705085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 170695a0b26dSToby Isaac } 170795a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 170895a0b26dSToby Isaac } 170995a0b26dSToby Isaac } 171095a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 171195a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 171295a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 171395a0b26dSToby Isaac for (; k < numFillCols; k++) { 1714ad540459SPierre Jolivet if (ja[matOffset + k] == col) break; 171595a0b26dSToby Isaac } 171663a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, col); 1717ad540459SPierre Jolivet for (r = 0; r < cDof; r++) vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 171895a0b26dSToby Isaac } 17199371c9d4SSatish Balay } else { 172095a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 172195a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 1722ad540459SPierre Jolivet if (ja[matOffset + k] == aOff) break; 172395a0b26dSToby Isaac } 172463a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, aOff); 172595a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1726085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1727085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1728085f0adfSToby Isaac 1729085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 173095a0b26dSToby Isaac } 173195a0b26dSToby Isaac } 173295a0b26dSToby Isaac } 173395a0b26dSToby Isaac offset += aDof; 173495a0b26dSToby Isaac } 1735085f0adfSToby Isaac if (numFields) { 17369566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 1737085f0adfSToby Isaac } else { 17389566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, closureSize, closure, &perms, &flips)); 1739085f0adfSToby Isaac } 174095a0b26dSToby Isaac } 17419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 174295a0b26dSToby Isaac } 174348a46eb9SPierre 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)); 17449566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 174528b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not restore RowIJ of constraint matrix"); 17469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 17479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 17489566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 174995a0b26dSToby Isaac } 175095a0b26dSToby Isaac 175195a0b26dSToby Isaac /* clean up */ 17529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anIS, &anchors)); 17539566063dSJacob Faibussowitsch PetscCall(PetscFree2(perm, iperm)); 17549566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 17559566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 17563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 175795a0b26dSToby Isaac } 175895a0b26dSToby Isaac 17596f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 17606f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 1761d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTreeRefineCell(DM dm, PetscInt cell, DM *ncdm) 1762d71ae5a4SJacob Faibussowitsch { 17636f5f1567SToby Isaac DM K; 1764420f55faSMatthew G. Knepley PetscMPIInt rank; 17656f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 17666f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 17676f5f1567SToby Isaac PetscInt *Kembedding; 17686f5f1567SToby Isaac PetscInt *cellClosure = NULL, nc; 17696f5f1567SToby Isaac PetscScalar *newVertexCoords; 17706f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 17716f5f1567SToby Isaac PetscSection parentSection; 17726f5f1567SToby Isaac 17736f5f1567SToby Isaac PetscFunctionBegin; 17749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 17769566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm)); 17779566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ncdm, dim)); 17786f5f1567SToby Isaac 17799566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 17809566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &parentSection)); 17819566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &K)); 17826858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 1783dd400576SPatrick Sanan if (rank == 0) { 17846f5f1567SToby Isaac /* compute the new charts */ 17859566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim + 1, &pNewCount, dim + 1, &pNewStart, dim + 1, &pNewEnd, dim + 1, &pOldStart, dim + 1, &pOldEnd)); 17866f5f1567SToby Isaac offset = 0; 17876f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 17886f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 17896f5f1567SToby Isaac 17906f5f1567SToby Isaac pNewStart[d] = offset; 17919566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pOldStart[d], &pOldEnd[d])); 17929566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 17936f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 17946f5f1567SToby Isaac /* adding the new points */ 17956f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 17966f5f1567SToby Isaac if (!d) { 17976f5f1567SToby Isaac /* removing the cell */ 17986f5f1567SToby Isaac pNewCount[d]--; 17996f5f1567SToby Isaac } 18006f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18016f5f1567SToby Isaac PetscInt parent; 18029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &parent, NULL)); 18036f5f1567SToby Isaac if (parent == k) { 18046f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 18056f5f1567SToby Isaac pNewCount[d]--; 18066f5f1567SToby Isaac } 18076f5f1567SToby Isaac } 18086f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 18096f5f1567SToby Isaac offset = pNewEnd[d]; 18106f5f1567SToby Isaac } 18111dca8a05SBarry 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]); 18126f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 18139566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 18146f5f1567SToby Isaac 18159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pNewEnd[dim], &newConeSizes)); 18166f5f1567SToby Isaac { 1817b5a892a1SMatthew G. Knepley DMPolytopeType pct, qct; 18186f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 18196f5f1567SToby Isaac 18209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &kStart, &kEnd)); 18219566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(kEnd - kStart, &Kembedding, kEnd - kStart, &perm, kEnd - kStart, &iperm, kEnd - kStart, &preOrient)); 18226f5f1567SToby Isaac 18236f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18246f5f1567SToby Isaac perm[k - kStart] = k; 18256f5f1567SToby Isaac iperm[k - kStart] = k - kStart; 18266f5f1567SToby Isaac preOrient[k - kStart] = 0; 18276f5f1567SToby Isaac } 18286f5f1567SToby Isaac 18299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18306f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 18316f5f1567SToby Isaac PetscInt parentOrientA = closureK[2 * j + 1]; 18326f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2 * j + 1]; 18336f5f1567SToby Isaac PetscInt p, q; 18346f5f1567SToby Isaac 18356f5f1567SToby Isaac p = closureK[2 * j]; 18366f5f1567SToby Isaac q = cellClosure[2 * j]; 18379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, p, &pct)); 18389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, q, &qct)); 18396f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 1840ad540459SPierre Jolivet if (q >= pOldStart[d] && q < pOldEnd[d]) Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 18416f5f1567SToby Isaac } 1842b5a892a1SMatthew G. Knepley parentOrientA = DMPolytopeConvertNewOrientation_Internal(pct, parentOrientA); 1843b5a892a1SMatthew G. Knepley parentOrientB = DMPolytopeConvertNewOrientation_Internal(qct, parentOrientB); 18446f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 18456f5f1567SToby Isaac PetscInt numChildren, i; 18466f5f1567SToby Isaac const PetscInt *children; 18476f5f1567SToby Isaac 18489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(K, p, &numChildren, &children)); 18496f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 18506f5f1567SToby Isaac PetscInt kPerm, oPerm; 18516f5f1567SToby Isaac 18526f5f1567SToby Isaac k = children[i]; 18539566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(K, p, parentOrientA, 0, k, parentOrientB, &oPerm, &kPerm)); 18546f5f1567SToby Isaac /* perm = what refTree position I'm in */ 18556f5f1567SToby Isaac perm[kPerm - kStart] = k; 18566f5f1567SToby Isaac /* iperm = who is at this position */ 18576f5f1567SToby Isaac iperm[k - kStart] = kPerm - kStart; 18586f5f1567SToby Isaac preOrient[kPerm - kStart] = oPerm; 18596f5f1567SToby Isaac } 18606f5f1567SToby Isaac } 18616f5f1567SToby Isaac } 18629566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18636f5f1567SToby Isaac } 18649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, pNewEnd[dim])); 18656f5f1567SToby Isaac offset = 0; 18666f5f1567SToby Isaac numNewCones = 0; 18676f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18686f5f1567SToby Isaac PetscInt kStart, kEnd, k; 18696f5f1567SToby Isaac PetscInt p; 18706f5f1567SToby Isaac PetscInt size; 18716f5f1567SToby Isaac 18726f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 18736f5f1567SToby Isaac /* skip cell 0 */ 18746f5f1567SToby Isaac if (p == cell) continue; 18756f5f1567SToby Isaac /* old cones to new cones */ 18769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 18776f5f1567SToby Isaac newConeSizes[offset++] = size; 18786f5f1567SToby Isaac numNewCones += size; 18796f5f1567SToby Isaac } 18806f5f1567SToby Isaac 18819566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 18826f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18836f5f1567SToby Isaac PetscInt kParent; 18846f5f1567SToby Isaac 18859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 18866f5f1567SToby Isaac if (kParent != k) { 18876f5f1567SToby Isaac Kembedding[k] = offset; 18889566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 18896f5f1567SToby Isaac newConeSizes[offset++] = size; 18906f5f1567SToby Isaac numNewCones += size; 189148a46eb9SPierre Jolivet if (kParent != 0) PetscCall(PetscSectionSetDof(parentSection, Kembedding[k], 1)); 18926f5f1567SToby Isaac } 18936f5f1567SToby Isaac } 18946f5f1567SToby Isaac } 18956f5f1567SToby Isaac 18969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 18979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &numPointsWithParents)); 18989566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numNewCones, &newCones, numNewCones, &newOrientations)); 18999566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPointsWithParents, &parents, numPointsWithParents, &childIDs)); 19006f5f1567SToby Isaac 19016f5f1567SToby Isaac /* fill new cones */ 19026f5f1567SToby Isaac offset = 0; 19036f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19046f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 19056f5f1567SToby Isaac PetscInt p; 19066f5f1567SToby Isaac PetscInt size; 19076f5f1567SToby Isaac const PetscInt *cone, *orientation; 19086f5f1567SToby Isaac 19096f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19106f5f1567SToby Isaac /* skip cell 0 */ 19116f5f1567SToby Isaac if (p == cell) continue; 19126f5f1567SToby Isaac /* old cones to new cones */ 19139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 19149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 19159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &orientation)); 19166f5f1567SToby Isaac for (l = 0; l < size; l++) { 19176f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 19186f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 19196f5f1567SToby Isaac } 19206f5f1567SToby Isaac } 19216f5f1567SToby Isaac 19229566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 19236f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19246f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 19256f5f1567SToby Isaac PetscInt preO = preOrient[k]; 19266f5f1567SToby Isaac 19279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 19286f5f1567SToby Isaac if (kParent != k) { 19296f5f1567SToby Isaac /* embed new cones */ 19309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 19319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, kPerm, &cone)); 19329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, kPerm, &orientation)); 19336f5f1567SToby Isaac for (l = 0; l < size; l++) { 19346f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size - (preO + 1) - l) % size); 19356f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 1936b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_NUM_POLYTOPES; 19376f5f1567SToby Isaac 19386f5f1567SToby Isaac q = iperm[cone[m]]; 19396f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 19409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, q, &lSize)); 1941b5a892a1SMatthew G. Knepley if (lSize == 2) ct = DM_POLYTOPE_SEGMENT; 1942b5a892a1SMatthew G. Knepley else if (lSize == 4) ct = DM_POLYTOPE_QUADRILATERAL; 1943b5a892a1SMatthew G. Knepley oTrue = DMPolytopeConvertNewOrientation_Internal(ct, orientation[m]); 19446f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 19456f5f1567SToby Isaac newO = DihedralCompose(lSize, oTrue, preOrient[q]); 1946b5a892a1SMatthew G. Knepley newOrientations[offset++] = DMPolytopeConvertOldOrientation_Internal(ct, newO); 19476f5f1567SToby Isaac } 19486f5f1567SToby Isaac if (kParent != 0) { 19496f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 19509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, Kembedding[k], &pOffset)); 19516f5f1567SToby Isaac parents[pOffset] = newPoint; 19526f5f1567SToby Isaac childIDs[pOffset] = k; 19536f5f1567SToby Isaac } 19546f5f1567SToby Isaac } 19556f5f1567SToby Isaac } 19566f5f1567SToby Isaac } 19576f5f1567SToby Isaac 19589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * (pNewEnd[dim] - pNewStart[dim]), &newVertexCoords)); 19596f5f1567SToby Isaac 19606f5f1567SToby Isaac /* fill coordinates */ 19616f5f1567SToby Isaac offset = 0; 19626f5f1567SToby Isaac { 1963d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 19646f5f1567SToby Isaac PetscSection vSection; 19656f5f1567SToby Isaac PetscInt v; 19666f5f1567SToby Isaac Vec coords; 19676f5f1567SToby Isaac PetscScalar *coordvals; 19686f5f1567SToby Isaac PetscInt dof, off; 1969c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 19706f5f1567SToby Isaac 197176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1972d90620a3SMatthew G. Knepley PetscInt k; 19739566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, 0, &kStart, &kEnd)); 19746f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19759566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ)); 197663a3b9bcSJacob Faibussowitsch PetscCheck(detJ > 0., PETSC_COMM_SELF, PETSC_ERR_PLIB, "reference tree cell %" PetscInt_FMT " has bad determinant", k); 19776f5f1567SToby Isaac } 1978d90620a3SMatthew G. Knepley } 19799566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ)); 19809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &vSection)); 19819566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coords)); 19829566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19836f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 19849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(vSection, v, &dof)); 19859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, v, &off)); 1986ad540459SPierre Jolivet for (l = 0; l < dof; l++) newVertexCoords[offset++] = coordvals[off + l]; 19876f5f1567SToby Isaac } 19889566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 19896f5f1567SToby Isaac 19909566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &vSection)); 19919566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &coords)); 19929566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19939566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &kStart, &kEnd)); 19946f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 19959bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 19966f5f1567SToby Isaac PetscInt vPerm = perm[v]; 19976f5f1567SToby Isaac PetscInt kParent; 1998c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 19996f5f1567SToby Isaac 20009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, v, &kParent, NULL)); 20016f5f1567SToby Isaac if (kParent != v) { 20026f5f1567SToby Isaac /* this is a new vertex */ 20039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, vPerm, &off)); 20049bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off + l]); 2005367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord); 20069bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset + l] = newCoord[l]; 20076f5f1567SToby Isaac offset += dim; 20086f5f1567SToby Isaac } 20096f5f1567SToby Isaac } 20109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 20116f5f1567SToby Isaac } 20126f5f1567SToby Isaac 20136f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 20146f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 20156f5f1567SToby Isaac PetscInt tmp; 20166f5f1567SToby Isaac 20176f5f1567SToby Isaac tmp = pNewCount[d]; 20186f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 20196f5f1567SToby Isaac pNewCount[dim - d] = tmp; 20206f5f1567SToby Isaac } 20216f5f1567SToby Isaac 20229566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, pNewCount, newConeSizes, newCones, newOrientations, newVertexCoords)); 20239566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20249566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, parents, childIDs)); 20256f5f1567SToby Isaac 20266f5f1567SToby Isaac /* clean up */ 20279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 20289566063dSJacob Faibussowitsch PetscCall(PetscFree5(pNewCount, pNewStart, pNewEnd, pOldStart, pOldEnd)); 20299566063dSJacob Faibussowitsch PetscCall(PetscFree(newConeSizes)); 20309566063dSJacob Faibussowitsch PetscCall(PetscFree2(newCones, newOrientations)); 20319566063dSJacob Faibussowitsch PetscCall(PetscFree(newVertexCoords)); 20329566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs)); 20339566063dSJacob Faibussowitsch PetscCall(PetscFree4(Kembedding, perm, iperm, preOrient)); 20349371c9d4SSatish Balay } else { 20356f5f1567SToby Isaac PetscInt p, counts[4]; 20366f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 20376f5f1567SToby Isaac Vec coordVec; 20386f5f1567SToby Isaac PetscScalar *coords; 20396f5f1567SToby Isaac 20406f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20416f5f1567SToby Isaac PetscInt dStart, dEnd; 20426f5f1567SToby Isaac 20439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 20446f5f1567SToby Isaac counts[d] = dEnd - dStart; 20456f5f1567SToby Isaac } 20469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &coneSizes)); 204748a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMPlexGetConeSize(dm, p, &coneSizes[p - pStart])); 20489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 20499566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &orientations)); 20509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordVec)); 20519566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordVec, &coords)); 20526f5f1567SToby Isaac 20539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd)); 20549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 20559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, counts, coneSizes, cones, orientations, NULL)); 20569566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20579566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, NULL, NULL)); 20589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordVec, &coords)); 20596f5f1567SToby Isaac } 20609566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 20616f5f1567SToby Isaac 20623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20636f5f1567SToby Isaac } 20646ecaa68aSToby Isaac 2065d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 2066d71ae5a4SJacob Faibussowitsch { 20676ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 20686ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 20696ecaa68aSToby Isaac PetscSection localCoarse, localFine; 20706ecaa68aSToby Isaac PetscSection aSec, cSec; 20716ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 207246bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 207346bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 207446bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 20756ecaa68aSToby Isaac IS aIS; 20766ecaa68aSToby Isaac const PetscInt *anchors; 20776ecaa68aSToby Isaac Mat cMat; 20784acb8e1eSToby Isaac PetscInt numFields, maxFields; 20796ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 20806ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 20811c58ffc4SToby Isaac PetscInt *maxChildIds; 2082e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 20834acb8e1eSToby Isaac const PetscInt ***perms; 20844acb8e1eSToby Isaac const PetscScalar ***flips; 20856ecaa68aSToby Isaac 20866ecaa68aSToby Isaac PetscFunctionBegin; 20879566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 20889566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 20899566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 20906ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 209189698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 209289698031SToby Isaac const PetscInt *leaves; 20936ecaa68aSToby Isaac 20949566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 209589698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 209689698031SToby Isaac p = leaves ? leaves[l] : l; 20979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 20989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 2099ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 21006ecaa68aSToby Isaac } 21019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 21027cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 210389698031SToby Isaac p = leaves ? leaves[l] : l; 21049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 21059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 2106ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l; 21076ecaa68aSToby Isaac } 21089566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 21099566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 21106ecaa68aSToby Isaac } 21116ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 21129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 2113ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2; 211457168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 211557168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 211646bdb399SToby Isaac 21179566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 21189566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 211946bdb399SToby Isaac 21209566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 21219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 21229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 212346bdb399SToby Isaac 21249566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 21259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 212646bdb399SToby Isaac 212746bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 21289566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 21299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootMatricesSec)); 21309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootIndicesSec, pStartC, pEndC)); 21319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootMatricesSec, pStartC, pEndC)); 21329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 2133713c1c5dSToby Isaac maxFields = PetscMax(1, numFields); 21349566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields + 1, &offsets, maxFields + 1, &offsetsCopy, maxFields + 1, &newOffsets, maxFields + 1, &newOffsetsCopy, maxFields + 1, &rowOffsets, maxFields + 1, &numD, maxFields + 1, &numO)); 21359566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxFields + 1, (PetscInt ****)&perms, maxFields + 1, (PetscScalar ****)&flips)); 21369566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)perms, (maxFields + 1) * sizeof(const PetscInt **))); 21379566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)flips, (maxFields + 1) * sizeof(const PetscScalar **))); 213846bdb399SToby Isaac 213946bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 21408d2f55e7SToby Isaac PetscInt dof, matSize = 0; 21416ecaa68aSToby Isaac PetscInt aDof = 0; 21426ecaa68aSToby Isaac PetscInt cDof = 0; 21436ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 21446ecaa68aSToby Isaac PetscInt numRowIndices = 0; 21456ecaa68aSToby Isaac PetscInt numColIndices = 0; 2146f13f9184SToby Isaac PetscInt f; 21476ecaa68aSToby Isaac 21489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 2149ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 215048a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 215148a46eb9SPierre Jolivet if (p >= cStart && p < cEnd) PetscCall(PetscSectionGetDof(cSec, p, &cDof)); 2152f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2153f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 21546ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2155f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 21566ecaa68aSToby Isaac 21579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 215846bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 21596ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 21606ecaa68aSToby Isaac 21619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 21626ecaa68aSToby Isaac numRowIndices += clDof; 21636ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &clDof)); 21656ecaa68aSToby Isaac offsets[f + 1] += clDof; 21666ecaa68aSToby Isaac } 21676ecaa68aSToby Isaac } 21686ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21696ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 21706ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 21716ecaa68aSToby Isaac } 217246bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 21739566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, NULL, NULL, NULL, &numColIndices, NULL, NULL, newOffsets, PETSC_FALSE)); 21749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 21756ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 21766ecaa68aSToby Isaac numColIndices = numRowIndices; 21776ecaa68aSToby Isaac matSize = 0; 21789371c9d4SSatish Balay } else if (numFields) { /* we send one submat for each field: sum their sizes */ 21796ecaa68aSToby Isaac matSize = 0; 21806ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21816ecaa68aSToby Isaac PetscInt numRow, numCol; 21826ecaa68aSToby Isaac 21836ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2184f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 21856ecaa68aSToby Isaac matSize += numRow * numCol; 21866ecaa68aSToby Isaac } 21879371c9d4SSatish Balay } else { 21886ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 21896ecaa68aSToby Isaac } 2190f13f9184SToby Isaac } else if (maxChildId == -1) { 21918d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2192f13f9184SToby Isaac PetscInt aOff, a; 21936ecaa68aSToby Isaac 21949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 21956ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21966ecaa68aSToby Isaac PetscInt fDof; 21976ecaa68aSToby Isaac 21989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 219921968bf8SToby Isaac offsets[f + 1] = fDof; 22006ecaa68aSToby Isaac } 22016ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 22026ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 22036ecaa68aSToby Isaac 22049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, anchor, &aLocalDof)); 22056ecaa68aSToby Isaac numColIndices += aLocalDof; 22066ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22076ecaa68aSToby Isaac PetscInt fDof; 22086ecaa68aSToby Isaac 22099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 221021968bf8SToby Isaac newOffsets[f + 1] += fDof; 22116ecaa68aSToby Isaac } 22126ecaa68aSToby Isaac } 22136ecaa68aSToby Isaac if (numFields) { 22146ecaa68aSToby Isaac matSize = 0; 2215ad540459SPierre Jolivet for (f = 0; f < numFields; f++) matSize += offsets[f + 1] * newOffsets[f + 1]; 22169371c9d4SSatish Balay } else { 22176ecaa68aSToby Isaac matSize = numColIndices * dof; 22186ecaa68aSToby Isaac } 22199371c9d4SSatish Balay } else { /* no children, and no constraints on dofs: just get the global indices */ 22206ecaa68aSToby Isaac numColIndices = dof; 22216ecaa68aSToby Isaac matSize = 0; 22226ecaa68aSToby Isaac } 22238d2f55e7SToby Isaac } 222446bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 22259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootIndicesSec, p, numColIndices ? numColIndices + 2 * numFields : 0)); 22269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootMatricesSec, p, matSize)); 22276ecaa68aSToby Isaac } 22289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootIndicesSec)); 22299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootMatricesSec)); 22306ecaa68aSToby Isaac { 22316ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 22326ecaa68aSToby Isaac 22339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 22349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootMatricesSec, &numRootMatrices)); 22359566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRootIndices, &rootIndices, numRootMatrices, &rootMatrices)); 22366ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22376ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2238f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 22396ecaa68aSToby Isaac PetscInt *pInd; 22406ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22416ecaa68aSToby Isaac PetscScalar *pMat = NULL; 22426ecaa68aSToby Isaac 22439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, p, &numColIndices)); 2244ad540459SPierre Jolivet if (!numColIndices) continue; 2245f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2246f13f9184SToby Isaac offsets[f] = 0; 2247f13f9184SToby Isaac newOffsets[f] = 0; 2248f13f9184SToby Isaac offsetsCopy[f] = 0; 2249f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2250f13f9184SToby Isaac } 22516ecaa68aSToby Isaac numColIndices -= 2 * numFields; 22529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, p, &pIndOff)); 22536ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 22549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootMatricesSec, p, &matSize)); 22556ecaa68aSToby Isaac if (matSize) { 22569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootMatricesSec, p, &pMatOff)); 22576ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 22586ecaa68aSToby Isaac } 22599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 2260ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 22616ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 22626ecaa68aSToby Isaac PetscInt i, j; 22636ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 22646ecaa68aSToby Isaac 22656ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 22666ecaa68aSToby Isaac PetscInt numIndices, *indices; 22679566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 226808401ef6SPierre Jolivet PetscCheck(numIndices == numColIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "mismatching constraint indices calculations"); 2269ad540459SPierre Jolivet for (i = 0; i < numColIndices; i++) pInd[i] = indices[i]; 22706ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 227146bdb399SToby Isaac pInd[numColIndices + i] = offsets[i + 1]; 227246bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i + 1]; 22736ecaa68aSToby Isaac } 22749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 22759371c9d4SSatish Balay } else { 22766ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 22776ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 22786ecaa68aSToby Isaac PetscInt numPoints, *points; 22796ecaa68aSToby Isaac 22809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices * numRowIndices, MPIU_SCALAR, &pMatIn)); 22816ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 2282ad540459SPierre Jolivet for (j = 0; j < numRowIndices; j++) pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 22836ecaa68aSToby Isaac } 22849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 22854acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 22869566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 22879566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 22884acb8e1eSToby Isaac } 22896ecaa68aSToby Isaac if (numFields) { 22906ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 22916ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 22926ecaa68aSToby Isaac 22936ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22946ecaa68aSToby Isaac PetscInt fDof; 22956ecaa68aSToby Isaac 22969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &fDof)); 22976ecaa68aSToby Isaac offsets[f + 1] += fDof; 22986ecaa68aSToby Isaac } 22996ecaa68aSToby Isaac } 23006ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23016ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23026ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 23036ecaa68aSToby Isaac } 23046ecaa68aSToby Isaac } 23054acb8e1eSToby Isaac /* TODO : flips here ? */ 23066ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 23079566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, perms, pMatIn, &numPoints, NULL, &points, &pMatModified, newOffsets, PETSC_FALSE)); 23084acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23099566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 23109566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 23114acb8e1eSToby Isaac } 23124acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23139566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23149566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23154acb8e1eSToby Isaac } 23166ecaa68aSToby Isaac if (!numFields) { 2317ad540459SPierre Jolivet for (i = 0; i < numRowIndices * numColIndices; i++) pMat[i] = pMatModified[i]; 23189371c9d4SSatish Balay } else { 2319f13f9184SToby Isaac PetscInt i, j, count; 23206ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 23216ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f + 1]; i++) { 2322ad540459SPierre Jolivet for (j = newOffsets[f]; j < newOffsets[f + 1]; j++, count++) pMat[count] = pMatModified[i * numColIndices + j]; 23236ecaa68aSToby Isaac } 23246ecaa68aSToby Isaac } 23256ecaa68aSToby Isaac } 23269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatModified)); 23279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 23289566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatIn)); 23296ecaa68aSToby Isaac if (numFields) { 233046bdb399SToby Isaac for (f = 0; f < numFields; f++) { 233146bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 233246bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 23336ecaa68aSToby Isaac } 23344acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23354acb8e1eSToby Isaac PetscInt globalOff, c = points[2 * cl]; 23369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23379566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd)); 23386ecaa68aSToby Isaac } 23396ecaa68aSToby Isaac } else { 23404acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23414acb8e1eSToby Isaac PetscInt c = points[2 * cl], globalOff; 23424acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 23434acb8e1eSToby Isaac 23449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23459566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd)); 23466ecaa68aSToby Isaac } 23476ecaa68aSToby Isaac } 23484acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23499566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23509566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23514acb8e1eSToby Isaac } 23529566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numPoints, MPIU_SCALAR, &points)); 23536ecaa68aSToby Isaac } 23549371c9d4SSatish Balay } else if (matSize) { 23556ecaa68aSToby Isaac PetscInt cOff; 23566ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 23576ecaa68aSToby Isaac 23586ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 235908401ef6SPierre Jolivet PetscCheck(numRowIndices == dof, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Miscounted dofs"); 23609566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 23619566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 23629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &cOff)); 23639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 23649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 23656ecaa68aSToby Isaac if (numFields) { 23666ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23676ecaa68aSToby Isaac PetscInt fDof; 2368f13f9184SToby Isaac 23699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &fDof)); 23706ecaa68aSToby Isaac offsets[f + 1] = fDof; 23716ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23726ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 23739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 23746ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 23756ecaa68aSToby Isaac } 23766ecaa68aSToby Isaac } 23776ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23786ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23796ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 23806ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 23816ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 23826ecaa68aSToby Isaac } 23839566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, -1, NULL, rowIndices)); 23846ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23856ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23879566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, -1, NULL, colIndices)); 23886ecaa68aSToby Isaac } 23899371c9d4SSatish Balay } else { 23909566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, NULL, rowIndices)); 23916ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23926ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23949566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, NULL, colIndices)); 23956ecaa68aSToby Isaac } 23966ecaa68aSToby Isaac } 23976ecaa68aSToby Isaac if (numFields) { 2398f13f9184SToby Isaac PetscInt count, a; 2399f13f9184SToby Isaac 24006ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24016ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 24026ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 24039566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, iSize, &rowIndices[offsets[f]], jSize, &colIndices[newOffsets[f]], &pMat[count])); 24046ecaa68aSToby Isaac count += iSize * jSize; 240546bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 240646bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 24076ecaa68aSToby Isaac } 24086ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 24096ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 24106ecaa68aSToby Isaac PetscInt gOff; 24119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 24129566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 24136ecaa68aSToby Isaac } 24149371c9d4SSatish Balay } else { 24156ecaa68aSToby Isaac PetscInt a; 24169566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, numRowIndices, rowIndices, numColIndices, colIndices, pMat)); 24176ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 24186ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 24196ecaa68aSToby Isaac PetscInt gOff; 24209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 24219566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, NULL, pInd)); 24226ecaa68aSToby Isaac } 24236ecaa68aSToby Isaac } 24249566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 24259566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 24269371c9d4SSatish Balay } else { 24276ecaa68aSToby Isaac PetscInt gOff; 24286ecaa68aSToby Isaac 24299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 24306ecaa68aSToby Isaac if (numFields) { 24316ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24326ecaa68aSToby Isaac PetscInt fDof; 24339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 24346ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 24356ecaa68aSToby Isaac } 24366ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 243746bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 243846bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f + 1]; 24396ecaa68aSToby Isaac } 24409566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 2441367003a6SStefano Zampini } else { 24429566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 24436ecaa68aSToby Isaac } 24446ecaa68aSToby Isaac } 24456ecaa68aSToby Isaac } 24469566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 24476ecaa68aSToby Isaac } 244846bdb399SToby Isaac { 244946bdb399SToby Isaac PetscSF indicesSF, matricesSF; 245046bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 245146bdb399SToby Isaac 24529566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 24539566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafMatricesSec)); 24549566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootIndicesSec, &remoteOffsetsIndices, leafIndicesSec)); 24559566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootMatricesSec, &remoteOffsetsMatrices, leafMatricesSec)); 24569566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootIndicesSec, remoteOffsetsIndices, leafIndicesSec, &indicesSF)); 24579566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootMatricesSec, remoteOffsetsMatrices, leafMatricesSec, &matricesSF)); 24589566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 24599566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsIndices)); 24609566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsMatrices)); 24619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numLeafIndices)); 24629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafMatricesSec, &numLeafMatrices)); 24639566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numLeafIndices, &leafIndices, numLeafMatrices, &leafMatrices)); 24649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24689566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&matricesSF)); 24699566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 24709566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootIndices, rootMatrices)); 24719566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 24729566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootMatricesSec)); 247346bdb399SToby Isaac } 247446bdb399SToby Isaac /* count to preallocate */ 24759566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 247646bdb399SToby Isaac { 247746bdb399SToby Isaac PetscInt nGlobal; 247846bdb399SToby Isaac PetscInt *dnnz, *onnz; 2479b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2480b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 24811c58ffc4SToby Isaac PetscInt maxDof; 24821c58ffc4SToby Isaac PetscInt *rowIndices; 24831c58ffc4SToby Isaac DM refTree; 24841c58ffc4SToby Isaac PetscInt **refPointFieldN; 24851c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 24861c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 24870eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, maxConDof, maxColumns, leafStart, leafEnd; 24881c58ffc4SToby Isaac PetscScalar *pointWork; 248946bdb399SToby Isaac 24909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalFine, &nGlobal)); 24919566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nGlobal, &dnnz, nGlobal, &onnz)); 24929566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 24939566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 24949566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 24959566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 24969566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 24979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 24989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafIndicesSec, &leafStart, &leafEnd)); 24999566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 25000eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 250146bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 250246bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 250346bdb399SToby Isaac PetscInt matSize; 250421968bf8SToby Isaac PetscInt i; 250546bdb399SToby Isaac 25069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 25079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 2508ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 25099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 251008401ef6SPierre Jolivet PetscCheck(gOff >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I though having global dofs meant a non-negative offset"); 25111dca8a05SBarry Smith PetscCheck(gOff >= rowStart && (gOff + gDof - gcDof) <= rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I thought the row map would constrain the global dofs"); 25129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 25139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 251446bdb399SToby Isaac numColIndices -= 2 * numFields; 251508401ef6SPierre Jolivet PetscCheck(numColIndices > 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "global fine dof with no dofs to interpolate from"); 251646bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 251721968bf8SToby Isaac offsets[0] = 0; 251821968bf8SToby Isaac offsetsCopy[0] = 0; 251921968bf8SToby Isaac newOffsets[0] = 0; 252021968bf8SToby Isaac newOffsetsCopy[0] = 0; 252146bdb399SToby Isaac if (numFields) { 252221968bf8SToby Isaac PetscInt f; 252346bdb399SToby Isaac for (f = 0; f < numFields; f++) { 252446bdb399SToby Isaac PetscInt rowDof; 252546bdb399SToby Isaac 25269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 252721968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 252821968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 252921968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 253021968bf8SToby Isaac numD[f] = 0; 253121968bf8SToby Isaac numO[f] = 0; 253246bdb399SToby Isaac } 25339566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 253446bdb399SToby Isaac for (f = 0; f < numFields; f++) { 253521968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 253621968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 253746bdb399SToby Isaac 253846bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 253946bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 254046bdb399SToby Isaac 254146bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 254221968bf8SToby Isaac numD[f]++; 25439371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 254421968bf8SToby Isaac numO[f]++; 254546bdb399SToby Isaac } 254646bdb399SToby Isaac } 254746bdb399SToby Isaac } 25489371c9d4SSatish Balay } else { 25499566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 255021968bf8SToby Isaac numD[0] = 0; 255121968bf8SToby Isaac numO[0] = 0; 255246bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 255346bdb399SToby Isaac PetscInt gInd = pInd[i]; 255446bdb399SToby Isaac 255546bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 255621968bf8SToby Isaac numD[0]++; 25579371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 255821968bf8SToby Isaac numO[0]++; 255946bdb399SToby Isaac } 256046bdb399SToby Isaac } 256146bdb399SToby Isaac } 25629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 256346bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 256446bdb399SToby Isaac PetscInt childId; 256546bdb399SToby Isaac 256646bdb399SToby Isaac childId = childIds[p - pStartF]; 256721968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 256846bdb399SToby Isaac if (numFields) { 2569b9a5774bSToby Isaac PetscInt f; 2570b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 257121968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 257246bdb399SToby Isaac for (row = 0; row < numRows; row++) { 257321968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 257421968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 257546bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25761dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2577b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25789371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25791dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2580b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25819371c9d4SSatish Balay } else { /* constrained */ 258208401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 258346bdb399SToby Isaac } 258446bdb399SToby Isaac } 258546bdb399SToby Isaac } 25869371c9d4SSatish Balay } else { 2587b9a5774bSToby Isaac PetscInt i; 2588b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 258946bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 259046bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 259146bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25921dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2593b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25949371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25951dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2596b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25979371c9d4SSatish Balay } else { /* constrained */ 259808401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 259946bdb399SToby Isaac } 260046bdb399SToby Isaac } 260146bdb399SToby Isaac } 26029371c9d4SSatish Balay } else { /* interpolate from all */ 260346bdb399SToby Isaac if (numFields) { 2604b9a5774bSToby Isaac PetscInt f; 2605b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 260621968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 260746bdb399SToby Isaac for (row = 0; row < numRows; row++) { 260821968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 260946bdb399SToby Isaac if (gIndFine >= 0) { 26101dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2611b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2612b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 261346bdb399SToby Isaac } 261446bdb399SToby Isaac } 261546bdb399SToby Isaac } 26169371c9d4SSatish Balay } else { 2617b9a5774bSToby Isaac PetscInt i; 2618b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 261946bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 262046bdb399SToby Isaac if (gIndFine >= 0) { 26211dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2622b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2623b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 262446bdb399SToby Isaac } 262546bdb399SToby Isaac } 262646bdb399SToby Isaac } 262746bdb399SToby Isaac } 26289371c9d4SSatish Balay } else { /* interpolate from all */ 262946bdb399SToby Isaac if (numFields) { 2630b9a5774bSToby Isaac PetscInt f; 2631b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 263221968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 263346bdb399SToby Isaac for (row = 0; row < numRows; row++) { 263421968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 263546bdb399SToby Isaac if (gIndFine >= 0) { 26361dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2637b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2638b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 263946bdb399SToby Isaac } 264046bdb399SToby Isaac } 264146bdb399SToby Isaac } 26429371c9d4SSatish Balay } else { /* every dof get a full row */ 2643b9a5774bSToby Isaac PetscInt i; 2644b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 264546bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 264646bdb399SToby Isaac if (gIndFine >= 0) { 26471dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2648b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2649b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 265046bdb399SToby Isaac } 265146bdb399SToby Isaac } 265246bdb399SToby Isaac } 265346bdb399SToby Isaac } 265446bdb399SToby Isaac } 26559566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, dnnz, onnz, NULL, NULL)); 26569566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnnz, onnz)); 265721968bf8SToby Isaac 26589566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 26599566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 26609566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 26619566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 26629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 26639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxConDof)); 26649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(leafIndicesSec, &maxColumns)); 26659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConDof * maxColumns, &pointWork)); 26660eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2667e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2668e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2669e44e4e7fSToby Isaac PetscInt matSize; 2670e44e4e7fSToby Isaac PetscInt childId; 2671e44e4e7fSToby Isaac 26729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 26739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 2674ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 2675e44e4e7fSToby Isaac childId = childIds[p - pStartF]; 26769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 26779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 26789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 2679e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2680e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2681e44e4e7fSToby Isaac offsets[0] = 0; 2682e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2683e44e4e7fSToby Isaac newOffsets[0] = 0; 2684e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2685e44e4e7fSToby Isaac rowOffsets[0] = 0; 2686e44e4e7fSToby Isaac if (numFields) { 2687e44e4e7fSToby Isaac PetscInt f; 2688e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2689e44e4e7fSToby Isaac PetscInt rowDof; 2690e44e4e7fSToby Isaac 26919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 2692e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2693e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2694e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2695e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2696e44e4e7fSToby Isaac } 26979566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 26989371c9d4SSatish Balay } else { 26999566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 27001c58ffc4SToby Isaac } 27019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 2702e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2703e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2704e44e4e7fSToby Isaac if (numFields) { 2705e44e4e7fSToby Isaac PetscInt f; 2706e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2707e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 270848a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[offsets[f] + row], pInd[newOffsets[f] + row], 1., INSERT_VALUES)); 270921968bf8SToby Isaac } 27109371c9d4SSatish Balay } else { 2711e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 271248a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[row], pInd[row], 1., INSERT_VALUES)); 2713e44e4e7fSToby Isaac } 27149371c9d4SSatish Balay } else { /* interpolate from all */ 2715e44e4e7fSToby Isaac if (numFields) { 2716e44e4e7fSToby Isaac PetscInt f; 2717e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2718e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2719e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 27209566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], refPointFieldMats[childId - pRefStart][f], INSERT_VALUES)); 2721e44e4e7fSToby Isaac } 27229371c9d4SSatish Balay } else { 27239566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, refPointFieldMats[childId - pRefStart][0], INSERT_VALUES)); 2724e44e4e7fSToby Isaac } 2725e44e4e7fSToby Isaac } 27269371c9d4SSatish Balay } else { /* interpolate from all */ 2727e44e4e7fSToby Isaac PetscInt pMatOff; 2728e44e4e7fSToby Isaac PetscScalar *pMat; 2729e44e4e7fSToby Isaac 27309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafMatricesSec, p, &pMatOff)); 2731e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2732e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2733e44e4e7fSToby Isaac if (numFields) { 2734e44e4e7fSToby Isaac PetscInt f, count; 2735e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2736e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2737e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2738e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2739e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2740e44e4e7fSToby Isaac 27419566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], inMat, INSERT_VALUES)); 2742e44e4e7fSToby Isaac count += numCols * numInRows; 2743e44e4e7fSToby Isaac } 27449371c9d4SSatish Balay } else { 27459566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, pMat, INSERT_VALUES)); 2746e44e4e7fSToby Isaac } 27479371c9d4SSatish Balay } else { /* multiply the incoming matrix by the child interpolation */ 2748e44e4e7fSToby Isaac if (numFields) { 2749e44e4e7fSToby Isaac PetscInt f, count; 2750e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2751e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2752e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2753e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2754e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2755e44e4e7fSToby Isaac PetscInt i, j, k; 275608401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][f] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2757e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2758e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2759e44e4e7fSToby Isaac PetscScalar val = 0.; 2760ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2761e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2762e44e4e7fSToby Isaac } 2763e44e4e7fSToby Isaac } 27649566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], pointWork, INSERT_VALUES)); 2765e44e4e7fSToby Isaac count += numCols * numInRows; 2766e44e4e7fSToby Isaac } 27679371c9d4SSatish Balay } else { /* every dof gets a full row */ 2768e44e4e7fSToby Isaac PetscInt numRows = gDof; 2769e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2770e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2771e44e4e7fSToby Isaac PetscInt i, j, k; 277208401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][0] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2773e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2774e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2775e44e4e7fSToby Isaac PetscScalar val = 0.; 2776ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2777e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2778e44e4e7fSToby Isaac } 2779e44e4e7fSToby Isaac } 27809566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, rowIndices, numCols, pInd, pointWork, INSERT_VALUES)); 2781e44e4e7fSToby Isaac } 2782e44e4e7fSToby Isaac } 2783e44e4e7fSToby Isaac } 2784e44e4e7fSToby Isaac } 27859566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 27869566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 27879566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 2788e44e4e7fSToby Isaac } 27899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 27909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 27919566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 27929566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafMatricesSec)); 27939566063dSJacob Faibussowitsch PetscCall(PetscFree2(leafIndices, leafMatrices)); 27949566063dSJacob Faibussowitsch PetscCall(PetscFree2(*(PetscInt ****)&perms, *(PetscScalar ****)&flips)); 27959566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 27969566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 27973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27986ecaa68aSToby Isaac } 2799154bca37SToby Isaac 28008d2f55e7SToby Isaac /* 28018d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 28028d2f55e7SToby Isaac * 28038d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 28048d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 28058d2f55e7SToby Isaac * for each fine dof \phi^f_j; 28068d2f55e7SToby Isaac * a_{i,j} = 0; 28078d2f55e7SToby Isaac * for each fine dof \phi^f_k: 28088d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 28098d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 28108d2f55e7SToby Isaac */ 2811d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 2812d71ae5a4SJacob Faibussowitsch { 28138d2f55e7SToby Isaac PetscDS ds; 28148d2f55e7SToby Isaac PetscSection section, cSection; 28158d2f55e7SToby Isaac DMLabel canonical, depth; 28168d2f55e7SToby Isaac Mat cMat, mat; 28178d2f55e7SToby Isaac PetscInt *nnz; 28188d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 28198d2f55e7SToby Isaac PetscInt m, n; 28208d2f55e7SToby Isaac PetscScalar *pointScalar; 28218d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 28228d2f55e7SToby Isaac 28238d2f55e7SToby Isaac PetscFunctionBegin; 28249566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, §ion)); 28259566063dSJacob Faibussowitsch PetscCall(DMGetDimension(refTree, &dim)); 28269566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(dim, &v0, dim, &v0parent, dim, &vtmp, dim * dim, &J, dim * dim, &Jparent, dim * dim, &invJ)); 28279566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim, &pointScalar, dim, &pointRef)); 28289566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 28299566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 28309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numSecFields)); 28319566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical)); 28329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "depth", &depth)); 28339566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSection, &cMat, NULL)); 28349566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(refTree, &pStart, &pEnd)); 28359566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd)); 28369566063dSJacob Faibussowitsch PetscCall(MatGetSize(cMat, &n, &m)); /* the injector has transpose sizes from the constraint matrix */ 28378d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 28389566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 28398d2f55e7SToby 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 */ 28408d2f55e7SToby Isaac const PetscInt *children; 28418d2f55e7SToby Isaac PetscInt numChildren; 28428d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28438d2f55e7SToby Isaac 28448d2f55e7SToby Isaac if (canonical) { 28458d2f55e7SToby Isaac PetscInt pCanonical; 28469566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28478d2f55e7SToby Isaac if (p != pCanonical) continue; 28488d2f55e7SToby Isaac } 28499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28508d2f55e7SToby Isaac if (!numChildren) continue; 28518d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28528d2f55e7SToby Isaac PetscInt child = children[i]; 28538d2f55e7SToby Isaac PetscInt dof; 28548d2f55e7SToby Isaac 28559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 28568d2f55e7SToby Isaac numChildDof += dof; 28578d2f55e7SToby Isaac } 28589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 28598d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 28608d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 28618d2f55e7SToby Isaac PetscInt selfOff; 28628d2f55e7SToby Isaac 28638d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 28648d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28658d2f55e7SToby Isaac PetscInt child = children[i]; 28668d2f55e7SToby Isaac PetscInt dof; 28678d2f55e7SToby Isaac 28689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 28698d2f55e7SToby Isaac numChildDof += dof; 28708d2f55e7SToby Isaac } 28719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 28729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 28739371c9d4SSatish Balay } else { 28749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 28758d2f55e7SToby Isaac } 2876ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) nnz[selfOff + i] = numChildDof; 28778d2f55e7SToby Isaac } 28788d2f55e7SToby Isaac } 28799566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(PETSC_COMM_SELF, m, n, m, n, -1, nnz, -1, NULL, &mat)); 28809566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 28818d2f55e7SToby Isaac /* Setp 2: compute entries */ 28828d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 28838d2f55e7SToby Isaac const PetscInt *children; 28848d2f55e7SToby Isaac PetscInt numChildren; 28858d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28868d2f55e7SToby Isaac 28878d2f55e7SToby Isaac /* same conditions about when entries occur */ 28888d2f55e7SToby Isaac if (canonical) { 28898d2f55e7SToby Isaac PetscInt pCanonical; 28909566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28918d2f55e7SToby Isaac if (p != pCanonical) continue; 28928d2f55e7SToby Isaac } 28939566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28948d2f55e7SToby Isaac if (!numChildren) continue; 28958d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28968d2f55e7SToby Isaac PetscInt child = children[i]; 28978d2f55e7SToby Isaac PetscInt dof; 28988d2f55e7SToby Isaac 28999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 29008d2f55e7SToby Isaac numChildDof += dof; 29018d2f55e7SToby Isaac } 29029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 29038d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 29048d2f55e7SToby Isaac 29058d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 290659fc6756SToby Isaac PetscInt pI = -1, cI = -1; 290752a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell; 29088d2f55e7SToby Isaac PetscInt cellShapeOff; 29098d2f55e7SToby Isaac PetscObject disc; 29108d2f55e7SToby Isaac PetscDualSpace dsp; 29118d2f55e7SToby Isaac PetscClassId classId; 29128d2f55e7SToby Isaac PetscScalar *pointMat; 29133b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 29148d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 29158d2f55e7SToby Isaac const PetscInt *depthNumDof; 29168d2f55e7SToby Isaac 29178d2f55e7SToby Isaac if (numSecFields) { 29188d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 29198d2f55e7SToby Isaac PetscInt child = children[i]; 29208d2f55e7SToby Isaac PetscInt dof; 29218d2f55e7SToby Isaac 29229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 29238d2f55e7SToby Isaac numChildDof += dof; 29248d2f55e7SToby Isaac } 29259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 29269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 29279371c9d4SSatish Balay } else { 29289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 29298d2f55e7SToby Isaac } 29308d2f55e7SToby Isaac 29313b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 29328d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 29338d2f55e7SToby Isaac parentCell = p; 29349371c9d4SSatish Balay } else { 29358d2f55e7SToby Isaac PetscInt *star = NULL; 29368d2f55e7SToby Isaac PetscInt numStar; 29378d2f55e7SToby Isaac 29388d2f55e7SToby Isaac parentCell = -1; 29399566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29408d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 29418d2f55e7SToby Isaac PetscInt c = star[2 * i]; 29428d2f55e7SToby Isaac 29438d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 29448d2f55e7SToby Isaac parentCell = c; 29458d2f55e7SToby Isaac break; 29468d2f55e7SToby Isaac } 29478d2f55e7SToby Isaac } 29489566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29498d2f55e7SToby Isaac } 2950a5b23f4aSJose E. Roman /* determine the offset of p's shape functions within parentCell's shape functions */ 29519566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 29529566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &classId)); 2953c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 29549566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 29559371c9d4SSatish Balay } else if (classId == PETSCFV_CLASSID) { 29569566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace((PetscFV)disc, &dsp)); 29579371c9d4SSatish Balay } else { 29589b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported discretization object"); 2959c5356c36SToby Isaac } 29609566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dsp, &depthNumDof)); 29619566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dsp, &Nc)); 29628d2f55e7SToby Isaac { 29638d2f55e7SToby Isaac PetscInt *closure = NULL; 29648d2f55e7SToby Isaac PetscInt numClosure; 29658d2f55e7SToby Isaac 29669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 296759fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) { 29688d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 29698d2f55e7SToby Isaac 29708d2f55e7SToby Isaac pO = closure[2 * i + 1]; 297159fc6756SToby Isaac if (point == p) { 297259fc6756SToby Isaac pI = i; 297359fc6756SToby Isaac break; 297459fc6756SToby Isaac } 29759566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 29768d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 29778d2f55e7SToby Isaac } 29789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 29798d2f55e7SToby Isaac } 29808d2f55e7SToby Isaac 29819566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 29829566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 298352a3aeb4SToby Isaac matCols = matRows + numSelfDof; 2984ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) matRows[i] = selfOff + i; 298552a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.; 29863b1c2a6aSToby Isaac { 29873b1c2a6aSToby Isaac PetscInt colOff = 0; 29883b1c2a6aSToby Isaac 29893b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 29903b1c2a6aSToby Isaac PetscInt child = children[i]; 29913b1c2a6aSToby Isaac PetscInt dof, off, j; 29923b1c2a6aSToby Isaac 29933b1c2a6aSToby Isaac if (numSecFields) { 29949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSection, child, f, &dof)); 29959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSection, child, f, &off)); 29969371c9d4SSatish Balay } else { 29979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSection, child, &dof)); 29989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSection, child, &off)); 29993b1c2a6aSToby Isaac } 30003b1c2a6aSToby Isaac 3001ad540459SPierre Jolivet for (j = 0; j < dof; j++) matCols[colOff++] = off + j; 30023b1c2a6aSToby Isaac } 30033b1c2a6aSToby Isaac } 30048d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 30058d2f55e7SToby Isaac PetscFE fe = (PetscFE)disc; 30068d2f55e7SToby Isaac PetscInt fSize; 300759fc6756SToby Isaac const PetscInt ***perms; 300859fc6756SToby Isaac const PetscScalar ***flips; 300959fc6756SToby Isaac const PetscInt *pperms; 301059fc6756SToby Isaac 30119566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dsp)); 30129566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dsp, &fSize)); 30139566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dsp, &perms, &flips)); 301459fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL; 301552a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */ 30168d2f55e7SToby Isaac PetscQuadrature q; 301752a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k; 30188d2f55e7SToby Isaac const PetscReal *points; 30198d2f55e7SToby Isaac const PetscReal *weights; 30208d2f55e7SToby Isaac PetscInt *closure = NULL; 30218d2f55e7SToby Isaac PetscInt numClosure; 302259fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i; 302359fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell; 3024ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent; 30258d2f55e7SToby Isaac 30269566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dsp, parentCellShapeDof, &q)); 30279566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, &thisNc, &numPoints, &points, &weights)); 302863a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 30299566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, numPoints, points, 0, &Tparent)); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 30303b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 30318d2f55e7SToby Isaac PetscInt childCell = -1; 303252a3aeb4SToby Isaac PetscReal *parentValAtPoint; 3033c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 30348d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 30358d2f55e7SToby Isaac const PetscScalar *point; 3036ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild; 30378d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 30388d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 30398d2f55e7SToby Isaac PetscInt d; 30408d2f55e7SToby Isaac 3041ad540459SPierre Jolivet for (d = 0; d < dim; d++) pointScalar[d] = points[dim * j + d]; 30428d2f55e7SToby Isaac point = pointScalar; 30438d2f55e7SToby Isaac #else 30448d2f55e7SToby Isaac point = pointReal; 30458d2f55e7SToby Isaac #endif 30468d2f55e7SToby Isaac 3047ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc]; 30483b1c2a6aSToby Isaac 30493b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 30508d2f55e7SToby Isaac PetscInt child = children[k]; 30518d2f55e7SToby Isaac PetscInt *star = NULL; 30528d2f55e7SToby Isaac PetscInt numStar, s; 30538d2f55e7SToby Isaac 30549566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30558d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 30568d2f55e7SToby Isaac PetscInt c = star[2 * s]; 30578d2f55e7SToby Isaac 30588d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 30599566063dSJacob Faibussowitsch PetscCall(DMPlexLocatePoint_Internal(refTree, dim, point, c, &childCell)); 30608d2f55e7SToby Isaac if (childCell >= 0) break; 30618d2f55e7SToby Isaac } 30629566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30638d2f55e7SToby Isaac if (childCell >= 0) break; 30648d2f55e7SToby Isaac } 306508401ef6SPierre Jolivet PetscCheck(childCell >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not locate quadrature point"); 30669566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ)); 30679566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent)); 3068c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp); 3069c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef); 30708d2f55e7SToby Isaac 30719566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, 1, pointRef, 0, &Tchild)); 30729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 30733b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3074c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 30758d2f55e7SToby Isaac PetscInt l; 307659fc6756SToby Isaac const PetscInt *cperms; 30778d2f55e7SToby Isaac 30789566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, child, &childDepth)); 30798d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 308059fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) { 30818d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 30828d2f55e7SToby Isaac PetscInt pointDepth; 30838d2f55e7SToby Isaac 30848d2f55e7SToby Isaac childO = closure[2 * l + 1]; 308559fc6756SToby Isaac if (point == child) { 308659fc6756SToby Isaac cI = l; 308759fc6756SToby Isaac break; 308859fc6756SToby Isaac } 30899566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 30908d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 30918d2f55e7SToby Isaac } 30928d2f55e7SToby Isaac if (l == numClosure) { 30938d2f55e7SToby Isaac pointMatOff += childDof; 30948d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 30958d2f55e7SToby Isaac } 309659fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL; 30978d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 309859fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l; 309959fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell; 310052a3aeb4SToby Isaac PetscReal *childValAtPoint; 310152a3aeb4SToby Isaac PetscReal val = 0.; 31028d2f55e7SToby Isaac 3103ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc]; 3104ad540459SPierre Jolivet for (m = 0; m < Nc; m++) val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m]; 310552a3aeb4SToby Isaac 310652a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val; 31078d2f55e7SToby Isaac } 31088d2f55e7SToby Isaac pointMatOff += childDof; 31098d2f55e7SToby Isaac } 31109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 31119566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tchild)); 31128d2f55e7SToby Isaac } 31139566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tparent)); 31148d2f55e7SToby Isaac } 31159371c9d4SSatish Balay } else { /* just the volume-weighted averages of the children */ 31163b1c2a6aSToby Isaac PetscReal parentVol; 3117bfaa5bdcSToby Isaac PetscInt childCell; 31183b1c2a6aSToby Isaac 31199566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL)); 3120bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) { 312152a3aeb4SToby Isaac PetscInt child = children[i], j; 31223b1c2a6aSToby Isaac PetscReal childVol; 31233b1c2a6aSToby Isaac 31243b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 31259566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL)); 3126ad540459SPierre Jolivet for (j = 0; j < Nc; j++) pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol; 3127bfaa5bdcSToby Isaac childCell++; 31283b1c2a6aSToby Isaac } 31298d2f55e7SToby Isaac } 31303b1c2a6aSToby Isaac /* Insert pointMat into mat */ 31319566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numSelfDof, matRows, numChildDof, matCols, pointMat, INSERT_VALUES)); 31329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 31339566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 31348d2f55e7SToby Isaac } 31358d2f55e7SToby Isaac } 31369566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJ)); 31379566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointScalar, pointRef)); 31389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 31399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 31408d2f55e7SToby Isaac *inj = mat; 31413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31428d2f55e7SToby Isaac } 31438d2f55e7SToby Isaac 3144d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3145d71ae5a4SJacob Faibussowitsch { 3146f30e825dSToby Isaac PetscDS ds; 3147f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3148f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3149f30e825dSToby Isaac PetscSection refConSec, refSection; 3150f30e825dSToby Isaac 3151f30e825dSToby Isaac PetscFunctionBegin; 31529566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 31539566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 31549566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 31559566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 31569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 31579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 31589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 31599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 31609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &cols)); 3161f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3162f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3163f30e825dSToby Isaac 31649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 31659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 31669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3167f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3168f30e825dSToby Isaac 31699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFields, &refPointFieldMats[p - pRefStart])); 3170f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 317152a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r; 3172f30e825dSToby Isaac 3173f30e825dSToby Isaac if (numFields > 1) { 31749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 31759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 31769371c9d4SSatish Balay } else { 31779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 31789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 3179f30e825dSToby Isaac } 3180f30e825dSToby Isaac 3181ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r; 3182f30e825dSToby Isaac numCols = 0; 3183f30e825dSToby Isaac { 3184f30e825dSToby Isaac PetscInt aDof, aOff, j; 3185f30e825dSToby Isaac 3186f30e825dSToby Isaac if (numFields > 1) { 31879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, parent, f, &aDof)); 31889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, parent, f, &aOff)); 31899371c9d4SSatish Balay } else { 31909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &aDof)); 31919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, parent, &aOff)); 3192f30e825dSToby Isaac } 3193f30e825dSToby Isaac 3194ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + j; 3195f30e825dSToby Isaac } 31969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 3197f30e825dSToby Isaac /* transpose of constraint matrix */ 31989566063dSJacob Faibussowitsch PetscCall(MatGetValues(inj, numCols, cols, cDof, rows, refPointFieldMats[p - pRefStart][f])); 3199f30e825dSToby Isaac } 3200f30e825dSToby Isaac } 3201f30e825dSToby Isaac *childrenMats = refPointFieldMats; 32029566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 32039566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 32043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3205f30e825dSToby Isaac } 3206f30e825dSToby Isaac 3207d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3208d71ae5a4SJacob Faibussowitsch { 3209f30e825dSToby Isaac PetscDS ds; 3210f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3211f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3212c6154584SToby Isaac PetscSection refConSec, refSection; 3213f30e825dSToby Isaac 3214f30e825dSToby Isaac PetscFunctionBegin; 3215f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3216f30e825dSToby Isaac *childrenMats = NULL; 32179566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 32189566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 32199566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 32209566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 32219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 3222f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3223f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3224f30e825dSToby Isaac 32259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 32269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 32279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3228f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3229f30e825dSToby Isaac 3230f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3231f30e825dSToby Isaac PetscInt cDof; 3232f30e825dSToby Isaac 3233f30e825dSToby Isaac if (numFields > 1) { 32349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 32359371c9d4SSatish Balay } else { 32369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 3237f30e825dSToby Isaac } 3238f30e825dSToby Isaac 32399566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 3240f30e825dSToby Isaac } 32419566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 3242f30e825dSToby Isaac } 32439566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 32443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3245f30e825dSToby Isaac } 3246f30e825dSToby Isaac 3247d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree, Mat *injRef) 3248d71ae5a4SJacob Faibussowitsch { 3249ebf164c7SToby Isaac Mat cMatRef; 32506148253fSToby Isaac PetscObject injRefObj; 32518d2f55e7SToby Isaac 3252154bca37SToby Isaac PetscFunctionBegin; 32539566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, NULL, &cMatRef, NULL)); 32549566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", &injRefObj)); 3255ebf164c7SToby Isaac *injRef = (Mat)injRefObj; 3256ebf164c7SToby Isaac if (!*injRef) { 32579566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorReferenceTree(refTree, injRef)); 32589566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", (PetscObject)*injRef)); 3259ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 32609566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)*injRef)); 3261ebf164c7SToby Isaac } 32623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32636148253fSToby Isaac } 3264f30e825dSToby Isaac 3265d71ae5a4SJacob 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) 3266d71ae5a4SJacob Faibussowitsch { 3267c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3268ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3269ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3270c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3271c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3272c921d74cSToby Isaac const PetscInt *rootDegrees; 3273c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3274ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3275ebf164c7SToby Isaac 3276ebf164c7SToby Isaac PetscFunctionBegin; 32779566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 32789566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 32799566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 32809566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 32819566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 32829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafIndicesSec, pStartF, pEndF)); 32839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 32848d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 32857e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 32867e96bdafSToby Isaac const PetscInt *leaves; 32878d2f55e7SToby Isaac 32889566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 32897e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 32907e96bdafSToby Isaac p = leaves ? leaves[l] : l; 32919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 32929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 32938d2f55e7SToby Isaac if ((dof - cdof) > 0) { 32948d2f55e7SToby Isaac numPointsWithDofs++; 3295f30e825dSToby Isaac 32969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &dof)); 32979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafIndicesSec, p, dof + 1)); 32988d2f55e7SToby Isaac } 32998d2f55e7SToby Isaac } 33009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 33019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafIndicesSec)); 33029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numIndices)); 33039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1), &leafInds)); 33049566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(PetscMalloc1(numIndices, &leafVals)); 33057e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 33067e96bdafSToby Isaac p = leaves ? leaves[l] : l; 33079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 33089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 33098d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3310f30e825dSToby Isaac PetscInt off, gOff; 3311f30e825dSToby Isaac PetscInt *pInd; 3312c921d74cSToby Isaac PetscScalar *pVal = NULL; 3313f30e825dSToby Isaac 33147e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3315f30e825dSToby Isaac 33169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3317f30e825dSToby Isaac 3318c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3319c921d74cSToby Isaac if (gatheredValues) { 3320c921d74cSToby Isaac PetscInt i; 3321c921d74cSToby Isaac 3322c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3323c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3324c921d74cSToby Isaac } 33259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 3326f30e825dSToby Isaac 3327f30e825dSToby Isaac offsets[0] = 0; 3328f30e825dSToby Isaac if (numFields) { 3329f30e825dSToby Isaac PetscInt f; 3330f30e825dSToby Isaac 3331f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3332f30e825dSToby Isaac PetscInt fDof; 33339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &fDof)); 3334f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3335f30e825dSToby Isaac } 33369566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 3337367003a6SStefano Zampini } else { 33389566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 3339f30e825dSToby Isaac } 33409566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(VecGetValues(fineVec, dof, pInd, pVal)); 33418d2f55e7SToby Isaac } 33428d2f55e7SToby Isaac } 33439566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 33449566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 33458d2f55e7SToby Isaac } 3346f30e825dSToby Isaac 33479566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 33489566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 33499566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 3350f30e825dSToby Isaac 33516148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 33526148253fSToby Isaac MPI_Datatype threeInt; 33536148253fSToby Isaac PetscMPIInt rank; 33546148253fSToby Isaac PetscInt(*parentNodeAndIdCoarse)[3]; 33556148253fSToby Isaac PetscInt(*parentNodeAndIdFine)[3]; 33566148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 33576148253fSToby Isaac PetscSF pointSF, sfToParents; 33586148253fSToby Isaac const PetscInt *ilocal; 33596148253fSToby Isaac const PetscSFNode *iremote; 33606148253fSToby Isaac PetscSFNode *iremoteToParents; 33616148253fSToby Isaac PetscInt *ilocalToParents; 33626148253fSToby Isaac 33639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)coarse), &rank)); 33649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &threeInt)); 33659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&threeInt)); 33669566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndC - pStartC, &parentNodeAndIdCoarse, pEndF - pStartF, &parentNodeAndIdFine)); 33679566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(coarse, &pointSF)); 33689566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &nleaves, &ilocal, &iremote)); 33696148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 33706148253fSToby Isaac PetscInt parent, childId; 33719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(coarse, p, &parent, &childId)); 33726148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 33736148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 33746148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 33756148253fSToby Isaac if (nleaves > 0) { 33766148253fSToby Isaac PetscInt leaf = -1; 33776148253fSToby Isaac 33786148253fSToby Isaac if (ilocal) { 33799566063dSJacob Faibussowitsch PetscCall(PetscFindInt(parent, nleaves, ilocal, &leaf)); 33809371c9d4SSatish Balay } else { 33816148253fSToby Isaac leaf = p - pStartC; 33826148253fSToby Isaac } 33836148253fSToby Isaac if (leaf >= 0) { 33846148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 33856148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 33866148253fSToby Isaac } 33876148253fSToby Isaac } 33886148253fSToby Isaac } 33896148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 33906148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 33916148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 33926148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 33936148253fSToby Isaac } 33949566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 33959566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 33966148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3397f30e825dSToby Isaac PetscInt dof; 3398f30e825dSToby Isaac 33999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &dof)); 3400f30e825dSToby Isaac if (dof) { 3401f30e825dSToby Isaac PetscInt off; 3402f30e825dSToby Isaac 34039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3404c921d74cSToby Isaac if (gatheredIndices) { 3405c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3406c921d74cSToby Isaac } else if (gatheredValues) { 3407c921d74cSToby Isaac leafVals[off] = (PetscScalar)PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3408c921d74cSToby Isaac } 3409f30e825dSToby Isaac } 3410ad540459SPierre Jolivet if (parentNodeAndIdFine[p - pStartF][0] >= 0) nleavesToParents++; 34116148253fSToby Isaac } 34129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &ilocalToParents)); 34139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &iremoteToParents)); 34146148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 34156148253fSToby Isaac if (parentNodeAndIdFine[p - pStartF][0] >= 0) { 34166148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 34176148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p - pStartF][0]; 34186148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p - pStartF][1]; 34196148253fSToby Isaac nleavesToParents++; 34206148253fSToby Isaac } 34216148253fSToby Isaac } 34229566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)coarse), &sfToParents)); 34239566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfToParents, pEndC - pStartC, nleavesToParents, ilocalToParents, PETSC_OWN_POINTER, iremoteToParents, PETSC_OWN_POINTER)); 34249566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34256148253fSToby Isaac 34266148253fSToby Isaac coarseToFineEmbedded = sfToParents; 34276148253fSToby Isaac 34289566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentNodeAndIdCoarse, parentNodeAndIdFine)); 34299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&threeInt)); 34306148253fSToby Isaac } 3431f30e825dSToby Isaac 34326148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 34336148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 34346148253fSToby Isaac PetscSF sfDofsOnly; 34356148253fSToby Isaac 34366148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 34379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3439ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 34406148253fSToby Isaac } 34419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 34426148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 34439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3445ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = p - pStartC; 34466148253fSToby Isaac } 34479566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly)); 34489566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34499566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 34506148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 34516148253fSToby Isaac } 3452f30e825dSToby Isaac 34536148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 34549566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(coarseToFineEmbedded, &rootDegrees)); 34559566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(coarseToFineEmbedded, &rootDegrees)); 34569566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &multiRootSec)); 34579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(multiRootSec, pStartC, pEndC)); 345848a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionSetDof(multiRootSec, p, rootDegrees[p - pStartC])); 34599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(multiRootSec)); 34609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(multiRootSec, &numMulti)); 34619566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 3462f30e825dSToby Isaac { /* distribute the leaf section */ 3463f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3464f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 34658d2f55e7SToby Isaac 34669566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(coarseToFineEmbedded, &multi)); 34679566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(multi, &multiInv)); 34689566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(multiInv, leafIndicesSec, &remoteOffsets, rootIndicesSec)); 34699566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(multiInv, leafIndicesSec, remoteOffsets, rootIndicesSec, &indicesSF)); 34709566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 34719566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&multiInv)); 34729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 3473c921d74cSToby Isaac if (gatheredIndices) { 34749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootInds)); 34759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 34769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 3477c921d74cSToby Isaac } 3478c921d74cSToby Isaac if (gatheredValues) { 34799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootVals)); 34809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 34819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 3482c921d74cSToby Isaac } 34839566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 34848d2f55e7SToby Isaac } 34859566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 34869566063dSJacob Faibussowitsch PetscCall(PetscFree(leafInds)); 34879566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVals)); 34889566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 3489c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3490c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3491c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3492c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 34933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3494ebf164c7SToby Isaac } 3495ebf164c7SToby Isaac 3496d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3497d71ae5a4SJacob Faibussowitsch { 3498ebf164c7SToby Isaac DM refTree; 3499c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3500ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3501ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3502ebf164c7SToby Isaac PetscSection cSecRef; 3503277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd; 3504ebf164c7SToby Isaac Mat injRef; 3505c921d74cSToby Isaac PetscInt numFields, maxDof; 3506ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3507ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3508ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3509ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3510ebf164c7SToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3511ebf164c7SToby Isaac 3512ebf164c7SToby Isaac PetscFunctionBegin; 3513ebf164c7SToby Isaac 3514ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 35159566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 35169566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 35179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 35189566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 3519ebf164c7SToby Isaac 35209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 35219566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 35229566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 35239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 35249566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 35259566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 35269566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 35279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 3528ebf164c7SToby Isaac { 3529ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 35309566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 3531ebf164c7SToby Isaac } 3532ebf164c7SToby Isaac 35339566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, childIds, NULL, numFields, offsets, &multiRootSec, &rootIndicesSec, &rootIndices, NULL)); 35348d2f55e7SToby Isaac 35359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &parentIndices)); 3536f30e825dSToby Isaac 3537f30e825dSToby Isaac /* count indices */ 35389566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 35399566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 35409566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 35419566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 35429566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 35439566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(rowEnd - rowStart, &nnzD, rowEnd - rowStart, &nnzO)); 3544f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3545f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 35468d2f55e7SToby Isaac 35479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 35489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3549f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 35509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 35518d2f55e7SToby Isaac 35528d2f55e7SToby Isaac rowOffsets[0] = 0; 3553f30e825dSToby Isaac offsetsCopy[0] = 0; 35548d2f55e7SToby Isaac if (numFields) { 35558d2f55e7SToby Isaac PetscInt f; 35568d2f55e7SToby Isaac 3557f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3558f30e825dSToby Isaac PetscInt fDof; 35599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3560f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 35618d2f55e7SToby Isaac } 35629566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3563367003a6SStefano Zampini } else { 35649566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3565f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 35668d2f55e7SToby Isaac } 3567f30e825dSToby Isaac 35689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 35699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3570f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3571f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3572f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3573f30e825dSToby Isaac const PetscInt *childIndices; 3574f30e825dSToby Isaac 35759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 35769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3577f30e825dSToby Isaac childId = rootIndices[offset++]; 3578f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3579f30e825dSToby Isaac numIndices--; 3580f30e825dSToby Isaac 3581f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3582f30e825dSToby Isaac PetscInt i; 3583f30e825dSToby Isaac 3584f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3585f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3586f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3587f30e825dSToby Isaac if (rowIndex < 0) continue; 358808401ef6SPierre Jolivet PetscCheck(colIndex >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unconstrained fine and constrained coarse"); 3589a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3590f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 35919371c9d4SSatish Balay } else { 3592f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3593f30e825dSToby Isaac } 3594f30e825dSToby Isaac } 35959371c9d4SSatish Balay } else { 3596f30e825dSToby Isaac PetscInt parentId, f, lim; 3597f30e825dSToby Isaac 35989566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3599f30e825dSToby Isaac 3600f30e825dSToby Isaac lim = PetscMax(1, numFields); 3601f30e825dSToby Isaac offsets[0] = 0; 36028d2f55e7SToby Isaac if (numFields) { 36038d2f55e7SToby Isaac PetscInt f; 3604f30e825dSToby Isaac 36058d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3606f30e825dSToby Isaac PetscInt fDof; 36079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3608f30e825dSToby Isaac 3609f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 36108d2f55e7SToby Isaac } 36119371c9d4SSatish Balay } else { 3612f30e825dSToby Isaac PetscInt cDof; 3613f30e825dSToby Isaac 36149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3615f30e825dSToby Isaac offsets[1] = cDof; 3616f30e825dSToby Isaac } 3617f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3618f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3619f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3620f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3621f30e825dSToby Isaac 3622f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3623f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3624f30e825dSToby Isaac 3625f30e825dSToby Isaac if (colIndex < 0) continue; 3626f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3627f30e825dSToby Isaac numD++; 36289371c9d4SSatish Balay } else { 3629f30e825dSToby Isaac numO++; 3630f30e825dSToby Isaac } 3631f30e825dSToby Isaac } 3632f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3633f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3634f30e825dSToby Isaac 3635f30e825dSToby Isaac if (rowIndex < 0) continue; 3636f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3637f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 36388d2f55e7SToby Isaac } 36398d2f55e7SToby Isaac } 36408d2f55e7SToby Isaac } 3641f30e825dSToby Isaac } 3642f30e825dSToby Isaac } 3643f30e825dSToby Isaac /* preallocate */ 36449566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, nnzD, nnzO, NULL, NULL)); 36459566063dSJacob Faibussowitsch PetscCall(PetscFree2(nnzD, nnzO)); 3646f30e825dSToby Isaac /* insert values */ 36479566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 3648f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3649f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3650f30e825dSToby Isaac 36519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 36529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3653f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 36549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 3655f30e825dSToby Isaac 3656f30e825dSToby Isaac rowOffsets[0] = 0; 3657f30e825dSToby Isaac offsetsCopy[0] = 0; 36588d2f55e7SToby Isaac if (numFields) { 36598d2f55e7SToby Isaac PetscInt f; 3660f30e825dSToby Isaac 36618d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3662f30e825dSToby Isaac PetscInt fDof; 36639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3664f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3665f30e825dSToby Isaac } 36669566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3667367003a6SStefano Zampini } else { 36689566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3669f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3670f30e825dSToby Isaac } 3671f30e825dSToby Isaac 36729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 36739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3674f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3675f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3676f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3677f30e825dSToby Isaac const PetscInt *childIndices; 3678f30e825dSToby Isaac 36799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 36809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3681f30e825dSToby Isaac childId = rootIndices[offset++]; 3682f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3683f30e825dSToby Isaac numIndices--; 3684f30e825dSToby Isaac 3685f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3686f30e825dSToby Isaac PetscInt i; 3687f30e825dSToby Isaac 368848a46eb9SPierre Jolivet for (i = 0; i < numIndices; i++) PetscCall(MatSetValue(mat, parentIndices[i], childIndices[i], 1., INSERT_VALUES)); 36899371c9d4SSatish Balay } else { 3690f30e825dSToby Isaac PetscInt parentId, f, lim; 36918d2f55e7SToby Isaac 36929566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3693f30e825dSToby Isaac 3694f30e825dSToby Isaac lim = PetscMax(1, numFields); 3695f30e825dSToby Isaac offsets[0] = 0; 36968d2f55e7SToby Isaac if (numFields) { 3697f30e825dSToby Isaac PetscInt f; 36988d2f55e7SToby Isaac 3699f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3700f30e825dSToby Isaac PetscInt fDof; 37019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3702f30e825dSToby Isaac 3703f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 37048d2f55e7SToby Isaac } 37059371c9d4SSatish Balay } else { 3706f30e825dSToby Isaac PetscInt cDof; 3707f30e825dSToby Isaac 37089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3709f30e825dSToby Isaac offsets[1] = cDof; 37108d2f55e7SToby Isaac } 3711f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3712f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3713f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3714f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3715f30e825dSToby Isaac 37169566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, rowOffsets[f + 1] - rowOffsets[f], rowIndices, offsets[f + 1] - offsets[f], colIndices, childMat, INSERT_VALUES)); 37178d2f55e7SToby Isaac } 37188d2f55e7SToby Isaac } 37198d2f55e7SToby Isaac } 37208d2f55e7SToby Isaac } 37219566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 37229566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 37239566063dSJacob Faibussowitsch PetscCall(PetscFree(parentIndices)); 37249566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 37259566063dSJacob Faibussowitsch PetscCall(PetscFree(rootIndices)); 37269566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 3727f30e825dSToby Isaac 37289566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 37299566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 37303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3731154bca37SToby Isaac } 373238fc2455SToby Isaac 3733d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 3734d71ae5a4SJacob Faibussowitsch { 373562095d54SToby Isaac PetscSF coarseToFineEmbedded; 373662095d54SToby Isaac PetscSection globalCoarse, globalFine; 373762095d54SToby Isaac PetscSection localCoarse, localFine; 373862095d54SToby Isaac PetscSection aSec, cSec; 373962095d54SToby Isaac PetscSection rootValuesSec; 374062095d54SToby Isaac PetscSection leafValuesSec; 374162095d54SToby Isaac PetscScalar *rootValues, *leafValues; 374262095d54SToby Isaac IS aIS; 374362095d54SToby Isaac const PetscInt *anchors; 374462095d54SToby Isaac Mat cMat; 374562095d54SToby Isaac PetscInt numFields; 3746412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd; 374762095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 374862095d54SToby Isaac PetscInt *maxChildIds; 374962095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 37500eb7e1eaSToby Isaac PetscFV fv = NULL; 37510eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 37520eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 37530eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 37540eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 375562095d54SToby Isaac 3756ebf164c7SToby Isaac PetscFunctionBegin; 37579566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 37589566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 37599566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(coarse, 0, &cellStart, &cellEnd)); 37609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 37619566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 37629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(coarse, &dim)); 376362095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 3764e4a60869SToby Isaac PetscInt nleaves, l; 3765e4a60869SToby Isaac const PetscInt *leaves; 376662095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 376762095d54SToby Isaac 37689566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 3769e4a60869SToby Isaac 3770e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 3771e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3772e4a60869SToby Isaac 37739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 3775ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 377662095d54SToby Isaac } 37779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 37784833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 3779e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3780e4a60869SToby Isaac 37819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 3783ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l; 378462095d54SToby Isaac } 37859566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 37869566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 378762095d54SToby Isaac } 378862095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 37899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 3790ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2; 37919566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 37929566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 379362095d54SToby Isaac 37949566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 37959566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 379662095d54SToby Isaac 37979566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 37989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 37999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 380062095d54SToby Isaac 38019566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 38029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 380362095d54SToby Isaac 380462095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 38059566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootValuesSec)); 38069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootValuesSec, pStartC, pEndC)); 38079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 380862095d54SToby Isaac { 380962095d54SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 38109566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &newOffsets, maxFields, &newOffsetsCopy, maxFields, &rowOffsets, maxFields, &numD, maxFields, &numO)); 381162095d54SToby Isaac } 38120eb7e1eaSToby Isaac if (grad) { 38130eb7e1eaSToby Isaac PetscInt i; 38140eb7e1eaSToby Isaac 38159566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeom, &cellDM)); 38169566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeom, &cellGeomArray)); 38179566063dSJacob Faibussowitsch PetscCall(VecGetDM(grad, &gradDM)); 38189566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(grad, &gradArray)); 38190eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1, numFields); i++) { 38200eb7e1eaSToby Isaac PetscObject obj; 38210eb7e1eaSToby Isaac PetscClassId id; 38220eb7e1eaSToby Isaac 38239566063dSJacob Faibussowitsch PetscCall(DMGetField(coarse, i, NULL, &obj)); 38249566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 38250eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 38260eb7e1eaSToby Isaac fv = (PetscFV)obj; 38279566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numFVcomps)); 38280eb7e1eaSToby Isaac fvField = i; 38290eb7e1eaSToby Isaac break; 38300eb7e1eaSToby Isaac } 38310eb7e1eaSToby Isaac } 38320eb7e1eaSToby Isaac } 383362095d54SToby Isaac 383462095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 383562095d54SToby Isaac PetscInt dof; 383662095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 383762095d54SToby Isaac PetscInt numValues = 0; 383862095d54SToby Isaac 38399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 3840ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 384162095d54SToby Isaac offsets[0] = 0; 384262095d54SToby Isaac newOffsets[0] = 0; 384362095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 384462095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 384562095d54SToby Isaac 38469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 384762095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 384862095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 384962095d54SToby Isaac 38509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 385162095d54SToby Isaac numValues += clDof; 385262095d54SToby Isaac } 38539566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 38549371c9d4SSatish Balay } else if (maxChildId == -1) { 38559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &numValues)); 385662095d54SToby Isaac } 385762095d54SToby Isaac /* we will pack the column indices with the field offsets */ 385878b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 38590eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 38600eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 38610eb7e1eaSToby Isaac } 38629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootValuesSec, p, numValues)); 386362095d54SToby Isaac } 38649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootValuesSec)); 386562095d54SToby Isaac { 386662095d54SToby Isaac PetscInt numRootValues; 386762095d54SToby Isaac const PetscScalar *coarseArray; 386862095d54SToby Isaac 38699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootValuesSec, &numRootValues)); 38709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootValues, &rootValues)); 38719566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecCoarseLocal, &coarseArray)); 387262095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 387362095d54SToby Isaac PetscInt numValues; 387462095d54SToby Isaac PetscInt pValOff; 387562095d54SToby Isaac PetscScalar *pVal; 387662095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 387762095d54SToby Isaac 38789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootValuesSec, p, &numValues)); 3879ad540459SPierre Jolivet if (!numValues) continue; 38809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootValuesSec, p, &pValOff)); 388162095d54SToby Isaac pVal = &(rootValues[pValOff]); 388262095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 38830eb7e1eaSToby Isaac PetscInt closureSize = numValues; 38849566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(coarse, NULL, vecCoarseLocal, p, &closureSize, &pVal)); 38850eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 3886193eb951SToby Isaac PetscFVCellGeom *cg; 38876dd00756SToby Isaac PetscScalar *gradVals = NULL; 38880eb7e1eaSToby Isaac PetscInt i; 38890eb7e1eaSToby Isaac 38900eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 38910eb7e1eaSToby Isaac 38929566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(cellDM, p, cellGeomArray, (void *)&cg)); 38930eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 38940eb7e1eaSToby Isaac pVal += dim; 38959566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRead(gradDM, p, gradArray, (void *)&gradVals)); 38960eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 38970eb7e1eaSToby Isaac } 38989371c9d4SSatish Balay } else if (maxChildId == -1) { 389978b7adb5SToby Isaac PetscInt lDof, lOff, i; 390078b7adb5SToby Isaac 39019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &lDof)); 39029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, p, &lOff)); 390378b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 390478b7adb5SToby Isaac } 390578b7adb5SToby Isaac } 39069566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecCoarseLocal, &coarseArray)); 39079566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 390862095d54SToby Isaac } 390962095d54SToby Isaac { 391062095d54SToby Isaac PetscSF valuesSF; 391162095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 391262095d54SToby Isaac 39139566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafValuesSec)); 39149566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootValuesSec, &remoteOffsetsValues, leafValuesSec)); 39159566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootValuesSec, remoteOffsetsValues, leafValuesSec, &valuesSF)); 39169566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 39179566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsValues)); 39189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafValuesSec, &numLeafValues)); 39199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeafValues, &leafValues)); 39209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 39219566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 39229566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&valuesSF)); 39239566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 39249566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootValuesSec)); 392562095d54SToby Isaac } 39269566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 392762095d54SToby Isaac { 392862095d54SToby Isaac PetscInt maxDof; 392962095d54SToby Isaac PetscInt *rowIndices; 393062095d54SToby Isaac DM refTree; 393162095d54SToby Isaac PetscInt **refPointFieldN; 393262095d54SToby Isaac PetscScalar ***refPointFieldMats; 393362095d54SToby Isaac PetscSection refConSec, refAnSec; 39340eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, leafStart, leafEnd; 393562095d54SToby Isaac PetscScalar *pointWork; 393662095d54SToby Isaac 39379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 39389566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 39399566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 39409566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 39419566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(fine, refTree)); 39429566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 39439566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 39449566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 39459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 39469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafValuesSec, &leafStart, &leafEnd)); 39479566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(fine, 0, &cellStart, &cellEnd)); 39480eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 394962095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 395062095d54SToby Isaac PetscInt numValues, pValOff; 395162095d54SToby Isaac PetscInt childId; 395262095d54SToby Isaac const PetscScalar *pVal; 39530eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 395462095d54SToby Isaac 39559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 39569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &lDof)); 39579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 3958ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 39599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 39609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafValuesSec, p, &numValues)); 396162095d54SToby Isaac if (!numValues) continue; 39629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafValuesSec, p, &pValOff)); 396362095d54SToby Isaac pVal = &leafValues[pValOff]; 396462095d54SToby Isaac offsets[0] = 0; 396562095d54SToby Isaac offsetsCopy[0] = 0; 396662095d54SToby Isaac newOffsets[0] = 0; 396762095d54SToby Isaac newOffsetsCopy[0] = 0; 39684833aeb0SToby Isaac childId = cids[p - pStartF]; 396962095d54SToby Isaac if (numFields) { 397062095d54SToby Isaac PetscInt f; 397162095d54SToby Isaac for (f = 0; f < numFields; f++) { 397262095d54SToby Isaac PetscInt rowDof; 397362095d54SToby Isaac 39749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 397562095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 397662095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 397762095d54SToby Isaac /* TODO: closure indices */ 39789f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 397962095d54SToby Isaac } 39809566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 39819371c9d4SSatish Balay } else { 39824833aeb0SToby Isaac offsets[0] = 0; 39834833aeb0SToby Isaac offsets[1] = lDof; 39844833aeb0SToby Isaac newOffsets[0] = 0; 39854833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 39869566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 398762095d54SToby Isaac } 398862095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 39899566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numValues, rowIndices, pVal, INSERT_VALUES)); 399062095d54SToby Isaac } else { 399162095d54SToby Isaac PetscInt f; 399262095d54SToby Isaac 399378b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 399478b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 399578b7adb5SToby Isaac fvGradData = &pVal[numValues]; 399678b7adb5SToby Isaac } 399762095d54SToby Isaac for (f = 0; f < PetscMax(1, numFields); f++) { 399862095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 399962095d54SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 400062095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 400162095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 400262095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 400362095d54SToby Isaac PetscInt i, j; 400462095d54SToby Isaac 4005708c7f19SToby Isaac #if 0 400663a3b9bcSJacob 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)); 4007708c7f19SToby Isaac #endif 400862095d54SToby Isaac for (i = 0; i < numRows; i++) { 400962095d54SToby Isaac PetscScalar val = 0.; 4010ad540459SPierre Jolivet for (j = 0; j < numCols; j++) val += childMat[i * numCols + j] * cVal[j]; 401162095d54SToby Isaac rVal[i] = val; 401262095d54SToby Isaac } 40130eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 40140eb7e1eaSToby Isaac PetscReal centroid[3]; 40150eb7e1eaSToby Isaac PetscScalar diff[3]; 40160eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 40170eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 40180eb7e1eaSToby Isaac 40199566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(fine, p, NULL, centroid, NULL)); 4020ad540459SPierre Jolivet for (i = 0; i < dim; i++) diff[i] = centroid[i] - parentCentroid[i]; 40210eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 40220eb7e1eaSToby Isaac PetscScalar val = 0.; 40230eb7e1eaSToby Isaac 4024ad540459SPierre Jolivet for (j = 0; j < dim; j++) val += gradient[dim * i + j] * diff[j]; 40250eb7e1eaSToby Isaac rVal[i] += val; 40260eb7e1eaSToby Isaac } 40270eb7e1eaSToby Isaac } 40289566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numRows, &rowIndices[offsets[f]], rVal, INSERT_VALUES)); 402962095d54SToby Isaac } 403062095d54SToby Isaac } 403162095d54SToby Isaac } 40329566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 40339566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 40349566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 403562095d54SToby Isaac } 40369566063dSJacob Faibussowitsch PetscCall(PetscFree(leafValues)); 40379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafValuesSec)); 40389566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 40399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 40403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4041ebf164c7SToby Isaac } 4042ebf164c7SToby Isaac 4043d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4044d71ae5a4SJacob Faibussowitsch { 4045c921d74cSToby Isaac DM refTree; 4046c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4047c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4048c921d74cSToby Isaac PetscSection localCoarse, localFine; 4049c921d74cSToby Isaac PetscSection cSecRef; 4050c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4051d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4052c921d74cSToby Isaac Mat injRef; 4053c921d74cSToby Isaac PetscInt numFields, maxDof; 4054c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4055c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4056c921d74cSToby Isaac PetscLayout rowMap, colMap; 4057c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4058c921d74cSToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4059c921d74cSToby Isaac 4060ebf164c7SToby Isaac PetscFunctionBegin; 4061c921d74cSToby Isaac 4062c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 40639566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40649566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecCoarse, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40659566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 40669566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(coarse, refTree)); 40679566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 40689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 40699566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 4070c921d74cSToby Isaac 40719566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 40729566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 40739566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 40749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 40759566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 40769566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 40779566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 40789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 4079c921d74cSToby Isaac { 4080c921d74cSToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 40819566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 4082c921d74cSToby Isaac } 4083c921d74cSToby Isaac 40849566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, cids, vecFine, numFields, offsets, &multiRootSec, &rootIndicesSec, NULL, &rootValues)); 4085c921d74cSToby Isaac 40869566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxDof, &parentIndices, maxDof, &parentValues)); 4087c921d74cSToby Isaac 4088c921d74cSToby Isaac /* count indices */ 40899566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecFine, &colMap)); 40909566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecCoarse, &rowMap)); 40919566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 40929566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 40939566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 40949566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 4095c921d74cSToby Isaac /* insert values */ 40969566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 4097c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4098c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 409978b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4100c921d74cSToby Isaac 41019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 41029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 4103c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 41049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &dof)); 41059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 4106c921d74cSToby Isaac 4107c921d74cSToby Isaac rowOffsets[0] = 0; 4108c921d74cSToby Isaac offsetsCopy[0] = 0; 4109c921d74cSToby Isaac if (numFields) { 4110c921d74cSToby Isaac PetscInt f; 4111c921d74cSToby Isaac 4112c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4113c921d74cSToby Isaac PetscInt fDof; 41149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 4115c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4116c921d74cSToby Isaac } 41179566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 4118367003a6SStefano Zampini } else { 41199566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 4120c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4121c921d74cSToby Isaac } 4122c921d74cSToby Isaac 41239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 41249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 4125c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 41262f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4127c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4128c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4129c921d74cSToby Isaac const PetscScalar *childValues; 4130c921d74cSToby Isaac 41319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 41329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 4133c921d74cSToby Isaac childId = (PetscInt)PetscRealPart(rootValues[offset++]); 4134c921d74cSToby Isaac childValues = &rootValues[offset]; 4135c921d74cSToby Isaac numIndices--; 4136c921d74cSToby Isaac 4137c921d74cSToby Isaac if (childId == -2) { /* skip */ 4138c921d74cSToby Isaac continue; 4139c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 41402f65e181SToby Isaac PetscInt m; 41412f65e181SToby Isaac 414278b7adb5SToby Isaac contribute = PETSC_TRUE; 41432f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4144beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4145d3bc4906SToby Isaac PetscInt parentId, f, lim; 4146d3bc4906SToby Isaac 414778b7adb5SToby Isaac contribute = PETSC_TRUE; 41489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 4149d3bc4906SToby Isaac 4150d3bc4906SToby Isaac lim = PetscMax(1, numFields); 4151d3bc4906SToby Isaac offsets[0] = 0; 4152d3bc4906SToby Isaac if (numFields) { 4153d3bc4906SToby Isaac PetscInt f; 4154d3bc4906SToby Isaac 4155d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4156d3bc4906SToby Isaac PetscInt fDof; 41579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 4158d3bc4906SToby Isaac 4159d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4160d3bc4906SToby Isaac } 41619371c9d4SSatish Balay } else { 4162d3bc4906SToby Isaac PetscInt cDof; 4163d3bc4906SToby Isaac 41649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 4165d3bc4906SToby Isaac offsets[1] = cDof; 4166d3bc4906SToby Isaac } 4167d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4168d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4169d3bc4906SToby Isaac PetscInt n = offsets[f + 1] - offsets[f]; 4170e328ff09SToby Isaac PetscInt m = rowOffsets[f + 1] - rowOffsets[f]; 4171d3bc4906SToby Isaac PetscInt i, j; 4172d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4173d3bc4906SToby Isaac 4174e328ff09SToby Isaac for (i = 0; i < m; i++) { 4175d3bc4906SToby Isaac PetscScalar val = 0.; 4176ad540459SPierre Jolivet for (j = 0; j < n; j++) val += childMat[n * i + j] * colValues[j]; 4177e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val; 4178d3bc4906SToby Isaac } 4179d3bc4906SToby Isaac } 4180c921d74cSToby Isaac } 4181c921d74cSToby Isaac } 41829566063dSJacob Faibussowitsch if (contribute) PetscCall(VecSetValues(vecCoarse, dof, parentIndices, parentValues, INSERT_VALUES)); 4183c921d74cSToby Isaac } 41849566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 41859566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 41869566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentIndices, parentValues)); 41879566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 41889566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 41899566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 41903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4191ebf164c7SToby Isaac } 4192ebf164c7SToby Isaac 4193ff1f73f7SToby Isaac /*@ 4194ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4195ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4196ff1f73f7SToby Isaac coarsening and refinement at the same time. 4197ff1f73f7SToby Isaac 419820f4b53cSBarry Smith Collective 4199ff1f73f7SToby Isaac 4200ff1f73f7SToby Isaac Input Parameters: 4201a1cb98faSBarry Smith + dmIn - The `DMPLEX` mesh for the input vector 420220f4b53cSBarry Smith . dmOut - The second `DMPLEX` mesh 4203ff1f73f7SToby Isaac . vecIn - The input vector 420420f4b53cSBarry Smith . sfRefine - A star forest indicating points in the mesh `dmIn` (roots in the star forest) that are parents to points in 420520f4b53cSBarry Smith the mesh `dmOut` (leaves in the star forest), i.e. where `dmOut` is more refined than `dmIn` 420620f4b53cSBarry Smith . sfCoarsen - A star forest indicating points in the mesh `dmOut` (roots in the star forest) that are parents to points in 420720f4b53cSBarry Smith the mesh `dmIn` (leaves in the star forest), i.e. where `dmOut` is more coarsened than `dmIn` 420820f4b53cSBarry Smith . cidsRefine - The childIds of the points in `dmOut`. These childIds relate back to the reference tree: childid[j] = k implies 420920f4b53cSBarry Smith that mesh point j of `dmOut` was refined from a point in `dmIn` just as the mesh point k in the reference 421020f4b53cSBarry Smith tree was refined from its parent. childid[j] = -1 indicates that the point j in `dmOut` is exactly 421120f4b53cSBarry Smith equivalent to its root in `dmIn`, so no interpolation is necessary. childid[j] = -2 indicates that this 421220f4b53cSBarry Smith point j in `dmOut` is not a leaf of `sfRefine`. 421320f4b53cSBarry Smith . cidsCoarsen - The childIds of the points in `dmIn`. These childIds relate back to the reference tree: childid[j] = k implies 421420f4b53cSBarry Smith that mesh point j of dmIn coarsens to a point in `dmOut` just as the mesh point k in the reference 421520f4b53cSBarry Smith tree coarsens to its parent. childid[j] = -2 indicates that point j in `dmOut` is not a leaf in `sfCoarsen`. 421620f4b53cSBarry Smith . useBCs - `PETSC_TRUE` indicates that boundary values should be inserted into `vecIn` before transfer. 4217ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4218ff1f73f7SToby Isaac 42192fe279fdSBarry Smith Output Parameter: 42208966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred 422120f4b53cSBarry Smith projection of `vecIn` from `dmIn` to `dmOut`. Note that any field discretized with a `PetscFV` finite volume 4222ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4223ff1f73f7SToby Isaac coarse points to fine points. 4224ff1f73f7SToby Isaac 4225ff1f73f7SToby Isaac Level: developer 4226ff1f73f7SToby Isaac 4227a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSF`, `Vec`, `PetscFV`, `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()`, `PetscFVGetComputeGradients()` 4228ff1f73f7SToby Isaac @*/ 4229d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) 4230d71ae5a4SJacob Faibussowitsch { 423138fc2455SToby Isaac PetscFunctionBegin; 42329566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0)); 4233ff1f73f7SToby Isaac if (sfRefine) { 4234fbfa57b9SToby Isaac Vec vecInLocal; 42350eb7e1eaSToby Isaac DM dmGrad = NULL; 42360eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4237fbfa57b9SToby Isaac 42389566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecInLocal)); 42399566063dSJacob Faibussowitsch PetscCall(VecSet(vecInLocal, 0.0)); 42400eb7e1eaSToby Isaac { 42410eb7e1eaSToby Isaac PetscInt numFields, i; 42420eb7e1eaSToby Isaac 42439566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dmIn, &numFields)); 42440eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 42450eb7e1eaSToby Isaac PetscObject obj; 42460eb7e1eaSToby Isaac PetscClassId classid; 42470eb7e1eaSToby Isaac 42489566063dSJacob Faibussowitsch PetscCall(DMGetField(dmIn, i, NULL, &obj)); 42499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &classid)); 42500eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 42519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dmIn, (PetscFV)obj, &cellGeom, &faceGeom, &dmGrad)); 42520eb7e1eaSToby Isaac break; 42530eb7e1eaSToby Isaac } 42540eb7e1eaSToby Isaac } 42550eb7e1eaSToby Isaac } 42561baa6e33SBarry Smith if (useBCs) PetscCall(DMPlexInsertBoundaryValues(dmIn, PETSC_TRUE, vecInLocal, time, faceGeom, cellGeom, NULL)); 42579566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42589566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42590eb7e1eaSToby Isaac if (dmGrad) { 42609566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmGrad, &grad)); 42619566063dSJacob Faibussowitsch PetscCall(DMPlexReconstructGradientsFVM(dmIn, vecInLocal, grad)); 42620eb7e1eaSToby Isaac } 42639566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree_Interpolate(dmIn, vecInLocal, dmOut, vecOut, sfRefine, cidsRefine, grad, cellGeom)); 42649566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecInLocal)); 426548a46eb9SPierre Jolivet if (dmGrad) PetscCall(DMRestoreGlobalVector(dmGrad, &grad)); 4266ebf164c7SToby Isaac } 42671baa6e33SBarry Smith if (sfCoarsen) PetscCall(DMPlexTransferVecTree_Inject(dmIn, vecIn, dmOut, vecOut, sfCoarsen, cidsCoarsen)); 42689566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(vecOut)); 42699566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(vecOut)); 42703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 427138fc2455SToby Isaac } 4272