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 201cc06b55SBarry Smith .seealso: [](ch_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 48d3a532e9SStefano Zampini Developer Notes: 49d3a532e9SStefano Zampini The reference tree is shallow copied during `DMClone()`, thus it is may be shared by different `DM`s. 50d3a532e9SStefano Zampini It is not a topological-only object, since some parts of the library use its local section to compute 51d3a532e9SStefano Zampini interpolation and injection matrices. This may lead to unexpected failures during those calls. 52d3a532e9SStefano Zampini 531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()` 54d6a7ad0dSToby Isaac @*/ 55d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 56d71ae5a4SJacob Faibussowitsch { 57d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 58d6a7ad0dSToby Isaac 59d6a7ad0dSToby Isaac PetscFunctionBegin; 60d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 614f572ea9SToby Isaac PetscAssertPointer(ref, 2); 62d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64d6a7ad0dSToby Isaac } 65d6a7ad0dSToby Isaac 66d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 67d71ae5a4SJacob Faibussowitsch { 68dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 69dcbd3bf7SToby Isaac 70dcbd3bf7SToby Isaac PetscFunctionBegin; 71dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 72dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 73dcbd3bf7SToby Isaac if (childB) *childB = childA; 743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75dcbd3bf7SToby Isaac } 76dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, &dStart, &dEnd)); 78ad540459SPierre Jolivet if (parent >= dStart && parent <= dEnd) break; 79dcbd3bf7SToby Isaac } 8063a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot perform child symmetry for %" PetscInt_FMT "-cells", dim); 8128b400f6SJacob Faibussowitsch PetscCheck(dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "A vertex has no children"); 82dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 83dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 84dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 85dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 86dcbd3bf7SToby Isaac 879566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, childA, &size)); 889566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, childA, &supp)); 89dcbd3bf7SToby Isaac 90dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 91dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 92dcbd3bf7SToby Isaac PetscInt sParent; 93dcbd3bf7SToby Isaac 94dcbd3bf7SToby Isaac sA = supp[i]; 95dcbd3bf7SToby Isaac if (sA == parent) continue; 969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, sA, &sParent, NULL)); 97ad540459SPierre Jolivet if (sParent == parent) break; 98dcbd3bf7SToby Isaac } 9908401ef6SPierre Jolivet PetscCheck(i != size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "could not find support in children"); 100dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 101dcbd3bf7SToby Isaac * parentOrientB */ 1029566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry_Default(dm, parent, parentOrientA, 0, sA, parentOrientB, &sOrientB, &sB)); 1039566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, sA, &sConeSize)); 1049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sA, &coneA)); 1059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sB, &coneB)); 1069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sA, &oA)); 1079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sB, &oB)); 108dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 109dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 110dcbd3bf7SToby Isaac if (coneA[i] == childA) { 111dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 112dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 113dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize - (sOrientB + 1) - i) % sConeSize); 114dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 115dcbd3bf7SToby Isaac if (childOrientB) { 116b5a892a1SMatthew G. Knepley DMPolytopeType ct; 117dcbd3bf7SToby Isaac PetscInt oBtrue; 118dcbd3bf7SToby Isaac 1199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, childA, &coneSize)); 120dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 1211dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected a vertex or an edge"); 122b5a892a1SMatthew G. Knepley ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 123dcbd3bf7SToby Isaac /* we may have to flip an edge */ 124b5a892a1SMatthew G. Knepley oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientation(ct, -1, oB[j]); 125b5a892a1SMatthew G. Knepley oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 126b5a892a1SMatthew G. Knepley ABswap = DihedralSwap(coneSize, DMPolytopeConvertNewOrientation_Internal(ct, oA[i]), oBtrue); 127dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 128dcbd3bf7SToby Isaac } 129dcbd3bf7SToby Isaac break; 130dcbd3bf7SToby Isaac } 131dcbd3bf7SToby Isaac } 13208401ef6SPierre Jolivet PetscCheck(i != sConeSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "support cone mismatch"); 1333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 134dcbd3bf7SToby Isaac } 135dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 1369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 137dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 138dcbd3bf7SToby Isaac if (dim == 2) { 139dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 140dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 141dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 142dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 143dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 144dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 145947b95d8SBarry Smith } else { 146dcbd3bf7SToby Isaac ABswapVert = ABswap; 147dcbd3bf7SToby Isaac } 148dcbd3bf7SToby Isaac if (childB) { 149dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 150dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 151dcbd3bf7SToby Isaac const PetscInt *children; 152dcbd3bf7SToby Isaac 153dcbd3bf7SToby Isaac /* count which position the child is in */ 1549566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, parent, &numChildren, &children)); 155dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 156dcbd3bf7SToby Isaac p = children[i]; 157dcbd3bf7SToby Isaac if (p == childA) { 158dcbd3bf7SToby Isaac posA = i; 159dcbd3bf7SToby Isaac break; 160dcbd3bf7SToby Isaac } 161dcbd3bf7SToby Isaac } 162dcbd3bf7SToby Isaac if (posA >= coneSize) { 163dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 164dcbd3bf7SToby Isaac * is invariant */ 1651dca8a05SBarry Smith PetscCheck(dim == 2 && posA == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Expected a middle triangle, got something else"); 166dcbd3bf7SToby Isaac *childB = childA; 1679371c9d4SSatish Balay } else { 168dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 169dcbd3bf7SToby Isaac PetscInt posB; 170dcbd3bf7SToby Isaac 171dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize - (ABswapVert + 1) - posA) % coneSize); 172dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 173dcbd3bf7SToby Isaac } 174dcbd3bf7SToby Isaac } 175dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 1763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 177dcbd3bf7SToby Isaac } 178dcbd3bf7SToby Isaac 179dcbd3bf7SToby Isaac /*@ 180dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 181dcbd3bf7SToby Isaac 182dcbd3bf7SToby Isaac Input Parameters: 183a1cb98faSBarry Smith + dm - the reference tree `DMPLEX` object 184dcbd3bf7SToby Isaac . parent - the parent point 185dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 186dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 187dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 188dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 189dcbd3bf7SToby Isaac 190dcbd3bf7SToby Isaac Output Parameters: 19120f4b53cSBarry Smith + childOrientB - if not `NULL`, set to the new orientation for describing the child 19220f4b53cSBarry Smith - childB - if not `NULL`, the new childID for describing the child 193dcbd3bf7SToby Isaac 194dcbd3bf7SToby Isaac Level: developer 195dcbd3bf7SToby Isaac 1961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetReferenceTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetTree()` 197dcbd3bf7SToby Isaac @*/ 198d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 199d71ae5a4SJacob Faibussowitsch { 200dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 201dcbd3bf7SToby Isaac 202dcbd3bf7SToby Isaac PetscFunctionBegin; 203dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20428b400f6SJacob Faibussowitsch PetscCheck(mesh->getchildsymmetry, PETSC_COMM_SELF, PETSC_ERR_SUP, "DMPlexReferenceTreeGetChildSymmetry not implemented"); 2059566063dSJacob Faibussowitsch PetscCall(mesh->getchildsymmetry(dm, parent, parentOrientA, childOrientA, childA, parentOrientB, childOrientB, childB)); 2063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207dcbd3bf7SToby Isaac } 208dcbd3bf7SToby Isaac 209776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM, PetscSection, PetscInt *, PetscInt *, PetscBool, PetscBool); 210f9f063d4SToby Isaac 211d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceTree_SetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 212d71ae5a4SJacob Faibussowitsch { 213f2c1aa1dSLisandro Dalcin PetscFunctionBegin; 2149566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm, parentSection, parents, childIDs, PETSC_TRUE, PETSC_FALSE)); 2153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 216f2c1aa1dSLisandro Dalcin } 217f2c1aa1dSLisandro Dalcin 218d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 219d71ae5a4SJacob Faibussowitsch { 2200e2cc29aSToby Isaac MPI_Comm comm; 2210e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 222da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 223da43764aSToby Isaac DMLabel identity, identityRef; 22410f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 225da43764aSToby Isaac PetscScalar *unionCoords; 226da43764aSToby Isaac IS perm; 227da43764aSToby Isaac 228da43764aSToby Isaac PetscFunctionBegin; 2290e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(K, &dim)); 2319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd)); 2329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, labelName, &identity)); 2339566063dSJacob Faibussowitsch PetscCall(DMGetLabel(Kref, labelName, &identityRef)); 2349566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(Kref, &pRefStart, &pRefEnd)); 2359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionSection)); 2369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart))); 237da43764aSToby Isaac /* count points that will go in the union */ 23848a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(PetscSectionSetDof(unionSection, p - pStart, 1)); 239da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 240da43764aSToby Isaac PetscInt q, qSize; 2419566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &q)); 2429566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(identityRef, q, &qSize)); 24348a46eb9SPierre Jolivet if (qSize > 1) PetscCall(PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1)); 244da43764aSToby Isaac } 2459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart, &permvals)); 246da43764aSToby Isaac offset = 0; 247da43764aSToby Isaac /* stratify points in the union by topological dimension */ 248da43764aSToby Isaac for (d = 0; d <= dim; d++) { 249da43764aSToby Isaac PetscInt cStart, cEnd, c; 250da43764aSToby Isaac 2519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, &cEnd)); 252ad540459SPierre Jolivet for (c = cStart; c < cEnd; c++) permvals[offset++] = c; 253da43764aSToby Isaac 2549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd)); 255ad540459SPierre Jolivet for (c = cStart; c < cEnd; c++) permvals[offset++] = c + (pEnd - pStart); 256da43764aSToby Isaac } 2579566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm)); 2589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(unionSection, perm)); 2599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionSection)); 2609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionSection, &numUnionPoints)); 2619566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numUnionPoints, &coneSizes, dim + 1, &numDimPoints)); 262da43764aSToby Isaac /* count dimension points */ 263da43764aSToby Isaac for (d = 0; d <= dim; d++) { 264da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 2659566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, NULL)); 2669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, cStart - pStart, &cOff)); 267da43764aSToby Isaac if (d < dim) { 2689566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d + 1, &cStart, NULL)); 2699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, cStart - pStart, &cOff2)); 2709371c9d4SSatish Balay } else { 271da43764aSToby Isaac cOff2 = numUnionPoints; 272da43764aSToby Isaac } 273da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 274da43764aSToby Isaac } 2759566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionConeSection)); 2769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionConeSection, 0, numUnionPoints)); 277da43764aSToby Isaac /* count the cones in the union */ 278da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 279da43764aSToby Isaac PetscInt dof, uOff; 280da43764aSToby Isaac 2819566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof)); 2829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart, &uOff)); 2839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof)); 284da43764aSToby Isaac coneSizes[uOff] = dof; 285da43764aSToby Isaac } 286da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 287da43764aSToby Isaac PetscInt dof, uDof, uOff; 288da43764aSToby Isaac 2899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof)); 2909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 2919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 292da43764aSToby Isaac if (uDof) { 2939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof)); 294da43764aSToby Isaac coneSizes[uOff] = dof; 295da43764aSToby Isaac } 296da43764aSToby Isaac } 2979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionConeSection)); 2989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionConeSection, &numCones)); 2999566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numCones, &unionCones, numCones, &unionOrientations)); 300da43764aSToby Isaac /* write the cones in the union */ 301da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 302da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 303da43764aSToby Isaac const PetscInt *cone, *orientation; 304da43764aSToby Isaac 3059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof)); 3069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, p, &cone)); 3079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, p, &orientation)); 3089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart, &uOff)); 3099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection, uOff, &cOff)); 310da43764aSToby Isaac for (c = 0; c < dof; c++) { 311da43764aSToby Isaac PetscInt e, eOff; 312da43764aSToby Isaac e = cone[c]; 3139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 314da43764aSToby Isaac unionCones[cOff + c] = eOff; 315da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 316da43764aSToby Isaac } 317da43764aSToby Isaac } 318da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 319da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 320da43764aSToby Isaac const PetscInt *cone, *orientation; 321da43764aSToby Isaac 3229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof)); 3239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(Kref, p, &cone)); 3249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(Kref, p, &orientation)); 3259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 3269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 327da43764aSToby Isaac if (uDof) { 3289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection, uOff, &cOff)); 329da43764aSToby Isaac for (c = 0; c < dof; c++) { 330da43764aSToby Isaac PetscInt e, eOff, eDof; 331da43764aSToby Isaac 332da43764aSToby Isaac e = cone[c]; 3339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart), &eDof)); 334da43764aSToby Isaac if (eDof) { 3359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff)); 3369371c9d4SSatish Balay } else { 3379566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, e, &e)); 3389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 339da43764aSToby Isaac } 340da43764aSToby Isaac unionCones[cOff + c] = eOff; 341da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 342da43764aSToby Isaac } 343da43764aSToby Isaac } 344da43764aSToby Isaac } 345da43764aSToby Isaac /* get the coordinates */ 346da43764aSToby Isaac { 347da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 348da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 349da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 350da43764aSToby Isaac PetscScalar *Kcoords; 351da43764aSToby Isaac 3529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &KcoordsSec)); 3539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &KcoordsVec)); 3549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(Kref, &KrefCoordsSec)); 3559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(Kref, &KrefCoordsVec)); 356da43764aSToby Isaac 357da43764aSToby Isaac numVerts = numDimPoints[0]; 3589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVerts * dim, &unionCoords)); 3599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &vStart, &vEnd)); 360da43764aSToby Isaac 361da43764aSToby Isaac offset = 0; 362da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 3639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, v - pStart, &vOff)); 3649566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords)); 365ad540459SPierre Jolivet for (d = 0; d < dim; d++) unionCoords[offset * dim + d] = Kcoords[d]; 366da43764aSToby Isaac offset++; 367da43764aSToby Isaac } 3689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(Kref, 0, &vRefStart, &vRefEnd)); 369da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 3709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, v - pRefStart + (pEnd - pStart), &vDof)); 3719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, v - pRefStart + (pEnd - pStart), &vOff)); 3729566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords)); 373da43764aSToby Isaac if (vDof) { 374ad540459SPierre Jolivet for (d = 0; d < dim; d++) unionCoords[offset * dim + d] = Kcoords[d]; 375da43764aSToby Isaac offset++; 376da43764aSToby Isaac } 377da43764aSToby Isaac } 378da43764aSToby Isaac } 3799566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, ref)); 3809566063dSJacob Faibussowitsch PetscCall(DMSetType(*ref, DMPLEX)); 3819566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ref, dim)); 3829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ref, dim, numDimPoints, coneSizes, unionCones, unionOrientations, unionCoords)); 38310f7e118SToby Isaac /* set the tree */ 3849566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &parentSection)); 3859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, numUnionPoints)); 38610f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 38710f7e118SToby Isaac PetscInt uDof, uOff; 38810f7e118SToby Isaac 3899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 3909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 3911baa6e33SBarry Smith if (uDof) PetscCall(PetscSectionSetDof(parentSection, uOff, 1)); 39210f7e118SToby Isaac } 3939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 3949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &parentSize)); 3959566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(parentSize, &parents, parentSize, &childIDs)); 39610f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 39710f7e118SToby Isaac PetscInt uDof, uOff; 39810f7e118SToby Isaac 3999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 4009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 40110f7e118SToby Isaac if (uDof) { 40210f7e118SToby Isaac PetscInt pOff, parent, parentU; 4039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, uOff, &pOff)); 4049566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &parent)); 4059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, parent - pStart, &parentU)); 40610f7e118SToby Isaac parents[pOff] = parentU; 40710f7e118SToby Isaac childIDs[pOff] = uOff; 40810f7e118SToby Isaac } 40910f7e118SToby Isaac } 4109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_SetTree(*ref, parentSection, parents, childIDs)); 4119566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 4129566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs)); 41310f7e118SToby Isaac 414da43764aSToby Isaac /* clean up */ 4159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionSection)); 4169566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionConeSection)); 4179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 4189566063dSJacob Faibussowitsch PetscCall(PetscFree(unionCoords)); 4199566063dSJacob Faibussowitsch PetscCall(PetscFree2(unionCones, unionOrientations)); 4209566063dSJacob Faibussowitsch PetscCall(PetscFree2(coneSizes, numDimPoints)); 4213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4220e2cc29aSToby Isaac } 4230e2cc29aSToby Isaac 4240e2cc29aSToby Isaac /*@ 4250e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4260e2cc29aSToby Isaac 427d083f849SBarry Smith Collective 4280e2cc29aSToby Isaac 4290e2cc29aSToby Isaac Input Parameters: 4300e2cc29aSToby Isaac + comm - the MPI communicator 4310e2cc29aSToby Isaac . dim - the spatial dimension 4320e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4330e2cc29aSToby Isaac 4342fe279fdSBarry Smith Output Parameter: 435a1cb98faSBarry Smith . ref - the reference tree `DMPLEX` object 4360e2cc29aSToby Isaac 4370e2cc29aSToby Isaac Level: intermediate 4380e2cc29aSToby Isaac 439db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()` 4400e2cc29aSToby Isaac @*/ 441d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 442d71ae5a4SJacob Faibussowitsch { 4430e2cc29aSToby Isaac DM_Plex *mesh; 4440e2cc29aSToby Isaac DM K, Kref; 4450e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4460e2cc29aSToby Isaac DMLabel identity; 4470e2cc29aSToby Isaac 4480e2cc29aSToby Isaac PetscFunctionBegin; 4490e2cc29aSToby Isaac #if 1 4500e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4510e2cc29aSToby Isaac #endif 4520e2cc29aSToby Isaac /* create a reference element */ 4539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(comm, DMPolytopeTypeSimpleShape(dim, simplex), &K)); 4549566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(K, "identity")); 4559566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, "identity", &identity)); 4569566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd)); 45748a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMLabelSetValue(identity, p, p)); 4580e2cc29aSToby Isaac /* refine it */ 4599566063dSJacob Faibussowitsch PetscCall(DMRefine(K, comm, &Kref)); 4600e2cc29aSToby Isaac 4610e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4620e2cc29aSToby Isaac * points that appear in both */ 4639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref)); 4640e2cc29aSToby Isaac mesh = (DM_Plex *)(*ref)->data; 4650e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 4669566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 4679566063dSJacob Faibussowitsch PetscCall(DMDestroy(&Kref)); 4683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 469da43764aSToby Isaac } 470da43764aSToby Isaac 471d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 472d71ae5a4SJacob Faibussowitsch { 473878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 474878b19aaSToby Isaac PetscSection childSec, pSec; 475878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 476878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 477878b19aaSToby Isaac 478878b19aaSToby Isaac PetscFunctionBegin; 479878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4809566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 4819566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 482878b19aaSToby Isaac pSec = mesh->parentSection; 4833ba16761SJacob Faibussowitsch if (!pSec) PetscFunctionReturn(PETSC_SUCCESS); 4849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(pSec, &pSize)); 485878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 486878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 487878b19aaSToby Isaac 488878b19aaSToby Isaac parMax = PetscMax(parMax, par + 1); 489878b19aaSToby Isaac parMin = PetscMin(parMin, par); 490878b19aaSToby Isaac } 491878b19aaSToby Isaac if (parMin > parMax) { 492878b19aaSToby Isaac parMin = -1; 493878b19aaSToby Isaac parMax = -1; 494878b19aaSToby Isaac } 4959566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)pSec), &childSec)); 4969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(childSec, parMin, parMax)); 497878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 498878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 499878b19aaSToby Isaac 5009566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(childSec, par, 1)); 501878b19aaSToby Isaac } 5029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(childSec)); 5039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(childSec, &cSize)); 5049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cSize, &children)); 5059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(parMax - parMin, &offsets)); 5069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pSec, &pStart, &pEnd)); 507878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 508878b19aaSToby Isaac PetscInt dof, off, i; 509878b19aaSToby Isaac 5109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, p, &dof)); 5119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, p, &off)); 512878b19aaSToby Isaac for (i = 0; i < dof; i++) { 513878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 514878b19aaSToby Isaac 5159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, par, &cOff)); 516878b19aaSToby Isaac children[cOff + offsets[par - parMin]++] = p; 517878b19aaSToby Isaac } 518878b19aaSToby Isaac } 519878b19aaSToby Isaac mesh->childSection = childSec; 520878b19aaSToby Isaac mesh->children = children; 5219566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 5223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 523878b19aaSToby Isaac } 524878b19aaSToby Isaac 525d71ae5a4SJacob Faibussowitsch static PetscErrorCode AnchorsFlatten(PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 526d71ae5a4SJacob Faibussowitsch { 5276dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5286dd5a8c8SToby Isaac const PetscInt *vals; 5296dd5a8c8SToby Isaac PetscSection secNew; 5306dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5316dd5a8c8SToby Isaac PetscBool compress; 5326dd5a8c8SToby Isaac 5336dd5a8c8SToby Isaac PetscFunctionBegin; 5349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 5359566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &size)); 5369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &vals)); 5379566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &secNew)); 5389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secNew, pStart, pEnd)); 5396dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5406dd5a8c8SToby Isaac PetscInt dof; 5416dd5a8c8SToby Isaac 5426dd5a8c8SToby Isaac p = vals[i]; 5436dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5456dd5a8c8SToby Isaac if (dof) break; 5466dd5a8c8SToby Isaac } 5476dd5a8c8SToby Isaac if (i == size) { 5489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew)); 5496dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5506dd5a8c8SToby Isaac compress = PETSC_FALSE; 5516dd5a8c8SToby Isaac sizeNew = 0; 5529371c9d4SSatish Balay } else { 5536dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5546dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5556dd5a8c8SToby Isaac PetscInt dof, off; 5566dd5a8c8SToby Isaac 5579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5596dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5606dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5616dd5a8c8SToby Isaac 56248a46eb9SPierre Jolivet if (q >= pStart && q < pEnd) PetscCall(PetscSectionGetDof(section, q, &qDof)); 5631baa6e33SBarry Smith if (qDof) PetscCall(PetscSectionAddDof(secNew, p, qDof)); 56448a46eb9SPierre Jolivet else PetscCall(PetscSectionAddDof(secNew, p, 1)); 5656dd5a8c8SToby Isaac } 5666dd5a8c8SToby Isaac } 5679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew)); 5689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secNew, &sizeNew)); 5699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew, &valsNew)); 5706dd5a8c8SToby Isaac compress = PETSC_FALSE; 5716dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5726dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 5736dd5a8c8SToby Isaac 5749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dofNew)); 5779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &offNew)); 5786dd5a8c8SToby Isaac count = 0; 5796dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5806dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 5816dd5a8c8SToby Isaac 5826dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &qDof)); 5849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &qOff)); 5856dd5a8c8SToby Isaac } 5866dd5a8c8SToby Isaac if (qDof) { 5876dd5a8c8SToby Isaac PetscInt oldCount = count; 5886dd5a8c8SToby Isaac 5896dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 5906dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 5916dd5a8c8SToby Isaac 5926dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 593ad540459SPierre Jolivet if (valsNew[offNew + k] == r) break; 5946dd5a8c8SToby Isaac } 595ad540459SPierre Jolivet if (k == oldCount) valsNew[offNew + count++] = r; 5966dd5a8c8SToby Isaac } 5979371c9d4SSatish Balay } else { 5986dd5a8c8SToby Isaac PetscInt k, oldCount = count; 5996dd5a8c8SToby Isaac 6006dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 601ad540459SPierre Jolivet if (valsNew[offNew + k] == q) break; 6026dd5a8c8SToby Isaac } 603ad540459SPierre Jolivet if (k == oldCount) valsNew[offNew + count++] = q; 6046dd5a8c8SToby Isaac } 6056dd5a8c8SToby Isaac } 6066dd5a8c8SToby Isaac if (count < dofNew) { 6079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secNew, p, count)); 6086dd5a8c8SToby Isaac compress = PETSC_TRUE; 6096dd5a8c8SToby Isaac } 6106dd5a8c8SToby Isaac } 6116dd5a8c8SToby Isaac } 6129566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &vals)); 6131c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&anyNew, &globalAnyNew, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)secNew))); 6146dd5a8c8SToby Isaac if (!globalAnyNew) { 6159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew)); 6166dd5a8c8SToby Isaac *sectionNew = NULL; 6176dd5a8c8SToby Isaac *isNew = NULL; 6189371c9d4SSatish Balay } else { 6196dd5a8c8SToby Isaac PetscBool globalCompress; 6206dd5a8c8SToby Isaac 6211c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&compress, &globalCompress, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)secNew))); 6226dd5a8c8SToby Isaac if (compress) { 6236dd5a8c8SToby Isaac PetscSection secComp; 6246dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6256dd5a8c8SToby Isaac 6269566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &secComp)); 6279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secComp, pStart, pEnd)); 6286dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6296dd5a8c8SToby Isaac PetscInt dof; 6306dd5a8c8SToby Isaac 6319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof)); 6329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secComp, p, dof)); 6336dd5a8c8SToby Isaac } 6349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secComp)); 6359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secComp, &sizeNew)); 6369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew, &valsComp)); 6376dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6386dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6396dd5a8c8SToby Isaac 6409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof)); 6419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &off)); 6429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secComp, p, &offNew)); 643ad540459SPierre Jolivet for (j = 0; j < dof; j++) valsComp[offNew + j] = valsNew[off + j]; 6446dd5a8c8SToby Isaac } 6459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew)); 6466dd5a8c8SToby Isaac secNew = secComp; 6479566063dSJacob Faibussowitsch PetscCall(PetscFree(valsNew)); 6486dd5a8c8SToby Isaac valsNew = valsComp; 6496dd5a8c8SToby Isaac } 6509566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), sizeNew, valsNew, PETSC_OWN_POINTER, isNew)); 6516dd5a8c8SToby Isaac } 6523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6536dd5a8c8SToby Isaac } 6546dd5a8c8SToby Isaac 655d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 656d71ae5a4SJacob Faibussowitsch { 65766af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 65866af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 65966af876cSToby Isaac PetscSection aSec; 660f9f063d4SToby Isaac DMLabel canonLabel; 66166af876cSToby Isaac IS aIS; 66266af876cSToby Isaac 66366af876cSToby Isaac PetscFunctionBegin; 66466af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6659566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 6669566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "canonical", &canonLabel)); 66766af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 66866af876cSToby Isaac PetscInt parent; 66966af876cSToby Isaac 670f9f063d4SToby Isaac if (canonLabel) { 671f9f063d4SToby Isaac PetscInt canon; 672f9f063d4SToby Isaac 6739566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 674f9f063d4SToby Isaac if (p != canon) continue; 675f9f063d4SToby Isaac } 6769566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 67766af876cSToby Isaac if (parent != p) { 67866af876cSToby Isaac aMin = PetscMin(aMin, p); 67966af876cSToby Isaac aMax = PetscMax(aMax, p + 1); 68066af876cSToby Isaac } 68166af876cSToby Isaac } 68266af876cSToby Isaac if (aMin > aMax) { 68366af876cSToby Isaac aMin = -1; 68466af876cSToby Isaac aMax = -1; 68566af876cSToby Isaac } 6869566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &aSec)); 6879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(aSec, aMin, aMax)); 68866af876cSToby Isaac for (p = aMin; p < aMax; p++) { 68966af876cSToby Isaac PetscInt parent, ancestor = p; 69066af876cSToby Isaac 691f9f063d4SToby Isaac if (canonLabel) { 692f9f063d4SToby Isaac PetscInt canon; 693f9f063d4SToby Isaac 6949566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 695f9f063d4SToby Isaac if (p != canon) continue; 696f9f063d4SToby Isaac } 6979566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 69866af876cSToby Isaac while (parent != ancestor) { 69966af876cSToby Isaac ancestor = parent; 7009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, ancestor, &parent, NULL)); 70166af876cSToby Isaac } 70266af876cSToby Isaac if (ancestor != p) { 70366af876cSToby Isaac PetscInt closureSize, *closure = NULL; 70466af876cSToby Isaac 7059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 7069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(aSec, p, closureSize)); 7079566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 70866af876cSToby Isaac } 70966af876cSToby Isaac } 7109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(aSec)); 7119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(aSec, &size)); 7129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &anchors)); 71366af876cSToby Isaac for (p = aMin; p < aMax; p++) { 71466af876cSToby Isaac PetscInt parent, ancestor = p; 71566af876cSToby Isaac 716f9f063d4SToby Isaac if (canonLabel) { 717f9f063d4SToby Isaac PetscInt canon; 718f9f063d4SToby Isaac 7199566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 720f9f063d4SToby Isaac if (p != canon) continue; 721f9f063d4SToby Isaac } 7229566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 72366af876cSToby Isaac while (parent != ancestor) { 72466af876cSToby Isaac ancestor = parent; 7259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, ancestor, &parent, NULL)); 72666af876cSToby Isaac } 72766af876cSToby Isaac if (ancestor != p) { 72866af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 72966af876cSToby Isaac 7309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 73166af876cSToby Isaac 7329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 733ad540459SPierre Jolivet for (j = 0; j < closureSize; j++) anchors[aOff + j] = closure[2 * j]; 7349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 73566af876cSToby Isaac } 73666af876cSToby Isaac } 7379566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, anchors, PETSC_OWN_POINTER, &aIS)); 7386dd5a8c8SToby Isaac { 7396dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7406dd5a8c8SToby Isaac IS aISNew = aIS; 7416dd5a8c8SToby Isaac 7429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aSec)); 7439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aIS)); 7446dd5a8c8SToby Isaac while (aSecNew) { 7459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec)); 7469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS)); 7476dd5a8c8SToby Isaac aSec = aSecNew; 7486dd5a8c8SToby Isaac aIS = aISNew; 7496dd5a8c8SToby Isaac aSecNew = NULL; 7506dd5a8c8SToby Isaac aISNew = NULL; 7519566063dSJacob Faibussowitsch PetscCall(AnchorsFlatten(aSec, aIS, &aSecNew, &aISNew)); 7526dd5a8c8SToby Isaac } 7536dd5a8c8SToby Isaac } 7549566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm, aSec, aIS)); 7559566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec)); 7569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS)); 7573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75866af876cSToby Isaac } 75966af876cSToby Isaac 760d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTrueSupportSize(DM dm, PetscInt p, PetscInt *dof, PetscInt *numTrueSupp) 761d71ae5a4SJacob Faibussowitsch { 7626461c1adSToby Isaac PetscFunctionBegin; 7636461c1adSToby Isaac if (numTrueSupp[p] == -1) { 7646461c1adSToby Isaac PetscInt i, alldof; 7656461c1adSToby Isaac const PetscInt *supp; 7666461c1adSToby Isaac PetscInt count = 0; 7676461c1adSToby Isaac 7689566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &alldof)); 7699566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &supp)); 7706461c1adSToby Isaac for (i = 0; i < alldof; i++) { 7716461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 7726461c1adSToby Isaac const PetscInt *cone; 7736461c1adSToby Isaac 7749566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &numCones)); 7759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &cone)); 7766461c1adSToby Isaac for (j = 0; j < numCones; j++) { 7776461c1adSToby Isaac if (cone[j] == p) break; 7786461c1adSToby Isaac } 7796461c1adSToby Isaac if (j < numCones) count++; 7806461c1adSToby Isaac } 7816461c1adSToby Isaac numTrueSupp[p] = count; 7826461c1adSToby Isaac } 7836461c1adSToby Isaac *dof = numTrueSupp[p]; 7843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7856461c1adSToby Isaac } 7866461c1adSToby Isaac 787d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 788d71ae5a4SJacob Faibussowitsch { 789776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 790776742edSToby Isaac PetscSection newSupportSection; 791776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 7926461c1adSToby Isaac PetscInt *numTrueSupp; 793776742edSToby Isaac PetscInt *offsets; 794776742edSToby Isaac 795776742edSToby Isaac PetscFunctionBegin; 796776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 797776742edSToby Isaac /* symmetrize the hierarchy */ 7989566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 799*f4f49eeaSPierre Jolivet PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)mesh->supportSection), &newSupportSection)); 8009566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSupportSection, pStart, pEnd)); 8029566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd, &offsets)); 8039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd, &numTrueSupp)); 8046461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 8056461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 806776742edSToby Isaac * parent(q) */ 807776742edSToby Isaac for (d = 0; d <= depth; d++) { 8089566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pStart, &pEnd)); 809776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 810776742edSToby Isaac PetscInt dof, q, qdof, parent; 811776742edSToby Isaac 8129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm, p, &dof, numTrueSupp)); 8139566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, dof)); 814776742edSToby Isaac q = p; 8159566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 816776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 817776742edSToby Isaac q = parent; 818776742edSToby Isaac 8199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm, q, &qdof, numTrueSupp)); 8209566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, qdof)); 8219566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, q, dof)); 8229566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 823776742edSToby Isaac } 824776742edSToby Isaac } 825776742edSToby Isaac } 8269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSupportSection)); 8279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSupportSection, &newSize)); 8289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newSize, &newSupports)); 829776742edSToby Isaac for (d = 0; d <= depth; d++) { 8309566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pStart, &pEnd)); 831776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 832776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 833776742edSToby Isaac 8349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 8369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(newSupportSection, p, &newDof)); 8379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, p, &newOff)); 838776742edSToby Isaac for (i = 0; i < dof; i++) { 8396461c1adSToby Isaac PetscInt numCones, j; 8406461c1adSToby Isaac const PetscInt *cone; 8416461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 8426461c1adSToby Isaac 8439566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &numCones)); 8449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &cone)); 8456461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8466461c1adSToby Isaac if (cone[j] == p) break; 8476461c1adSToby Isaac } 8486461c1adSToby Isaac if (j < numCones) newSupports[newOff + offsets[p]++] = q; 849776742edSToby Isaac } 850776742edSToby Isaac 851776742edSToby Isaac q = p; 8529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 853776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 854776742edSToby Isaac q = parent; 8559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, q, &qdof)); 8569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &qoff)); 8579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, q, &newqOff)); 858776742edSToby Isaac for (i = 0; i < qdof; i++) { 8596461c1adSToby Isaac PetscInt numCones, j; 8606461c1adSToby Isaac const PetscInt *cone; 8616461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 8626461c1adSToby Isaac 8639566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, r, &numCones)); 8649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, r, &cone)); 8656461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8666461c1adSToby Isaac if (cone[j] == q) break; 8676461c1adSToby Isaac } 8686461c1adSToby Isaac if (j < numCones) newSupports[newOff + offsets[p]++] = r; 869776742edSToby Isaac } 870776742edSToby Isaac for (i = 0; i < dof; i++) { 8716461c1adSToby Isaac PetscInt numCones, j; 8726461c1adSToby Isaac const PetscInt *cone; 8736461c1adSToby Isaac PetscInt r = mesh->supports[off + i]; 8746461c1adSToby Isaac 8759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, r, &numCones)); 8769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, r, &cone)); 8776461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8786461c1adSToby Isaac if (cone[j] == p) break; 8796461c1adSToby Isaac } 8806461c1adSToby Isaac if (j < numCones) newSupports[newqOff + offsets[q]++] = r; 881776742edSToby Isaac } 8829566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 883776742edSToby Isaac } 884776742edSToby Isaac } 885776742edSToby Isaac } 8869566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 887776742edSToby Isaac mesh->supportSection = newSupportSection; 8889566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 889776742edSToby Isaac mesh->supports = newSupports; 8909566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 8919566063dSJacob Faibussowitsch PetscCall(PetscFree(numTrueSupp)); 8923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 893776742edSToby Isaac } 894776742edSToby Isaac 895f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM, PetscSection, PetscSection, Mat); 896f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM, PetscSection, PetscSection, Mat); 897f7c74593SToby Isaac 898d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 899d71ae5a4SJacob Faibussowitsch { 900f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 901f9f063d4SToby Isaac DM refTree; 902f9f063d4SToby Isaac PetscInt size; 903f9f063d4SToby Isaac 904f9f063d4SToby Isaac PetscFunctionBegin; 905f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 906f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 9079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)parentSection)); 9089566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 909f9f063d4SToby Isaac mesh->parentSection = parentSection; 9109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &size)); 911f9f063d4SToby Isaac if (parents != mesh->parents) { 9129566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 9139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->parents)); 9149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->parents, parents, size)); 915f9f063d4SToby Isaac } 916f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 9179566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 9189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->childIDs)); 9199566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->childIDs, childIDs, size)); 920f9f063d4SToby Isaac } 9219566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 922f9f063d4SToby Isaac if (refTree) { 923f9f063d4SToby Isaac DMLabel canonLabel; 924f9f063d4SToby Isaac 9259566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonLabel)); 926f9f063d4SToby Isaac if (canonLabel) { 927f9f063d4SToby Isaac PetscInt i; 928f9f063d4SToby Isaac 929f9f063d4SToby Isaac for (i = 0; i < size; i++) { 930f9f063d4SToby Isaac PetscInt canon; 9319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon)); 932ad540459SPierre Jolivet if (canon >= 0) mesh->childIDs[i] = canon; 933f9f063d4SToby Isaac } 934f9f063d4SToby Isaac } 935f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 9366e0288c8SStefano Zampini } else { 937f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 938f9f063d4SToby Isaac } 9399566063dSJacob Faibussowitsch PetscCall(DMPlexTreeSymmetrize(dm)); 940f9f063d4SToby Isaac if (computeCanonical) { 941f9f063d4SToby Isaac PetscInt d, dim; 942f9f063d4SToby Isaac 943f9f063d4SToby Isaac /* add the canonical label */ 9449566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9459566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "canonical")); 946f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 947f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 948f9f063d4SToby Isaac const PetscInt *cChildren; 949f9f063d4SToby Isaac 9509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 951f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 9529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, p, &cNumChildren, &cChildren)); 953f9f063d4SToby Isaac if (cNumChildren) { 954f9f063d4SToby Isaac canon = p; 955f9f063d4SToby Isaac break; 956f9f063d4SToby Isaac } 957f9f063d4SToby Isaac } 958f9f063d4SToby Isaac if (canon == -1) continue; 959f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 960f9f063d4SToby Isaac PetscInt numChildren, i; 961f9f063d4SToby Isaac const PetscInt *children; 962f9f063d4SToby Isaac 9639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, p, &numChildren, &children)); 964f9f063d4SToby Isaac if (numChildren) { 96563a3b9bcSJacob 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); 9669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "canonical", p, canon)); 96748a46eb9SPierre Jolivet for (i = 0; i < numChildren; i++) PetscCall(DMSetLabelValue(dm, "canonical", children[i], cChildren[i])); 968f9f063d4SToby Isaac } 969f9f063d4SToby Isaac } 970f9f063d4SToby Isaac } 971f9f063d4SToby Isaac } 9721baa6e33SBarry Smith if (exchangeSupports) PetscCall(DMPlexTreeExchangeSupports(dm)); 973f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 974f7c74593SToby Isaac /* reset anchors */ 9759566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm, NULL, NULL)); 9763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 977f9f063d4SToby Isaac } 978f9f063d4SToby Isaac 9790b7167a0SToby Isaac /*@ 9800b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 981aaa8cc7dSPierre Jolivet the point-to-point constraints determined by the tree: a point is constrained to the points in the closure of its 9820b7167a0SToby Isaac tree root. 9830b7167a0SToby Isaac 98420f4b53cSBarry Smith Collective 9850b7167a0SToby Isaac 9860b7167a0SToby Isaac Input Parameters: 987a1cb98faSBarry Smith + dm - the `DMPLEX` object 9880b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 9890b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 9900b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 9910b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 9920b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 9930b7167a0SToby Isaac 9940b7167a0SToby Isaac Level: intermediate 9950b7167a0SToby Isaac 9961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 9970b7167a0SToby Isaac @*/ 998d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 999d71ae5a4SJacob Faibussowitsch { 10000b7167a0SToby Isaac PetscFunctionBegin; 10019566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm, parentSection, parents, childIDs, PETSC_FALSE, PETSC_TRUE)); 10023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10030b7167a0SToby Isaac } 10040b7167a0SToby Isaac 1005b2f41788SToby Isaac /*@ 1006b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 100720f4b53cSBarry Smith Collective 1008b2f41788SToby Isaac 1009f899ff85SJose E. Roman Input Parameter: 1010a1cb98faSBarry Smith . dm - the `DMPLEX` object 1011b2f41788SToby Isaac 1012b2f41788SToby Isaac Output Parameters: 1013b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1014b2f41788SToby Isaac offset indexes the parent and childID list 1015b2f41788SToby Isaac . parents - a list of the point parents 1016b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1017b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1018b2f41788SToby Isaac . childSection - the inverse of the parent section 1019b2f41788SToby Isaac - children - a list of the point children 1020b2f41788SToby Isaac 1021b2f41788SToby Isaac Level: intermediate 1022b2f41788SToby Isaac 10231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`,`DMPlexSetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 1024b2f41788SToby Isaac @*/ 1025d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1026d71ae5a4SJacob Faibussowitsch { 1027b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1028b2f41788SToby Isaac 1029b2f41788SToby Isaac PetscFunctionBegin; 1030b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1031b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1032b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1033b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1034b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1035b2f41788SToby Isaac if (children) *children = mesh->children; 10363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1037b2f41788SToby Isaac } 1038b2f41788SToby Isaac 1039d961a43aSToby Isaac /*@ 1040eaf898f9SPatrick Sanan DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the DAG) 1041d961a43aSToby Isaac 1042d961a43aSToby Isaac Input Parameters: 1043a1cb98faSBarry Smith + dm - the `DMPLEX` object 1044d961a43aSToby Isaac - point - the query point 1045d961a43aSToby Isaac 1046d961a43aSToby Isaac Output Parameters: 104720f4b53cSBarry Smith + parent - if not `NULL`, set to the parent of the point, or the point itself if the point does not have a parent 104820f4b53cSBarry Smith - childID - if not `NULL`, set to the child ID of the point with respect to its parent, or 0 if the point 1049d961a43aSToby Isaac does not have a parent 1050d961a43aSToby Isaac 1051d961a43aSToby Isaac Level: intermediate 1052d961a43aSToby Isaac 10531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeChildren()` 1054d961a43aSToby Isaac @*/ 1055d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1056d71ae5a4SJacob Faibussowitsch { 1057d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1058d961a43aSToby Isaac PetscSection pSec; 1059d961a43aSToby Isaac 1060d961a43aSToby Isaac PetscFunctionBegin; 1061d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1062d961a43aSToby Isaac pSec = mesh->parentSection; 1063d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1064d961a43aSToby Isaac PetscInt dof; 1065d961a43aSToby Isaac 10669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, point, &dof)); 1067d961a43aSToby Isaac if (dof) { 1068d961a43aSToby Isaac PetscInt off; 1069d961a43aSToby Isaac 10709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, point, &off)); 1071d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1072d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 10733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1074d961a43aSToby Isaac } 1075d961a43aSToby Isaac } 1076ad540459SPierre Jolivet if (parent) *parent = point; 1077ad540459SPierre Jolivet if (childID) *childID = 0; 10783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1079d961a43aSToby Isaac } 1080d961a43aSToby Isaac 1081d961a43aSToby Isaac /*@C 1082eaf898f9SPatrick Sanan DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the DAG) 1083d961a43aSToby Isaac 1084d961a43aSToby Isaac Input Parameters: 1085a1cb98faSBarry Smith + dm - the `DMPLEX` object 1086d961a43aSToby Isaac - point - the query point 1087d961a43aSToby Isaac 1088d961a43aSToby Isaac Output Parameters: 108920f4b53cSBarry Smith + numChildren - if not `NULL`, set to the number of children 109020f4b53cSBarry Smith - children - if not `NULL`, set to a list children, or set to `NULL` if the point has no children 1091d961a43aSToby Isaac 1092d961a43aSToby Isaac Level: intermediate 1093d961a43aSToby Isaac 10941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeParent()` 1095d961a43aSToby Isaac @*/ 1096d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1097d71ae5a4SJacob Faibussowitsch { 1098d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1099d961a43aSToby Isaac PetscSection childSec; 1100d961a43aSToby Isaac PetscInt dof = 0; 1101d961a43aSToby Isaac 1102d961a43aSToby Isaac PetscFunctionBegin; 1103d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1104d961a43aSToby Isaac childSec = mesh->childSection; 110548a46eb9SPierre Jolivet if (childSec && point >= childSec->pStart && point < childSec->pEnd) PetscCall(PetscSectionGetDof(childSec, point, &dof)); 1106d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1107d961a43aSToby Isaac if (children) { 1108d961a43aSToby Isaac if (dof) { 1109d961a43aSToby Isaac PetscInt off; 1110d961a43aSToby Isaac 11119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, point, &off)); 1112d961a43aSToby Isaac *children = &mesh->children[off]; 11139371c9d4SSatish Balay } else { 1114d961a43aSToby Isaac *children = NULL; 1115d961a43aSToby Isaac } 1116d961a43aSToby Isaac } 11173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1118d961a43aSToby Isaac } 11190c37af3bSToby Isaac 1120d71ae5a4SJacob 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) 1121d71ae5a4SJacob Faibussowitsch { 112252a3aeb4SToby Isaac PetscInt f, b, p, c, offset, qPoints; 1123b3a4bf2aSToby Isaac 1124b3a4bf2aSToby Isaac PetscFunctionBegin; 11259566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(space, nPoints, points, work, NULL, NULL)); 112652a3aeb4SToby Isaac for (f = 0, offset = 0; f < nFunctionals; f++) { 112752a3aeb4SToby Isaac qPoints = pointsPerFn[f]; 112852a3aeb4SToby Isaac for (b = 0; b < nBasis; b++) { 1129b3a4bf2aSToby Isaac PetscScalar val = 0.; 1130b3a4bf2aSToby Isaac 113152a3aeb4SToby Isaac for (p = 0; p < qPoints; p++) { 1132ad540459SPierre Jolivet for (c = 0; c < nComps; c++) val += work[((offset + p) * nBasis + b) * nComps + c] * weights[(offset + p) * nComps + c]; 113352a3aeb4SToby Isaac } 11349566063dSJacob Faibussowitsch PetscCall(MatSetValue(basisAtPoints, b, f, val, INSERT_VALUES)); 1135b3a4bf2aSToby Isaac } 1136b3a4bf2aSToby Isaac offset += qPoints; 1137b3a4bf2aSToby Isaac } 11389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(basisAtPoints, MAT_FINAL_ASSEMBLY)); 11399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(basisAtPoints, MAT_FINAL_ASSEMBLY)); 11403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1141b3a4bf2aSToby Isaac } 1142b3a4bf2aSToby Isaac 1143d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 1144d71ae5a4SJacob Faibussowitsch { 11450c37af3bSToby Isaac PetscDS ds; 11460c37af3bSToby Isaac PetscInt spdim; 11470c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 11480c37af3bSToby Isaac const PetscInt *anchors; 1149f7c74593SToby Isaac PetscSection aSec; 11500c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 11510c37af3bSToby Isaac IS aIS; 11520c37af3bSToby Isaac 11530c37af3bSToby Isaac PetscFunctionBegin; 11549566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11559566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 11569566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 11579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 11589566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 11599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 11609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &conStart, &conEnd)); 11619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &spdim)); 11629566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(spdim, &v0, spdim, &v0parent, spdim, &vtmp, spdim * spdim, &J, spdim * spdim, &Jparent, spdim * spdim, &invJparent)); 11630c37af3bSToby Isaac 11640c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 11650dd1b1feSToby Isaac PetscObject disc; 11660dd1b1feSToby Isaac PetscClassId id; 1167b3a4bf2aSToby Isaac PetscSpace bspace; 1168b3a4bf2aSToby Isaac PetscDualSpace dspace; 11699c3cf19fSMatthew G. Knepley PetscInt i, j, k, nPoints, Nc, offset; 117052a3aeb4SToby Isaac PetscInt fSize, maxDof; 1171b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 11721683a169SBarry Smith PetscScalar *scwork; 11731683a169SBarry Smith const PetscScalar *X; 11742c44ad04SToby Isaac PetscInt *sizes, *workIndRow, *workIndCol; 11750c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 11762c44ad04SToby Isaac const PetscInt *numDof = NULL; 1177085f0adfSToby Isaac const PetscInt ***perms = NULL; 1178085f0adfSToby Isaac const PetscScalar ***flips = NULL; 11790c37af3bSToby Isaac 11809566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 11819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &id)); 11820dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1183b3a4bf2aSToby Isaac PetscFE fe = (PetscFE)disc; 1184b3a4bf2aSToby Isaac 11859566063dSJacob Faibussowitsch PetscCall(PetscFEGetBasisSpace(fe, &bspace)); 11869566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dspace)); 11879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize)); 11889566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc)); 11899371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) { 1190b3a4bf2aSToby Isaac PetscFV fv = (PetscFV)disc; 1191b3a4bf2aSToby Isaac 11929566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc)); 11939566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)fv), &bspace)); 11949566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(bspace, PETSCSPACEPOLYNOMIAL)); 11959566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(bspace, 0, PETSC_DETERMINE)); 11969566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(bspace, Nc)); 11979566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(bspace, spdim)); 11989566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(bspace)); 11999566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv, &dspace)); 12009566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize)); 12019371c9d4SSatish Balay } else SETERRQ(PetscObjectComm(disc), PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 12029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dspace, &numDof)); 1203ad540459SPierre Jolivet for (i = 0, maxDof = 0; i <= spdim; i++) maxDof = PetscMax(maxDof, numDof[i]); 12049566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dspace, &perms, &flips)); 12050dd1b1feSToby Isaac 12069566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &Amat)); 12079566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Amat, fSize, fSize, fSize, fSize)); 12089566063dSJacob Faibussowitsch PetscCall(MatSetType(Amat, MATSEQDENSE)); 12099566063dSJacob Faibussowitsch PetscCall(MatSetUp(Amat)); 12109566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Bmat)); 12119566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Xmat)); 12120c37af3bSToby Isaac nPoints = 0; 12130c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 121452a3aeb4SToby Isaac PetscInt qPoints, thisNc; 12150c37af3bSToby Isaac PetscQuadrature quad; 12160c37af3bSToby Isaac 12179566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad)); 12189566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &thisNc, &qPoints, NULL, NULL)); 121963a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 12200c37af3bSToby Isaac nPoints += qPoints; 12210c37af3bSToby Isaac } 12229566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(fSize, &sizes, nPoints * Nc, &weights, spdim * nPoints, &pointsRef, spdim * nPoints, &pointsReal, nPoints * fSize * Nc, &work, maxDof, &workIndRow, maxDof, &workIndCol)); 12239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &scwork)); 12240c37af3bSToby Isaac offset = 0; 12250c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12260c37af3bSToby Isaac PetscInt qPoints; 12270c37af3bSToby Isaac const PetscReal *p, *w; 12280c37af3bSToby Isaac PetscQuadrature quad; 12290c37af3bSToby Isaac 12309566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad)); 12319566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &qPoints, &p, &w)); 12329566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(weights + Nc * offset, w, Nc * qPoints)); 12339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pointsRef + spdim * offset, p, spdim * qPoints)); 1234b3a4bf2aSToby Isaac sizes[i] = qPoints; 12350c37af3bSToby Isaac offset += qPoints; 12360c37af3bSToby Isaac } 12379566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsRef, weights, work, Amat)); 12389566063dSJacob Faibussowitsch PetscCall(MatLUFactor(Amat, NULL, NULL, NULL)); 12390c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 12400c37af3bSToby Isaac PetscInt parent; 12410c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 12420c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 12430c37af3bSToby Isaac 12449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, c, &parent, NULL)); 12450c37af3bSToby Isaac if (parent == c) continue; 12469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 12470c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12480c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12490c37af3bSToby Isaac PetscInt conDof; 12500c37af3bSToby Isaac 12510c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1252085f0adfSToby Isaac if (numFields) { 12539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof)); 12549371c9d4SSatish Balay } else { 12559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof)); 12560c37af3bSToby Isaac } 12570c37af3bSToby Isaac if (conDof) break; 12580c37af3bSToby Isaac } 12590c37af3bSToby Isaac if (i == closureSize) { 12609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 12610c37af3bSToby Isaac continue; 12620c37af3bSToby Isaac } 12630c37af3bSToby Isaac 12649566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ)); 12659566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent)); 12660c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1267c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 1268c330f8ffSToby Isaac 1269c330f8ffSToby Isaac CoordinatesRefToReal(spdim, spdim, xi0, v0, J, &pointsRef[i * spdim], vtmp); 1270c330f8ffSToby Isaac CoordinatesRealToRef(spdim, spdim, xi0, v0parent, invJparent, vtmp, &pointsReal[i * spdim]); 12710c37af3bSToby Isaac } 12729566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsReal, weights, work, Bmat)); 12739566063dSJacob Faibussowitsch PetscCall(MatMatSolve(Amat, Bmat, Xmat)); 12749566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Xmat, &X)); 12759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP)); 12769566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(closureSize + 1, &childOffsets, closureSizeP + 1, &parentOffsets)); 12770c37af3bSToby Isaac childOffsets[0] = 0; 12780c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12790c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12800c37af3bSToby Isaac PetscInt dof; 12810c37af3bSToby Isaac 1282085f0adfSToby Isaac if (numFields) { 12839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 12849371c9d4SSatish Balay } else { 12859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 12860c37af3bSToby Isaac } 128752a3aeb4SToby Isaac childOffsets[i + 1] = childOffsets[i] + dof; 12880c37af3bSToby Isaac } 12890c37af3bSToby Isaac parentOffsets[0] = 0; 12900c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 12910c37af3bSToby Isaac PetscInt p = closureP[2 * i]; 12920c37af3bSToby Isaac PetscInt dof; 12930c37af3bSToby Isaac 1294085f0adfSToby Isaac if (numFields) { 12959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 12969371c9d4SSatish Balay } else { 12979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 12980c37af3bSToby Isaac } 129952a3aeb4SToby Isaac parentOffsets[i + 1] = parentOffsets[i] + dof; 13000c37af3bSToby Isaac } 13010c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13022c44ad04SToby Isaac PetscInt conDof, conOff, aDof, aOff, nWork; 13030c37af3bSToby Isaac PetscInt p = closure[2 * i]; 13040c37af3bSToby Isaac PetscInt o = closure[2 * i + 1]; 1305085f0adfSToby Isaac const PetscInt *perm; 1306085f0adfSToby Isaac const PetscScalar *flip; 13070c37af3bSToby Isaac 13080c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1309085f0adfSToby Isaac if (numFields) { 13109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof)); 13119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &conOff)); 13129371c9d4SSatish Balay } else { 13139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof)); 13149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &conOff)); 13150c37af3bSToby Isaac } 13160c37af3bSToby Isaac if (!conDof) continue; 1317085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL; 1318085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL; 13199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 13209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 13212c44ad04SToby Isaac nWork = childOffsets[i + 1] - childOffsets[i]; 13220c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 13230c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 13240c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 13250c37af3bSToby Isaac 1326085f0adfSToby Isaac if (numFields) { 13279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aSecDof)); 13289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aSecOff)); 13299371c9d4SSatish Balay } else { 13309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aSecDof)); 13319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aSecOff)); 13320c37af3bSToby Isaac } 13330c37af3bSToby Isaac if (!aSecDof) continue; 13340c37af3bSToby Isaac 13350c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 13360c37af3bSToby Isaac PetscInt q = closureP[2 * j]; 13370c37af3bSToby Isaac PetscInt oq = closureP[2 * j + 1]; 13382c44ad04SToby Isaac 13392c44ad04SToby Isaac if (q == a) { 134052a3aeb4SToby Isaac PetscInt r, s, nWorkP; 1341085f0adfSToby Isaac const PetscInt *permP; 1342085f0adfSToby Isaac const PetscScalar *flipP; 1343085f0adfSToby Isaac 1344085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL; 1345085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL; 13462c44ad04SToby Isaac nWorkP = parentOffsets[j + 1] - parentOffsets[j]; 13472c44ad04SToby Isaac /* get a copy of the child-to-anchor portion of the matrix, and transpose so that rows correspond to the 13481683a169SBarry Smith * child and columns correspond to the anchor: BUT the maxrix returned by MatDenseGetArrayRead() is 13492c44ad04SToby Isaac * column-major, so transpose-transpose = do nothing */ 13502c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1351ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] = X[fSize * (r + childOffsets[i]) + (s + parentOffsets[j])]; 13522c44ad04SToby Isaac } 1353ad540459SPierre Jolivet for (r = 0; r < nWork; r++) workIndRow[perm ? perm[r] : r] = conOff + r; 1354ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) workIndCol[permP ? permP[s] : s] = aSecOff + s; 13552c44ad04SToby Isaac if (flip) { 13562c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1357ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] *= flip[r]; 13582c44ad04SToby Isaac } 13592c44ad04SToby Isaac } 13602c44ad04SToby Isaac if (flipP) { 13612c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1362ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] *= flipP[s]; 13632c44ad04SToby Isaac } 13642c44ad04SToby Isaac } 13659566063dSJacob Faibussowitsch PetscCall(MatSetValues(cMat, nWork, workIndRow, nWorkP, workIndCol, scwork, INSERT_VALUES)); 13662c44ad04SToby Isaac break; 13670c37af3bSToby Isaac } 13680c37af3bSToby Isaac } 13690c37af3bSToby Isaac } 13700c37af3bSToby Isaac } 13719566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Xmat, &X)); 13729566063dSJacob Faibussowitsch PetscCall(PetscFree2(childOffsets, parentOffsets)); 13739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 13749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP)); 13750c37af3bSToby Isaac } 13769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Amat)); 13779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bmat)); 13789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Xmat)); 13799566063dSJacob Faibussowitsch PetscCall(PetscFree(scwork)); 13809566063dSJacob Faibussowitsch PetscCall(PetscFree7(sizes, weights, pointsRef, pointsReal, work, workIndRow, workIndCol)); 138148a46eb9SPierre Jolivet if (id == PETSCFV_CLASSID) PetscCall(PetscSpaceDestroy(&bspace)); 13820c37af3bSToby Isaac } 13839566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 13849566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 13859566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJparent)); 13869566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 13873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13880c37af3bSToby Isaac } 138995a0b26dSToby Isaac 1390d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 1391d71ae5a4SJacob Faibussowitsch { 1392f7c74593SToby Isaac Mat refCmat; 139321968bf8SToby Isaac PetscDS ds; 1394085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 139521968bf8SToby Isaac PetscScalar ***refPointFieldMats; 139621968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 139721968bf8SToby Isaac IS refAnIS; 139821968bf8SToby Isaac const PetscInt *refAnchors; 1399085f0adfSToby Isaac const PetscInt **perms; 1400085f0adfSToby Isaac const PetscScalar **flips; 140195a0b26dSToby Isaac 140295a0b26dSToby Isaac PetscFunctionBegin; 14039566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 14049566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1405085f0adfSToby Isaac maxFields = PetscMax(1, numFields); 14069566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 14079566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 14089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(refAnIS, &refAnchors)); 14099566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 14109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 14119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 14129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldN)); 14139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 14149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 14159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 14169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxAnDof, &cols)); 141795a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 141895a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 141995a0b26dSToby Isaac 14209566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 14219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 142295a0b26dSToby Isaac if (!pDof || parent == p) continue; 142395a0b26dSToby Isaac 14249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxFields, &refPointFieldMats[p - pRefStart])); 14259566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxFields, &refPointFieldN[p - pRefStart])); 14269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure)); 1427085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1428085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i; 142995a0b26dSToby Isaac 1430085f0adfSToby Isaac if (f < numFields) { 14319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 14329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 14339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips)); 1434085f0adfSToby Isaac } else { 14359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 14369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 14379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(refSection, closureSize, closure, &perms, &flips)); 143895a0b26dSToby Isaac } 143995a0b26dSToby Isaac 1440ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r; 144195a0b26dSToby Isaac numCols = 0; 144295a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 144395a0b26dSToby Isaac PetscInt q = closure[2 * i]; 144495a0b26dSToby Isaac PetscInt aDof, aOff, j; 1445085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 144695a0b26dSToby Isaac 1447085f0adfSToby Isaac if (numFields) { 14489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof)); 14499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff)); 14509371c9d4SSatish Balay } else { 14519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof)); 14529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff)); 145395a0b26dSToby Isaac } 145495a0b26dSToby Isaac 1455ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + (perm ? perm[j] : j); 145695a0b26dSToby Isaac } 145795a0b26dSToby Isaac refPointFieldN[p - pRefStart][f] = numCols; 14589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 14599566063dSJacob Faibussowitsch PetscCall(MatGetValues(refCmat, cDof, rows, numCols, cols, refPointFieldMats[p - pRefStart][f])); 1460085f0adfSToby Isaac if (flips) { 1461085f0adfSToby Isaac PetscInt colOff = 0; 1462085f0adfSToby Isaac 1463085f0adfSToby Isaac for (i = 0; i < closureSize; i++) { 1464085f0adfSToby Isaac PetscInt q = closure[2 * i]; 1465085f0adfSToby Isaac PetscInt aDof, aOff, j; 1466085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 1467085f0adfSToby Isaac 1468085f0adfSToby Isaac if (numFields) { 14699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof)); 14709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff)); 14719371c9d4SSatish Balay } else { 14729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof)); 14739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff)); 1474085f0adfSToby Isaac } 1475085f0adfSToby Isaac if (flip) { 1476085f0adfSToby Isaac PetscInt k; 1477085f0adfSToby Isaac for (k = 0; k < cDof; k++) { 1478ad540459SPierre Jolivet for (j = 0; j < aDof; j++) refPointFieldMats[p - pRefStart][f][k * numCols + colOff + j] *= flip[j]; 1479085f0adfSToby Isaac } 1480085f0adfSToby Isaac } 1481085f0adfSToby Isaac colOff += aDof; 1482085f0adfSToby Isaac } 1483085f0adfSToby Isaac } 1484085f0adfSToby Isaac if (numFields) { 14859566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips)); 1486085f0adfSToby Isaac } else { 14879566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(refSection, closureSize, closure, &perms, &flips)); 1488085f0adfSToby Isaac } 148995a0b26dSToby Isaac } 14909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure)); 149195a0b26dSToby Isaac } 149221968bf8SToby Isaac *childrenMats = refPointFieldMats; 149321968bf8SToby Isaac *childrenN = refPointFieldN; 14949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(refAnIS, &refAnchors)); 14959566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 14969566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 14973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 149821968bf8SToby Isaac } 149921968bf8SToby Isaac 1500d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 1501d71ae5a4SJacob Faibussowitsch { 150221968bf8SToby Isaac PetscDS ds; 150321968bf8SToby Isaac PetscInt **refPointFieldN; 150421968bf8SToby Isaac PetscScalar ***refPointFieldMats; 1505085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f; 150621968bf8SToby Isaac PetscSection refConSec; 150721968bf8SToby Isaac 150821968bf8SToby Isaac PetscFunctionBegin; 150921968bf8SToby Isaac refPointFieldN = *childrenN; 151021968bf8SToby Isaac *childrenN = NULL; 151121968bf8SToby Isaac refPointFieldMats = *childrenMats; 151221968bf8SToby Isaac *childrenMats = NULL; 15139566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 15149566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1515367003a6SStefano Zampini maxFields = PetscMax(1, numFields); 15169566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 15179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 151821968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 151921968bf8SToby Isaac PetscInt parent, pDof; 152021968bf8SToby Isaac 15219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 15229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 152321968bf8SToby Isaac if (!pDof || parent == p) continue; 152421968bf8SToby Isaac 1525085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 152621968bf8SToby Isaac PetscInt cDof; 152721968bf8SToby Isaac 1528085f0adfSToby Isaac if (numFields) { 15299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 15309371c9d4SSatish Balay } else { 15319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 153221968bf8SToby Isaac } 153321968bf8SToby Isaac 15349566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 153521968bf8SToby Isaac } 15369566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 15379566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN[p - pRefStart])); 153821968bf8SToby Isaac } 15399566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 15409566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN)); 15413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 154221968bf8SToby Isaac } 154321968bf8SToby Isaac 1544d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 1545d71ae5a4SJacob Faibussowitsch { 154621968bf8SToby Isaac DM refTree; 154721968bf8SToby Isaac PetscDS ds; 154821968bf8SToby Isaac Mat refCmat; 1549085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 155021968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 155121968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 155221968bf8SToby Isaac IS refAnIS, anIS; 155321968bf8SToby Isaac const PetscInt *anchors; 155421968bf8SToby Isaac 155521968bf8SToby Isaac PetscFunctionBegin; 155621968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15579566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 15589566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1559085f0adfSToby Isaac maxFields = PetscMax(1, numFields); 15609566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 15619566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, refTree)); 1562c77c71ffSToby Isaac PetscCall(DMSetLocalSection(refTree, NULL)); 1563c77c71ffSToby Isaac PetscCall(DMSetDefaultConstraints(refTree, NULL, NULL, NULL)); 15649566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 15659566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 15669566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anSec, &anIS)); 15679566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anIS, &anchors)); 15689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 15699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(conSec, &conStart, &conEnd)); 15709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 15719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 15729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof * maxAnDof, &pointWork)); 157321968bf8SToby Isaac 157421968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 15759566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 157695a0b26dSToby Isaac 157795a0b26dSToby Isaac /* step 2: compute the preorder */ 15789566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 15799566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &perm, pEnd - pStart, &iperm)); 158095a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 158195a0b26dSToby Isaac perm[p - pStart] = p; 158295a0b26dSToby Isaac iperm[p - pStart] = p - pStart; 158395a0b26dSToby Isaac } 158495a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 158595a0b26dSToby Isaac PetscInt point = perm[p]; 158695a0b26dSToby Isaac PetscInt parent; 158795a0b26dSToby Isaac 15889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 158995a0b26dSToby Isaac if (parent == point) { 159095a0b26dSToby Isaac p++; 15919371c9d4SSatish Balay } else { 159295a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 159395a0b26dSToby Isaac 15949566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 159595a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 159695a0b26dSToby Isaac PetscInt q = closure[2 * i]; 159795a0b26dSToby Isaac if (iperm[q - pStart] > iperm[point - pStart]) { 159895a0b26dSToby Isaac /* swap */ 159995a0b26dSToby Isaac perm[p] = q; 160095a0b26dSToby Isaac perm[iperm[q - pStart]] = point; 160195a0b26dSToby Isaac iperm[point - pStart] = iperm[q - pStart]; 160295a0b26dSToby Isaac iperm[q - pStart] = p; 160395a0b26dSToby Isaac break; 160495a0b26dSToby Isaac } 160595a0b26dSToby Isaac } 160695a0b26dSToby Isaac size = closureSize; 16079566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1608ad540459SPierre Jolivet if (i == size) p++; 160995a0b26dSToby Isaac } 161095a0b26dSToby Isaac } 161195a0b26dSToby Isaac 161295a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 161395a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 161495a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 161595a0b26dSToby Isaac * values outside of the Mat first. 161695a0b26dSToby Isaac */ 161795a0b26dSToby Isaac { 161895a0b26dSToby Isaac PetscInt nRows, row, nnz; 161995a0b26dSToby Isaac PetscBool done; 1620cd6fc93eSToby Isaac PetscInt secStart, secEnd; 162195a0b26dSToby Isaac const PetscInt *ia, *ja; 162295a0b26dSToby Isaac PetscScalar *vals; 162395a0b26dSToby Isaac 1624cd6fc93eSToby Isaac PetscCall(PetscSectionGetChart(section, &secStart, &secEnd)); 16259566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 162628b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not get RowIJ of constraint matrix"); 162795a0b26dSToby Isaac nnz = ia[nRows]; 162895a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 162995a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 16309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &vals)); 163195a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 163295a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 163395a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 163495a0b26dSToby Isaac 16359566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, &childid)); 163695a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 16379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &pointDof)); 163895a0b26dSToby Isaac if (!pointDof) continue; 16399566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1640085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1641085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 164295a0b26dSToby Isaac PetscScalar *pointMat; 1643085f0adfSToby Isaac const PetscInt **perms; 1644085f0adfSToby Isaac const PetscScalar **flips; 164595a0b26dSToby Isaac 1646085f0adfSToby Isaac if (numFields) { 16479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, point, f, &cDof)); 16489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, point, f, &cOff)); 16499371c9d4SSatish Balay } else { 16509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &cDof)); 16519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, point, &cOff)); 165295a0b26dSToby Isaac } 165395a0b26dSToby Isaac if (!cDof) continue; 16549566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 16559566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, closureSize, closure, &perms, &flips)); 165695a0b26dSToby Isaac 165795a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 165876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 165995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 166095a0b26dSToby Isaac if (cDof > 1 && r) { 166163a3b9bcSJacob 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])); 166295a0b26dSToby Isaac } 166395a0b26dSToby Isaac } 166476bd3646SJed Brown } 166595a0b26dSToby Isaac /* zero rows */ 1666ad540459SPierre Jolivet for (i = ia[cOff]; i < ia[cOff + cDof]; i++) vals[i] = 0.; 166795a0b26dSToby Isaac matOffset = ia[cOff]; 166895a0b26dSToby Isaac numFillCols = ia[cOff + 1] - matOffset; 166995a0b26dSToby Isaac pointMat = refPointFieldMats[childid - pRefStart][f]; 167095a0b26dSToby Isaac numCols = refPointFieldN[childid - pRefStart][f]; 167195a0b26dSToby Isaac offset = 0; 167295a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 167395a0b26dSToby Isaac PetscInt q = closure[2 * i]; 167495a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 1675085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1676085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 167795a0b26dSToby Isaac 167895a0b26dSToby Isaac qConDof = qConOff = 0; 1679cd6fc93eSToby Isaac if (q < secStart || q >= secEnd) continue; 1680085f0adfSToby Isaac if (numFields) { 16819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, q, f, &aDof)); 16829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, q, f, &aOff)); 168395a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, q, f, &qConDof)); 16859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, q, f, &qConOff)); 168695a0b26dSToby Isaac } 16879371c9d4SSatish Balay } else { 16889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &aDof)); 16899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &aOff)); 169095a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, q, &qConDof)); 16929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, q, &qConOff)); 169395a0b26dSToby Isaac } 169495a0b26dSToby Isaac } 169595a0b26dSToby Isaac if (!aDof) continue; 169695a0b26dSToby Isaac if (qConDof) { 169795a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 169895a0b26dSToby Isaac * be filled, thanks to preordering */ 169995a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 170095a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 170195a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 170295a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 170395a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 170495a0b26dSToby Isaac PetscScalar inVal = 0; 170595a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1706085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 170795a0b26dSToby Isaac 1708085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 170995a0b26dSToby Isaac } 171095a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 171195a0b26dSToby Isaac } 171295a0b26dSToby Isaac } 171395a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 171495a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 171595a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 171695a0b26dSToby Isaac for (; k < numFillCols; k++) { 1717ad540459SPierre Jolivet if (ja[matOffset + k] == col) break; 171895a0b26dSToby Isaac } 171963a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, col); 1720ad540459SPierre Jolivet for (r = 0; r < cDof; r++) vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 172195a0b26dSToby Isaac } 17229371c9d4SSatish Balay } else { 172395a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 172495a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 1725ad540459SPierre Jolivet if (ja[matOffset + k] == aOff) break; 172695a0b26dSToby Isaac } 172763a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, aOff); 172895a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1729085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1730085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1731085f0adfSToby Isaac 1732085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 173395a0b26dSToby Isaac } 173495a0b26dSToby Isaac } 173595a0b26dSToby Isaac } 173695a0b26dSToby Isaac offset += aDof; 173795a0b26dSToby Isaac } 1738085f0adfSToby Isaac if (numFields) { 17399566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 1740085f0adfSToby Isaac } else { 17419566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, closureSize, closure, &perms, &flips)); 1742085f0adfSToby Isaac } 174395a0b26dSToby Isaac } 17449566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 174595a0b26dSToby Isaac } 174648a46eb9SPierre 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)); 17479566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 174828b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not restore RowIJ of constraint matrix"); 17499566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 17509566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 17519566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 175295a0b26dSToby Isaac } 175395a0b26dSToby Isaac 175495a0b26dSToby Isaac /* clean up */ 17559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anIS, &anchors)); 17569566063dSJacob Faibussowitsch PetscCall(PetscFree2(perm, iperm)); 17579566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 17589566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 17593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 176095a0b26dSToby Isaac } 176195a0b26dSToby Isaac 17626f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 17636f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 1764d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTreeRefineCell(DM dm, PetscInt cell, DM *ncdm) 1765d71ae5a4SJacob Faibussowitsch { 17666f5f1567SToby Isaac DM K; 1767420f55faSMatthew G. Knepley PetscMPIInt rank; 17686f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 17696f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 17706f5f1567SToby Isaac PetscInt *Kembedding; 17716f5f1567SToby Isaac PetscInt *cellClosure = NULL, nc; 17726f5f1567SToby Isaac PetscScalar *newVertexCoords; 17736f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 17746f5f1567SToby Isaac PetscSection parentSection; 17756f5f1567SToby Isaac 17766f5f1567SToby Isaac PetscFunctionBegin; 17779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17789566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 17799566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm)); 17809566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ncdm, dim)); 17816f5f1567SToby Isaac 17829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 17839566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &parentSection)); 17849566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &K)); 17856858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 1786dd400576SPatrick Sanan if (rank == 0) { 17876f5f1567SToby Isaac /* compute the new charts */ 17889566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim + 1, &pNewCount, dim + 1, &pNewStart, dim + 1, &pNewEnd, dim + 1, &pOldStart, dim + 1, &pOldEnd)); 17896f5f1567SToby Isaac offset = 0; 17906f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 17916f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 17926f5f1567SToby Isaac 17936f5f1567SToby Isaac pNewStart[d] = offset; 17949566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pOldStart[d], &pOldEnd[d])); 17959566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 17966f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 17976f5f1567SToby Isaac /* adding the new points */ 17986f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 17996f5f1567SToby Isaac if (!d) { 18006f5f1567SToby Isaac /* removing the cell */ 18016f5f1567SToby Isaac pNewCount[d]--; 18026f5f1567SToby Isaac } 18036f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18046f5f1567SToby Isaac PetscInt parent; 18059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &parent, NULL)); 18066f5f1567SToby Isaac if (parent == k) { 18076f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 18086f5f1567SToby Isaac pNewCount[d]--; 18096f5f1567SToby Isaac } 18106f5f1567SToby Isaac } 18116f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 18126f5f1567SToby Isaac offset = pNewEnd[d]; 18136f5f1567SToby Isaac } 18141dca8a05SBarry 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]); 18156f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 18169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 18176f5f1567SToby Isaac 18189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pNewEnd[dim], &newConeSizes)); 18196f5f1567SToby Isaac { 1820b5a892a1SMatthew G. Knepley DMPolytopeType pct, qct; 18216f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 18226f5f1567SToby Isaac 18239566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &kStart, &kEnd)); 18249566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(kEnd - kStart, &Kembedding, kEnd - kStart, &perm, kEnd - kStart, &iperm, kEnd - kStart, &preOrient)); 18256f5f1567SToby Isaac 18266f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18276f5f1567SToby Isaac perm[k - kStart] = k; 18286f5f1567SToby Isaac iperm[k - kStart] = k - kStart; 18296f5f1567SToby Isaac preOrient[k - kStart] = 0; 18306f5f1567SToby Isaac } 18316f5f1567SToby Isaac 18329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18336f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 18346f5f1567SToby Isaac PetscInt parentOrientA = closureK[2 * j + 1]; 18356f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2 * j + 1]; 18366f5f1567SToby Isaac PetscInt p, q; 18376f5f1567SToby Isaac 18386f5f1567SToby Isaac p = closureK[2 * j]; 18396f5f1567SToby Isaac q = cellClosure[2 * j]; 18409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, p, &pct)); 18419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, q, &qct)); 18426f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 1843ad540459SPierre Jolivet if (q >= pOldStart[d] && q < pOldEnd[d]) Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 18446f5f1567SToby Isaac } 1845b5a892a1SMatthew G. Knepley parentOrientA = DMPolytopeConvertNewOrientation_Internal(pct, parentOrientA); 1846b5a892a1SMatthew G. Knepley parentOrientB = DMPolytopeConvertNewOrientation_Internal(qct, parentOrientB); 18476f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 18486f5f1567SToby Isaac PetscInt numChildren, i; 18496f5f1567SToby Isaac const PetscInt *children; 18506f5f1567SToby Isaac 18519566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(K, p, &numChildren, &children)); 18526f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 18536f5f1567SToby Isaac PetscInt kPerm, oPerm; 18546f5f1567SToby Isaac 18556f5f1567SToby Isaac k = children[i]; 18569566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(K, p, parentOrientA, 0, k, parentOrientB, &oPerm, &kPerm)); 18576f5f1567SToby Isaac /* perm = what refTree position I'm in */ 18586f5f1567SToby Isaac perm[kPerm - kStart] = k; 18596f5f1567SToby Isaac /* iperm = who is at this position */ 18606f5f1567SToby Isaac iperm[k - kStart] = kPerm - kStart; 18616f5f1567SToby Isaac preOrient[kPerm - kStart] = oPerm; 18626f5f1567SToby Isaac } 18636f5f1567SToby Isaac } 18646f5f1567SToby Isaac } 18659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18666f5f1567SToby Isaac } 18679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, pNewEnd[dim])); 18686f5f1567SToby Isaac offset = 0; 18696f5f1567SToby Isaac numNewCones = 0; 18706f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18716f5f1567SToby Isaac PetscInt kStart, kEnd, k; 18726f5f1567SToby Isaac PetscInt p; 18736f5f1567SToby Isaac PetscInt size; 18746f5f1567SToby Isaac 18756f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 18766f5f1567SToby Isaac /* skip cell 0 */ 18776f5f1567SToby Isaac if (p == cell) continue; 18786f5f1567SToby Isaac /* old cones to new cones */ 18799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 18806f5f1567SToby Isaac newConeSizes[offset++] = size; 18816f5f1567SToby Isaac numNewCones += size; 18826f5f1567SToby Isaac } 18836f5f1567SToby Isaac 18849566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 18856f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18866f5f1567SToby Isaac PetscInt kParent; 18876f5f1567SToby Isaac 18889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 18896f5f1567SToby Isaac if (kParent != k) { 18906f5f1567SToby Isaac Kembedding[k] = offset; 18919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 18926f5f1567SToby Isaac newConeSizes[offset++] = size; 18936f5f1567SToby Isaac numNewCones += size; 189448a46eb9SPierre Jolivet if (kParent != 0) PetscCall(PetscSectionSetDof(parentSection, Kembedding[k], 1)); 18956f5f1567SToby Isaac } 18966f5f1567SToby Isaac } 18976f5f1567SToby Isaac } 18986f5f1567SToby Isaac 18999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 19009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &numPointsWithParents)); 19019566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numNewCones, &newCones, numNewCones, &newOrientations)); 19029566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPointsWithParents, &parents, numPointsWithParents, &childIDs)); 19036f5f1567SToby Isaac 19046f5f1567SToby Isaac /* fill new cones */ 19056f5f1567SToby Isaac offset = 0; 19066f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19076f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 19086f5f1567SToby Isaac PetscInt p; 19096f5f1567SToby Isaac PetscInt size; 19106f5f1567SToby Isaac const PetscInt *cone, *orientation; 19116f5f1567SToby Isaac 19126f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19136f5f1567SToby Isaac /* skip cell 0 */ 19146f5f1567SToby Isaac if (p == cell) continue; 19156f5f1567SToby Isaac /* old cones to new cones */ 19169566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 19179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 19189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &orientation)); 19196f5f1567SToby Isaac for (l = 0; l < size; l++) { 19206f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 19216f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 19226f5f1567SToby Isaac } 19236f5f1567SToby Isaac } 19246f5f1567SToby Isaac 19259566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 19266f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19276f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 19286f5f1567SToby Isaac PetscInt preO = preOrient[k]; 19296f5f1567SToby Isaac 19309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 19316f5f1567SToby Isaac if (kParent != k) { 19326f5f1567SToby Isaac /* embed new cones */ 19339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 19349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, kPerm, &cone)); 19359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, kPerm, &orientation)); 19366f5f1567SToby Isaac for (l = 0; l < size; l++) { 19376f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size - (preO + 1) - l) % size); 19386f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 1939b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_NUM_POLYTOPES; 19406f5f1567SToby Isaac 19416f5f1567SToby Isaac q = iperm[cone[m]]; 19426f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 19439566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, q, &lSize)); 1944b5a892a1SMatthew G. Knepley if (lSize == 2) ct = DM_POLYTOPE_SEGMENT; 1945b5a892a1SMatthew G. Knepley else if (lSize == 4) ct = DM_POLYTOPE_QUADRILATERAL; 1946b5a892a1SMatthew G. Knepley oTrue = DMPolytopeConvertNewOrientation_Internal(ct, orientation[m]); 19476f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 19486f5f1567SToby Isaac newO = DihedralCompose(lSize, oTrue, preOrient[q]); 1949b5a892a1SMatthew G. Knepley newOrientations[offset++] = DMPolytopeConvertOldOrientation_Internal(ct, newO); 19506f5f1567SToby Isaac } 19516f5f1567SToby Isaac if (kParent != 0) { 19526f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 19539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, Kembedding[k], &pOffset)); 19546f5f1567SToby Isaac parents[pOffset] = newPoint; 19556f5f1567SToby Isaac childIDs[pOffset] = k; 19566f5f1567SToby Isaac } 19576f5f1567SToby Isaac } 19586f5f1567SToby Isaac } 19596f5f1567SToby Isaac } 19606f5f1567SToby Isaac 19619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * (pNewEnd[dim] - pNewStart[dim]), &newVertexCoords)); 19626f5f1567SToby Isaac 19636f5f1567SToby Isaac /* fill coordinates */ 19646f5f1567SToby Isaac offset = 0; 19656f5f1567SToby Isaac { 1966d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 19676f5f1567SToby Isaac PetscSection vSection; 19686f5f1567SToby Isaac PetscInt v; 19696f5f1567SToby Isaac Vec coords; 19706f5f1567SToby Isaac PetscScalar *coordvals; 19716f5f1567SToby Isaac PetscInt dof, off; 1972c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 19736f5f1567SToby Isaac 197476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1975d90620a3SMatthew G. Knepley PetscInt k; 19769566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, 0, &kStart, &kEnd)); 19776f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19789566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ)); 197963a3b9bcSJacob Faibussowitsch PetscCheck(detJ > 0., PETSC_COMM_SELF, PETSC_ERR_PLIB, "reference tree cell %" PetscInt_FMT " has bad determinant", k); 19806f5f1567SToby Isaac } 1981d90620a3SMatthew G. Knepley } 19829566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ)); 19839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &vSection)); 19849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coords)); 19859566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19866f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 19879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(vSection, v, &dof)); 19889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, v, &off)); 1989ad540459SPierre Jolivet for (l = 0; l < dof; l++) newVertexCoords[offset++] = coordvals[off + l]; 19906f5f1567SToby Isaac } 19919566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 19926f5f1567SToby Isaac 19939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &vSection)); 19949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &coords)); 19959566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &kStart, &kEnd)); 19976f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 19989bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 19996f5f1567SToby Isaac PetscInt vPerm = perm[v]; 20006f5f1567SToby Isaac PetscInt kParent; 2001c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 20026f5f1567SToby Isaac 20039566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, v, &kParent, NULL)); 20046f5f1567SToby Isaac if (kParent != v) { 20056f5f1567SToby Isaac /* this is a new vertex */ 20069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, vPerm, &off)); 20079bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off + l]); 2008367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord); 20099bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset + l] = newCoord[l]; 20106f5f1567SToby Isaac offset += dim; 20116f5f1567SToby Isaac } 20126f5f1567SToby Isaac } 20139566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 20146f5f1567SToby Isaac } 20156f5f1567SToby Isaac 20166f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 20176f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 20186f5f1567SToby Isaac PetscInt tmp; 20196f5f1567SToby Isaac 20206f5f1567SToby Isaac tmp = pNewCount[d]; 20216f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 20226f5f1567SToby Isaac pNewCount[dim - d] = tmp; 20236f5f1567SToby Isaac } 20246f5f1567SToby Isaac 20259566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, pNewCount, newConeSizes, newCones, newOrientations, newVertexCoords)); 20269566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20279566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, parents, childIDs)); 20286f5f1567SToby Isaac 20296f5f1567SToby Isaac /* clean up */ 20309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 20319566063dSJacob Faibussowitsch PetscCall(PetscFree5(pNewCount, pNewStart, pNewEnd, pOldStart, pOldEnd)); 20329566063dSJacob Faibussowitsch PetscCall(PetscFree(newConeSizes)); 20339566063dSJacob Faibussowitsch PetscCall(PetscFree2(newCones, newOrientations)); 20349566063dSJacob Faibussowitsch PetscCall(PetscFree(newVertexCoords)); 20359566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs)); 20369566063dSJacob Faibussowitsch PetscCall(PetscFree4(Kembedding, perm, iperm, preOrient)); 20379371c9d4SSatish Balay } else { 20386f5f1567SToby Isaac PetscInt p, counts[4]; 20396f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 20406f5f1567SToby Isaac Vec coordVec; 20416f5f1567SToby Isaac PetscScalar *coords; 20426f5f1567SToby Isaac 20436f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20446f5f1567SToby Isaac PetscInt dStart, dEnd; 20456f5f1567SToby Isaac 20469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 20476f5f1567SToby Isaac counts[d] = dEnd - dStart; 20486f5f1567SToby Isaac } 20499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &coneSizes)); 205048a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMPlexGetConeSize(dm, p, &coneSizes[p - pStart])); 20519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 20529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &orientations)); 20539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordVec)); 20549566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordVec, &coords)); 20556f5f1567SToby Isaac 20569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd)); 20579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 20589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, counts, coneSizes, cones, orientations, NULL)); 20599566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20609566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, NULL, NULL)); 20619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordVec, &coords)); 20626f5f1567SToby Isaac } 20639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 20643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20656f5f1567SToby Isaac } 20666ecaa68aSToby Isaac 2067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 2068d71ae5a4SJacob Faibussowitsch { 20696ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 20706ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 20716ecaa68aSToby Isaac PetscSection localCoarse, localFine; 20726ecaa68aSToby Isaac PetscSection aSec, cSec; 20736ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 207446bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 207546bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 207646bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 20776ecaa68aSToby Isaac IS aIS; 20786ecaa68aSToby Isaac const PetscInt *anchors; 20796ecaa68aSToby Isaac Mat cMat; 20804acb8e1eSToby Isaac PetscInt numFields, maxFields; 20816ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 20826ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 20831c58ffc4SToby Isaac PetscInt *maxChildIds; 2084e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 20854acb8e1eSToby Isaac const PetscInt ***perms; 20864acb8e1eSToby Isaac const PetscScalar ***flips; 20876ecaa68aSToby Isaac 20886ecaa68aSToby Isaac PetscFunctionBegin; 20899566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 20909566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 20919566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 20926ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 209389698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 209489698031SToby Isaac const PetscInt *leaves; 20956ecaa68aSToby Isaac 20969566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 209789698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 209889698031SToby Isaac p = leaves ? leaves[l] : l; 20999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 21009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 2101ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 21026ecaa68aSToby Isaac } 21039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 21047cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 210589698031SToby Isaac p = leaves ? leaves[l] : l; 21069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 21079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 2108ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l; 21096ecaa68aSToby Isaac } 21109566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 21119566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 21126ecaa68aSToby Isaac } 21136ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 21149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 2115ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2; 211657168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 211757168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 211846bdb399SToby Isaac 21199566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 21209566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 212146bdb399SToby Isaac 21229566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 21239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 21249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 212546bdb399SToby Isaac 21269566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 21279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 212846bdb399SToby Isaac 212946bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 21309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 21319566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootMatricesSec)); 21329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootIndicesSec, pStartC, pEndC)); 21339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootMatricesSec, pStartC, pEndC)); 21349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 2135713c1c5dSToby Isaac maxFields = PetscMax(1, numFields); 21369566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields + 1, &offsets, maxFields + 1, &offsetsCopy, maxFields + 1, &newOffsets, maxFields + 1, &newOffsetsCopy, maxFields + 1, &rowOffsets, maxFields + 1, &numD, maxFields + 1, &numO)); 21379566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxFields + 1, (PetscInt ****)&perms, maxFields + 1, (PetscScalar ****)&flips)); 21389566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)perms, (maxFields + 1) * sizeof(const PetscInt **))); 21399566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)flips, (maxFields + 1) * sizeof(const PetscScalar **))); 214046bdb399SToby Isaac 214146bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 21428d2f55e7SToby Isaac PetscInt dof, matSize = 0; 21436ecaa68aSToby Isaac PetscInt aDof = 0; 21446ecaa68aSToby Isaac PetscInt cDof = 0; 21456ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 21466ecaa68aSToby Isaac PetscInt numRowIndices = 0; 21476ecaa68aSToby Isaac PetscInt numColIndices = 0; 2148f13f9184SToby Isaac PetscInt f; 21496ecaa68aSToby Isaac 21509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 2151ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 215248a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 215348a46eb9SPierre Jolivet if (p >= cStart && p < cEnd) PetscCall(PetscSectionGetDof(cSec, p, &cDof)); 2154f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2155f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 21566ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2157f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 21586ecaa68aSToby Isaac 21599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 216046bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 21616ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 21626ecaa68aSToby Isaac 21639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 21646ecaa68aSToby Isaac numRowIndices += clDof; 21656ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &clDof)); 21676ecaa68aSToby Isaac offsets[f + 1] += clDof; 21686ecaa68aSToby Isaac } 21696ecaa68aSToby Isaac } 21706ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21716ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 21726ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 21736ecaa68aSToby Isaac } 217446bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 21759566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, NULL, NULL, NULL, &numColIndices, NULL, NULL, newOffsets, PETSC_FALSE)); 21769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 21776ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 21786ecaa68aSToby Isaac numColIndices = numRowIndices; 21796ecaa68aSToby Isaac matSize = 0; 21809371c9d4SSatish Balay } else if (numFields) { /* we send one submat for each field: sum their sizes */ 21816ecaa68aSToby Isaac matSize = 0; 21826ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21836ecaa68aSToby Isaac PetscInt numRow, numCol; 21846ecaa68aSToby Isaac 21856ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2186f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 21876ecaa68aSToby Isaac matSize += numRow * numCol; 21886ecaa68aSToby Isaac } 21899371c9d4SSatish Balay } else { 21906ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 21916ecaa68aSToby Isaac } 2192f13f9184SToby Isaac } else if (maxChildId == -1) { 21938d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2194f13f9184SToby Isaac PetscInt aOff, a; 21956ecaa68aSToby Isaac 21969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 21976ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21986ecaa68aSToby Isaac PetscInt fDof; 21996ecaa68aSToby Isaac 22009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 220121968bf8SToby Isaac offsets[f + 1] = fDof; 22026ecaa68aSToby Isaac } 22036ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 22046ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 22056ecaa68aSToby Isaac 22069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, anchor, &aLocalDof)); 22076ecaa68aSToby Isaac numColIndices += aLocalDof; 22086ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22096ecaa68aSToby Isaac PetscInt fDof; 22106ecaa68aSToby Isaac 22119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 221221968bf8SToby Isaac newOffsets[f + 1] += fDof; 22136ecaa68aSToby Isaac } 22146ecaa68aSToby Isaac } 22156ecaa68aSToby Isaac if (numFields) { 22166ecaa68aSToby Isaac matSize = 0; 2217ad540459SPierre Jolivet for (f = 0; f < numFields; f++) matSize += offsets[f + 1] * newOffsets[f + 1]; 22189371c9d4SSatish Balay } else { 22196ecaa68aSToby Isaac matSize = numColIndices * dof; 22206ecaa68aSToby Isaac } 22219371c9d4SSatish Balay } else { /* no children, and no constraints on dofs: just get the global indices */ 22226ecaa68aSToby Isaac numColIndices = dof; 22236ecaa68aSToby Isaac matSize = 0; 22246ecaa68aSToby Isaac } 22258d2f55e7SToby Isaac } 222646bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 22279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootIndicesSec, p, numColIndices ? numColIndices + 2 * numFields : 0)); 22289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootMatricesSec, p, matSize)); 22296ecaa68aSToby Isaac } 22309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootIndicesSec)); 22319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootMatricesSec)); 22326ecaa68aSToby Isaac { 22336ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 22346ecaa68aSToby Isaac 22359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 22369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootMatricesSec, &numRootMatrices)); 22379566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRootIndices, &rootIndices, numRootMatrices, &rootMatrices)); 22386ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22396ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2240f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 22416ecaa68aSToby Isaac PetscInt *pInd; 22426ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22436ecaa68aSToby Isaac PetscScalar *pMat = NULL; 22446ecaa68aSToby Isaac 22459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, p, &numColIndices)); 2246ad540459SPierre Jolivet if (!numColIndices) continue; 2247f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2248f13f9184SToby Isaac offsets[f] = 0; 2249f13f9184SToby Isaac newOffsets[f] = 0; 2250f13f9184SToby Isaac offsetsCopy[f] = 0; 2251f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2252f13f9184SToby Isaac } 22536ecaa68aSToby Isaac numColIndices -= 2 * numFields; 22549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, p, &pIndOff)); 2255*f4f49eeaSPierre Jolivet pInd = &rootIndices[pIndOff]; 22569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootMatricesSec, p, &matSize)); 22576ecaa68aSToby Isaac if (matSize) { 22589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootMatricesSec, p, &pMatOff)); 22596ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 22606ecaa68aSToby Isaac } 22619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 2262ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 22636ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 22646ecaa68aSToby Isaac PetscInt i, j; 22656ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 22666ecaa68aSToby Isaac 22676ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 22686ecaa68aSToby Isaac PetscInt numIndices, *indices; 22699566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 227008401ef6SPierre Jolivet PetscCheck(numIndices == numColIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "mismatching constraint indices calculations"); 2271ad540459SPierre Jolivet for (i = 0; i < numColIndices; i++) pInd[i] = indices[i]; 22726ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 227346bdb399SToby Isaac pInd[numColIndices + i] = offsets[i + 1]; 227446bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i + 1]; 22756ecaa68aSToby Isaac } 22769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 22779371c9d4SSatish Balay } else { 22786ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 22796ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 22806ecaa68aSToby Isaac PetscInt numPoints, *points; 22816ecaa68aSToby Isaac 22829566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices * numRowIndices, MPIU_SCALAR, &pMatIn)); 22836ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 2284ad540459SPierre Jolivet for (j = 0; j < numRowIndices; j++) pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 22856ecaa68aSToby Isaac } 22869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 22874acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 22889566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 22899566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 22904acb8e1eSToby Isaac } 22916ecaa68aSToby Isaac if (numFields) { 22926ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 22936ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 22946ecaa68aSToby Isaac 22956ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22966ecaa68aSToby Isaac PetscInt fDof; 22976ecaa68aSToby Isaac 22989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &fDof)); 22996ecaa68aSToby Isaac offsets[f + 1] += fDof; 23006ecaa68aSToby Isaac } 23016ecaa68aSToby Isaac } 23026ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23036ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23046ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 23056ecaa68aSToby Isaac } 23066ecaa68aSToby Isaac } 23074acb8e1eSToby Isaac /* TODO : flips here ? */ 23086ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 23099566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, perms, pMatIn, &numPoints, NULL, &points, &pMatModified, newOffsets, PETSC_FALSE)); 23104acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23119566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 23129566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 23134acb8e1eSToby Isaac } 23144acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23159566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23169566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23174acb8e1eSToby Isaac } 23186ecaa68aSToby Isaac if (!numFields) { 2319ad540459SPierre Jolivet for (i = 0; i < numRowIndices * numColIndices; i++) pMat[i] = pMatModified[i]; 23209371c9d4SSatish Balay } else { 2321f13f9184SToby Isaac PetscInt i, j, count; 23226ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 23236ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f + 1]; i++) { 2324ad540459SPierre Jolivet for (j = newOffsets[f]; j < newOffsets[f + 1]; j++, count++) pMat[count] = pMatModified[i * numColIndices + j]; 23256ecaa68aSToby Isaac } 23266ecaa68aSToby Isaac } 23276ecaa68aSToby Isaac } 23289566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatModified)); 23299566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 23309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatIn)); 23316ecaa68aSToby Isaac if (numFields) { 233246bdb399SToby Isaac for (f = 0; f < numFields; f++) { 233346bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 233446bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 23356ecaa68aSToby Isaac } 23364acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23374acb8e1eSToby Isaac PetscInt globalOff, c = points[2 * cl]; 23389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23399566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd)); 23406ecaa68aSToby Isaac } 23416ecaa68aSToby Isaac } else { 23424acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23434acb8e1eSToby Isaac PetscInt c = points[2 * cl], globalOff; 23444acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 23454acb8e1eSToby Isaac 23469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23479566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd)); 23486ecaa68aSToby Isaac } 23496ecaa68aSToby Isaac } 23504acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23519566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23529566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23534acb8e1eSToby Isaac } 23549566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numPoints, MPIU_SCALAR, &points)); 23556ecaa68aSToby Isaac } 23569371c9d4SSatish Balay } else if (matSize) { 23576ecaa68aSToby Isaac PetscInt cOff; 23586ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 23596ecaa68aSToby Isaac 23606ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 236108401ef6SPierre Jolivet PetscCheck(numRowIndices == dof, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Miscounted dofs"); 23629566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 23639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 23649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &cOff)); 23659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 23669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 23676ecaa68aSToby Isaac if (numFields) { 23686ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23696ecaa68aSToby Isaac PetscInt fDof; 2370f13f9184SToby Isaac 23719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &fDof)); 23726ecaa68aSToby Isaac offsets[f + 1] = fDof; 23736ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23746ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 23759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 23766ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 23776ecaa68aSToby Isaac } 23786ecaa68aSToby Isaac } 23796ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23806ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23816ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 23826ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 23836ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 23846ecaa68aSToby Isaac } 23859566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, -1, NULL, rowIndices)); 23866ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23876ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23899566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, -1, NULL, colIndices)); 23906ecaa68aSToby Isaac } 23919371c9d4SSatish Balay } else { 23929566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, NULL, rowIndices)); 23936ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23946ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23969566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, NULL, colIndices)); 23976ecaa68aSToby Isaac } 23986ecaa68aSToby Isaac } 23996ecaa68aSToby Isaac if (numFields) { 2400f13f9184SToby Isaac PetscInt count, a; 2401f13f9184SToby Isaac 24026ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24036ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 24046ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 24059566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, iSize, &rowIndices[offsets[f]], jSize, &colIndices[newOffsets[f]], &pMat[count])); 24066ecaa68aSToby Isaac count += iSize * jSize; 240746bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 240846bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 24096ecaa68aSToby Isaac } 24106ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 24116ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 24126ecaa68aSToby Isaac PetscInt gOff; 24139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 24149566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 24156ecaa68aSToby Isaac } 24169371c9d4SSatish Balay } else { 24176ecaa68aSToby Isaac PetscInt a; 24189566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, numRowIndices, rowIndices, numColIndices, colIndices, pMat)); 24196ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 24206ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 24216ecaa68aSToby Isaac PetscInt gOff; 24229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 24239566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, NULL, pInd)); 24246ecaa68aSToby Isaac } 24256ecaa68aSToby Isaac } 24269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 24279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 24289371c9d4SSatish Balay } else { 24296ecaa68aSToby Isaac PetscInt gOff; 24306ecaa68aSToby Isaac 24319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 24326ecaa68aSToby Isaac if (numFields) { 24336ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24346ecaa68aSToby Isaac PetscInt fDof; 24359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 24366ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 24376ecaa68aSToby Isaac } 24386ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 243946bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 244046bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f + 1]; 24416ecaa68aSToby Isaac } 24429566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 2443367003a6SStefano Zampini } else { 24449566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 24456ecaa68aSToby Isaac } 24466ecaa68aSToby Isaac } 24476ecaa68aSToby Isaac } 24489566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 24496ecaa68aSToby Isaac } 245046bdb399SToby Isaac { 245146bdb399SToby Isaac PetscSF indicesSF, matricesSF; 245246bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 245346bdb399SToby Isaac 24549566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 24559566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafMatricesSec)); 24569566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootIndicesSec, &remoteOffsetsIndices, leafIndicesSec)); 24579566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootMatricesSec, &remoteOffsetsMatrices, leafMatricesSec)); 24589566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootIndicesSec, remoteOffsetsIndices, leafIndicesSec, &indicesSF)); 24599566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootMatricesSec, remoteOffsetsMatrices, leafMatricesSec, &matricesSF)); 24609566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 24619566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsIndices)); 24629566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsMatrices)); 24639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numLeafIndices)); 24649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafMatricesSec, &numLeafMatrices)); 24659566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numLeafIndices, &leafIndices, numLeafMatrices, &leafMatrices)); 24669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24709566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&matricesSF)); 24719566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 24729566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootIndices, rootMatrices)); 24739566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 24749566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootMatricesSec)); 247546bdb399SToby Isaac } 247646bdb399SToby Isaac /* count to preallocate */ 24779566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 247846bdb399SToby Isaac { 247946bdb399SToby Isaac PetscInt nGlobal; 248046bdb399SToby Isaac PetscInt *dnnz, *onnz; 2481b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2482b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 24831c58ffc4SToby Isaac PetscInt maxDof; 24841c58ffc4SToby Isaac PetscInt *rowIndices; 24851c58ffc4SToby Isaac DM refTree; 24861c58ffc4SToby Isaac PetscInt **refPointFieldN; 24871c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 24881c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 24890eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, maxConDof, maxColumns, leafStart, leafEnd; 24901c58ffc4SToby Isaac PetscScalar *pointWork; 249146bdb399SToby Isaac 24929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalFine, &nGlobal)); 24939566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nGlobal, &dnnz, nGlobal, &onnz)); 24949566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 24959566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 24969566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 24979566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 24989566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 24999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 25009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafIndicesSec, &leafStart, &leafEnd)); 25019566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 25020eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 250346bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 250446bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 250546bdb399SToby Isaac PetscInt matSize; 250621968bf8SToby Isaac PetscInt i; 250746bdb399SToby Isaac 25089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 25099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 2510ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 25119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 251208401ef6SPierre Jolivet PetscCheck(gOff >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I though having global dofs meant a non-negative offset"); 25131dca8a05SBarry Smith PetscCheck(gOff >= rowStart && (gOff + gDof - gcDof) <= rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I thought the row map would constrain the global dofs"); 25149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 25159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 251646bdb399SToby Isaac numColIndices -= 2 * numFields; 251708401ef6SPierre Jolivet PetscCheck(numColIndices > 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "global fine dof with no dofs to interpolate from"); 251846bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 251921968bf8SToby Isaac offsets[0] = 0; 252021968bf8SToby Isaac offsetsCopy[0] = 0; 252121968bf8SToby Isaac newOffsets[0] = 0; 252221968bf8SToby Isaac newOffsetsCopy[0] = 0; 252346bdb399SToby Isaac if (numFields) { 252421968bf8SToby Isaac PetscInt f; 252546bdb399SToby Isaac for (f = 0; f < numFields; f++) { 252646bdb399SToby Isaac PetscInt rowDof; 252746bdb399SToby Isaac 25289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 252921968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 253021968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 253121968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 253221968bf8SToby Isaac numD[f] = 0; 253321968bf8SToby Isaac numO[f] = 0; 253446bdb399SToby Isaac } 25359566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 253646bdb399SToby Isaac for (f = 0; f < numFields; f++) { 253721968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 253821968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 253946bdb399SToby Isaac 254046bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 254146bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 254246bdb399SToby Isaac 254346bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 254421968bf8SToby Isaac numD[f]++; 25459371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 254621968bf8SToby Isaac numO[f]++; 254746bdb399SToby Isaac } 254846bdb399SToby Isaac } 254946bdb399SToby Isaac } 25509371c9d4SSatish Balay } else { 25519566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 255221968bf8SToby Isaac numD[0] = 0; 255321968bf8SToby Isaac numO[0] = 0; 255446bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 255546bdb399SToby Isaac PetscInt gInd = pInd[i]; 255646bdb399SToby Isaac 255746bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 255821968bf8SToby Isaac numD[0]++; 25599371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 256021968bf8SToby Isaac numO[0]++; 256146bdb399SToby Isaac } 256246bdb399SToby Isaac } 256346bdb399SToby Isaac } 25649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 256546bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 256646bdb399SToby Isaac PetscInt childId; 256746bdb399SToby Isaac 256846bdb399SToby Isaac childId = childIds[p - pStartF]; 256921968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 257046bdb399SToby Isaac if (numFields) { 2571b9a5774bSToby Isaac PetscInt f; 2572b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 257321968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 257446bdb399SToby Isaac for (row = 0; row < numRows; row++) { 257521968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 257621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 257746bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25781dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2579b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25809371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25811dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2582b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25839371c9d4SSatish Balay } else { /* constrained */ 258408401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 258546bdb399SToby Isaac } 258646bdb399SToby Isaac } 258746bdb399SToby Isaac } 25889371c9d4SSatish Balay } else { 2589b9a5774bSToby Isaac PetscInt i; 2590b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 259146bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 259246bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 259346bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25941dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2595b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25969371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25971dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2598b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25999371c9d4SSatish Balay } else { /* constrained */ 260008401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 260146bdb399SToby Isaac } 260246bdb399SToby Isaac } 260346bdb399SToby Isaac } 26049371c9d4SSatish Balay } else { /* interpolate from all */ 260546bdb399SToby Isaac if (numFields) { 2606b9a5774bSToby Isaac PetscInt f; 2607b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 260821968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 260946bdb399SToby Isaac for (row = 0; row < numRows; row++) { 261021968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 261146bdb399SToby Isaac if (gIndFine >= 0) { 26121dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2613b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2614b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 261546bdb399SToby Isaac } 261646bdb399SToby Isaac } 261746bdb399SToby Isaac } 26189371c9d4SSatish Balay } else { 2619b9a5774bSToby Isaac PetscInt i; 2620b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 262146bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 262246bdb399SToby Isaac if (gIndFine >= 0) { 26231dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2624b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2625b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 262646bdb399SToby Isaac } 262746bdb399SToby Isaac } 262846bdb399SToby Isaac } 262946bdb399SToby Isaac } 26309371c9d4SSatish Balay } else { /* interpolate from all */ 263146bdb399SToby Isaac if (numFields) { 2632b9a5774bSToby Isaac PetscInt f; 2633b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 263421968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 263546bdb399SToby Isaac for (row = 0; row < numRows; row++) { 263621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 263746bdb399SToby Isaac if (gIndFine >= 0) { 26381dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2639b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2640b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 264146bdb399SToby Isaac } 264246bdb399SToby Isaac } 264346bdb399SToby Isaac } 26449371c9d4SSatish Balay } else { /* every dof get a full row */ 2645b9a5774bSToby Isaac PetscInt i; 2646b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 264746bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 264846bdb399SToby Isaac if (gIndFine >= 0) { 26491dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2650b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2651b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 265246bdb399SToby Isaac } 265346bdb399SToby Isaac } 265446bdb399SToby Isaac } 265546bdb399SToby Isaac } 265646bdb399SToby Isaac } 26579566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, dnnz, onnz, NULL, NULL)); 26589566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnnz, onnz)); 265921968bf8SToby Isaac 26609566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 2661d3a532e9SStefano Zampini PetscCall(DMCopyDisc(fine, refTree)); 2662d3a532e9SStefano Zampini PetscCall(DMSetLocalSection(refTree, NULL)); 2663d3a532e9SStefano Zampini PetscCall(DMSetDefaultConstraints(refTree, NULL, NULL, NULL)); 26649566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 26659566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 26669566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 26679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 26689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxConDof)); 26699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(leafIndicesSec, &maxColumns)); 26709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConDof * maxColumns, &pointWork)); 26710eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2672e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2673e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2674e44e4e7fSToby Isaac PetscInt matSize; 2675e44e4e7fSToby Isaac PetscInt childId; 2676e44e4e7fSToby Isaac 26779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 26789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 2679ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 2680e44e4e7fSToby Isaac childId = childIds[p - pStartF]; 26819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 26829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 26839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 2684e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2685e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2686e44e4e7fSToby Isaac offsets[0] = 0; 2687e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2688e44e4e7fSToby Isaac newOffsets[0] = 0; 2689e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2690e44e4e7fSToby Isaac rowOffsets[0] = 0; 2691e44e4e7fSToby Isaac if (numFields) { 2692e44e4e7fSToby Isaac PetscInt f; 2693e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2694e44e4e7fSToby Isaac PetscInt rowDof; 2695e44e4e7fSToby Isaac 26969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 2697e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2698e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2699e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2700e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2701e44e4e7fSToby Isaac } 27029566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 27039371c9d4SSatish Balay } else { 27049566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 27051c58ffc4SToby Isaac } 27069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 2707e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2708e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2709e44e4e7fSToby Isaac if (numFields) { 2710e44e4e7fSToby Isaac PetscInt f; 2711e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2712e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 271348a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[offsets[f] + row], pInd[newOffsets[f] + row], 1., INSERT_VALUES)); 271421968bf8SToby Isaac } 27159371c9d4SSatish Balay } else { 2716e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 271748a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[row], pInd[row], 1., INSERT_VALUES)); 2718e44e4e7fSToby Isaac } 27199371c9d4SSatish Balay } else { /* interpolate from all */ 2720e44e4e7fSToby Isaac if (numFields) { 2721e44e4e7fSToby Isaac PetscInt f; 2722e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2723e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2724e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 27259566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], refPointFieldMats[childId - pRefStart][f], INSERT_VALUES)); 2726e44e4e7fSToby Isaac } 27279371c9d4SSatish Balay } else { 27289566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, refPointFieldMats[childId - pRefStart][0], INSERT_VALUES)); 2729e44e4e7fSToby Isaac } 2730e44e4e7fSToby Isaac } 27319371c9d4SSatish Balay } else { /* interpolate from all */ 2732e44e4e7fSToby Isaac PetscInt pMatOff; 2733e44e4e7fSToby Isaac PetscScalar *pMat; 2734e44e4e7fSToby Isaac 27359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafMatricesSec, p, &pMatOff)); 2736e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2737e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2738e44e4e7fSToby Isaac if (numFields) { 2739e44e4e7fSToby Isaac PetscInt f, count; 2740e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2741e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2742e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2743e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2744e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2745e44e4e7fSToby Isaac 27469566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], inMat, INSERT_VALUES)); 2747e44e4e7fSToby Isaac count += numCols * numInRows; 2748e44e4e7fSToby Isaac } 27499371c9d4SSatish Balay } else { 27509566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, pMat, INSERT_VALUES)); 2751e44e4e7fSToby Isaac } 27529371c9d4SSatish Balay } else { /* multiply the incoming matrix by the child interpolation */ 2753e44e4e7fSToby Isaac if (numFields) { 2754e44e4e7fSToby Isaac PetscInt f, count; 2755e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2756e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2757e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2758e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2759e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2760e44e4e7fSToby Isaac PetscInt i, j, k; 276108401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][f] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2762e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2763e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2764e44e4e7fSToby Isaac PetscScalar val = 0.; 2765ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2766e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2767e44e4e7fSToby Isaac } 2768e44e4e7fSToby Isaac } 27699566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], pointWork, INSERT_VALUES)); 2770e44e4e7fSToby Isaac count += numCols * numInRows; 2771e44e4e7fSToby Isaac } 27729371c9d4SSatish Balay } else { /* every dof gets a full row */ 2773e44e4e7fSToby Isaac PetscInt numRows = gDof; 2774e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2775e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2776e44e4e7fSToby Isaac PetscInt i, j, k; 277708401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][0] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2778e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2779e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2780e44e4e7fSToby Isaac PetscScalar val = 0.; 2781ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2782e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2783e44e4e7fSToby Isaac } 2784e44e4e7fSToby Isaac } 27859566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, rowIndices, numCols, pInd, pointWork, INSERT_VALUES)); 2786e44e4e7fSToby Isaac } 2787e44e4e7fSToby Isaac } 2788e44e4e7fSToby Isaac } 2789e44e4e7fSToby Isaac } 27909566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 27919566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 27929566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 2793e44e4e7fSToby Isaac } 27949566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 27959566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 27969566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 27979566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafMatricesSec)); 27989566063dSJacob Faibussowitsch PetscCall(PetscFree2(leafIndices, leafMatrices)); 27999566063dSJacob Faibussowitsch PetscCall(PetscFree2(*(PetscInt ****)&perms, *(PetscScalar ****)&flips)); 28009566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 28019566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 28023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28036ecaa68aSToby Isaac } 2804154bca37SToby Isaac 28058d2f55e7SToby Isaac /* 28068d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 28078d2f55e7SToby Isaac * 28088d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 28098d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 28108d2f55e7SToby Isaac * for each fine dof \phi^f_j; 28118d2f55e7SToby Isaac * a_{i,j} = 0; 28128d2f55e7SToby Isaac * for each fine dof \phi^f_k: 28138d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 28148d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 28158d2f55e7SToby Isaac */ 2816d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 2817d71ae5a4SJacob Faibussowitsch { 28188d2f55e7SToby Isaac PetscDS ds; 28198d2f55e7SToby Isaac PetscSection section, cSection; 28208d2f55e7SToby Isaac DMLabel canonical, depth; 28218d2f55e7SToby Isaac Mat cMat, mat; 28228d2f55e7SToby Isaac PetscInt *nnz; 28238d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 28248d2f55e7SToby Isaac PetscInt m, n; 28258d2f55e7SToby Isaac PetscScalar *pointScalar; 28268d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 28278d2f55e7SToby Isaac 28288d2f55e7SToby Isaac PetscFunctionBegin; 28299566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, §ion)); 28309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(refTree, &dim)); 28319566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(dim, &v0, dim, &v0parent, dim, &vtmp, dim * dim, &J, dim * dim, &Jparent, dim * dim, &invJ)); 28329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim, &pointScalar, dim, &pointRef)); 28339566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 28349566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 28359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numSecFields)); 28369566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical)); 28379566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "depth", &depth)); 28389566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSection, &cMat, NULL)); 28399566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(refTree, &pStart, &pEnd)); 28409566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd)); 28419566063dSJacob Faibussowitsch PetscCall(MatGetSize(cMat, &n, &m)); /* the injector has transpose sizes from the constraint matrix */ 28428d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 28439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 28448d2f55e7SToby 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 */ 28458d2f55e7SToby Isaac const PetscInt *children; 28468d2f55e7SToby Isaac PetscInt numChildren; 28478d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28488d2f55e7SToby Isaac 28498d2f55e7SToby Isaac if (canonical) { 28508d2f55e7SToby Isaac PetscInt pCanonical; 28519566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28528d2f55e7SToby Isaac if (p != pCanonical) continue; 28538d2f55e7SToby Isaac } 28549566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28558d2f55e7SToby Isaac if (!numChildren) continue; 28568d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28578d2f55e7SToby Isaac PetscInt child = children[i]; 28588d2f55e7SToby Isaac PetscInt dof; 28598d2f55e7SToby Isaac 28609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 28618d2f55e7SToby Isaac numChildDof += dof; 28628d2f55e7SToby Isaac } 28639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 28648d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 28658d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 28668d2f55e7SToby Isaac PetscInt selfOff; 28678d2f55e7SToby Isaac 28688d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 28698d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28708d2f55e7SToby Isaac PetscInt child = children[i]; 28718d2f55e7SToby Isaac PetscInt dof; 28728d2f55e7SToby Isaac 28739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 28748d2f55e7SToby Isaac numChildDof += dof; 28758d2f55e7SToby Isaac } 28769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 28779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 28789371c9d4SSatish Balay } else { 28799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 28808d2f55e7SToby Isaac } 2881ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) nnz[selfOff + i] = numChildDof; 28828d2f55e7SToby Isaac } 28838d2f55e7SToby Isaac } 28849566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(PETSC_COMM_SELF, m, n, m, n, -1, nnz, -1, NULL, &mat)); 28859566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 28868d2f55e7SToby Isaac /* Setp 2: compute entries */ 28878d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 28888d2f55e7SToby Isaac const PetscInt *children; 28898d2f55e7SToby Isaac PetscInt numChildren; 28908d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28918d2f55e7SToby Isaac 28928d2f55e7SToby Isaac /* same conditions about when entries occur */ 28938d2f55e7SToby Isaac if (canonical) { 28948d2f55e7SToby Isaac PetscInt pCanonical; 28959566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28968d2f55e7SToby Isaac if (p != pCanonical) continue; 28978d2f55e7SToby Isaac } 28989566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28998d2f55e7SToby Isaac if (!numChildren) continue; 29008d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 29018d2f55e7SToby Isaac PetscInt child = children[i]; 29028d2f55e7SToby Isaac PetscInt dof; 29038d2f55e7SToby Isaac 29049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 29058d2f55e7SToby Isaac numChildDof += dof; 29068d2f55e7SToby Isaac } 29079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 29088d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 29098d2f55e7SToby Isaac 29108d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 291159fc6756SToby Isaac PetscInt pI = -1, cI = -1; 291252a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell; 29138d2f55e7SToby Isaac PetscInt cellShapeOff; 29148d2f55e7SToby Isaac PetscObject disc; 29158d2f55e7SToby Isaac PetscDualSpace dsp; 29168d2f55e7SToby Isaac PetscClassId classId; 29178d2f55e7SToby Isaac PetscScalar *pointMat; 29183b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 29198d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 29208d2f55e7SToby Isaac const PetscInt *depthNumDof; 29218d2f55e7SToby Isaac 29228d2f55e7SToby Isaac if (numSecFields) { 29238d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 29248d2f55e7SToby Isaac PetscInt child = children[i]; 29258d2f55e7SToby Isaac PetscInt dof; 29268d2f55e7SToby Isaac 29279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 29288d2f55e7SToby Isaac numChildDof += dof; 29298d2f55e7SToby Isaac } 29309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 29319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 29329371c9d4SSatish Balay } else { 29339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 29348d2f55e7SToby Isaac } 29358d2f55e7SToby Isaac 29363b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 29378d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 29388d2f55e7SToby Isaac parentCell = p; 29399371c9d4SSatish Balay } else { 29408d2f55e7SToby Isaac PetscInt *star = NULL; 29418d2f55e7SToby Isaac PetscInt numStar; 29428d2f55e7SToby Isaac 29438d2f55e7SToby Isaac parentCell = -1; 29449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29458d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 29468d2f55e7SToby Isaac PetscInt c = star[2 * i]; 29478d2f55e7SToby Isaac 29488d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 29498d2f55e7SToby Isaac parentCell = c; 29508d2f55e7SToby Isaac break; 29518d2f55e7SToby Isaac } 29528d2f55e7SToby Isaac } 29539566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29548d2f55e7SToby Isaac } 2955a5b23f4aSJose E. Roman /* determine the offset of p's shape functions within parentCell's shape functions */ 29569566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 29579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &classId)); 2958c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 29599566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 29609371c9d4SSatish Balay } else if (classId == PETSCFV_CLASSID) { 29619566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace((PetscFV)disc, &dsp)); 29629371c9d4SSatish Balay } else { 29639b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported discretization object"); 2964c5356c36SToby Isaac } 29659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dsp, &depthNumDof)); 29669566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dsp, &Nc)); 29678d2f55e7SToby Isaac { 29688d2f55e7SToby Isaac PetscInt *closure = NULL; 29698d2f55e7SToby Isaac PetscInt numClosure; 29708d2f55e7SToby Isaac 29719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 297259fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) { 29738d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 29748d2f55e7SToby Isaac 29758d2f55e7SToby Isaac pO = closure[2 * i + 1]; 297659fc6756SToby Isaac if (point == p) { 297759fc6756SToby Isaac pI = i; 297859fc6756SToby Isaac break; 297959fc6756SToby Isaac } 29809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 29818d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 29828d2f55e7SToby Isaac } 29839566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 29848d2f55e7SToby Isaac } 29858d2f55e7SToby Isaac 29869566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 29879566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 298852a3aeb4SToby Isaac matCols = matRows + numSelfDof; 2989ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) matRows[i] = selfOff + i; 299052a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.; 29913b1c2a6aSToby Isaac { 29923b1c2a6aSToby Isaac PetscInt colOff = 0; 29933b1c2a6aSToby Isaac 29943b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 29953b1c2a6aSToby Isaac PetscInt child = children[i]; 29963b1c2a6aSToby Isaac PetscInt dof, off, j; 29973b1c2a6aSToby Isaac 29983b1c2a6aSToby Isaac if (numSecFields) { 29999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSection, child, f, &dof)); 30009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSection, child, f, &off)); 30019371c9d4SSatish Balay } else { 30029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSection, child, &dof)); 30039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSection, child, &off)); 30043b1c2a6aSToby Isaac } 30053b1c2a6aSToby Isaac 3006ad540459SPierre Jolivet for (j = 0; j < dof; j++) matCols[colOff++] = off + j; 30073b1c2a6aSToby Isaac } 30083b1c2a6aSToby Isaac } 30098d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 30108d2f55e7SToby Isaac PetscFE fe = (PetscFE)disc; 30118d2f55e7SToby Isaac PetscInt fSize; 301259fc6756SToby Isaac const PetscInt ***perms; 301359fc6756SToby Isaac const PetscScalar ***flips; 301459fc6756SToby Isaac const PetscInt *pperms; 301559fc6756SToby Isaac 30169566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dsp)); 30179566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dsp, &fSize)); 30189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dsp, &perms, &flips)); 301959fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL; 302052a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */ 30218d2f55e7SToby Isaac PetscQuadrature q; 302252a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k; 30238d2f55e7SToby Isaac const PetscReal *points; 30248d2f55e7SToby Isaac const PetscReal *weights; 30258d2f55e7SToby Isaac PetscInt *closure = NULL; 30268d2f55e7SToby Isaac PetscInt numClosure; 302759fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i; 302859fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell; 3029ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent; 30308d2f55e7SToby Isaac 30319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dsp, parentCellShapeDof, &q)); 30329566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, &thisNc, &numPoints, &points, &weights)); 303363a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 30349566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, numPoints, points, 0, &Tparent)); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 30353b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 30368d2f55e7SToby Isaac PetscInt childCell = -1; 303752a3aeb4SToby Isaac PetscReal *parentValAtPoint; 3038c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 30398d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 30408d2f55e7SToby Isaac const PetscScalar *point; 3041ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild; 30428d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 30438d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 30448d2f55e7SToby Isaac PetscInt d; 30458d2f55e7SToby Isaac 3046ad540459SPierre Jolivet for (d = 0; d < dim; d++) pointScalar[d] = points[dim * j + d]; 30478d2f55e7SToby Isaac point = pointScalar; 30488d2f55e7SToby Isaac #else 30498d2f55e7SToby Isaac point = pointReal; 30508d2f55e7SToby Isaac #endif 30518d2f55e7SToby Isaac 3052ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc]; 30533b1c2a6aSToby Isaac 30543b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 30558d2f55e7SToby Isaac PetscInt child = children[k]; 30568d2f55e7SToby Isaac PetscInt *star = NULL; 30578d2f55e7SToby Isaac PetscInt numStar, s; 30588d2f55e7SToby Isaac 30599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30608d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 30618d2f55e7SToby Isaac PetscInt c = star[2 * s]; 30628d2f55e7SToby Isaac 30638d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 30649566063dSJacob Faibussowitsch PetscCall(DMPlexLocatePoint_Internal(refTree, dim, point, c, &childCell)); 30658d2f55e7SToby Isaac if (childCell >= 0) break; 30668d2f55e7SToby Isaac } 30679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30688d2f55e7SToby Isaac if (childCell >= 0) break; 30698d2f55e7SToby Isaac } 307008401ef6SPierre Jolivet PetscCheck(childCell >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not locate quadrature point"); 30719566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ)); 30729566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent)); 3073c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp); 3074c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef); 30758d2f55e7SToby Isaac 30769566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, 1, pointRef, 0, &Tchild)); 30779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 30783b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3079c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 30808d2f55e7SToby Isaac PetscInt l; 308159fc6756SToby Isaac const PetscInt *cperms; 30828d2f55e7SToby Isaac 30839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, child, &childDepth)); 30848d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 308559fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) { 30868d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 30878d2f55e7SToby Isaac PetscInt pointDepth; 30888d2f55e7SToby Isaac 30898d2f55e7SToby Isaac childO = closure[2 * l + 1]; 309059fc6756SToby Isaac if (point == child) { 309159fc6756SToby Isaac cI = l; 309259fc6756SToby Isaac break; 309359fc6756SToby Isaac } 30949566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 30958d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 30968d2f55e7SToby Isaac } 30978d2f55e7SToby Isaac if (l == numClosure) { 30988d2f55e7SToby Isaac pointMatOff += childDof; 30998d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 31008d2f55e7SToby Isaac } 310159fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL; 31028d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 310359fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l; 310459fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell; 310552a3aeb4SToby Isaac PetscReal *childValAtPoint; 310652a3aeb4SToby Isaac PetscReal val = 0.; 31078d2f55e7SToby Isaac 3108ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc]; 3109ad540459SPierre Jolivet for (m = 0; m < Nc; m++) val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m]; 311052a3aeb4SToby Isaac 311152a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val; 31128d2f55e7SToby Isaac } 31138d2f55e7SToby Isaac pointMatOff += childDof; 31148d2f55e7SToby Isaac } 31159566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 31169566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tchild)); 31178d2f55e7SToby Isaac } 31189566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tparent)); 31198d2f55e7SToby Isaac } 31209371c9d4SSatish Balay } else { /* just the volume-weighted averages of the children */ 31213b1c2a6aSToby Isaac PetscReal parentVol; 3122bfaa5bdcSToby Isaac PetscInt childCell; 31233b1c2a6aSToby Isaac 31249566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL)); 3125bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) { 312652a3aeb4SToby Isaac PetscInt child = children[i], j; 31273b1c2a6aSToby Isaac PetscReal childVol; 31283b1c2a6aSToby Isaac 31293b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 31309566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL)); 3131ad540459SPierre Jolivet for (j = 0; j < Nc; j++) pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol; 3132bfaa5bdcSToby Isaac childCell++; 31333b1c2a6aSToby Isaac } 31348d2f55e7SToby Isaac } 31353b1c2a6aSToby Isaac /* Insert pointMat into mat */ 31369566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numSelfDof, matRows, numChildDof, matCols, pointMat, INSERT_VALUES)); 31379566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 31389566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 31398d2f55e7SToby Isaac } 31408d2f55e7SToby Isaac } 31419566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJ)); 31429566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointScalar, pointRef)); 31439566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 31449566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 31458d2f55e7SToby Isaac *inj = mat; 31463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31478d2f55e7SToby Isaac } 31488d2f55e7SToby Isaac 3149d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3150d71ae5a4SJacob Faibussowitsch { 3151f30e825dSToby Isaac PetscDS ds; 3152f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3153f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3154f30e825dSToby Isaac PetscSection refConSec, refSection; 3155f30e825dSToby Isaac 3156f30e825dSToby Isaac PetscFunctionBegin; 31579566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 31589566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 31599566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 31609566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 31619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 31629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 31639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 31649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 31659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &cols)); 3166f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3167f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3168f30e825dSToby Isaac 31699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 31709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 31719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3172f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3173f30e825dSToby Isaac 31749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFields, &refPointFieldMats[p - pRefStart])); 3175f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 317652a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r; 3177f30e825dSToby Isaac 3178f30e825dSToby Isaac if (numFields > 1) { 31799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 31809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 31819371c9d4SSatish Balay } else { 31829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 31839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 3184f30e825dSToby Isaac } 3185f30e825dSToby Isaac 3186ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r; 3187f30e825dSToby Isaac numCols = 0; 3188f30e825dSToby Isaac { 3189f30e825dSToby Isaac PetscInt aDof, aOff, j; 3190f30e825dSToby Isaac 3191f30e825dSToby Isaac if (numFields > 1) { 31929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, parent, f, &aDof)); 31939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, parent, f, &aOff)); 31949371c9d4SSatish Balay } else { 31959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &aDof)); 31969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, parent, &aOff)); 3197f30e825dSToby Isaac } 3198f30e825dSToby Isaac 3199ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + j; 3200f30e825dSToby Isaac } 32019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 3202f30e825dSToby Isaac /* transpose of constraint matrix */ 32039566063dSJacob Faibussowitsch PetscCall(MatGetValues(inj, numCols, cols, cDof, rows, refPointFieldMats[p - pRefStart][f])); 3204f30e825dSToby Isaac } 3205f30e825dSToby Isaac } 3206f30e825dSToby Isaac *childrenMats = refPointFieldMats; 32079566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 32089566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 32093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3210f30e825dSToby Isaac } 3211f30e825dSToby Isaac 3212d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3213d71ae5a4SJacob Faibussowitsch { 3214f30e825dSToby Isaac PetscDS ds; 3215f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3216f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3217c6154584SToby Isaac PetscSection refConSec, refSection; 3218f30e825dSToby Isaac 3219f30e825dSToby Isaac PetscFunctionBegin; 3220f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3221f30e825dSToby Isaac *childrenMats = NULL; 32229566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 32239566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 32249566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 32259566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 32269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 3227f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3228f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3229f30e825dSToby Isaac 32309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 32319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 32329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3233f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3234f30e825dSToby Isaac 3235f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3236f30e825dSToby Isaac PetscInt cDof; 3237f30e825dSToby Isaac 3238f30e825dSToby Isaac if (numFields > 1) { 32399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 32409371c9d4SSatish Balay } else { 32419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 3242f30e825dSToby Isaac } 3243f30e825dSToby Isaac 32449566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 3245f30e825dSToby Isaac } 32469566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 3247f30e825dSToby Isaac } 32489566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 32493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3250f30e825dSToby Isaac } 3251f30e825dSToby Isaac 3252d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree, Mat *injRef) 3253d71ae5a4SJacob Faibussowitsch { 3254ebf164c7SToby Isaac Mat cMatRef; 32556148253fSToby Isaac PetscObject injRefObj; 32568d2f55e7SToby Isaac 3257154bca37SToby Isaac PetscFunctionBegin; 32589566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, NULL, &cMatRef, NULL)); 32599566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", &injRefObj)); 3260ebf164c7SToby Isaac *injRef = (Mat)injRefObj; 3261ebf164c7SToby Isaac if (!*injRef) { 32629566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorReferenceTree(refTree, injRef)); 32639566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", (PetscObject)*injRef)); 3264ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 32659566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)*injRef)); 3266ebf164c7SToby Isaac } 32673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32686148253fSToby Isaac } 3269f30e825dSToby Isaac 3270d71ae5a4SJacob 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) 3271d71ae5a4SJacob Faibussowitsch { 3272c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3273ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3274ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3275c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3276c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3277c921d74cSToby Isaac const PetscInt *rootDegrees; 3278c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3279ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3280ebf164c7SToby Isaac 3281ebf164c7SToby Isaac PetscFunctionBegin; 32829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 32839566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 32849566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 32859566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 32869566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 32879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafIndicesSec, pStartF, pEndF)); 32889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 32898d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 32907e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 32917e96bdafSToby Isaac const PetscInt *leaves; 32928d2f55e7SToby Isaac 32939566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 32947e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 32957e96bdafSToby Isaac p = leaves ? leaves[l] : l; 32969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 32979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 32988d2f55e7SToby Isaac if ((dof - cdof) > 0) { 32998d2f55e7SToby Isaac numPointsWithDofs++; 3300f30e825dSToby Isaac 33019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &dof)); 33029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafIndicesSec, p, dof + 1)); 33038d2f55e7SToby Isaac } 33048d2f55e7SToby Isaac } 33059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 33069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafIndicesSec)); 33079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numIndices)); 33089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1), &leafInds)); 33099566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(PetscMalloc1(numIndices, &leafVals)); 33107e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 33117e96bdafSToby Isaac p = leaves ? leaves[l] : l; 33129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 33139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 33148d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3315f30e825dSToby Isaac PetscInt off, gOff; 3316f30e825dSToby Isaac PetscInt *pInd; 3317c921d74cSToby Isaac PetscScalar *pVal = NULL; 3318f30e825dSToby Isaac 33197e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3320f30e825dSToby Isaac 33219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3322f30e825dSToby Isaac 3323c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3324c921d74cSToby Isaac if (gatheredValues) { 3325c921d74cSToby Isaac PetscInt i; 3326c921d74cSToby Isaac 3327c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3328c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3329c921d74cSToby Isaac } 33309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 3331f30e825dSToby Isaac 3332f30e825dSToby Isaac offsets[0] = 0; 3333f30e825dSToby Isaac if (numFields) { 3334f30e825dSToby Isaac PetscInt f; 3335f30e825dSToby Isaac 3336f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3337f30e825dSToby Isaac PetscInt fDof; 33389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &fDof)); 3339f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3340f30e825dSToby Isaac } 33419566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 3342367003a6SStefano Zampini } else { 33439566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 3344f30e825dSToby Isaac } 33459566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(VecGetValues(fineVec, dof, pInd, pVal)); 33468d2f55e7SToby Isaac } 33478d2f55e7SToby Isaac } 33489566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 33499566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 33508d2f55e7SToby Isaac } 3351f30e825dSToby Isaac 33529566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 33539566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 33549566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 3355f30e825dSToby Isaac 33566148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 33576148253fSToby Isaac MPI_Datatype threeInt; 33586148253fSToby Isaac PetscMPIInt rank; 33596148253fSToby Isaac PetscInt(*parentNodeAndIdCoarse)[3]; 33606148253fSToby Isaac PetscInt(*parentNodeAndIdFine)[3]; 33616148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 33626148253fSToby Isaac PetscSF pointSF, sfToParents; 33636148253fSToby Isaac const PetscInt *ilocal; 33646148253fSToby Isaac const PetscSFNode *iremote; 33656148253fSToby Isaac PetscSFNode *iremoteToParents; 33666148253fSToby Isaac PetscInt *ilocalToParents; 33676148253fSToby Isaac 33689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)coarse), &rank)); 33699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &threeInt)); 33709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&threeInt)); 33719566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndC - pStartC, &parentNodeAndIdCoarse, pEndF - pStartF, &parentNodeAndIdFine)); 33729566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(coarse, &pointSF)); 33739566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &nleaves, &ilocal, &iremote)); 33746148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 33756148253fSToby Isaac PetscInt parent, childId; 33769566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(coarse, p, &parent, &childId)); 33776148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 33786148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 33796148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 33806148253fSToby Isaac if (nleaves > 0) { 33816148253fSToby Isaac PetscInt leaf = -1; 33826148253fSToby Isaac 33836148253fSToby Isaac if (ilocal) { 33849566063dSJacob Faibussowitsch PetscCall(PetscFindInt(parent, nleaves, ilocal, &leaf)); 33859371c9d4SSatish Balay } else { 33866148253fSToby Isaac leaf = p - pStartC; 33876148253fSToby Isaac } 33886148253fSToby Isaac if (leaf >= 0) { 33896148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 33906148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 33916148253fSToby Isaac } 33926148253fSToby Isaac } 33936148253fSToby Isaac } 33946148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 33956148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 33966148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 33976148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 33986148253fSToby Isaac } 33999566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 34009566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 34016148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3402f30e825dSToby Isaac PetscInt dof; 3403f30e825dSToby Isaac 34049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &dof)); 3405f30e825dSToby Isaac if (dof) { 3406f30e825dSToby Isaac PetscInt off; 3407f30e825dSToby Isaac 34089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3409c921d74cSToby Isaac if (gatheredIndices) { 3410c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3411c921d74cSToby Isaac } else if (gatheredValues) { 3412c921d74cSToby Isaac leafVals[off] = (PetscScalar)PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3413c921d74cSToby Isaac } 3414f30e825dSToby Isaac } 3415ad540459SPierre Jolivet if (parentNodeAndIdFine[p - pStartF][0] >= 0) nleavesToParents++; 34166148253fSToby Isaac } 34179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &ilocalToParents)); 34189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &iremoteToParents)); 34196148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 34206148253fSToby Isaac if (parentNodeAndIdFine[p - pStartF][0] >= 0) { 34216148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 34226148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p - pStartF][0]; 34236148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p - pStartF][1]; 34246148253fSToby Isaac nleavesToParents++; 34256148253fSToby Isaac } 34266148253fSToby Isaac } 34279566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)coarse), &sfToParents)); 34289566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfToParents, pEndC - pStartC, nleavesToParents, ilocalToParents, PETSC_OWN_POINTER, iremoteToParents, PETSC_OWN_POINTER)); 34299566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34306148253fSToby Isaac 34316148253fSToby Isaac coarseToFineEmbedded = sfToParents; 34326148253fSToby Isaac 34339566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentNodeAndIdCoarse, parentNodeAndIdFine)); 34349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&threeInt)); 34356148253fSToby Isaac } 3436f30e825dSToby Isaac 34376148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 34386148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 34396148253fSToby Isaac PetscSF sfDofsOnly; 34406148253fSToby Isaac 34416148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 34429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3444ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 34456148253fSToby Isaac } 34469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 34476148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 34489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3450ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = p - pStartC; 34516148253fSToby Isaac } 34529566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly)); 34539566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34549566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 34556148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 34566148253fSToby Isaac } 3457f30e825dSToby Isaac 34586148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 34599566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(coarseToFineEmbedded, &rootDegrees)); 34609566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(coarseToFineEmbedded, &rootDegrees)); 34619566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &multiRootSec)); 34629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(multiRootSec, pStartC, pEndC)); 346348a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionSetDof(multiRootSec, p, rootDegrees[p - pStartC])); 34649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(multiRootSec)); 34659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(multiRootSec, &numMulti)); 34669566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 3467f30e825dSToby Isaac { /* distribute the leaf section */ 3468f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3469f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 34708d2f55e7SToby Isaac 34719566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(coarseToFineEmbedded, &multi)); 34729566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(multi, &multiInv)); 34739566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(multiInv, leafIndicesSec, &remoteOffsets, rootIndicesSec)); 34749566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(multiInv, leafIndicesSec, remoteOffsets, rootIndicesSec, &indicesSF)); 34759566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 34769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&multiInv)); 34779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 3478c921d74cSToby Isaac if (gatheredIndices) { 34799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootInds)); 34809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 34819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 3482c921d74cSToby Isaac } 3483c921d74cSToby Isaac if (gatheredValues) { 34849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootVals)); 34859566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 34869566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 3487c921d74cSToby Isaac } 34889566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 34898d2f55e7SToby Isaac } 34909566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 34919566063dSJacob Faibussowitsch PetscCall(PetscFree(leafInds)); 34929566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVals)); 34939566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 3494c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3495c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3496c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3497c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 34983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3499ebf164c7SToby Isaac } 3500ebf164c7SToby Isaac 3501d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3502d71ae5a4SJacob Faibussowitsch { 3503ebf164c7SToby Isaac DM refTree; 3504c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3505ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3506ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3507ebf164c7SToby Isaac PetscSection cSecRef; 3508277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd; 3509ebf164c7SToby Isaac Mat injRef; 3510c921d74cSToby Isaac PetscInt numFields, maxDof; 3511ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3512ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3513ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3514ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3515ebf164c7SToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3516ebf164c7SToby Isaac 3517ebf164c7SToby Isaac PetscFunctionBegin; 3518ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 35199566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 3520d3a532e9SStefano Zampini PetscCall(DMCopyDisc(coarse, refTree)); 3521d3a532e9SStefano Zampini PetscCall(DMSetLocalSection(refTree, NULL)); 3522d3a532e9SStefano Zampini PetscCall(DMSetDefaultConstraints(refTree, NULL, NULL, NULL)); 35239566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 35249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 35259566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 3526ebf164c7SToby Isaac 35279566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 35289566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 35299566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 35309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 35319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 35329566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 35339566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 35349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 3535ebf164c7SToby Isaac { 3536ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 35379566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 3538ebf164c7SToby Isaac } 3539ebf164c7SToby Isaac 35409566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, childIds, NULL, numFields, offsets, &multiRootSec, &rootIndicesSec, &rootIndices, NULL)); 35418d2f55e7SToby Isaac 35429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &parentIndices)); 3543f30e825dSToby Isaac 3544f30e825dSToby Isaac /* count indices */ 35459566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 35469566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 35479566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 35489566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 35499566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 35509566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(rowEnd - rowStart, &nnzD, rowEnd - rowStart, &nnzO)); 3551f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3552f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 35538d2f55e7SToby Isaac 35549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 35559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3556f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 35579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 35588d2f55e7SToby Isaac 35598d2f55e7SToby Isaac rowOffsets[0] = 0; 3560f30e825dSToby Isaac offsetsCopy[0] = 0; 35618d2f55e7SToby Isaac if (numFields) { 35628d2f55e7SToby Isaac PetscInt f; 35638d2f55e7SToby Isaac 3564f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3565f30e825dSToby Isaac PetscInt fDof; 35669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3567f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 35688d2f55e7SToby Isaac } 35699566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3570367003a6SStefano Zampini } else { 35719566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3572f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 35738d2f55e7SToby Isaac } 3574f30e825dSToby Isaac 35759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 35769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3577f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3578f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3579f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3580f30e825dSToby Isaac const PetscInt *childIndices; 3581f30e825dSToby Isaac 35829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 35839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3584f30e825dSToby Isaac childId = rootIndices[offset++]; 3585f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3586f30e825dSToby Isaac numIndices--; 3587f30e825dSToby Isaac 3588f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3589f30e825dSToby Isaac PetscInt i; 3590f30e825dSToby Isaac 3591f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3592f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3593f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3594f30e825dSToby Isaac if (rowIndex < 0) continue; 359508401ef6SPierre Jolivet PetscCheck(colIndex >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unconstrained fine and constrained coarse"); 3596a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3597f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 35989371c9d4SSatish Balay } else { 3599f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3600f30e825dSToby Isaac } 3601f30e825dSToby Isaac } 36029371c9d4SSatish Balay } else { 3603f30e825dSToby Isaac PetscInt parentId, f, lim; 3604f30e825dSToby Isaac 36059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3606f30e825dSToby Isaac 3607f30e825dSToby Isaac lim = PetscMax(1, numFields); 3608f30e825dSToby Isaac offsets[0] = 0; 36098d2f55e7SToby Isaac if (numFields) { 36108d2f55e7SToby Isaac PetscInt f; 3611f30e825dSToby Isaac 36128d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3613f30e825dSToby Isaac PetscInt fDof; 36149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3615f30e825dSToby Isaac 3616f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 36178d2f55e7SToby Isaac } 36189371c9d4SSatish Balay } else { 3619f30e825dSToby Isaac PetscInt cDof; 3620f30e825dSToby Isaac 36219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3622f30e825dSToby Isaac offsets[1] = cDof; 3623f30e825dSToby Isaac } 3624f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3625f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3626f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3627f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3628f30e825dSToby Isaac 3629f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3630f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3631f30e825dSToby Isaac 3632f30e825dSToby Isaac if (colIndex < 0) continue; 3633f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3634f30e825dSToby Isaac numD++; 36359371c9d4SSatish Balay } else { 3636f30e825dSToby Isaac numO++; 3637f30e825dSToby Isaac } 3638f30e825dSToby Isaac } 3639f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3640f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3641f30e825dSToby Isaac 3642f30e825dSToby Isaac if (rowIndex < 0) continue; 3643f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3644f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 36458d2f55e7SToby Isaac } 36468d2f55e7SToby Isaac } 36478d2f55e7SToby Isaac } 3648f30e825dSToby Isaac } 3649f30e825dSToby Isaac } 3650f30e825dSToby Isaac /* preallocate */ 36519566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, nnzD, nnzO, NULL, NULL)); 36529566063dSJacob Faibussowitsch PetscCall(PetscFree2(nnzD, nnzO)); 3653f30e825dSToby Isaac /* insert values */ 36549566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 3655f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3656f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3657f30e825dSToby Isaac 36589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 36599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3660f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 36619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 3662f30e825dSToby Isaac 3663f30e825dSToby Isaac rowOffsets[0] = 0; 3664f30e825dSToby Isaac offsetsCopy[0] = 0; 36658d2f55e7SToby Isaac if (numFields) { 36668d2f55e7SToby Isaac PetscInt f; 3667f30e825dSToby Isaac 36688d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3669f30e825dSToby Isaac PetscInt fDof; 36709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3671f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3672f30e825dSToby Isaac } 36739566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3674367003a6SStefano Zampini } else { 36759566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3676f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3677f30e825dSToby Isaac } 3678f30e825dSToby Isaac 36799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 36809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3681f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3682f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3683f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3684f30e825dSToby Isaac const PetscInt *childIndices; 3685f30e825dSToby Isaac 36869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 36879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3688f30e825dSToby Isaac childId = rootIndices[offset++]; 3689f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3690f30e825dSToby Isaac numIndices--; 3691f30e825dSToby Isaac 3692f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3693f30e825dSToby Isaac PetscInt i; 3694f30e825dSToby Isaac 369548a46eb9SPierre Jolivet for (i = 0; i < numIndices; i++) PetscCall(MatSetValue(mat, parentIndices[i], childIndices[i], 1., INSERT_VALUES)); 36969371c9d4SSatish Balay } else { 3697f30e825dSToby Isaac PetscInt parentId, f, lim; 36988d2f55e7SToby Isaac 36999566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3700f30e825dSToby Isaac 3701f30e825dSToby Isaac lim = PetscMax(1, numFields); 3702f30e825dSToby Isaac offsets[0] = 0; 37038d2f55e7SToby Isaac if (numFields) { 3704f30e825dSToby Isaac PetscInt f; 37058d2f55e7SToby Isaac 3706f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3707f30e825dSToby Isaac PetscInt fDof; 37089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3709f30e825dSToby Isaac 3710f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 37118d2f55e7SToby Isaac } 37129371c9d4SSatish Balay } else { 3713f30e825dSToby Isaac PetscInt cDof; 3714f30e825dSToby Isaac 37159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3716f30e825dSToby Isaac offsets[1] = cDof; 37178d2f55e7SToby Isaac } 3718f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3719f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3720f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3721f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3722f30e825dSToby Isaac 37239566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, rowOffsets[f + 1] - rowOffsets[f], rowIndices, offsets[f + 1] - offsets[f], colIndices, childMat, INSERT_VALUES)); 37248d2f55e7SToby Isaac } 37258d2f55e7SToby Isaac } 37268d2f55e7SToby Isaac } 37278d2f55e7SToby Isaac } 37289566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 37299566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 37309566063dSJacob Faibussowitsch PetscCall(PetscFree(parentIndices)); 37319566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 37329566063dSJacob Faibussowitsch PetscCall(PetscFree(rootIndices)); 37339566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 3734f30e825dSToby Isaac 37359566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 37369566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 37373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3738154bca37SToby Isaac } 373938fc2455SToby Isaac 3740d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 3741d71ae5a4SJacob Faibussowitsch { 374262095d54SToby Isaac PetscSF coarseToFineEmbedded; 374362095d54SToby Isaac PetscSection globalCoarse, globalFine; 374462095d54SToby Isaac PetscSection localCoarse, localFine; 374562095d54SToby Isaac PetscSection aSec, cSec; 374662095d54SToby Isaac PetscSection rootValuesSec; 374762095d54SToby Isaac PetscSection leafValuesSec; 374862095d54SToby Isaac PetscScalar *rootValues, *leafValues; 374962095d54SToby Isaac IS aIS; 375062095d54SToby Isaac const PetscInt *anchors; 375162095d54SToby Isaac Mat cMat; 375262095d54SToby Isaac PetscInt numFields; 3753412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd; 375462095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 375562095d54SToby Isaac PetscInt *maxChildIds; 375662095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 37570eb7e1eaSToby Isaac PetscFV fv = NULL; 37580eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 37590eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 37600eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 37610eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 376262095d54SToby Isaac 3763ebf164c7SToby Isaac PetscFunctionBegin; 37649566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 37659566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 37669566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(coarse, 0, &cellStart, &cellEnd)); 37679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 37689566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 37699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(coarse, &dim)); 377062095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 3771e4a60869SToby Isaac PetscInt nleaves, l; 3772e4a60869SToby Isaac const PetscInt *leaves; 377362095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 377462095d54SToby Isaac 37759566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 3776e4a60869SToby Isaac 3777e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 3778e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3779e4a60869SToby Isaac 37809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 3782ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 378362095d54SToby Isaac } 37849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 37854833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 3786e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3787e4a60869SToby Isaac 37889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 3790ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l; 379162095d54SToby Isaac } 37929566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 37939566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 379462095d54SToby Isaac } 379562095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 37969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 3797ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2; 37989566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 37999566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 380062095d54SToby Isaac 38019566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 38029566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 380362095d54SToby Isaac 38049566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 38059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 38069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 380762095d54SToby Isaac 38089566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 38099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 381062095d54SToby Isaac 381162095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 38129566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootValuesSec)); 38139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootValuesSec, pStartC, pEndC)); 38149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 381562095d54SToby Isaac { 381662095d54SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 38179566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &newOffsets, maxFields, &newOffsetsCopy, maxFields, &rowOffsets, maxFields, &numD, maxFields, &numO)); 381862095d54SToby Isaac } 38190eb7e1eaSToby Isaac if (grad) { 38200eb7e1eaSToby Isaac PetscInt i; 38210eb7e1eaSToby Isaac 38229566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeom, &cellDM)); 38239566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeom, &cellGeomArray)); 38249566063dSJacob Faibussowitsch PetscCall(VecGetDM(grad, &gradDM)); 38259566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(grad, &gradArray)); 38260eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1, numFields); i++) { 38270eb7e1eaSToby Isaac PetscObject obj; 38280eb7e1eaSToby Isaac PetscClassId id; 38290eb7e1eaSToby Isaac 38309566063dSJacob Faibussowitsch PetscCall(DMGetField(coarse, i, NULL, &obj)); 38319566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 38320eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 38330eb7e1eaSToby Isaac fv = (PetscFV)obj; 38349566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numFVcomps)); 38350eb7e1eaSToby Isaac fvField = i; 38360eb7e1eaSToby Isaac break; 38370eb7e1eaSToby Isaac } 38380eb7e1eaSToby Isaac } 38390eb7e1eaSToby Isaac } 384062095d54SToby Isaac 384162095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 384262095d54SToby Isaac PetscInt dof; 384362095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 384462095d54SToby Isaac PetscInt numValues = 0; 384562095d54SToby Isaac 38469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 3847ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 384862095d54SToby Isaac offsets[0] = 0; 384962095d54SToby Isaac newOffsets[0] = 0; 385062095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 385162095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 385262095d54SToby Isaac 38539566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 385462095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 385562095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 385662095d54SToby Isaac 38579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 385862095d54SToby Isaac numValues += clDof; 385962095d54SToby Isaac } 38609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 38619371c9d4SSatish Balay } else if (maxChildId == -1) { 38629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &numValues)); 386362095d54SToby Isaac } 386462095d54SToby Isaac /* we will pack the column indices with the field offsets */ 386578b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 38660eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 38670eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 38680eb7e1eaSToby Isaac } 38699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootValuesSec, p, numValues)); 387062095d54SToby Isaac } 38719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootValuesSec)); 387262095d54SToby Isaac { 387362095d54SToby Isaac PetscInt numRootValues; 387462095d54SToby Isaac const PetscScalar *coarseArray; 387562095d54SToby Isaac 38769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootValuesSec, &numRootValues)); 38779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootValues, &rootValues)); 38789566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecCoarseLocal, &coarseArray)); 387962095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 388062095d54SToby Isaac PetscInt numValues; 388162095d54SToby Isaac PetscInt pValOff; 388262095d54SToby Isaac PetscScalar *pVal; 388362095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 388462095d54SToby Isaac 38859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootValuesSec, p, &numValues)); 3886ad540459SPierre Jolivet if (!numValues) continue; 38879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootValuesSec, p, &pValOff)); 3888*f4f49eeaSPierre Jolivet pVal = &rootValues[pValOff]; 388962095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 38900eb7e1eaSToby Isaac PetscInt closureSize = numValues; 38919566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(coarse, NULL, vecCoarseLocal, p, &closureSize, &pVal)); 38920eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 3893193eb951SToby Isaac PetscFVCellGeom *cg; 38946dd00756SToby Isaac PetscScalar *gradVals = NULL; 38950eb7e1eaSToby Isaac PetscInt i; 38960eb7e1eaSToby Isaac 38970eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 38980eb7e1eaSToby Isaac 38999566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(cellDM, p, cellGeomArray, (void *)&cg)); 39000eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 39010eb7e1eaSToby Isaac pVal += dim; 39029566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRead(gradDM, p, gradArray, (void *)&gradVals)); 39030eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 39040eb7e1eaSToby Isaac } 39059371c9d4SSatish Balay } else if (maxChildId == -1) { 390678b7adb5SToby Isaac PetscInt lDof, lOff, i; 390778b7adb5SToby Isaac 39089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &lDof)); 39099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, p, &lOff)); 391078b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 391178b7adb5SToby Isaac } 391278b7adb5SToby Isaac } 39139566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecCoarseLocal, &coarseArray)); 39149566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 391562095d54SToby Isaac } 391662095d54SToby Isaac { 391762095d54SToby Isaac PetscSF valuesSF; 391862095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 391962095d54SToby Isaac 39209566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafValuesSec)); 39219566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootValuesSec, &remoteOffsetsValues, leafValuesSec)); 39229566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootValuesSec, remoteOffsetsValues, leafValuesSec, &valuesSF)); 39239566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 39249566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsValues)); 39259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafValuesSec, &numLeafValues)); 39269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeafValues, &leafValues)); 39279566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 39289566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 39299566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&valuesSF)); 39309566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 39319566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootValuesSec)); 393262095d54SToby Isaac } 39339566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 393462095d54SToby Isaac { 393562095d54SToby Isaac PetscInt maxDof; 393662095d54SToby Isaac PetscInt *rowIndices; 393762095d54SToby Isaac DM refTree; 393862095d54SToby Isaac PetscInt **refPointFieldN; 393962095d54SToby Isaac PetscScalar ***refPointFieldMats; 394062095d54SToby Isaac PetscSection refConSec, refAnSec; 39410eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, leafStart, leafEnd; 394262095d54SToby Isaac PetscScalar *pointWork; 394362095d54SToby Isaac 39449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 39459566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 39469566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 39479566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 39489566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(fine, refTree)); 39499566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 39509566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 39519566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 39529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 39539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafValuesSec, &leafStart, &leafEnd)); 39549566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(fine, 0, &cellStart, &cellEnd)); 39550eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 395662095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 395762095d54SToby Isaac PetscInt numValues, pValOff; 395862095d54SToby Isaac PetscInt childId; 395962095d54SToby Isaac const PetscScalar *pVal; 39600eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 396162095d54SToby Isaac 39629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 39639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &lDof)); 39649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 3965ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 39669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 39679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafValuesSec, p, &numValues)); 396862095d54SToby Isaac if (!numValues) continue; 39699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafValuesSec, p, &pValOff)); 397062095d54SToby Isaac pVal = &leafValues[pValOff]; 397162095d54SToby Isaac offsets[0] = 0; 397262095d54SToby Isaac offsetsCopy[0] = 0; 397362095d54SToby Isaac newOffsets[0] = 0; 397462095d54SToby Isaac newOffsetsCopy[0] = 0; 39754833aeb0SToby Isaac childId = cids[p - pStartF]; 397662095d54SToby Isaac if (numFields) { 397762095d54SToby Isaac PetscInt f; 397862095d54SToby Isaac for (f = 0; f < numFields; f++) { 397962095d54SToby Isaac PetscInt rowDof; 398062095d54SToby Isaac 39819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 398262095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 398362095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 398462095d54SToby Isaac /* TODO: closure indices */ 39859f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 398662095d54SToby Isaac } 39879566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 39889371c9d4SSatish Balay } else { 39894833aeb0SToby Isaac offsets[0] = 0; 39904833aeb0SToby Isaac offsets[1] = lDof; 39914833aeb0SToby Isaac newOffsets[0] = 0; 39924833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 39939566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 399462095d54SToby Isaac } 399562095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 39969566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numValues, rowIndices, pVal, INSERT_VALUES)); 399762095d54SToby Isaac } else { 399862095d54SToby Isaac PetscInt f; 399962095d54SToby Isaac 400078b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 400178b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 400278b7adb5SToby Isaac fvGradData = &pVal[numValues]; 400378b7adb5SToby Isaac } 400462095d54SToby Isaac for (f = 0; f < PetscMax(1, numFields); f++) { 400562095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 400662095d54SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 400762095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 400862095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 400962095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 401062095d54SToby Isaac PetscInt i, j; 401162095d54SToby Isaac 4012708c7f19SToby Isaac #if 0 401363a3b9bcSJacob 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)); 4014708c7f19SToby Isaac #endif 401562095d54SToby Isaac for (i = 0; i < numRows; i++) { 401662095d54SToby Isaac PetscScalar val = 0.; 4017ad540459SPierre Jolivet for (j = 0; j < numCols; j++) val += childMat[i * numCols + j] * cVal[j]; 401862095d54SToby Isaac rVal[i] = val; 401962095d54SToby Isaac } 40200eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 40210eb7e1eaSToby Isaac PetscReal centroid[3]; 40220eb7e1eaSToby Isaac PetscScalar diff[3]; 40230eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 40240eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 40250eb7e1eaSToby Isaac 40269566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(fine, p, NULL, centroid, NULL)); 4027ad540459SPierre Jolivet for (i = 0; i < dim; i++) diff[i] = centroid[i] - parentCentroid[i]; 40280eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 40290eb7e1eaSToby Isaac PetscScalar val = 0.; 40300eb7e1eaSToby Isaac 4031ad540459SPierre Jolivet for (j = 0; j < dim; j++) val += gradient[dim * i + j] * diff[j]; 40320eb7e1eaSToby Isaac rVal[i] += val; 40330eb7e1eaSToby Isaac } 40340eb7e1eaSToby Isaac } 40359566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numRows, &rowIndices[offsets[f]], rVal, INSERT_VALUES)); 403662095d54SToby Isaac } 403762095d54SToby Isaac } 403862095d54SToby Isaac } 40399566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 40409566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 40419566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 404262095d54SToby Isaac } 40439566063dSJacob Faibussowitsch PetscCall(PetscFree(leafValues)); 40449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafValuesSec)); 40459566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 40469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 40473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4048ebf164c7SToby Isaac } 4049ebf164c7SToby Isaac 4050d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4051d71ae5a4SJacob Faibussowitsch { 4052c921d74cSToby Isaac DM refTree; 4053c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4054c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4055c921d74cSToby Isaac PetscSection localCoarse, localFine; 4056c921d74cSToby Isaac PetscSection cSecRef; 4057c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4058d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4059c921d74cSToby Isaac Mat injRef; 4060c921d74cSToby Isaac PetscInt numFields, maxDof; 4061c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4062c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4063c921d74cSToby Isaac PetscLayout rowMap, colMap; 4064c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4065c921d74cSToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4066c921d74cSToby Isaac 4067ebf164c7SToby Isaac PetscFunctionBegin; 4068c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 40699566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40709566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecCoarse, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40719566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 40729566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(coarse, refTree)); 40739566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 40749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 40759566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 4076c921d74cSToby Isaac 40779566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 40789566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 40799566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 40809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 40819566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 40829566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 40839566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 40849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 4085c921d74cSToby Isaac { 4086c921d74cSToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 40879566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 4088c921d74cSToby Isaac } 4089c921d74cSToby Isaac 40909566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, cids, vecFine, numFields, offsets, &multiRootSec, &rootIndicesSec, NULL, &rootValues)); 4091c921d74cSToby Isaac 40929566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxDof, &parentIndices, maxDof, &parentValues)); 4093c921d74cSToby Isaac 4094c921d74cSToby Isaac /* count indices */ 40959566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecFine, &colMap)); 40969566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecCoarse, &rowMap)); 40979566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 40989566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 40999566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 41009566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 4101c921d74cSToby Isaac /* insert values */ 41029566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 4103c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4104c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 410578b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4106c921d74cSToby Isaac 41079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 41089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 4109c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 41109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &dof)); 41119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 4112c921d74cSToby Isaac 4113c921d74cSToby Isaac rowOffsets[0] = 0; 4114c921d74cSToby Isaac offsetsCopy[0] = 0; 4115c921d74cSToby Isaac if (numFields) { 4116c921d74cSToby Isaac PetscInt f; 4117c921d74cSToby Isaac 4118c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4119c921d74cSToby Isaac PetscInt fDof; 41209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 4121c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4122c921d74cSToby Isaac } 41239566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 4124367003a6SStefano Zampini } else { 41259566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 4126c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4127c921d74cSToby Isaac } 4128c921d74cSToby Isaac 41299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 41309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 4131c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 41322f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4133c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4134c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4135c921d74cSToby Isaac const PetscScalar *childValues; 4136c921d74cSToby Isaac 41379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 41389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 4139c921d74cSToby Isaac childId = (PetscInt)PetscRealPart(rootValues[offset++]); 4140c921d74cSToby Isaac childValues = &rootValues[offset]; 4141c921d74cSToby Isaac numIndices--; 4142c921d74cSToby Isaac 4143c921d74cSToby Isaac if (childId == -2) { /* skip */ 4144c921d74cSToby Isaac continue; 4145c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 41462f65e181SToby Isaac PetscInt m; 41472f65e181SToby Isaac 414878b7adb5SToby Isaac contribute = PETSC_TRUE; 41492f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4150beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4151d3bc4906SToby Isaac PetscInt parentId, f, lim; 4152d3bc4906SToby Isaac 415378b7adb5SToby Isaac contribute = PETSC_TRUE; 41549566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 4155d3bc4906SToby Isaac 4156d3bc4906SToby Isaac lim = PetscMax(1, numFields); 4157d3bc4906SToby Isaac offsets[0] = 0; 4158d3bc4906SToby Isaac if (numFields) { 4159d3bc4906SToby Isaac PetscInt f; 4160d3bc4906SToby Isaac 4161d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4162d3bc4906SToby Isaac PetscInt fDof; 41639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 4164d3bc4906SToby Isaac 4165d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4166d3bc4906SToby Isaac } 41679371c9d4SSatish Balay } else { 4168d3bc4906SToby Isaac PetscInt cDof; 4169d3bc4906SToby Isaac 41709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 4171d3bc4906SToby Isaac offsets[1] = cDof; 4172d3bc4906SToby Isaac } 4173d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4174d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4175d3bc4906SToby Isaac PetscInt n = offsets[f + 1] - offsets[f]; 4176e328ff09SToby Isaac PetscInt m = rowOffsets[f + 1] - rowOffsets[f]; 4177d3bc4906SToby Isaac PetscInt i, j; 4178d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4179d3bc4906SToby Isaac 4180e328ff09SToby Isaac for (i = 0; i < m; i++) { 4181d3bc4906SToby Isaac PetscScalar val = 0.; 4182ad540459SPierre Jolivet for (j = 0; j < n; j++) val += childMat[n * i + j] * colValues[j]; 4183e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val; 4184d3bc4906SToby Isaac } 4185d3bc4906SToby Isaac } 4186c921d74cSToby Isaac } 4187c921d74cSToby Isaac } 41889566063dSJacob Faibussowitsch if (contribute) PetscCall(VecSetValues(vecCoarse, dof, parentIndices, parentValues, INSERT_VALUES)); 4189c921d74cSToby Isaac } 41909566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 41919566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 41929566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentIndices, parentValues)); 41939566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 41949566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 41959566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 41963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4197ebf164c7SToby Isaac } 4198ebf164c7SToby Isaac 4199ff1f73f7SToby Isaac /*@ 4200ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4201ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4202ff1f73f7SToby Isaac coarsening and refinement at the same time. 4203ff1f73f7SToby Isaac 420420f4b53cSBarry Smith Collective 4205ff1f73f7SToby Isaac 4206ff1f73f7SToby Isaac Input Parameters: 4207a1cb98faSBarry Smith + dmIn - The `DMPLEX` mesh for the input vector 420820f4b53cSBarry Smith . dmOut - The second `DMPLEX` mesh 4209ff1f73f7SToby Isaac . vecIn - The input vector 421020f4b53cSBarry Smith . sfRefine - A star forest indicating points in the mesh `dmIn` (roots in the star forest) that are parents to points in 421120f4b53cSBarry Smith the mesh `dmOut` (leaves in the star forest), i.e. where `dmOut` is more refined than `dmIn` 421220f4b53cSBarry Smith . sfCoarsen - A star forest indicating points in the mesh `dmOut` (roots in the star forest) that are parents to points in 421320f4b53cSBarry Smith the mesh `dmIn` (leaves in the star forest), i.e. where `dmOut` is more coarsened than `dmIn` 421420f4b53cSBarry Smith . cidsRefine - The childIds of the points in `dmOut`. These childIds relate back to the reference tree: childid[j] = k implies 421520f4b53cSBarry Smith that mesh point j of `dmOut` was refined from a point in `dmIn` just as the mesh point k in the reference 421620f4b53cSBarry Smith tree was refined from its parent. childid[j] = -1 indicates that the point j in `dmOut` is exactly 421720f4b53cSBarry Smith equivalent to its root in `dmIn`, so no interpolation is necessary. childid[j] = -2 indicates that this 421820f4b53cSBarry Smith point j in `dmOut` is not a leaf of `sfRefine`. 421920f4b53cSBarry Smith . cidsCoarsen - The childIds of the points in `dmIn`. These childIds relate back to the reference tree: childid[j] = k implies 422020f4b53cSBarry Smith that mesh point j of dmIn coarsens to a point in `dmOut` just as the mesh point k in the reference 422120f4b53cSBarry Smith tree coarsens to its parent. childid[j] = -2 indicates that point j in `dmOut` is not a leaf in `sfCoarsen`. 422220f4b53cSBarry Smith . useBCs - `PETSC_TRUE` indicates that boundary values should be inserted into `vecIn` before transfer. 4223ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4224ff1f73f7SToby Isaac 42252fe279fdSBarry Smith Output Parameter: 42268966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred 422720f4b53cSBarry Smith projection of `vecIn` from `dmIn` to `dmOut`. Note that any field discretized with a `PetscFV` finite volume 4228ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4229ff1f73f7SToby Isaac coarse points to fine points. 4230ff1f73f7SToby Isaac 4231ff1f73f7SToby Isaac Level: developer 4232ff1f73f7SToby Isaac 42331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSF`, `Vec`, `PetscFV`, `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()`, `PetscFVGetComputeGradients()` 4234ff1f73f7SToby Isaac @*/ 4235d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) 4236d71ae5a4SJacob Faibussowitsch { 423738fc2455SToby Isaac PetscFunctionBegin; 42389566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0)); 4239ff1f73f7SToby Isaac if (sfRefine) { 4240fbfa57b9SToby Isaac Vec vecInLocal; 42410eb7e1eaSToby Isaac DM dmGrad = NULL; 42420eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4243fbfa57b9SToby Isaac 42449566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecInLocal)); 42459566063dSJacob Faibussowitsch PetscCall(VecSet(vecInLocal, 0.0)); 42460eb7e1eaSToby Isaac { 42470eb7e1eaSToby Isaac PetscInt numFields, i; 42480eb7e1eaSToby Isaac 42499566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dmIn, &numFields)); 42500eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 42510eb7e1eaSToby Isaac PetscObject obj; 42520eb7e1eaSToby Isaac PetscClassId classid; 42530eb7e1eaSToby Isaac 42549566063dSJacob Faibussowitsch PetscCall(DMGetField(dmIn, i, NULL, &obj)); 42559566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &classid)); 42560eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 42579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dmIn, (PetscFV)obj, &cellGeom, &faceGeom, &dmGrad)); 42580eb7e1eaSToby Isaac break; 42590eb7e1eaSToby Isaac } 42600eb7e1eaSToby Isaac } 42610eb7e1eaSToby Isaac } 42621baa6e33SBarry Smith if (useBCs) PetscCall(DMPlexInsertBoundaryValues(dmIn, PETSC_TRUE, vecInLocal, time, faceGeom, cellGeom, NULL)); 42639566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42649566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42650eb7e1eaSToby Isaac if (dmGrad) { 42669566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmGrad, &grad)); 42679566063dSJacob Faibussowitsch PetscCall(DMPlexReconstructGradientsFVM(dmIn, vecInLocal, grad)); 42680eb7e1eaSToby Isaac } 42699566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree_Interpolate(dmIn, vecInLocal, dmOut, vecOut, sfRefine, cidsRefine, grad, cellGeom)); 42709566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecInLocal)); 427148a46eb9SPierre Jolivet if (dmGrad) PetscCall(DMRestoreGlobalVector(dmGrad, &grad)); 4272ebf164c7SToby Isaac } 42731baa6e33SBarry Smith if (sfCoarsen) PetscCall(DMPlexTransferVecTree_Inject(dmIn, vecIn, dmOut, vecOut, sfCoarsen, cidsCoarsen)); 42749566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(vecOut)); 42759566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(vecOut)); 42763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 427738fc2455SToby Isaac } 4278