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