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 @*/ 229371c9d4SSatish Balay PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) { 23d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 24d6a7ad0dSToby Isaac 25d6a7ad0dSToby Isaac PetscFunctionBegin; 26d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2747a1df27SMatthew G. Knepley if (ref) { PetscValidHeaderSpecific(ref, DM_CLASSID, 2); } 289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ref)); 299566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 30d6a7ad0dSToby Isaac mesh->referenceTree = ref; 31d6a7ad0dSToby Isaac PetscFunctionReturn(0); 32d6a7ad0dSToby Isaac } 33d6a7ad0dSToby Isaac 34d6a7ad0dSToby Isaac /*@ 35d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 36d6a7ad0dSToby Isaac 37d6a7ad0dSToby Isaac Not collective 38d6a7ad0dSToby Isaac 39d6a7ad0dSToby Isaac Input Parameters: 40d6a7ad0dSToby Isaac . dm - The DMPlex object 41d6a7ad0dSToby Isaac 427a7aea1fSJed Brown Output Parameters: 43d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 44d6a7ad0dSToby Isaac 450b7167a0SToby Isaac Level: intermediate 46d6a7ad0dSToby Isaac 47db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()` 48d6a7ad0dSToby Isaac @*/ 499371c9d4SSatish Balay PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) { 50d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 51d6a7ad0dSToby Isaac 52d6a7ad0dSToby Isaac PetscFunctionBegin; 53d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54d6a7ad0dSToby Isaac PetscValidPointer(ref, 2); 55d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 56d6a7ad0dSToby Isaac PetscFunctionReturn(0); 57d6a7ad0dSToby Isaac } 58d6a7ad0dSToby Isaac 599371c9d4SSatish Balay static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) { 60dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 61dcbd3bf7SToby Isaac 62dcbd3bf7SToby Isaac PetscFunctionBegin; 63dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 64dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 65dcbd3bf7SToby Isaac if (childB) *childB = childA; 66dcbd3bf7SToby Isaac PetscFunctionReturn(0); 67dcbd3bf7SToby Isaac } 68dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, &dStart, &dEnd)); 709371c9d4SSatish Balay if (parent >= dStart && parent <= dEnd) { break; } 71dcbd3bf7SToby Isaac } 7263a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot perform child symmetry for %" PetscInt_FMT "-cells", dim); 7328b400f6SJacob Faibussowitsch PetscCheck(dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "A vertex has no children"); 74dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 75dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 76dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 77dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 78dcbd3bf7SToby Isaac 799566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, childA, &size)); 809566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, childA, &supp)); 81dcbd3bf7SToby Isaac 82dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 83dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 84dcbd3bf7SToby Isaac PetscInt sParent; 85dcbd3bf7SToby Isaac 86dcbd3bf7SToby Isaac sA = supp[i]; 87dcbd3bf7SToby Isaac if (sA == parent) continue; 889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, sA, &sParent, NULL)); 899371c9d4SSatish Balay if (sParent == parent) { break; } 90dcbd3bf7SToby Isaac } 9108401ef6SPierre Jolivet PetscCheck(i != size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "could not find support in children"); 92dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 93dcbd3bf7SToby Isaac * parentOrientB */ 949566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry_Default(dm, parent, parentOrientA, 0, sA, parentOrientB, &sOrientB, &sB)); 959566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, sA, &sConeSize)); 969566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sA, &coneA)); 979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sB, &coneB)); 989566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sA, &oA)); 999566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sB, &oB)); 100dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 101dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 102dcbd3bf7SToby Isaac if (coneA[i] == childA) { 103dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 104dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 105dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize - (sOrientB + 1) - i) % sConeSize); 106dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 107dcbd3bf7SToby Isaac if (childOrientB) { 108b5a892a1SMatthew G. Knepley DMPolytopeType ct; 109dcbd3bf7SToby Isaac PetscInt oBtrue; 110dcbd3bf7SToby Isaac 1119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, childA, &coneSize)); 112dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 1131dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected a vertex or an edge"); 114b5a892a1SMatthew G. Knepley ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 115dcbd3bf7SToby Isaac /* we may have to flip an edge */ 116b5a892a1SMatthew G. Knepley oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientation(ct, -1, oB[j]); 117b5a892a1SMatthew G. Knepley oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 118b5a892a1SMatthew G. Knepley ABswap = DihedralSwap(coneSize, DMPolytopeConvertNewOrientation_Internal(ct, oA[i]), oBtrue); 119dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 120dcbd3bf7SToby Isaac } 121dcbd3bf7SToby Isaac break; 122dcbd3bf7SToby Isaac } 123dcbd3bf7SToby Isaac } 12408401ef6SPierre Jolivet PetscCheck(i != sConeSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "support cone mismatch"); 125dcbd3bf7SToby Isaac PetscFunctionReturn(0); 126dcbd3bf7SToby Isaac } 127dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 1289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 129dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 130dcbd3bf7SToby Isaac if (dim == 2) { 131dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 132dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 133dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 134dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 135dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 136dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 137947b95d8SBarry Smith } else { 138dcbd3bf7SToby Isaac ABswapVert = ABswap; 139dcbd3bf7SToby Isaac } 140dcbd3bf7SToby Isaac if (childB) { 141dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 142dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 143dcbd3bf7SToby Isaac const PetscInt *children; 144dcbd3bf7SToby Isaac 145dcbd3bf7SToby Isaac /* count which position the child is in */ 1469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, parent, &numChildren, &children)); 147dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 148dcbd3bf7SToby Isaac p = children[i]; 149dcbd3bf7SToby Isaac if (p == childA) { 150dcbd3bf7SToby Isaac posA = i; 151dcbd3bf7SToby Isaac break; 152dcbd3bf7SToby Isaac } 153dcbd3bf7SToby Isaac } 154dcbd3bf7SToby Isaac if (posA >= coneSize) { 155dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 156dcbd3bf7SToby Isaac * is invariant */ 1571dca8a05SBarry Smith PetscCheck(dim == 2 && posA == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Expected a middle triangle, got something else"); 158dcbd3bf7SToby Isaac *childB = childA; 1599371c9d4SSatish Balay } else { 160dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 161dcbd3bf7SToby Isaac PetscInt posB; 162dcbd3bf7SToby Isaac 163dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize - (ABswapVert + 1) - posA) % coneSize); 164dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 165dcbd3bf7SToby Isaac } 166dcbd3bf7SToby Isaac } 167dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 168dcbd3bf7SToby Isaac PetscFunctionReturn(0); 169dcbd3bf7SToby Isaac } 170dcbd3bf7SToby Isaac 171dcbd3bf7SToby Isaac /*@ 172dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 173dcbd3bf7SToby Isaac 174dcbd3bf7SToby Isaac Input Parameters: 175dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object 176dcbd3bf7SToby Isaac . parent - the parent point 177dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 178dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 179dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 180dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 181dcbd3bf7SToby Isaac 182dcbd3bf7SToby Isaac Output Parameters: 183dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child 184ff1f73f7SToby Isaac - childB - if not NULL, the new childID for describing the child 185dcbd3bf7SToby Isaac 186dcbd3bf7SToby Isaac Level: developer 187dcbd3bf7SToby Isaac 188db781477SPatrick Sanan .seealso: `DMPlexGetReferenceTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetTree()` 189dcbd3bf7SToby Isaac @*/ 1909371c9d4SSatish Balay PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) { 191dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 192dcbd3bf7SToby Isaac 193dcbd3bf7SToby Isaac PetscFunctionBegin; 194dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19528b400f6SJacob Faibussowitsch PetscCheck(mesh->getchildsymmetry, PETSC_COMM_SELF, PETSC_ERR_SUP, "DMPlexReferenceTreeGetChildSymmetry not implemented"); 1969566063dSJacob Faibussowitsch PetscCall(mesh->getchildsymmetry(dm, parent, parentOrientA, childOrientA, childA, parentOrientB, childOrientB, childB)); 197dcbd3bf7SToby Isaac PetscFunctionReturn(0); 198dcbd3bf7SToby Isaac } 199dcbd3bf7SToby Isaac 200776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM, PetscSection, PetscInt *, PetscInt *, PetscBool, PetscBool); 201f9f063d4SToby Isaac 2029371c9d4SSatish Balay PetscErrorCode DMPlexCreateReferenceTree_SetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) { 203f2c1aa1dSLisandro Dalcin PetscFunctionBegin; 2049566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm, parentSection, parents, childIDs, PETSC_TRUE, PETSC_FALSE)); 205f2c1aa1dSLisandro Dalcin PetscFunctionReturn(0); 206f2c1aa1dSLisandro Dalcin } 207f2c1aa1dSLisandro Dalcin 2089371c9d4SSatish Balay PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) { 2090e2cc29aSToby Isaac MPI_Comm comm; 2100e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 211da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 212da43764aSToby Isaac DMLabel identity, identityRef; 21310f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 214da43764aSToby Isaac PetscScalar *unionCoords; 215da43764aSToby Isaac IS perm; 216da43764aSToby Isaac 217da43764aSToby Isaac PetscFunctionBegin; 2180e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2199566063dSJacob Faibussowitsch PetscCall(DMGetDimension(K, &dim)); 2209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd)); 2219566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, labelName, &identity)); 2229566063dSJacob Faibussowitsch PetscCall(DMGetLabel(Kref, labelName, &identityRef)); 2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(Kref, &pRefStart, &pRefEnd)); 2249566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionSection)); 2259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart))); 226da43764aSToby Isaac /* count points that will go in the union */ 2279371c9d4SSatish Balay for (p = pStart; p < pEnd; p++) { PetscCall(PetscSectionSetDof(unionSection, p - pStart, 1)); } 228da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 229da43764aSToby Isaac PetscInt q, qSize; 2309566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &q)); 2319566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(identityRef, q, &qSize)); 2329371c9d4SSatish Balay if (qSize > 1) { PetscCall(PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1)); } 233da43764aSToby Isaac } 2349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart, &permvals)); 235da43764aSToby Isaac offset = 0; 236da43764aSToby Isaac /* stratify points in the union by topological dimension */ 237da43764aSToby Isaac for (d = 0; d <= dim; d++) { 238da43764aSToby Isaac PetscInt cStart, cEnd, c; 239da43764aSToby Isaac 2409566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, &cEnd)); 2419371c9d4SSatish Balay for (c = cStart; c < cEnd; c++) { permvals[offset++] = c; } 242da43764aSToby Isaac 2439566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd)); 2449371c9d4SSatish Balay for (c = cStart; c < cEnd; c++) { permvals[offset++] = c + (pEnd - pStart); } 245da43764aSToby Isaac } 2469566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm)); 2479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(unionSection, perm)); 2489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionSection)); 2499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionSection, &numUnionPoints)); 2509566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numUnionPoints, &coneSizes, dim + 1, &numDimPoints)); 251da43764aSToby Isaac /* count dimension points */ 252da43764aSToby Isaac for (d = 0; d <= dim; d++) { 253da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 2549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, NULL)); 2559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, cStart - pStart, &cOff)); 256da43764aSToby Isaac if (d < dim) { 2579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d + 1, &cStart, NULL)); 2589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, cStart - pStart, &cOff2)); 2599371c9d4SSatish Balay } else { 260da43764aSToby Isaac cOff2 = numUnionPoints; 261da43764aSToby Isaac } 262da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 263da43764aSToby Isaac } 2649566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionConeSection)); 2659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionConeSection, 0, numUnionPoints)); 266da43764aSToby Isaac /* count the cones in the union */ 267da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 268da43764aSToby Isaac PetscInt dof, uOff; 269da43764aSToby Isaac 2709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof)); 2719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart, &uOff)); 2729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof)); 273da43764aSToby Isaac coneSizes[uOff] = dof; 274da43764aSToby Isaac } 275da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 276da43764aSToby Isaac PetscInt dof, uDof, uOff; 277da43764aSToby Isaac 2789566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof)); 2799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 2809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 281da43764aSToby Isaac if (uDof) { 2829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof)); 283da43764aSToby Isaac coneSizes[uOff] = dof; 284da43764aSToby Isaac } 285da43764aSToby Isaac } 2869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionConeSection)); 2879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionConeSection, &numCones)); 2889566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numCones, &unionCones, numCones, &unionOrientations)); 289da43764aSToby Isaac /* write the cones in the union */ 290da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 291da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 292da43764aSToby Isaac const PetscInt *cone, *orientation; 293da43764aSToby Isaac 2949566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof)); 2959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, p, &cone)); 2969566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, p, &orientation)); 2979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart, &uOff)); 2989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection, uOff, &cOff)); 299da43764aSToby Isaac for (c = 0; c < dof; c++) { 300da43764aSToby Isaac PetscInt e, eOff; 301da43764aSToby Isaac e = cone[c]; 3029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 303da43764aSToby Isaac unionCones[cOff + c] = eOff; 304da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 305da43764aSToby Isaac } 306da43764aSToby Isaac } 307da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 308da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 309da43764aSToby Isaac const PetscInt *cone, *orientation; 310da43764aSToby Isaac 3119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof)); 3129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(Kref, p, &cone)); 3139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(Kref, p, &orientation)); 3149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 3159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 316da43764aSToby Isaac if (uDof) { 3179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection, uOff, &cOff)); 318da43764aSToby Isaac for (c = 0; c < dof; c++) { 319da43764aSToby Isaac PetscInt e, eOff, eDof; 320da43764aSToby Isaac 321da43764aSToby Isaac e = cone[c]; 3229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart), &eDof)); 323da43764aSToby Isaac if (eDof) { 3249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff)); 3259371c9d4SSatish Balay } else { 3269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, e, &e)); 3279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 328da43764aSToby Isaac } 329da43764aSToby Isaac unionCones[cOff + c] = eOff; 330da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 331da43764aSToby Isaac } 332da43764aSToby Isaac } 333da43764aSToby Isaac } 334da43764aSToby Isaac /* get the coordinates */ 335da43764aSToby Isaac { 336da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 337da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 338da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 339da43764aSToby Isaac PetscScalar *Kcoords; 340da43764aSToby Isaac 3419566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &KcoordsSec)); 3429566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &KcoordsVec)); 3439566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(Kref, &KrefCoordsSec)); 3449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(Kref, &KrefCoordsVec)); 345da43764aSToby Isaac 346da43764aSToby Isaac numVerts = numDimPoints[0]; 3479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVerts * dim, &unionCoords)); 3489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &vStart, &vEnd)); 349da43764aSToby Isaac 350da43764aSToby Isaac offset = 0; 351da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 3529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, v - pStart, &vOff)); 3539566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords)); 3549371c9d4SSatish Balay for (d = 0; d < dim; d++) { unionCoords[offset * dim + d] = Kcoords[d]; } 355da43764aSToby Isaac offset++; 356da43764aSToby Isaac } 3579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(Kref, 0, &vRefStart, &vRefEnd)); 358da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 3599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, v - pRefStart + (pEnd - pStart), &vDof)); 3609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, v - pRefStart + (pEnd - pStart), &vOff)); 3619566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords)); 362da43764aSToby Isaac if (vDof) { 3639371c9d4SSatish Balay for (d = 0; d < dim; d++) { unionCoords[offset * dim + d] = Kcoords[d]; } 364da43764aSToby Isaac offset++; 365da43764aSToby Isaac } 366da43764aSToby Isaac } 367da43764aSToby Isaac } 3689566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, ref)); 3699566063dSJacob Faibussowitsch PetscCall(DMSetType(*ref, DMPLEX)); 3709566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ref, dim)); 3719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ref, dim, numDimPoints, coneSizes, unionCones, unionOrientations, unionCoords)); 37210f7e118SToby Isaac /* set the tree */ 3739566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &parentSection)); 3749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, numUnionPoints)); 37510f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 37610f7e118SToby Isaac PetscInt uDof, uOff; 37710f7e118SToby Isaac 3789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 3799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 3801baa6e33SBarry Smith if (uDof) PetscCall(PetscSectionSetDof(parentSection, uOff, 1)); 38110f7e118SToby Isaac } 3829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 3839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &parentSize)); 3849566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(parentSize, &parents, parentSize, &childIDs)); 38510f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 38610f7e118SToby Isaac PetscInt uDof, uOff; 38710f7e118SToby Isaac 3889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof)); 3899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff)); 39010f7e118SToby Isaac if (uDof) { 39110f7e118SToby Isaac PetscInt pOff, parent, parentU; 3929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, uOff, &pOff)); 3939566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &parent)); 3949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, parent - pStart, &parentU)); 39510f7e118SToby Isaac parents[pOff] = parentU; 39610f7e118SToby Isaac childIDs[pOff] = uOff; 39710f7e118SToby Isaac } 39810f7e118SToby Isaac } 3999566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_SetTree(*ref, parentSection, parents, childIDs)); 4009566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 4019566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs)); 40210f7e118SToby Isaac 403da43764aSToby Isaac /* clean up */ 4049566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionSection)); 4059566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionConeSection)); 4069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 4079566063dSJacob Faibussowitsch PetscCall(PetscFree(unionCoords)); 4089566063dSJacob Faibussowitsch PetscCall(PetscFree2(unionCones, unionOrientations)); 4099566063dSJacob Faibussowitsch PetscCall(PetscFree2(coneSizes, numDimPoints)); 4100e2cc29aSToby Isaac PetscFunctionReturn(0); 4110e2cc29aSToby Isaac } 4120e2cc29aSToby Isaac 4130e2cc29aSToby Isaac /*@ 4140e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4150e2cc29aSToby Isaac 416d083f849SBarry Smith Collective 4170e2cc29aSToby Isaac 4180e2cc29aSToby Isaac Input Parameters: 4190e2cc29aSToby Isaac + comm - the MPI communicator 4200e2cc29aSToby Isaac . dim - the spatial dimension 4210e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4220e2cc29aSToby Isaac 4230e2cc29aSToby Isaac Output Parameters: 4240e2cc29aSToby Isaac . ref - the reference tree DMPlex object 4250e2cc29aSToby Isaac 4260e2cc29aSToby Isaac Level: intermediate 4270e2cc29aSToby Isaac 428db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()` 4290e2cc29aSToby Isaac @*/ 4309371c9d4SSatish Balay PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) { 4310e2cc29aSToby Isaac DM_Plex *mesh; 4320e2cc29aSToby Isaac DM K, Kref; 4330e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4340e2cc29aSToby Isaac DMLabel identity; 4350e2cc29aSToby Isaac 4360e2cc29aSToby Isaac PetscFunctionBegin; 4370e2cc29aSToby Isaac #if 1 4380e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4390e2cc29aSToby Isaac #endif 4400e2cc29aSToby Isaac /* create a reference element */ 4419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(comm, DMPolytopeTypeSimpleShape(dim, simplex), &K)); 4429566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(K, "identity")); 4439566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, "identity", &identity)); 4449566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd)); 4459371c9d4SSatish Balay for (p = pStart; p < pEnd; p++) { PetscCall(DMLabelSetValue(identity, p, p)); } 4460e2cc29aSToby Isaac /* refine it */ 4479566063dSJacob Faibussowitsch PetscCall(DMRefine(K, comm, &Kref)); 4480e2cc29aSToby Isaac 4490e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4500e2cc29aSToby Isaac * points that appear in both */ 4519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref)); 4520e2cc29aSToby Isaac mesh = (DM_Plex *)(*ref)->data; 4530e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 4549566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 4559566063dSJacob Faibussowitsch PetscCall(DMDestroy(&Kref)); 456da43764aSToby Isaac PetscFunctionReturn(0); 457da43764aSToby Isaac } 458da43764aSToby Isaac 4599371c9d4SSatish Balay static PetscErrorCode DMPlexTreeSymmetrize(DM dm) { 460878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 461878b19aaSToby Isaac PetscSection childSec, pSec; 462878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 463878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 464878b19aaSToby Isaac 465878b19aaSToby Isaac PetscFunctionBegin; 466878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4679566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 4689566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 469878b19aaSToby Isaac pSec = mesh->parentSection; 470878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 4719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(pSec, &pSize)); 472878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 473878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 474878b19aaSToby Isaac 475878b19aaSToby Isaac parMax = PetscMax(parMax, par + 1); 476878b19aaSToby Isaac parMin = PetscMin(parMin, par); 477878b19aaSToby Isaac } 478878b19aaSToby Isaac if (parMin > parMax) { 479878b19aaSToby Isaac parMin = -1; 480878b19aaSToby Isaac parMax = -1; 481878b19aaSToby Isaac } 4829566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)pSec), &childSec)); 4839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(childSec, parMin, parMax)); 484878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 485878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 486878b19aaSToby Isaac 4879566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(childSec, par, 1)); 488878b19aaSToby Isaac } 4899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(childSec)); 4909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(childSec, &cSize)); 4919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cSize, &children)); 4929566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(parMax - parMin, &offsets)); 4939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pSec, &pStart, &pEnd)); 494878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 495878b19aaSToby Isaac PetscInt dof, off, i; 496878b19aaSToby Isaac 4979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, p, &dof)); 4989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, p, &off)); 499878b19aaSToby Isaac for (i = 0; i < dof; i++) { 500878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 501878b19aaSToby Isaac 5029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, par, &cOff)); 503878b19aaSToby Isaac children[cOff + offsets[par - parMin]++] = p; 504878b19aaSToby Isaac } 505878b19aaSToby Isaac } 506878b19aaSToby Isaac mesh->childSection = childSec; 507878b19aaSToby Isaac mesh->children = children; 5089566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 509878b19aaSToby Isaac PetscFunctionReturn(0); 510878b19aaSToby Isaac } 511878b19aaSToby Isaac 5129371c9d4SSatish Balay static PetscErrorCode AnchorsFlatten(PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) { 5136dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5146dd5a8c8SToby Isaac const PetscInt *vals; 5156dd5a8c8SToby Isaac PetscSection secNew; 5166dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5176dd5a8c8SToby Isaac PetscBool compress; 5186dd5a8c8SToby Isaac 5196dd5a8c8SToby Isaac PetscFunctionBegin; 5209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 5219566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &size)); 5229566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &vals)); 5239566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &secNew)); 5249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secNew, pStart, pEnd)); 5256dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5266dd5a8c8SToby Isaac PetscInt dof; 5276dd5a8c8SToby Isaac 5286dd5a8c8SToby Isaac p = vals[i]; 5296dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5316dd5a8c8SToby Isaac if (dof) break; 5326dd5a8c8SToby Isaac } 5336dd5a8c8SToby Isaac if (i == size) { 5349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew)); 5356dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5366dd5a8c8SToby Isaac compress = PETSC_FALSE; 5376dd5a8c8SToby Isaac sizeNew = 0; 5389371c9d4SSatish Balay } else { 5396dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5406dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5416dd5a8c8SToby Isaac PetscInt dof, off; 5426dd5a8c8SToby Isaac 5439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5456dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5466dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5476dd5a8c8SToby Isaac 5489371c9d4SSatish Balay if (q >= pStart && q < pEnd) { PetscCall(PetscSectionGetDof(section, q, &qDof)); } 5491baa6e33SBarry Smith if (qDof) PetscCall(PetscSectionAddDof(secNew, p, qDof)); 5509371c9d4SSatish Balay else { PetscCall(PetscSectionAddDof(secNew, p, 1)); } 5516dd5a8c8SToby Isaac } 5526dd5a8c8SToby Isaac } 5539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew)); 5549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secNew, &sizeNew)); 5559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew, &valsNew)); 5566dd5a8c8SToby Isaac compress = PETSC_FALSE; 5576dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5586dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 5596dd5a8c8SToby Isaac 5609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dofNew)); 5639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &offNew)); 5646dd5a8c8SToby Isaac count = 0; 5656dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5666dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 5676dd5a8c8SToby Isaac 5686dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &qDof)); 5709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &qOff)); 5716dd5a8c8SToby Isaac } 5726dd5a8c8SToby Isaac if (qDof) { 5736dd5a8c8SToby Isaac PetscInt oldCount = count; 5746dd5a8c8SToby Isaac 5756dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 5766dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 5776dd5a8c8SToby Isaac 5786dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 5799371c9d4SSatish Balay if (valsNew[offNew + k] == r) { break; } 5806dd5a8c8SToby Isaac } 5819371c9d4SSatish Balay if (k == oldCount) { valsNew[offNew + count++] = r; } 5826dd5a8c8SToby Isaac } 5839371c9d4SSatish Balay } else { 5846dd5a8c8SToby Isaac PetscInt k, oldCount = count; 5856dd5a8c8SToby Isaac 5866dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 5879371c9d4SSatish Balay if (valsNew[offNew + k] == q) { break; } 5886dd5a8c8SToby Isaac } 5899371c9d4SSatish Balay if (k == oldCount) { valsNew[offNew + count++] = q; } 5906dd5a8c8SToby Isaac } 5916dd5a8c8SToby Isaac } 5926dd5a8c8SToby Isaac if (count < dofNew) { 5939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secNew, p, count)); 5946dd5a8c8SToby Isaac compress = PETSC_TRUE; 5956dd5a8c8SToby Isaac } 5966dd5a8c8SToby Isaac } 5976dd5a8c8SToby Isaac } 5989566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &vals)); 5991c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&anyNew, &globalAnyNew, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)secNew))); 6006dd5a8c8SToby Isaac if (!globalAnyNew) { 6019566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew)); 6026dd5a8c8SToby Isaac *sectionNew = NULL; 6036dd5a8c8SToby Isaac *isNew = NULL; 6049371c9d4SSatish Balay } else { 6056dd5a8c8SToby Isaac PetscBool globalCompress; 6066dd5a8c8SToby Isaac 6071c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&compress, &globalCompress, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)secNew))); 6086dd5a8c8SToby Isaac if (compress) { 6096dd5a8c8SToby Isaac PetscSection secComp; 6106dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6116dd5a8c8SToby Isaac 6129566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &secComp)); 6139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secComp, pStart, pEnd)); 6146dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6156dd5a8c8SToby Isaac PetscInt dof; 6166dd5a8c8SToby Isaac 6179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof)); 6189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secComp, p, dof)); 6196dd5a8c8SToby Isaac } 6209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secComp)); 6219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secComp, &sizeNew)); 6229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew, &valsComp)); 6236dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6246dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6256dd5a8c8SToby Isaac 6269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof)); 6279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &off)); 6289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secComp, p, &offNew)); 6299371c9d4SSatish Balay for (j = 0; j < dof; j++) { valsComp[offNew + j] = valsNew[off + j]; } 6306dd5a8c8SToby Isaac } 6319566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew)); 6326dd5a8c8SToby Isaac secNew = secComp; 6339566063dSJacob Faibussowitsch PetscCall(PetscFree(valsNew)); 6346dd5a8c8SToby Isaac valsNew = valsComp; 6356dd5a8c8SToby Isaac } 6369566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), sizeNew, valsNew, PETSC_OWN_POINTER, isNew)); 6376dd5a8c8SToby Isaac } 6386dd5a8c8SToby Isaac PetscFunctionReturn(0); 6396dd5a8c8SToby Isaac } 6406dd5a8c8SToby Isaac 6419371c9d4SSatish Balay static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) { 64266af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 64366af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 64466af876cSToby Isaac PetscSection aSec; 645f9f063d4SToby Isaac DMLabel canonLabel; 64666af876cSToby Isaac IS aIS; 64766af876cSToby Isaac 64866af876cSToby Isaac PetscFunctionBegin; 64966af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6509566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 6519566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "canonical", &canonLabel)); 65266af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 65366af876cSToby Isaac PetscInt parent; 65466af876cSToby Isaac 655f9f063d4SToby Isaac if (canonLabel) { 656f9f063d4SToby Isaac PetscInt canon; 657f9f063d4SToby Isaac 6589566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 659f9f063d4SToby Isaac if (p != canon) continue; 660f9f063d4SToby Isaac } 6619566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 66266af876cSToby Isaac if (parent != p) { 66366af876cSToby Isaac aMin = PetscMin(aMin, p); 66466af876cSToby Isaac aMax = PetscMax(aMax, p + 1); 66566af876cSToby Isaac } 66666af876cSToby Isaac } 66766af876cSToby Isaac if (aMin > aMax) { 66866af876cSToby Isaac aMin = -1; 66966af876cSToby Isaac aMax = -1; 67066af876cSToby Isaac } 6719566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &aSec)); 6729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(aSec, aMin, aMax)); 67366af876cSToby Isaac for (p = aMin; p < aMax; p++) { 67466af876cSToby Isaac PetscInt parent, ancestor = p; 67566af876cSToby Isaac 676f9f063d4SToby Isaac if (canonLabel) { 677f9f063d4SToby Isaac PetscInt canon; 678f9f063d4SToby Isaac 6799566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 680f9f063d4SToby Isaac if (p != canon) continue; 681f9f063d4SToby Isaac } 6829566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 68366af876cSToby Isaac while (parent != ancestor) { 68466af876cSToby Isaac ancestor = parent; 6859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, ancestor, &parent, NULL)); 68666af876cSToby Isaac } 68766af876cSToby Isaac if (ancestor != p) { 68866af876cSToby Isaac PetscInt closureSize, *closure = NULL; 68966af876cSToby Isaac 6909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 6919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(aSec, p, closureSize)); 6929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 69366af876cSToby Isaac } 69466af876cSToby Isaac } 6959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(aSec)); 6969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(aSec, &size)); 6979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &anchors)); 69866af876cSToby Isaac for (p = aMin; p < aMax; p++) { 69966af876cSToby Isaac PetscInt parent, ancestor = p; 70066af876cSToby Isaac 701f9f063d4SToby Isaac if (canonLabel) { 702f9f063d4SToby Isaac PetscInt canon; 703f9f063d4SToby Isaac 7049566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon)); 705f9f063d4SToby Isaac if (p != canon) continue; 706f9f063d4SToby Isaac } 7079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL)); 70866af876cSToby Isaac while (parent != ancestor) { 70966af876cSToby Isaac ancestor = parent; 7109566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, ancestor, &parent, NULL)); 71166af876cSToby Isaac } 71266af876cSToby Isaac if (ancestor != p) { 71366af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 71466af876cSToby Isaac 7159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 71666af876cSToby Isaac 7179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 7189371c9d4SSatish Balay for (j = 0; j < closureSize; j++) { anchors[aOff + j] = closure[2 * j]; } 7199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure)); 72066af876cSToby Isaac } 72166af876cSToby Isaac } 7229566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, anchors, PETSC_OWN_POINTER, &aIS)); 7236dd5a8c8SToby Isaac { 7246dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7256dd5a8c8SToby Isaac IS aISNew = aIS; 7266dd5a8c8SToby Isaac 7279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aSec)); 7289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aIS)); 7296dd5a8c8SToby Isaac while (aSecNew) { 7309566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec)); 7319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS)); 7326dd5a8c8SToby Isaac aSec = aSecNew; 7336dd5a8c8SToby Isaac aIS = aISNew; 7346dd5a8c8SToby Isaac aSecNew = NULL; 7356dd5a8c8SToby Isaac aISNew = NULL; 7369566063dSJacob Faibussowitsch PetscCall(AnchorsFlatten(aSec, aIS, &aSecNew, &aISNew)); 7376dd5a8c8SToby Isaac } 7386dd5a8c8SToby Isaac } 7399566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm, aSec, aIS)); 7409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec)); 7419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS)); 74266af876cSToby Isaac PetscFunctionReturn(0); 74366af876cSToby Isaac } 74466af876cSToby Isaac 7459371c9d4SSatish Balay static PetscErrorCode DMPlexGetTrueSupportSize(DM dm, PetscInt p, PetscInt *dof, PetscInt *numTrueSupp) { 7466461c1adSToby Isaac PetscFunctionBegin; 7476461c1adSToby Isaac if (numTrueSupp[p] == -1) { 7486461c1adSToby Isaac PetscInt i, alldof; 7496461c1adSToby Isaac const PetscInt *supp; 7506461c1adSToby Isaac PetscInt count = 0; 7516461c1adSToby Isaac 7529566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &alldof)); 7539566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &supp)); 7546461c1adSToby Isaac for (i = 0; i < alldof; i++) { 7556461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 7566461c1adSToby Isaac const PetscInt *cone; 7576461c1adSToby Isaac 7589566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &numCones)); 7599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &cone)); 7606461c1adSToby Isaac for (j = 0; j < numCones; j++) { 7616461c1adSToby Isaac if (cone[j] == p) break; 7626461c1adSToby Isaac } 7636461c1adSToby Isaac if (j < numCones) count++; 7646461c1adSToby Isaac } 7656461c1adSToby Isaac numTrueSupp[p] = count; 7666461c1adSToby Isaac } 7676461c1adSToby Isaac *dof = numTrueSupp[p]; 7686461c1adSToby Isaac PetscFunctionReturn(0); 7696461c1adSToby Isaac } 7706461c1adSToby Isaac 7719371c9d4SSatish Balay static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) { 772776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 773776742edSToby Isaac PetscSection newSupportSection; 774776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 7756461c1adSToby Isaac PetscInt *numTrueSupp; 776776742edSToby Isaac PetscInt *offsets; 777776742edSToby Isaac 778776742edSToby Isaac PetscFunctionBegin; 779776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 780776742edSToby Isaac /* symmetrize the hierarchy */ 7819566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7829566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)), &newSupportSection)); 7839566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 7849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSupportSection, pStart, pEnd)); 7859566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd, &offsets)); 7869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd, &numTrueSupp)); 7876461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 7886461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 789776742edSToby Isaac * parent(q) */ 790776742edSToby Isaac for (d = 0; d <= depth; d++) { 7919566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pStart, &pEnd)); 792776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 793776742edSToby Isaac PetscInt dof, q, qdof, parent; 794776742edSToby Isaac 7959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm, p, &dof, numTrueSupp)); 7969566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, dof)); 797776742edSToby Isaac q = p; 7989566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 799776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 800776742edSToby Isaac q = parent; 801776742edSToby Isaac 8029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm, q, &qdof, numTrueSupp)); 8039566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, qdof)); 8049566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, q, dof)); 8059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 806776742edSToby Isaac } 807776742edSToby Isaac } 808776742edSToby Isaac } 8099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSupportSection)); 8109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSupportSection, &newSize)); 8119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newSize, &newSupports)); 812776742edSToby Isaac for (d = 0; d <= depth; d++) { 8139566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pStart, &pEnd)); 814776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 815776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 816776742edSToby Isaac 8179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 8199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(newSupportSection, p, &newDof)); 8209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, p, &newOff)); 821776742edSToby Isaac for (i = 0; i < dof; i++) { 8226461c1adSToby Isaac PetscInt numCones, j; 8236461c1adSToby Isaac const PetscInt *cone; 8246461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 8256461c1adSToby Isaac 8269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &numCones)); 8279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &cone)); 8286461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8296461c1adSToby Isaac if (cone[j] == p) break; 8306461c1adSToby Isaac } 8316461c1adSToby Isaac if (j < numCones) newSupports[newOff + offsets[p]++] = q; 832776742edSToby Isaac } 833776742edSToby Isaac 834776742edSToby Isaac q = p; 8359566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 836776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 837776742edSToby Isaac q = parent; 8389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, q, &qdof)); 8399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &qoff)); 8409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, q, &newqOff)); 841776742edSToby Isaac for (i = 0; i < qdof; i++) { 8426461c1adSToby Isaac PetscInt numCones, j; 8436461c1adSToby Isaac const PetscInt *cone; 8446461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 8456461c1adSToby Isaac 8469566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, r, &numCones)); 8479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, r, &cone)); 8486461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8496461c1adSToby Isaac if (cone[j] == q) break; 8506461c1adSToby Isaac } 8516461c1adSToby Isaac if (j < numCones) newSupports[newOff + offsets[p]++] = r; 852776742edSToby Isaac } 853776742edSToby Isaac for (i = 0; i < dof; i++) { 8546461c1adSToby Isaac PetscInt numCones, j; 8556461c1adSToby Isaac const PetscInt *cone; 8566461c1adSToby Isaac PetscInt r = mesh->supports[off + 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] == p) break; 8626461c1adSToby Isaac } 8636461c1adSToby Isaac if (j < numCones) newSupports[newqOff + offsets[q]++] = r; 864776742edSToby Isaac } 8659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL)); 866776742edSToby Isaac } 867776742edSToby Isaac } 868776742edSToby Isaac } 8699566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 870776742edSToby Isaac mesh->supportSection = newSupportSection; 8719566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 872776742edSToby Isaac mesh->supports = newSupports; 8739566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 8749566063dSJacob Faibussowitsch PetscCall(PetscFree(numTrueSupp)); 875776742edSToby Isaac 876776742edSToby Isaac PetscFunctionReturn(0); 877776742edSToby Isaac } 878776742edSToby Isaac 879f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM, PetscSection, PetscSection, Mat); 880f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM, PetscSection, PetscSection, Mat); 881f7c74593SToby Isaac 8829371c9d4SSatish Balay static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) { 883f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 884f9f063d4SToby Isaac DM refTree; 885f9f063d4SToby Isaac PetscInt size; 886f9f063d4SToby Isaac 887f9f063d4SToby Isaac PetscFunctionBegin; 888f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 889f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 8909566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)parentSection)); 8919566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 892f9f063d4SToby Isaac mesh->parentSection = parentSection; 8939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &size)); 894f9f063d4SToby Isaac if (parents != mesh->parents) { 8959566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 8969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->parents)); 8979566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->parents, parents, size)); 898f9f063d4SToby Isaac } 899f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 9009566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 9019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->childIDs)); 9029566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->childIDs, childIDs, size)); 903f9f063d4SToby Isaac } 9049566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 905f9f063d4SToby Isaac if (refTree) { 906f9f063d4SToby Isaac DMLabel canonLabel; 907f9f063d4SToby Isaac 9089566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonLabel)); 909f9f063d4SToby Isaac if (canonLabel) { 910f9f063d4SToby Isaac PetscInt i; 911f9f063d4SToby Isaac 912f9f063d4SToby Isaac for (i = 0; i < size; i++) { 913f9f063d4SToby Isaac PetscInt canon; 9149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon)); 9159371c9d4SSatish Balay if (canon >= 0) { mesh->childIDs[i] = canon; } 916f9f063d4SToby Isaac } 917f9f063d4SToby Isaac } 918f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 9196e0288c8SStefano Zampini } else { 920f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 921f9f063d4SToby Isaac } 9229566063dSJacob Faibussowitsch PetscCall(DMPlexTreeSymmetrize(dm)); 923f9f063d4SToby Isaac if (computeCanonical) { 924f9f063d4SToby Isaac PetscInt d, dim; 925f9f063d4SToby Isaac 926f9f063d4SToby Isaac /* add the canonical label */ 9279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9289566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "canonical")); 929f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 930f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 931f9f063d4SToby Isaac const PetscInt *cChildren; 932f9f063d4SToby Isaac 9339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 934f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 9359566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, p, &cNumChildren, &cChildren)); 936f9f063d4SToby Isaac if (cNumChildren) { 937f9f063d4SToby Isaac canon = p; 938f9f063d4SToby Isaac break; 939f9f063d4SToby Isaac } 940f9f063d4SToby Isaac } 941f9f063d4SToby Isaac if (canon == -1) continue; 942f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 943f9f063d4SToby Isaac PetscInt numChildren, i; 944f9f063d4SToby Isaac const PetscInt *children; 945f9f063d4SToby Isaac 9469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, p, &numChildren, &children)); 947f9f063d4SToby Isaac if (numChildren) { 94863a3b9bcSJacob 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); 9499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "canonical", p, canon)); 9509371c9d4SSatish Balay for (i = 0; i < numChildren; i++) { PetscCall(DMSetLabelValue(dm, "canonical", children[i], cChildren[i])); } 951f9f063d4SToby Isaac } 952f9f063d4SToby Isaac } 953f9f063d4SToby Isaac } 954f9f063d4SToby Isaac } 9551baa6e33SBarry Smith if (exchangeSupports) PetscCall(DMPlexTreeExchangeSupports(dm)); 956f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 957f7c74593SToby Isaac /* reset anchors */ 9589566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm, NULL, NULL)); 959f9f063d4SToby Isaac PetscFunctionReturn(0); 960f9f063d4SToby Isaac } 961f9f063d4SToby Isaac 9620b7167a0SToby Isaac /*@ 9630b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 9640b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 9650b7167a0SToby Isaac tree root. 9660b7167a0SToby Isaac 9670b7167a0SToby Isaac Collective on dm 9680b7167a0SToby Isaac 9690b7167a0SToby Isaac Input Parameters: 9700b7167a0SToby Isaac + dm - the DMPlex object 9710b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 9720b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 9730b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 9740b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 9750b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 9760b7167a0SToby Isaac 9770b7167a0SToby Isaac Level: intermediate 9780b7167a0SToby Isaac 979db781477SPatrick Sanan .seealso: `DMPlexGetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 9800b7167a0SToby Isaac @*/ 9819371c9d4SSatish Balay PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) { 9820b7167a0SToby Isaac PetscFunctionBegin; 9839566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm, parentSection, parents, childIDs, PETSC_FALSE, PETSC_TRUE)); 9840b7167a0SToby Isaac PetscFunctionReturn(0); 9850b7167a0SToby Isaac } 9860b7167a0SToby Isaac 987b2f41788SToby Isaac /*@ 988b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 989b2f41788SToby Isaac Collective on dm 990b2f41788SToby Isaac 991f899ff85SJose E. Roman Input Parameter: 992b2f41788SToby Isaac . dm - the DMPlex object 993b2f41788SToby Isaac 994b2f41788SToby Isaac Output Parameters: 995b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 996b2f41788SToby Isaac offset indexes the parent and childID list 997b2f41788SToby Isaac . parents - a list of the point parents 998b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 999b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1000b2f41788SToby Isaac . childSection - the inverse of the parent section 1001b2f41788SToby Isaac - children - a list of the point children 1002b2f41788SToby Isaac 1003b2f41788SToby Isaac Level: intermediate 1004b2f41788SToby Isaac 1005db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 1006b2f41788SToby Isaac @*/ 10079371c9d4SSatish Balay PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) { 1008b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1009b2f41788SToby Isaac 1010b2f41788SToby Isaac PetscFunctionBegin; 1011b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1012b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1013b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1014b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1015b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1016b2f41788SToby Isaac if (children) *children = mesh->children; 1017b2f41788SToby Isaac PetscFunctionReturn(0); 1018b2f41788SToby Isaac } 1019b2f41788SToby Isaac 1020d961a43aSToby Isaac /*@ 1021eaf898f9SPatrick Sanan DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the DAG) 1022d961a43aSToby Isaac 1023d961a43aSToby Isaac Input Parameters: 1024d961a43aSToby Isaac + dm - the DMPlex object 1025d961a43aSToby Isaac - point - the query point 1026d961a43aSToby Isaac 1027d961a43aSToby Isaac Output Parameters: 1028d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 1029d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 1030d961a43aSToby Isaac does not have a parent 1031d961a43aSToby Isaac 1032d961a43aSToby Isaac Level: intermediate 1033d961a43aSToby Isaac 1034db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeChildren()` 1035d961a43aSToby Isaac @*/ 10369371c9d4SSatish Balay PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) { 1037d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1038d961a43aSToby Isaac PetscSection pSec; 1039d961a43aSToby Isaac 1040d961a43aSToby Isaac PetscFunctionBegin; 1041d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1042d961a43aSToby Isaac pSec = mesh->parentSection; 1043d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1044d961a43aSToby Isaac PetscInt dof; 1045d961a43aSToby Isaac 10469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, point, &dof)); 1047d961a43aSToby Isaac if (dof) { 1048d961a43aSToby Isaac PetscInt off; 1049d961a43aSToby Isaac 10509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, point, &off)); 1051d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1052d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 1053d961a43aSToby Isaac PetscFunctionReturn(0); 1054d961a43aSToby Isaac } 1055d961a43aSToby Isaac } 10569371c9d4SSatish Balay if (parent) { *parent = point; } 10579371c9d4SSatish Balay if (childID) { *childID = 0; } 1058d961a43aSToby Isaac PetscFunctionReturn(0); 1059d961a43aSToby Isaac } 1060d961a43aSToby Isaac 1061d961a43aSToby Isaac /*@C 1062eaf898f9SPatrick Sanan DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the DAG) 1063d961a43aSToby Isaac 1064d961a43aSToby Isaac Input Parameters: 1065d961a43aSToby Isaac + dm - the DMPlex object 1066d961a43aSToby Isaac - point - the query point 1067d961a43aSToby Isaac 1068d961a43aSToby Isaac Output Parameters: 1069d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 1070d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 1071d961a43aSToby Isaac 1072d961a43aSToby Isaac Level: intermediate 1073d961a43aSToby Isaac 1074d961a43aSToby Isaac Fortran Notes: 1075d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1076d961a43aSToby Isaac include petsc.h90 in your code. 1077d961a43aSToby Isaac 1078db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeParent()` 1079d961a43aSToby Isaac @*/ 10809371c9d4SSatish Balay PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) { 1081d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1082d961a43aSToby Isaac PetscSection childSec; 1083d961a43aSToby Isaac PetscInt dof = 0; 1084d961a43aSToby Isaac 1085d961a43aSToby Isaac PetscFunctionBegin; 1086d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1087d961a43aSToby Isaac childSec = mesh->childSection; 10889371c9d4SSatish Balay if (childSec && point >= childSec->pStart && point < childSec->pEnd) { PetscCall(PetscSectionGetDof(childSec, point, &dof)); } 1089d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1090d961a43aSToby Isaac if (children) { 1091d961a43aSToby Isaac if (dof) { 1092d961a43aSToby Isaac PetscInt off; 1093d961a43aSToby Isaac 10949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, point, &off)); 1095d961a43aSToby Isaac *children = &mesh->children[off]; 10969371c9d4SSatish Balay } else { 1097d961a43aSToby Isaac *children = NULL; 1098d961a43aSToby Isaac } 1099d961a43aSToby Isaac } 1100d961a43aSToby Isaac PetscFunctionReturn(0); 1101d961a43aSToby Isaac } 11020c37af3bSToby Isaac 11039371c9d4SSatish Balay 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) { 110452a3aeb4SToby Isaac PetscInt f, b, p, c, offset, qPoints; 1105b3a4bf2aSToby Isaac 1106b3a4bf2aSToby Isaac PetscFunctionBegin; 11079566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(space, nPoints, points, work, NULL, NULL)); 110852a3aeb4SToby Isaac for (f = 0, offset = 0; f < nFunctionals; f++) { 110952a3aeb4SToby Isaac qPoints = pointsPerFn[f]; 111052a3aeb4SToby Isaac for (b = 0; b < nBasis; b++) { 1111b3a4bf2aSToby Isaac PetscScalar val = 0.; 1112b3a4bf2aSToby Isaac 111352a3aeb4SToby Isaac for (p = 0; p < qPoints; p++) { 11149371c9d4SSatish Balay for (c = 0; c < nComps; c++) { val += work[((offset + p) * nBasis + b) * nComps + c] * weights[(offset + p) * nComps + c]; } 111552a3aeb4SToby Isaac } 11169566063dSJacob Faibussowitsch PetscCall(MatSetValue(basisAtPoints, b, f, val, INSERT_VALUES)); 1117b3a4bf2aSToby Isaac } 1118b3a4bf2aSToby Isaac offset += qPoints; 1119b3a4bf2aSToby Isaac } 11209566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(basisAtPoints, MAT_FINAL_ASSEMBLY)); 11219566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(basisAtPoints, MAT_FINAL_ASSEMBLY)); 1122b3a4bf2aSToby Isaac PetscFunctionReturn(0); 1123b3a4bf2aSToby Isaac } 1124b3a4bf2aSToby Isaac 11259371c9d4SSatish Balay static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) { 11260c37af3bSToby Isaac PetscDS ds; 11270c37af3bSToby Isaac PetscInt spdim; 11280c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 11290c37af3bSToby Isaac const PetscInt *anchors; 1130f7c74593SToby Isaac PetscSection aSec; 11310c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 11320c37af3bSToby Isaac IS aIS; 11330c37af3bSToby Isaac 11340c37af3bSToby Isaac PetscFunctionBegin; 11359566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11369566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 11379566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 11389566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 11399566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 11409566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 11419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &conStart, &conEnd)); 11429566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &spdim)); 11439566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(spdim, &v0, spdim, &v0parent, spdim, &vtmp, spdim * spdim, &J, spdim * spdim, &Jparent, spdim * spdim, &invJparent)); 11440c37af3bSToby Isaac 11450c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 11460dd1b1feSToby Isaac PetscObject disc; 11470dd1b1feSToby Isaac PetscClassId id; 1148b3a4bf2aSToby Isaac PetscSpace bspace; 1149b3a4bf2aSToby Isaac PetscDualSpace dspace; 11509c3cf19fSMatthew G. Knepley PetscInt i, j, k, nPoints, Nc, offset; 115152a3aeb4SToby Isaac PetscInt fSize, maxDof; 1152b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 11531683a169SBarry Smith PetscScalar *scwork; 11541683a169SBarry Smith const PetscScalar *X; 11552c44ad04SToby Isaac PetscInt *sizes, *workIndRow, *workIndCol; 11560c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 11572c44ad04SToby Isaac const PetscInt *numDof = NULL; 1158085f0adfSToby Isaac const PetscInt ***perms = NULL; 1159085f0adfSToby Isaac const PetscScalar ***flips = NULL; 11600c37af3bSToby Isaac 11619566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 11629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &id)); 11630dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1164b3a4bf2aSToby Isaac PetscFE fe = (PetscFE)disc; 1165b3a4bf2aSToby Isaac 11669566063dSJacob Faibussowitsch PetscCall(PetscFEGetBasisSpace(fe, &bspace)); 11679566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dspace)); 11689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize)); 11699566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc)); 11709371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) { 1171b3a4bf2aSToby Isaac PetscFV fv = (PetscFV)disc; 1172b3a4bf2aSToby Isaac 11739566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc)); 11749566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)fv), &bspace)); 11759566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(bspace, PETSCSPACEPOLYNOMIAL)); 11769566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(bspace, 0, PETSC_DETERMINE)); 11779566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(bspace, Nc)); 11789566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(bspace, spdim)); 11799566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(bspace)); 11809566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv, &dspace)); 11819566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize)); 11829371c9d4SSatish Balay } else SETERRQ(PetscObjectComm(disc), PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 11839566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dspace, &numDof)); 11842c44ad04SToby Isaac for (i = 0, maxDof = 0; i <= spdim; i++) { maxDof = PetscMax(maxDof, numDof[i]); } 11859566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dspace, &perms, &flips)); 11860dd1b1feSToby Isaac 11879566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &Amat)); 11889566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Amat, fSize, fSize, fSize, fSize)); 11899566063dSJacob Faibussowitsch PetscCall(MatSetType(Amat, MATSEQDENSE)); 11909566063dSJacob Faibussowitsch PetscCall(MatSetUp(Amat)); 11919566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Bmat)); 11929566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Xmat)); 11930c37af3bSToby Isaac nPoints = 0; 11940c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 119552a3aeb4SToby Isaac PetscInt qPoints, thisNc; 11960c37af3bSToby Isaac PetscQuadrature quad; 11970c37af3bSToby Isaac 11989566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad)); 11999566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &thisNc, &qPoints, NULL, NULL)); 120063a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 12010c37af3bSToby Isaac nPoints += qPoints; 12020c37af3bSToby Isaac } 12039566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(fSize, &sizes, nPoints * Nc, &weights, spdim * nPoints, &pointsRef, spdim * nPoints, &pointsReal, nPoints * fSize * Nc, &work, maxDof, &workIndRow, maxDof, &workIndCol)); 12049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &scwork)); 12050c37af3bSToby Isaac offset = 0; 12060c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12070c37af3bSToby Isaac PetscInt qPoints; 12080c37af3bSToby Isaac const PetscReal *p, *w; 12090c37af3bSToby Isaac PetscQuadrature quad; 12100c37af3bSToby Isaac 12119566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad)); 12129566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &qPoints, &p, &w)); 12139566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(weights + Nc * offset, w, Nc * qPoints)); 12149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pointsRef + spdim * offset, p, spdim * qPoints)); 1215b3a4bf2aSToby Isaac sizes[i] = qPoints; 12160c37af3bSToby Isaac offset += qPoints; 12170c37af3bSToby Isaac } 12189566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsRef, weights, work, Amat)); 12199566063dSJacob Faibussowitsch PetscCall(MatLUFactor(Amat, NULL, NULL, NULL)); 12200c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 12210c37af3bSToby Isaac PetscInt parent; 12220c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 12230c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 12240c37af3bSToby Isaac 12259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, c, &parent, NULL)); 12260c37af3bSToby Isaac if (parent == c) continue; 12279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 12280c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12290c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12300c37af3bSToby Isaac PetscInt conDof; 12310c37af3bSToby Isaac 12320c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1233085f0adfSToby Isaac if (numFields) { 12349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof)); 12359371c9d4SSatish Balay } else { 12369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof)); 12370c37af3bSToby Isaac } 12380c37af3bSToby Isaac if (conDof) break; 12390c37af3bSToby Isaac } 12400c37af3bSToby Isaac if (i == closureSize) { 12419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 12420c37af3bSToby Isaac continue; 12430c37af3bSToby Isaac } 12440c37af3bSToby Isaac 12459566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ)); 12469566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent)); 12470c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1248c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 1249c330f8ffSToby Isaac 1250c330f8ffSToby Isaac CoordinatesRefToReal(spdim, spdim, xi0, v0, J, &pointsRef[i * spdim], vtmp); 1251c330f8ffSToby Isaac CoordinatesRealToRef(spdim, spdim, xi0, v0parent, invJparent, vtmp, &pointsReal[i * spdim]); 12520c37af3bSToby Isaac } 12539566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsReal, weights, work, Bmat)); 12549566063dSJacob Faibussowitsch PetscCall(MatMatSolve(Amat, Bmat, Xmat)); 12559566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Xmat, &X)); 12569566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP)); 12579566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(closureSize + 1, &childOffsets, closureSizeP + 1, &parentOffsets)); 12580c37af3bSToby Isaac childOffsets[0] = 0; 12590c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12600c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12610c37af3bSToby Isaac PetscInt dof; 12620c37af3bSToby Isaac 1263085f0adfSToby Isaac if (numFields) { 12649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 12659371c9d4SSatish Balay } else { 12669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 12670c37af3bSToby Isaac } 126852a3aeb4SToby Isaac childOffsets[i + 1] = childOffsets[i] + dof; 12690c37af3bSToby Isaac } 12700c37af3bSToby Isaac parentOffsets[0] = 0; 12710c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 12720c37af3bSToby Isaac PetscInt p = closureP[2 * i]; 12730c37af3bSToby Isaac PetscInt dof; 12740c37af3bSToby Isaac 1275085f0adfSToby Isaac if (numFields) { 12769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 12779371c9d4SSatish Balay } else { 12789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 12790c37af3bSToby Isaac } 128052a3aeb4SToby Isaac parentOffsets[i + 1] = parentOffsets[i] + dof; 12810c37af3bSToby Isaac } 12820c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12832c44ad04SToby Isaac PetscInt conDof, conOff, aDof, aOff, nWork; 12840c37af3bSToby Isaac PetscInt p = closure[2 * i]; 12850c37af3bSToby Isaac PetscInt o = closure[2 * i + 1]; 1286085f0adfSToby Isaac const PetscInt *perm; 1287085f0adfSToby Isaac const PetscScalar *flip; 12880c37af3bSToby Isaac 12890c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1290085f0adfSToby Isaac if (numFields) { 12919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof)); 12929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &conOff)); 12939371c9d4SSatish Balay } else { 12949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof)); 12959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &conOff)); 12960c37af3bSToby Isaac } 12970c37af3bSToby Isaac if (!conDof) continue; 1298085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL; 1299085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL; 13009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 13019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 13022c44ad04SToby Isaac nWork = childOffsets[i + 1] - childOffsets[i]; 13030c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 13040c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 13050c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 13060c37af3bSToby Isaac 1307085f0adfSToby Isaac if (numFields) { 13089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aSecDof)); 13099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aSecOff)); 13109371c9d4SSatish Balay } else { 13119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aSecDof)); 13129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aSecOff)); 13130c37af3bSToby Isaac } 13140c37af3bSToby Isaac if (!aSecDof) continue; 13150c37af3bSToby Isaac 13160c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 13170c37af3bSToby Isaac PetscInt q = closureP[2 * j]; 13180c37af3bSToby Isaac PetscInt oq = closureP[2 * j + 1]; 13192c44ad04SToby Isaac 13202c44ad04SToby Isaac if (q == a) { 132152a3aeb4SToby Isaac PetscInt r, s, nWorkP; 1322085f0adfSToby Isaac const PetscInt *permP; 1323085f0adfSToby Isaac const PetscScalar *flipP; 1324085f0adfSToby Isaac 1325085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL; 1326085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL; 13272c44ad04SToby Isaac nWorkP = parentOffsets[j + 1] - parentOffsets[j]; 13282c44ad04SToby Isaac /* get a copy of the child-to-anchor portion of the matrix, and transpose so that rows correspond to the 13291683a169SBarry Smith * child and columns correspond to the anchor: BUT the maxrix returned by MatDenseGetArrayRead() is 13302c44ad04SToby Isaac * column-major, so transpose-transpose = do nothing */ 13312c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 13329371c9d4SSatish Balay for (s = 0; s < nWorkP; s++) { scwork[r * nWorkP + s] = X[fSize * (r + childOffsets[i]) + (s + parentOffsets[j])]; } 13332c44ad04SToby Isaac } 133452a3aeb4SToby Isaac for (r = 0; r < nWork; r++) { workIndRow[perm ? perm[r] : r] = conOff + r; } 133552a3aeb4SToby Isaac for (s = 0; s < nWorkP; s++) { workIndCol[permP ? permP[s] : s] = aSecOff + s; } 13362c44ad04SToby Isaac if (flip) { 13372c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 13389371c9d4SSatish Balay for (s = 0; s < nWorkP; s++) { scwork[r * nWorkP + s] *= flip[r]; } 13392c44ad04SToby Isaac } 13402c44ad04SToby Isaac } 13412c44ad04SToby Isaac if (flipP) { 13422c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 13439371c9d4SSatish Balay for (s = 0; s < nWorkP; s++) { scwork[r * nWorkP + s] *= flipP[s]; } 13442c44ad04SToby Isaac } 13452c44ad04SToby Isaac } 13469566063dSJacob Faibussowitsch PetscCall(MatSetValues(cMat, nWork, workIndRow, nWorkP, workIndCol, scwork, INSERT_VALUES)); 13472c44ad04SToby Isaac break; 13480c37af3bSToby Isaac } 13490c37af3bSToby Isaac } 13500c37af3bSToby Isaac } 13510c37af3bSToby Isaac } 13529566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Xmat, &X)); 13539566063dSJacob Faibussowitsch PetscCall(PetscFree2(childOffsets, parentOffsets)); 13549566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 13559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP)); 13560c37af3bSToby Isaac } 13579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Amat)); 13589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bmat)); 13599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Xmat)); 13609566063dSJacob Faibussowitsch PetscCall(PetscFree(scwork)); 13619566063dSJacob Faibussowitsch PetscCall(PetscFree7(sizes, weights, pointsRef, pointsReal, work, workIndRow, workIndCol)); 13629371c9d4SSatish Balay if (id == PETSCFV_CLASSID) { PetscCall(PetscSpaceDestroy(&bspace)); } 13630c37af3bSToby Isaac } 13649566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 13659566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 13669566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJparent)); 13679566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 13680c37af3bSToby Isaac 13690c37af3bSToby Isaac PetscFunctionReturn(0); 13700c37af3bSToby Isaac } 137195a0b26dSToby Isaac 13729371c9d4SSatish Balay static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) { 1373f7c74593SToby Isaac Mat refCmat; 137421968bf8SToby Isaac PetscDS ds; 1375085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 137621968bf8SToby Isaac PetscScalar ***refPointFieldMats; 137721968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 137821968bf8SToby Isaac IS refAnIS; 137921968bf8SToby Isaac const PetscInt *refAnchors; 1380085f0adfSToby Isaac const PetscInt **perms; 1381085f0adfSToby Isaac const PetscScalar **flips; 138295a0b26dSToby Isaac 138395a0b26dSToby Isaac PetscFunctionBegin; 13849566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 13859566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1386085f0adfSToby Isaac maxFields = PetscMax(1, numFields); 13879566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 13889566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 13899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(refAnIS, &refAnchors)); 13909566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 13919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 13929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 13939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldN)); 13949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 13959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 13969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 13979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxAnDof, &cols)); 139895a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 139995a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 140095a0b26dSToby Isaac 14019566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 14029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 140395a0b26dSToby Isaac if (!pDof || parent == p) continue; 140495a0b26dSToby Isaac 14059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxFields, &refPointFieldMats[p - pRefStart])); 14069566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxFields, &refPointFieldN[p - pRefStart])); 14079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure)); 1408085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1409085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i; 141095a0b26dSToby Isaac 1411085f0adfSToby Isaac if (f < numFields) { 14129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 14139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 14149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips)); 1415085f0adfSToby Isaac } else { 14169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 14179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 14189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(refSection, closureSize, closure, &perms, &flips)); 141995a0b26dSToby Isaac } 142095a0b26dSToby Isaac 14219371c9d4SSatish Balay for (r = 0; r < cDof; r++) { rows[r] = cOff + r; } 142295a0b26dSToby Isaac numCols = 0; 142395a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 142495a0b26dSToby Isaac PetscInt q = closure[2 * i]; 142595a0b26dSToby Isaac PetscInt aDof, aOff, j; 1426085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 142795a0b26dSToby Isaac 1428085f0adfSToby Isaac if (numFields) { 14299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof)); 14309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff)); 14319371c9d4SSatish Balay } else { 14329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof)); 14339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff)); 143495a0b26dSToby Isaac } 143595a0b26dSToby Isaac 14369371c9d4SSatish Balay for (j = 0; j < aDof; j++) { cols[numCols++] = aOff + (perm ? perm[j] : j); } 143795a0b26dSToby Isaac } 143895a0b26dSToby Isaac refPointFieldN[p - pRefStart][f] = numCols; 14399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 14409566063dSJacob Faibussowitsch PetscCall(MatGetValues(refCmat, cDof, rows, numCols, cols, refPointFieldMats[p - pRefStart][f])); 1441085f0adfSToby Isaac if (flips) { 1442085f0adfSToby Isaac PetscInt colOff = 0; 1443085f0adfSToby Isaac 1444085f0adfSToby Isaac for (i = 0; i < closureSize; i++) { 1445085f0adfSToby Isaac PetscInt q = closure[2 * i]; 1446085f0adfSToby Isaac PetscInt aDof, aOff, j; 1447085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 1448085f0adfSToby Isaac 1449085f0adfSToby Isaac if (numFields) { 14509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof)); 14519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff)); 14529371c9d4SSatish Balay } else { 14539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof)); 14549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff)); 1455085f0adfSToby Isaac } 1456085f0adfSToby Isaac if (flip) { 1457085f0adfSToby Isaac PetscInt k; 1458085f0adfSToby Isaac for (k = 0; k < cDof; k++) { 14599371c9d4SSatish Balay for (j = 0; j < aDof; j++) { refPointFieldMats[p - pRefStart][f][k * numCols + colOff + j] *= flip[j]; } 1460085f0adfSToby Isaac } 1461085f0adfSToby Isaac } 1462085f0adfSToby Isaac colOff += aDof; 1463085f0adfSToby Isaac } 1464085f0adfSToby Isaac } 1465085f0adfSToby Isaac if (numFields) { 14669566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips)); 1467085f0adfSToby Isaac } else { 14689566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(refSection, closureSize, closure, &perms, &flips)); 1469085f0adfSToby Isaac } 147095a0b26dSToby Isaac } 14719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure)); 147295a0b26dSToby Isaac } 147321968bf8SToby Isaac *childrenMats = refPointFieldMats; 147421968bf8SToby Isaac *childrenN = refPointFieldN; 14759566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(refAnIS, &refAnchors)); 14769566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 14779566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 147821968bf8SToby Isaac PetscFunctionReturn(0); 147921968bf8SToby Isaac } 148021968bf8SToby Isaac 14819371c9d4SSatish Balay static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) { 148221968bf8SToby Isaac PetscDS ds; 148321968bf8SToby Isaac PetscInt **refPointFieldN; 148421968bf8SToby Isaac PetscScalar ***refPointFieldMats; 1485085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f; 148621968bf8SToby Isaac PetscSection refConSec; 148721968bf8SToby Isaac 148821968bf8SToby Isaac PetscFunctionBegin; 148921968bf8SToby Isaac refPointFieldN = *childrenN; 149021968bf8SToby Isaac *childrenN = NULL; 149121968bf8SToby Isaac refPointFieldMats = *childrenMats; 149221968bf8SToby Isaac *childrenMats = NULL; 14939566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 14949566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1495367003a6SStefano Zampini maxFields = PetscMax(1, numFields); 14969566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 14979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 149821968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 149921968bf8SToby Isaac PetscInt parent, pDof; 150021968bf8SToby Isaac 15019566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 15029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 150321968bf8SToby Isaac if (!pDof || parent == p) continue; 150421968bf8SToby Isaac 1505085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 150621968bf8SToby Isaac PetscInt cDof; 150721968bf8SToby Isaac 1508085f0adfSToby Isaac if (numFields) { 15099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 15109371c9d4SSatish Balay } else { 15119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 151221968bf8SToby Isaac } 151321968bf8SToby Isaac 15149566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 151521968bf8SToby Isaac } 15169566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 15179566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN[p - pRefStart])); 151821968bf8SToby Isaac } 15199566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 15209566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN)); 152121968bf8SToby Isaac PetscFunctionReturn(0); 152221968bf8SToby Isaac } 152321968bf8SToby Isaac 15249371c9d4SSatish Balay static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) { 152521968bf8SToby Isaac DM refTree; 152621968bf8SToby Isaac PetscDS ds; 152721968bf8SToby Isaac Mat refCmat; 1528085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 152921968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 153021968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 153121968bf8SToby Isaac IS refAnIS, anIS; 153221968bf8SToby Isaac const PetscInt *anchors; 153321968bf8SToby Isaac 153421968bf8SToby Isaac PetscFunctionBegin; 153521968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15369566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 15379566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 1538085f0adfSToby Isaac maxFields = PetscMax(1, numFields); 15399566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 15409566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, refTree)); 15419566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL)); 15429566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS)); 15439566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anSec, &anIS)); 15449566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anIS, &anchors)); 15459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 15469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(conSec, &conStart, &conEnd)); 15479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 15489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof)); 15499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof * maxAnDof, &pointWork)); 155021968bf8SToby Isaac 155121968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 15529566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 155395a0b26dSToby Isaac 155495a0b26dSToby Isaac /* step 2: compute the preorder */ 15559566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 15569566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &perm, pEnd - pStart, &iperm)); 155795a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 155895a0b26dSToby Isaac perm[p - pStart] = p; 155995a0b26dSToby Isaac iperm[p - pStart] = p - pStart; 156095a0b26dSToby Isaac } 156195a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 156295a0b26dSToby Isaac PetscInt point = perm[p]; 156395a0b26dSToby Isaac PetscInt parent; 156495a0b26dSToby Isaac 15659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 156695a0b26dSToby Isaac if (parent == point) { 156795a0b26dSToby Isaac p++; 15689371c9d4SSatish Balay } else { 156995a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 157095a0b26dSToby Isaac 15719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 157295a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 157395a0b26dSToby Isaac PetscInt q = closure[2 * i]; 157495a0b26dSToby Isaac if (iperm[q - pStart] > iperm[point - pStart]) { 157595a0b26dSToby Isaac /* swap */ 157695a0b26dSToby Isaac perm[p] = q; 157795a0b26dSToby Isaac perm[iperm[q - pStart]] = point; 157895a0b26dSToby Isaac iperm[point - pStart] = iperm[q - pStart]; 157995a0b26dSToby Isaac iperm[q - pStart] = p; 158095a0b26dSToby Isaac break; 158195a0b26dSToby Isaac } 158295a0b26dSToby Isaac } 158395a0b26dSToby Isaac size = closureSize; 15849566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 15859371c9d4SSatish Balay if (i == size) { p++; } 158695a0b26dSToby Isaac } 158795a0b26dSToby Isaac } 158895a0b26dSToby Isaac 158995a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 159095a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 159195a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 159295a0b26dSToby Isaac * values outside of the Mat first. 159395a0b26dSToby Isaac */ 159495a0b26dSToby Isaac { 159595a0b26dSToby Isaac PetscInt nRows, row, nnz; 159695a0b26dSToby Isaac PetscBool done; 1597*cd6fc93eSToby Isaac PetscInt secStart, secEnd; 159895a0b26dSToby Isaac const PetscInt *ia, *ja; 159995a0b26dSToby Isaac PetscScalar *vals; 160095a0b26dSToby Isaac 1601*cd6fc93eSToby Isaac PetscCall(PetscSectionGetChart(section, &secStart, &secEnd)); 16029566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 160328b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not get RowIJ of constraint matrix"); 160495a0b26dSToby Isaac nnz = ia[nRows]; 160595a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 160695a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 16079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &vals)); 160895a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 160995a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 161095a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 161195a0b26dSToby Isaac 16129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, &childid)); 161395a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 16149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &pointDof)); 161595a0b26dSToby Isaac if (!pointDof) continue; 16169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 1617085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1618085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 161995a0b26dSToby Isaac PetscScalar *pointMat; 1620085f0adfSToby Isaac const PetscInt **perms; 1621085f0adfSToby Isaac const PetscScalar **flips; 162295a0b26dSToby Isaac 1623085f0adfSToby Isaac if (numFields) { 16249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, point, f, &cDof)); 16259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, point, f, &cOff)); 16269371c9d4SSatish Balay } else { 16279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &cDof)); 16289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, point, &cOff)); 162995a0b26dSToby Isaac } 163095a0b26dSToby Isaac if (!cDof) continue; 16319566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 16329566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, closureSize, closure, &perms, &flips)); 163395a0b26dSToby Isaac 163495a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 163576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 163695a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 163795a0b26dSToby Isaac if (cDof > 1 && r) { 163863a3b9bcSJacob 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])); 163995a0b26dSToby Isaac } 164095a0b26dSToby Isaac } 164176bd3646SJed Brown } 164295a0b26dSToby Isaac /* zero rows */ 16439371c9d4SSatish Balay for (i = ia[cOff]; i < ia[cOff + cDof]; i++) { vals[i] = 0.; } 164495a0b26dSToby Isaac matOffset = ia[cOff]; 164595a0b26dSToby Isaac numFillCols = ia[cOff + 1] - matOffset; 164695a0b26dSToby Isaac pointMat = refPointFieldMats[childid - pRefStart][f]; 164795a0b26dSToby Isaac numCols = refPointFieldN[childid - pRefStart][f]; 164895a0b26dSToby Isaac offset = 0; 164995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 165095a0b26dSToby Isaac PetscInt q = closure[2 * i]; 165195a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 1652085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1653085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 165495a0b26dSToby Isaac 165595a0b26dSToby Isaac qConDof = qConOff = 0; 1656*cd6fc93eSToby Isaac if (q < secStart || q >= secEnd) continue; 1657085f0adfSToby Isaac if (numFields) { 16589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, q, f, &aDof)); 16599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, q, f, &aOff)); 166095a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, q, f, &qConDof)); 16629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, q, f, &qConOff)); 166395a0b26dSToby Isaac } 16649371c9d4SSatish Balay } else { 16659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &aDof)); 16669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &aOff)); 166795a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 16689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, q, &qConDof)); 16699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, q, &qConOff)); 167095a0b26dSToby Isaac } 167195a0b26dSToby Isaac } 167295a0b26dSToby Isaac if (!aDof) continue; 167395a0b26dSToby Isaac if (qConDof) { 167495a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 167595a0b26dSToby Isaac * be filled, thanks to preordering */ 167695a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 167795a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 167895a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 167995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 168095a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 168195a0b26dSToby Isaac PetscScalar inVal = 0; 168295a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1683085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 168495a0b26dSToby Isaac 1685085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 168695a0b26dSToby Isaac } 168795a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 168895a0b26dSToby Isaac } 168995a0b26dSToby Isaac } 169095a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 169195a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 169295a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 169395a0b26dSToby Isaac for (; k < numFillCols; k++) { 16949371c9d4SSatish Balay if (ja[matOffset + k] == col) { break; } 169595a0b26dSToby Isaac } 169663a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, col); 16979371c9d4SSatish Balay for (r = 0; r < cDof; r++) { vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; } 169895a0b26dSToby Isaac } 16999371c9d4SSatish Balay } else { 170095a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 170195a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 17029371c9d4SSatish Balay if (ja[matOffset + k] == aOff) { break; } 170395a0b26dSToby Isaac } 170463a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, aOff); 170595a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1706085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1707085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1708085f0adfSToby Isaac 1709085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 171095a0b26dSToby Isaac } 171195a0b26dSToby Isaac } 171295a0b26dSToby Isaac } 171395a0b26dSToby Isaac offset += aDof; 171495a0b26dSToby Isaac } 1715085f0adfSToby Isaac if (numFields) { 17169566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, closureSize, closure, &perms, &flips)); 1717085f0adfSToby Isaac } else { 17189566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, closureSize, closure, &perms, &flips)); 1719085f0adfSToby Isaac } 172095a0b26dSToby Isaac } 17219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 172295a0b26dSToby Isaac } 17239371c9d4SSatish Balay for (row = 0; row < nRows; row++) { PetscCall(MatSetValues(cMat, 1, &row, ia[row + 1] - ia[row], &ja[ia[row]], &vals[ia[row]], INSERT_VALUES)); } 17249566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done)); 172528b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not restore RowIJ of constraint matrix"); 17269566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY)); 17279566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY)); 17289566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 172995a0b26dSToby Isaac } 173095a0b26dSToby Isaac 173195a0b26dSToby Isaac /* clean up */ 17329566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anIS, &anchors)); 17339566063dSJacob Faibussowitsch PetscCall(PetscFree2(perm, iperm)); 17349566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 17359566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 173695a0b26dSToby Isaac PetscFunctionReturn(0); 173795a0b26dSToby Isaac } 173895a0b26dSToby Isaac 17396f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 17406f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 17419371c9d4SSatish Balay PetscErrorCode DMPlexTreeRefineCell(DM dm, PetscInt cell, DM *ncdm) { 17426f5f1567SToby Isaac DM K; 1743420f55faSMatthew G. Knepley PetscMPIInt rank; 17446f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 17456f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 17466f5f1567SToby Isaac PetscInt *Kembedding; 17476f5f1567SToby Isaac PetscInt *cellClosure = NULL, nc; 17486f5f1567SToby Isaac PetscScalar *newVertexCoords; 17496f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 17506f5f1567SToby Isaac PetscSection parentSection; 17516f5f1567SToby Isaac 17526f5f1567SToby Isaac PetscFunctionBegin; 17539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17549566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 17559566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm)); 17569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ncdm, dim)); 17576f5f1567SToby Isaac 17589566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 17599566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &parentSection)); 17609566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &K)); 17616858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 1762dd400576SPatrick Sanan if (rank == 0) { 17636f5f1567SToby Isaac /* compute the new charts */ 17649566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim + 1, &pNewCount, dim + 1, &pNewStart, dim + 1, &pNewEnd, dim + 1, &pOldStart, dim + 1, &pOldEnd)); 17656f5f1567SToby Isaac offset = 0; 17666f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 17676f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 17686f5f1567SToby Isaac 17696f5f1567SToby Isaac pNewStart[d] = offset; 17709566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pOldStart[d], &pOldEnd[d])); 17719566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 17726f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 17736f5f1567SToby Isaac /* adding the new points */ 17746f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 17756f5f1567SToby Isaac if (!d) { 17766f5f1567SToby Isaac /* removing the cell */ 17776f5f1567SToby Isaac pNewCount[d]--; 17786f5f1567SToby Isaac } 17796f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 17806f5f1567SToby Isaac PetscInt parent; 17819566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &parent, NULL)); 17826f5f1567SToby Isaac if (parent == k) { 17836f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 17846f5f1567SToby Isaac pNewCount[d]--; 17856f5f1567SToby Isaac } 17866f5f1567SToby Isaac } 17876f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 17886f5f1567SToby Isaac offset = pNewEnd[d]; 17896f5f1567SToby Isaac } 17901dca8a05SBarry 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]); 17916f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 17929566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 17936f5f1567SToby Isaac 17949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pNewEnd[dim], &newConeSizes)); 17956f5f1567SToby Isaac { 1796b5a892a1SMatthew G. Knepley DMPolytopeType pct, qct; 17976f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 17986f5f1567SToby Isaac 17999566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &kStart, &kEnd)); 18009566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(kEnd - kStart, &Kembedding, kEnd - kStart, &perm, kEnd - kStart, &iperm, kEnd - kStart, &preOrient)); 18016f5f1567SToby Isaac 18026f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18036f5f1567SToby Isaac perm[k - kStart] = k; 18046f5f1567SToby Isaac iperm[k - kStart] = k - kStart; 18056f5f1567SToby Isaac preOrient[k - kStart] = 0; 18066f5f1567SToby Isaac } 18076f5f1567SToby Isaac 18089566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18096f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 18106f5f1567SToby Isaac PetscInt parentOrientA = closureK[2 * j + 1]; 18116f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2 * j + 1]; 18126f5f1567SToby Isaac PetscInt p, q; 18136f5f1567SToby Isaac 18146f5f1567SToby Isaac p = closureK[2 * j]; 18156f5f1567SToby Isaac q = cellClosure[2 * j]; 18169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, p, &pct)); 18179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, q, &qct)); 18186f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18199371c9d4SSatish Balay if (q >= pOldStart[d] && q < pOldEnd[d]) { Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; } 18206f5f1567SToby Isaac } 1821b5a892a1SMatthew G. Knepley parentOrientA = DMPolytopeConvertNewOrientation_Internal(pct, parentOrientA); 1822b5a892a1SMatthew G. Knepley parentOrientB = DMPolytopeConvertNewOrientation_Internal(qct, parentOrientB); 18236f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 18246f5f1567SToby Isaac PetscInt numChildren, i; 18256f5f1567SToby Isaac const PetscInt *children; 18266f5f1567SToby Isaac 18279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(K, p, &numChildren, &children)); 18286f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 18296f5f1567SToby Isaac PetscInt kPerm, oPerm; 18306f5f1567SToby Isaac 18316f5f1567SToby Isaac k = children[i]; 18329566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(K, p, parentOrientA, 0, k, parentOrientB, &oPerm, &kPerm)); 18336f5f1567SToby Isaac /* perm = what refTree position I'm in */ 18346f5f1567SToby Isaac perm[kPerm - kStart] = k; 18356f5f1567SToby Isaac /* iperm = who is at this position */ 18366f5f1567SToby Isaac iperm[k - kStart] = kPerm - kStart; 18376f5f1567SToby Isaac preOrient[kPerm - kStart] = oPerm; 18386f5f1567SToby Isaac } 18396f5f1567SToby Isaac } 18406f5f1567SToby Isaac } 18419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK)); 18426f5f1567SToby Isaac } 18439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, pNewEnd[dim])); 18446f5f1567SToby Isaac offset = 0; 18456f5f1567SToby Isaac numNewCones = 0; 18466f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18476f5f1567SToby Isaac PetscInt kStart, kEnd, k; 18486f5f1567SToby Isaac PetscInt p; 18496f5f1567SToby Isaac PetscInt size; 18506f5f1567SToby Isaac 18516f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 18526f5f1567SToby Isaac /* skip cell 0 */ 18536f5f1567SToby Isaac if (p == cell) continue; 18546f5f1567SToby Isaac /* old cones to new cones */ 18559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 18566f5f1567SToby Isaac newConeSizes[offset++] = size; 18576f5f1567SToby Isaac numNewCones += size; 18586f5f1567SToby Isaac } 18596f5f1567SToby Isaac 18609566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 18616f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18626f5f1567SToby Isaac PetscInt kParent; 18636f5f1567SToby Isaac 18649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 18656f5f1567SToby Isaac if (kParent != k) { 18666f5f1567SToby Isaac Kembedding[k] = offset; 18679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 18686f5f1567SToby Isaac newConeSizes[offset++] = size; 18696f5f1567SToby Isaac numNewCones += size; 18709371c9d4SSatish Balay if (kParent != 0) { PetscCall(PetscSectionSetDof(parentSection, Kembedding[k], 1)); } 18716f5f1567SToby Isaac } 18726f5f1567SToby Isaac } 18736f5f1567SToby Isaac } 18746f5f1567SToby Isaac 18759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 18769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &numPointsWithParents)); 18779566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numNewCones, &newCones, numNewCones, &newOrientations)); 18789566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPointsWithParents, &parents, numPointsWithParents, &childIDs)); 18796f5f1567SToby Isaac 18806f5f1567SToby Isaac /* fill new cones */ 18816f5f1567SToby Isaac offset = 0; 18826f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18836f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 18846f5f1567SToby Isaac PetscInt p; 18856f5f1567SToby Isaac PetscInt size; 18866f5f1567SToby Isaac const PetscInt *cone, *orientation; 18876f5f1567SToby Isaac 18886f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 18896f5f1567SToby Isaac /* skip cell 0 */ 18906f5f1567SToby Isaac if (p == cell) continue; 18916f5f1567SToby Isaac /* old cones to new cones */ 18929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 18939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 18949566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &orientation)); 18956f5f1567SToby Isaac for (l = 0; l < size; l++) { 18966f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 18976f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 18986f5f1567SToby Isaac } 18996f5f1567SToby Isaac } 19006f5f1567SToby Isaac 19019566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd)); 19026f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19036f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 19046f5f1567SToby Isaac PetscInt preO = preOrient[k]; 19056f5f1567SToby Isaac 19069566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL)); 19076f5f1567SToby Isaac if (kParent != k) { 19086f5f1567SToby Isaac /* embed new cones */ 19099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size)); 19109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, kPerm, &cone)); 19119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, kPerm, &orientation)); 19126f5f1567SToby Isaac for (l = 0; l < size; l++) { 19136f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size - (preO + 1) - l) % size); 19146f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 1915b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_NUM_POLYTOPES; 19166f5f1567SToby Isaac 19176f5f1567SToby Isaac q = iperm[cone[m]]; 19186f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 19199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, q, &lSize)); 1920b5a892a1SMatthew G. Knepley if (lSize == 2) ct = DM_POLYTOPE_SEGMENT; 1921b5a892a1SMatthew G. Knepley else if (lSize == 4) ct = DM_POLYTOPE_QUADRILATERAL; 1922b5a892a1SMatthew G. Knepley oTrue = DMPolytopeConvertNewOrientation_Internal(ct, orientation[m]); 19236f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 19246f5f1567SToby Isaac newO = DihedralCompose(lSize, oTrue, preOrient[q]); 1925b5a892a1SMatthew G. Knepley newOrientations[offset++] = DMPolytopeConvertOldOrientation_Internal(ct, newO); 19266f5f1567SToby Isaac } 19276f5f1567SToby Isaac if (kParent != 0) { 19286f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 19299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, Kembedding[k], &pOffset)); 19306f5f1567SToby Isaac parents[pOffset] = newPoint; 19316f5f1567SToby Isaac childIDs[pOffset] = k; 19326f5f1567SToby Isaac } 19336f5f1567SToby Isaac } 19346f5f1567SToby Isaac } 19356f5f1567SToby Isaac } 19366f5f1567SToby Isaac 19379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * (pNewEnd[dim] - pNewStart[dim]), &newVertexCoords)); 19386f5f1567SToby Isaac 19396f5f1567SToby Isaac /* fill coordinates */ 19406f5f1567SToby Isaac offset = 0; 19416f5f1567SToby Isaac { 1942d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 19436f5f1567SToby Isaac PetscSection vSection; 19446f5f1567SToby Isaac PetscInt v; 19456f5f1567SToby Isaac Vec coords; 19466f5f1567SToby Isaac PetscScalar *coordvals; 19476f5f1567SToby Isaac PetscInt dof, off; 1948c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 19496f5f1567SToby Isaac 195076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1951d90620a3SMatthew G. Knepley PetscInt k; 19529566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, 0, &kStart, &kEnd)); 19536f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19549566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ)); 195563a3b9bcSJacob Faibussowitsch PetscCheck(detJ > 0., PETSC_COMM_SELF, PETSC_ERR_PLIB, "reference tree cell %" PetscInt_FMT " has bad determinant", k); 19566f5f1567SToby Isaac } 1957d90620a3SMatthew G. Knepley } 19589566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ)); 19599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &vSection)); 19609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coords)); 19619566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19626f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 19639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(vSection, v, &dof)); 19649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, v, &off)); 19659371c9d4SSatish Balay for (l = 0; l < dof; l++) { newVertexCoords[offset++] = coordvals[off + l]; } 19666f5f1567SToby Isaac } 19679566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 19686f5f1567SToby Isaac 19699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &vSection)); 19709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &coords)); 19719566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals)); 19729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &kStart, &kEnd)); 19736f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 19749bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 19756f5f1567SToby Isaac PetscInt vPerm = perm[v]; 19766f5f1567SToby Isaac PetscInt kParent; 1977c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 19786f5f1567SToby Isaac 19799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, v, &kParent, NULL)); 19806f5f1567SToby Isaac if (kParent != v) { 19816f5f1567SToby Isaac /* this is a new vertex */ 19829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, vPerm, &off)); 19839bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off + l]); 1984367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord); 19859bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset + l] = newCoord[l]; 19866f5f1567SToby Isaac offset += dim; 19876f5f1567SToby Isaac } 19886f5f1567SToby Isaac } 19899566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals)); 19906f5f1567SToby Isaac } 19916f5f1567SToby Isaac 19926f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 19936f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 19946f5f1567SToby Isaac PetscInt tmp; 19956f5f1567SToby Isaac 19966f5f1567SToby Isaac tmp = pNewCount[d]; 19976f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 19986f5f1567SToby Isaac pNewCount[dim - d] = tmp; 19996f5f1567SToby Isaac } 20006f5f1567SToby Isaac 20019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, pNewCount, newConeSizes, newCones, newOrientations, newVertexCoords)); 20029566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20039566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, parents, childIDs)); 20046f5f1567SToby Isaac 20056f5f1567SToby Isaac /* clean up */ 20069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure)); 20079566063dSJacob Faibussowitsch PetscCall(PetscFree5(pNewCount, pNewStart, pNewEnd, pOldStart, pOldEnd)); 20089566063dSJacob Faibussowitsch PetscCall(PetscFree(newConeSizes)); 20099566063dSJacob Faibussowitsch PetscCall(PetscFree2(newCones, newOrientations)); 20109566063dSJacob Faibussowitsch PetscCall(PetscFree(newVertexCoords)); 20119566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs)); 20129566063dSJacob Faibussowitsch PetscCall(PetscFree4(Kembedding, perm, iperm, preOrient)); 20139371c9d4SSatish Balay } else { 20146f5f1567SToby Isaac PetscInt p, counts[4]; 20156f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 20166f5f1567SToby Isaac Vec coordVec; 20176f5f1567SToby Isaac PetscScalar *coords; 20186f5f1567SToby Isaac 20196f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20206f5f1567SToby Isaac PetscInt dStart, dEnd; 20216f5f1567SToby Isaac 20229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 20236f5f1567SToby Isaac counts[d] = dEnd - dStart; 20246f5f1567SToby Isaac } 20259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &coneSizes)); 20269371c9d4SSatish Balay for (p = pStart; p < pEnd; p++) { PetscCall(DMPlexGetConeSize(dm, p, &coneSizes[p - pStart])); } 20279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 20289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &orientations)); 20299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordVec)); 20309566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordVec, &coords)); 20316f5f1567SToby Isaac 20329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd)); 20339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 20349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, counts, coneSizes, cones, orientations, NULL)); 20359566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K)); 20369566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, NULL, NULL)); 20379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordVec, &coords)); 20386f5f1567SToby Isaac } 20399566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 20406f5f1567SToby Isaac 20416f5f1567SToby Isaac PetscFunctionReturn(0); 20426f5f1567SToby Isaac } 20436ecaa68aSToby Isaac 20449371c9d4SSatish Balay PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) { 20456ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 20466ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 20476ecaa68aSToby Isaac PetscSection localCoarse, localFine; 20486ecaa68aSToby Isaac PetscSection aSec, cSec; 20496ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 205046bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 205146bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 205246bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 20536ecaa68aSToby Isaac IS aIS; 20546ecaa68aSToby Isaac const PetscInt *anchors; 20556ecaa68aSToby Isaac Mat cMat; 20564acb8e1eSToby Isaac PetscInt numFields, maxFields; 20576ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 20586ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 20591c58ffc4SToby Isaac PetscInt *maxChildIds; 2060e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 20614acb8e1eSToby Isaac const PetscInt ***perms; 20624acb8e1eSToby Isaac const PetscScalar ***flips; 20636ecaa68aSToby Isaac 20646ecaa68aSToby Isaac PetscFunctionBegin; 20659566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 20669566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 20679566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 20686ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 206989698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 207089698031SToby Isaac const PetscInt *leaves; 20716ecaa68aSToby Isaac 20729566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 207389698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 207489698031SToby Isaac p = leaves ? leaves[l] : l; 20759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 20769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 20779371c9d4SSatish Balay if ((dof - cdof) > 0) { numPointsWithDofs++; } 20786ecaa68aSToby Isaac } 20799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 20807cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 208189698031SToby Isaac p = leaves ? leaves[l] : l; 20829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 20839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 20849371c9d4SSatish Balay if ((dof - cdof) > 0) { pointsWithDofs[offset++] = l; } 20856ecaa68aSToby Isaac } 20869566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 20879566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 20886ecaa68aSToby Isaac } 20896ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 20909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 20919371c9d4SSatish Balay for (p = pStartC; p < pEndC; p++) { maxChildIds[p - pStartC] = -2; } 209257168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 209357168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX)); 209446bdb399SToby Isaac 20959566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 20969566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 209746bdb399SToby Isaac 20989566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 20999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 21009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 210146bdb399SToby Isaac 21029566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 21039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 210446bdb399SToby Isaac 210546bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 21069566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 21079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootMatricesSec)); 21089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootIndicesSec, pStartC, pEndC)); 21099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootMatricesSec, pStartC, pEndC)); 21109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 2111713c1c5dSToby Isaac maxFields = PetscMax(1, numFields); 21129566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields + 1, &offsets, maxFields + 1, &offsetsCopy, maxFields + 1, &newOffsets, maxFields + 1, &newOffsetsCopy, maxFields + 1, &rowOffsets, maxFields + 1, &numD, maxFields + 1, &numO)); 21139566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxFields + 1, (PetscInt ****)&perms, maxFields + 1, (PetscScalar ****)&flips)); 21149566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)perms, (maxFields + 1) * sizeof(const PetscInt **))); 21159566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)flips, (maxFields + 1) * sizeof(const PetscScalar **))); 211646bdb399SToby Isaac 211746bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 21188d2f55e7SToby Isaac PetscInt dof, matSize = 0; 21196ecaa68aSToby Isaac PetscInt aDof = 0; 21206ecaa68aSToby Isaac PetscInt cDof = 0; 21216ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 21226ecaa68aSToby Isaac PetscInt numRowIndices = 0; 21236ecaa68aSToby Isaac PetscInt numColIndices = 0; 2124f13f9184SToby Isaac PetscInt f; 21256ecaa68aSToby Isaac 21269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 21279371c9d4SSatish Balay if (dof < 0) { dof = -(dof + 1); } 21289371c9d4SSatish Balay if (p >= aStart && p < aEnd) { PetscCall(PetscSectionGetDof(aSec, p, &aDof)); } 21299371c9d4SSatish Balay if (p >= cStart && p < cEnd) { PetscCall(PetscSectionGetDof(cSec, p, &cDof)); } 2130f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2131f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 21326ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2133f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 21346ecaa68aSToby Isaac 21359566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 213646bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 21376ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 21386ecaa68aSToby Isaac 21399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 21406ecaa68aSToby Isaac numRowIndices += clDof; 21416ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &clDof)); 21436ecaa68aSToby Isaac offsets[f + 1] += clDof; 21446ecaa68aSToby Isaac } 21456ecaa68aSToby Isaac } 21466ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21476ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 21486ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 21496ecaa68aSToby Isaac } 215046bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 21519566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, NULL, NULL, NULL, &numColIndices, NULL, NULL, newOffsets, PETSC_FALSE)); 21529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 21536ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 21546ecaa68aSToby Isaac numColIndices = numRowIndices; 21556ecaa68aSToby Isaac matSize = 0; 21569371c9d4SSatish Balay } else if (numFields) { /* we send one submat for each field: sum their sizes */ 21576ecaa68aSToby Isaac matSize = 0; 21586ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21596ecaa68aSToby Isaac PetscInt numRow, numCol; 21606ecaa68aSToby Isaac 21616ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2162f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 21636ecaa68aSToby Isaac matSize += numRow * numCol; 21646ecaa68aSToby Isaac } 21659371c9d4SSatish Balay } else { 21666ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 21676ecaa68aSToby Isaac } 2168f13f9184SToby Isaac } else if (maxChildId == -1) { 21698d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2170f13f9184SToby Isaac PetscInt aOff, a; 21716ecaa68aSToby Isaac 21729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 21736ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21746ecaa68aSToby Isaac PetscInt fDof; 21756ecaa68aSToby Isaac 21769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 217721968bf8SToby Isaac offsets[f + 1] = fDof; 21786ecaa68aSToby Isaac } 21796ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 21806ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 21816ecaa68aSToby Isaac 21829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, anchor, &aLocalDof)); 21836ecaa68aSToby Isaac numColIndices += aLocalDof; 21846ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 21856ecaa68aSToby Isaac PetscInt fDof; 21866ecaa68aSToby Isaac 21879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 218821968bf8SToby Isaac newOffsets[f + 1] += fDof; 21896ecaa68aSToby Isaac } 21906ecaa68aSToby Isaac } 21916ecaa68aSToby Isaac if (numFields) { 21926ecaa68aSToby Isaac matSize = 0; 21939371c9d4SSatish Balay for (f = 0; f < numFields; f++) { matSize += offsets[f + 1] * newOffsets[f + 1]; } 21949371c9d4SSatish Balay } else { 21956ecaa68aSToby Isaac matSize = numColIndices * dof; 21966ecaa68aSToby Isaac } 21979371c9d4SSatish Balay } else { /* no children, and no constraints on dofs: just get the global indices */ 21986ecaa68aSToby Isaac numColIndices = dof; 21996ecaa68aSToby Isaac matSize = 0; 22006ecaa68aSToby Isaac } 22018d2f55e7SToby Isaac } 220246bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 22039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootIndicesSec, p, numColIndices ? numColIndices + 2 * numFields : 0)); 22049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootMatricesSec, p, matSize)); 22056ecaa68aSToby Isaac } 22069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootIndicesSec)); 22079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootMatricesSec)); 22086ecaa68aSToby Isaac { 22096ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 22106ecaa68aSToby Isaac 22119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 22129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootMatricesSec, &numRootMatrices)); 22139566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRootIndices, &rootIndices, numRootMatrices, &rootMatrices)); 22146ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22156ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2216f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 22176ecaa68aSToby Isaac PetscInt *pInd; 22186ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22196ecaa68aSToby Isaac PetscScalar *pMat = NULL; 22206ecaa68aSToby Isaac 22219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, p, &numColIndices)); 22229371c9d4SSatish Balay if (!numColIndices) { continue; } 2223f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2224f13f9184SToby Isaac offsets[f] = 0; 2225f13f9184SToby Isaac newOffsets[f] = 0; 2226f13f9184SToby Isaac offsetsCopy[f] = 0; 2227f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2228f13f9184SToby Isaac } 22296ecaa68aSToby Isaac numColIndices -= 2 * numFields; 22309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, p, &pIndOff)); 22316ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 22329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootMatricesSec, p, &matSize)); 22336ecaa68aSToby Isaac if (matSize) { 22349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootMatricesSec, p, &pMatOff)); 22356ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 22366ecaa68aSToby Isaac } 22379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 22389371c9d4SSatish Balay if (dof < 0) { dof = -(dof + 1); } 22396ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 22406ecaa68aSToby Isaac PetscInt i, j; 22416ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 22426ecaa68aSToby Isaac 22436ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 22446ecaa68aSToby Isaac PetscInt numIndices, *indices; 22459566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 224608401ef6SPierre Jolivet PetscCheck(numIndices == numColIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "mismatching constraint indices calculations"); 22479371c9d4SSatish Balay for (i = 0; i < numColIndices; i++) { pInd[i] = indices[i]; } 22486ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 224946bdb399SToby Isaac pInd[numColIndices + i] = offsets[i + 1]; 225046bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i + 1]; 22516ecaa68aSToby Isaac } 22529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL)); 22539371c9d4SSatish Balay } else { 22546ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 22556ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 22566ecaa68aSToby Isaac PetscInt numPoints, *points; 22576ecaa68aSToby Isaac 22589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices * numRowIndices, MPIU_SCALAR, &pMatIn)); 22596ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 22609371c9d4SSatish Balay for (j = 0; j < numRowIndices; j++) { pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; } 22616ecaa68aSToby Isaac } 22629566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 22634acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 22649566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 22659566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 22664acb8e1eSToby Isaac } 22676ecaa68aSToby Isaac if (numFields) { 22686ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 22696ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 22706ecaa68aSToby Isaac 22716ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22726ecaa68aSToby Isaac PetscInt fDof; 22736ecaa68aSToby Isaac 22749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &fDof)); 22756ecaa68aSToby Isaac offsets[f + 1] += fDof; 22766ecaa68aSToby Isaac } 22776ecaa68aSToby Isaac } 22786ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22796ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 22806ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 22816ecaa68aSToby Isaac } 22826ecaa68aSToby Isaac } 22834acb8e1eSToby Isaac /* TODO : flips here ? */ 22846ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 22859566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, perms, pMatIn, &numPoints, NULL, &points, &pMatModified, newOffsets, PETSC_FALSE)); 22864acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 22879566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f])); 22889566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f])); 22894acb8e1eSToby Isaac } 22904acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 22919566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 22929566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 22934acb8e1eSToby Isaac } 22946ecaa68aSToby Isaac if (!numFields) { 22959371c9d4SSatish Balay for (i = 0; i < numRowIndices * numColIndices; i++) { pMat[i] = pMatModified[i]; } 22969371c9d4SSatish Balay } else { 2297f13f9184SToby Isaac PetscInt i, j, count; 22986ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 22996ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f + 1]; i++) { 23009371c9d4SSatish Balay for (j = newOffsets[f]; j < newOffsets[f + 1]; j++, count++) { pMat[count] = pMatModified[i * numColIndices + j]; } 23016ecaa68aSToby Isaac } 23026ecaa68aSToby Isaac } 23036ecaa68aSToby Isaac } 23049566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatModified)); 23059566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 23069566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatIn)); 23076ecaa68aSToby Isaac if (numFields) { 230846bdb399SToby Isaac for (f = 0; f < numFields; f++) { 230946bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 231046bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 23116ecaa68aSToby Isaac } 23124acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23134acb8e1eSToby Isaac PetscInt globalOff, c = points[2 * cl]; 23149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23159566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd)); 23166ecaa68aSToby Isaac } 23176ecaa68aSToby Isaac } else { 23184acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 23194acb8e1eSToby Isaac PetscInt c = points[2 * cl], globalOff; 23204acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 23214acb8e1eSToby Isaac 23229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 23239566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd)); 23246ecaa68aSToby Isaac } 23256ecaa68aSToby Isaac } 23264acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 23279566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f])); 23289566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, numPoints, points, &perms[f], &flips[f])); 23294acb8e1eSToby Isaac } 23309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numPoints, MPIU_SCALAR, &points)); 23316ecaa68aSToby Isaac } 23329371c9d4SSatish Balay } else if (matSize) { 23336ecaa68aSToby Isaac PetscInt cOff; 23346ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 23356ecaa68aSToby Isaac 23366ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 233708401ef6SPierre Jolivet PetscCheck(numRowIndices == dof, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Miscounted dofs"); 23389566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 23399566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 23409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &cOff)); 23419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 23429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 23436ecaa68aSToby Isaac if (numFields) { 23446ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23456ecaa68aSToby Isaac PetscInt fDof; 2346f13f9184SToby Isaac 23479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &fDof)); 23486ecaa68aSToby Isaac offsets[f + 1] = fDof; 23496ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23506ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 23519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof)); 23526ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 23536ecaa68aSToby Isaac } 23546ecaa68aSToby Isaac } 23556ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23566ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23576ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 23586ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 23596ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 23606ecaa68aSToby Isaac } 23619566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, -1, NULL, rowIndices)); 23626ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23636ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23659566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, -1, NULL, colIndices)); 23666ecaa68aSToby Isaac } 23679371c9d4SSatish Balay } else { 23689566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, NULL, rowIndices)); 23696ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23706ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 23719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff)); 23729566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, NULL, colIndices)); 23736ecaa68aSToby Isaac } 23746ecaa68aSToby Isaac } 23756ecaa68aSToby Isaac if (numFields) { 2376f13f9184SToby Isaac PetscInt count, a; 2377f13f9184SToby Isaac 23786ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 23796ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 23806ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 23819566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, iSize, &rowIndices[offsets[f]], jSize, &colIndices[newOffsets[f]], &pMat[count])); 23826ecaa68aSToby Isaac count += iSize * jSize; 238346bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 238446bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1]; 23856ecaa68aSToby Isaac } 23866ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23876ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 23886ecaa68aSToby Isaac PetscInt gOff; 23899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 23909566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 23916ecaa68aSToby Isaac } 23929371c9d4SSatish Balay } else { 23936ecaa68aSToby Isaac PetscInt a; 23949566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, numRowIndices, rowIndices, numColIndices, colIndices, pMat)); 23956ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23966ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 23976ecaa68aSToby Isaac PetscInt gOff; 23989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff)); 23999566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, NULL, pInd)); 24006ecaa68aSToby Isaac } 24016ecaa68aSToby Isaac } 24029566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numColIndices, MPIU_INT, &colIndices)); 24039566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices)); 24049371c9d4SSatish Balay } else { 24056ecaa68aSToby Isaac PetscInt gOff; 24066ecaa68aSToby Isaac 24079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 24086ecaa68aSToby Isaac if (numFields) { 24096ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24106ecaa68aSToby Isaac PetscInt fDof; 24119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 24126ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 24136ecaa68aSToby Isaac } 24146ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 241546bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1]; 241646bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f + 1]; 24176ecaa68aSToby Isaac } 24189566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 2419367003a6SStefano Zampini } else { 24209566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 24216ecaa68aSToby Isaac } 24226ecaa68aSToby Isaac } 24236ecaa68aSToby Isaac } 24249566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 24256ecaa68aSToby Isaac } 242646bdb399SToby Isaac { 242746bdb399SToby Isaac PetscSF indicesSF, matricesSF; 242846bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 242946bdb399SToby Isaac 24309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 24319566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafMatricesSec)); 24329566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootIndicesSec, &remoteOffsetsIndices, leafIndicesSec)); 24339566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootMatricesSec, &remoteOffsetsMatrices, leafMatricesSec)); 24349566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootIndicesSec, remoteOffsetsIndices, leafIndicesSec, &indicesSF)); 24359566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootMatricesSec, remoteOffsetsMatrices, leafMatricesSec, &matricesSF)); 24369566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 24379566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsIndices)); 24389566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsMatrices)); 24399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numLeafIndices)); 24409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafMatricesSec, &numLeafMatrices)); 24419566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numLeafIndices, &leafIndices, numLeafMatrices, &leafMatrices)); 24429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24439566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24449566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE)); 24459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE)); 24469566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&matricesSF)); 24479566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 24489566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootIndices, rootMatrices)); 24499566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 24509566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootMatricesSec)); 245146bdb399SToby Isaac } 245246bdb399SToby Isaac /* count to preallocate */ 24539566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 245446bdb399SToby Isaac { 245546bdb399SToby Isaac PetscInt nGlobal; 245646bdb399SToby Isaac PetscInt *dnnz, *onnz; 2457b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2458b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 24591c58ffc4SToby Isaac PetscInt maxDof; 24601c58ffc4SToby Isaac PetscInt *rowIndices; 24611c58ffc4SToby Isaac DM refTree; 24621c58ffc4SToby Isaac PetscInt **refPointFieldN; 24631c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 24641c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 24650eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, maxConDof, maxColumns, leafStart, leafEnd; 24661c58ffc4SToby Isaac PetscScalar *pointWork; 246746bdb399SToby Isaac 24689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalFine, &nGlobal)); 24699566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nGlobal, &dnnz, nGlobal, &onnz)); 24709566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 24719566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 24729566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 24739566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 24749566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 24759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 24769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafIndicesSec, &leafStart, &leafEnd)); 24779566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 24780eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 247946bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 248046bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 248146bdb399SToby Isaac PetscInt matSize; 248221968bf8SToby Isaac PetscInt i; 248346bdb399SToby Isaac 24849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 24859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 24869371c9d4SSatish Balay if ((gDof - gcDof) <= 0) { continue; } 24879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 248808401ef6SPierre Jolivet PetscCheck(gOff >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I though having global dofs meant a non-negative offset"); 24891dca8a05SBarry Smith PetscCheck(gOff >= rowStart && (gOff + gDof - gcDof) <= rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I thought the row map would constrain the global dofs"); 24909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 24919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 249246bdb399SToby Isaac numColIndices -= 2 * numFields; 249308401ef6SPierre Jolivet PetscCheck(numColIndices > 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "global fine dof with no dofs to interpolate from"); 249446bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 249521968bf8SToby Isaac offsets[0] = 0; 249621968bf8SToby Isaac offsetsCopy[0] = 0; 249721968bf8SToby Isaac newOffsets[0] = 0; 249821968bf8SToby Isaac newOffsetsCopy[0] = 0; 249946bdb399SToby Isaac if (numFields) { 250021968bf8SToby Isaac PetscInt f; 250146bdb399SToby Isaac for (f = 0; f < numFields; f++) { 250246bdb399SToby Isaac PetscInt rowDof; 250346bdb399SToby Isaac 25049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 250521968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 250621968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 250721968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 250821968bf8SToby Isaac numD[f] = 0; 250921968bf8SToby Isaac numO[f] = 0; 251046bdb399SToby Isaac } 25119566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 251246bdb399SToby Isaac for (f = 0; f < numFields; f++) { 251321968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 251421968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 251546bdb399SToby Isaac 251646bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 251746bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 251846bdb399SToby Isaac 251946bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 252021968bf8SToby Isaac numD[f]++; 25219371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 252221968bf8SToby Isaac numO[f]++; 252346bdb399SToby Isaac } 252446bdb399SToby Isaac } 252546bdb399SToby Isaac } 25269371c9d4SSatish Balay } else { 25279566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 252821968bf8SToby Isaac numD[0] = 0; 252921968bf8SToby Isaac numO[0] = 0; 253046bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 253146bdb399SToby Isaac PetscInt gInd = pInd[i]; 253246bdb399SToby Isaac 253346bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 253421968bf8SToby Isaac numD[0]++; 25359371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */ 253621968bf8SToby Isaac numO[0]++; 253746bdb399SToby Isaac } 253846bdb399SToby Isaac } 253946bdb399SToby Isaac } 25409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 254146bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 254246bdb399SToby Isaac PetscInt childId; 254346bdb399SToby Isaac 254446bdb399SToby Isaac childId = childIds[p - pStartF]; 254521968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 254646bdb399SToby Isaac if (numFields) { 2547b9a5774bSToby Isaac PetscInt f; 2548b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 254921968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 255046bdb399SToby Isaac for (row = 0; row < numRows; row++) { 255121968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 255221968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 255346bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25541dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2555b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25569371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25571dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2558b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25599371c9d4SSatish Balay } else { /* constrained */ 256008401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 256146bdb399SToby Isaac } 256246bdb399SToby Isaac } 256346bdb399SToby Isaac } 25649371c9d4SSatish Balay } else { 2565b9a5774bSToby Isaac PetscInt i; 2566b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 256746bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 256846bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 256946bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 25701dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2571b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 25729371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */ 25731dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2574b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 25759371c9d4SSatish Balay } else { /* constrained */ 257608401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 257746bdb399SToby Isaac } 257846bdb399SToby Isaac } 257946bdb399SToby Isaac } 25809371c9d4SSatish Balay } else { /* interpolate from all */ 258146bdb399SToby Isaac if (numFields) { 2582b9a5774bSToby Isaac PetscInt f; 2583b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 258421968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 258546bdb399SToby Isaac for (row = 0; row < numRows; row++) { 258621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 258746bdb399SToby Isaac if (gIndFine >= 0) { 25881dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2589b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2590b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 259146bdb399SToby Isaac } 259246bdb399SToby Isaac } 259346bdb399SToby Isaac } 25949371c9d4SSatish Balay } else { 2595b9a5774bSToby Isaac PetscInt i; 2596b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 259746bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 259846bdb399SToby Isaac if (gIndFine >= 0) { 25991dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2600b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2601b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 260246bdb399SToby Isaac } 260346bdb399SToby Isaac } 260446bdb399SToby Isaac } 260546bdb399SToby Isaac } 26069371c9d4SSatish Balay } else { /* interpolate from all */ 260746bdb399SToby Isaac if (numFields) { 2608b9a5774bSToby Isaac PetscInt f; 2609b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 261021968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 261146bdb399SToby Isaac for (row = 0; row < numRows; row++) { 261221968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 261346bdb399SToby Isaac if (gIndFine >= 0) { 26141dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2615b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2616b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 261746bdb399SToby Isaac } 261846bdb399SToby Isaac } 261946bdb399SToby Isaac } 26209371c9d4SSatish Balay } else { /* every dof get a full row */ 2621b9a5774bSToby Isaac PetscInt i; 2622b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 262346bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 262446bdb399SToby Isaac if (gIndFine >= 0) { 26251dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs"); 2626b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2627b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 262846bdb399SToby Isaac } 262946bdb399SToby Isaac } 263046bdb399SToby Isaac } 263146bdb399SToby Isaac } 263246bdb399SToby Isaac } 26339566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, dnnz, onnz, NULL, NULL)); 26349566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnnz, onnz)); 263521968bf8SToby Isaac 26369566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 26379566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 26389566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 26399566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 26409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 26419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxConDof)); 26429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(leafIndicesSec, &maxColumns)); 26439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConDof * maxColumns, &pointWork)); 26440eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2645e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2646e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2647e44e4e7fSToby Isaac PetscInt matSize; 2648e44e4e7fSToby Isaac PetscInt childId; 2649e44e4e7fSToby Isaac 26509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 26519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 26529371c9d4SSatish Balay if ((gDof - gcDof) <= 0) { continue; } 2653e44e4e7fSToby Isaac childId = childIds[p - pStartF]; 26549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 26559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices)); 26569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff)); 2657e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2658e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2659e44e4e7fSToby Isaac offsets[0] = 0; 2660e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2661e44e4e7fSToby Isaac newOffsets[0] = 0; 2662e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2663e44e4e7fSToby Isaac rowOffsets[0] = 0; 2664e44e4e7fSToby Isaac if (numFields) { 2665e44e4e7fSToby Isaac PetscInt f; 2666e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2667e44e4e7fSToby Isaac PetscInt rowDof; 2668e44e4e7fSToby Isaac 26699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 2670e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2671e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2672e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2673e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2674e44e4e7fSToby Isaac } 26759566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 26769371c9d4SSatish Balay } else { 26779566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 26781c58ffc4SToby Isaac } 26799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize)); 2680e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2681e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2682e44e4e7fSToby Isaac if (numFields) { 2683e44e4e7fSToby Isaac PetscInt f; 2684e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2685e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row; 26869371c9d4SSatish Balay for (row = 0; row < numRows; row++) { PetscCall(MatSetValue(mat, rowIndices[offsets[f] + row], pInd[newOffsets[f] + row], 1., INSERT_VALUES)); } 268721968bf8SToby Isaac } 26889371c9d4SSatish Balay } else { 2689e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 26909371c9d4SSatish Balay for (row = 0; row < numRows; row++) { PetscCall(MatSetValue(mat, rowIndices[row], pInd[row], 1., INSERT_VALUES)); } 2691e44e4e7fSToby Isaac } 26929371c9d4SSatish Balay } else { /* interpolate from all */ 2693e44e4e7fSToby Isaac if (numFields) { 2694e44e4e7fSToby Isaac PetscInt f; 2695e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2696e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2697e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 26989566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], refPointFieldMats[childId - pRefStart][f], INSERT_VALUES)); 2699e44e4e7fSToby Isaac } 27009371c9d4SSatish Balay } else { 27019566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, refPointFieldMats[childId - pRefStart][0], INSERT_VALUES)); 2702e44e4e7fSToby Isaac } 2703e44e4e7fSToby Isaac } 27049371c9d4SSatish Balay } else { /* interpolate from all */ 2705e44e4e7fSToby Isaac PetscInt pMatOff; 2706e44e4e7fSToby Isaac PetscScalar *pMat; 2707e44e4e7fSToby Isaac 27089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafMatricesSec, p, &pMatOff)); 2709e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2710e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2711e44e4e7fSToby Isaac if (numFields) { 2712e44e4e7fSToby Isaac PetscInt f, count; 2713e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2714e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2715e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2716e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2717e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2718e44e4e7fSToby Isaac 27199566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], inMat, INSERT_VALUES)); 2720e44e4e7fSToby Isaac count += numCols * numInRows; 2721e44e4e7fSToby Isaac } 27229371c9d4SSatish Balay } else { 27239566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, pMat, INSERT_VALUES)); 2724e44e4e7fSToby Isaac } 27259371c9d4SSatish Balay } else { /* multiply the incoming matrix by the child interpolation */ 2726e44e4e7fSToby Isaac if (numFields) { 2727e44e4e7fSToby Isaac PetscInt f, count; 2728e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2729e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 2730e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2731e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f]; 2732e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2733e44e4e7fSToby Isaac PetscInt i, j, k; 273408401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][f] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2735e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2736e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2737e44e4e7fSToby Isaac PetscScalar val = 0.; 27389371c9d4SSatish Balay for (k = 0; k < numInRows; k++) { val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; } 2739e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2740e44e4e7fSToby Isaac } 2741e44e4e7fSToby Isaac } 27429566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], pointWork, INSERT_VALUES)); 2743e44e4e7fSToby Isaac count += numCols * numInRows; 2744e44e4e7fSToby Isaac } 27459371c9d4SSatish Balay } else { /* every dof gets a full row */ 2746e44e4e7fSToby Isaac PetscInt numRows = gDof; 2747e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2748e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2749e44e4e7fSToby Isaac PetscInt i, j, k; 275008401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][0] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch"); 2751e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2752e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2753e44e4e7fSToby Isaac PetscScalar val = 0.; 27549371c9d4SSatish Balay for (k = 0; k < numInRows; k++) { val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; } 2755e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2756e44e4e7fSToby Isaac } 2757e44e4e7fSToby Isaac } 27589566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, rowIndices, numCols, pInd, pointWork, INSERT_VALUES)); 2759e44e4e7fSToby Isaac } 2760e44e4e7fSToby Isaac } 2761e44e4e7fSToby Isaac } 2762e44e4e7fSToby Isaac } 27639566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 27649566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 27659566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 2766e44e4e7fSToby Isaac } 27679566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 27689566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 27699566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 27709566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafMatricesSec)); 27719566063dSJacob Faibussowitsch PetscCall(PetscFree2(leafIndices, leafMatrices)); 27729566063dSJacob Faibussowitsch PetscCall(PetscFree2(*(PetscInt ****)&perms, *(PetscScalar ****)&flips)); 27739566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 27749566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 27756ecaa68aSToby Isaac PetscFunctionReturn(0); 27766ecaa68aSToby Isaac } 2777154bca37SToby Isaac 27788d2f55e7SToby Isaac /* 27798d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 27808d2f55e7SToby Isaac * 27818d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 27828d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 27838d2f55e7SToby Isaac * for each fine dof \phi^f_j; 27848d2f55e7SToby Isaac * a_{i,j} = 0; 27858d2f55e7SToby Isaac * for each fine dof \phi^f_k: 27868d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 27878d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 27888d2f55e7SToby Isaac */ 27899371c9d4SSatish Balay PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) { 27908d2f55e7SToby Isaac PetscDS ds; 27918d2f55e7SToby Isaac PetscSection section, cSection; 27928d2f55e7SToby Isaac DMLabel canonical, depth; 27938d2f55e7SToby Isaac Mat cMat, mat; 27948d2f55e7SToby Isaac PetscInt *nnz; 27958d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 27968d2f55e7SToby Isaac PetscInt m, n; 27978d2f55e7SToby Isaac PetscScalar *pointScalar; 27988d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 27998d2f55e7SToby Isaac 28008d2f55e7SToby Isaac PetscFunctionBegin; 28019566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, §ion)); 28029566063dSJacob Faibussowitsch PetscCall(DMGetDimension(refTree, &dim)); 28039566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(dim, &v0, dim, &v0parent, dim, &vtmp, dim * dim, &J, dim * dim, &Jparent, dim * dim, &invJ)); 28049566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim, &pointScalar, dim, &pointRef)); 28059566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 28069566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 28079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numSecFields)); 28089566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical)); 28099566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "depth", &depth)); 28109566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSection, &cMat, NULL)); 28119566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(refTree, &pStart, &pEnd)); 28129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd)); 28139566063dSJacob Faibussowitsch PetscCall(MatGetSize(cMat, &n, &m)); /* the injector has transpose sizes from the constraint matrix */ 28148d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 28159566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz)); 28168d2f55e7SToby 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 */ 28178d2f55e7SToby Isaac const PetscInt *children; 28188d2f55e7SToby Isaac PetscInt numChildren; 28198d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28208d2f55e7SToby Isaac 28218d2f55e7SToby Isaac if (canonical) { 28228d2f55e7SToby Isaac PetscInt pCanonical; 28239566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28248d2f55e7SToby Isaac if (p != pCanonical) continue; 28258d2f55e7SToby Isaac } 28269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28278d2f55e7SToby Isaac if (!numChildren) continue; 28288d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28298d2f55e7SToby Isaac PetscInt child = children[i]; 28308d2f55e7SToby Isaac PetscInt dof; 28318d2f55e7SToby Isaac 28329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 28338d2f55e7SToby Isaac numChildDof += dof; 28348d2f55e7SToby Isaac } 28359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 28368d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 28378d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 28388d2f55e7SToby Isaac PetscInt selfOff; 28398d2f55e7SToby Isaac 28408d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 28418d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28428d2f55e7SToby Isaac PetscInt child = children[i]; 28438d2f55e7SToby Isaac PetscInt dof; 28448d2f55e7SToby Isaac 28459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 28468d2f55e7SToby Isaac numChildDof += dof; 28478d2f55e7SToby Isaac } 28489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 28499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 28509371c9d4SSatish Balay } else { 28519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 28528d2f55e7SToby Isaac } 28539371c9d4SSatish Balay for (i = 0; i < numSelfDof; i++) { nnz[selfOff + i] = numChildDof; } 28548d2f55e7SToby Isaac } 28558d2f55e7SToby Isaac } 28569566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(PETSC_COMM_SELF, m, n, m, n, -1, nnz, -1, NULL, &mat)); 28579566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 28588d2f55e7SToby Isaac /* Setp 2: compute entries */ 28598d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 28608d2f55e7SToby Isaac const PetscInt *children; 28618d2f55e7SToby Isaac PetscInt numChildren; 28628d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 28638d2f55e7SToby Isaac 28648d2f55e7SToby Isaac /* same conditions about when entries occur */ 28658d2f55e7SToby Isaac if (canonical) { 28668d2f55e7SToby Isaac PetscInt pCanonical; 28679566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical)); 28688d2f55e7SToby Isaac if (p != pCanonical) continue; 28698d2f55e7SToby Isaac } 28709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children)); 28718d2f55e7SToby Isaac if (!numChildren) continue; 28728d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28738d2f55e7SToby Isaac PetscInt child = children[i]; 28748d2f55e7SToby Isaac PetscInt dof; 28758d2f55e7SToby Isaac 28769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof)); 28778d2f55e7SToby Isaac numChildDof += dof; 28788d2f55e7SToby Isaac } 28799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof)); 28808d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 28818d2f55e7SToby Isaac 28828d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 288359fc6756SToby Isaac PetscInt pI = -1, cI = -1; 288452a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell; 28858d2f55e7SToby Isaac PetscInt cellShapeOff; 28868d2f55e7SToby Isaac PetscObject disc; 28878d2f55e7SToby Isaac PetscDualSpace dsp; 28888d2f55e7SToby Isaac PetscClassId classId; 28898d2f55e7SToby Isaac PetscScalar *pointMat; 28903b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 28918d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 28928d2f55e7SToby Isaac const PetscInt *depthNumDof; 28938d2f55e7SToby Isaac 28948d2f55e7SToby Isaac if (numSecFields) { 28958d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 28968d2f55e7SToby Isaac PetscInt child = children[i]; 28978d2f55e7SToby Isaac PetscInt dof; 28988d2f55e7SToby Isaac 28999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof)); 29008d2f55e7SToby Isaac numChildDof += dof; 29018d2f55e7SToby Isaac } 29029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof)); 29039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff)); 29049371c9d4SSatish Balay } else { 29059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff)); 29068d2f55e7SToby Isaac } 29078d2f55e7SToby Isaac 29083b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 29098d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 29108d2f55e7SToby Isaac parentCell = p; 29119371c9d4SSatish Balay } else { 29128d2f55e7SToby Isaac PetscInt *star = NULL; 29138d2f55e7SToby Isaac PetscInt numStar; 29148d2f55e7SToby Isaac 29158d2f55e7SToby Isaac parentCell = -1; 29169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29178d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 29188d2f55e7SToby Isaac PetscInt c = star[2 * i]; 29198d2f55e7SToby Isaac 29208d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 29218d2f55e7SToby Isaac parentCell = c; 29228d2f55e7SToby Isaac break; 29238d2f55e7SToby Isaac } 29248d2f55e7SToby Isaac } 29259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star)); 29268d2f55e7SToby Isaac } 2927a5b23f4aSJose E. Roman /* determine the offset of p's shape functions within parentCell's shape functions */ 29289566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 29299566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &classId)); 2930c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 29319566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 29329371c9d4SSatish Balay } else if (classId == PETSCFV_CLASSID) { 29339566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace((PetscFV)disc, &dsp)); 29349371c9d4SSatish Balay } else { 29359b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported discretization object"); 2936c5356c36SToby Isaac } 29379566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dsp, &depthNumDof)); 29389566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dsp, &Nc)); 29398d2f55e7SToby Isaac { 29408d2f55e7SToby Isaac PetscInt *closure = NULL; 29418d2f55e7SToby Isaac PetscInt numClosure; 29428d2f55e7SToby Isaac 29439566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 294459fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) { 29458d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 29468d2f55e7SToby Isaac 29478d2f55e7SToby Isaac pO = closure[2 * i + 1]; 294859fc6756SToby Isaac if (point == p) { 294959fc6756SToby Isaac pI = i; 295059fc6756SToby Isaac break; 295159fc6756SToby Isaac } 29529566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 29538d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 29548d2f55e7SToby Isaac } 29559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure)); 29568d2f55e7SToby Isaac } 29578d2f55e7SToby Isaac 29589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 29599566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 296052a3aeb4SToby Isaac matCols = matRows + numSelfDof; 29619371c9d4SSatish Balay for (i = 0; i < numSelfDof; i++) { matRows[i] = selfOff + i; } 296252a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.; 29633b1c2a6aSToby Isaac { 29643b1c2a6aSToby Isaac PetscInt colOff = 0; 29653b1c2a6aSToby Isaac 29663b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 29673b1c2a6aSToby Isaac PetscInt child = children[i]; 29683b1c2a6aSToby Isaac PetscInt dof, off, j; 29693b1c2a6aSToby Isaac 29703b1c2a6aSToby Isaac if (numSecFields) { 29719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSection, child, f, &dof)); 29729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSection, child, f, &off)); 29739371c9d4SSatish Balay } else { 29749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSection, child, &dof)); 29759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSection, child, &off)); 29763b1c2a6aSToby Isaac } 29773b1c2a6aSToby Isaac 29789371c9d4SSatish Balay for (j = 0; j < dof; j++) { matCols[colOff++] = off + j; } 29793b1c2a6aSToby Isaac } 29803b1c2a6aSToby Isaac } 29818d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 29828d2f55e7SToby Isaac PetscFE fe = (PetscFE)disc; 29838d2f55e7SToby Isaac PetscInt fSize; 298459fc6756SToby Isaac const PetscInt ***perms; 298559fc6756SToby Isaac const PetscScalar ***flips; 298659fc6756SToby Isaac const PetscInt *pperms; 298759fc6756SToby Isaac 29889566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dsp)); 29899566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dsp, &fSize)); 29909566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dsp, &perms, &flips)); 299159fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL; 299252a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */ 29938d2f55e7SToby Isaac PetscQuadrature q; 299452a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k; 29958d2f55e7SToby Isaac const PetscReal *points; 29968d2f55e7SToby Isaac const PetscReal *weights; 29978d2f55e7SToby Isaac PetscInt *closure = NULL; 29988d2f55e7SToby Isaac PetscInt numClosure; 299959fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i; 300059fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell; 3001ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent; 30028d2f55e7SToby Isaac 30039566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dsp, parentCellShapeDof, &q)); 30049566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, &thisNc, &numPoints, &points, &weights)); 300563a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc); 30069566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, numPoints, points, 0, &Tparent)); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 30073b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 30088d2f55e7SToby Isaac PetscInt childCell = -1; 300952a3aeb4SToby Isaac PetscReal *parentValAtPoint; 3010c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 30118d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 30128d2f55e7SToby Isaac const PetscScalar *point; 3013ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild; 30148d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 30158d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 30168d2f55e7SToby Isaac PetscInt d; 30178d2f55e7SToby Isaac 30189371c9d4SSatish Balay for (d = 0; d < dim; d++) { pointScalar[d] = points[dim * j + d]; } 30198d2f55e7SToby Isaac point = pointScalar; 30208d2f55e7SToby Isaac #else 30218d2f55e7SToby Isaac point = pointReal; 30228d2f55e7SToby Isaac #endif 30238d2f55e7SToby Isaac 3024ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc]; 30253b1c2a6aSToby Isaac 30263b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 30278d2f55e7SToby Isaac PetscInt child = children[k]; 30288d2f55e7SToby Isaac PetscInt *star = NULL; 30298d2f55e7SToby Isaac PetscInt numStar, s; 30308d2f55e7SToby Isaac 30319566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30328d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 30338d2f55e7SToby Isaac PetscInt c = star[2 * s]; 30348d2f55e7SToby Isaac 30358d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 30369566063dSJacob Faibussowitsch PetscCall(DMPlexLocatePoint_Internal(refTree, dim, point, c, &childCell)); 30378d2f55e7SToby Isaac if (childCell >= 0) break; 30388d2f55e7SToby Isaac } 30399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star)); 30408d2f55e7SToby Isaac if (childCell >= 0) break; 30418d2f55e7SToby Isaac } 304208401ef6SPierre Jolivet PetscCheck(childCell >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not locate quadrature point"); 30439566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ)); 30449566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent)); 3045c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp); 3046c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef); 30478d2f55e7SToby Isaac 30489566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, 1, pointRef, 0, &Tchild)); 30499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 30503b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3051c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 30528d2f55e7SToby Isaac PetscInt l; 305359fc6756SToby Isaac const PetscInt *cperms; 30548d2f55e7SToby Isaac 30559566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, child, &childDepth)); 30568d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 305759fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) { 30588d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 30598d2f55e7SToby Isaac PetscInt pointDepth; 30608d2f55e7SToby Isaac 30618d2f55e7SToby Isaac childO = closure[2 * l + 1]; 306259fc6756SToby Isaac if (point == child) { 306359fc6756SToby Isaac cI = l; 306459fc6756SToby Isaac break; 306559fc6756SToby Isaac } 30669566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth)); 30678d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 30688d2f55e7SToby Isaac } 30698d2f55e7SToby Isaac if (l == numClosure) { 30708d2f55e7SToby Isaac pointMatOff += childDof; 30718d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 30728d2f55e7SToby Isaac } 307359fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL; 30748d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 307559fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l; 307659fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell; 307752a3aeb4SToby Isaac PetscReal *childValAtPoint; 307852a3aeb4SToby Isaac PetscReal val = 0.; 30798d2f55e7SToby Isaac 3080ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc]; 30819371c9d4SSatish Balay for (m = 0; m < Nc; m++) { val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m]; } 308252a3aeb4SToby Isaac 308352a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val; 30848d2f55e7SToby Isaac } 30858d2f55e7SToby Isaac pointMatOff += childDof; 30868d2f55e7SToby Isaac } 30879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure)); 30889566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tchild)); 30898d2f55e7SToby Isaac } 30909566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tparent)); 30918d2f55e7SToby Isaac } 30929371c9d4SSatish Balay } else { /* just the volume-weighted averages of the children */ 30933b1c2a6aSToby Isaac PetscReal parentVol; 3094bfaa5bdcSToby Isaac PetscInt childCell; 30953b1c2a6aSToby Isaac 30969566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL)); 3097bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) { 309852a3aeb4SToby Isaac PetscInt child = children[i], j; 30993b1c2a6aSToby Isaac PetscReal childVol; 31003b1c2a6aSToby Isaac 31013b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 31029566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL)); 31039371c9d4SSatish Balay for (j = 0; j < Nc; j++) { pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol; } 3104bfaa5bdcSToby Isaac childCell++; 31053b1c2a6aSToby Isaac } 31068d2f55e7SToby Isaac } 31073b1c2a6aSToby Isaac /* Insert pointMat into mat */ 31089566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numSelfDof, matRows, numChildDof, matCols, pointMat, INSERT_VALUES)); 31099566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows)); 31109566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat)); 31118d2f55e7SToby Isaac } 31128d2f55e7SToby Isaac } 31139566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJ)); 31149566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointScalar, pointRef)); 31159566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 31169566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 31178d2f55e7SToby Isaac *inj = mat; 31188d2f55e7SToby Isaac PetscFunctionReturn(0); 31198d2f55e7SToby Isaac } 31208d2f55e7SToby Isaac 31219371c9d4SSatish Balay static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) { 3122f30e825dSToby Isaac PetscDS ds; 3123f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3124f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3125f30e825dSToby Isaac PetscSection refConSec, refSection; 3126f30e825dSToby Isaac 3127f30e825dSToby Isaac PetscFunctionBegin; 31289566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 31299566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 31309566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 31319566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 31329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 31339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats)); 31349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof)); 31359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows)); 31369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &cols)); 3137f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3138f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3139f30e825dSToby Isaac 31409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 31419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 31429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3143f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3144f30e825dSToby Isaac 31459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFields, &refPointFieldMats[p - pRefStart])); 3146f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 314752a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r; 3148f30e825dSToby Isaac 3149f30e825dSToby Isaac if (numFields > 1) { 31509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 31519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff)); 31529371c9d4SSatish Balay } else { 31539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 31549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff)); 3155f30e825dSToby Isaac } 3156f30e825dSToby Isaac 31579371c9d4SSatish Balay for (r = 0; r < cDof; r++) { rows[r] = cOff + r; } 3158f30e825dSToby Isaac numCols = 0; 3159f30e825dSToby Isaac { 3160f30e825dSToby Isaac PetscInt aDof, aOff, j; 3161f30e825dSToby Isaac 3162f30e825dSToby Isaac if (numFields > 1) { 31639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, parent, f, &aDof)); 31649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, parent, f, &aOff)); 31659371c9d4SSatish Balay } else { 31669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &aDof)); 31679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, parent, &aOff)); 3168f30e825dSToby Isaac } 3169f30e825dSToby Isaac 31709371c9d4SSatish Balay for (j = 0; j < aDof; j++) { cols[numCols++] = aOff + j; } 3171f30e825dSToby Isaac } 31729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f])); 3173f30e825dSToby Isaac /* transpose of constraint matrix */ 31749566063dSJacob Faibussowitsch PetscCall(MatGetValues(inj, numCols, cols, cDof, rows, refPointFieldMats[p - pRefStart][f])); 3175f30e825dSToby Isaac } 3176f30e825dSToby Isaac } 3177f30e825dSToby Isaac *childrenMats = refPointFieldMats; 31789566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 31799566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 3180f30e825dSToby Isaac PetscFunctionReturn(0); 3181f30e825dSToby Isaac } 3182f30e825dSToby Isaac 31839371c9d4SSatish Balay static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) { 3184f30e825dSToby Isaac PetscDS ds; 3185f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3186f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3187c6154584SToby Isaac PetscSection refConSec, refSection; 3188f30e825dSToby Isaac 3189f30e825dSToby Isaac PetscFunctionBegin; 3190f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3191f30e825dSToby Isaac *childrenMats = NULL; 31929566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds)); 31939566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection)); 31949566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields)); 31959566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 31969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 3197f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3198f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3199f30e825dSToby Isaac 32009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL)); 32019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof)); 32029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof)); 3203f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3204f30e825dSToby Isaac 3205f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3206f30e825dSToby Isaac PetscInt cDof; 3207f30e825dSToby Isaac 3208f30e825dSToby Isaac if (numFields > 1) { 32099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof)); 32109371c9d4SSatish Balay } else { 32119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof)); 3212f30e825dSToby Isaac } 3213f30e825dSToby Isaac 32149566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 3215f30e825dSToby Isaac } 32169566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 3217f30e825dSToby Isaac } 32189566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 3219f30e825dSToby Isaac PetscFunctionReturn(0); 3220f30e825dSToby Isaac } 3221f30e825dSToby Isaac 32229371c9d4SSatish Balay static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree, Mat *injRef) { 3223ebf164c7SToby Isaac Mat cMatRef; 32246148253fSToby Isaac PetscObject injRefObj; 32258d2f55e7SToby Isaac 3226154bca37SToby Isaac PetscFunctionBegin; 32279566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, NULL, &cMatRef, NULL)); 32289566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", &injRefObj)); 3229ebf164c7SToby Isaac *injRef = (Mat)injRefObj; 3230ebf164c7SToby Isaac if (!*injRef) { 32319566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorReferenceTree(refTree, injRef)); 32329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", (PetscObject)*injRef)); 3233ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 32349566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)*injRef)); 3235ebf164c7SToby Isaac } 3236ebf164c7SToby Isaac PetscFunctionReturn(0); 32376148253fSToby Isaac } 3238f30e825dSToby Isaac 32399371c9d4SSatish Balay 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) { 3240c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3241ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3242ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3243c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3244c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3245c921d74cSToby Isaac const PetscInt *rootDegrees; 3246c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3247ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3248ebf164c7SToby Isaac 3249ebf164c7SToby Isaac PetscFunctionBegin; 32509566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 32519566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 32529566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 32539566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 32549566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec)); 32559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafIndicesSec, pStartF, pEndF)); 32569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 32578d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 32587e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 32597e96bdafSToby Isaac const PetscInt *leaves; 32608d2f55e7SToby Isaac 32619566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 32627e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 32637e96bdafSToby Isaac p = leaves ? leaves[l] : l; 32649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 32659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 32668d2f55e7SToby Isaac if ((dof - cdof) > 0) { 32678d2f55e7SToby Isaac numPointsWithDofs++; 3268f30e825dSToby Isaac 32699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &dof)); 32709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafIndicesSec, p, dof + 1)); 32718d2f55e7SToby Isaac } 32728d2f55e7SToby Isaac } 32739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 32749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafIndicesSec)); 32759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numIndices)); 32769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1), &leafInds)); 32779566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(PetscMalloc1(numIndices, &leafVals)); 32787e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 32797e96bdafSToby Isaac p = leaves ? leaves[l] : l; 32809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 32819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 32828d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3283f30e825dSToby Isaac PetscInt off, gOff; 3284f30e825dSToby Isaac PetscInt *pInd; 3285c921d74cSToby Isaac PetscScalar *pVal = NULL; 3286f30e825dSToby Isaac 32877e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3288f30e825dSToby Isaac 32899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3290f30e825dSToby Isaac 3291c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3292c921d74cSToby Isaac if (gatheredValues) { 3293c921d74cSToby Isaac PetscInt i; 3294c921d74cSToby Isaac 3295c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3296c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3297c921d74cSToby Isaac } 32989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 3299f30e825dSToby Isaac 3300f30e825dSToby Isaac offsets[0] = 0; 3301f30e825dSToby Isaac if (numFields) { 3302f30e825dSToby Isaac PetscInt f; 3303f30e825dSToby Isaac 3304f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3305f30e825dSToby Isaac PetscInt fDof; 33069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &fDof)); 3307f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3308f30e825dSToby Isaac } 33099566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd)); 3310367003a6SStefano Zampini } else { 33119566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd)); 3312f30e825dSToby Isaac } 33139566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(VecGetValues(fineVec, dof, pInd, pVal)); 33148d2f55e7SToby Isaac } 33158d2f55e7SToby Isaac } 33169566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 33179566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 33188d2f55e7SToby Isaac } 3319f30e825dSToby Isaac 33209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 33219566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 33229566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 3323f30e825dSToby Isaac 33246148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 33256148253fSToby Isaac MPI_Datatype threeInt; 33266148253fSToby Isaac PetscMPIInt rank; 33276148253fSToby Isaac PetscInt(*parentNodeAndIdCoarse)[3]; 33286148253fSToby Isaac PetscInt(*parentNodeAndIdFine)[3]; 33296148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 33306148253fSToby Isaac PetscSF pointSF, sfToParents; 33316148253fSToby Isaac const PetscInt *ilocal; 33326148253fSToby Isaac const PetscSFNode *iremote; 33336148253fSToby Isaac PetscSFNode *iremoteToParents; 33346148253fSToby Isaac PetscInt *ilocalToParents; 33356148253fSToby Isaac 33369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)coarse), &rank)); 33379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &threeInt)); 33389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&threeInt)); 33399566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndC - pStartC, &parentNodeAndIdCoarse, pEndF - pStartF, &parentNodeAndIdFine)); 33409566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(coarse, &pointSF)); 33419566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &nleaves, &ilocal, &iremote)); 33426148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 33436148253fSToby Isaac PetscInt parent, childId; 33449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(coarse, p, &parent, &childId)); 33456148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 33466148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 33476148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 33486148253fSToby Isaac if (nleaves > 0) { 33496148253fSToby Isaac PetscInt leaf = -1; 33506148253fSToby Isaac 33516148253fSToby Isaac if (ilocal) { 33529566063dSJacob Faibussowitsch PetscCall(PetscFindInt(parent, nleaves, ilocal, &leaf)); 33539371c9d4SSatish Balay } else { 33546148253fSToby Isaac leaf = p - pStartC; 33556148253fSToby Isaac } 33566148253fSToby Isaac if (leaf >= 0) { 33576148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 33586148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 33596148253fSToby Isaac } 33606148253fSToby Isaac } 33616148253fSToby Isaac } 33626148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 33636148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 33646148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 33656148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 33666148253fSToby Isaac } 33679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 33689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE)); 33696148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3370f30e825dSToby Isaac PetscInt dof; 3371f30e825dSToby Isaac 33729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &dof)); 3373f30e825dSToby Isaac if (dof) { 3374f30e825dSToby Isaac PetscInt off; 3375f30e825dSToby Isaac 33769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off)); 3377c921d74cSToby Isaac if (gatheredIndices) { 3378c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3379c921d74cSToby Isaac } else if (gatheredValues) { 3380c921d74cSToby Isaac leafVals[off] = (PetscScalar)PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]); 3381c921d74cSToby Isaac } 3382f30e825dSToby Isaac } 33839371c9d4SSatish Balay if (parentNodeAndIdFine[p - pStartF][0] >= 0) { nleavesToParents++; } 33846148253fSToby Isaac } 33859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &ilocalToParents)); 33869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &iremoteToParents)); 33876148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 33886148253fSToby Isaac if (parentNodeAndIdFine[p - pStartF][0] >= 0) { 33896148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 33906148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p - pStartF][0]; 33916148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p - pStartF][1]; 33926148253fSToby Isaac nleavesToParents++; 33936148253fSToby Isaac } 33946148253fSToby Isaac } 33959566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)coarse), &sfToParents)); 33969566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfToParents, pEndC - pStartC, nleavesToParents, ilocalToParents, PETSC_OWN_POINTER, iremoteToParents, PETSC_OWN_POINTER)); 33979566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 33986148253fSToby Isaac 33996148253fSToby Isaac coarseToFineEmbedded = sfToParents; 34006148253fSToby Isaac 34019566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentNodeAndIdCoarse, parentNodeAndIdFine)); 34029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&threeInt)); 34036148253fSToby Isaac } 3404f30e825dSToby Isaac 34056148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 34066148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 34076148253fSToby Isaac PetscSF sfDofsOnly; 34086148253fSToby Isaac 34096148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 34109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 34129371c9d4SSatish Balay if ((dof - cdof) > 0) { numPointsWithDofs++; } 34136148253fSToby Isaac } 34149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 34156148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 34169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 34179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 34189371c9d4SSatish Balay if ((dof - cdof) > 0) { pointsWithDofs[offset++] = p - pStartC; } 34196148253fSToby Isaac } 34209566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly)); 34219566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 34229566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 34236148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 34246148253fSToby Isaac } 3425f30e825dSToby Isaac 34266148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 34279566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(coarseToFineEmbedded, &rootDegrees)); 34289566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(coarseToFineEmbedded, &rootDegrees)); 34299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &multiRootSec)); 34309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(multiRootSec, pStartC, pEndC)); 34319371c9d4SSatish Balay for (p = pStartC; p < pEndC; p++) { PetscCall(PetscSectionSetDof(multiRootSec, p, rootDegrees[p - pStartC])); } 34329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(multiRootSec)); 34339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(multiRootSec, &numMulti)); 34349566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec)); 3435f30e825dSToby Isaac { /* distribute the leaf section */ 3436f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3437f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 34388d2f55e7SToby Isaac 34399566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(coarseToFineEmbedded, &multi)); 34409566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(multi, &multiInv)); 34419566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(multiInv, leafIndicesSec, &remoteOffsets, rootIndicesSec)); 34429566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(multiInv, leafIndicesSec, remoteOffsets, rootIndicesSec, &indicesSF)); 34439566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 34449566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&multiInv)); 34459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices)); 3446c921d74cSToby Isaac if (gatheredIndices) { 34479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootInds)); 34489566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 34499566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE)); 3450c921d74cSToby Isaac } 3451c921d74cSToby Isaac if (gatheredValues) { 34529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootVals)); 34539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 34549566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE)); 3455c921d74cSToby Isaac } 34569566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 34578d2f55e7SToby Isaac } 34589566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 34599566063dSJacob Faibussowitsch PetscCall(PetscFree(leafInds)); 34609566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVals)); 34619566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 3462c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3463c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3464c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3465c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 3466ebf164c7SToby Isaac PetscFunctionReturn(0); 3467ebf164c7SToby Isaac } 3468ebf164c7SToby Isaac 34699371c9d4SSatish Balay PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) { 3470ebf164c7SToby Isaac DM refTree; 3471c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3472ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3473ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3474ebf164c7SToby Isaac PetscSection cSecRef; 3475277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd; 3476ebf164c7SToby Isaac Mat injRef; 3477c921d74cSToby Isaac PetscInt numFields, maxDof; 3478ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3479ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3480ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3481ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3482ebf164c7SToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3483ebf164c7SToby Isaac 3484ebf164c7SToby Isaac PetscFunctionBegin; 3485ebf164c7SToby Isaac 3486ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 34879566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 34889566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 34899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 34909566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 3491ebf164c7SToby Isaac 34929566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 34939566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 34949566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 34959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 34969566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 34979566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 34989566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 34999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 3500ebf164c7SToby Isaac { 3501ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 35029566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 3503ebf164c7SToby Isaac } 3504ebf164c7SToby Isaac 35059566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, childIds, NULL, numFields, offsets, &multiRootSec, &rootIndicesSec, &rootIndices, NULL)); 35068d2f55e7SToby Isaac 35079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &parentIndices)); 3508f30e825dSToby Isaac 3509f30e825dSToby Isaac /* count indices */ 35109566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap)); 35119566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 35129566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 35139566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 35149566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 35159566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(rowEnd - rowStart, &nnzD, rowEnd - rowStart, &nnzO)); 3516f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3517f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 35188d2f55e7SToby Isaac 35199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 35209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3521f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 35229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 35238d2f55e7SToby Isaac 35248d2f55e7SToby Isaac rowOffsets[0] = 0; 3525f30e825dSToby Isaac offsetsCopy[0] = 0; 35268d2f55e7SToby Isaac if (numFields) { 35278d2f55e7SToby Isaac PetscInt f; 35288d2f55e7SToby Isaac 3529f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3530f30e825dSToby Isaac PetscInt fDof; 35319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3532f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 35338d2f55e7SToby Isaac } 35349566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3535367003a6SStefano Zampini } else { 35369566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3537f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 35388d2f55e7SToby Isaac } 3539f30e825dSToby Isaac 35409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 35419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3542f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3543f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3544f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3545f30e825dSToby Isaac const PetscInt *childIndices; 3546f30e825dSToby Isaac 35479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 35489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3549f30e825dSToby Isaac childId = rootIndices[offset++]; 3550f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3551f30e825dSToby Isaac numIndices--; 3552f30e825dSToby Isaac 3553f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3554f30e825dSToby Isaac PetscInt i; 3555f30e825dSToby Isaac 3556f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3557f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3558f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3559f30e825dSToby Isaac if (rowIndex < 0) continue; 356008401ef6SPierre Jolivet PetscCheck(colIndex >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unconstrained fine and constrained coarse"); 3561a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3562f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 35639371c9d4SSatish Balay } else { 3564f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3565f30e825dSToby Isaac } 3566f30e825dSToby Isaac } 35679371c9d4SSatish Balay } else { 3568f30e825dSToby Isaac PetscInt parentId, f, lim; 3569f30e825dSToby Isaac 35709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3571f30e825dSToby Isaac 3572f30e825dSToby Isaac lim = PetscMax(1, numFields); 3573f30e825dSToby Isaac offsets[0] = 0; 35748d2f55e7SToby Isaac if (numFields) { 35758d2f55e7SToby Isaac PetscInt f; 3576f30e825dSToby Isaac 35778d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3578f30e825dSToby Isaac PetscInt fDof; 35799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3580f30e825dSToby Isaac 3581f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 35828d2f55e7SToby Isaac } 35839371c9d4SSatish Balay } else { 3584f30e825dSToby Isaac PetscInt cDof; 3585f30e825dSToby Isaac 35869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3587f30e825dSToby Isaac offsets[1] = cDof; 3588f30e825dSToby Isaac } 3589f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3590f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3591f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3592f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3593f30e825dSToby Isaac 3594f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3595f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3596f30e825dSToby Isaac 3597f30e825dSToby Isaac if (colIndex < 0) continue; 3598f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3599f30e825dSToby Isaac numD++; 36009371c9d4SSatish Balay } else { 3601f30e825dSToby Isaac numO++; 3602f30e825dSToby Isaac } 3603f30e825dSToby Isaac } 3604f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3605f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3606f30e825dSToby Isaac 3607f30e825dSToby Isaac if (rowIndex < 0) continue; 3608f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3609f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 36108d2f55e7SToby Isaac } 36118d2f55e7SToby Isaac } 36128d2f55e7SToby Isaac } 3613f30e825dSToby Isaac } 3614f30e825dSToby Isaac } 3615f30e825dSToby Isaac /* preallocate */ 36169566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, nnzD, nnzO, NULL, NULL)); 36179566063dSJacob Faibussowitsch PetscCall(PetscFree2(nnzD, nnzO)); 3618f30e825dSToby Isaac /* insert values */ 36199566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 3620f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3621f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3622f30e825dSToby Isaac 36239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 36249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 3625f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 36269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 3627f30e825dSToby Isaac 3628f30e825dSToby Isaac rowOffsets[0] = 0; 3629f30e825dSToby Isaac offsetsCopy[0] = 0; 36308d2f55e7SToby Isaac if (numFields) { 36318d2f55e7SToby Isaac PetscInt f; 3632f30e825dSToby Isaac 36338d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3634f30e825dSToby Isaac PetscInt fDof; 36359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 3636f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3637f30e825dSToby Isaac } 36389566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 3639367003a6SStefano Zampini } else { 36409566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 3641f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3642f30e825dSToby Isaac } 3643f30e825dSToby Isaac 36449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 36459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 3646f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3647f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3648f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3649f30e825dSToby Isaac const PetscInt *childIndices; 3650f30e825dSToby Isaac 36519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 36529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 3653f30e825dSToby Isaac childId = rootIndices[offset++]; 3654f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3655f30e825dSToby Isaac numIndices--; 3656f30e825dSToby Isaac 3657f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3658f30e825dSToby Isaac PetscInt i; 3659f30e825dSToby Isaac 36609371c9d4SSatish Balay for (i = 0; i < numIndices; i++) { PetscCall(MatSetValue(mat, parentIndices[i], childIndices[i], 1., INSERT_VALUES)); } 36619371c9d4SSatish Balay } else { 3662f30e825dSToby Isaac PetscInt parentId, f, lim; 36638d2f55e7SToby Isaac 36649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 3665f30e825dSToby Isaac 3666f30e825dSToby Isaac lim = PetscMax(1, numFields); 3667f30e825dSToby Isaac offsets[0] = 0; 36688d2f55e7SToby Isaac if (numFields) { 3669f30e825dSToby Isaac PetscInt f; 36708d2f55e7SToby Isaac 3671f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3672f30e825dSToby Isaac PetscInt fDof; 36739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 3674f30e825dSToby Isaac 3675f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 36768d2f55e7SToby Isaac } 36779371c9d4SSatish Balay } else { 3678f30e825dSToby Isaac PetscInt cDof; 3679f30e825dSToby Isaac 36809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 3681f30e825dSToby Isaac offsets[1] = cDof; 36828d2f55e7SToby Isaac } 3683f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3684f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3685f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3686f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3687f30e825dSToby Isaac 36889566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, rowOffsets[f + 1] - rowOffsets[f], rowIndices, offsets[f + 1] - offsets[f], colIndices, childMat, INSERT_VALUES)); 36898d2f55e7SToby Isaac } 36908d2f55e7SToby Isaac } 36918d2f55e7SToby Isaac } 36928d2f55e7SToby Isaac } 36939566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 36949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 36959566063dSJacob Faibussowitsch PetscCall(PetscFree(parentIndices)); 36969566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 36979566063dSJacob Faibussowitsch PetscCall(PetscFree(rootIndices)); 36989566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 3699f30e825dSToby Isaac 37009566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 37019566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 3702154bca37SToby Isaac PetscFunctionReturn(0); 3703154bca37SToby Isaac } 370438fc2455SToby Isaac 37059371c9d4SSatish Balay static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) { 370662095d54SToby Isaac PetscSF coarseToFineEmbedded; 370762095d54SToby Isaac PetscSection globalCoarse, globalFine; 370862095d54SToby Isaac PetscSection localCoarse, localFine; 370962095d54SToby Isaac PetscSection aSec, cSec; 371062095d54SToby Isaac PetscSection rootValuesSec; 371162095d54SToby Isaac PetscSection leafValuesSec; 371262095d54SToby Isaac PetscScalar *rootValues, *leafValues; 371362095d54SToby Isaac IS aIS; 371462095d54SToby Isaac const PetscInt *anchors; 371562095d54SToby Isaac Mat cMat; 371662095d54SToby Isaac PetscInt numFields; 3717412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd; 371862095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 371962095d54SToby Isaac PetscInt *maxChildIds; 372062095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 37210eb7e1eaSToby Isaac PetscFV fv = NULL; 37220eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 37230eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 37240eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 37250eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 372662095d54SToby Isaac 3727ebf164c7SToby Isaac PetscFunctionBegin; 37289566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 37299566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 37309566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(coarse, 0, &cellStart, &cellEnd)); 37319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 37329566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 37339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(coarse, &dim)); 373462095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 3735e4a60869SToby Isaac PetscInt nleaves, l; 3736e4a60869SToby Isaac const PetscInt *leaves; 373762095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 373862095d54SToby Isaac 37399566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL)); 3740e4a60869SToby Isaac 3741e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 3742e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3743e4a60869SToby Isaac 37449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 37469371c9d4SSatish Balay if ((dof - cdof) > 0) { numPointsWithDofs++; } 374762095d54SToby Isaac } 37489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs)); 37494833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 3750e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3751e4a60869SToby Isaac 37529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof)); 37539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof)); 37549371c9d4SSatish Balay if ((dof - cdof) > 0) { pointsWithDofs[offset++] = l; } 375562095d54SToby Isaac } 37569566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 37579566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 375862095d54SToby Isaac } 375962095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 37609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds)); 37619371c9d4SSatish Balay for (p = pStartC; p < pEndC; p++) { maxChildIds[p - pStartC] = -2; } 37629566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 37639566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX)); 376462095d54SToby Isaac 37659566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 37669566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 376762095d54SToby Isaac 37689566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS)); 37699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 37709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 377162095d54SToby Isaac 37729566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL)); 37739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 377462095d54SToby Isaac 377562095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 37769566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootValuesSec)); 37779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootValuesSec, pStartC, pEndC)); 37789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields)); 377962095d54SToby Isaac { 378062095d54SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 37819566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &newOffsets, maxFields, &newOffsetsCopy, maxFields, &rowOffsets, maxFields, &numD, maxFields, &numO)); 378262095d54SToby Isaac } 37830eb7e1eaSToby Isaac if (grad) { 37840eb7e1eaSToby Isaac PetscInt i; 37850eb7e1eaSToby Isaac 37869566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeom, &cellDM)); 37879566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeom, &cellGeomArray)); 37889566063dSJacob Faibussowitsch PetscCall(VecGetDM(grad, &gradDM)); 37899566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(grad, &gradArray)); 37900eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1, numFields); i++) { 37910eb7e1eaSToby Isaac PetscObject obj; 37920eb7e1eaSToby Isaac PetscClassId id; 37930eb7e1eaSToby Isaac 37949566063dSJacob Faibussowitsch PetscCall(DMGetField(coarse, i, NULL, &obj)); 37959566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 37960eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 37970eb7e1eaSToby Isaac fv = (PetscFV)obj; 37989566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numFVcomps)); 37990eb7e1eaSToby Isaac fvField = i; 38000eb7e1eaSToby Isaac break; 38010eb7e1eaSToby Isaac } 38020eb7e1eaSToby Isaac } 38030eb7e1eaSToby Isaac } 380462095d54SToby Isaac 380562095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 380662095d54SToby Isaac PetscInt dof; 380762095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 380862095d54SToby Isaac PetscInt numValues = 0; 380962095d54SToby Isaac 38109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 38119371c9d4SSatish Balay if (dof < 0) { dof = -(dof + 1); } 381262095d54SToby Isaac offsets[0] = 0; 381362095d54SToby Isaac newOffsets[0] = 0; 381462095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 381562095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 381662095d54SToby Isaac 38179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 381862095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 381962095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 382062095d54SToby Isaac 38219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof)); 382262095d54SToby Isaac numValues += clDof; 382362095d54SToby Isaac } 38249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 38259371c9d4SSatish Balay } else if (maxChildId == -1) { 38269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &numValues)); 382762095d54SToby Isaac } 382862095d54SToby Isaac /* we will pack the column indices with the field offsets */ 382978b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 38300eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 38310eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 38320eb7e1eaSToby Isaac } 38339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootValuesSec, p, numValues)); 383462095d54SToby Isaac } 38359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootValuesSec)); 383662095d54SToby Isaac { 383762095d54SToby Isaac PetscInt numRootValues; 383862095d54SToby Isaac const PetscScalar *coarseArray; 383962095d54SToby Isaac 38409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootValuesSec, &numRootValues)); 38419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootValues, &rootValues)); 38429566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecCoarseLocal, &coarseArray)); 384362095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 384462095d54SToby Isaac PetscInt numValues; 384562095d54SToby Isaac PetscInt pValOff; 384662095d54SToby Isaac PetscScalar *pVal; 384762095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 384862095d54SToby Isaac 38499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootValuesSec, p, &numValues)); 38509371c9d4SSatish Balay if (!numValues) { continue; } 38519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootValuesSec, p, &pValOff)); 385262095d54SToby Isaac pVal = &(rootValues[pValOff]); 385362095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 38540eb7e1eaSToby Isaac PetscInt closureSize = numValues; 38559566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(coarse, NULL, vecCoarseLocal, p, &closureSize, &pVal)); 38560eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 3857193eb951SToby Isaac PetscFVCellGeom *cg; 38586dd00756SToby Isaac PetscScalar *gradVals = NULL; 38590eb7e1eaSToby Isaac PetscInt i; 38600eb7e1eaSToby Isaac 38610eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 38620eb7e1eaSToby Isaac 38639566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(cellDM, p, cellGeomArray, (void *)&cg)); 38640eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 38650eb7e1eaSToby Isaac pVal += dim; 38669566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRead(gradDM, p, gradArray, (void *)&gradVals)); 38670eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 38680eb7e1eaSToby Isaac } 38699371c9d4SSatish Balay } else if (maxChildId == -1) { 387078b7adb5SToby Isaac PetscInt lDof, lOff, i; 387178b7adb5SToby Isaac 38729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &lDof)); 38739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, p, &lOff)); 387478b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 387578b7adb5SToby Isaac } 387678b7adb5SToby Isaac } 38779566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecCoarseLocal, &coarseArray)); 38789566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 387962095d54SToby Isaac } 388062095d54SToby Isaac { 388162095d54SToby Isaac PetscSF valuesSF; 388262095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 388362095d54SToby Isaac 38849566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafValuesSec)); 38859566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootValuesSec, &remoteOffsetsValues, leafValuesSec)); 38869566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootValuesSec, remoteOffsetsValues, leafValuesSec, &valuesSF)); 38879566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 38889566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsValues)); 38899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafValuesSec, &numLeafValues)); 38909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeafValues, &leafValues)); 38919566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 38929566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE)); 38939566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&valuesSF)); 38949566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 38959566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootValuesSec)); 389662095d54SToby Isaac } 38979566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 389862095d54SToby Isaac { 389962095d54SToby Isaac PetscInt maxDof; 390062095d54SToby Isaac PetscInt *rowIndices; 390162095d54SToby Isaac DM refTree; 390262095d54SToby Isaac PetscInt **refPointFieldN; 390362095d54SToby Isaac PetscScalar ***refPointFieldMats; 390462095d54SToby Isaac PetscSection refConSec, refAnSec; 39050eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, leafStart, leafEnd; 390662095d54SToby Isaac PetscScalar *pointWork; 390762095d54SToby Isaac 39089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof)); 39099566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 39109566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 39119566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree)); 39129566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(fine, refTree)); 39139566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 39149566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL)); 39159566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL)); 39169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd)); 39179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafValuesSec, &leafStart, &leafEnd)); 39189566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(fine, 0, &cellStart, &cellEnd)); 39190eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 392062095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 392162095d54SToby Isaac PetscInt numValues, pValOff; 392262095d54SToby Isaac PetscInt childId; 392362095d54SToby Isaac const PetscScalar *pVal; 39240eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 392562095d54SToby Isaac 39269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof)); 39279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &lDof)); 39289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof)); 39299371c9d4SSatish Balay if ((gDof - gcDof) <= 0) { continue; } 39309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff)); 39319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafValuesSec, p, &numValues)); 393262095d54SToby Isaac if (!numValues) continue; 39339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafValuesSec, p, &pValOff)); 393462095d54SToby Isaac pVal = &leafValues[pValOff]; 393562095d54SToby Isaac offsets[0] = 0; 393662095d54SToby Isaac offsetsCopy[0] = 0; 393762095d54SToby Isaac newOffsets[0] = 0; 393862095d54SToby Isaac newOffsetsCopy[0] = 0; 39394833aeb0SToby Isaac childId = cids[p - pStartF]; 394062095d54SToby Isaac if (numFields) { 394162095d54SToby Isaac PetscInt f; 394262095d54SToby Isaac for (f = 0; f < numFields; f++) { 394362095d54SToby Isaac PetscInt rowDof; 394462095d54SToby Isaac 39459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof)); 394662095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 394762095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 394862095d54SToby Isaac /* TODO: closure indices */ 39499f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 395062095d54SToby Isaac } 39519566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices)); 39529371c9d4SSatish Balay } else { 39534833aeb0SToby Isaac offsets[0] = 0; 39544833aeb0SToby Isaac offsets[1] = lDof; 39554833aeb0SToby Isaac newOffsets[0] = 0; 39564833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 39579566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices)); 395862095d54SToby Isaac } 395962095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 39609566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numValues, rowIndices, pVal, INSERT_VALUES)); 396162095d54SToby Isaac } else { 396262095d54SToby Isaac PetscInt f; 396362095d54SToby Isaac 396478b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 396578b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 396678b7adb5SToby Isaac fvGradData = &pVal[numValues]; 396778b7adb5SToby Isaac } 396862095d54SToby Isaac for (f = 0; f < PetscMax(1, numFields); f++) { 396962095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 397062095d54SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f]; 397162095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 397262095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 397362095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 397462095d54SToby Isaac PetscInt i, j; 397562095d54SToby Isaac 3976708c7f19SToby Isaac #if 0 397763a3b9bcSJacob 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)); 3978708c7f19SToby Isaac #endif 397962095d54SToby Isaac for (i = 0; i < numRows; i++) { 398062095d54SToby Isaac PetscScalar val = 0.; 39819371c9d4SSatish Balay for (j = 0; j < numCols; j++) { val += childMat[i * numCols + j] * cVal[j]; } 398262095d54SToby Isaac rVal[i] = val; 398362095d54SToby Isaac } 39840eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 39850eb7e1eaSToby Isaac PetscReal centroid[3]; 39860eb7e1eaSToby Isaac PetscScalar diff[3]; 39870eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 39880eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 39890eb7e1eaSToby Isaac 39909566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(fine, p, NULL, centroid, NULL)); 39919371c9d4SSatish Balay for (i = 0; i < dim; i++) { diff[i] = centroid[i] - parentCentroid[i]; } 39920eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 39930eb7e1eaSToby Isaac PetscScalar val = 0.; 39940eb7e1eaSToby Isaac 39959371c9d4SSatish Balay for (j = 0; j < dim; j++) { val += gradient[dim * i + j] * diff[j]; } 39960eb7e1eaSToby Isaac rVal[i] += val; 39970eb7e1eaSToby Isaac } 39980eb7e1eaSToby Isaac } 39999566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numRows, &rowIndices[offsets[f]], rVal, INSERT_VALUES)); 400062095d54SToby Isaac } 400162095d54SToby Isaac } 400262095d54SToby Isaac } 40039566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN)); 40049566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork)); 40059566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices)); 400662095d54SToby Isaac } 40079566063dSJacob Faibussowitsch PetscCall(PetscFree(leafValues)); 40089566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafValuesSec)); 40099566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO)); 40109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 4011ebf164c7SToby Isaac PetscFunctionReturn(0); 4012ebf164c7SToby Isaac } 4013ebf164c7SToby Isaac 40149371c9d4SSatish Balay static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) { 4015c921d74cSToby Isaac DM refTree; 4016c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4017c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4018c921d74cSToby Isaac PetscSection localCoarse, localFine; 4019c921d74cSToby Isaac PetscSection cSecRef; 4020c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4021d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4022c921d74cSToby Isaac Mat injRef; 4023c921d74cSToby Isaac PetscInt numFields, maxDof; 4024c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4025c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4026c921d74cSToby Isaac PetscLayout rowMap, colMap; 4027c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4028c921d74cSToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4029c921d74cSToby Isaac 4030ebf164c7SToby Isaac PetscFunctionBegin; 4031c921d74cSToby Isaac 4032c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 40339566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40349566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecCoarse, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 40359566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree)); 40369566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(coarse, refTree)); 40379566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL)); 40389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd)); 40399566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef)); 4040c921d74cSToby Isaac 40419566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF)); 40429566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine)); 40439566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine)); 40449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields)); 40459566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC)); 40469566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse)); 40479566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse)); 40489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof)); 4049c921d74cSToby Isaac { 4050c921d74cSToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1; 40519566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets)); 4052c921d74cSToby Isaac } 4053c921d74cSToby Isaac 40549566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, cids, vecFine, numFields, offsets, &multiRootSec, &rootIndicesSec, NULL, &rootValues)); 4055c921d74cSToby Isaac 40569566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxDof, &parentIndices, maxDof, &parentValues)); 4057c921d74cSToby Isaac 4058c921d74cSToby Isaac /* count indices */ 40599566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecFine, &colMap)); 40609566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecCoarse, &rowMap)); 40619566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 40629566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 40639566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd)); 40649566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd)); 4065c921d74cSToby Isaac /* insert values */ 40669566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 4067c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4068c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 406978b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4070c921d74cSToby Isaac 40719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof)); 40729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof)); 4073c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 40749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &dof)); 40759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff)); 4076c921d74cSToby Isaac 4077c921d74cSToby Isaac rowOffsets[0] = 0; 4078c921d74cSToby Isaac offsetsCopy[0] = 0; 4079c921d74cSToby Isaac if (numFields) { 4080c921d74cSToby Isaac PetscInt f; 4081c921d74cSToby Isaac 4082c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4083c921d74cSToby Isaac PetscInt fDof; 40849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof)); 4085c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4086c921d74cSToby Isaac } 40879566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices)); 4088367003a6SStefano Zampini } else { 40899566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices)); 4090c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4091c921d74cSToby Isaac } 4092c921d74cSToby Isaac 40939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves)); 40949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart)); 4095c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 40962f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4097c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4098c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4099c921d74cSToby Isaac const PetscScalar *childValues; 4100c921d74cSToby Isaac 41019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices)); 41029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset)); 4103c921d74cSToby Isaac childId = (PetscInt)PetscRealPart(rootValues[offset++]); 4104c921d74cSToby Isaac childValues = &rootValues[offset]; 4105c921d74cSToby Isaac numIndices--; 4106c921d74cSToby Isaac 4107c921d74cSToby Isaac if (childId == -2) { /* skip */ 4108c921d74cSToby Isaac continue; 4109c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 41102f65e181SToby Isaac PetscInt m; 41112f65e181SToby Isaac 411278b7adb5SToby Isaac contribute = PETSC_TRUE; 41132f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4114beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4115d3bc4906SToby Isaac PetscInt parentId, f, lim; 4116d3bc4906SToby Isaac 411778b7adb5SToby Isaac contribute = PETSC_TRUE; 41189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL)); 4119d3bc4906SToby Isaac 4120d3bc4906SToby Isaac lim = PetscMax(1, numFields); 4121d3bc4906SToby Isaac offsets[0] = 0; 4122d3bc4906SToby Isaac if (numFields) { 4123d3bc4906SToby Isaac PetscInt f; 4124d3bc4906SToby Isaac 4125d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4126d3bc4906SToby Isaac PetscInt fDof; 41279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof)); 4128d3bc4906SToby Isaac 4129d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4130d3bc4906SToby Isaac } 41319371c9d4SSatish Balay } else { 4132d3bc4906SToby Isaac PetscInt cDof; 4133d3bc4906SToby Isaac 41349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof)); 4135d3bc4906SToby Isaac offsets[1] = cDof; 4136d3bc4906SToby Isaac } 4137d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4138d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4139d3bc4906SToby Isaac PetscInt n = offsets[f + 1] - offsets[f]; 4140e328ff09SToby Isaac PetscInt m = rowOffsets[f + 1] - rowOffsets[f]; 4141d3bc4906SToby Isaac PetscInt i, j; 4142d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4143d3bc4906SToby Isaac 4144e328ff09SToby Isaac for (i = 0; i < m; i++) { 4145d3bc4906SToby Isaac PetscScalar val = 0.; 41469371c9d4SSatish Balay for (j = 0; j < n; j++) { val += childMat[n * i + j] * colValues[j]; } 4147e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val; 4148d3bc4906SToby Isaac } 4149d3bc4906SToby Isaac } 4150c921d74cSToby Isaac } 4151c921d74cSToby Isaac } 41529566063dSJacob Faibussowitsch if (contribute) PetscCall(VecSetValues(vecCoarse, dof, parentIndices, parentValues, INSERT_VALUES)); 4153c921d74cSToby Isaac } 41549566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 41559566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 41569566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentIndices, parentValues)); 41579566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats)); 41589566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 41599566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets)); 4160ebf164c7SToby Isaac PetscFunctionReturn(0); 4161ebf164c7SToby Isaac } 4162ebf164c7SToby Isaac 4163ff1f73f7SToby Isaac /*@ 4164ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4165ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4166ff1f73f7SToby Isaac coarsening and refinement at the same time. 4167ff1f73f7SToby Isaac 4168ff1f73f7SToby Isaac collective 4169ff1f73f7SToby Isaac 4170ff1f73f7SToby Isaac Input Parameters: 4171ff1f73f7SToby Isaac + dmIn - The DMPlex mesh for the input vector 4172ff1f73f7SToby Isaac . vecIn - The input vector 4173ff1f73f7SToby Isaac . sfRefine - A star forest indicating points in the mesh dmIn (roots in the star forest) that are parents to points in 4174ff1f73f7SToby Isaac the mesh dmOut (leaves in the star forest), i.e. where dmOut is more refined than dmIn 4175ff1f73f7SToby Isaac . sfCoarsen - A star forest indicating points in the mesh dmOut (roots in the star forest) that are parents to points in 4176ff1f73f7SToby Isaac the mesh dmIn (leaves in the star forest), i.e. where dmOut is more coarsened than dmIn 4177ff1f73f7SToby Isaac . cidsRefine - The childIds of the points in dmOut. These childIds relate back to the reference tree: childid[j] = k implies 4178ff1f73f7SToby Isaac that mesh point j of dmOut was refined from a point in dmIn just as the mesh point k in the reference 4179ff1f73f7SToby Isaac tree was refined from its parent. childid[j] = -1 indicates that the point j in dmOut is exactly 4180ff1f73f7SToby Isaac equivalent to its root in dmIn, so no interpolation is necessary. childid[j] = -2 indicates that this 4181ff1f73f7SToby Isaac point j in dmOut is not a leaf of sfRefine. 4182ff1f73f7SToby Isaac . cidsCoarsen - The childIds of the points in dmIn. These childIds relate back to the reference tree: childid[j] = k implies 4183ff1f73f7SToby Isaac that mesh point j of dmIn coarsens to a point in dmOut just as the mesh point k in the reference 4184ff1f73f7SToby Isaac tree coarsens to its parent. childid[j] = -2 indicates that point j in dmOut is not a leaf in sfCoarsen. 4185ff1f73f7SToby Isaac . useBCs - PETSC_TRUE indicates that boundary values should be inserted into vecIn before transfer. 4186ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4187ff1f73f7SToby Isaac 4188ff1f73f7SToby Isaac Output Parameters: 41898966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred 4190ff1f73f7SToby Isaac projection of vecIn from dmIn to dmOut. Note that any field discretized with a PetscFV finite volume 4191ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4192ff1f73f7SToby Isaac coarse points to fine points. 4193ff1f73f7SToby Isaac 4194ff1f73f7SToby Isaac Level: developer 4195ff1f73f7SToby Isaac 4196db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()`, `PetscFVGetComputeGradients()` 4197ff1f73f7SToby Isaac @*/ 41989371c9d4SSatish Balay PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) { 419938fc2455SToby Isaac PetscFunctionBegin; 42009566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0)); 4201ff1f73f7SToby Isaac if (sfRefine) { 4202fbfa57b9SToby Isaac Vec vecInLocal; 42030eb7e1eaSToby Isaac DM dmGrad = NULL; 42040eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4205fbfa57b9SToby Isaac 42069566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecInLocal)); 42079566063dSJacob Faibussowitsch PetscCall(VecSet(vecInLocal, 0.0)); 42080eb7e1eaSToby Isaac { 42090eb7e1eaSToby Isaac PetscInt numFields, i; 42100eb7e1eaSToby Isaac 42119566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dmIn, &numFields)); 42120eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 42130eb7e1eaSToby Isaac PetscObject obj; 42140eb7e1eaSToby Isaac PetscClassId classid; 42150eb7e1eaSToby Isaac 42169566063dSJacob Faibussowitsch PetscCall(DMGetField(dmIn, i, NULL, &obj)); 42179566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &classid)); 42180eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 42199566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dmIn, (PetscFV)obj, &cellGeom, &faceGeom, &dmGrad)); 42200eb7e1eaSToby Isaac break; 42210eb7e1eaSToby Isaac } 42220eb7e1eaSToby Isaac } 42230eb7e1eaSToby Isaac } 42241baa6e33SBarry Smith if (useBCs) PetscCall(DMPlexInsertBoundaryValues(dmIn, PETSC_TRUE, vecInLocal, time, faceGeom, cellGeom, NULL)); 42259566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42269566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmIn, vecIn, INSERT_VALUES, vecInLocal)); 42270eb7e1eaSToby Isaac if (dmGrad) { 42289566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmGrad, &grad)); 42299566063dSJacob Faibussowitsch PetscCall(DMPlexReconstructGradientsFVM(dmIn, vecInLocal, grad)); 42300eb7e1eaSToby Isaac } 42319566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree_Interpolate(dmIn, vecInLocal, dmOut, vecOut, sfRefine, cidsRefine, grad, cellGeom)); 42329566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecInLocal)); 42339371c9d4SSatish Balay if (dmGrad) { PetscCall(DMRestoreGlobalVector(dmGrad, &grad)); } 4234ebf164c7SToby Isaac } 42351baa6e33SBarry Smith if (sfCoarsen) PetscCall(DMPlexTransferVecTree_Inject(dmIn, vecIn, dmOut, vecOut, sfCoarsen, cidsCoarsen)); 42369566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(vecOut)); 42379566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(vecOut)); 423838fc2455SToby Isaac PetscFunctionReturn(0); 423938fc2455SToby Isaac } 4240