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: 15d6a7ad0dSToby Isaac + dm - The DMPlex object 16d6a7ad0dSToby Isaac - ref - The reference tree DMPlex object 17d6a7ad0dSToby Isaac 180b7167a0SToby Isaac Level: intermediate 19d6a7ad0dSToby Isaac 20db781477SPatrick Sanan .seealso: `DMPlexGetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()` 21d6a7ad0dSToby Isaac @*/ 22*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 23*d71ae5a4SJacob 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: 41d6a7ad0dSToby Isaac . dm - The DMPlex object 42d6a7ad0dSToby Isaac 437a7aea1fSJed Brown Output Parameters: 44d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 45d6a7ad0dSToby Isaac 460b7167a0SToby Isaac Level: intermediate 47d6a7ad0dSToby Isaac 48db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()` 49d6a7ad0dSToby Isaac @*/ 50*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 51*d71ae5a4SJacob 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 61*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 62*d71ae5a4SJacob 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: 178dcbd3bf7SToby Isaac + 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 191db781477SPatrick Sanan .seealso: `DMPlexGetReferenceTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetTree()` 192dcbd3bf7SToby Isaac @*/ 193*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 194*d71ae5a4SJacob 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 206*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceTree_SetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 207*d71ae5a4SJacob 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 213*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 214*d71ae5a4SJacob 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: 4300e2cc29aSToby Isaac . ref - the reference tree DMPlex object 4310e2cc29aSToby Isaac 4320e2cc29aSToby Isaac Level: intermediate 4330e2cc29aSToby Isaac 434db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()` 4350e2cc29aSToby Isaac @*/ 436*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 437*d71ae5a4SJacob 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 466*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 467*d71ae5a4SJacob 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 520*d71ae5a4SJacob Faibussowitsch static PetscErrorCode AnchorsFlatten(PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 521*d71ae5a4SJacob 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 650*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 651*d71ae5a4SJacob 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 755*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTrueSupportSize(DM dm, PetscInt p, PetscInt *dof, PetscInt *numTrueSupp) 756*d71ae5a4SJacob 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 782*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 783*d71ae5a4SJacob 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 894*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 895*d71ae5a4SJacob 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: 9830b7167a0SToby Isaac + 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 992db781477SPatrick Sanan .seealso: `DMPlexGetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 9930b7167a0SToby Isaac @*/ 994*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 995*d71ae5a4SJacob 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: 1006b2f41788SToby Isaac . 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 1019db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 1020b2f41788SToby Isaac @*/ 1021*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1022*d71ae5a4SJacob 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: 1039d961a43aSToby Isaac + 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 1049db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeChildren()` 1050d961a43aSToby Isaac @*/ 1051*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1052*d71ae5a4SJacob 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: 1081d961a43aSToby Isaac + 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 1090d961a43aSToby Isaac Fortran Notes: 1091d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1092d961a43aSToby Isaac include petsc.h90 in your code. 1093d961a43aSToby Isaac 1094db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeParent()` 1095d961a43aSToby Isaac @*/ 1096*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1097*d71ae5a4SJacob Faibussowitsch { 1098d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1099d961a43aSToby Isaac PetscSection childSec; 1100d961a43aSToby Isaac PetscInt dof = 0; 1101d961a43aSToby Isaac 1102d961a43aSToby Isaac PetscFunctionBegin; 1103d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1104d961a43aSToby Isaac childSec = mesh->childSection; 110548a46eb9SPierre Jolivet if (childSec && point >= childSec->pStart && point < childSec->pEnd) PetscCall(PetscSectionGetDof(childSec, point, &dof)); 1106d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1107d961a43aSToby Isaac if (children) { 1108d961a43aSToby Isaac if (dof) { 1109d961a43aSToby Isaac PetscInt off; 1110d961a43aSToby Isaac 11119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, point, &off)); 1112d961a43aSToby Isaac *children = &mesh->children[off]; 11139371c9d4SSatish Balay } else { 1114d961a43aSToby Isaac *children = NULL; 1115d961a43aSToby Isaac } 1116d961a43aSToby Isaac } 1117d961a43aSToby Isaac PetscFunctionReturn(0); 1118d961a43aSToby Isaac } 11190c37af3bSToby Isaac 1120*d71ae5a4SJacob 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) 1121*d71ae5a4SJacob Faibussowitsch { 112252a3aeb4SToby Isaac PetscInt f, b, p, c, offset, qPoints; 1123b3a4bf2aSToby Isaac 1124b3a4bf2aSToby Isaac PetscFunctionBegin; 11259566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(space, nPoints, points, work, NULL, NULL)); 112652a3aeb4SToby Isaac for (f = 0, offset = 0; f < nFunctionals; f++) { 112752a3aeb4SToby Isaac qPoints = pointsPerFn[f]; 112852a3aeb4SToby Isaac for (b = 0; b < nBasis; b++) { 1129b3a4bf2aSToby Isaac PetscScalar val = 0.; 1130b3a4bf2aSToby Isaac 113152a3aeb4SToby Isaac for (p = 0; p < qPoints; p++) { 1132ad540459SPierre Jolivet for (c = 0; c < nComps; c++) val += work[((offset + p) * nBasis + b) * nComps + c] * weights[(offset + p) * nComps + c]; 113352a3aeb4SToby Isaac } 11349566063dSJacob Faibussowitsch PetscCall(MatSetValue(basisAtPoints, b, f, val, INSERT_VALUES)); 1135b3a4bf2aSToby Isaac } 1136b3a4bf2aSToby Isaac offset += qPoints; 1137b3a4bf2aSToby Isaac } 11389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(basisAtPoints, MAT_FINAL_ASSEMBLY)); 11399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(basisAtPoints, MAT_FINAL_ASSEMBLY)); 1140b3a4bf2aSToby Isaac PetscFunctionReturn(0); 1141b3a4bf2aSToby Isaac } 1142b3a4bf2aSToby Isaac 1143*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 1144*d71ae5a4SJacob Faibussowitsch { 11450c37af3bSToby Isaac PetscDS ds; 11460c37af3bSToby Isaac PetscInt spdim; 11470c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 11480c37af3bSToby Isaac const PetscInt *anchors; 1149f7c74593SToby Isaac PetscSection aSec; 11500c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 11510c37af3bSToby Isaac IS aIS; 11520c37af3bSToby Isaac 11530c37af3bSToby Isaac PetscFunctionBegin; 11549566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11559566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 11569566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 11579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 11589566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 11599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 11609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &conStart, &conEnd)); 11619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &spdim)); 11629566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(spdim, &v0, spdim, &v0parent, spdim, &vtmp, spdim * spdim, &J, spdim * spdim, &Jparent, spdim * spdim, &invJparent)); 11630c37af3bSToby Isaac 11640c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 11650dd1b1feSToby Isaac PetscObject disc; 11660dd1b1feSToby Isaac PetscClassId id; 1167b3a4bf2aSToby Isaac PetscSpace bspace; 1168b3a4bf2aSToby Isaac PetscDualSpace dspace; 11699c3cf19fSMatthew G. Knepley PetscInt i, j, k, nPoints, Nc, offset; 117052a3aeb4SToby Isaac PetscInt fSize, maxDof; 1171b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 11721683a169SBarry Smith PetscScalar *scwork; 11731683a169SBarry Smith const PetscScalar *X; 11742c44ad04SToby Isaac PetscInt *sizes, *workIndRow, *workIndCol; 11750c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 11762c44ad04SToby Isaac const PetscInt *numDof = NULL; 1177085f0adfSToby Isaac const PetscInt ***perms = NULL; 1178085f0adfSToby Isaac const PetscScalar ***flips = NULL; 11790c37af3bSToby Isaac 11809566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 11819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &id)); 11820dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1183b3a4bf2aSToby Isaac PetscFE fe = (PetscFE)disc; 1184b3a4bf2aSToby Isaac 11859566063dSJacob Faibussowitsch PetscCall(PetscFEGetBasisSpace(fe, &bspace)); 11869566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dspace)); 11879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize)); 11889566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc)); 11899371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) { 1190b3a4bf2aSToby Isaac PetscFV fv = (PetscFV)disc; 1191b3a4bf2aSToby Isaac 11929566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc)); 11939566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)fv), &bspace)); 11949566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(bspace, PETSCSPACEPOLYNOMIAL)); 11959566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(bspace, 0, PETSC_DETERMINE)); 11969566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(bspace, Nc)); 11979566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(bspace, spdim)); 11989566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(bspace)); 11999566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv, &dspace)); 12009566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize)); 12019371c9d4SSatish Balay } else SETERRQ(PetscObjectComm(disc), PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 12029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dspace, &numDof)); 1203ad540459SPierre Jolivet for (i = 0, maxDof = 0; i <= spdim; i++) maxDof = PetscMax(maxDof, numDof[i]); 12049566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dspace, &perms, &flips)); 12050dd1b1feSToby Isaac 12069566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &Amat)); 12079566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Amat, fSize, fSize, fSize, fSize)); 12089566063dSJacob Faibussowitsch PetscCall(MatSetType(Amat, MATSEQDENSE)); 12099566063dSJacob Faibussowitsch PetscCall(MatSetUp(Amat)); 12109566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Bmat)); 12119566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Xmat)); 12120c37af3bSToby Isaac nPoints = 0; 12130c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 121452a3aeb4SToby Isaac PetscInt qPoints, thisNc; 12150c37af3bSToby Isaac PetscQuadrature quad; 12160c37af3bSToby Isaac 12179566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad)); 12189566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &thisNc, &qPoints, NULL, NULL)); 121963a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 12200c37af3bSToby Isaac nPoints += qPoints; 12210c37af3bSToby Isaac } 12229566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(fSize, &sizes, nPoints * Nc, &weights, spdim * nPoints, &pointsRef, spdim * nPoints, &pointsReal, nPoints * fSize * Nc, &work, maxDof, &workIndRow, maxDof, &workIndCol)); 12239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &scwork)); 12240c37af3bSToby Isaac offset = 0; 12250c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12260c37af3bSToby Isaac PetscInt qPoints; 12270c37af3bSToby Isaac const PetscReal *p, *w; 12280c37af3bSToby Isaac PetscQuadrature quad; 12290c37af3bSToby Isaac 12309566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad)); 12319566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &qPoints, &p, &w)); 12329566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(weights + Nc * offset, w, Nc * qPoints)); 12339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pointsRef + spdim * offset, p, spdim * qPoints)); 1234b3a4bf2aSToby Isaac sizes[i] = qPoints; 12350c37af3bSToby Isaac offset += qPoints; 12360c37af3bSToby Isaac } 12379566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsRef, weights, work, Amat)); 12389566063dSJacob Faibussowitsch PetscCall(MatLUFactor(Amat, NULL, NULL, NULL)); 12390c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 12400c37af3bSToby Isaac PetscInt parent; 12410c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 12420c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 12430c37af3bSToby Isaac 12449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, c, &parent, NULL)); 12450c37af3bSToby Isaac if (parent == c) continue; 12469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 12470c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12480c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12490c37af3bSToby Isaac PetscInt conDof; 12500c37af3bSToby Isaac 12510c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1252085f0adfSToby Isaac if (numFields) { 12539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof)); 12549371c9d4SSatish Balay } else { 12559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof)); 12560c37af3bSToby Isaac } 12570c37af3bSToby Isaac if (conDof) break; 12580c37af3bSToby Isaac } 12590c37af3bSToby Isaac if (i == closureSize) { 12609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 12610c37af3bSToby Isaac continue; 12620c37af3bSToby Isaac } 12630c37af3bSToby Isaac 12649566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ)); 12659566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent)); 12660c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1267c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 1268c330f8ffSToby Isaac 1269c330f8ffSToby Isaac CoordinatesRefToReal(spdim, spdim, xi0, v0, J, &pointsRef[i * spdim], vtmp); 1270c330f8ffSToby Isaac CoordinatesRealToRef(spdim, spdim, xi0, v0parent, invJparent, vtmp, &pointsReal[i * spdim]); 12710c37af3bSToby Isaac } 12729566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsReal, weights, work, Bmat)); 12739566063dSJacob Faibussowitsch PetscCall(MatMatSolve(Amat, Bmat, Xmat)); 12749566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Xmat, &X)); 12759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP)); 12769566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(closureSize + 1, &childOffsets, closureSizeP + 1, &parentOffsets)); 12770c37af3bSToby Isaac childOffsets[0] = 0; 12780c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12790c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12800c37af3bSToby Isaac PetscInt dof; 12810c37af3bSToby Isaac 1282085f0adfSToby Isaac if (numFields) { 12839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 12849371c9d4SSatish Balay } else { 12859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 12860c37af3bSToby Isaac } 128752a3aeb4SToby Isaac childOffsets[i + 1] = childOffsets[i] + dof; 12880c37af3bSToby Isaac } 12890c37af3bSToby Isaac parentOffsets[0] = 0; 12900c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 12910c37af3bSToby Isaac PetscInt p = closureP[2 * i]; 12920c37af3bSToby Isaac PetscInt dof; 12930c37af3bSToby Isaac 1294085f0adfSToby Isaac if (numFields) { 12959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 12969371c9d4SSatish Balay } else { 12979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 12980c37af3bSToby Isaac } 129952a3aeb4SToby Isaac parentOffsets[i + 1] = parentOffsets[i] + dof; 13000c37af3bSToby Isaac } 13010c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13022c44ad04SToby Isaac PetscInt conDof, conOff, aDof, aOff, nWork; 13030c37af3bSToby Isaac PetscInt p = closure[2 * i]; 13040c37af3bSToby Isaac PetscInt o = closure[2 * i + 1]; 1305085f0adfSToby Isaac const PetscInt *perm; 1306085f0adfSToby Isaac const PetscScalar *flip; 13070c37af3bSToby Isaac 13080c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1309085f0adfSToby Isaac if (numFields) { 13109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof)); 13119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &conOff)); 13129371c9d4SSatish Balay } else { 13139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof)); 13149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &conOff)); 13150c37af3bSToby Isaac } 13160c37af3bSToby Isaac if (!conDof) continue; 1317085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL; 1318085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL; 13199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 13209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 13212c44ad04SToby Isaac nWork = childOffsets[i + 1] - childOffsets[i]; 13220c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 13230c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 13240c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 13250c37af3bSToby Isaac 1326085f0adfSToby Isaac if (numFields) { 13279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aSecDof)); 13289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aSecOff)); 13299371c9d4SSatish Balay } else { 13309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aSecDof)); 13319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aSecOff)); 13320c37af3bSToby Isaac } 13330c37af3bSToby Isaac if (!aSecDof) continue; 13340c37af3bSToby Isaac 13350c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 13360c37af3bSToby Isaac PetscInt q = closureP[2 * j]; 13370c37af3bSToby Isaac PetscInt oq = closureP[2 * j + 1]; 13382c44ad04SToby Isaac 13392c44ad04SToby Isaac if (q == a) { 134052a3aeb4SToby Isaac PetscInt r, s, nWorkP; 1341085f0adfSToby Isaac const PetscInt *permP; 1342085f0adfSToby Isaac const PetscScalar *flipP; 1343085f0adfSToby Isaac 1344085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL; 1345085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL; 13462c44ad04SToby Isaac nWorkP = parentOffsets[j + 1] - parentOffsets[j]; 13472c44ad04SToby Isaac /* get a copy of the child-to-anchor portion of the matrix, and transpose so that rows correspond to the 13481683a169SBarry Smith * child and columns correspond to the anchor: BUT the maxrix returned by MatDenseGetArrayRead() is 13492c44ad04SToby Isaac * column-major, so transpose-transpose = do nothing */ 13502c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1351ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] = X[fSize * (r + childOffsets[i]) + (s + parentOffsets[j])]; 13522c44ad04SToby Isaac } 1353ad540459SPierre Jolivet for (r = 0; r < nWork; r++) workIndRow[perm ? perm[r] : r] = conOff + r; 1354ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) workIndCol[permP ? permP[s] : s] = aSecOff + s; 13552c44ad04SToby Isaac if (flip) { 13562c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1357ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] *= flip[r]; 13582c44ad04SToby Isaac } 13592c44ad04SToby Isaac } 13602c44ad04SToby Isaac if (flipP) { 13612c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 1362ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] *= flipP[s]; 13632c44ad04SToby Isaac } 13642c44ad04SToby Isaac } 13659566063dSJacob Faibussowitsch PetscCall(MatSetValues(cMat, nWork, workIndRow, nWorkP, workIndCol, scwork, INSERT_VALUES)); 13662c44ad04SToby Isaac break; 13670c37af3bSToby Isaac } 13680c37af3bSToby Isaac } 13690c37af3bSToby Isaac } 13700c37af3bSToby Isaac } 13719566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Xmat, &X)); 13729566063dSJacob Faibussowitsch PetscCall(PetscFree2(childOffsets, parentOffsets)); 13739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 13749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP)); 13750c37af3bSToby Isaac } 13769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Amat)); 13779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bmat)); 13789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Xmat)); 13799566063dSJacob Faibussowitsch PetscCall(PetscFree(scwork)); 13809566063dSJacob Faibussowitsch PetscCall(PetscFree7(sizes, weights, pointsRef, pointsReal, work, workIndRow, workIndCol)); 138148a46eb9SPierre Jolivet if (id == PETSCFV_CLASSID) PetscCall(PetscSpaceDestroy(&bspace)); 13820c37af3bSToby Isaac } 13839566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 13849566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 13859566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJparent)); 13869566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 13870c37af3bSToby Isaac 13880c37af3bSToby Isaac PetscFunctionReturn(0); 13890c37af3bSToby Isaac } 139095a0b26dSToby Isaac 1391*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 1392*d71ae5a4SJacob Faibussowitsch { 1393f7c74593SToby Isaac Mat refCmat; 139421968bf8SToby Isaac PetscDS ds; 1395085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 139621968bf8SToby Isaac PetscScalar ***refPointFieldMats; 139721968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 139821968bf8SToby Isaac IS refAnIS; 139921968bf8SToby Isaac const PetscInt *refAnchors; 1400085f0adfSToby Isaac const PetscInt **perms; 1401085f0adfSToby Isaac const PetscScalar **flips; 140295a0b26dSToby Isaac 140395a0b26dSToby Isaac PetscFunctionBegin; 14049566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 14059566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1406085f0adfSToby Isaac maxFields = PetscMax(1, numFields); 14079566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 14089566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 14099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(refAnIS, &refAnchors)); 14109566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 14119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 14129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 14139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldN)); 14149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 14159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 14169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 14179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxAnDof, &cols)); 141895a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 141995a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 142095a0b26dSToby Isaac 14219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 14229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 142395a0b26dSToby Isaac if (!pDof || parent == p) continue; 142495a0b26dSToby Isaac 14259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxFields, &refPointFieldMats[p - pRefStart])); 14269566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxFields, &refPointFieldN[p - pRefStart])); 14279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure)); 1428085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1429085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i; 143095a0b26dSToby Isaac 1431085f0adfSToby Isaac if (f < numFields) { 14329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 14339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 14349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips)); 1435085f0adfSToby Isaac } else { 14369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 14379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 14389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(refSection, closureSize, closure, &perms, &flips)); 143995a0b26dSToby Isaac } 144095a0b26dSToby Isaac 1441ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r; 144295a0b26dSToby Isaac numCols = 0; 144395a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 144495a0b26dSToby Isaac PetscInt q = closure[2 * i]; 144595a0b26dSToby Isaac PetscInt aDof, aOff, j; 1446085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 144795a0b26dSToby Isaac 1448085f0adfSToby Isaac if (numFields) { 14499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof)); 14509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff)); 14519371c9d4SSatish Balay } else { 14529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof)); 14539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff)); 145495a0b26dSToby Isaac } 145595a0b26dSToby Isaac 1456ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + (perm ? perm[j] : j); 145795a0b26dSToby Isaac } 145895a0b26dSToby Isaac refPointFieldN[p - pRefStart][f] = numCols; 14599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 14609566063dSJacob Faibussowitsch PetscCall(MatGetValues(refCmat, cDof, rows, numCols, cols, refPointFieldMats[p - pRefStart][f])); 1461085f0adfSToby Isaac if (flips) { 1462085f0adfSToby Isaac PetscInt colOff = 0; 1463085f0adfSToby Isaac 1464085f0adfSToby Isaac for (i = 0; i < closureSize; i++) { 1465085f0adfSToby Isaac PetscInt q = closure[2 * i]; 1466085f0adfSToby Isaac PetscInt aDof, aOff, j; 1467085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 1468085f0adfSToby Isaac 1469085f0adfSToby Isaac if (numFields) { 14709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof)); 14719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff)); 14729371c9d4SSatish Balay } else { 14739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof)); 14749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff)); 1475085f0adfSToby Isaac } 1476085f0adfSToby Isaac if (flip) { 1477085f0adfSToby Isaac PetscInt k; 1478085f0adfSToby Isaac for (k = 0; k < cDof; k++) { 1479ad540459SPierre Jolivet for (j = 0; j < aDof; j++) refPointFieldMats[p - pRefStart][f][k * numCols + colOff + j] *= flip[j]; 1480085f0adfSToby Isaac } 1481085f0adfSToby Isaac } 1482085f0adfSToby Isaac colOff += aDof; 1483085f0adfSToby Isaac } 1484085f0adfSToby Isaac } 1485085f0adfSToby Isaac if (numFields) { 14869566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips)); 1487085f0adfSToby Isaac } else { 14889566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(refSection, closureSize, closure, &perms, &flips)); 1489085f0adfSToby Isaac } 149095a0b26dSToby Isaac } 14919566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure)); 149295a0b26dSToby Isaac } 149321968bf8SToby Isaac *childrenMats = refPointFieldMats; 149421968bf8SToby Isaac *childrenN = refPointFieldN; 14959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(refAnIS, &refAnchors)); 14969566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 14979566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 149821968bf8SToby Isaac PetscFunctionReturn(0); 149921968bf8SToby Isaac } 150021968bf8SToby Isaac 1501*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 1502*d71ae5a4SJacob Faibussowitsch { 150321968bf8SToby Isaac PetscDS ds; 150421968bf8SToby Isaac PetscInt **refPointFieldN; 150521968bf8SToby Isaac PetscScalar ***refPointFieldMats; 1506085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f; 150721968bf8SToby Isaac PetscSection refConSec; 150821968bf8SToby Isaac 150921968bf8SToby Isaac PetscFunctionBegin; 151021968bf8SToby Isaac refPointFieldN = *childrenN; 151121968bf8SToby Isaac *childrenN = NULL; 151221968bf8SToby Isaac refPointFieldMats = *childrenMats; 151321968bf8SToby Isaac *childrenMats = NULL; 15149566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 15159566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1516367003a6SStefano Zampini maxFields = PetscMax(1, numFields); 15179566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 15189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 151921968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 152021968bf8SToby Isaac PetscInt parent, pDof; 152121968bf8SToby Isaac 15229566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 15239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 152421968bf8SToby Isaac if (!pDof || parent == p) continue; 152521968bf8SToby Isaac 1526085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 152721968bf8SToby Isaac PetscInt cDof; 152821968bf8SToby Isaac 1529085f0adfSToby Isaac if (numFields) { 15309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 15319371c9d4SSatish Balay } else { 15329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 153321968bf8SToby Isaac } 153421968bf8SToby Isaac 15359566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 153621968bf8SToby Isaac } 15379566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 15389566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN[p - pRefStart])); 153921968bf8SToby Isaac } 15409566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 15419566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN)); 154221968bf8SToby Isaac PetscFunctionReturn(0); 154321968bf8SToby Isaac } 154421968bf8SToby Isaac 1545*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 1546*d71ae5a4SJacob Faibussowitsch { 154721968bf8SToby Isaac DM refTree; 154821968bf8SToby Isaac PetscDS ds; 154921968bf8SToby Isaac Mat refCmat; 1550085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 155121968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 155221968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 155321968bf8SToby Isaac IS refAnIS, anIS; 155421968bf8SToby Isaac const PetscInt *anchors; 155521968bf8SToby Isaac 155621968bf8SToby Isaac PetscFunctionBegin; 155721968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15589566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 15599566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1560085f0adfSToby Isaac maxFields = PetscMax(1, numFields); 15619566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 15629566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, refTree)); 15639566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 15649566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 15659566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anSec, &anIS)); 15669566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anIS, &anchors)); 15679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 15689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(conSec, &conStart, &conEnd)); 15699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 15709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 15719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof * maxAnDof, &pointWork)); 157221968bf8SToby Isaac 157321968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 15749566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 157595a0b26dSToby Isaac 157695a0b26dSToby Isaac /* step 2: compute the preorder */ 15779566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 15789566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &perm, pEnd - pStart, &iperm)); 157995a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 158095a0b26dSToby Isaac perm[p - pStart] = p; 158195a0b26dSToby Isaac iperm[p - pStart] = p - pStart; 158295a0b26dSToby Isaac } 158395a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 158495a0b26dSToby Isaac PetscInt point = perm[p]; 158595a0b26dSToby Isaac PetscInt parent; 158695a0b26dSToby Isaac 15879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 158895a0b26dSToby Isaac if (parent == point) { 158995a0b26dSToby Isaac p++; 15909371c9d4SSatish Balay } else { 159195a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 159295a0b26dSToby Isaac 15939566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 159495a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 159595a0b26dSToby Isaac PetscInt q = closure[2 * i]; 159695a0b26dSToby Isaac if (iperm[q - pStart] > iperm[point - pStart]) { 159795a0b26dSToby Isaac /* swap */ 159895a0b26dSToby Isaac perm[p] = q; 159995a0b26dSToby Isaac perm[iperm[q - pStart]] = point; 160095a0b26dSToby Isaac iperm[point - pStart] = iperm[q - pStart]; 160195a0b26dSToby Isaac iperm[q - pStart] = p; 160295a0b26dSToby Isaac break; 160395a0b26dSToby Isaac } 160495a0b26dSToby Isaac } 160595a0b26dSToby Isaac size = closureSize; 16069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1607ad540459SPierre Jolivet if (i == size) p++; 160895a0b26dSToby Isaac } 160995a0b26dSToby Isaac } 161095a0b26dSToby Isaac 161195a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 161295a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 161395a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 161495a0b26dSToby Isaac * values outside of the Mat first. 161595a0b26dSToby Isaac */ 161695a0b26dSToby Isaac { 161795a0b26dSToby Isaac PetscInt nRows, row, nnz; 161895a0b26dSToby Isaac PetscBool done; 1619cd6fc93eSToby Isaac PetscInt secStart, secEnd; 162095a0b26dSToby Isaac const PetscInt *ia, *ja; 162195a0b26dSToby Isaac PetscScalar *vals; 162295a0b26dSToby Isaac 1623cd6fc93eSToby Isaac PetscCall(PetscSectionGetChart(section, &secStart, &secEnd)); 16249566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 162528b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not get RowIJ of constraint matrix"); 162695a0b26dSToby Isaac nnz = ia[nRows]; 162795a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 162895a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 16299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &vals)); 163095a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 163195a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 163295a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 163395a0b26dSToby Isaac 16349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, &childid)); 163595a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 16369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &pointDof)); 163795a0b26dSToby Isaac if (!pointDof) continue; 16389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1639085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1640085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 164195a0b26dSToby Isaac PetscScalar *pointMat; 1642085f0adfSToby Isaac const PetscInt **perms; 1643085f0adfSToby Isaac const PetscScalar **flips; 164495a0b26dSToby Isaac 1645085f0adfSToby Isaac if (numFields) { 16469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, point, f, &cDof)); 16479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, point, f, &cOff)); 16489371c9d4SSatish Balay } else { 16499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &cDof)); 16509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, point, &cOff)); 165195a0b26dSToby Isaac } 165295a0b26dSToby Isaac if (!cDof) continue; 16539566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 16549566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, closureSize, closure, &perms, &flips)); 165595a0b26dSToby Isaac 165695a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 165776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 165895a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 165995a0b26dSToby Isaac if (cDof > 1 && r) { 166063a3b9bcSJacob 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])); 166195a0b26dSToby Isaac } 166295a0b26dSToby Isaac } 166376bd3646SJed Brown } 166495a0b26dSToby Isaac /* zero rows */ 1665ad540459SPierre Jolivet for (i = ia[cOff]; i < ia[cOff + cDof]; i++) vals[i] = 0.; 166695a0b26dSToby Isaac matOffset = ia[cOff]; 166795a0b26dSToby Isaac numFillCols = ia[cOff + 1] - matOffset; 166895a0b26dSToby Isaac pointMat = refPointFieldMats[childid - pRefStart][f]; 166995a0b26dSToby Isaac numCols = refPointFieldN[childid - pRefStart][f]; 167095a0b26dSToby Isaac offset = 0; 167195a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 167295a0b26dSToby Isaac PetscInt q = closure[2 * i]; 167395a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 1674085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1675085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 167695a0b26dSToby Isaac 167795a0b26dSToby Isaac qConDof = qConOff = 0; 1678cd6fc93eSToby Isaac if (q < secStart || q >= secEnd) continue; 1679085f0adfSToby Isaac if (numFields) { 16809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, q, f, &aDof)); 16819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, q, f, &aOff)); 168295a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, q, f, &qConDof)); 16849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, q, f, &qConOff)); 168595a0b26dSToby Isaac } 16869371c9d4SSatish Balay } else { 16879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &aDof)); 16889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &aOff)); 168995a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, q, &qConDof)); 16919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, q, &qConOff)); 169295a0b26dSToby Isaac } 169395a0b26dSToby Isaac } 169495a0b26dSToby Isaac if (!aDof) continue; 169595a0b26dSToby Isaac if (qConDof) { 169695a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 169795a0b26dSToby Isaac * be filled, thanks to preordering */ 169895a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 169995a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 170095a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 170195a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 170295a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 170395a0b26dSToby Isaac PetscScalar inVal = 0; 170495a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1705085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 170695a0b26dSToby Isaac 1707085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 170895a0b26dSToby Isaac } 170995a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 171095a0b26dSToby Isaac } 171195a0b26dSToby Isaac } 171295a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 171395a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 171495a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 171595a0b26dSToby Isaac for (; k < numFillCols; k++) { 1716ad540459SPierre Jolivet if (ja[matOffset + k] == col) break; 171795a0b26dSToby Isaac } 171863a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, col); 1719ad540459SPierre Jolivet for (r = 0; r < cDof; r++) vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 172095a0b26dSToby Isaac } 17219371c9d4SSatish Balay } else { 172295a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 172395a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 1724ad540459SPierre Jolivet if (ja[matOffset + k] == aOff) break; 172595a0b26dSToby Isaac } 172663a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, aOff); 172795a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1728085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1729085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1730085f0adfSToby Isaac 1731085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 173295a0b26dSToby Isaac } 173395a0b26dSToby Isaac } 173495a0b26dSToby Isaac } 173595a0b26dSToby Isaac offset += aDof; 173695a0b26dSToby Isaac } 1737085f0adfSToby Isaac if (numFields) { 17389566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 1739085f0adfSToby Isaac } else { 17409566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, closureSize, closure, &perms, &flips)); 1741085f0adfSToby Isaac } 174295a0b26dSToby Isaac } 17439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 174495a0b26dSToby Isaac } 174548a46eb9SPierre 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)); 17469566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 174728b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not restore RowIJ of constraint matrix"); 17489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 17499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 17509566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 175195a0b26dSToby Isaac } 175295a0b26dSToby Isaac 175395a0b26dSToby Isaac /* clean up */ 17549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anIS, &anchors)); 17559566063dSJacob Faibussowitsch PetscCall(PetscFree2(perm, iperm)); 17569566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 17579566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 175895a0b26dSToby Isaac PetscFunctionReturn(0); 175995a0b26dSToby Isaac } 176095a0b26dSToby Isaac 17616f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 17626f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 1763*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTreeRefineCell(DM dm, PetscInt cell, DM *ncdm) 1764*d71ae5a4SJacob Faibussowitsch { 17656f5f1567SToby Isaac DM K; 1766420f55faSMatthew G. Knepley PetscMPIInt rank; 17676f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 17686f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 17696f5f1567SToby Isaac PetscInt *Kembedding; 17706f5f1567SToby Isaac PetscInt *cellClosure = NULL, nc; 17716f5f1567SToby Isaac PetscScalar *newVertexCoords; 17726f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 17736f5f1567SToby Isaac PetscSection parentSection; 17746f5f1567SToby Isaac 17756f5f1567SToby Isaac PetscFunctionBegin; 17769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17779566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 17789566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm)); 17799566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ncdm, dim)); 17806f5f1567SToby Isaac 17819566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 17829566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &parentSection)); 17839566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &K)); 17846858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 1785dd400576SPatrick Sanan if (rank == 0) { 17866f5f1567SToby Isaac /* compute the new charts */ 17879566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim + 1, &pNewCount, dim + 1, &pNewStart, dim + 1, &pNewEnd, dim + 1, &pOldStart, dim + 1, &pOldEnd)); 17886f5f1567SToby Isaac offset = 0; 17896f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 17906f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 17916f5f1567SToby Isaac 17926f5f1567SToby Isaac pNewStart[d] = offset; 17939566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pOldStart[d], &pOldEnd[d])); 17949566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 17956f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 17966f5f1567SToby Isaac /* adding the new points */ 17976f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 17986f5f1567SToby Isaac if (!d) { 17996f5f1567SToby Isaac /* removing the cell */ 18006f5f1567SToby Isaac pNewCount[d]--; 18016f5f1567SToby Isaac } 18026f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18036f5f1567SToby Isaac PetscInt parent; 18049566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &parent, NULL)); 18056f5f1567SToby Isaac if (parent == k) { 18066f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 18076f5f1567SToby Isaac pNewCount[d]--; 18086f5f1567SToby Isaac } 18096f5f1567SToby Isaac } 18106f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 18116f5f1567SToby Isaac offset = pNewEnd[d]; 18126f5f1567SToby Isaac } 18131dca8a05SBarry 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]); 18146f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 18159566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 18166f5f1567SToby Isaac 18179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pNewEnd[dim], &newConeSizes)); 18186f5f1567SToby Isaac { 1819b5a892a1SMatthew G. Knepley DMPolytopeType pct, qct; 18206f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 18216f5f1567SToby Isaac 18229566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &kStart, &kEnd)); 18239566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(kEnd - kStart, &Kembedding, kEnd - kStart, &perm, kEnd - kStart, &iperm, kEnd - kStart, &preOrient)); 18246f5f1567SToby Isaac 18256f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18266f5f1567SToby Isaac perm[k - kStart] = k; 18276f5f1567SToby Isaac iperm[k - kStart] = k - kStart; 18286f5f1567SToby Isaac preOrient[k - kStart] = 0; 18296f5f1567SToby Isaac } 18306f5f1567SToby Isaac 18319566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18326f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 18336f5f1567SToby Isaac PetscInt parentOrientA = closureK[2 * j + 1]; 18346f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2 * j + 1]; 18356f5f1567SToby Isaac PetscInt p, q; 18366f5f1567SToby Isaac 18376f5f1567SToby Isaac p = closureK[2 * j]; 18386f5f1567SToby Isaac q = cellClosure[2 * j]; 18399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, p, &pct)); 18409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, q, &qct)); 18416f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 1842ad540459SPierre Jolivet if (q >= pOldStart[d] && q < pOldEnd[d]) Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 18436f5f1567SToby Isaac } 1844b5a892a1SMatthew G. Knepley parentOrientA = DMPolytopeConvertNewOrientation_Internal(pct, parentOrientA); 1845b5a892a1SMatthew G. Knepley parentOrientB = DMPolytopeConvertNewOrientation_Internal(qct, parentOrientB); 18466f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 18476f5f1567SToby Isaac PetscInt numChildren, i; 18486f5f1567SToby Isaac const PetscInt *children; 18496f5f1567SToby Isaac 18509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(K, p, &numChildren, &children)); 18516f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 18526f5f1567SToby Isaac PetscInt kPerm, oPerm; 18536f5f1567SToby Isaac 18546f5f1567SToby Isaac k = children[i]; 18559566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(K, p, parentOrientA, 0, k, parentOrientB, &oPerm, &kPerm)); 18566f5f1567SToby Isaac /* perm = what refTree position I'm in */ 18576f5f1567SToby Isaac perm[kPerm - kStart] = k; 18586f5f1567SToby Isaac /* iperm = who is at this position */ 18596f5f1567SToby Isaac iperm[k - kStart] = kPerm - kStart; 18606f5f1567SToby Isaac preOrient[kPerm - kStart] = oPerm; 18616f5f1567SToby Isaac } 18626f5f1567SToby Isaac } 18636f5f1567SToby Isaac } 18649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18656f5f1567SToby Isaac } 18669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, pNewEnd[dim])); 18676f5f1567SToby Isaac offset = 0; 18686f5f1567SToby Isaac numNewCones = 0; 18696f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18706f5f1567SToby Isaac PetscInt kStart, kEnd, k; 18716f5f1567SToby Isaac PetscInt p; 18726f5f1567SToby Isaac PetscInt size; 18736f5f1567SToby Isaac 18746f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 18756f5f1567SToby Isaac /* skip cell 0 */ 18766f5f1567SToby Isaac if (p == cell) continue; 18776f5f1567SToby Isaac /* old cones to new cones */ 18789566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 18796f5f1567SToby Isaac newConeSizes[offset++] = size; 18806f5f1567SToby Isaac numNewCones += size; 18816f5f1567SToby Isaac } 18826f5f1567SToby Isaac 18839566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 18846f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18856f5f1567SToby Isaac PetscInt kParent; 18866f5f1567SToby Isaac 18879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 18886f5f1567SToby Isaac if (kParent != k) { 18896f5f1567SToby Isaac Kembedding[k] = offset; 18909566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 18916f5f1567SToby Isaac newConeSizes[offset++] = size; 18926f5f1567SToby Isaac numNewCones += size; 189348a46eb9SPierre Jolivet if (kParent != 0) PetscCall(PetscSectionSetDof(parentSection, Kembedding[k], 1)); 18946f5f1567SToby Isaac } 18956f5f1567SToby Isaac } 18966f5f1567SToby Isaac } 18976f5f1567SToby Isaac 18989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 18999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &numPointsWithParents)); 19009566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numNewCones, &newCones, numNewCones, &newOrientations)); 19019566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPointsWithParents, &parents, numPointsWithParents, &childIDs)); 19026f5f1567SToby Isaac 19036f5f1567SToby Isaac /* fill new cones */ 19046f5f1567SToby Isaac offset = 0; 19056f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19066f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 19076f5f1567SToby Isaac PetscInt p; 19086f5f1567SToby Isaac PetscInt size; 19096f5f1567SToby Isaac const PetscInt *cone, *orientation; 19106f5f1567SToby Isaac 19116f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19126f5f1567SToby Isaac /* skip cell 0 */ 19136f5f1567SToby Isaac if (p == cell) continue; 19146f5f1567SToby Isaac /* old cones to new cones */ 19159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 19169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 19179566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &orientation)); 19186f5f1567SToby Isaac for (l = 0; l < size; l++) { 19196f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 19206f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 19216f5f1567SToby Isaac } 19226f5f1567SToby Isaac } 19236f5f1567SToby Isaac 19249566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 19256f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19266f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 19276f5f1567SToby Isaac PetscInt preO = preOrient[k]; 19286f5f1567SToby Isaac 19299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 19306f5f1567SToby Isaac if (kParent != k) { 19316f5f1567SToby Isaac /* embed new cones */ 19329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 19339566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, kPerm, &cone)); 19349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, kPerm, &orientation)); 19356f5f1567SToby Isaac for (l = 0; l < size; l++) { 19366f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size - (preO + 1) - l) % size); 19376f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 1938b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_NUM_POLYTOPES; 19396f5f1567SToby Isaac 19406f5f1567SToby Isaac q = iperm[cone[m]]; 19416f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 19429566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, q, &lSize)); 1943b5a892a1SMatthew G. Knepley if (lSize == 2) ct = DM_POLYTOPE_SEGMENT; 1944b5a892a1SMatthew G. Knepley else if (lSize == 4) ct = DM_POLYTOPE_QUADRILATERAL; 1945b5a892a1SMatthew G. Knepley oTrue = DMPolytopeConvertNewOrientation_Internal(ct, orientation[m]); 19466f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 19476f5f1567SToby Isaac newO = DihedralCompose(lSize, oTrue, preOrient[q]); 1948b5a892a1SMatthew G. Knepley newOrientations[offset++] = DMPolytopeConvertOldOrientation_Internal(ct, newO); 19496f5f1567SToby Isaac } 19506f5f1567SToby Isaac if (kParent != 0) { 19516f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 19529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, Kembedding[k], &pOffset)); 19536f5f1567SToby Isaac parents[pOffset] = newPoint; 19546f5f1567SToby Isaac childIDs[pOffset] = k; 19556f5f1567SToby Isaac } 19566f5f1567SToby Isaac } 19576f5f1567SToby Isaac } 19586f5f1567SToby Isaac } 19596f5f1567SToby Isaac 19609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * (pNewEnd[dim] - pNewStart[dim]), &newVertexCoords)); 19616f5f1567SToby Isaac 19626f5f1567SToby Isaac /* fill coordinates */ 19636f5f1567SToby Isaac offset = 0; 19646f5f1567SToby Isaac { 1965d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 19666f5f1567SToby Isaac PetscSection vSection; 19676f5f1567SToby Isaac PetscInt v; 19686f5f1567SToby Isaac Vec coords; 19696f5f1567SToby Isaac PetscScalar *coordvals; 19706f5f1567SToby Isaac PetscInt dof, off; 1971c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 19726f5f1567SToby Isaac 197376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1974d90620a3SMatthew G. Knepley PetscInt k; 19759566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, 0, &kStart, &kEnd)); 19766f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19779566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ)); 197863a3b9bcSJacob Faibussowitsch PetscCheck(detJ > 0., PETSC_COMM_SELF, PETSC_ERR_PLIB, "reference tree cell %" PetscInt_FMT " has bad determinant", k); 19796f5f1567SToby Isaac } 1980d90620a3SMatthew G. Knepley } 19819566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ)); 19829566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &vSection)); 19839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coords)); 19849566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19856f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 19869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(vSection, v, &dof)); 19879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, v, &off)); 1988ad540459SPierre Jolivet for (l = 0; l < dof; l++) newVertexCoords[offset++] = coordvals[off + l]; 19896f5f1567SToby Isaac } 19909566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 19916f5f1567SToby Isaac 19929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &vSection)); 19939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &coords)); 19949566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &kStart, &kEnd)); 19966f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 19979bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 19986f5f1567SToby Isaac PetscInt vPerm = perm[v]; 19996f5f1567SToby Isaac PetscInt kParent; 2000c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 20016f5f1567SToby Isaac 20029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, v, &kParent, NULL)); 20036f5f1567SToby Isaac if (kParent != v) { 20046f5f1567SToby Isaac /* this is a new vertex */ 20059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, vPerm, &off)); 20069bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off + l]); 2007367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord); 20089bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset + l] = newCoord[l]; 20096f5f1567SToby Isaac offset += dim; 20106f5f1567SToby Isaac } 20116f5f1567SToby Isaac } 20129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 20136f5f1567SToby Isaac } 20146f5f1567SToby Isaac 20156f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 20166f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 20176f5f1567SToby Isaac PetscInt tmp; 20186f5f1567SToby Isaac 20196f5f1567SToby Isaac tmp = pNewCount[d]; 20206f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 20216f5f1567SToby Isaac pNewCount[dim - d] = tmp; 20226f5f1567SToby Isaac } 20236f5f1567SToby Isaac 20249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, pNewCount, newConeSizes, newCones, newOrientations, newVertexCoords)); 20259566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20269566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, parents, childIDs)); 20276f5f1567SToby Isaac 20286f5f1567SToby Isaac /* clean up */ 20299566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 20309566063dSJacob Faibussowitsch PetscCall(PetscFree5(pNewCount, pNewStart, pNewEnd, pOldStart, pOldEnd)); 20319566063dSJacob Faibussowitsch PetscCall(PetscFree(newConeSizes)); 20329566063dSJacob Faibussowitsch PetscCall(PetscFree2(newCones, newOrientations)); 20339566063dSJacob Faibussowitsch PetscCall(PetscFree(newVertexCoords)); 20349566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs)); 20359566063dSJacob Faibussowitsch PetscCall(PetscFree4(Kembedding, perm, iperm, preOrient)); 20369371c9d4SSatish Balay } else { 20376f5f1567SToby Isaac PetscInt p, counts[4]; 20386f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 20396f5f1567SToby Isaac Vec coordVec; 20406f5f1567SToby Isaac PetscScalar *coords; 20416f5f1567SToby Isaac 20426f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20436f5f1567SToby Isaac PetscInt dStart, dEnd; 20446f5f1567SToby Isaac 20459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 20466f5f1567SToby Isaac counts[d] = dEnd - dStart; 20476f5f1567SToby Isaac } 20489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &coneSizes)); 204948a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMPlexGetConeSize(dm, p, &coneSizes[p - pStart])); 20509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 20519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &orientations)); 20529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordVec)); 20539566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordVec, &coords)); 20546f5f1567SToby Isaac 20559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd)); 20569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 20579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, counts, coneSizes, cones, orientations, NULL)); 20589566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20599566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, NULL, NULL)); 20609566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordVec, &coords)); 20616f5f1567SToby Isaac } 20629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 20636f5f1567SToby Isaac 20646f5f1567SToby Isaac PetscFunctionReturn(0); 20656f5f1567SToby Isaac } 20666ecaa68aSToby Isaac 2067*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 2068*d71ae5a4SJacob Faibussowitsch { 20696ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 20706ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 20716ecaa68aSToby Isaac PetscSection localCoarse, localFine; 20726ecaa68aSToby Isaac PetscSection aSec, cSec; 20736ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 207446bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 207546bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 207646bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 20776ecaa68aSToby Isaac IS aIS; 20786ecaa68aSToby Isaac const PetscInt *anchors; 20796ecaa68aSToby Isaac Mat cMat; 20804acb8e1eSToby Isaac PetscInt numFields, maxFields; 20816ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 20826ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 20831c58ffc4SToby Isaac PetscInt *maxChildIds; 2084e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 20854acb8e1eSToby Isaac const PetscInt ***perms; 20864acb8e1eSToby Isaac const PetscScalar ***flips; 20876ecaa68aSToby Isaac 20886ecaa68aSToby Isaac PetscFunctionBegin; 20899566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 20909566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 20919566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 20926ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 209389698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 209489698031SToby Isaac const PetscInt *leaves; 20956ecaa68aSToby Isaac 20969566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 209789698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 209889698031SToby Isaac p = leaves ? leaves[l] : l; 20999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 21009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 2101ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 21026ecaa68aSToby Isaac } 21039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 21047cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 210589698031SToby Isaac p = leaves ? leaves[l] : l; 21069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 21079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 2108ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l; 21096ecaa68aSToby Isaac } 21109566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 21119566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 21126ecaa68aSToby Isaac } 21136ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 21149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 2115ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2; 211657168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 211757168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 211846bdb399SToby Isaac 21199566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 21209566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 212146bdb399SToby Isaac 21229566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 21239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 21249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 212546bdb399SToby Isaac 21269566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 21279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 212846bdb399SToby Isaac 212946bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 21309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 21319566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootMatricesSec)); 21329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootIndicesSec, pStartC, pEndC)); 21339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootMatricesSec, pStartC, pEndC)); 21349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 2135713c1c5dSToby Isaac maxFields = PetscMax(1, numFields); 21369566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields + 1, &offsets, maxFields + 1, &offsetsCopy, maxFields + 1, &newOffsets, maxFields + 1, &newOffsetsCopy, maxFields + 1, &rowOffsets, maxFields + 1, &numD, maxFields + 1, &numO)); 21379566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxFields + 1, (PetscInt ****)&perms, maxFields + 1, (PetscScalar ****)&flips)); 21389566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)perms, (maxFields + 1) * sizeof(const PetscInt **))); 21399566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)flips, (maxFields + 1) * sizeof(const PetscScalar **))); 214046bdb399SToby Isaac 214146bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 21428d2f55e7SToby Isaac PetscInt dof, matSize = 0; 21436ecaa68aSToby Isaac PetscInt aDof = 0; 21446ecaa68aSToby Isaac PetscInt cDof = 0; 21456ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 21466ecaa68aSToby Isaac PetscInt numRowIndices = 0; 21476ecaa68aSToby Isaac PetscInt numColIndices = 0; 2148f13f9184SToby Isaac PetscInt f; 21496ecaa68aSToby Isaac 21509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 2151ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 215248a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 215348a46eb9SPierre Jolivet if (p >= cStart && p < cEnd) PetscCall(PetscSectionGetDof(cSec, p, &cDof)); 2154f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2155f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 21566ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2157f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 21586ecaa68aSToby Isaac 21599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 216046bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 21616ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 21626ecaa68aSToby Isaac 21639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 21646ecaa68aSToby Isaac numRowIndices += clDof; 21656ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &clDof)); 21676ecaa68aSToby Isaac offsets[f + 1] += clDof; 21686ecaa68aSToby Isaac } 21696ecaa68aSToby Isaac } 21706ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21716ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 21726ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 21736ecaa68aSToby Isaac } 217446bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 21759566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, NULL, NULL, NULL, &numColIndices, NULL, NULL, newOffsets, PETSC_FALSE)); 21769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 21776ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 21786ecaa68aSToby Isaac numColIndices = numRowIndices; 21796ecaa68aSToby Isaac matSize = 0; 21809371c9d4SSatish Balay } else if (numFields) { /* we send one submat for each field: sum their sizes */ 21816ecaa68aSToby Isaac matSize = 0; 21826ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21836ecaa68aSToby Isaac PetscInt numRow, numCol; 21846ecaa68aSToby Isaac 21856ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2186f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 21876ecaa68aSToby Isaac matSize += numRow * numCol; 21886ecaa68aSToby Isaac } 21899371c9d4SSatish Balay } else { 21906ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 21916ecaa68aSToby Isaac } 2192f13f9184SToby Isaac } else if (maxChildId == -1) { 21938d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2194f13f9184SToby Isaac PetscInt aOff, a; 21956ecaa68aSToby Isaac 21969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 21976ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21986ecaa68aSToby Isaac PetscInt fDof; 21996ecaa68aSToby Isaac 22009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 220121968bf8SToby Isaac offsets[f + 1] = fDof; 22026ecaa68aSToby Isaac } 22036ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 22046ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 22056ecaa68aSToby Isaac 22069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, anchor, &aLocalDof)); 22076ecaa68aSToby Isaac numColIndices += aLocalDof; 22086ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22096ecaa68aSToby Isaac PetscInt fDof; 22106ecaa68aSToby Isaac 22119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 221221968bf8SToby Isaac newOffsets[f + 1] += fDof; 22136ecaa68aSToby Isaac } 22146ecaa68aSToby Isaac } 22156ecaa68aSToby Isaac if (numFields) { 22166ecaa68aSToby Isaac matSize = 0; 2217ad540459SPierre Jolivet for (f = 0; f < numFields; f++) matSize += offsets[f + 1] * newOffsets[f + 1]; 22189371c9d4SSatish Balay } else { 22196ecaa68aSToby Isaac matSize = numColIndices * dof; 22206ecaa68aSToby Isaac } 22219371c9d4SSatish Balay } else { /* no children, and no constraints on dofs: just get the global indices */ 22226ecaa68aSToby Isaac numColIndices = dof; 22236ecaa68aSToby Isaac matSize = 0; 22246ecaa68aSToby Isaac } 22258d2f55e7SToby Isaac } 222646bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 22279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootIndicesSec, p, numColIndices ? numColIndices + 2 * numFields : 0)); 22289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootMatricesSec, p, matSize)); 22296ecaa68aSToby Isaac } 22309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootIndicesSec)); 22319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootMatricesSec)); 22326ecaa68aSToby Isaac { 22336ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 22346ecaa68aSToby Isaac 22359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 22369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootMatricesSec, &numRootMatrices)); 22379566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRootIndices, &rootIndices, numRootMatrices, &rootMatrices)); 22386ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22396ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2240f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 22416ecaa68aSToby Isaac PetscInt *pInd; 22426ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22436ecaa68aSToby Isaac PetscScalar *pMat = NULL; 22446ecaa68aSToby Isaac 22459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, p, &numColIndices)); 2246ad540459SPierre Jolivet if (!numColIndices) continue; 2247f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2248f13f9184SToby Isaac offsets[f] = 0; 2249f13f9184SToby Isaac newOffsets[f] = 0; 2250f13f9184SToby Isaac offsetsCopy[f] = 0; 2251f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2252f13f9184SToby Isaac } 22536ecaa68aSToby Isaac numColIndices -= 2 * numFields; 22549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, p, &pIndOff)); 22556ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 22569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootMatricesSec, p, &matSize)); 22576ecaa68aSToby Isaac if (matSize) { 22589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootMatricesSec, p, &pMatOff)); 22596ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 22606ecaa68aSToby Isaac } 22619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 2262ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 22636ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 22646ecaa68aSToby Isaac PetscInt i, j; 22656ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 22666ecaa68aSToby Isaac 22676ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 22686ecaa68aSToby Isaac PetscInt numIndices, *indices; 22699566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 227008401ef6SPierre Jolivet PetscCheck(numIndices == numColIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "mismatching constraint indices calculations"); 2271ad540459SPierre Jolivet for (i = 0; i < numColIndices; i++) pInd[i] = indices[i]; 22726ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 227346bdb399SToby Isaac pInd[numColIndices + i] = offsets[i + 1]; 227446bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i + 1]; 22756ecaa68aSToby Isaac } 22769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 22779371c9d4SSatish Balay } else { 22786ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 22796ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 22806ecaa68aSToby Isaac PetscInt numPoints, *points; 22816ecaa68aSToby Isaac 22829566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices * numRowIndices, MPIU_SCALAR, &pMatIn)); 22836ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 2284ad540459SPierre Jolivet for (j = 0; j < numRowIndices; j++) pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 22856ecaa68aSToby Isaac } 22869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 22874acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 22889566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 22899566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 22904acb8e1eSToby Isaac } 22916ecaa68aSToby Isaac if (numFields) { 22926ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 22936ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 22946ecaa68aSToby Isaac 22956ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22966ecaa68aSToby Isaac PetscInt fDof; 22976ecaa68aSToby Isaac 22989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &fDof)); 22996ecaa68aSToby Isaac offsets[f + 1] += fDof; 23006ecaa68aSToby Isaac } 23016ecaa68aSToby Isaac } 23026ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23036ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23046ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 23056ecaa68aSToby Isaac } 23066ecaa68aSToby Isaac } 23074acb8e1eSToby Isaac /* TODO : flips here ? */ 23086ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 23099566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, perms, pMatIn, &numPoints, NULL, &points, &pMatModified, newOffsets, PETSC_FALSE)); 23104acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23119566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 23129566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 23134acb8e1eSToby Isaac } 23144acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23159566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23169566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23174acb8e1eSToby Isaac } 23186ecaa68aSToby Isaac if (!numFields) { 2319ad540459SPierre Jolivet for (i = 0; i < numRowIndices * numColIndices; i++) pMat[i] = pMatModified[i]; 23209371c9d4SSatish Balay } else { 2321f13f9184SToby Isaac PetscInt i, j, count; 23226ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 23236ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f + 1]; i++) { 2324ad540459SPierre Jolivet for (j = newOffsets[f]; j < newOffsets[f + 1]; j++, count++) pMat[count] = pMatModified[i * numColIndices + j]; 23256ecaa68aSToby Isaac } 23266ecaa68aSToby Isaac } 23276ecaa68aSToby Isaac } 23289566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatModified)); 23299566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 23309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatIn)); 23316ecaa68aSToby Isaac if (numFields) { 233246bdb399SToby Isaac for (f = 0; f < numFields; f++) { 233346bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 233446bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 23356ecaa68aSToby Isaac } 23364acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23374acb8e1eSToby Isaac PetscInt globalOff, c = points[2 * cl]; 23389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23399566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd)); 23406ecaa68aSToby Isaac } 23416ecaa68aSToby Isaac } else { 23424acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23434acb8e1eSToby Isaac PetscInt c = points[2 * cl], globalOff; 23444acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 23454acb8e1eSToby Isaac 23469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23479566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd)); 23486ecaa68aSToby Isaac } 23496ecaa68aSToby Isaac } 23504acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23519566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23529566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23534acb8e1eSToby Isaac } 23549566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numPoints, MPIU_SCALAR, &points)); 23556ecaa68aSToby Isaac } 23569371c9d4SSatish Balay } else if (matSize) { 23576ecaa68aSToby Isaac PetscInt cOff; 23586ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 23596ecaa68aSToby Isaac 23606ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 236108401ef6SPierre Jolivet PetscCheck(numRowIndices == dof, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Miscounted dofs"); 23629566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 23639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 23649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &cOff)); 23659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 23669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 23676ecaa68aSToby Isaac if (numFields) { 23686ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23696ecaa68aSToby Isaac PetscInt fDof; 2370f13f9184SToby Isaac 23719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &fDof)); 23726ecaa68aSToby Isaac offsets[f + 1] = fDof; 23736ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23746ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 23759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 23766ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 23776ecaa68aSToby Isaac } 23786ecaa68aSToby Isaac } 23796ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23806ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23816ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 23826ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 23836ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 23846ecaa68aSToby Isaac } 23859566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, -1, NULL, rowIndices)); 23866ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23876ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23899566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, -1, NULL, colIndices)); 23906ecaa68aSToby Isaac } 23919371c9d4SSatish Balay } else { 23929566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, NULL, rowIndices)); 23936ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23946ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23969566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, NULL, colIndices)); 23976ecaa68aSToby Isaac } 23986ecaa68aSToby Isaac } 23996ecaa68aSToby Isaac if (numFields) { 2400f13f9184SToby Isaac PetscInt count, a; 2401f13f9184SToby Isaac 24026ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24036ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 24046ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 24059566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, iSize, &rowIndices[offsets[f]], jSize, &colIndices[newOffsets[f]], &pMat[count])); 24066ecaa68aSToby Isaac count += iSize * jSize; 240746bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 240846bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 24096ecaa68aSToby Isaac } 24106ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 24116ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 24126ecaa68aSToby Isaac PetscInt gOff; 24139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 24149566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 24156ecaa68aSToby Isaac } 24169371c9d4SSatish Balay } else { 24176ecaa68aSToby Isaac PetscInt a; 24189566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, numRowIndices, rowIndices, numColIndices, colIndices, pMat)); 24196ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 24206ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 24216ecaa68aSToby Isaac PetscInt gOff; 24229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 24239566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, NULL, pInd)); 24246ecaa68aSToby Isaac } 24256ecaa68aSToby Isaac } 24269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 24279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 24289371c9d4SSatish Balay } else { 24296ecaa68aSToby Isaac PetscInt gOff; 24306ecaa68aSToby Isaac 24319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 24326ecaa68aSToby Isaac if (numFields) { 24336ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24346ecaa68aSToby Isaac PetscInt fDof; 24359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 24366ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 24376ecaa68aSToby Isaac } 24386ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 243946bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 244046bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f + 1]; 24416ecaa68aSToby Isaac } 24429566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 2443367003a6SStefano Zampini } else { 24449566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 24456ecaa68aSToby Isaac } 24466ecaa68aSToby Isaac } 24476ecaa68aSToby Isaac } 24489566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 24496ecaa68aSToby Isaac } 245046bdb399SToby Isaac { 245146bdb399SToby Isaac PetscSF indicesSF, matricesSF; 245246bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 245346bdb399SToby Isaac 24549566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 24559566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafMatricesSec)); 24569566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootIndicesSec, &remoteOffsetsIndices, leafIndicesSec)); 24579566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootMatricesSec, &remoteOffsetsMatrices, leafMatricesSec)); 24589566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootIndicesSec, remoteOffsetsIndices, leafIndicesSec, &indicesSF)); 24599566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootMatricesSec, remoteOffsetsMatrices, leafMatricesSec, &matricesSF)); 24609566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 24619566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsIndices)); 24629566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsMatrices)); 24639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numLeafIndices)); 24649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafMatricesSec, &numLeafMatrices)); 24659566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numLeafIndices, &leafIndices, numLeafMatrices, &leafMatrices)); 24669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24709566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&matricesSF)); 24719566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 24729566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootIndices, rootMatrices)); 24739566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 24749566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootMatricesSec)); 247546bdb399SToby Isaac } 247646bdb399SToby Isaac /* count to preallocate */ 24779566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 247846bdb399SToby Isaac { 247946bdb399SToby Isaac PetscInt nGlobal; 248046bdb399SToby Isaac PetscInt *dnnz, *onnz; 2481b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2482b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 24831c58ffc4SToby Isaac PetscInt maxDof; 24841c58ffc4SToby Isaac PetscInt *rowIndices; 24851c58ffc4SToby Isaac DM refTree; 24861c58ffc4SToby Isaac PetscInt **refPointFieldN; 24871c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 24881c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 24890eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, maxConDof, maxColumns, leafStart, leafEnd; 24901c58ffc4SToby Isaac PetscScalar *pointWork; 249146bdb399SToby Isaac 24929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalFine, &nGlobal)); 24939566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nGlobal, &dnnz, nGlobal, &onnz)); 24949566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 24959566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 24969566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 24979566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 24989566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 24999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 25009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafIndicesSec, &leafStart, &leafEnd)); 25019566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 25020eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 250346bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 250446bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 250546bdb399SToby Isaac PetscInt matSize; 250621968bf8SToby Isaac PetscInt i; 250746bdb399SToby Isaac 25089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 25099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 2510ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 25119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 251208401ef6SPierre Jolivet PetscCheck(gOff >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I though having global dofs meant a non-negative offset"); 25131dca8a05SBarry Smith PetscCheck(gOff >= rowStart && (gOff + gDof - gcDof) <= rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I thought the row map would constrain the global dofs"); 25149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 25159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 251646bdb399SToby Isaac numColIndices -= 2 * numFields; 251708401ef6SPierre Jolivet PetscCheck(numColIndices > 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "global fine dof with no dofs to interpolate from"); 251846bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 251921968bf8SToby Isaac offsets[0] = 0; 252021968bf8SToby Isaac offsetsCopy[0] = 0; 252121968bf8SToby Isaac newOffsets[0] = 0; 252221968bf8SToby Isaac newOffsetsCopy[0] = 0; 252346bdb399SToby Isaac if (numFields) { 252421968bf8SToby Isaac PetscInt f; 252546bdb399SToby Isaac for (f = 0; f < numFields; f++) { 252646bdb399SToby Isaac PetscInt rowDof; 252746bdb399SToby Isaac 25289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 252921968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 253021968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 253121968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 253221968bf8SToby Isaac numD[f] = 0; 253321968bf8SToby Isaac numO[f] = 0; 253446bdb399SToby Isaac } 25359566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 253646bdb399SToby Isaac for (f = 0; f < numFields; f++) { 253721968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 253821968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 253946bdb399SToby Isaac 254046bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 254146bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 254246bdb399SToby Isaac 254346bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 254421968bf8SToby Isaac numD[f]++; 25459371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 254621968bf8SToby Isaac numO[f]++; 254746bdb399SToby Isaac } 254846bdb399SToby Isaac } 254946bdb399SToby Isaac } 25509371c9d4SSatish Balay } else { 25519566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 255221968bf8SToby Isaac numD[0] = 0; 255321968bf8SToby Isaac numO[0] = 0; 255446bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 255546bdb399SToby Isaac PetscInt gInd = pInd[i]; 255646bdb399SToby Isaac 255746bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 255821968bf8SToby Isaac numD[0]++; 25599371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 256021968bf8SToby Isaac numO[0]++; 256146bdb399SToby Isaac } 256246bdb399SToby Isaac } 256346bdb399SToby Isaac } 25649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 256546bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 256646bdb399SToby Isaac PetscInt childId; 256746bdb399SToby Isaac 256846bdb399SToby Isaac childId = childIds[p - pStartF]; 256921968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 257046bdb399SToby Isaac if (numFields) { 2571b9a5774bSToby Isaac PetscInt f; 2572b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 257321968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 257446bdb399SToby Isaac for (row = 0; row < numRows; row++) { 257521968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 257621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 257746bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25781dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2579b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25809371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25811dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2582b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25839371c9d4SSatish Balay } else { /* constrained */ 258408401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 258546bdb399SToby Isaac } 258646bdb399SToby Isaac } 258746bdb399SToby Isaac } 25889371c9d4SSatish Balay } else { 2589b9a5774bSToby Isaac PetscInt i; 2590b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 259146bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 259246bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 259346bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25941dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2595b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25969371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25971dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2598b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25999371c9d4SSatish Balay } else { /* constrained */ 260008401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 260146bdb399SToby Isaac } 260246bdb399SToby Isaac } 260346bdb399SToby Isaac } 26049371c9d4SSatish Balay } else { /* interpolate from all */ 260546bdb399SToby Isaac if (numFields) { 2606b9a5774bSToby Isaac PetscInt f; 2607b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 260821968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 260946bdb399SToby Isaac for (row = 0; row < numRows; row++) { 261021968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 261146bdb399SToby Isaac if (gIndFine >= 0) { 26121dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2613b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2614b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 261546bdb399SToby Isaac } 261646bdb399SToby Isaac } 261746bdb399SToby Isaac } 26189371c9d4SSatish Balay } else { 2619b9a5774bSToby Isaac PetscInt i; 2620b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 262146bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 262246bdb399SToby Isaac if (gIndFine >= 0) { 26231dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2624b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2625b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 262646bdb399SToby Isaac } 262746bdb399SToby Isaac } 262846bdb399SToby Isaac } 262946bdb399SToby Isaac } 26309371c9d4SSatish Balay } else { /* interpolate from all */ 263146bdb399SToby Isaac if (numFields) { 2632b9a5774bSToby Isaac PetscInt f; 2633b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 263421968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 263546bdb399SToby Isaac for (row = 0; row < numRows; row++) { 263621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 263746bdb399SToby Isaac if (gIndFine >= 0) { 26381dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2639b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2640b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 264146bdb399SToby Isaac } 264246bdb399SToby Isaac } 264346bdb399SToby Isaac } 26449371c9d4SSatish Balay } else { /* every dof get a full row */ 2645b9a5774bSToby Isaac PetscInt i; 2646b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 264746bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 264846bdb399SToby Isaac if (gIndFine >= 0) { 26491dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2650b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2651b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 265246bdb399SToby Isaac } 265346bdb399SToby Isaac } 265446bdb399SToby Isaac } 265546bdb399SToby Isaac } 265646bdb399SToby Isaac } 26579566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, dnnz, onnz, NULL, NULL)); 26589566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnnz, onnz)); 265921968bf8SToby Isaac 26609566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 26619566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 26629566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 26639566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 26649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 26659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxConDof)); 26669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(leafIndicesSec, &maxColumns)); 26679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConDof * maxColumns, &pointWork)); 26680eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2669e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2670e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2671e44e4e7fSToby Isaac PetscInt matSize; 2672e44e4e7fSToby Isaac PetscInt childId; 2673e44e4e7fSToby Isaac 26749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 26759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 2676ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 2677e44e4e7fSToby Isaac childId = childIds[p - pStartF]; 26789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 26799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 26809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 2681e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2682e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2683e44e4e7fSToby Isaac offsets[0] = 0; 2684e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2685e44e4e7fSToby Isaac newOffsets[0] = 0; 2686e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2687e44e4e7fSToby Isaac rowOffsets[0] = 0; 2688e44e4e7fSToby Isaac if (numFields) { 2689e44e4e7fSToby Isaac PetscInt f; 2690e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2691e44e4e7fSToby Isaac PetscInt rowDof; 2692e44e4e7fSToby Isaac 26939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 2694e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2695e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2696e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2697e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2698e44e4e7fSToby Isaac } 26999566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 27009371c9d4SSatish Balay } else { 27019566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 27021c58ffc4SToby Isaac } 27039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 2704e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2705e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2706e44e4e7fSToby Isaac if (numFields) { 2707e44e4e7fSToby Isaac PetscInt f; 2708e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2709e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 271048a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[offsets[f] + row], pInd[newOffsets[f] + row], 1., INSERT_VALUES)); 271121968bf8SToby Isaac } 27129371c9d4SSatish Balay } else { 2713e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 271448a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[row], pInd[row], 1., INSERT_VALUES)); 2715e44e4e7fSToby Isaac } 27169371c9d4SSatish Balay } else { /* interpolate from all */ 2717e44e4e7fSToby Isaac if (numFields) { 2718e44e4e7fSToby Isaac PetscInt f; 2719e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2720e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2721e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 27229566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], refPointFieldMats[childId - pRefStart][f], INSERT_VALUES)); 2723e44e4e7fSToby Isaac } 27249371c9d4SSatish Balay } else { 27259566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, refPointFieldMats[childId - pRefStart][0], INSERT_VALUES)); 2726e44e4e7fSToby Isaac } 2727e44e4e7fSToby Isaac } 27289371c9d4SSatish Balay } else { /* interpolate from all */ 2729e44e4e7fSToby Isaac PetscInt pMatOff; 2730e44e4e7fSToby Isaac PetscScalar *pMat; 2731e44e4e7fSToby Isaac 27329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafMatricesSec, p, &pMatOff)); 2733e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2734e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2735e44e4e7fSToby Isaac if (numFields) { 2736e44e4e7fSToby Isaac PetscInt f, count; 2737e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2738e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2739e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2740e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2741e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2742e44e4e7fSToby Isaac 27439566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], inMat, INSERT_VALUES)); 2744e44e4e7fSToby Isaac count += numCols * numInRows; 2745e44e4e7fSToby Isaac } 27469371c9d4SSatish Balay } else { 27479566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, pMat, INSERT_VALUES)); 2748e44e4e7fSToby Isaac } 27499371c9d4SSatish Balay } else { /* multiply the incoming matrix by the child interpolation */ 2750e44e4e7fSToby Isaac if (numFields) { 2751e44e4e7fSToby Isaac PetscInt f, count; 2752e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2753e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2754e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2755e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2756e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2757e44e4e7fSToby Isaac PetscInt i, j, k; 275808401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][f] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2759e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2760e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2761e44e4e7fSToby Isaac PetscScalar val = 0.; 2762ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2763e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2764e44e4e7fSToby Isaac } 2765e44e4e7fSToby Isaac } 27669566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], pointWork, INSERT_VALUES)); 2767e44e4e7fSToby Isaac count += numCols * numInRows; 2768e44e4e7fSToby Isaac } 27699371c9d4SSatish Balay } else { /* every dof gets a full row */ 2770e44e4e7fSToby Isaac PetscInt numRows = gDof; 2771e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2772e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2773e44e4e7fSToby Isaac PetscInt i, j, k; 277408401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][0] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2775e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2776e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2777e44e4e7fSToby Isaac PetscScalar val = 0.; 2778ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2779e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2780e44e4e7fSToby Isaac } 2781e44e4e7fSToby Isaac } 27829566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, rowIndices, numCols, pInd, pointWork, INSERT_VALUES)); 2783e44e4e7fSToby Isaac } 2784e44e4e7fSToby Isaac } 2785e44e4e7fSToby Isaac } 2786e44e4e7fSToby Isaac } 27879566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 27889566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 27899566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 2790e44e4e7fSToby Isaac } 27919566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 27929566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 27939566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 27949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafMatricesSec)); 27959566063dSJacob Faibussowitsch PetscCall(PetscFree2(leafIndices, leafMatrices)); 27969566063dSJacob Faibussowitsch PetscCall(PetscFree2(*(PetscInt ****)&perms, *(PetscScalar ****)&flips)); 27979566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 27989566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 27996ecaa68aSToby Isaac PetscFunctionReturn(0); 28006ecaa68aSToby Isaac } 2801154bca37SToby Isaac 28028d2f55e7SToby Isaac /* 28038d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 28048d2f55e7SToby Isaac * 28058d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 28068d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 28078d2f55e7SToby Isaac * for each fine dof \phi^f_j; 28088d2f55e7SToby Isaac * a_{i,j} = 0; 28098d2f55e7SToby Isaac * for each fine dof \phi^f_k: 28108d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 28118d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 28128d2f55e7SToby Isaac */ 2813*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 2814*d71ae5a4SJacob Faibussowitsch { 28158d2f55e7SToby Isaac PetscDS ds; 28168d2f55e7SToby Isaac PetscSection section, cSection; 28178d2f55e7SToby Isaac DMLabel canonical, depth; 28188d2f55e7SToby Isaac Mat cMat, mat; 28198d2f55e7SToby Isaac PetscInt *nnz; 28208d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 28218d2f55e7SToby Isaac PetscInt m, n; 28228d2f55e7SToby Isaac PetscScalar *pointScalar; 28238d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 28248d2f55e7SToby Isaac 28258d2f55e7SToby Isaac PetscFunctionBegin; 28269566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, §ion)); 28279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(refTree, &dim)); 28289566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(dim, &v0, dim, &v0parent, dim, &vtmp, dim * dim, &J, dim * dim, &Jparent, dim * dim, &invJ)); 28299566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim, &pointScalar, dim, &pointRef)); 28309566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 28319566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 28329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numSecFields)); 28339566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical)); 28349566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "depth", &depth)); 28359566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSection, &cMat, NULL)); 28369566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(refTree, &pStart, &pEnd)); 28379566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd)); 28389566063dSJacob Faibussowitsch PetscCall(MatGetSize(cMat, &n, &m)); /* the injector has transpose sizes from the constraint matrix */ 28398d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 28409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 28418d2f55e7SToby 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 */ 28428d2f55e7SToby Isaac const PetscInt *children; 28438d2f55e7SToby Isaac PetscInt numChildren; 28448d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28458d2f55e7SToby Isaac 28468d2f55e7SToby Isaac if (canonical) { 28478d2f55e7SToby Isaac PetscInt pCanonical; 28489566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28498d2f55e7SToby Isaac if (p != pCanonical) continue; 28508d2f55e7SToby Isaac } 28519566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28528d2f55e7SToby Isaac if (!numChildren) continue; 28538d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28548d2f55e7SToby Isaac PetscInt child = children[i]; 28558d2f55e7SToby Isaac PetscInt dof; 28568d2f55e7SToby Isaac 28579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 28588d2f55e7SToby Isaac numChildDof += dof; 28598d2f55e7SToby Isaac } 28609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 28618d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 28628d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 28638d2f55e7SToby Isaac PetscInt selfOff; 28648d2f55e7SToby Isaac 28658d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 28668d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28678d2f55e7SToby Isaac PetscInt child = children[i]; 28688d2f55e7SToby Isaac PetscInt dof; 28698d2f55e7SToby Isaac 28709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 28718d2f55e7SToby Isaac numChildDof += dof; 28728d2f55e7SToby Isaac } 28739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 28749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 28759371c9d4SSatish Balay } else { 28769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 28778d2f55e7SToby Isaac } 2878ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) nnz[selfOff + i] = numChildDof; 28798d2f55e7SToby Isaac } 28808d2f55e7SToby Isaac } 28819566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(PETSC_COMM_SELF, m, n, m, n, -1, nnz, -1, NULL, &mat)); 28829566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 28838d2f55e7SToby Isaac /* Setp 2: compute entries */ 28848d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 28858d2f55e7SToby Isaac const PetscInt *children; 28868d2f55e7SToby Isaac PetscInt numChildren; 28878d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28888d2f55e7SToby Isaac 28898d2f55e7SToby Isaac /* same conditions about when entries occur */ 28908d2f55e7SToby Isaac if (canonical) { 28918d2f55e7SToby Isaac PetscInt pCanonical; 28929566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28938d2f55e7SToby Isaac if (p != pCanonical) continue; 28948d2f55e7SToby Isaac } 28959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28968d2f55e7SToby Isaac if (!numChildren) continue; 28978d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28988d2f55e7SToby Isaac PetscInt child = children[i]; 28998d2f55e7SToby Isaac PetscInt dof; 29008d2f55e7SToby Isaac 29019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 29028d2f55e7SToby Isaac numChildDof += dof; 29038d2f55e7SToby Isaac } 29049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 29058d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 29068d2f55e7SToby Isaac 29078d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 290859fc6756SToby Isaac PetscInt pI = -1, cI = -1; 290952a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell; 29108d2f55e7SToby Isaac PetscInt cellShapeOff; 29118d2f55e7SToby Isaac PetscObject disc; 29128d2f55e7SToby Isaac PetscDualSpace dsp; 29138d2f55e7SToby Isaac PetscClassId classId; 29148d2f55e7SToby Isaac PetscScalar *pointMat; 29153b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 29168d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 29178d2f55e7SToby Isaac const PetscInt *depthNumDof; 29188d2f55e7SToby Isaac 29198d2f55e7SToby Isaac if (numSecFields) { 29208d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 29218d2f55e7SToby Isaac PetscInt child = children[i]; 29228d2f55e7SToby Isaac PetscInt dof; 29238d2f55e7SToby Isaac 29249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 29258d2f55e7SToby Isaac numChildDof += dof; 29268d2f55e7SToby Isaac } 29279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 29289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 29299371c9d4SSatish Balay } else { 29309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 29318d2f55e7SToby Isaac } 29328d2f55e7SToby Isaac 29333b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 29348d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 29358d2f55e7SToby Isaac parentCell = p; 29369371c9d4SSatish Balay } else { 29378d2f55e7SToby Isaac PetscInt *star = NULL; 29388d2f55e7SToby Isaac PetscInt numStar; 29398d2f55e7SToby Isaac 29408d2f55e7SToby Isaac parentCell = -1; 29419566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29428d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 29438d2f55e7SToby Isaac PetscInt c = star[2 * i]; 29448d2f55e7SToby Isaac 29458d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 29468d2f55e7SToby Isaac parentCell = c; 29478d2f55e7SToby Isaac break; 29488d2f55e7SToby Isaac } 29498d2f55e7SToby Isaac } 29509566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29518d2f55e7SToby Isaac } 2952a5b23f4aSJose E. Roman /* determine the offset of p's shape functions within parentCell's shape functions */ 29539566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 29549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &classId)); 2955c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 29569566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 29579371c9d4SSatish Balay } else if (classId == PETSCFV_CLASSID) { 29589566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace((PetscFV)disc, &dsp)); 29599371c9d4SSatish Balay } else { 29609b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported discretization object"); 2961c5356c36SToby Isaac } 29629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dsp, &depthNumDof)); 29639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dsp, &Nc)); 29648d2f55e7SToby Isaac { 29658d2f55e7SToby Isaac PetscInt *closure = NULL; 29668d2f55e7SToby Isaac PetscInt numClosure; 29678d2f55e7SToby Isaac 29689566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 296959fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) { 29708d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 29718d2f55e7SToby Isaac 29728d2f55e7SToby Isaac pO = closure[2 * i + 1]; 297359fc6756SToby Isaac if (point == p) { 297459fc6756SToby Isaac pI = i; 297559fc6756SToby Isaac break; 297659fc6756SToby Isaac } 29779566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 29788d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 29798d2f55e7SToby Isaac } 29809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 29818d2f55e7SToby Isaac } 29828d2f55e7SToby Isaac 29839566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 29849566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 298552a3aeb4SToby Isaac matCols = matRows + numSelfDof; 2986ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) matRows[i] = selfOff + i; 298752a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.; 29883b1c2a6aSToby Isaac { 29893b1c2a6aSToby Isaac PetscInt colOff = 0; 29903b1c2a6aSToby Isaac 29913b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 29923b1c2a6aSToby Isaac PetscInt child = children[i]; 29933b1c2a6aSToby Isaac PetscInt dof, off, j; 29943b1c2a6aSToby Isaac 29953b1c2a6aSToby Isaac if (numSecFields) { 29969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSection, child, f, &dof)); 29979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSection, child, f, &off)); 29989371c9d4SSatish Balay } else { 29999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSection, child, &dof)); 30009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSection, child, &off)); 30013b1c2a6aSToby Isaac } 30023b1c2a6aSToby Isaac 3003ad540459SPierre Jolivet for (j = 0; j < dof; j++) matCols[colOff++] = off + j; 30043b1c2a6aSToby Isaac } 30053b1c2a6aSToby Isaac } 30068d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 30078d2f55e7SToby Isaac PetscFE fe = (PetscFE)disc; 30088d2f55e7SToby Isaac PetscInt fSize; 300959fc6756SToby Isaac const PetscInt ***perms; 301059fc6756SToby Isaac const PetscScalar ***flips; 301159fc6756SToby Isaac const PetscInt *pperms; 301259fc6756SToby Isaac 30139566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dsp)); 30149566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dsp, &fSize)); 30159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dsp, &perms, &flips)); 301659fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL; 301752a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */ 30188d2f55e7SToby Isaac PetscQuadrature q; 301952a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k; 30208d2f55e7SToby Isaac const PetscReal *points; 30218d2f55e7SToby Isaac const PetscReal *weights; 30228d2f55e7SToby Isaac PetscInt *closure = NULL; 30238d2f55e7SToby Isaac PetscInt numClosure; 302459fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i; 302559fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell; 3026ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent; 30278d2f55e7SToby Isaac 30289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dsp, parentCellShapeDof, &q)); 30299566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, &thisNc, &numPoints, &points, &weights)); 303063a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 30319566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, numPoints, points, 0, &Tparent)); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 30323b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 30338d2f55e7SToby Isaac PetscInt childCell = -1; 303452a3aeb4SToby Isaac PetscReal *parentValAtPoint; 3035c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 30368d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 30378d2f55e7SToby Isaac const PetscScalar *point; 3038ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild; 30398d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 30408d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 30418d2f55e7SToby Isaac PetscInt d; 30428d2f55e7SToby Isaac 3043ad540459SPierre Jolivet for (d = 0; d < dim; d++) pointScalar[d] = points[dim * j + d]; 30448d2f55e7SToby Isaac point = pointScalar; 30458d2f55e7SToby Isaac #else 30468d2f55e7SToby Isaac point = pointReal; 30478d2f55e7SToby Isaac #endif 30488d2f55e7SToby Isaac 3049ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc]; 30503b1c2a6aSToby Isaac 30513b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 30528d2f55e7SToby Isaac PetscInt child = children[k]; 30538d2f55e7SToby Isaac PetscInt *star = NULL; 30548d2f55e7SToby Isaac PetscInt numStar, s; 30558d2f55e7SToby Isaac 30569566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30578d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 30588d2f55e7SToby Isaac PetscInt c = star[2 * s]; 30598d2f55e7SToby Isaac 30608d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 30619566063dSJacob Faibussowitsch PetscCall(DMPlexLocatePoint_Internal(refTree, dim, point, c, &childCell)); 30628d2f55e7SToby Isaac if (childCell >= 0) break; 30638d2f55e7SToby Isaac } 30649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30658d2f55e7SToby Isaac if (childCell >= 0) break; 30668d2f55e7SToby Isaac } 306708401ef6SPierre Jolivet PetscCheck(childCell >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not locate quadrature point"); 30689566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ)); 30699566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent)); 3070c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp); 3071c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef); 30728d2f55e7SToby Isaac 30739566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, 1, pointRef, 0, &Tchild)); 30749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 30753b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3076c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 30778d2f55e7SToby Isaac PetscInt l; 307859fc6756SToby Isaac const PetscInt *cperms; 30798d2f55e7SToby Isaac 30809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, child, &childDepth)); 30818d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 308259fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) { 30838d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 30848d2f55e7SToby Isaac PetscInt pointDepth; 30858d2f55e7SToby Isaac 30868d2f55e7SToby Isaac childO = closure[2 * l + 1]; 308759fc6756SToby Isaac if (point == child) { 308859fc6756SToby Isaac cI = l; 308959fc6756SToby Isaac break; 309059fc6756SToby Isaac } 30919566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 30928d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 30938d2f55e7SToby Isaac } 30948d2f55e7SToby Isaac if (l == numClosure) { 30958d2f55e7SToby Isaac pointMatOff += childDof; 30968d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 30978d2f55e7SToby Isaac } 309859fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL; 30998d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 310059fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l; 310159fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell; 310252a3aeb4SToby Isaac PetscReal *childValAtPoint; 310352a3aeb4SToby Isaac PetscReal val = 0.; 31048d2f55e7SToby Isaac 3105ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc]; 3106ad540459SPierre Jolivet for (m = 0; m < Nc; m++) val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m]; 310752a3aeb4SToby Isaac 310852a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val; 31098d2f55e7SToby Isaac } 31108d2f55e7SToby Isaac pointMatOff += childDof; 31118d2f55e7SToby Isaac } 31129566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 31139566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tchild)); 31148d2f55e7SToby Isaac } 31159566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tparent)); 31168d2f55e7SToby Isaac } 31179371c9d4SSatish Balay } else { /* just the volume-weighted averages of the children */ 31183b1c2a6aSToby Isaac PetscReal parentVol; 3119bfaa5bdcSToby Isaac PetscInt childCell; 31203b1c2a6aSToby Isaac 31219566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL)); 3122bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) { 312352a3aeb4SToby Isaac PetscInt child = children[i], j; 31243b1c2a6aSToby Isaac PetscReal childVol; 31253b1c2a6aSToby Isaac 31263b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 31279566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL)); 3128ad540459SPierre Jolivet for (j = 0; j < Nc; j++) pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol; 3129bfaa5bdcSToby Isaac childCell++; 31303b1c2a6aSToby Isaac } 31318d2f55e7SToby Isaac } 31323b1c2a6aSToby Isaac /* Insert pointMat into mat */ 31339566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numSelfDof, matRows, numChildDof, matCols, pointMat, INSERT_VALUES)); 31349566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 31359566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 31368d2f55e7SToby Isaac } 31378d2f55e7SToby Isaac } 31389566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJ)); 31399566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointScalar, pointRef)); 31409566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 31419566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 31428d2f55e7SToby Isaac *inj = mat; 31438d2f55e7SToby Isaac PetscFunctionReturn(0); 31448d2f55e7SToby Isaac } 31458d2f55e7SToby Isaac 3146*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3147*d71ae5a4SJacob Faibussowitsch { 3148f30e825dSToby Isaac PetscDS ds; 3149f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3150f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3151f30e825dSToby Isaac PetscSection refConSec, refSection; 3152f30e825dSToby Isaac 3153f30e825dSToby Isaac PetscFunctionBegin; 31549566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 31559566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 31569566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 31579566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 31589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 31599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 31609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 31619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 31629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &cols)); 3163f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3164f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3165f30e825dSToby Isaac 31669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 31679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 31689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3169f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3170f30e825dSToby Isaac 31719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFields, &refPointFieldMats[p - pRefStart])); 3172f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 317352a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r; 3174f30e825dSToby Isaac 3175f30e825dSToby Isaac if (numFields > 1) { 31769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 31779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 31789371c9d4SSatish Balay } else { 31799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 31809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 3181f30e825dSToby Isaac } 3182f30e825dSToby Isaac 3183ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r; 3184f30e825dSToby Isaac numCols = 0; 3185f30e825dSToby Isaac { 3186f30e825dSToby Isaac PetscInt aDof, aOff, j; 3187f30e825dSToby Isaac 3188f30e825dSToby Isaac if (numFields > 1) { 31899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, parent, f, &aDof)); 31909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, parent, f, &aOff)); 31919371c9d4SSatish Balay } else { 31929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &aDof)); 31939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, parent, &aOff)); 3194f30e825dSToby Isaac } 3195f30e825dSToby Isaac 3196ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + j; 3197f30e825dSToby Isaac } 31989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 3199f30e825dSToby Isaac /* transpose of constraint matrix */ 32009566063dSJacob Faibussowitsch PetscCall(MatGetValues(inj, numCols, cols, cDof, rows, refPointFieldMats[p - pRefStart][f])); 3201f30e825dSToby Isaac } 3202f30e825dSToby Isaac } 3203f30e825dSToby Isaac *childrenMats = refPointFieldMats; 32049566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 32059566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 3206f30e825dSToby Isaac PetscFunctionReturn(0); 3207f30e825dSToby Isaac } 3208f30e825dSToby Isaac 3209*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3210*d71ae5a4SJacob Faibussowitsch { 3211f30e825dSToby Isaac PetscDS ds; 3212f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3213f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3214c6154584SToby Isaac PetscSection refConSec, refSection; 3215f30e825dSToby Isaac 3216f30e825dSToby Isaac PetscFunctionBegin; 3217f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3218f30e825dSToby Isaac *childrenMats = NULL; 32199566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 32209566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 32219566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 32229566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 32239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 3224f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3225f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3226f30e825dSToby Isaac 32279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 32289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 32299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3230f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3231f30e825dSToby Isaac 3232f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3233f30e825dSToby Isaac PetscInt cDof; 3234f30e825dSToby Isaac 3235f30e825dSToby Isaac if (numFields > 1) { 32369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 32379371c9d4SSatish Balay } else { 32389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 3239f30e825dSToby Isaac } 3240f30e825dSToby Isaac 32419566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 3242f30e825dSToby Isaac } 32439566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 3244f30e825dSToby Isaac } 32459566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 3246f30e825dSToby Isaac PetscFunctionReturn(0); 3247f30e825dSToby Isaac } 3248f30e825dSToby Isaac 3249*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree, Mat *injRef) 3250*d71ae5a4SJacob Faibussowitsch { 3251ebf164c7SToby Isaac Mat cMatRef; 32526148253fSToby Isaac PetscObject injRefObj; 32538d2f55e7SToby Isaac 3254154bca37SToby Isaac PetscFunctionBegin; 32559566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, NULL, &cMatRef, NULL)); 32569566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", &injRefObj)); 3257ebf164c7SToby Isaac *injRef = (Mat)injRefObj; 3258ebf164c7SToby Isaac if (!*injRef) { 32599566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorReferenceTree(refTree, injRef)); 32609566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", (PetscObject)*injRef)); 3261ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 32629566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)*injRef)); 3263ebf164c7SToby Isaac } 3264ebf164c7SToby Isaac PetscFunctionReturn(0); 32656148253fSToby Isaac } 3266f30e825dSToby Isaac 3267*d71ae5a4SJacob 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) 3268*d71ae5a4SJacob Faibussowitsch { 3269c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3270ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3271ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3272c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3273c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3274c921d74cSToby Isaac const PetscInt *rootDegrees; 3275c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3276ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3277ebf164c7SToby Isaac 3278ebf164c7SToby Isaac PetscFunctionBegin; 32799566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 32809566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 32819566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 32829566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 32839566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 32849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafIndicesSec, pStartF, pEndF)); 32859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 32868d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 32877e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 32887e96bdafSToby Isaac const PetscInt *leaves; 32898d2f55e7SToby Isaac 32909566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 32917e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 32927e96bdafSToby Isaac p = leaves ? leaves[l] : l; 32939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 32949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 32958d2f55e7SToby Isaac if ((dof - cdof) > 0) { 32968d2f55e7SToby Isaac numPointsWithDofs++; 3297f30e825dSToby Isaac 32989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &dof)); 32999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafIndicesSec, p, dof + 1)); 33008d2f55e7SToby Isaac } 33018d2f55e7SToby Isaac } 33029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 33039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafIndicesSec)); 33049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numIndices)); 33059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1), &leafInds)); 33069566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(PetscMalloc1(numIndices, &leafVals)); 33077e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 33087e96bdafSToby Isaac p = leaves ? leaves[l] : l; 33099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 33109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 33118d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3312f30e825dSToby Isaac PetscInt off, gOff; 3313f30e825dSToby Isaac PetscInt *pInd; 3314c921d74cSToby Isaac PetscScalar *pVal = NULL; 3315f30e825dSToby Isaac 33167e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3317f30e825dSToby Isaac 33189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3319f30e825dSToby Isaac 3320c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3321c921d74cSToby Isaac if (gatheredValues) { 3322c921d74cSToby Isaac PetscInt i; 3323c921d74cSToby Isaac 3324c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3325c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3326c921d74cSToby Isaac } 33279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 3328f30e825dSToby Isaac 3329f30e825dSToby Isaac offsets[0] = 0; 3330f30e825dSToby Isaac if (numFields) { 3331f30e825dSToby Isaac PetscInt f; 3332f30e825dSToby Isaac 3333f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3334f30e825dSToby Isaac PetscInt fDof; 33359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &fDof)); 3336f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3337f30e825dSToby Isaac } 33389566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 3339367003a6SStefano Zampini } else { 33409566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 3341f30e825dSToby Isaac } 33429566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(VecGetValues(fineVec, dof, pInd, pVal)); 33438d2f55e7SToby Isaac } 33448d2f55e7SToby Isaac } 33459566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 33469566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 33478d2f55e7SToby Isaac } 3348f30e825dSToby Isaac 33499566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 33509566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 33519566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 3352f30e825dSToby Isaac 33536148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 33546148253fSToby Isaac MPI_Datatype threeInt; 33556148253fSToby Isaac PetscMPIInt rank; 33566148253fSToby Isaac PetscInt(*parentNodeAndIdCoarse)[3]; 33576148253fSToby Isaac PetscInt(*parentNodeAndIdFine)[3]; 33586148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 33596148253fSToby Isaac PetscSF pointSF, sfToParents; 33606148253fSToby Isaac const PetscInt *ilocal; 33616148253fSToby Isaac const PetscSFNode *iremote; 33626148253fSToby Isaac PetscSFNode *iremoteToParents; 33636148253fSToby Isaac PetscInt *ilocalToParents; 33646148253fSToby Isaac 33659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)coarse), &rank)); 33669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &threeInt)); 33679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&threeInt)); 33689566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndC - pStartC, &parentNodeAndIdCoarse, pEndF - pStartF, &parentNodeAndIdFine)); 33699566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(coarse, &pointSF)); 33709566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &nleaves, &ilocal, &iremote)); 33716148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 33726148253fSToby Isaac PetscInt parent, childId; 33739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(coarse, p, &parent, &childId)); 33746148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 33756148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 33766148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 33776148253fSToby Isaac if (nleaves > 0) { 33786148253fSToby Isaac PetscInt leaf = -1; 33796148253fSToby Isaac 33806148253fSToby Isaac if (ilocal) { 33819566063dSJacob Faibussowitsch PetscCall(PetscFindInt(parent, nleaves, ilocal, &leaf)); 33829371c9d4SSatish Balay } else { 33836148253fSToby Isaac leaf = p - pStartC; 33846148253fSToby Isaac } 33856148253fSToby Isaac if (leaf >= 0) { 33866148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 33876148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 33886148253fSToby Isaac } 33896148253fSToby Isaac } 33906148253fSToby Isaac } 33916148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 33926148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 33936148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 33946148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 33956148253fSToby Isaac } 33969566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 33979566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 33986148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3399f30e825dSToby Isaac PetscInt dof; 3400f30e825dSToby Isaac 34019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &dof)); 3402f30e825dSToby Isaac if (dof) { 3403f30e825dSToby Isaac PetscInt off; 3404f30e825dSToby Isaac 34059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3406c921d74cSToby Isaac if (gatheredIndices) { 3407c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3408c921d74cSToby Isaac } else if (gatheredValues) { 3409c921d74cSToby Isaac leafVals[off] = (PetscScalar)PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3410c921d74cSToby Isaac } 3411f30e825dSToby Isaac } 3412ad540459SPierre Jolivet if (parentNodeAndIdFine[p - pStartF][0] >= 0) nleavesToParents++; 34136148253fSToby Isaac } 34149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &ilocalToParents)); 34159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &iremoteToParents)); 34166148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 34176148253fSToby Isaac if (parentNodeAndIdFine[p - pStartF][0] >= 0) { 34186148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 34196148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p - pStartF][0]; 34206148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p - pStartF][1]; 34216148253fSToby Isaac nleavesToParents++; 34226148253fSToby Isaac } 34236148253fSToby Isaac } 34249566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)coarse), &sfToParents)); 34259566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfToParents, pEndC - pStartC, nleavesToParents, ilocalToParents, PETSC_OWN_POINTER, iremoteToParents, PETSC_OWN_POINTER)); 34269566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34276148253fSToby Isaac 34286148253fSToby Isaac coarseToFineEmbedded = sfToParents; 34296148253fSToby Isaac 34309566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentNodeAndIdCoarse, parentNodeAndIdFine)); 34319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&threeInt)); 34326148253fSToby Isaac } 3433f30e825dSToby Isaac 34346148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 34356148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 34366148253fSToby Isaac PetscSF sfDofsOnly; 34376148253fSToby Isaac 34386148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 34399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3441ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 34426148253fSToby Isaac } 34439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 34446148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 34459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3447ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = p - pStartC; 34486148253fSToby Isaac } 34499566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly)); 34509566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34519566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 34526148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 34536148253fSToby Isaac } 3454f30e825dSToby Isaac 34556148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 34569566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(coarseToFineEmbedded, &rootDegrees)); 34579566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(coarseToFineEmbedded, &rootDegrees)); 34589566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &multiRootSec)); 34599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(multiRootSec, pStartC, pEndC)); 346048a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionSetDof(multiRootSec, p, rootDegrees[p - pStartC])); 34619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(multiRootSec)); 34629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(multiRootSec, &numMulti)); 34639566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 3464f30e825dSToby Isaac { /* distribute the leaf section */ 3465f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3466f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 34678d2f55e7SToby Isaac 34689566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(coarseToFineEmbedded, &multi)); 34699566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(multi, &multiInv)); 34709566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(multiInv, leafIndicesSec, &remoteOffsets, rootIndicesSec)); 34719566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(multiInv, leafIndicesSec, remoteOffsets, rootIndicesSec, &indicesSF)); 34729566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 34739566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&multiInv)); 34749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 3475c921d74cSToby Isaac if (gatheredIndices) { 34769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootInds)); 34779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 34789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 3479c921d74cSToby Isaac } 3480c921d74cSToby Isaac if (gatheredValues) { 34819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootVals)); 34829566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 34839566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 3484c921d74cSToby Isaac } 34859566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 34868d2f55e7SToby Isaac } 34879566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 34889566063dSJacob Faibussowitsch PetscCall(PetscFree(leafInds)); 34899566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVals)); 34909566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 3491c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3492c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3493c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3494c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 3495ebf164c7SToby Isaac PetscFunctionReturn(0); 3496ebf164c7SToby Isaac } 3497ebf164c7SToby Isaac 3498*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3499*d71ae5a4SJacob Faibussowitsch { 3500ebf164c7SToby Isaac DM refTree; 3501c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3502ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3503ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3504ebf164c7SToby Isaac PetscSection cSecRef; 3505277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd; 3506ebf164c7SToby Isaac Mat injRef; 3507c921d74cSToby Isaac PetscInt numFields, maxDof; 3508ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3509ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3510ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3511ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3512ebf164c7SToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3513ebf164c7SToby Isaac 3514ebf164c7SToby Isaac PetscFunctionBegin; 3515ebf164c7SToby Isaac 3516ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 35179566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 35189566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 35199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 35209566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 3521ebf164c7SToby Isaac 35229566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 35239566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 35249566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 35259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 35269566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 35279566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 35289566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 35299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 3530ebf164c7SToby Isaac { 3531ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 35329566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 3533ebf164c7SToby Isaac } 3534ebf164c7SToby Isaac 35359566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, childIds, NULL, numFields, offsets, &multiRootSec, &rootIndicesSec, &rootIndices, NULL)); 35368d2f55e7SToby Isaac 35379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &parentIndices)); 3538f30e825dSToby Isaac 3539f30e825dSToby Isaac /* count indices */ 35409566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 35419566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 35429566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 35439566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 35449566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 35459566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(rowEnd - rowStart, &nnzD, rowEnd - rowStart, &nnzO)); 3546f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3547f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 35488d2f55e7SToby Isaac 35499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 35509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3551f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 35529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 35538d2f55e7SToby Isaac 35548d2f55e7SToby Isaac rowOffsets[0] = 0; 3555f30e825dSToby Isaac offsetsCopy[0] = 0; 35568d2f55e7SToby Isaac if (numFields) { 35578d2f55e7SToby Isaac PetscInt f; 35588d2f55e7SToby Isaac 3559f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3560f30e825dSToby Isaac PetscInt fDof; 35619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3562f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 35638d2f55e7SToby Isaac } 35649566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3565367003a6SStefano Zampini } else { 35669566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3567f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 35688d2f55e7SToby Isaac } 3569f30e825dSToby Isaac 35709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 35719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3572f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3573f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3574f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3575f30e825dSToby Isaac const PetscInt *childIndices; 3576f30e825dSToby Isaac 35779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 35789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3579f30e825dSToby Isaac childId = rootIndices[offset++]; 3580f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3581f30e825dSToby Isaac numIndices--; 3582f30e825dSToby Isaac 3583f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3584f30e825dSToby Isaac PetscInt i; 3585f30e825dSToby Isaac 3586f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3587f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3588f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3589f30e825dSToby Isaac if (rowIndex < 0) continue; 359008401ef6SPierre Jolivet PetscCheck(colIndex >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unconstrained fine and constrained coarse"); 3591a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3592f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 35939371c9d4SSatish Balay } else { 3594f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3595f30e825dSToby Isaac } 3596f30e825dSToby Isaac } 35979371c9d4SSatish Balay } else { 3598f30e825dSToby Isaac PetscInt parentId, f, lim; 3599f30e825dSToby Isaac 36009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3601f30e825dSToby Isaac 3602f30e825dSToby Isaac lim = PetscMax(1, numFields); 3603f30e825dSToby Isaac offsets[0] = 0; 36048d2f55e7SToby Isaac if (numFields) { 36058d2f55e7SToby Isaac PetscInt f; 3606f30e825dSToby Isaac 36078d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3608f30e825dSToby Isaac PetscInt fDof; 36099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3610f30e825dSToby Isaac 3611f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 36128d2f55e7SToby Isaac } 36139371c9d4SSatish Balay } else { 3614f30e825dSToby Isaac PetscInt cDof; 3615f30e825dSToby Isaac 36169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3617f30e825dSToby Isaac offsets[1] = cDof; 3618f30e825dSToby Isaac } 3619f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3620f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3621f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3622f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3623f30e825dSToby Isaac 3624f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3625f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3626f30e825dSToby Isaac 3627f30e825dSToby Isaac if (colIndex < 0) continue; 3628f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3629f30e825dSToby Isaac numD++; 36309371c9d4SSatish Balay } else { 3631f30e825dSToby Isaac numO++; 3632f30e825dSToby Isaac } 3633f30e825dSToby Isaac } 3634f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3635f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3636f30e825dSToby Isaac 3637f30e825dSToby Isaac if (rowIndex < 0) continue; 3638f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3639f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 36408d2f55e7SToby Isaac } 36418d2f55e7SToby Isaac } 36428d2f55e7SToby Isaac } 3643f30e825dSToby Isaac } 3644f30e825dSToby Isaac } 3645f30e825dSToby Isaac /* preallocate */ 36469566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, nnzD, nnzO, NULL, NULL)); 36479566063dSJacob Faibussowitsch PetscCall(PetscFree2(nnzD, nnzO)); 3648f30e825dSToby Isaac /* insert values */ 36499566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 3650f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3651f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3652f30e825dSToby Isaac 36539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 36549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3655f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 36569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 3657f30e825dSToby Isaac 3658f30e825dSToby Isaac rowOffsets[0] = 0; 3659f30e825dSToby Isaac offsetsCopy[0] = 0; 36608d2f55e7SToby Isaac if (numFields) { 36618d2f55e7SToby Isaac PetscInt f; 3662f30e825dSToby Isaac 36638d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3664f30e825dSToby Isaac PetscInt fDof; 36659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3666f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3667f30e825dSToby Isaac } 36689566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3669367003a6SStefano Zampini } else { 36709566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3671f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3672f30e825dSToby Isaac } 3673f30e825dSToby Isaac 36749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 36759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3676f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3677f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3678f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3679f30e825dSToby Isaac const PetscInt *childIndices; 3680f30e825dSToby Isaac 36819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 36829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3683f30e825dSToby Isaac childId = rootIndices[offset++]; 3684f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3685f30e825dSToby Isaac numIndices--; 3686f30e825dSToby Isaac 3687f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3688f30e825dSToby Isaac PetscInt i; 3689f30e825dSToby Isaac 369048a46eb9SPierre Jolivet for (i = 0; i < numIndices; i++) PetscCall(MatSetValue(mat, parentIndices[i], childIndices[i], 1., INSERT_VALUES)); 36919371c9d4SSatish Balay } else { 3692f30e825dSToby Isaac PetscInt parentId, f, lim; 36938d2f55e7SToby Isaac 36949566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3695f30e825dSToby Isaac 3696f30e825dSToby Isaac lim = PetscMax(1, numFields); 3697f30e825dSToby Isaac offsets[0] = 0; 36988d2f55e7SToby Isaac if (numFields) { 3699f30e825dSToby Isaac PetscInt f; 37008d2f55e7SToby Isaac 3701f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3702f30e825dSToby Isaac PetscInt fDof; 37039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3704f30e825dSToby Isaac 3705f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 37068d2f55e7SToby Isaac } 37079371c9d4SSatish Balay } else { 3708f30e825dSToby Isaac PetscInt cDof; 3709f30e825dSToby Isaac 37109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3711f30e825dSToby Isaac offsets[1] = cDof; 37128d2f55e7SToby Isaac } 3713f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3714f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3715f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3716f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3717f30e825dSToby Isaac 37189566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, rowOffsets[f + 1] - rowOffsets[f], rowIndices, offsets[f + 1] - offsets[f], colIndices, childMat, INSERT_VALUES)); 37198d2f55e7SToby Isaac } 37208d2f55e7SToby Isaac } 37218d2f55e7SToby Isaac } 37228d2f55e7SToby Isaac } 37239566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 37249566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 37259566063dSJacob Faibussowitsch PetscCall(PetscFree(parentIndices)); 37269566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 37279566063dSJacob Faibussowitsch PetscCall(PetscFree(rootIndices)); 37289566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 3729f30e825dSToby Isaac 37309566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 37319566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 3732154bca37SToby Isaac PetscFunctionReturn(0); 3733154bca37SToby Isaac } 373438fc2455SToby Isaac 3735*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 3736*d71ae5a4SJacob Faibussowitsch { 373762095d54SToby Isaac PetscSF coarseToFineEmbedded; 373862095d54SToby Isaac PetscSection globalCoarse, globalFine; 373962095d54SToby Isaac PetscSection localCoarse, localFine; 374062095d54SToby Isaac PetscSection aSec, cSec; 374162095d54SToby Isaac PetscSection rootValuesSec; 374262095d54SToby Isaac PetscSection leafValuesSec; 374362095d54SToby Isaac PetscScalar *rootValues, *leafValues; 374462095d54SToby Isaac IS aIS; 374562095d54SToby Isaac const PetscInt *anchors; 374662095d54SToby Isaac Mat cMat; 374762095d54SToby Isaac PetscInt numFields; 3748412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd; 374962095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 375062095d54SToby Isaac PetscInt *maxChildIds; 375162095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 37520eb7e1eaSToby Isaac PetscFV fv = NULL; 37530eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 37540eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 37550eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 37560eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 375762095d54SToby Isaac 3758ebf164c7SToby Isaac PetscFunctionBegin; 37599566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 37609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 37619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(coarse, 0, &cellStart, &cellEnd)); 37629566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 37639566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 37649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(coarse, &dim)); 376562095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 3766e4a60869SToby Isaac PetscInt nleaves, l; 3767e4a60869SToby Isaac const PetscInt *leaves; 376862095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 376962095d54SToby Isaac 37709566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 3771e4a60869SToby Isaac 3772e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 3773e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3774e4a60869SToby Isaac 37759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 3777ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++; 377862095d54SToby Isaac } 37799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 37804833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 3781e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3782e4a60869SToby Isaac 37839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 3785ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l; 378662095d54SToby Isaac } 37879566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 37889566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 378962095d54SToby Isaac } 379062095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 37919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 3792ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2; 37939566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 37949566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 379562095d54SToby Isaac 37969566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 37979566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 379862095d54SToby Isaac 37999566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 38009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 38019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 380262095d54SToby Isaac 38039566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 38049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 380562095d54SToby Isaac 380662095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 38079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootValuesSec)); 38089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootValuesSec, pStartC, pEndC)); 38099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 381062095d54SToby Isaac { 381162095d54SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 38129566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &newOffsets, maxFields, &newOffsetsCopy, maxFields, &rowOffsets, maxFields, &numD, maxFields, &numO)); 381362095d54SToby Isaac } 38140eb7e1eaSToby Isaac if (grad) { 38150eb7e1eaSToby Isaac PetscInt i; 38160eb7e1eaSToby Isaac 38179566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeom, &cellDM)); 38189566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeom, &cellGeomArray)); 38199566063dSJacob Faibussowitsch PetscCall(VecGetDM(grad, &gradDM)); 38209566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(grad, &gradArray)); 38210eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1, numFields); i++) { 38220eb7e1eaSToby Isaac PetscObject obj; 38230eb7e1eaSToby Isaac PetscClassId id; 38240eb7e1eaSToby Isaac 38259566063dSJacob Faibussowitsch PetscCall(DMGetField(coarse, i, NULL, &obj)); 38269566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 38270eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 38280eb7e1eaSToby Isaac fv = (PetscFV)obj; 38299566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numFVcomps)); 38300eb7e1eaSToby Isaac fvField = i; 38310eb7e1eaSToby Isaac break; 38320eb7e1eaSToby Isaac } 38330eb7e1eaSToby Isaac } 38340eb7e1eaSToby Isaac } 383562095d54SToby Isaac 383662095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 383762095d54SToby Isaac PetscInt dof; 383862095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 383962095d54SToby Isaac PetscInt numValues = 0; 384062095d54SToby Isaac 38419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 3842ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1); 384362095d54SToby Isaac offsets[0] = 0; 384462095d54SToby Isaac newOffsets[0] = 0; 384562095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 384662095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 384762095d54SToby Isaac 38489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 384962095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 385062095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 385162095d54SToby Isaac 38529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 385362095d54SToby Isaac numValues += clDof; 385462095d54SToby Isaac } 38559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 38569371c9d4SSatish Balay } else if (maxChildId == -1) { 38579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &numValues)); 385862095d54SToby Isaac } 385962095d54SToby Isaac /* we will pack the column indices with the field offsets */ 386078b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 38610eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 38620eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 38630eb7e1eaSToby Isaac } 38649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootValuesSec, p, numValues)); 386562095d54SToby Isaac } 38669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootValuesSec)); 386762095d54SToby Isaac { 386862095d54SToby Isaac PetscInt numRootValues; 386962095d54SToby Isaac const PetscScalar *coarseArray; 387062095d54SToby Isaac 38719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootValuesSec, &numRootValues)); 38729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootValues, &rootValues)); 38739566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecCoarseLocal, &coarseArray)); 387462095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 387562095d54SToby Isaac PetscInt numValues; 387662095d54SToby Isaac PetscInt pValOff; 387762095d54SToby Isaac PetscScalar *pVal; 387862095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 387962095d54SToby Isaac 38809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootValuesSec, p, &numValues)); 3881ad540459SPierre Jolivet if (!numValues) continue; 38829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootValuesSec, p, &pValOff)); 388362095d54SToby Isaac pVal = &(rootValues[pValOff]); 388462095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 38850eb7e1eaSToby Isaac PetscInt closureSize = numValues; 38869566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(coarse, NULL, vecCoarseLocal, p, &closureSize, &pVal)); 38870eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 3888193eb951SToby Isaac PetscFVCellGeom *cg; 38896dd00756SToby Isaac PetscScalar *gradVals = NULL; 38900eb7e1eaSToby Isaac PetscInt i; 38910eb7e1eaSToby Isaac 38920eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 38930eb7e1eaSToby Isaac 38949566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(cellDM, p, cellGeomArray, (void *)&cg)); 38950eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 38960eb7e1eaSToby Isaac pVal += dim; 38979566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRead(gradDM, p, gradArray, (void *)&gradVals)); 38980eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 38990eb7e1eaSToby Isaac } 39009371c9d4SSatish Balay } else if (maxChildId == -1) { 390178b7adb5SToby Isaac PetscInt lDof, lOff, i; 390278b7adb5SToby Isaac 39039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &lDof)); 39049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, p, &lOff)); 390578b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 390678b7adb5SToby Isaac } 390778b7adb5SToby Isaac } 39089566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecCoarseLocal, &coarseArray)); 39099566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 391062095d54SToby Isaac } 391162095d54SToby Isaac { 391262095d54SToby Isaac PetscSF valuesSF; 391362095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 391462095d54SToby Isaac 39159566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafValuesSec)); 39169566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootValuesSec, &remoteOffsetsValues, leafValuesSec)); 39179566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootValuesSec, remoteOffsetsValues, leafValuesSec, &valuesSF)); 39189566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 39199566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsValues)); 39209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafValuesSec, &numLeafValues)); 39219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeafValues, &leafValues)); 39229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 39239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 39249566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&valuesSF)); 39259566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 39269566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootValuesSec)); 392762095d54SToby Isaac } 39289566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 392962095d54SToby Isaac { 393062095d54SToby Isaac PetscInt maxDof; 393162095d54SToby Isaac PetscInt *rowIndices; 393262095d54SToby Isaac DM refTree; 393362095d54SToby Isaac PetscInt **refPointFieldN; 393462095d54SToby Isaac PetscScalar ***refPointFieldMats; 393562095d54SToby Isaac PetscSection refConSec, refAnSec; 39360eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, leafStart, leafEnd; 393762095d54SToby Isaac PetscScalar *pointWork; 393862095d54SToby Isaac 39399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 39409566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 39419566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 39429566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 39439566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(fine, refTree)); 39449566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 39459566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 39469566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 39479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 39489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafValuesSec, &leafStart, &leafEnd)); 39499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(fine, 0, &cellStart, &cellEnd)); 39500eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 395162095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 395262095d54SToby Isaac PetscInt numValues, pValOff; 395362095d54SToby Isaac PetscInt childId; 395462095d54SToby Isaac const PetscScalar *pVal; 39550eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 395662095d54SToby Isaac 39579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 39589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &lDof)); 39599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 3960ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue; 39619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 39629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafValuesSec, p, &numValues)); 396362095d54SToby Isaac if (!numValues) continue; 39649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafValuesSec, p, &pValOff)); 396562095d54SToby Isaac pVal = &leafValues[pValOff]; 396662095d54SToby Isaac offsets[0] = 0; 396762095d54SToby Isaac offsetsCopy[0] = 0; 396862095d54SToby Isaac newOffsets[0] = 0; 396962095d54SToby Isaac newOffsetsCopy[0] = 0; 39704833aeb0SToby Isaac childId = cids[p - pStartF]; 397162095d54SToby Isaac if (numFields) { 397262095d54SToby Isaac PetscInt f; 397362095d54SToby Isaac for (f = 0; f < numFields; f++) { 397462095d54SToby Isaac PetscInt rowDof; 397562095d54SToby Isaac 39769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 397762095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 397862095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 397962095d54SToby Isaac /* TODO: closure indices */ 39809f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 398162095d54SToby Isaac } 39829566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 39839371c9d4SSatish Balay } else { 39844833aeb0SToby Isaac offsets[0] = 0; 39854833aeb0SToby Isaac offsets[1] = lDof; 39864833aeb0SToby Isaac newOffsets[0] = 0; 39874833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 39889566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 398962095d54SToby Isaac } 399062095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 39919566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numValues, rowIndices, pVal, INSERT_VALUES)); 399262095d54SToby Isaac } else { 399362095d54SToby Isaac PetscInt f; 399462095d54SToby Isaac 399578b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 399678b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 399778b7adb5SToby Isaac fvGradData = &pVal[numValues]; 399878b7adb5SToby Isaac } 399962095d54SToby Isaac for (f = 0; f < PetscMax(1, numFields); f++) { 400062095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 400162095d54SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 400262095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 400362095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 400462095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 400562095d54SToby Isaac PetscInt i, j; 400662095d54SToby Isaac 4007708c7f19SToby Isaac #if 0 400863a3b9bcSJacob 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)); 4009708c7f19SToby Isaac #endif 401062095d54SToby Isaac for (i = 0; i < numRows; i++) { 401162095d54SToby Isaac PetscScalar val = 0.; 4012ad540459SPierre Jolivet for (j = 0; j < numCols; j++) val += childMat[i * numCols + j] * cVal[j]; 401362095d54SToby Isaac rVal[i] = val; 401462095d54SToby Isaac } 40150eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 40160eb7e1eaSToby Isaac PetscReal centroid[3]; 40170eb7e1eaSToby Isaac PetscScalar diff[3]; 40180eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 40190eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 40200eb7e1eaSToby Isaac 40219566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(fine, p, NULL, centroid, NULL)); 4022ad540459SPierre Jolivet for (i = 0; i < dim; i++) diff[i] = centroid[i] - parentCentroid[i]; 40230eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 40240eb7e1eaSToby Isaac PetscScalar val = 0.; 40250eb7e1eaSToby Isaac 4026ad540459SPierre Jolivet for (j = 0; j < dim; j++) val += gradient[dim * i + j] * diff[j]; 40270eb7e1eaSToby Isaac rVal[i] += val; 40280eb7e1eaSToby Isaac } 40290eb7e1eaSToby Isaac } 40309566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numRows, &rowIndices[offsets[f]], rVal, INSERT_VALUES)); 403162095d54SToby Isaac } 403262095d54SToby Isaac } 403362095d54SToby Isaac } 40349566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 40359566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 40369566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 403762095d54SToby Isaac } 40389566063dSJacob Faibussowitsch PetscCall(PetscFree(leafValues)); 40399566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafValuesSec)); 40409566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 40419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 4042ebf164c7SToby Isaac PetscFunctionReturn(0); 4043ebf164c7SToby Isaac } 4044ebf164c7SToby Isaac 4045*d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4046*d71ae5a4SJacob Faibussowitsch { 4047c921d74cSToby Isaac DM refTree; 4048c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4049c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4050c921d74cSToby Isaac PetscSection localCoarse, localFine; 4051c921d74cSToby Isaac PetscSection cSecRef; 4052c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4053d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4054c921d74cSToby Isaac Mat injRef; 4055c921d74cSToby Isaac PetscInt numFields, maxDof; 4056c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4057c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4058c921d74cSToby Isaac PetscLayout rowMap, colMap; 4059c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4060c921d74cSToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4061c921d74cSToby Isaac 4062ebf164c7SToby Isaac PetscFunctionBegin; 4063c921d74cSToby Isaac 4064c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 40659566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40669566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecCoarse, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40679566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 40689566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(coarse, refTree)); 40699566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 40709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 40719566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 4072c921d74cSToby Isaac 40739566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 40749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 40759566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 40769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 40779566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 40789566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 40799566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 40809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 4081c921d74cSToby Isaac { 4082c921d74cSToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 40839566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 4084c921d74cSToby Isaac } 4085c921d74cSToby Isaac 40869566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, cids, vecFine, numFields, offsets, &multiRootSec, &rootIndicesSec, NULL, &rootValues)); 4087c921d74cSToby Isaac 40889566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxDof, &parentIndices, maxDof, &parentValues)); 4089c921d74cSToby Isaac 4090c921d74cSToby Isaac /* count indices */ 40919566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecFine, &colMap)); 40929566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecCoarse, &rowMap)); 40939566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 40949566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 40959566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 40969566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 4097c921d74cSToby Isaac /* insert values */ 40989566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 4099c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4100c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 410178b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4102c921d74cSToby Isaac 41039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 41049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 4105c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 41069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &dof)); 41079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 4108c921d74cSToby Isaac 4109c921d74cSToby Isaac rowOffsets[0] = 0; 4110c921d74cSToby Isaac offsetsCopy[0] = 0; 4111c921d74cSToby Isaac if (numFields) { 4112c921d74cSToby Isaac PetscInt f; 4113c921d74cSToby Isaac 4114c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4115c921d74cSToby Isaac PetscInt fDof; 41169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 4117c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4118c921d74cSToby Isaac } 41199566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 4120367003a6SStefano Zampini } else { 41219566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 4122c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4123c921d74cSToby Isaac } 4124c921d74cSToby Isaac 41259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 41269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 4127c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 41282f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4129c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4130c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4131c921d74cSToby Isaac const PetscScalar *childValues; 4132c921d74cSToby Isaac 41339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 41349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 4135c921d74cSToby Isaac childId = (PetscInt)PetscRealPart(rootValues[offset++]); 4136c921d74cSToby Isaac childValues = &rootValues[offset]; 4137c921d74cSToby Isaac numIndices--; 4138c921d74cSToby Isaac 4139c921d74cSToby Isaac if (childId == -2) { /* skip */ 4140c921d74cSToby Isaac continue; 4141c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 41422f65e181SToby Isaac PetscInt m; 41432f65e181SToby Isaac 414478b7adb5SToby Isaac contribute = PETSC_TRUE; 41452f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4146beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4147d3bc4906SToby Isaac PetscInt parentId, f, lim; 4148d3bc4906SToby Isaac 414978b7adb5SToby Isaac contribute = PETSC_TRUE; 41509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 4151d3bc4906SToby Isaac 4152d3bc4906SToby Isaac lim = PetscMax(1, numFields); 4153d3bc4906SToby Isaac offsets[0] = 0; 4154d3bc4906SToby Isaac if (numFields) { 4155d3bc4906SToby Isaac PetscInt f; 4156d3bc4906SToby Isaac 4157d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4158d3bc4906SToby Isaac PetscInt fDof; 41599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 4160d3bc4906SToby Isaac 4161d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4162d3bc4906SToby Isaac } 41639371c9d4SSatish Balay } else { 4164d3bc4906SToby Isaac PetscInt cDof; 4165d3bc4906SToby Isaac 41669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 4167d3bc4906SToby Isaac offsets[1] = cDof; 4168d3bc4906SToby Isaac } 4169d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4170d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4171d3bc4906SToby Isaac PetscInt n = offsets[f + 1] - offsets[f]; 4172e328ff09SToby Isaac PetscInt m = rowOffsets[f + 1] - rowOffsets[f]; 4173d3bc4906SToby Isaac PetscInt i, j; 4174d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4175d3bc4906SToby Isaac 4176e328ff09SToby Isaac for (i = 0; i < m; i++) { 4177d3bc4906SToby Isaac PetscScalar val = 0.; 4178ad540459SPierre Jolivet for (j = 0; j < n; j++) val += childMat[n * i + j] * colValues[j]; 4179e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val; 4180d3bc4906SToby Isaac } 4181d3bc4906SToby Isaac } 4182c921d74cSToby Isaac } 4183c921d74cSToby Isaac } 41849566063dSJacob Faibussowitsch if (contribute) PetscCall(VecSetValues(vecCoarse, dof, parentIndices, parentValues, INSERT_VALUES)); 4185c921d74cSToby Isaac } 41869566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 41879566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 41889566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentIndices, parentValues)); 41899566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 41909566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 41919566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 4192ebf164c7SToby Isaac PetscFunctionReturn(0); 4193ebf164c7SToby Isaac } 4194ebf164c7SToby Isaac 4195ff1f73f7SToby Isaac /*@ 4196ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4197ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4198ff1f73f7SToby Isaac coarsening and refinement at the same time. 4199ff1f73f7SToby Isaac 4200ff1f73f7SToby Isaac collective 4201ff1f73f7SToby Isaac 4202ff1f73f7SToby Isaac Input Parameters: 4203ff1f73f7SToby Isaac + dmIn - The DMPlex mesh for the input vector 4204ff1f73f7SToby Isaac . vecIn - The input vector 4205ff1f73f7SToby Isaac . sfRefine - A star forest indicating points in the mesh dmIn (roots in the star forest) that are parents to points in 4206ff1f73f7SToby Isaac the mesh dmOut (leaves in the star forest), i.e. where dmOut is more refined than dmIn 4207ff1f73f7SToby Isaac . sfCoarsen - A star forest indicating points in the mesh dmOut (roots in the star forest) that are parents to points in 4208ff1f73f7SToby Isaac the mesh dmIn (leaves in the star forest), i.e. where dmOut is more coarsened than dmIn 4209ff1f73f7SToby Isaac . cidsRefine - The childIds of the points in dmOut. These childIds relate back to the reference tree: childid[j] = k implies 4210ff1f73f7SToby Isaac that mesh point j of dmOut was refined from a point in dmIn just as the mesh point k in the reference 4211ff1f73f7SToby Isaac tree was refined from its parent. childid[j] = -1 indicates that the point j in dmOut is exactly 4212ff1f73f7SToby Isaac equivalent to its root in dmIn, so no interpolation is necessary. childid[j] = -2 indicates that this 4213ff1f73f7SToby Isaac point j in dmOut is not a leaf of sfRefine. 4214ff1f73f7SToby Isaac . cidsCoarsen - The childIds of the points in dmIn. These childIds relate back to the reference tree: childid[j] = k implies 4215ff1f73f7SToby Isaac that mesh point j of dmIn coarsens to a point in dmOut just as the mesh point k in the reference 4216ff1f73f7SToby Isaac tree coarsens to its parent. childid[j] = -2 indicates that point j in dmOut is not a leaf in sfCoarsen. 4217ff1f73f7SToby Isaac . useBCs - PETSC_TRUE indicates that boundary values should be inserted into vecIn before transfer. 4218ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4219ff1f73f7SToby Isaac 4220ff1f73f7SToby Isaac Output Parameters: 42218966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred 4222ff1f73f7SToby Isaac projection of vecIn from dmIn to dmOut. Note that any field discretized with a PetscFV finite volume 4223ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4224ff1f73f7SToby Isaac coarse points to fine points. 4225ff1f73f7SToby Isaac 4226ff1f73f7SToby Isaac Level: developer 4227ff1f73f7SToby Isaac 4228db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()`, `PetscFVGetComputeGradients()` 4229ff1f73f7SToby Isaac @*/ 4230*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) 4231*d71ae5a4SJacob Faibussowitsch { 423238fc2455SToby Isaac PetscFunctionBegin; 42339566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0)); 4234ff1f73f7SToby Isaac if (sfRefine) { 4235fbfa57b9SToby Isaac Vec vecInLocal; 42360eb7e1eaSToby Isaac DM dmGrad = NULL; 42370eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4238fbfa57b9SToby Isaac 42399566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecInLocal)); 42409566063dSJacob Faibussowitsch PetscCall(VecSet(vecInLocal, 0.0)); 42410eb7e1eaSToby Isaac { 42420eb7e1eaSToby Isaac PetscInt numFields, i; 42430eb7e1eaSToby Isaac 42449566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dmIn, &numFields)); 42450eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 42460eb7e1eaSToby Isaac PetscObject obj; 42470eb7e1eaSToby Isaac PetscClassId classid; 42480eb7e1eaSToby Isaac 42499566063dSJacob Faibussowitsch PetscCall(DMGetField(dmIn, i, NULL, &obj)); 42509566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &classid)); 42510eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 42529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dmIn, (PetscFV)obj, &cellGeom, &faceGeom, &dmGrad)); 42530eb7e1eaSToby Isaac break; 42540eb7e1eaSToby Isaac } 42550eb7e1eaSToby Isaac } 42560eb7e1eaSToby Isaac } 42571baa6e33SBarry Smith if (useBCs) PetscCall(DMPlexInsertBoundaryValues(dmIn, PETSC_TRUE, vecInLocal, time, faceGeom, cellGeom, NULL)); 42589566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42599566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42600eb7e1eaSToby Isaac if (dmGrad) { 42619566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmGrad, &grad)); 42629566063dSJacob Faibussowitsch PetscCall(DMPlexReconstructGradientsFVM(dmIn, vecInLocal, grad)); 42630eb7e1eaSToby Isaac } 42649566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree_Interpolate(dmIn, vecInLocal, dmOut, vecOut, sfRefine, cidsRefine, grad, cellGeom)); 42659566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecInLocal)); 426648a46eb9SPierre Jolivet if (dmGrad) PetscCall(DMRestoreGlobalVector(dmGrad, &grad)); 4267ebf164c7SToby Isaac } 42681baa6e33SBarry Smith if (sfCoarsen) PetscCall(DMPlexTransferVecTree_Inject(dmIn, vecIn, dmOut, vecOut, sfCoarsen, cidsCoarsen)); 42699566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(vecOut)); 42709566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(vecOut)); 427138fc2455SToby Isaac PetscFunctionReturn(0); 427238fc2455SToby Isaac } 4273