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 @*/ 22d6a7ad0dSToby Isaac PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 23d6a7ad0dSToby Isaac { 24d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 25d6a7ad0dSToby Isaac 26d6a7ad0dSToby Isaac PetscFunctionBegin; 27d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2847a1df27SMatthew G. Knepley if (ref) {PetscValidHeaderSpecific(ref, DM_CLASSID, 2);} 299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ref)); 309566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 31d6a7ad0dSToby Isaac mesh->referenceTree = ref; 32d6a7ad0dSToby Isaac PetscFunctionReturn(0); 33d6a7ad0dSToby Isaac } 34d6a7ad0dSToby Isaac 35d6a7ad0dSToby Isaac /*@ 36d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 37d6a7ad0dSToby Isaac 38d6a7ad0dSToby Isaac Not collective 39d6a7ad0dSToby Isaac 40d6a7ad0dSToby Isaac Input Parameters: 41d6a7ad0dSToby Isaac . dm - The DMPlex object 42d6a7ad0dSToby Isaac 437a7aea1fSJed Brown Output Parameters: 44d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 45d6a7ad0dSToby Isaac 460b7167a0SToby Isaac Level: intermediate 47d6a7ad0dSToby Isaac 48db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()` 49d6a7ad0dSToby Isaac @*/ 50d6a7ad0dSToby Isaac PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 51d6a7ad0dSToby Isaac { 52d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 53d6a7ad0dSToby Isaac 54d6a7ad0dSToby Isaac PetscFunctionBegin; 55d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56d6a7ad0dSToby Isaac PetscValidPointer(ref,2); 57d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 58d6a7ad0dSToby Isaac PetscFunctionReturn(0); 59d6a7ad0dSToby Isaac } 60d6a7ad0dSToby Isaac 61dcbd3bf7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 62dcbd3bf7SToby Isaac { 63dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 64dcbd3bf7SToby Isaac 65dcbd3bf7SToby Isaac PetscFunctionBegin; 66dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 67dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 68dcbd3bf7SToby Isaac if (childB) *childB = childA; 69dcbd3bf7SToby Isaac PetscFunctionReturn(0); 70dcbd3bf7SToby Isaac } 71dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd)); 73dcbd3bf7SToby Isaac if (parent >= dStart && parent <= dEnd) { 74dcbd3bf7SToby Isaac break; 75dcbd3bf7SToby Isaac } 76dcbd3bf7SToby Isaac } 7763a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %" PetscInt_FMT "-cells",dim); 7828b400f6SJacob Faibussowitsch PetscCheck(dim,PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 79dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 80dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 81dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 82dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 83dcbd3bf7SToby Isaac 849566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm,childA,&size)); 859566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm,childA,&supp)); 86dcbd3bf7SToby Isaac 87dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 88dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 89dcbd3bf7SToby Isaac PetscInt sParent; 90dcbd3bf7SToby Isaac 91dcbd3bf7SToby Isaac sA = supp[i]; 92dcbd3bf7SToby Isaac if (sA == parent) continue; 939566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,sA,&sParent,NULL)); 94dcbd3bf7SToby Isaac if (sParent == parent) { 95dcbd3bf7SToby Isaac break; 96dcbd3bf7SToby Isaac } 97dcbd3bf7SToby Isaac } 9808401ef6SPierre Jolivet PetscCheck(i != size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 99dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 100dcbd3bf7SToby Isaac * parentOrientB */ 1019566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry_Default(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB)); 1029566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,sA,&sConeSize)); 1039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,sA,&coneA)); 1049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,sB,&coneB)); 1059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm,sA,&oA)); 1069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm,sB,&oB)); 107dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 108dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 109dcbd3bf7SToby Isaac if (coneA[i] == childA) { 110dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 111dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 112dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 113dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 114dcbd3bf7SToby Isaac if (childOrientB) { 115b5a892a1SMatthew G. Knepley DMPolytopeType ct; 116dcbd3bf7SToby Isaac PetscInt oBtrue; 117dcbd3bf7SToby Isaac 1189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,childA,&coneSize)); 119dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 1201dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 121b5a892a1SMatthew G. Knepley ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 122dcbd3bf7SToby Isaac /* we may have to flip an edge */ 123b5a892a1SMatthew G. Knepley oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientation(ct, -1, oB[j]); 124b5a892a1SMatthew G. Knepley oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 125b5a892a1SMatthew G. Knepley ABswap = DihedralSwap(coneSize,DMPolytopeConvertNewOrientation_Internal(ct, oA[i]),oBtrue); 126dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 127dcbd3bf7SToby Isaac } 128dcbd3bf7SToby Isaac break; 129dcbd3bf7SToby Isaac } 130dcbd3bf7SToby Isaac } 13108401ef6SPierre Jolivet PetscCheck(i != sConeSize,PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 132dcbd3bf7SToby Isaac PetscFunctionReturn(0); 133dcbd3bf7SToby Isaac } 134dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 1359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,parent,&coneSize)); 136dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 137dcbd3bf7SToby Isaac if (dim == 2) { 138dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 139dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 140dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 141dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 142dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 143dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 144947b95d8SBarry Smith } else { 145dcbd3bf7SToby Isaac ABswapVert = ABswap; 146dcbd3bf7SToby Isaac } 147dcbd3bf7SToby Isaac if (childB) { 148dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 149dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 150dcbd3bf7SToby Isaac const PetscInt *children; 151dcbd3bf7SToby Isaac 152dcbd3bf7SToby Isaac /* count which position the child is in */ 1539566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,parent,&numChildren,&children)); 154dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 155dcbd3bf7SToby Isaac p = children[i]; 156dcbd3bf7SToby Isaac if (p == childA) { 157dcbd3bf7SToby Isaac posA = i; 158dcbd3bf7SToby Isaac break; 159dcbd3bf7SToby Isaac } 160dcbd3bf7SToby Isaac } 161dcbd3bf7SToby Isaac if (posA >= coneSize) { 162dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 163dcbd3bf7SToby Isaac * is invariant */ 1641dca8a05SBarry Smith PetscCheck(dim == 2 && posA == 3,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Expected a middle triangle, got something else"); 165dcbd3bf7SToby Isaac *childB = childA; 166dcbd3bf7SToby Isaac } 167dcbd3bf7SToby Isaac else { 168dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 169dcbd3bf7SToby Isaac PetscInt posB; 170dcbd3bf7SToby Isaac 171dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 172dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 173dcbd3bf7SToby Isaac } 174dcbd3bf7SToby Isaac } 175dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 176dcbd3bf7SToby Isaac PetscFunctionReturn(0); 177dcbd3bf7SToby Isaac } 178dcbd3bf7SToby Isaac 179dcbd3bf7SToby Isaac /*@ 180dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 181dcbd3bf7SToby Isaac 182dcbd3bf7SToby Isaac Input Parameters: 183dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object 184dcbd3bf7SToby Isaac . parent - the parent point 185dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 186dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 187dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 188dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 189dcbd3bf7SToby Isaac 190dcbd3bf7SToby Isaac Output Parameters: 191dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child 192ff1f73f7SToby Isaac - childB - if not NULL, the new childID for describing the child 193dcbd3bf7SToby Isaac 194dcbd3bf7SToby Isaac Level: developer 195dcbd3bf7SToby Isaac 196db781477SPatrick Sanan .seealso: `DMPlexGetReferenceTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetTree()` 197dcbd3bf7SToby Isaac @*/ 198dcbd3bf7SToby Isaac PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 199dcbd3bf7SToby Isaac { 200dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 201dcbd3bf7SToby Isaac 202dcbd3bf7SToby Isaac PetscFunctionBegin; 203dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20428b400f6SJacob Faibussowitsch PetscCheck(mesh->getchildsymmetry,PETSC_COMM_SELF,PETSC_ERR_SUP,"DMPlexReferenceTreeGetChildSymmetry not implemented"); 2059566063dSJacob Faibussowitsch PetscCall(mesh->getchildsymmetry(dm,parent,parentOrientA,childOrientA,childA,parentOrientB,childOrientB,childB)); 206dcbd3bf7SToby Isaac PetscFunctionReturn(0); 207dcbd3bf7SToby Isaac } 208dcbd3bf7SToby Isaac 209776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM,PetscSection,PetscInt*,PetscInt*,PetscBool,PetscBool); 210f9f063d4SToby Isaac 211f2c1aa1dSLisandro Dalcin PetscErrorCode DMPlexCreateReferenceTree_SetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 212f2c1aa1dSLisandro Dalcin { 213f2c1aa1dSLisandro Dalcin PetscFunctionBegin; 2149566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_TRUE,PETSC_FALSE)); 215f2c1aa1dSLisandro Dalcin PetscFunctionReturn(0); 216f2c1aa1dSLisandro Dalcin } 217f2c1aa1dSLisandro Dalcin 2180e2cc29aSToby Isaac PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 219da43764aSToby Isaac { 2200e2cc29aSToby Isaac MPI_Comm comm; 2210e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 222da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 223da43764aSToby Isaac DMLabel identity, identityRef; 22410f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 225da43764aSToby Isaac PetscScalar *unionCoords; 226da43764aSToby Isaac IS perm; 227da43764aSToby Isaac 228da43764aSToby Isaac PetscFunctionBegin; 2290e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(K, &dim)); 2319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd)); 2329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, labelName, &identity)); 2339566063dSJacob Faibussowitsch PetscCall(DMGetLabel(Kref, labelName, &identityRef)); 2349566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(Kref, &pRefStart, &pRefEnd)); 2359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionSection)); 2369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart))); 237da43764aSToby Isaac /* count points that will go in the union */ 238da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 2399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionSection, p - pStart, 1)); 240da43764aSToby Isaac } 241da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 242da43764aSToby Isaac PetscInt q, qSize; 2439566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &q)); 2449566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(identityRef, q, &qSize)); 245da43764aSToby Isaac if (qSize > 1) { 2469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1)); 247da43764aSToby Isaac } 248da43764aSToby Isaac } 2499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart,&permvals)); 250da43764aSToby Isaac offset = 0; 251da43764aSToby Isaac /* stratify points in the union by topological dimension */ 252da43764aSToby Isaac for (d = 0; d <= dim; d++) { 253da43764aSToby Isaac PetscInt cStart, cEnd, c; 254da43764aSToby Isaac 2559566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, &cEnd)); 256da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 257da43764aSToby Isaac permvals[offset++] = c; 258da43764aSToby Isaac } 259da43764aSToby Isaac 2609566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd)); 261da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 262da43764aSToby Isaac permvals[offset++] = c + (pEnd - pStart); 263da43764aSToby Isaac } 264da43764aSToby Isaac } 2659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm)); 2669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(unionSection,perm)); 2679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionSection)); 2689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionSection,&numUnionPoints)); 2699566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints)); 270da43764aSToby Isaac /* count dimension points */ 271da43764aSToby Isaac for (d = 0; d <= dim; d++) { 272da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 2739566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K,d,&cStart,NULL)); 2749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection,cStart-pStart,&cOff)); 275da43764aSToby Isaac if (d < dim) { 2769566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K,d+1,&cStart,NULL)); 2779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2)); 278da43764aSToby Isaac } 279da43764aSToby Isaac else { 280da43764aSToby Isaac cOff2 = numUnionPoints; 281da43764aSToby Isaac } 282da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 283da43764aSToby Isaac } 2849566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionConeSection)); 2859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionConeSection, 0, numUnionPoints)); 286da43764aSToby Isaac /* count the cones in the union */ 287da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 288da43764aSToby Isaac PetscInt dof, uOff; 289da43764aSToby Isaac 2909566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof)); 2919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart,&uOff)); 2929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof)); 293da43764aSToby Isaac coneSizes[uOff] = dof; 294da43764aSToby Isaac } 295da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 296da43764aSToby Isaac PetscInt dof, uDof, uOff; 297da43764aSToby Isaac 2989566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof)); 2999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof)); 3009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff)); 301da43764aSToby Isaac if (uDof) { 3029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof)); 303da43764aSToby Isaac coneSizes[uOff] = dof; 304da43764aSToby Isaac } 305da43764aSToby Isaac } 3069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionConeSection)); 3079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionConeSection,&numCones)); 3089566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations)); 309da43764aSToby Isaac /* write the cones in the union */ 310da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 311da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 312da43764aSToby Isaac const PetscInt *cone, *orientation; 313da43764aSToby Isaac 3149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof)); 3159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, p, &cone)); 3169566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, p, &orientation)); 3179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart,&uOff)); 3189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection,uOff,&cOff)); 319da43764aSToby Isaac for (c = 0; c < dof; c++) { 320da43764aSToby Isaac PetscInt e, eOff; 321da43764aSToby Isaac e = cone[c]; 3229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 323da43764aSToby Isaac unionCones[cOff + c] = eOff; 324da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 325da43764aSToby Isaac } 326da43764aSToby Isaac } 327da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 328da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 329da43764aSToby Isaac const PetscInt *cone, *orientation; 330da43764aSToby Isaac 3319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof)); 3329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(Kref, p, &cone)); 3339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(Kref, p, &orientation)); 3349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof)); 3359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff)); 336da43764aSToby Isaac if (uDof) { 3379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection,uOff,&cOff)); 338da43764aSToby Isaac for (c = 0; c < dof; c++) { 339da43764aSToby Isaac PetscInt e, eOff, eDof; 340da43764aSToby Isaac 341da43764aSToby Isaac e = cone[c]; 3429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof)); 343da43764aSToby Isaac if (eDof) { 3449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff)); 345da43764aSToby Isaac } 346da43764aSToby Isaac else { 3479566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, e, &e)); 3489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 349da43764aSToby Isaac } 350da43764aSToby Isaac unionCones[cOff + c] = eOff; 351da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 352da43764aSToby Isaac } 353da43764aSToby Isaac } 354da43764aSToby Isaac } 355da43764aSToby Isaac /* get the coordinates */ 356da43764aSToby Isaac { 357da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 358da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 359da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 360da43764aSToby Isaac PetscScalar *Kcoords; 361da43764aSToby Isaac 3629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &KcoordsSec)); 3639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &KcoordsVec)); 3649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(Kref, &KrefCoordsSec)); 3659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(Kref, &KrefCoordsVec)); 366da43764aSToby Isaac 367da43764aSToby Isaac numVerts = numDimPoints[0]; 3689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVerts * dim,&unionCoords)); 3699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K,0,&vStart,&vEnd)); 370da43764aSToby Isaac 371da43764aSToby Isaac offset = 0; 372da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 3739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection,v - pStart,&vOff)); 3749566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords)); 375da43764aSToby Isaac for (d = 0; d < dim; d++) { 376da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 377da43764aSToby Isaac } 378da43764aSToby Isaac offset++; 379da43764aSToby Isaac } 3809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd)); 381da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 3829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof)); 3839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff)); 3849566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords)); 385da43764aSToby Isaac if (vDof) { 386da43764aSToby Isaac for (d = 0; d < dim; d++) { 387da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 388da43764aSToby Isaac } 389da43764aSToby Isaac offset++; 390da43764aSToby Isaac } 391da43764aSToby Isaac } 392da43764aSToby Isaac } 3939566063dSJacob Faibussowitsch PetscCall(DMCreate(comm,ref)); 3949566063dSJacob Faibussowitsch PetscCall(DMSetType(*ref,DMPLEX)); 3959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ref,dim)); 3969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords)); 39710f7e118SToby Isaac /* set the tree */ 3989566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm,&parentSection)); 3999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection,0,numUnionPoints)); 40010f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 40110f7e118SToby Isaac PetscInt uDof, uOff; 40210f7e118SToby Isaac 4039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof)); 4049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff)); 405*1baa6e33SBarry Smith if (uDof) PetscCall(PetscSectionSetDof(parentSection,uOff,1)); 40610f7e118SToby Isaac } 4079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 4089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection,&parentSize)); 4099566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(parentSize,&parents,parentSize,&childIDs)); 41010f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 41110f7e118SToby Isaac PetscInt uDof, uOff; 41210f7e118SToby Isaac 4139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof)); 4149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff)); 41510f7e118SToby Isaac if (uDof) { 41610f7e118SToby Isaac PetscInt pOff, parent, parentU; 4179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection,uOff,&pOff)); 4189566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef,p,&parent)); 4199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, parent - pStart,&parentU)); 42010f7e118SToby Isaac parents[pOff] = parentU; 42110f7e118SToby Isaac childIDs[pOff] = uOff; 42210f7e118SToby Isaac } 42310f7e118SToby Isaac } 4249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_SetTree(*ref,parentSection,parents,childIDs)); 4259566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 4269566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents,childIDs)); 42710f7e118SToby Isaac 428da43764aSToby Isaac /* clean up */ 4299566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionSection)); 4309566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionConeSection)); 4319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 4329566063dSJacob Faibussowitsch PetscCall(PetscFree(unionCoords)); 4339566063dSJacob Faibussowitsch PetscCall(PetscFree2(unionCones,unionOrientations)); 4349566063dSJacob Faibussowitsch PetscCall(PetscFree2(coneSizes,numDimPoints)); 4350e2cc29aSToby Isaac PetscFunctionReturn(0); 4360e2cc29aSToby Isaac } 4370e2cc29aSToby Isaac 4380e2cc29aSToby Isaac /*@ 4390e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4400e2cc29aSToby Isaac 441d083f849SBarry Smith Collective 4420e2cc29aSToby Isaac 4430e2cc29aSToby Isaac Input Parameters: 4440e2cc29aSToby Isaac + comm - the MPI communicator 4450e2cc29aSToby Isaac . dim - the spatial dimension 4460e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4470e2cc29aSToby Isaac 4480e2cc29aSToby Isaac Output Parameters: 4490e2cc29aSToby Isaac . ref - the reference tree DMPlex object 4500e2cc29aSToby Isaac 4510e2cc29aSToby Isaac Level: intermediate 4520e2cc29aSToby Isaac 453db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()` 4540e2cc29aSToby Isaac @*/ 4550e2cc29aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 4560e2cc29aSToby Isaac { 4570e2cc29aSToby Isaac DM_Plex *mesh; 4580e2cc29aSToby Isaac DM K, Kref; 4590e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4600e2cc29aSToby Isaac DMLabel identity; 4610e2cc29aSToby Isaac 4620e2cc29aSToby Isaac PetscFunctionBegin; 4630e2cc29aSToby Isaac #if 1 4640e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4650e2cc29aSToby Isaac #endif 4660e2cc29aSToby Isaac /* create a reference element */ 4679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(comm, DMPolytopeTypeSimpleShape(dim, simplex), &K)); 4689566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(K, "identity")); 4699566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, "identity", &identity)); 4709566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd)); 4710e2cc29aSToby Isaac for (p = pStart; p < pEnd; p++) { 4729566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(identity, p, p)); 4730e2cc29aSToby Isaac } 4740e2cc29aSToby Isaac /* refine it */ 4759566063dSJacob Faibussowitsch PetscCall(DMRefine(K,comm,&Kref)); 4760e2cc29aSToby Isaac 4770e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4780e2cc29aSToby Isaac * points that appear in both */ 4799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref)); 4800e2cc29aSToby Isaac mesh = (DM_Plex *) (*ref)->data; 4810e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 4829566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 4839566063dSJacob Faibussowitsch PetscCall(DMDestroy(&Kref)); 484da43764aSToby Isaac PetscFunctionReturn(0); 485da43764aSToby Isaac } 486da43764aSToby Isaac 487878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 488878b19aaSToby Isaac { 489878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 490878b19aaSToby Isaac PetscSection childSec, pSec; 491878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 492878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 493878b19aaSToby Isaac 494878b19aaSToby Isaac PetscFunctionBegin; 495878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4969566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 4979566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 498878b19aaSToby Isaac pSec = mesh->parentSection; 499878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 5009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(pSec,&pSize)); 501878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 502878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 503878b19aaSToby Isaac 504878b19aaSToby Isaac parMax = PetscMax(parMax,par+1); 505878b19aaSToby Isaac parMin = PetscMin(parMin,par); 506878b19aaSToby Isaac } 507878b19aaSToby Isaac if (parMin > parMax) { 508878b19aaSToby Isaac parMin = -1; 509878b19aaSToby Isaac parMax = -1; 510878b19aaSToby Isaac } 5119566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec)); 5129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(childSec,parMin,parMax)); 513878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 514878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 515878b19aaSToby Isaac 5169566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(childSec,par,1)); 517878b19aaSToby Isaac } 5189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(childSec)); 5199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(childSec,&cSize)); 5209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cSize,&children)); 5219566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(parMax-parMin,&offsets)); 5229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pSec,&pStart,&pEnd)); 523878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 524878b19aaSToby Isaac PetscInt dof, off, i; 525878b19aaSToby Isaac 5269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec,p,&dof)); 5279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec,p,&off)); 528878b19aaSToby Isaac for (i = 0; i < dof; i++) { 529878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 530878b19aaSToby Isaac 5319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec,par,&cOff)); 532878b19aaSToby Isaac children[cOff + offsets[par-parMin]++] = p; 533878b19aaSToby Isaac } 534878b19aaSToby Isaac } 535878b19aaSToby Isaac mesh->childSection = childSec; 536878b19aaSToby Isaac mesh->children = children; 5379566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 538878b19aaSToby Isaac PetscFunctionReturn(0); 539878b19aaSToby Isaac } 540878b19aaSToby Isaac 5416dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 5426dd5a8c8SToby Isaac { 5436dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5446dd5a8c8SToby Isaac const PetscInt *vals; 5456dd5a8c8SToby Isaac PetscSection secNew; 5466dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5476dd5a8c8SToby Isaac PetscBool compress; 5486dd5a8c8SToby Isaac 5496dd5a8c8SToby Isaac PetscFunctionBegin; 5509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section,&pStart,&pEnd)); 5519566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is,&size)); 5529566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is,&vals)); 5539566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew)); 5549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secNew,pStart,pEnd)); 5556dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5566dd5a8c8SToby Isaac PetscInt dof; 5576dd5a8c8SToby Isaac 5586dd5a8c8SToby Isaac p = vals[i]; 5596dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5616dd5a8c8SToby Isaac if (dof) break; 5626dd5a8c8SToby Isaac } 5636dd5a8c8SToby Isaac if (i == size) { 5649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew)); 5656dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5666dd5a8c8SToby Isaac compress = PETSC_FALSE; 5676dd5a8c8SToby Isaac sizeNew = 0; 5686dd5a8c8SToby Isaac } 5696dd5a8c8SToby Isaac else { 5706dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5716dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5726dd5a8c8SToby Isaac PetscInt dof, off; 5736dd5a8c8SToby Isaac 5749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5766dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5776dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5786dd5a8c8SToby Isaac 5796dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &qDof)); 5816dd5a8c8SToby Isaac } 582*1baa6e33SBarry Smith if (qDof) PetscCall(PetscSectionAddDof(secNew, p, qDof)); 5836dd5a8c8SToby Isaac else { 5849566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(secNew, p, 1)); 5856dd5a8c8SToby Isaac } 5866dd5a8c8SToby Isaac } 5876dd5a8c8SToby Isaac } 5889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew)); 5899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secNew,&sizeNew)); 5909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew,&valsNew)); 5916dd5a8c8SToby Isaac compress = PETSC_FALSE; 5926dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5936dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 5946dd5a8c8SToby Isaac 5959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 5969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 5979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dofNew)); 5989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &offNew)); 5996dd5a8c8SToby Isaac count = 0; 6006dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 6016dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 6026dd5a8c8SToby Isaac 6036dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 6049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &qDof)); 6059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &qOff)); 6066dd5a8c8SToby Isaac } 6076dd5a8c8SToby Isaac if (qDof) { 6086dd5a8c8SToby Isaac PetscInt oldCount = count; 6096dd5a8c8SToby Isaac 6106dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 6116dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 6126dd5a8c8SToby Isaac 6136dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6146dd5a8c8SToby Isaac if (valsNew[offNew + k] == r) { 6156dd5a8c8SToby Isaac break; 6166dd5a8c8SToby Isaac } 6176dd5a8c8SToby Isaac } 6186dd5a8c8SToby Isaac if (k == oldCount) { 6196dd5a8c8SToby Isaac valsNew[offNew + count++] = r; 6206dd5a8c8SToby Isaac } 6216dd5a8c8SToby Isaac } 6226dd5a8c8SToby Isaac } 6236dd5a8c8SToby Isaac else { 6246dd5a8c8SToby Isaac PetscInt k, oldCount = count; 6256dd5a8c8SToby Isaac 6266dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6276dd5a8c8SToby Isaac if (valsNew[offNew + k] == q) { 6286dd5a8c8SToby Isaac break; 6296dd5a8c8SToby Isaac } 6306dd5a8c8SToby Isaac } 6316dd5a8c8SToby Isaac if (k == oldCount) { 6326dd5a8c8SToby Isaac valsNew[offNew + count++] = q; 6336dd5a8c8SToby Isaac } 6346dd5a8c8SToby Isaac } 6356dd5a8c8SToby Isaac } 6366dd5a8c8SToby Isaac if (count < dofNew) { 6379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secNew, p, count)); 6386dd5a8c8SToby Isaac compress = PETSC_TRUE; 6396dd5a8c8SToby Isaac } 6406dd5a8c8SToby Isaac } 6416dd5a8c8SToby Isaac } 6429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is,&vals)); 6431c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew))); 6446dd5a8c8SToby Isaac if (!globalAnyNew) { 6459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew)); 6466dd5a8c8SToby Isaac *sectionNew = NULL; 6476dd5a8c8SToby Isaac *isNew = NULL; 6486dd5a8c8SToby Isaac } 6496dd5a8c8SToby Isaac else { 6506dd5a8c8SToby Isaac PetscBool globalCompress; 6516dd5a8c8SToby Isaac 6521c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew))); 6536dd5a8c8SToby Isaac if (compress) { 6546dd5a8c8SToby Isaac PetscSection secComp; 6556dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6566dd5a8c8SToby Isaac 6579566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp)); 6589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secComp,pStart,pEnd)); 6596dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6606dd5a8c8SToby Isaac PetscInt dof; 6616dd5a8c8SToby Isaac 6629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof)); 6639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secComp, p, dof)); 6646dd5a8c8SToby Isaac } 6659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secComp)); 6669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secComp,&sizeNew)); 6679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew,&valsComp)); 6686dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6696dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6706dd5a8c8SToby Isaac 6719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof)); 6729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &off)); 6739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secComp, p, &offNew)); 6746dd5a8c8SToby Isaac for (j = 0; j < dof; j++) { 6756dd5a8c8SToby Isaac valsComp[offNew + j] = valsNew[off + j]; 6766dd5a8c8SToby Isaac } 6776dd5a8c8SToby Isaac } 6789566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew)); 6796dd5a8c8SToby Isaac secNew = secComp; 6809566063dSJacob Faibussowitsch PetscCall(PetscFree(valsNew)); 6816dd5a8c8SToby Isaac valsNew = valsComp; 6826dd5a8c8SToby Isaac } 6839566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew)); 6846dd5a8c8SToby Isaac } 6856dd5a8c8SToby Isaac PetscFunctionReturn(0); 6866dd5a8c8SToby Isaac } 6876dd5a8c8SToby Isaac 688f7c74593SToby Isaac static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 68966af876cSToby Isaac { 69066af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 69166af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 69266af876cSToby Isaac PetscSection aSec; 693f9f063d4SToby Isaac DMLabel canonLabel; 69466af876cSToby Isaac IS aIS; 69566af876cSToby Isaac 69666af876cSToby Isaac PetscFunctionBegin; 69766af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6989566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm,&pStart,&pEnd)); 6999566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm,"canonical",&canonLabel)); 70066af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 70166af876cSToby Isaac PetscInt parent; 70266af876cSToby Isaac 703f9f063d4SToby Isaac if (canonLabel) { 704f9f063d4SToby Isaac PetscInt canon; 705f9f063d4SToby Isaac 7069566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel,p,&canon)); 707f9f063d4SToby Isaac if (p != canon) continue; 708f9f063d4SToby Isaac } 7099566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,p,&parent,NULL)); 71066af876cSToby Isaac if (parent != p) { 71166af876cSToby Isaac aMin = PetscMin(aMin,p); 71266af876cSToby Isaac aMax = PetscMax(aMax,p+1); 71366af876cSToby Isaac } 71466af876cSToby Isaac } 71566af876cSToby Isaac if (aMin > aMax) { 71666af876cSToby Isaac aMin = -1; 71766af876cSToby Isaac aMax = -1; 71866af876cSToby Isaac } 7199566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&aSec)); 7209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(aSec,aMin,aMax)); 72166af876cSToby Isaac for (p = aMin; p < aMax; p++) { 72266af876cSToby Isaac PetscInt parent, ancestor = p; 72366af876cSToby Isaac 724f9f063d4SToby Isaac if (canonLabel) { 725f9f063d4SToby Isaac PetscInt canon; 726f9f063d4SToby Isaac 7279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel,p,&canon)); 728f9f063d4SToby Isaac if (p != canon) continue; 729f9f063d4SToby Isaac } 7309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,p,&parent,NULL)); 73166af876cSToby Isaac while (parent != ancestor) { 73266af876cSToby Isaac ancestor = parent; 7339566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,ancestor,&parent,NULL)); 73466af876cSToby Isaac } 73566af876cSToby Isaac if (ancestor != p) { 73666af876cSToby Isaac PetscInt closureSize, *closure = NULL; 73766af876cSToby Isaac 7389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure)); 7399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(aSec,p,closureSize)); 7409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure)); 74166af876cSToby Isaac } 74266af876cSToby Isaac } 7439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(aSec)); 7449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(aSec,&size)); 7459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size,&anchors)); 74666af876cSToby Isaac for (p = aMin; p < aMax; p++) { 74766af876cSToby Isaac PetscInt parent, ancestor = p; 74866af876cSToby Isaac 749f9f063d4SToby Isaac if (canonLabel) { 750f9f063d4SToby Isaac PetscInt canon; 751f9f063d4SToby Isaac 7529566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel,p,&canon)); 753f9f063d4SToby Isaac if (p != canon) continue; 754f9f063d4SToby Isaac } 7559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,p,&parent,NULL)); 75666af876cSToby Isaac while (parent != ancestor) { 75766af876cSToby Isaac ancestor = parent; 7589566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,ancestor,&parent,NULL)); 75966af876cSToby Isaac } 76066af876cSToby Isaac if (ancestor != p) { 76166af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 76266af876cSToby Isaac 7639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&aOff)); 76466af876cSToby Isaac 7659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure)); 76666af876cSToby Isaac for (j = 0; j < closureSize; j++) { 76766af876cSToby Isaac anchors[aOff + j] = closure[2*j]; 76866af876cSToby Isaac } 7699566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure)); 77066af876cSToby Isaac } 77166af876cSToby Isaac } 7729566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,size,anchors,PETSC_OWN_POINTER,&aIS)); 7736dd5a8c8SToby Isaac { 7746dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7756dd5a8c8SToby Isaac IS aISNew = aIS; 7766dd5a8c8SToby Isaac 7779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aSec)); 7789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aIS)); 7796dd5a8c8SToby Isaac while (aSecNew) { 7809566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec)); 7819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS)); 7826dd5a8c8SToby Isaac aSec = aSecNew; 7836dd5a8c8SToby Isaac aIS = aISNew; 7846dd5a8c8SToby Isaac aSecNew = NULL; 7856dd5a8c8SToby Isaac aISNew = NULL; 7869566063dSJacob Faibussowitsch PetscCall(AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew)); 7876dd5a8c8SToby Isaac } 7886dd5a8c8SToby Isaac } 7899566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm,aSec,aIS)); 7909566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec)); 7919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS)); 79266af876cSToby Isaac PetscFunctionReturn(0); 79366af876cSToby Isaac } 79466af876cSToby Isaac 7956461c1adSToby Isaac static PetscErrorCode DMPlexGetTrueSupportSize(DM dm,PetscInt p,PetscInt *dof,PetscInt *numTrueSupp) 7966461c1adSToby Isaac { 7976461c1adSToby Isaac PetscFunctionBegin; 7986461c1adSToby Isaac if (numTrueSupp[p] == -1) { 7996461c1adSToby Isaac PetscInt i, alldof; 8006461c1adSToby Isaac const PetscInt *supp; 8016461c1adSToby Isaac PetscInt count = 0; 8026461c1adSToby Isaac 8039566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm,p,&alldof)); 8049566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm,p,&supp)); 8056461c1adSToby Isaac for (i = 0; i < alldof; i++) { 8066461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 8076461c1adSToby Isaac const PetscInt *cone; 8086461c1adSToby Isaac 8099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,q,&numCones)); 8109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,q,&cone)); 8116461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8126461c1adSToby Isaac if (cone[j] == p) break; 8136461c1adSToby Isaac } 8146461c1adSToby Isaac if (j < numCones) count++; 8156461c1adSToby Isaac } 8166461c1adSToby Isaac numTrueSupp[p] = count; 8176461c1adSToby Isaac } 8186461c1adSToby Isaac *dof = numTrueSupp[p]; 8196461c1adSToby Isaac PetscFunctionReturn(0); 8206461c1adSToby Isaac } 8216461c1adSToby Isaac 822776742edSToby Isaac static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 823776742edSToby Isaac { 824776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 825776742edSToby Isaac PetscSection newSupportSection; 826776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 8276461c1adSToby Isaac PetscInt *numTrueSupp; 828776742edSToby Isaac PetscInt *offsets; 829776742edSToby Isaac 830776742edSToby Isaac PetscFunctionBegin; 831776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 832776742edSToby Isaac /* symmetrize the hierarchy */ 8339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm,&depth)); 8349566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)),&newSupportSection)); 8359566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm,&pStart,&pEnd)); 8369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSupportSection,pStart,pEnd)); 8379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd,&offsets)); 8389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd,&numTrueSupp)); 8396461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 8406461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 841776742edSToby Isaac * parent(q) */ 842776742edSToby Isaac for (d = 0; d <= depth; d++) { 8439566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,d,&pStart,&pEnd)); 844776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 845776742edSToby Isaac PetscInt dof, q, qdof, parent; 846776742edSToby Isaac 8479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm,p,&dof,numTrueSupp)); 8489566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, dof)); 849776742edSToby Isaac q = p; 8509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,q,&parent,NULL)); 851776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 852776742edSToby Isaac q = parent; 853776742edSToby Isaac 8549566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm,q,&qdof,numTrueSupp)); 8559566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection,p,qdof)); 8569566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection,q,dof)); 8579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,q,&parent,NULL)); 858776742edSToby Isaac } 859776742edSToby Isaac } 860776742edSToby Isaac } 8619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSupportSection)); 8629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSupportSection,&newSize)); 8639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newSize,&newSupports)); 864776742edSToby Isaac for (d = 0; d <= depth; d++) { 8659566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,d,&pStart,&pEnd)); 866776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 867776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 868776742edSToby Isaac 8699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 8719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(newSupportSection, p, &newDof)); 8729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, p, &newOff)); 873776742edSToby Isaac for (i = 0; i < dof; i++) { 8746461c1adSToby Isaac PetscInt numCones, j; 8756461c1adSToby Isaac const PetscInt *cone; 8766461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 8776461c1adSToby Isaac 8789566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,q,&numCones)); 8799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,q,&cone)); 8806461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8816461c1adSToby Isaac if (cone[j] == p) break; 8826461c1adSToby Isaac } 8836461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = q; 884776742edSToby Isaac } 885776742edSToby Isaac 886776742edSToby Isaac q = p; 8879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,q,&parent,NULL)); 888776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 889776742edSToby Isaac q = parent; 8909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, q, &qdof)); 8919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &qoff)); 8929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, q, &newqOff)); 893776742edSToby Isaac for (i = 0; i < qdof; i++) { 8946461c1adSToby Isaac PetscInt numCones, j; 8956461c1adSToby Isaac const PetscInt *cone; 8966461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 8976461c1adSToby Isaac 8989566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,r,&numCones)); 8999566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,r,&cone)); 9006461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9016461c1adSToby Isaac if (cone[j] == q) break; 9026461c1adSToby Isaac } 9036461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = r; 904776742edSToby Isaac } 905776742edSToby Isaac for (i = 0; i < dof; i++) { 9066461c1adSToby Isaac PetscInt numCones, j; 9076461c1adSToby Isaac const PetscInt *cone; 9086461c1adSToby Isaac PetscInt r = mesh->supports[off + i]; 9096461c1adSToby Isaac 9109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,r,&numCones)); 9119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,r,&cone)); 9126461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9136461c1adSToby Isaac if (cone[j] == p) break; 9146461c1adSToby Isaac } 9156461c1adSToby Isaac if (j < numCones) newSupports[newqOff+offsets[q]++] = r; 916776742edSToby Isaac } 9179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,q,&parent,NULL)); 918776742edSToby Isaac } 919776742edSToby Isaac } 920776742edSToby Isaac } 9219566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 922776742edSToby Isaac mesh->supportSection = newSupportSection; 9239566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 924776742edSToby Isaac mesh->supports = newSupports; 9259566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 9269566063dSJacob Faibussowitsch PetscCall(PetscFree(numTrueSupp)); 927776742edSToby Isaac 928776742edSToby Isaac PetscFunctionReturn(0); 929776742edSToby Isaac } 930776742edSToby Isaac 931f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM,PetscSection,PetscSection,Mat); 932f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM,PetscSection,PetscSection,Mat); 933f7c74593SToby Isaac 934776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 935f9f063d4SToby Isaac { 936f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 937f9f063d4SToby Isaac DM refTree; 938f9f063d4SToby Isaac PetscInt size; 939f9f063d4SToby Isaac 940f9f063d4SToby Isaac PetscFunctionBegin; 941f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 942f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 9439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)parentSection)); 9449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 945f9f063d4SToby Isaac mesh->parentSection = parentSection; 9469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection,&size)); 947f9f063d4SToby Isaac if (parents != mesh->parents) { 9489566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 9499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size,&mesh->parents)); 9509566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->parents, parents, size)); 951f9f063d4SToby Isaac } 952f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 9539566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 9549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size,&mesh->childIDs)); 9559566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->childIDs, childIDs, size)); 956f9f063d4SToby Isaac } 9579566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm,&refTree)); 958f9f063d4SToby Isaac if (refTree) { 959f9f063d4SToby Isaac DMLabel canonLabel; 960f9f063d4SToby Isaac 9619566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree,"canonical",&canonLabel)); 962f9f063d4SToby Isaac if (canonLabel) { 963f9f063d4SToby Isaac PetscInt i; 964f9f063d4SToby Isaac 965f9f063d4SToby Isaac for (i = 0; i < size; i++) { 966f9f063d4SToby Isaac PetscInt canon; 9679566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon)); 968f9f063d4SToby Isaac if (canon >= 0) { 969f9f063d4SToby Isaac mesh->childIDs[i] = canon; 970f9f063d4SToby Isaac } 971f9f063d4SToby Isaac } 972f9f063d4SToby Isaac } 973f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 9746e0288c8SStefano Zampini } else { 975f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 976f9f063d4SToby Isaac } 9779566063dSJacob Faibussowitsch PetscCall(DMPlexTreeSymmetrize(dm)); 978f9f063d4SToby Isaac if (computeCanonical) { 979f9f063d4SToby Isaac PetscInt d, dim; 980f9f063d4SToby Isaac 981f9f063d4SToby Isaac /* add the canonical label */ 9829566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&dim)); 9839566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm,"canonical")); 984f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 985f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 986f9f063d4SToby Isaac const PetscInt *cChildren; 987f9f063d4SToby Isaac 9889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,d,&dStart,&dEnd)); 989f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 9909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,p,&cNumChildren,&cChildren)); 991f9f063d4SToby Isaac if (cNumChildren) { 992f9f063d4SToby Isaac canon = p; 993f9f063d4SToby Isaac break; 994f9f063d4SToby Isaac } 995f9f063d4SToby Isaac } 996f9f063d4SToby Isaac if (canon == -1) continue; 997f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 998f9f063d4SToby Isaac PetscInt numChildren, i; 999f9f063d4SToby Isaac const PetscInt *children; 1000f9f063d4SToby Isaac 10019566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,p,&numChildren,&children)); 1002f9f063d4SToby Isaac if (numChildren) { 100363a3b9bcSJacob 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); 10049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm,"canonical",p,canon)); 1005f9f063d4SToby Isaac for (i = 0; i < numChildren; i++) { 10069566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm,"canonical",children[i],cChildren[i])); 1007f9f063d4SToby Isaac } 1008f9f063d4SToby Isaac } 1009f9f063d4SToby Isaac } 1010f9f063d4SToby Isaac } 1011f9f063d4SToby Isaac } 1012*1baa6e33SBarry Smith if (exchangeSupports) PetscCall(DMPlexTreeExchangeSupports(dm)); 1013f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 1014f7c74593SToby Isaac /* reset anchors */ 10159566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm,NULL,NULL)); 1016f9f063d4SToby Isaac PetscFunctionReturn(0); 1017f9f063d4SToby Isaac } 1018f9f063d4SToby Isaac 10190b7167a0SToby Isaac /*@ 10200b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 10210b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 10220b7167a0SToby Isaac tree root. 10230b7167a0SToby Isaac 10240b7167a0SToby Isaac Collective on dm 10250b7167a0SToby Isaac 10260b7167a0SToby Isaac Input Parameters: 10270b7167a0SToby Isaac + dm - the DMPlex object 10280b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 10290b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 10300b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 10310b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 10320b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 10330b7167a0SToby Isaac 10340b7167a0SToby Isaac Level: intermediate 10350b7167a0SToby Isaac 1036db781477SPatrick Sanan .seealso: `DMPlexGetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 10370b7167a0SToby Isaac @*/ 1038b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 10390b7167a0SToby Isaac { 10400b7167a0SToby Isaac PetscFunctionBegin; 10419566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_FALSE,PETSC_TRUE)); 10420b7167a0SToby Isaac PetscFunctionReturn(0); 10430b7167a0SToby Isaac } 10440b7167a0SToby Isaac 1045b2f41788SToby Isaac /*@ 1046b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 1047b2f41788SToby Isaac Collective on dm 1048b2f41788SToby Isaac 1049f899ff85SJose E. Roman Input Parameter: 1050b2f41788SToby Isaac . dm - the DMPlex object 1051b2f41788SToby Isaac 1052b2f41788SToby Isaac Output Parameters: 1053b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1054b2f41788SToby Isaac offset indexes the parent and childID list 1055b2f41788SToby Isaac . parents - a list of the point parents 1056b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1057b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1058b2f41788SToby Isaac . childSection - the inverse of the parent section 1059b2f41788SToby Isaac - children - a list of the point children 1060b2f41788SToby Isaac 1061b2f41788SToby Isaac Level: intermediate 1062b2f41788SToby Isaac 1063db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()` 1064b2f41788SToby Isaac @*/ 1065b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1066b2f41788SToby Isaac { 1067b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1068b2f41788SToby Isaac 1069b2f41788SToby Isaac PetscFunctionBegin; 1070b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1071b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1072b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1073b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1074b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1075b2f41788SToby Isaac if (children) *children = mesh->children; 1076b2f41788SToby Isaac PetscFunctionReturn(0); 1077b2f41788SToby Isaac } 1078b2f41788SToby Isaac 1079d961a43aSToby Isaac /*@ 1080eaf898f9SPatrick Sanan DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the DAG) 1081d961a43aSToby Isaac 1082d961a43aSToby Isaac Input Parameters: 1083d961a43aSToby Isaac + dm - the DMPlex object 1084d961a43aSToby Isaac - point - the query point 1085d961a43aSToby Isaac 1086d961a43aSToby Isaac Output Parameters: 1087d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 1088d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 1089d961a43aSToby Isaac does not have a parent 1090d961a43aSToby Isaac 1091d961a43aSToby Isaac Level: intermediate 1092d961a43aSToby Isaac 1093db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeChildren()` 1094d961a43aSToby Isaac @*/ 1095d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1096d961a43aSToby Isaac { 1097d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1098d961a43aSToby Isaac PetscSection pSec; 1099d961a43aSToby Isaac 1100d961a43aSToby Isaac PetscFunctionBegin; 1101d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1102d961a43aSToby Isaac pSec = mesh->parentSection; 1103d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1104d961a43aSToby Isaac PetscInt dof; 1105d961a43aSToby Isaac 11069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof (pSec, point, &dof)); 1107d961a43aSToby Isaac if (dof) { 1108d961a43aSToby Isaac PetscInt off; 1109d961a43aSToby Isaac 11109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset (pSec, point, &off)); 1111d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1112d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 1113d961a43aSToby Isaac PetscFunctionReturn(0); 1114d961a43aSToby Isaac } 1115d961a43aSToby Isaac } 1116d961a43aSToby Isaac if (parent) { 1117d961a43aSToby Isaac *parent = point; 1118d961a43aSToby Isaac } 1119d961a43aSToby Isaac if (childID) { 1120d961a43aSToby Isaac *childID = 0; 1121d961a43aSToby Isaac } 1122d961a43aSToby Isaac PetscFunctionReturn(0); 1123d961a43aSToby Isaac } 1124d961a43aSToby Isaac 1125d961a43aSToby Isaac /*@C 1126eaf898f9SPatrick Sanan DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the DAG) 1127d961a43aSToby Isaac 1128d961a43aSToby Isaac Input Parameters: 1129d961a43aSToby Isaac + dm - the DMPlex object 1130d961a43aSToby Isaac - point - the query point 1131d961a43aSToby Isaac 1132d961a43aSToby Isaac Output Parameters: 1133d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 1134d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 1135d961a43aSToby Isaac 1136d961a43aSToby Isaac Level: intermediate 1137d961a43aSToby Isaac 1138d961a43aSToby Isaac Fortran Notes: 1139d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1140d961a43aSToby Isaac include petsc.h90 in your code. 1141d961a43aSToby Isaac 1142db781477SPatrick Sanan .seealso: `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeParent()` 1143d961a43aSToby Isaac @*/ 1144d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1145d961a43aSToby Isaac { 1146d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1147d961a43aSToby Isaac PetscSection childSec; 1148d961a43aSToby Isaac PetscInt dof = 0; 1149d961a43aSToby Isaac 1150d961a43aSToby Isaac PetscFunctionBegin; 1151d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1152d961a43aSToby Isaac childSec = mesh->childSection; 1153d961a43aSToby Isaac if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 11549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof (childSec, point, &dof)); 1155d961a43aSToby Isaac } 1156d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1157d961a43aSToby Isaac if (children) { 1158d961a43aSToby Isaac if (dof) { 1159d961a43aSToby Isaac PetscInt off; 1160d961a43aSToby Isaac 11619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset (childSec, point, &off)); 1162d961a43aSToby Isaac *children = &mesh->children[off]; 1163d961a43aSToby Isaac } 1164d961a43aSToby Isaac else { 1165d961a43aSToby Isaac *children = NULL; 1166d961a43aSToby Isaac } 1167d961a43aSToby Isaac } 1168d961a43aSToby Isaac PetscFunctionReturn(0); 1169d961a43aSToby Isaac } 11700c37af3bSToby Isaac 117152a3aeb4SToby Isaac 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) 1172b3a4bf2aSToby Isaac { 117352a3aeb4SToby Isaac PetscInt f, b, p, c, offset, qPoints; 1174b3a4bf2aSToby Isaac 1175b3a4bf2aSToby Isaac PetscFunctionBegin; 11769566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(space,nPoints,points,work,NULL,NULL)); 117752a3aeb4SToby Isaac for (f = 0, offset = 0; f < nFunctionals; f++) { 117852a3aeb4SToby Isaac qPoints = pointsPerFn[f]; 117952a3aeb4SToby Isaac for (b = 0; b < nBasis; b++) { 1180b3a4bf2aSToby Isaac PetscScalar val = 0.; 1181b3a4bf2aSToby Isaac 118252a3aeb4SToby Isaac for (p = 0; p < qPoints; p++) { 118352a3aeb4SToby Isaac for (c = 0; c < nComps; c++) { 118452a3aeb4SToby Isaac val += work[((offset + p) * nBasis + b) * nComps + c] * weights[(offset + p) * nComps + c]; 1185b3a4bf2aSToby Isaac } 118652a3aeb4SToby Isaac } 11879566063dSJacob Faibussowitsch PetscCall(MatSetValue(basisAtPoints,b,f,val,INSERT_VALUES)); 1188b3a4bf2aSToby Isaac } 1189b3a4bf2aSToby Isaac offset += qPoints; 1190b3a4bf2aSToby Isaac } 11919566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(basisAtPoints,MAT_FINAL_ASSEMBLY)); 11929566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(basisAtPoints,MAT_FINAL_ASSEMBLY)); 1193b3a4bf2aSToby Isaac PetscFunctionReturn(0); 1194b3a4bf2aSToby Isaac } 1195b3a4bf2aSToby Isaac 1196f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 11970c37af3bSToby Isaac { 11980c37af3bSToby Isaac PetscDS ds; 11990c37af3bSToby Isaac PetscInt spdim; 12000c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 12010c37af3bSToby Isaac const PetscInt *anchors; 1202f7c74593SToby Isaac PetscSection aSec; 12030c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 12040c37af3bSToby Isaac IS aIS; 12050c37af3bSToby Isaac 12060c37af3bSToby Isaac PetscFunctionBegin; 12079566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm,&pStart,&pEnd)); 12089566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm,&ds)); 12099566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds,&numFields)); 12109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,0,&cStart,&cEnd)); 12119566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS)); 12129566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 12139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec,&conStart,&conEnd)); 12149566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&spdim)); 12159566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent)); 12160c37af3bSToby Isaac 12170c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 12180dd1b1feSToby Isaac PetscObject disc; 12190dd1b1feSToby Isaac PetscClassId id; 1220b3a4bf2aSToby Isaac PetscSpace bspace; 1221b3a4bf2aSToby Isaac PetscDualSpace dspace; 12229c3cf19fSMatthew G. Knepley PetscInt i, j, k, nPoints, Nc, offset; 122352a3aeb4SToby Isaac PetscInt fSize, maxDof; 1224b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 12251683a169SBarry Smith PetscScalar *scwork; 12261683a169SBarry Smith const PetscScalar *X; 12272c44ad04SToby Isaac PetscInt *sizes, *workIndRow, *workIndCol; 12280c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 12292c44ad04SToby Isaac const PetscInt *numDof = NULL; 1230085f0adfSToby Isaac const PetscInt ***perms = NULL; 1231085f0adfSToby Isaac const PetscScalar ***flips = NULL; 12320c37af3bSToby Isaac 12339566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds,f,&disc)); 12349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc,&id)); 12350dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1236b3a4bf2aSToby Isaac PetscFE fe = (PetscFE) disc; 1237b3a4bf2aSToby Isaac 12389566063dSJacob Faibussowitsch PetscCall(PetscFEGetBasisSpace(fe,&bspace)); 12399566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe,&dspace)); 12409566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace,&fSize)); 12419566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe,&Nc)); 12420dd1b1feSToby Isaac } 12430dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 1244b3a4bf2aSToby Isaac PetscFV fv = (PetscFV) disc; 1245b3a4bf2aSToby Isaac 12469566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv,&Nc)); 12479566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)fv),&bspace)); 12489566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(bspace,PETSCSPACEPOLYNOMIAL)); 12499566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(bspace,0,PETSC_DETERMINE)); 12509566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(bspace,Nc)); 12519566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(bspace,spdim)); 12529566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(bspace)); 12539566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv,&dspace)); 12549566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace,&fSize)); 12550dd1b1feSToby Isaac } 125698921bdaSJacob Faibussowitsch else SETERRQ(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 12579566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dspace,&numDof)); 12582c44ad04SToby Isaac for (i = 0, maxDof = 0; i <= spdim; i++) {maxDof = PetscMax(maxDof,numDof[i]);} 12599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dspace,&perms,&flips)); 12600dd1b1feSToby Isaac 12619566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,&Amat)); 12629566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Amat,fSize,fSize,fSize,fSize)); 12639566063dSJacob Faibussowitsch PetscCall(MatSetType(Amat,MATSEQDENSE)); 12649566063dSJacob Faibussowitsch PetscCall(MatSetUp(Amat)); 12659566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat)); 12669566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat)); 12670c37af3bSToby Isaac nPoints = 0; 12680c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 126952a3aeb4SToby Isaac PetscInt qPoints, thisNc; 12700c37af3bSToby Isaac PetscQuadrature quad; 12710c37af3bSToby Isaac 12729566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace,i,&quad)); 12739566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad,NULL,&thisNc,&qPoints,NULL,NULL)); 127463a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT,thisNc,Nc); 12750c37af3bSToby Isaac nPoints += qPoints; 12760c37af3bSToby Isaac } 12779566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(fSize,&sizes,nPoints*Nc,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal,nPoints*fSize*Nc,&work,maxDof,&workIndRow,maxDof,&workIndCol)); 12789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof,&scwork)); 12790c37af3bSToby Isaac offset = 0; 12800c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12810c37af3bSToby Isaac PetscInt qPoints; 12820c37af3bSToby Isaac const PetscReal *p, *w; 12830c37af3bSToby Isaac PetscQuadrature quad; 12840c37af3bSToby Isaac 12859566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace,i,&quad)); 12869566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad,NULL,NULL,&qPoints,&p,&w)); 12879566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(weights+Nc*offset,w,Nc*qPoints)); 12889566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pointsRef+spdim*offset,p,spdim*qPoints)); 1289b3a4bf2aSToby Isaac sizes[i] = qPoints; 12900c37af3bSToby Isaac offset += qPoints; 12910c37af3bSToby Isaac } 12929566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace,fSize,fSize,Nc,nPoints,sizes,pointsRef,weights,work,Amat)); 12939566063dSJacob Faibussowitsch PetscCall(MatLUFactor(Amat,NULL,NULL,NULL)); 12940c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 12950c37af3bSToby Isaac PetscInt parent; 12960c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 12970c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 12980c37af3bSToby Isaac 12999566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,c,&parent,NULL)); 13000c37af3bSToby Isaac if (parent == c) continue; 13019566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure)); 13020c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13030c37af3bSToby Isaac PetscInt p = closure[2*i]; 13040c37af3bSToby Isaac PetscInt conDof; 13050c37af3bSToby Isaac 13060c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1307085f0adfSToby Isaac if (numFields) { 13089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&conDof)); 13090c37af3bSToby Isaac } 13100c37af3bSToby Isaac else { 13119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&conDof)); 13120c37af3bSToby Isaac } 13130c37af3bSToby Isaac if (conDof) break; 13140c37af3bSToby Isaac } 13150c37af3bSToby Isaac if (i == closureSize) { 13169566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure)); 13170c37af3bSToby Isaac continue; 13180c37af3bSToby Isaac } 13190c37af3bSToby Isaac 13209566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ)); 13219566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent)); 13220c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1323c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 1324c330f8ffSToby Isaac 1325c330f8ffSToby Isaac CoordinatesRefToReal(spdim, spdim, xi0, v0, J, &pointsRef[i*spdim],vtmp); 1326c330f8ffSToby Isaac CoordinatesRealToRef(spdim, spdim, xi0, v0parent, invJparent, vtmp, &pointsReal[i*spdim]); 13270c37af3bSToby Isaac } 13289566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace,fSize,fSize,Nc,nPoints,sizes,pointsReal,weights,work,Bmat)); 13299566063dSJacob Faibussowitsch PetscCall(MatMatSolve(Amat,Bmat,Xmat)); 13309566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Xmat,&X)); 13319566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP)); 13329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets)); 13330c37af3bSToby Isaac childOffsets[0] = 0; 13340c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13350c37af3bSToby Isaac PetscInt p = closure[2*i]; 13360c37af3bSToby Isaac PetscInt dof; 13370c37af3bSToby Isaac 1338085f0adfSToby Isaac if (numFields) { 13399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,p,f,&dof)); 13400c37af3bSToby Isaac } 13410c37af3bSToby Isaac else { 13429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,p,&dof)); 13430c37af3bSToby Isaac } 134452a3aeb4SToby Isaac childOffsets[i+1]=childOffsets[i]+dof; 13450c37af3bSToby Isaac } 13460c37af3bSToby Isaac parentOffsets[0] = 0; 13470c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 13480c37af3bSToby Isaac PetscInt p = closureP[2*i]; 13490c37af3bSToby Isaac PetscInt dof; 13500c37af3bSToby Isaac 1351085f0adfSToby Isaac if (numFields) { 13529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,p,f,&dof)); 13530c37af3bSToby Isaac } 13540c37af3bSToby Isaac else { 13559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,p,&dof)); 13560c37af3bSToby Isaac } 135752a3aeb4SToby Isaac parentOffsets[i+1]=parentOffsets[i]+dof; 13580c37af3bSToby Isaac } 13590c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13602c44ad04SToby Isaac PetscInt conDof, conOff, aDof, aOff, nWork; 13610c37af3bSToby Isaac PetscInt p = closure[2*i]; 13620c37af3bSToby Isaac PetscInt o = closure[2*i+1]; 1363085f0adfSToby Isaac const PetscInt *perm; 1364085f0adfSToby Isaac const PetscScalar *flip; 13650c37af3bSToby Isaac 13660c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1367085f0adfSToby Isaac if (numFields) { 13689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&conDof)); 13699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&conOff)); 13700c37af3bSToby Isaac } 13710c37af3bSToby Isaac else { 13729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&conDof)); 13739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec,p,&conOff)); 13740c37af3bSToby Isaac } 13750c37af3bSToby Isaac if (!conDof) continue; 1376085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL; 1377085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL; 13789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&aDof)); 13799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&aOff)); 13802c44ad04SToby Isaac nWork = childOffsets[i+1]-childOffsets[i]; 13810c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 13820c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 13830c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 13840c37af3bSToby Isaac 1385085f0adfSToby Isaac if (numFields) { 13869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,a,f,&aSecDof)); 13879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section,a,f,&aSecOff)); 13880c37af3bSToby Isaac } 13890c37af3bSToby Isaac else { 13909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,a,&aSecDof)); 13919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,a,&aSecOff)); 13920c37af3bSToby Isaac } 13930c37af3bSToby Isaac if (!aSecDof) continue; 13940c37af3bSToby Isaac 13950c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 13960c37af3bSToby Isaac PetscInt q = closureP[2*j]; 13970c37af3bSToby Isaac PetscInt oq = closureP[2*j+1]; 13982c44ad04SToby Isaac 13992c44ad04SToby Isaac if (q == a) { 140052a3aeb4SToby Isaac PetscInt r, s, nWorkP; 1401085f0adfSToby Isaac const PetscInt *permP; 1402085f0adfSToby Isaac const PetscScalar *flipP; 1403085f0adfSToby Isaac 1404085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL; 1405085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL; 14062c44ad04SToby Isaac nWorkP = parentOffsets[j+1]-parentOffsets[j]; 14072c44ad04SToby Isaac /* get a copy of the child-to-anchor portion of the matrix, and transpose so that rows correspond to the 14081683a169SBarry Smith * child and columns correspond to the anchor: BUT the maxrix returned by MatDenseGetArrayRead() is 14092c44ad04SToby Isaac * column-major, so transpose-transpose = do nothing */ 14102c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14112c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14122c44ad04SToby Isaac scwork[r * nWorkP + s] = X[fSize * (r + childOffsets[i]) + (s + parentOffsets[j])]; 14132c44ad04SToby Isaac } 14142c44ad04SToby Isaac } 141552a3aeb4SToby Isaac for (r = 0; r < nWork; r++) {workIndRow[perm ? perm[r] : r] = conOff + r;} 141652a3aeb4SToby Isaac for (s = 0; s < nWorkP; s++) {workIndCol[permP ? permP[s] : s] = aSecOff + s;} 14172c44ad04SToby Isaac if (flip) { 14182c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14192c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14202c44ad04SToby Isaac scwork[r * nWorkP + s] *= flip[r]; 14212c44ad04SToby Isaac } 14222c44ad04SToby Isaac } 14232c44ad04SToby Isaac } 14242c44ad04SToby Isaac if (flipP) { 14252c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14262c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14272c44ad04SToby Isaac scwork[r * nWorkP + s] *= flipP[s]; 14282c44ad04SToby Isaac } 14292c44ad04SToby Isaac } 14302c44ad04SToby Isaac } 14319566063dSJacob Faibussowitsch PetscCall(MatSetValues(cMat,nWork,workIndRow,nWorkP,workIndCol,scwork,INSERT_VALUES)); 14322c44ad04SToby Isaac break; 14330c37af3bSToby Isaac } 14340c37af3bSToby Isaac } 14350c37af3bSToby Isaac } 14360c37af3bSToby Isaac } 14379566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Xmat,&X)); 14389566063dSJacob Faibussowitsch PetscCall(PetscFree2(childOffsets,parentOffsets)); 14399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure)); 14409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP)); 14410c37af3bSToby Isaac } 14429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Amat)); 14439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bmat)); 14449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Xmat)); 14459566063dSJacob Faibussowitsch PetscCall(PetscFree(scwork)); 14469566063dSJacob Faibussowitsch PetscCall(PetscFree7(sizes,weights,pointsRef,pointsReal,work,workIndRow,workIndCol)); 1447b3a4bf2aSToby Isaac if (id == PETSCFV_CLASSID) { 14489566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&bspace)); 1449b3a4bf2aSToby Isaac } 14500c37af3bSToby Isaac } 14519566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY)); 14529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY)); 14539566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent)); 14549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 14550c37af3bSToby Isaac 14560c37af3bSToby Isaac PetscFunctionReturn(0); 14570c37af3bSToby Isaac } 145895a0b26dSToby Isaac 145921968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 146095a0b26dSToby Isaac { 1461f7c74593SToby Isaac Mat refCmat; 146221968bf8SToby Isaac PetscDS ds; 1463085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 146421968bf8SToby Isaac PetscScalar ***refPointFieldMats; 146521968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 146621968bf8SToby Isaac IS refAnIS; 146721968bf8SToby Isaac const PetscInt *refAnchors; 1468085f0adfSToby Isaac const PetscInt **perms; 1469085f0adfSToby Isaac const PetscScalar **flips; 147095a0b26dSToby Isaac 147195a0b26dSToby Isaac PetscFunctionBegin; 14729566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree,&ds)); 14739566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds,&numFields)); 1474085f0adfSToby Isaac maxFields = PetscMax(1,numFields); 14759566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&refConSec,&refCmat,NULL)); 14769566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree,&refAnSec,&refAnIS)); 14779566063dSJacob Faibussowitsch PetscCall(ISGetIndices(refAnIS,&refAnchors)); 14789566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree,&refSection)); 14799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 14809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats)); 14819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd-pRefStart,&refPointFieldN)); 14829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec,&maxDof)); 14839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec,&maxAnDof)); 14849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof,&rows)); 14859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof*maxAnDof,&cols)); 148695a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 148795a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 148895a0b26dSToby Isaac 14899566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,p,&parent,NULL)); 14909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec,p,&pDof)); 149195a0b26dSToby Isaac if (!pDof || parent == p) continue; 149295a0b26dSToby Isaac 14939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxFields,&refPointFieldMats[p-pRefStart])); 14949566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxFields,&refPointFieldN[p-pRefStart])); 14959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure)); 1496085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1497085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i; 149895a0b26dSToby Isaac 1499085f0adfSToby Isaac if (f < numFields) { 15009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec,p,f,&cDof)); 15019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec,p,f,&cOff)); 15029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(refSection,f,closureSize,closure,&perms,&flips)); 1503085f0adfSToby Isaac } else { 15049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec,p,&cDof)); 15059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec,p,&cOff)); 15069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(refSection,closureSize,closure,&perms,&flips)); 150795a0b26dSToby Isaac } 150895a0b26dSToby Isaac 150995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 151095a0b26dSToby Isaac rows[r] = cOff + r; 151195a0b26dSToby Isaac } 151295a0b26dSToby Isaac numCols = 0; 151395a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 151495a0b26dSToby Isaac PetscInt q = closure[2*i]; 151595a0b26dSToby Isaac PetscInt aDof, aOff, j; 1516085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 151795a0b26dSToby Isaac 1518085f0adfSToby Isaac if (numFields) { 15199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection,q,f,&aDof)); 15209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection,q,f,&aOff)); 152195a0b26dSToby Isaac } 152295a0b26dSToby Isaac else { 15239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection,q,&aDof)); 15249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection,q,&aOff)); 152595a0b26dSToby Isaac } 152695a0b26dSToby Isaac 152795a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 1528085f0adfSToby Isaac cols[numCols++] = aOff + (perm ? perm[j] : j); 152995a0b26dSToby Isaac } 153095a0b26dSToby Isaac } 153195a0b26dSToby Isaac refPointFieldN[p-pRefStart][f] = numCols; 15329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f])); 15339566063dSJacob Faibussowitsch PetscCall(MatGetValues(refCmat,cDof,rows,numCols,cols,refPointFieldMats[p-pRefStart][f])); 1534085f0adfSToby Isaac if (flips) { 1535085f0adfSToby Isaac PetscInt colOff = 0; 1536085f0adfSToby Isaac 1537085f0adfSToby Isaac for (i = 0; i < closureSize; i++) { 1538085f0adfSToby Isaac PetscInt q = closure[2*i]; 1539085f0adfSToby Isaac PetscInt aDof, aOff, j; 1540085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 1541085f0adfSToby Isaac 1542085f0adfSToby Isaac if (numFields) { 15439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection,q,f,&aDof)); 15449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection,q,f,&aOff)); 1545085f0adfSToby Isaac } 1546085f0adfSToby Isaac else { 15479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection,q,&aDof)); 15489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection,q,&aOff)); 1549085f0adfSToby Isaac } 1550085f0adfSToby Isaac if (flip) { 1551085f0adfSToby Isaac PetscInt k; 1552085f0adfSToby Isaac for (k = 0; k < cDof; k++) { 1553085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1554085f0adfSToby Isaac refPointFieldMats[p-pRefStart][f][k * numCols + colOff + j] *= flip[j]; 1555085f0adfSToby Isaac } 1556085f0adfSToby Isaac } 1557085f0adfSToby Isaac } 1558085f0adfSToby Isaac colOff += aDof; 1559085f0adfSToby Isaac } 1560085f0adfSToby Isaac } 1561085f0adfSToby Isaac if (numFields) { 15629566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(refSection,f,closureSize,closure,&perms,&flips)); 1563085f0adfSToby Isaac } else { 15649566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(refSection,closureSize,closure,&perms,&flips)); 1565085f0adfSToby Isaac } 156695a0b26dSToby Isaac } 15679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure)); 156895a0b26dSToby Isaac } 156921968bf8SToby Isaac *childrenMats = refPointFieldMats; 157021968bf8SToby Isaac *childrenN = refPointFieldN; 15719566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(refAnIS,&refAnchors)); 15729566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 15739566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 157421968bf8SToby Isaac PetscFunctionReturn(0); 157521968bf8SToby Isaac } 157621968bf8SToby Isaac 157721968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 157821968bf8SToby Isaac { 157921968bf8SToby Isaac PetscDS ds; 158021968bf8SToby Isaac PetscInt **refPointFieldN; 158121968bf8SToby Isaac PetscScalar ***refPointFieldMats; 1582085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f; 158321968bf8SToby Isaac PetscSection refConSec; 158421968bf8SToby Isaac 158521968bf8SToby Isaac PetscFunctionBegin; 158621968bf8SToby Isaac refPointFieldN = *childrenN; 158721968bf8SToby Isaac *childrenN = NULL; 158821968bf8SToby Isaac refPointFieldMats = *childrenMats; 158921968bf8SToby Isaac *childrenMats = NULL; 15909566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree,&ds)); 15919566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds,&numFields)); 1592367003a6SStefano Zampini maxFields = PetscMax(1,numFields); 15939566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 15949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 159521968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 159621968bf8SToby Isaac PetscInt parent, pDof; 159721968bf8SToby Isaac 15989566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,p,&parent,NULL)); 15999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec,p,&pDof)); 160021968bf8SToby Isaac if (!pDof || parent == p) continue; 160121968bf8SToby Isaac 1602085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 160321968bf8SToby Isaac PetscInt cDof; 160421968bf8SToby Isaac 1605085f0adfSToby Isaac if (numFields) { 16069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec,p,f,&cDof)); 160721968bf8SToby Isaac } 160821968bf8SToby Isaac else { 16099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec,p,&cDof)); 161021968bf8SToby Isaac } 161121968bf8SToby Isaac 16129566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 161321968bf8SToby Isaac } 16149566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 16159566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN[p - pRefStart])); 161621968bf8SToby Isaac } 16179566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 16189566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN)); 161921968bf8SToby Isaac PetscFunctionReturn(0); 162021968bf8SToby Isaac } 162121968bf8SToby Isaac 162221968bf8SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 162321968bf8SToby Isaac { 162421968bf8SToby Isaac DM refTree; 162521968bf8SToby Isaac PetscDS ds; 162621968bf8SToby Isaac Mat refCmat; 1627085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 162821968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 162921968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 163021968bf8SToby Isaac IS refAnIS, anIS; 163121968bf8SToby Isaac const PetscInt *anchors; 163221968bf8SToby Isaac 163321968bf8SToby Isaac PetscFunctionBegin; 163421968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 16359566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm,&ds)); 16369566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds,&numFields)); 1637085f0adfSToby Isaac maxFields = PetscMax(1,numFields); 16389566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm,&refTree)); 16399566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm,refTree)); 16409566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&refConSec,&refCmat,NULL)); 16419566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree,&refAnSec,&refAnIS)); 16429566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm,&anSec,&anIS)); 16439566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anIS,&anchors)); 16449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 16459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(conSec,&conStart,&conEnd)); 16469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec,&maxDof)); 16479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec,&maxAnDof)); 16489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof*maxDof*maxAnDof,&pointWork)); 164921968bf8SToby Isaac 165021968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 16519566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 165295a0b26dSToby Isaac 165395a0b26dSToby Isaac /* step 2: compute the preorder */ 16549566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm,&pStart,&pEnd)); 16559566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd-pStart,&perm,pEnd-pStart,&iperm)); 165695a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 165795a0b26dSToby Isaac perm[p - pStart] = p; 165895a0b26dSToby Isaac iperm[p - pStart] = p-pStart; 165995a0b26dSToby Isaac } 166095a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 166195a0b26dSToby Isaac PetscInt point = perm[p]; 166295a0b26dSToby Isaac PetscInt parent; 166395a0b26dSToby Isaac 16649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,point,&parent,NULL)); 166595a0b26dSToby Isaac if (parent == point) { 166695a0b26dSToby Isaac p++; 166795a0b26dSToby Isaac } 166895a0b26dSToby Isaac else { 166995a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 167095a0b26dSToby Isaac 16719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 167295a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 167395a0b26dSToby Isaac PetscInt q = closure[2*i]; 167495a0b26dSToby Isaac if (iperm[q-pStart] > iperm[point-pStart]) { 167595a0b26dSToby Isaac /* swap */ 167695a0b26dSToby Isaac perm[p] = q; 167795a0b26dSToby Isaac perm[iperm[q-pStart]] = point; 167895a0b26dSToby Isaac iperm[point-pStart] = iperm[q-pStart]; 167995a0b26dSToby Isaac iperm[q-pStart] = p; 168095a0b26dSToby Isaac break; 168195a0b26dSToby Isaac } 168295a0b26dSToby Isaac } 168395a0b26dSToby Isaac size = closureSize; 16849566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 168595a0b26dSToby Isaac if (i == size) { 168695a0b26dSToby Isaac p++; 168795a0b26dSToby Isaac } 168895a0b26dSToby Isaac } 168995a0b26dSToby Isaac } 169095a0b26dSToby Isaac 169195a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 169295a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 169395a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 169495a0b26dSToby Isaac * values outside of the Mat first. 169595a0b26dSToby Isaac */ 169695a0b26dSToby Isaac { 169795a0b26dSToby Isaac PetscInt nRows, row, nnz; 169895a0b26dSToby Isaac PetscBool done; 169995a0b26dSToby Isaac const PetscInt *ia, *ja; 170095a0b26dSToby Isaac PetscScalar *vals; 170195a0b26dSToby Isaac 17029566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done)); 170328b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not get RowIJ of constraint matrix"); 170495a0b26dSToby Isaac nnz = ia[nRows]; 170595a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 170695a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 17079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&vals)); 170895a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 170995a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 171095a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 171195a0b26dSToby Isaac 17129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,point,&parent,&childid)); 171395a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 17149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec,point,&pointDof)); 171595a0b26dSToby Isaac if (!pointDof) continue; 17169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 1717085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1718085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 171995a0b26dSToby Isaac PetscScalar *pointMat; 1720085f0adfSToby Isaac const PetscInt **perms; 1721085f0adfSToby Isaac const PetscScalar **flips; 172295a0b26dSToby Isaac 1723085f0adfSToby Isaac if (numFields) { 17249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec,point,f,&cDof)); 17259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec,point,f,&cOff)); 172695a0b26dSToby Isaac } 172795a0b26dSToby Isaac else { 17289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec,point,&cDof)); 17299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec,point,&cOff)); 173095a0b26dSToby Isaac } 173195a0b26dSToby Isaac if (!cDof) continue; 17329566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(section,f,closureSize,closure,&perms,&flips)); 17339566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section,closureSize,closure,&perms,&flips)); 173495a0b26dSToby Isaac 173595a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 173676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 173795a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 173895a0b26dSToby Isaac if (cDof > 1 && r) { 173963a3b9bcSJacob 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])); 174095a0b26dSToby Isaac } 174195a0b26dSToby Isaac } 174276bd3646SJed Brown } 174395a0b26dSToby Isaac /* zero rows */ 174495a0b26dSToby Isaac for (i = ia[cOff] ; i< ia[cOff+cDof];i++) { 174595a0b26dSToby Isaac vals[i] = 0.; 174695a0b26dSToby Isaac } 174795a0b26dSToby Isaac matOffset = ia[cOff]; 174895a0b26dSToby Isaac numFillCols = ia[cOff+1] - matOffset; 174995a0b26dSToby Isaac pointMat = refPointFieldMats[childid-pRefStart][f]; 175095a0b26dSToby Isaac numCols = refPointFieldN[childid-pRefStart][f]; 175195a0b26dSToby Isaac offset = 0; 175295a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 175395a0b26dSToby Isaac PetscInt q = closure[2*i]; 175495a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 1755085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1756085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 175795a0b26dSToby Isaac 175895a0b26dSToby Isaac qConDof = qConOff = 0; 1759085f0adfSToby Isaac if (numFields) { 17609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,q,f,&aDof)); 17619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section,q,f,&aOff)); 176295a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 17639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec,q,f,&qConDof)); 17649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec,q,f,&qConOff)); 176595a0b26dSToby Isaac } 176695a0b26dSToby Isaac } 176795a0b26dSToby Isaac else { 17689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,q,&aDof)); 17699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,q,&aOff)); 177095a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 17719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec,q,&qConDof)); 17729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec,q,&qConOff)); 177395a0b26dSToby Isaac } 177495a0b26dSToby Isaac } 177595a0b26dSToby Isaac if (!aDof) continue; 177695a0b26dSToby Isaac if (qConDof) { 177795a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 177895a0b26dSToby Isaac * be filled, thanks to preordering */ 177995a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 178095a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 178195a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 178295a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 178395a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 178495a0b26dSToby Isaac PetscScalar inVal = 0; 178595a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1786085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 178795a0b26dSToby Isaac 1788085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 178995a0b26dSToby Isaac } 179095a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 179195a0b26dSToby Isaac } 179295a0b26dSToby Isaac } 179395a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 179495a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 179595a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 179695a0b26dSToby Isaac for (;k < numFillCols; k++) { 179795a0b26dSToby Isaac if (ja[matOffset + k] == col) { 179895a0b26dSToby Isaac break; 179995a0b26dSToby Isaac } 180095a0b26dSToby Isaac } 180163a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols,PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, col); 180295a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 180395a0b26dSToby Isaac vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 180495a0b26dSToby Isaac } 180595a0b26dSToby Isaac } 180695a0b26dSToby Isaac } 180795a0b26dSToby Isaac else { 180895a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 180995a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 181095a0b26dSToby Isaac if (ja[matOffset + k] == aOff) { 181195a0b26dSToby Isaac break; 181295a0b26dSToby Isaac } 181395a0b26dSToby Isaac } 181463a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols,PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, aOff); 181595a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1816085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1817085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1818085f0adfSToby Isaac 1819085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 182095a0b26dSToby Isaac } 182195a0b26dSToby Isaac } 182295a0b26dSToby Isaac } 182395a0b26dSToby Isaac offset += aDof; 182495a0b26dSToby Isaac } 1825085f0adfSToby Isaac if (numFields) { 18269566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section,f,closureSize,closure,&perms,&flips)); 1827085f0adfSToby Isaac } else { 18289566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section,closureSize,closure,&perms,&flips)); 1829085f0adfSToby Isaac } 183095a0b26dSToby Isaac } 18319566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 183295a0b26dSToby Isaac } 183395a0b26dSToby Isaac for (row = 0; row < nRows; row++) { 18349566063dSJacob Faibussowitsch PetscCall(MatSetValues(cMat,1,&row,ia[row+1]-ia[row],&ja[ia[row]],&vals[ia[row]],INSERT_VALUES)); 183595a0b26dSToby Isaac } 18369566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done)); 183728b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not restore RowIJ of constraint matrix"); 18389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY)); 18399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY)); 18409566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 184195a0b26dSToby Isaac } 184295a0b26dSToby Isaac 184395a0b26dSToby Isaac /* clean up */ 18449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anIS,&anchors)); 18459566063dSJacob Faibussowitsch PetscCall(PetscFree2(perm,iperm)); 18469566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 18479566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 184895a0b26dSToby Isaac PetscFunctionReturn(0); 184995a0b26dSToby Isaac } 185095a0b26dSToby Isaac 18516f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 18526f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 18536f5f1567SToby Isaac PetscErrorCode DMPlexTreeRefineCell (DM dm, PetscInt cell, DM *ncdm) 18546f5f1567SToby Isaac { 18556f5f1567SToby Isaac DM K; 1856420f55faSMatthew G. Knepley PetscMPIInt rank; 18576f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 18586f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 18596f5f1567SToby Isaac PetscInt *Kembedding; 18606f5f1567SToby Isaac PetscInt *cellClosure=NULL, nc; 18616f5f1567SToby Isaac PetscScalar *newVertexCoords; 18626f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 18636f5f1567SToby Isaac PetscSection parentSection; 18646f5f1567SToby Isaac 18656f5f1567SToby Isaac PetscFunctionBegin; 18669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank)); 18679566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&dim)); 18689566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm)); 18699566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ncdm,dim)); 18706f5f1567SToby Isaac 18719566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 18729566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm),&parentSection)); 18739566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm,&K)); 1874dd400576SPatrick Sanan if (rank == 0) { 18756f5f1567SToby Isaac /* compute the new charts */ 18769566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim+1,&pNewCount,dim+1,&pNewStart,dim+1,&pNewEnd,dim+1,&pOldStart,dim+1,&pOldEnd)); 18776f5f1567SToby Isaac offset = 0; 18786f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18796f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 18806f5f1567SToby Isaac 18816f5f1567SToby Isaac pNewStart[d] = offset; 18829566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,d,&pOldStart[d],&pOldEnd[d])); 18839566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K,d,&kStart,&kEnd)); 18846f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 18856f5f1567SToby Isaac /* adding the new points */ 18866f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 18876f5f1567SToby Isaac if (!d) { 18886f5f1567SToby Isaac /* removing the cell */ 18896f5f1567SToby Isaac pNewCount[d]--; 18906f5f1567SToby Isaac } 18916f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18926f5f1567SToby Isaac PetscInt parent; 18939566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K,k,&parent,NULL)); 18946f5f1567SToby Isaac if (parent == k) { 18956f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 18966f5f1567SToby Isaac pNewCount[d]--; 18976f5f1567SToby Isaac } 18986f5f1567SToby Isaac } 18996f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 19006f5f1567SToby Isaac offset = pNewEnd[d]; 19016f5f1567SToby Isaac 19026f5f1567SToby Isaac } 19031dca8a05SBarry 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]); 19046f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 19059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure)); 19066f5f1567SToby Isaac 19079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pNewEnd[dim],&newConeSizes)); 19086f5f1567SToby Isaac { 1909b5a892a1SMatthew G. Knepley DMPolytopeType pct, qct; 19106f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 19116f5f1567SToby Isaac 19129566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K,&kStart,&kEnd)); 19139566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(kEnd-kStart,&Kembedding,kEnd-kStart,&perm,kEnd-kStart,&iperm,kEnd-kStart,&preOrient)); 19146f5f1567SToby Isaac 19156f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19166f5f1567SToby Isaac perm[k - kStart] = k; 19176f5f1567SToby Isaac iperm [k - kStart] = k - kStart; 19186f5f1567SToby Isaac preOrient[k - kStart] = 0; 19196f5f1567SToby Isaac } 19206f5f1567SToby Isaac 19219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK)); 19226f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 19236f5f1567SToby Isaac PetscInt parentOrientA = closureK[2*j+1]; 19246f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2*j+1]; 19256f5f1567SToby Isaac PetscInt p, q; 19266f5f1567SToby Isaac 19276f5f1567SToby Isaac p = closureK[2*j]; 19286f5f1567SToby Isaac q = cellClosure[2*j]; 19299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, p, &pct)); 19309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, q, &qct)); 19316f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19326f5f1567SToby Isaac if (q >= pOldStart[d] && q < pOldEnd[d]) { 19336f5f1567SToby Isaac Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 19346f5f1567SToby Isaac } 19356f5f1567SToby Isaac } 1936b5a892a1SMatthew G. Knepley parentOrientA = DMPolytopeConvertNewOrientation_Internal(pct, parentOrientA); 1937b5a892a1SMatthew G. Knepley parentOrientB = DMPolytopeConvertNewOrientation_Internal(qct, parentOrientB); 19386f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 19396f5f1567SToby Isaac PetscInt numChildren, i; 19406f5f1567SToby Isaac const PetscInt *children; 19416f5f1567SToby Isaac 19429566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(K,p,&numChildren,&children)); 19436f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 19446f5f1567SToby Isaac PetscInt kPerm, oPerm; 19456f5f1567SToby Isaac 19466f5f1567SToby Isaac k = children[i]; 19479566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(K,p,parentOrientA,0,k,parentOrientB,&oPerm,&kPerm)); 19486f5f1567SToby Isaac /* perm = what refTree position I'm in */ 19496f5f1567SToby Isaac perm[kPerm-kStart] = k; 19506f5f1567SToby Isaac /* iperm = who is at this position */ 19516f5f1567SToby Isaac iperm[k-kStart] = kPerm-kStart; 19526f5f1567SToby Isaac preOrient[kPerm-kStart] = oPerm; 19536f5f1567SToby Isaac } 19546f5f1567SToby Isaac } 19556f5f1567SToby Isaac } 19569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK)); 19576f5f1567SToby Isaac } 19589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection,0,pNewEnd[dim])); 19596f5f1567SToby Isaac offset = 0; 19606f5f1567SToby Isaac numNewCones = 0; 19616f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19626f5f1567SToby Isaac PetscInt kStart, kEnd, k; 19636f5f1567SToby Isaac PetscInt p; 19646f5f1567SToby Isaac PetscInt size; 19656f5f1567SToby Isaac 19666f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19676f5f1567SToby Isaac /* skip cell 0 */ 19686f5f1567SToby Isaac if (p == cell) continue; 19696f5f1567SToby Isaac /* old cones to new cones */ 19709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,p,&size)); 19716f5f1567SToby Isaac newConeSizes[offset++] = size; 19726f5f1567SToby Isaac numNewCones += size; 19736f5f1567SToby Isaac } 19746f5f1567SToby Isaac 19759566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K,d,&kStart,&kEnd)); 19766f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19776f5f1567SToby Isaac PetscInt kParent; 19786f5f1567SToby Isaac 19799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K,k,&kParent,NULL)); 19806f5f1567SToby Isaac if (kParent != k) { 19816f5f1567SToby Isaac Kembedding[k] = offset; 19829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K,k,&size)); 19836f5f1567SToby Isaac newConeSizes[offset++] = size; 19846f5f1567SToby Isaac numNewCones += size; 19856f5f1567SToby Isaac if (kParent != 0) { 19869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(parentSection,Kembedding[k],1)); 19876f5f1567SToby Isaac } 19886f5f1567SToby Isaac } 19896f5f1567SToby Isaac } 19906f5f1567SToby Isaac } 19916f5f1567SToby Isaac 19929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 19939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection,&numPointsWithParents)); 19949566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numNewCones,&newCones,numNewCones,&newOrientations)); 19959566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPointsWithParents,&parents,numPointsWithParents,&childIDs)); 19966f5f1567SToby Isaac 19976f5f1567SToby Isaac /* fill new cones */ 19986f5f1567SToby Isaac offset = 0; 19996f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20006f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 20016f5f1567SToby Isaac PetscInt p; 20026f5f1567SToby Isaac PetscInt size; 20036f5f1567SToby Isaac const PetscInt *cone, *orientation; 20046f5f1567SToby Isaac 20056f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 20066f5f1567SToby Isaac /* skip cell 0 */ 20076f5f1567SToby Isaac if (p == cell) continue; 20086f5f1567SToby Isaac /* old cones to new cones */ 20099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,p,&size)); 20109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,p,&cone)); 20119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm,p,&orientation)); 20126f5f1567SToby Isaac for (l = 0; l < size; l++) { 20136f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 20146f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 20156f5f1567SToby Isaac } 20166f5f1567SToby Isaac } 20176f5f1567SToby Isaac 20189566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K,d,&kStart,&kEnd)); 20196f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20206f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 20216f5f1567SToby Isaac PetscInt preO = preOrient[k]; 20226f5f1567SToby Isaac 20239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K,k,&kParent,NULL)); 20246f5f1567SToby Isaac if (kParent != k) { 20256f5f1567SToby Isaac /* embed new cones */ 20269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K,k,&size)); 20279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K,kPerm,&cone)); 20289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K,kPerm,&orientation)); 20296f5f1567SToby Isaac for (l = 0; l < size; l++) { 20306f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size -(preO + 1) - l) % size); 20316f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 2032b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_NUM_POLYTOPES; 20336f5f1567SToby Isaac 20346f5f1567SToby Isaac q = iperm[cone[m]]; 20356f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 20369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K,q,&lSize)); 2037b5a892a1SMatthew G. Knepley if (lSize == 2) ct = DM_POLYTOPE_SEGMENT; 2038b5a892a1SMatthew G. Knepley else if (lSize == 4) ct = DM_POLYTOPE_QUADRILATERAL; 2039b5a892a1SMatthew G. Knepley oTrue = DMPolytopeConvertNewOrientation_Internal(ct, orientation[m]); 20406f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 20416f5f1567SToby Isaac newO = DihedralCompose(lSize,oTrue,preOrient[q]); 2042b5a892a1SMatthew G. Knepley newOrientations[offset++] = DMPolytopeConvertOldOrientation_Internal(ct, newO); 20436f5f1567SToby Isaac } 20446f5f1567SToby Isaac if (kParent != 0) { 20456f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 20469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection,Kembedding[k],&pOffset)); 20476f5f1567SToby Isaac parents[pOffset] = newPoint; 20486f5f1567SToby Isaac childIDs[pOffset] = k; 20496f5f1567SToby Isaac } 20506f5f1567SToby Isaac } 20516f5f1567SToby Isaac } 20526f5f1567SToby Isaac } 20536f5f1567SToby Isaac 20549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim*(pNewEnd[dim]-pNewStart[dim]),&newVertexCoords)); 20556f5f1567SToby Isaac 20566f5f1567SToby Isaac /* fill coordinates */ 20576f5f1567SToby Isaac offset = 0; 20586f5f1567SToby Isaac { 2059d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 20606f5f1567SToby Isaac PetscSection vSection; 20616f5f1567SToby Isaac PetscInt v; 20626f5f1567SToby Isaac Vec coords; 20636f5f1567SToby Isaac PetscScalar *coordvals; 20646f5f1567SToby Isaac PetscInt dof, off; 2065c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 20666f5f1567SToby Isaac 206776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 2068d90620a3SMatthew G. Knepley PetscInt k; 20699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K,0,&kStart,&kEnd)); 20706f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20719566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ)); 207263a3b9bcSJacob Faibussowitsch PetscCheck(detJ > 0.,PETSC_COMM_SELF,PETSC_ERR_PLIB,"reference tree cell %" PetscInt_FMT " has bad determinant",k); 20736f5f1567SToby Isaac } 2074d90620a3SMatthew G. Knepley } 20759566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ)); 20769566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm,&vSection)); 20779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm,&coords)); 20789566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords,&coordvals)); 20796f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 20806f5f1567SToby Isaac 20819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(vSection,v,&dof)); 20829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection,v,&off)); 20836f5f1567SToby Isaac for (l = 0; l < dof; l++) { 20846f5f1567SToby Isaac newVertexCoords[offset++] = coordvals[off + l]; 20856f5f1567SToby Isaac } 20866f5f1567SToby Isaac } 20879566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords,&coordvals)); 20886f5f1567SToby Isaac 20899566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K,&vSection)); 20909566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K,&coords)); 20919566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords,&coordvals)); 20929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K,0,&kStart,&kEnd)); 20936f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 20949bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 20956f5f1567SToby Isaac PetscInt vPerm = perm[v]; 20966f5f1567SToby Isaac PetscInt kParent; 2097c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 20986f5f1567SToby Isaac 20999566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K,v,&kParent,NULL)); 21006f5f1567SToby Isaac if (kParent != v) { 21016f5f1567SToby Isaac /* this is a new vertex */ 21029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection,vPerm,&off)); 21039bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off+l]); 2104367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord); 21059bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset+l] = newCoord[l]; 21066f5f1567SToby Isaac offset += dim; 21076f5f1567SToby Isaac } 21086f5f1567SToby Isaac } 21099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords,&coordvals)); 21106f5f1567SToby Isaac } 21116f5f1567SToby Isaac 21126f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 21136f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 21146f5f1567SToby Isaac PetscInt tmp; 21156f5f1567SToby Isaac 21166f5f1567SToby Isaac tmp = pNewCount[d]; 21176f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 21186f5f1567SToby Isaac pNewCount[dim - d] = tmp; 21196f5f1567SToby Isaac } 21206f5f1567SToby Isaac 21219566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm,dim,pNewCount,newConeSizes,newCones,newOrientations,newVertexCoords)); 21229566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm,K)); 21239566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm,parentSection,parents,childIDs)); 21246f5f1567SToby Isaac 21256f5f1567SToby Isaac /* clean up */ 21269566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure)); 21279566063dSJacob Faibussowitsch PetscCall(PetscFree5(pNewCount,pNewStart,pNewEnd,pOldStart,pOldEnd)); 21289566063dSJacob Faibussowitsch PetscCall(PetscFree(newConeSizes)); 21299566063dSJacob Faibussowitsch PetscCall(PetscFree2(newCones,newOrientations)); 21309566063dSJacob Faibussowitsch PetscCall(PetscFree(newVertexCoords)); 21319566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents,childIDs)); 21329566063dSJacob Faibussowitsch PetscCall(PetscFree4(Kembedding,perm,iperm,preOrient)); 21336f5f1567SToby Isaac } 21346f5f1567SToby Isaac else { 21356f5f1567SToby Isaac PetscInt p, counts[4]; 21366f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 21376f5f1567SToby Isaac Vec coordVec; 21386f5f1567SToby Isaac PetscScalar *coords; 21396f5f1567SToby Isaac 21406f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 21416f5f1567SToby Isaac PetscInt dStart, dEnd; 21426f5f1567SToby Isaac 21439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,d,&dStart,&dEnd)); 21446f5f1567SToby Isaac counts[d] = dEnd - dStart; 21456f5f1567SToby Isaac } 21469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart,&coneSizes)); 21476f5f1567SToby Isaac for (p = pStart; p < pEnd; p++) { 21489566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,p,&coneSizes[p-pStart])); 21496f5f1567SToby Isaac } 21509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 21519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &orientations)); 21529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm,&coordVec)); 21539566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordVec,&coords)); 21546f5f1567SToby Isaac 21559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection,pStart,pEnd)); 21569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 21579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm,dim,counts,coneSizes,cones,orientations,NULL)); 21589566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm,K)); 21599566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm,parentSection,NULL,NULL)); 21609566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordVec,&coords)); 21616f5f1567SToby Isaac } 21629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 21636f5f1567SToby Isaac 21646f5f1567SToby Isaac PetscFunctionReturn(0); 21656f5f1567SToby Isaac } 21666ecaa68aSToby Isaac 21676ecaa68aSToby Isaac PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 21686ecaa68aSToby Isaac { 21696ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 21706ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 21716ecaa68aSToby Isaac PetscSection localCoarse, localFine; 21726ecaa68aSToby Isaac PetscSection aSec, cSec; 21736ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 217446bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 217546bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 217646bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 21776ecaa68aSToby Isaac IS aIS; 21786ecaa68aSToby Isaac const PetscInt *anchors; 21796ecaa68aSToby Isaac Mat cMat; 21804acb8e1eSToby Isaac PetscInt numFields, maxFields; 21816ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 21826ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 21831c58ffc4SToby Isaac PetscInt *maxChildIds; 2184e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 21854acb8e1eSToby Isaac const PetscInt ***perms; 21864acb8e1eSToby Isaac const PetscScalar ***flips; 21876ecaa68aSToby Isaac 21886ecaa68aSToby Isaac PetscFunctionBegin; 21899566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse,&pStartC,&pEndC)); 21909566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine,&pStartF,&pEndF)); 21919566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine,&globalFine)); 21926ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 219389698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 219489698031SToby Isaac const PetscInt *leaves; 21956ecaa68aSToby Isaac 21969566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL)); 219789698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 219889698031SToby Isaac p = leaves ? leaves[l] : l; 21999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&dof)); 22009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 22016ecaa68aSToby Isaac if ((dof - cdof) > 0) { 22026ecaa68aSToby Isaac numPointsWithDofs++; 22036ecaa68aSToby Isaac } 22046ecaa68aSToby Isaac } 22059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs,&pointsWithDofs)); 22067cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 220789698031SToby Isaac p = leaves ? leaves[l] : l; 22089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&dof)); 22099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 22106ecaa68aSToby Isaac if ((dof - cdof) > 0) { 221189698031SToby Isaac pointsWithDofs[offset++] = l; 22126ecaa68aSToby Isaac } 22136ecaa68aSToby Isaac } 22149566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 22159566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 22166ecaa68aSToby Isaac } 22176ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 22189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC-pStartC,&maxChildIds)); 22196ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22208d2f55e7SToby Isaac maxChildIds[p - pStartC] = -2; 22216ecaa68aSToby Isaac } 22229566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX)); 22239566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX)); 222446bdb399SToby Isaac 22259566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse,&localCoarse)); 22269566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse,&globalCoarse)); 222746bdb399SToby Isaac 22289566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse,&aSec,&aIS)); 22299566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 22309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd)); 223146bdb399SToby Isaac 22329566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse,&cSec,&cMat,NULL)); 22339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec,&cStart,&cEnd)); 223446bdb399SToby Isaac 223546bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 22369566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec)); 22379566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootMatricesSec)); 22389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootIndicesSec,pStartC,pEndC)); 22399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootMatricesSec,pStartC,pEndC)); 22409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse,&numFields)); 2241713c1c5dSToby Isaac maxFields = PetscMax(1,numFields); 22429566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields+1,&offsets,maxFields+1,&offsetsCopy,maxFields+1,&newOffsets,maxFields+1,&newOffsetsCopy,maxFields+1,&rowOffsets,maxFields+1,&numD,maxFields+1,&numO)); 22439566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxFields+1,(PetscInt****)&perms,maxFields+1,(PetscScalar****)&flips)); 22449566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *) perms, (maxFields+1) * sizeof(const PetscInt **))); 22459566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *) flips, (maxFields+1) * sizeof(const PetscScalar **))); 224646bdb399SToby Isaac 224746bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 22488d2f55e7SToby Isaac PetscInt dof, matSize = 0; 22496ecaa68aSToby Isaac PetscInt aDof = 0; 22506ecaa68aSToby Isaac PetscInt cDof = 0; 22516ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22526ecaa68aSToby Isaac PetscInt numRowIndices = 0; 22536ecaa68aSToby Isaac PetscInt numColIndices = 0; 2254f13f9184SToby Isaac PetscInt f; 22556ecaa68aSToby Isaac 22569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse,p,&dof)); 22571cfc5b76SToby Isaac if (dof < 0) { 22581cfc5b76SToby Isaac dof = -(dof + 1); 22591cfc5b76SToby Isaac } 22606ecaa68aSToby Isaac if (p >= aStart && p < aEnd) { 22619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&aDof)); 22626ecaa68aSToby Isaac } 22636ecaa68aSToby Isaac if (p >= cStart && p < cEnd) { 22649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec,p,&cDof)); 22656ecaa68aSToby Isaac } 2266f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2267f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 22686ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2269f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 22706ecaa68aSToby Isaac 22719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure)); 227246bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 22736ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 22746ecaa68aSToby Isaac 22759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse,c,&clDof)); 22766ecaa68aSToby Isaac numRowIndices += clDof; 22776ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,c,f,&clDof)); 22796ecaa68aSToby Isaac offsets[f + 1] += clDof; 22806ecaa68aSToby Isaac } 22816ecaa68aSToby Isaac } 22826ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22836ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 22846ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 22856ecaa68aSToby Isaac } 228646bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 22879566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,NULL,NULL,NULL,&numColIndices,NULL,NULL,newOffsets,PETSC_FALSE)); 22889566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure)); 22896ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 22906ecaa68aSToby Isaac numColIndices = numRowIndices; 22916ecaa68aSToby Isaac matSize = 0; 22926ecaa68aSToby Isaac } 229346bdb399SToby Isaac else if (numFields) { /* we send one submat for each field: sum their sizes */ 22946ecaa68aSToby Isaac matSize = 0; 22956ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22966ecaa68aSToby Isaac PetscInt numRow, numCol; 22976ecaa68aSToby Isaac 22986ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2299f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 23006ecaa68aSToby Isaac matSize += numRow * numCol; 23016ecaa68aSToby Isaac } 23026ecaa68aSToby Isaac } 23036ecaa68aSToby Isaac else { 23046ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 23056ecaa68aSToby Isaac } 2306f13f9184SToby Isaac } else if (maxChildId == -1) { 23078d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2308f13f9184SToby Isaac PetscInt aOff, a; 23096ecaa68aSToby Isaac 23109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&aOff)); 23116ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23126ecaa68aSToby Isaac PetscInt fDof; 23136ecaa68aSToby Isaac 23149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 231521968bf8SToby Isaac offsets[f+1] = fDof; 23166ecaa68aSToby Isaac } 23176ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23186ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 23196ecaa68aSToby Isaac 23209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse,anchor,&aLocalDof)); 23216ecaa68aSToby Isaac numColIndices += aLocalDof; 23226ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23236ecaa68aSToby Isaac PetscInt fDof; 23246ecaa68aSToby Isaac 23259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof)); 232621968bf8SToby Isaac newOffsets[f+1] += fDof; 23276ecaa68aSToby Isaac } 23286ecaa68aSToby Isaac } 23296ecaa68aSToby Isaac if (numFields) { 23306ecaa68aSToby Isaac matSize = 0; 23316ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 233221968bf8SToby Isaac matSize += offsets[f+1] * newOffsets[f+1]; 23336ecaa68aSToby Isaac } 23346ecaa68aSToby Isaac } 23356ecaa68aSToby Isaac else { 23366ecaa68aSToby Isaac matSize = numColIndices * dof; 23376ecaa68aSToby Isaac } 23386ecaa68aSToby Isaac } 23396ecaa68aSToby Isaac else { /* no children, and no constraints on dofs: just get the global indices */ 23406ecaa68aSToby Isaac numColIndices = dof; 23416ecaa68aSToby Isaac matSize = 0; 23426ecaa68aSToby Isaac } 23438d2f55e7SToby Isaac } 234446bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 23459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootIndicesSec,p,numColIndices ? numColIndices+2*numFields : 0)); 23469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootMatricesSec,p,matSize)); 23476ecaa68aSToby Isaac } 23489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootIndicesSec)); 23499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootMatricesSec)); 23506ecaa68aSToby Isaac { 23516ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 23526ecaa68aSToby Isaac 23539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices)); 23549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootMatricesSec,&numRootMatrices)); 23559566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRootIndices,&rootIndices,numRootMatrices,&rootMatrices)); 23566ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 23576ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2358f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 23596ecaa68aSToby Isaac PetscInt *pInd; 23606ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 23616ecaa68aSToby Isaac PetscScalar *pMat = NULL; 23626ecaa68aSToby Isaac 23639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec,p,&numColIndices)); 23646ecaa68aSToby Isaac if (!numColIndices) { 23656ecaa68aSToby Isaac continue; 23666ecaa68aSToby Isaac } 2367f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2368f13f9184SToby Isaac offsets[f] = 0; 2369f13f9184SToby Isaac newOffsets[f] = 0; 2370f13f9184SToby Isaac offsetsCopy[f] = 0; 2371f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2372f13f9184SToby Isaac } 23736ecaa68aSToby Isaac numColIndices -= 2 * numFields; 23749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec,p,&pIndOff)); 23756ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 23769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootMatricesSec,p,&matSize)); 23776ecaa68aSToby Isaac if (matSize) { 23789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootMatricesSec,p,&pMatOff)); 23796ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 23806ecaa68aSToby Isaac } 23819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse,p,&dof)); 23821cfc5b76SToby Isaac if (dof < 0) { 23831cfc5b76SToby Isaac dof = -(dof + 1); 23841cfc5b76SToby Isaac } 23856ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 23866ecaa68aSToby Isaac PetscInt i, j; 23876ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 23886ecaa68aSToby Isaac 23896ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 23906ecaa68aSToby Isaac PetscInt numIndices, *indices; 23919566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(coarse,localCoarse,globalCoarse,p,PETSC_TRUE,&numIndices,&indices,offsets,NULL)); 239208401ef6SPierre Jolivet PetscCheck(numIndices == numColIndices,PETSC_COMM_SELF,PETSC_ERR_PLIB,"mismatching constraint indices calculations"); 23936ecaa68aSToby Isaac for (i = 0; i < numColIndices; i++) { 23946ecaa68aSToby Isaac pInd[i] = indices[i]; 23956ecaa68aSToby Isaac } 23966ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 239746bdb399SToby Isaac pInd[numColIndices + i] = offsets[i+1]; 239846bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i+1]; 23996ecaa68aSToby Isaac } 24009566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(coarse,localCoarse,globalCoarse,p,PETSC_TRUE,&numIndices,&indices,offsets,NULL)); 24016ecaa68aSToby Isaac } 24026ecaa68aSToby Isaac else { 24036ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 24046ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 24056ecaa68aSToby Isaac PetscInt numPoints,*points; 24066ecaa68aSToby Isaac 24079566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse,numRowIndices * numRowIndices,MPIU_SCALAR,&pMatIn)); 24086ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 24096ecaa68aSToby Isaac for (j = 0; j < numRowIndices; j++) { 24106ecaa68aSToby Isaac pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 24116ecaa68aSToby Isaac } 24126ecaa68aSToby Isaac } 24139566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 24144acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24159566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse,f,closureSize,closure,&perms[f],&flips[f])); 24169566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse,closureSize,closure,&perms[f],&flips[f])); 24174acb8e1eSToby Isaac } 24186ecaa68aSToby Isaac if (numFields) { 24196ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 24206ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 24216ecaa68aSToby Isaac 24226ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24236ecaa68aSToby Isaac PetscInt fDof; 24246ecaa68aSToby Isaac 24259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,c,f,&fDof)); 24266ecaa68aSToby Isaac offsets[f + 1] += fDof; 24276ecaa68aSToby Isaac } 24286ecaa68aSToby Isaac } 24296ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24306ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 24316ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 24326ecaa68aSToby Isaac } 24336ecaa68aSToby Isaac } 24344acb8e1eSToby Isaac /* TODO : flips here ? */ 24356ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 24369566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,perms,pMatIn,&numPoints,NULL,&points,&pMatModified,newOffsets,PETSC_FALSE)); 24374acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24389566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse,f,closureSize,closure,&perms[f],&flips[f])); 24399566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse,closureSize,closure,&perms[f],&flips[f])); 24404acb8e1eSToby Isaac } 24414acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24429566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse,f,numPoints,points,&perms[f],&flips[f])); 24439566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse,numPoints,points,&perms[f],&flips[f])); 24444acb8e1eSToby Isaac } 24456ecaa68aSToby Isaac if (!numFields) { 24466ecaa68aSToby Isaac for (i = 0; i < numRowIndices * numColIndices; i++) { 24476ecaa68aSToby Isaac pMat[i] = pMatModified[i]; 24486ecaa68aSToby Isaac } 24496ecaa68aSToby Isaac } 24506ecaa68aSToby Isaac else { 2451f13f9184SToby Isaac PetscInt i, j, count; 24526ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24536ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f+1]; i++) { 24546ecaa68aSToby Isaac for (j = newOffsets[f]; j < newOffsets[f+1]; j++, count++) { 24556ecaa68aSToby Isaac pMat[count] = pMatModified[i * numColIndices + j]; 24566ecaa68aSToby Isaac } 24576ecaa68aSToby Isaac } 24586ecaa68aSToby Isaac } 24596ecaa68aSToby Isaac } 24609566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse,numRowIndices * numColIndices,MPIU_SCALAR,&pMatModified)); 24619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 24629566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse,numRowIndices * numColIndices,MPIU_SCALAR,&pMatIn)); 24636ecaa68aSToby Isaac if (numFields) { 246446bdb399SToby Isaac for (f = 0; f < numFields; f++) { 246546bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 246646bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 24676ecaa68aSToby Isaac } 24684acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 24694acb8e1eSToby Isaac PetscInt globalOff, c = points[2*cl]; 24709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 24719566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd)); 24726ecaa68aSToby Isaac } 24736ecaa68aSToby Isaac } else { 24744acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 24754acb8e1eSToby Isaac PetscInt c = points[2*cl], globalOff; 24764acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 24774acb8e1eSToby Isaac 24789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 24799566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd)); 24806ecaa68aSToby Isaac } 24816ecaa68aSToby Isaac } 24824acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24839566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse,f,numPoints,points,&perms[f],&flips[f])); 24849566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse,numPoints,points,&perms[f],&flips[f])); 24854acb8e1eSToby Isaac } 24869566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse,numPoints,MPIU_SCALAR,&points)); 24876ecaa68aSToby Isaac } 24886ecaa68aSToby Isaac } 24896ecaa68aSToby Isaac else if (matSize) { 24906ecaa68aSToby Isaac PetscInt cOff; 24916ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 24926ecaa68aSToby Isaac 24936ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 249408401ef6SPierre Jolivet PetscCheck(numRowIndices == dof,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Miscounted dofs"); 24959566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse,numRowIndices,MPIU_INT,&rowIndices)); 24969566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse,numColIndices,MPIU_INT,&colIndices)); 24979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec,p,&cOff)); 24989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec,p,&aDof)); 24999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec,p,&aOff)); 25006ecaa68aSToby Isaac if (numFields) { 25016ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25026ecaa68aSToby Isaac PetscInt fDof; 2503f13f9184SToby Isaac 25049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec,p,f,&fDof)); 25056ecaa68aSToby Isaac offsets[f + 1] = fDof; 25066ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25076ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof)); 25096ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 25106ecaa68aSToby Isaac } 25116ecaa68aSToby Isaac } 25126ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25136ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 25146ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 25156ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 25166ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 25176ecaa68aSToby Isaac } 25189566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec,PETSC_TRUE,p,cOff,offsetsCopy,PETSC_TRUE,NULL,-1, NULL,rowIndices)); 25196ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25206ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse,anchor,&lOff)); 25229566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_TRUE,anchor,lOff,newOffsetsCopy,PETSC_TRUE,NULL,-1, NULL,colIndices)); 25236ecaa68aSToby Isaac } 25246ecaa68aSToby Isaac } 25256ecaa68aSToby Isaac else { 25269566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec,PETSC_TRUE,p,cOff,offsetsCopy,PETSC_TRUE,NULL, NULL,rowIndices)); 25276ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25286ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse,anchor,&lOff)); 25309566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_TRUE,anchor,lOff,newOffsetsCopy,PETSC_TRUE,NULL, NULL,colIndices)); 25316ecaa68aSToby Isaac } 25326ecaa68aSToby Isaac } 25336ecaa68aSToby Isaac if (numFields) { 2534f13f9184SToby Isaac PetscInt count, a; 2535f13f9184SToby Isaac 25366ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 25376ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 25386ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 25399566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,iSize,&rowIndices[offsets[f]],jSize,&colIndices[newOffsets[f]],&pMat[count])); 25406ecaa68aSToby Isaac count += iSize * jSize; 254146bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 254246bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 25436ecaa68aSToby Isaac } 25446ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25456ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25466ecaa68aSToby Isaac PetscInt gOff; 25479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse,anchor,&gOff)); 25489566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,NULL,-1, NULL,pInd)); 25496ecaa68aSToby Isaac } 25506ecaa68aSToby Isaac } 25516ecaa68aSToby Isaac else { 25526ecaa68aSToby Isaac PetscInt a; 25539566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat,numRowIndices,rowIndices,numColIndices,colIndices,pMat)); 25546ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25556ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25566ecaa68aSToby Isaac PetscInt gOff; 25579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse,anchor,&gOff)); 25589566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,NULL, NULL,pInd)); 25596ecaa68aSToby Isaac } 25606ecaa68aSToby Isaac } 25619566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse,numColIndices,MPIU_INT,&colIndices)); 25629566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse,numRowIndices,MPIU_INT,&rowIndices)); 25636ecaa68aSToby Isaac } 25646ecaa68aSToby Isaac else { 25656ecaa68aSToby Isaac PetscInt gOff; 25666ecaa68aSToby Isaac 25679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse,p,&gOff)); 25686ecaa68aSToby Isaac if (numFields) { 25696ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25706ecaa68aSToby Isaac PetscInt fDof; 25719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 25726ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 25736ecaa68aSToby Isaac } 25746ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 257546bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 257646bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f+1]; 25776ecaa68aSToby Isaac } 25789566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,-1, NULL,pInd)); 2579367003a6SStefano Zampini } else { 25809566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL, NULL,pInd)); 25816ecaa68aSToby Isaac } 25826ecaa68aSToby Isaac } 25836ecaa68aSToby Isaac } 25849566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 25856ecaa68aSToby Isaac } 258646bdb399SToby Isaac { 258746bdb399SToby Isaac PetscSF indicesSF, matricesSF; 258846bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 258946bdb399SToby Isaac 25909566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec)); 25919566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafMatricesSec)); 25929566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded,rootIndicesSec,&remoteOffsetsIndices,leafIndicesSec)); 25939566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded,rootMatricesSec,&remoteOffsetsMatrices,leafMatricesSec)); 25949566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded,rootIndicesSec,remoteOffsetsIndices,leafIndicesSec,&indicesSF)); 25959566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded,rootMatricesSec,remoteOffsetsMatrices,leafMatricesSec,&matricesSF)); 25969566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 25979566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsIndices)); 25989566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsMatrices)); 25999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec,&numLeafIndices)); 26009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafMatricesSec,&numLeafMatrices)); 26019566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numLeafIndices,&leafIndices,numLeafMatrices,&leafMatrices)); 26029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF,MPIU_INT,rootIndices,leafIndices,MPI_REPLACE)); 26039566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices,MPI_REPLACE)); 26049566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF,MPIU_INT,rootIndices,leafIndices,MPI_REPLACE)); 26059566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices,MPI_REPLACE)); 26069566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&matricesSF)); 26079566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 26089566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootIndices,rootMatrices)); 26099566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 26109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootMatricesSec)); 261146bdb399SToby Isaac } 261246bdb399SToby Isaac /* count to preallocate */ 26139566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine,&localFine)); 261446bdb399SToby Isaac { 261546bdb399SToby Isaac PetscInt nGlobal; 261646bdb399SToby Isaac PetscInt *dnnz, *onnz; 2617b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2618b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 26191c58ffc4SToby Isaac PetscInt maxDof; 26201c58ffc4SToby Isaac PetscInt *rowIndices; 26211c58ffc4SToby Isaac DM refTree; 26221c58ffc4SToby Isaac PetscInt **refPointFieldN; 26231c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 26241c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 26250eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,maxConDof,maxColumns,leafStart,leafEnd; 26261c58ffc4SToby Isaac PetscScalar *pointWork; 262746bdb399SToby Isaac 26289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalFine,&nGlobal)); 26299566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nGlobal,&dnnz,nGlobal,&onnz)); 26309566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat,&rowMap,&colMap)); 26319566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 26329566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 26339566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap,&rowStart,&rowEnd)); 26349566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap,&colStart,&colEnd)); 26359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine,&maxDof)); 26369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafIndicesSec,&leafStart,&leafEnd)); 26379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine,maxDof,MPIU_INT,&rowIndices)); 26380eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 263946bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 264046bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 264146bdb399SToby Isaac PetscInt matSize; 264221968bf8SToby Isaac PetscInt i; 264346bdb399SToby Isaac 26449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&gDof)); 26459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&gcDof)); 264646bdb399SToby Isaac if ((gDof - gcDof) <= 0) { 264746bdb399SToby Isaac continue; 264846bdb399SToby Isaac } 26499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine,p,&gOff)); 265008401ef6SPierre Jolivet PetscCheck(gOff >= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"I though having global dofs meant a non-negative offset"); 26511dca8a05SBarry Smith PetscCheck(gOff >= rowStart && (gOff + gDof - gcDof) <= rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"I thought the row map would constrain the global dofs"); 26529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec,p,&numColIndices)); 26539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec,p,&pIndOff)); 265446bdb399SToby Isaac numColIndices -= 2 * numFields; 265508401ef6SPierre Jolivet PetscCheck(numColIndices > 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"global fine dof with no dofs to interpolate from"); 265646bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 265721968bf8SToby Isaac offsets[0] = 0; 265821968bf8SToby Isaac offsetsCopy[0] = 0; 265921968bf8SToby Isaac newOffsets[0] = 0; 266021968bf8SToby Isaac newOffsetsCopy[0] = 0; 266146bdb399SToby Isaac if (numFields) { 266221968bf8SToby Isaac PetscInt f; 266346bdb399SToby Isaac for (f = 0; f < numFields; f++) { 266446bdb399SToby Isaac PetscInt rowDof; 266546bdb399SToby Isaac 26669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine,p,f,&rowDof)); 266721968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 266821968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 266921968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 267021968bf8SToby Isaac numD[f] = 0; 267121968bf8SToby Isaac numO[f] = 0; 267246bdb399SToby Isaac } 26739566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,rowIndices)); 267446bdb399SToby Isaac for (f = 0; f < numFields; f++) { 267521968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 267621968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 267746bdb399SToby Isaac 267846bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 267946bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 268046bdb399SToby Isaac 268146bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 268221968bf8SToby Isaac numD[f]++; 268346bdb399SToby Isaac } 268446bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 268521968bf8SToby Isaac numO[f]++; 268646bdb399SToby Isaac } 268746bdb399SToby Isaac } 268846bdb399SToby Isaac } 268946bdb399SToby Isaac } 269046bdb399SToby Isaac else { 26919566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,rowIndices)); 269221968bf8SToby Isaac numD[0] = 0; 269321968bf8SToby Isaac numO[0] = 0; 269446bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 269546bdb399SToby Isaac PetscInt gInd = pInd[i]; 269646bdb399SToby Isaac 269746bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 269821968bf8SToby Isaac numD[0]++; 269946bdb399SToby Isaac } 270046bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 270121968bf8SToby Isaac numO[0]++; 270246bdb399SToby Isaac } 270346bdb399SToby Isaac } 270446bdb399SToby Isaac } 27059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec,p,&matSize)); 270646bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 270746bdb399SToby Isaac PetscInt childId; 270846bdb399SToby Isaac 270946bdb399SToby Isaac childId = childIds[p-pStartF]; 271021968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 271146bdb399SToby Isaac if (numFields) { 2712b9a5774bSToby Isaac PetscInt f; 2713b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 271421968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 271546bdb399SToby Isaac for (row = 0; row < numRows; row++) { 271621968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 271721968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 271846bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 27191dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2720b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 272146bdb399SToby Isaac } 272246bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 27231dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2724b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 272546bdb399SToby Isaac } 272646bdb399SToby Isaac else { /* constrained */ 272708401ef6SPierre Jolivet PetscCheck(gIndFine < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 272846bdb399SToby Isaac } 272946bdb399SToby Isaac } 273046bdb399SToby Isaac } 273146bdb399SToby Isaac } 273246bdb399SToby Isaac else { 2733b9a5774bSToby Isaac PetscInt i; 2734b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 273546bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 273646bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 273746bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 27381dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2739b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 274046bdb399SToby Isaac } 274146bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 27421dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2743b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 274446bdb399SToby Isaac } 274546bdb399SToby Isaac else { /* constrained */ 274608401ef6SPierre Jolivet PetscCheck(gIndFine < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 274746bdb399SToby Isaac } 274846bdb399SToby Isaac } 274946bdb399SToby Isaac } 275046bdb399SToby Isaac } 275146bdb399SToby Isaac else { /* interpolate from all */ 275246bdb399SToby Isaac if (numFields) { 2753b9a5774bSToby Isaac PetscInt f; 2754b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 275521968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 275646bdb399SToby Isaac for (row = 0; row < numRows; row++) { 275721968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 275846bdb399SToby Isaac if (gIndFine >= 0) { 27591dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2760b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2761b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 276246bdb399SToby Isaac } 276346bdb399SToby Isaac } 276446bdb399SToby Isaac } 276546bdb399SToby Isaac } 276646bdb399SToby Isaac else { 2767b9a5774bSToby Isaac PetscInt i; 2768b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 276946bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 277046bdb399SToby Isaac if (gIndFine >= 0) { 27711dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2772b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2773b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 277446bdb399SToby Isaac } 277546bdb399SToby Isaac } 277646bdb399SToby Isaac } 277746bdb399SToby Isaac } 277846bdb399SToby Isaac } 277946bdb399SToby Isaac else { /* interpolate from all */ 278046bdb399SToby Isaac if (numFields) { 2781b9a5774bSToby Isaac PetscInt f; 2782b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 278321968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 278446bdb399SToby Isaac for (row = 0; row < numRows; row++) { 278521968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 278646bdb399SToby Isaac if (gIndFine >= 0) { 27871dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2788b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2789b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 279046bdb399SToby Isaac } 279146bdb399SToby Isaac } 279246bdb399SToby Isaac } 279346bdb399SToby Isaac } 279446bdb399SToby Isaac else { /* every dof get a full row */ 2795b9a5774bSToby Isaac PetscInt i; 2796b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 279746bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 279846bdb399SToby Isaac if (gIndFine >= 0) { 27991dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2800b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2801b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 280246bdb399SToby Isaac } 280346bdb399SToby Isaac } 280446bdb399SToby Isaac } 280546bdb399SToby Isaac } 280646bdb399SToby Isaac } 28079566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat,1,dnnz,onnz,NULL,NULL)); 28089566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnnz,onnz)); 280921968bf8SToby Isaac 28109566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine,&refTree)); 28119566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 28129566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 28139566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree,&refAnSec,NULL)); 28149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 28159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec,&maxConDof)); 28169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(leafIndicesSec,&maxColumns)); 28179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConDof*maxColumns,&pointWork)); 28180eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2819e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2820e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2821e44e4e7fSToby Isaac PetscInt matSize; 2822e44e4e7fSToby Isaac PetscInt childId; 2823e44e4e7fSToby Isaac 28249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&gDof)); 28259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&gcDof)); 2826e44e4e7fSToby Isaac if ((gDof - gcDof) <= 0) { 2827e44e4e7fSToby Isaac continue; 2828e44e4e7fSToby Isaac } 2829e44e4e7fSToby Isaac childId = childIds[p-pStartF]; 28309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine,p,&gOff)); 28319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec,p,&numColIndices)); 28329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec,p,&pIndOff)); 2833e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2834e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2835e44e4e7fSToby Isaac offsets[0] = 0; 2836e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2837e44e4e7fSToby Isaac newOffsets[0] = 0; 2838e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2839e44e4e7fSToby Isaac rowOffsets[0] = 0; 2840e44e4e7fSToby Isaac if (numFields) { 2841e44e4e7fSToby Isaac PetscInt f; 2842e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2843e44e4e7fSToby Isaac PetscInt rowDof; 2844e44e4e7fSToby Isaac 28459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine,p,f,&rowDof)); 2846e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2847e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2848e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2849e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2850e44e4e7fSToby Isaac } 28519566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,rowIndices)); 2852e44e4e7fSToby Isaac } 28531c58ffc4SToby Isaac else { 28549566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,rowIndices)); 28551c58ffc4SToby Isaac } 28569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec,p,&matSize)); 2857e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2858e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2859e44e4e7fSToby Isaac if (numFields) { 2860e44e4e7fSToby Isaac PetscInt f; 2861e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2862e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 2863e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 28649566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat,rowIndices[offsets[f]+row],pInd[newOffsets[f]+row],1.,INSERT_VALUES)); 286521968bf8SToby Isaac } 286621968bf8SToby Isaac } 2867e44e4e7fSToby Isaac } 2868e44e4e7fSToby Isaac else { 2869e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 2870e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 28719566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat,rowIndices[row],pInd[row],1.,INSERT_VALUES)); 2872e44e4e7fSToby Isaac } 2873e44e4e7fSToby Isaac } 2874e44e4e7fSToby Isaac } 2875e44e4e7fSToby Isaac else { /* interpolate from all */ 2876e44e4e7fSToby Isaac if (numFields) { 2877e44e4e7fSToby Isaac PetscInt f; 2878e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2879e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 2880e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 28819566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],refPointFieldMats[childId - pRefStart][f],INSERT_VALUES)); 2882e44e4e7fSToby Isaac } 2883e44e4e7fSToby Isaac } 2884e44e4e7fSToby Isaac else { 28859566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,refPointFieldMats[childId - pRefStart][0],INSERT_VALUES)); 2886e44e4e7fSToby Isaac } 2887e44e4e7fSToby Isaac } 2888e44e4e7fSToby Isaac } 2889e44e4e7fSToby Isaac else { /* interpolate from all */ 2890e44e4e7fSToby Isaac PetscInt pMatOff; 2891e44e4e7fSToby Isaac PetscScalar *pMat; 2892e44e4e7fSToby Isaac 28939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafMatricesSec,p,&pMatOff)); 2894e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2895e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2896e44e4e7fSToby Isaac if (numFields) { 2897e44e4e7fSToby Isaac PetscInt f, count; 2898e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2899e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2900e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2901e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2902e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2903e44e4e7fSToby Isaac 29049566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],inMat,INSERT_VALUES)); 2905e44e4e7fSToby Isaac count += numCols * numInRows; 2906e44e4e7fSToby Isaac } 2907e44e4e7fSToby Isaac } 2908e44e4e7fSToby Isaac else { 29099566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,pMat,INSERT_VALUES)); 2910e44e4e7fSToby Isaac } 2911e44e4e7fSToby Isaac } 2912e44e4e7fSToby Isaac else { /* multiply the incoming matrix by the child interpolation */ 2913e44e4e7fSToby Isaac if (numFields) { 2914e44e4e7fSToby Isaac PetscInt f, count; 2915e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2916e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2917e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2918e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2919e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2920e44e4e7fSToby Isaac PetscInt i, j, k; 292108401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][f] == numInRows,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2922e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2923e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2924e44e4e7fSToby Isaac PetscScalar val = 0.; 2925e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2926e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2927e44e4e7fSToby Isaac } 2928e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2929e44e4e7fSToby Isaac } 2930e44e4e7fSToby Isaac } 29319566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],pointWork,INSERT_VALUES)); 2932e44e4e7fSToby Isaac count += numCols * numInRows; 2933e44e4e7fSToby Isaac } 2934e44e4e7fSToby Isaac } 2935267d4f3fSToby Isaac else { /* every dof gets a full row */ 2936e44e4e7fSToby Isaac PetscInt numRows = gDof; 2937e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2938e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2939e44e4e7fSToby Isaac PetscInt i, j, k; 294008401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][0] == numInRows,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2941e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2942e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2943e44e4e7fSToby Isaac PetscScalar val = 0.; 2944e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2945e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2946e44e4e7fSToby Isaac } 2947e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2948e44e4e7fSToby Isaac } 2949e44e4e7fSToby Isaac } 29509566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,numRows,rowIndices,numCols,pInd,pointWork,INSERT_VALUES)); 2951e44e4e7fSToby Isaac } 2952e44e4e7fSToby Isaac } 2953e44e4e7fSToby Isaac } 2954e44e4e7fSToby Isaac } 29559566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 29569566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine,maxDof,MPIU_INT,&rowIndices)); 29579566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork)); 2958e44e4e7fSToby Isaac } 29599566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 29609566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 29619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 29629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafMatricesSec)); 29639566063dSJacob Faibussowitsch PetscCall(PetscFree2(leafIndices,leafMatrices)); 29649566063dSJacob Faibussowitsch PetscCall(PetscFree2(*(PetscInt****)&perms,*(PetscScalar****)&flips)); 29659566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO)); 29669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 29676ecaa68aSToby Isaac PetscFunctionReturn(0); 29686ecaa68aSToby Isaac } 2969154bca37SToby Isaac 29708d2f55e7SToby Isaac /* 29718d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 29728d2f55e7SToby Isaac * 29738d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 29748d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 29758d2f55e7SToby Isaac * for each fine dof \phi^f_j; 29768d2f55e7SToby Isaac * a_{i,j} = 0; 29778d2f55e7SToby Isaac * for each fine dof \phi^f_k: 29788d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 29798d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 29808d2f55e7SToby Isaac */ 29818d2f55e7SToby Isaac PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 29828d2f55e7SToby Isaac { 29838d2f55e7SToby Isaac PetscDS ds; 29848d2f55e7SToby Isaac PetscSection section, cSection; 29858d2f55e7SToby Isaac DMLabel canonical, depth; 29868d2f55e7SToby Isaac Mat cMat, mat; 29878d2f55e7SToby Isaac PetscInt *nnz; 29888d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 29898d2f55e7SToby Isaac PetscInt m, n; 29908d2f55e7SToby Isaac PetscScalar *pointScalar; 29918d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 29928d2f55e7SToby Isaac 29938d2f55e7SToby Isaac PetscFunctionBegin; 29949566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree,§ion)); 29959566063dSJacob Faibussowitsch PetscCall(DMGetDimension(refTree, &dim)); 29969566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(dim,&v0,dim,&v0parent,dim,&vtmp,dim*dim,&J,dim*dim,&Jparent,dim*dim,&invJ)); 29979566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim,&pointScalar,dim,&pointRef)); 29989566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree,&ds)); 29999566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds,&numFields)); 30009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&numSecFields)); 30019566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree,"canonical",&canonical)); 30029566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree,"depth",&depth)); 30039566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&cSection,&cMat,NULL)); 30049566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(refTree, &pStart, &pEnd)); 30059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd)); 30069566063dSJacob Faibussowitsch PetscCall(MatGetSize(cMat,&n,&m)); /* the injector has transpose sizes from the constraint matrix */ 30078d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 30089566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m,&nnz)); 30098d2f55e7SToby 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 */ 30108d2f55e7SToby Isaac const PetscInt *children; 30118d2f55e7SToby Isaac PetscInt numChildren; 30128d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30138d2f55e7SToby Isaac 30148d2f55e7SToby Isaac if (canonical) { 30158d2f55e7SToby Isaac PetscInt pCanonical; 30169566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical,p,&pCanonical)); 30178d2f55e7SToby Isaac if (p != pCanonical) continue; 30188d2f55e7SToby Isaac } 30199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree,p,&numChildren,&children)); 30208d2f55e7SToby Isaac if (!numChildren) continue; 30218d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30228d2f55e7SToby Isaac PetscInt child = children[i]; 30238d2f55e7SToby Isaac PetscInt dof; 30248d2f55e7SToby Isaac 30259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,child,&dof)); 30268d2f55e7SToby Isaac numChildDof += dof; 30278d2f55e7SToby Isaac } 30289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,p,&numSelfDof)); 30298d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30308d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 30318d2f55e7SToby Isaac PetscInt selfOff; 30328d2f55e7SToby Isaac 30338d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 30348d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30358d2f55e7SToby Isaac PetscInt child = children[i]; 30368d2f55e7SToby Isaac PetscInt dof; 30378d2f55e7SToby Isaac 30389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,child,f,&dof)); 30398d2f55e7SToby Isaac numChildDof += dof; 30408d2f55e7SToby Isaac } 30419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,p,f,&numSelfDof)); 30429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section,p,f,&selfOff)); 30438d2f55e7SToby Isaac } 30448d2f55e7SToby Isaac else { 30459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,p,&selfOff)); 30468d2f55e7SToby Isaac } 30478d2f55e7SToby Isaac for (i = 0; i < numSelfDof; i++) { 30488d2f55e7SToby Isaac nnz[selfOff + i] = numChildDof; 30498d2f55e7SToby Isaac } 30508d2f55e7SToby Isaac } 30518d2f55e7SToby Isaac } 30529566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(PETSC_COMM_SELF,m,n,m,n,-1,nnz,-1,NULL,&mat)); 30539566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 30548d2f55e7SToby Isaac /* Setp 2: compute entries */ 30558d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 30568d2f55e7SToby Isaac const PetscInt *children; 30578d2f55e7SToby Isaac PetscInt numChildren; 30588d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30598d2f55e7SToby Isaac 30608d2f55e7SToby Isaac /* same conditions about when entries occur */ 30618d2f55e7SToby Isaac if (canonical) { 30628d2f55e7SToby Isaac PetscInt pCanonical; 30639566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical,p,&pCanonical)); 30648d2f55e7SToby Isaac if (p != pCanonical) continue; 30658d2f55e7SToby Isaac } 30669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree,p,&numChildren,&children)); 30678d2f55e7SToby Isaac if (!numChildren) continue; 30688d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30698d2f55e7SToby Isaac PetscInt child = children[i]; 30708d2f55e7SToby Isaac PetscInt dof; 30718d2f55e7SToby Isaac 30729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,child,&dof)); 30738d2f55e7SToby Isaac numChildDof += dof; 30748d2f55e7SToby Isaac } 30759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section,p,&numSelfDof)); 30768d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30778d2f55e7SToby Isaac 30788d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 307959fc6756SToby Isaac PetscInt pI = -1, cI = -1; 308052a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell; 30818d2f55e7SToby Isaac PetscInt cellShapeOff; 30828d2f55e7SToby Isaac PetscObject disc; 30838d2f55e7SToby Isaac PetscDualSpace dsp; 30848d2f55e7SToby Isaac PetscClassId classId; 30858d2f55e7SToby Isaac PetscScalar *pointMat; 30863b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 30878d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 30888d2f55e7SToby Isaac const PetscInt *depthNumDof; 30898d2f55e7SToby Isaac 30908d2f55e7SToby Isaac if (numSecFields) { 30918d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30928d2f55e7SToby Isaac PetscInt child = children[i]; 30938d2f55e7SToby Isaac PetscInt dof; 30948d2f55e7SToby Isaac 30959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,child,f,&dof)); 30968d2f55e7SToby Isaac numChildDof += dof; 30978d2f55e7SToby Isaac } 30989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section,p,f,&numSelfDof)); 30999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section,p,f,&selfOff)); 31008d2f55e7SToby Isaac } 31018d2f55e7SToby Isaac else { 31029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,p,&selfOff)); 31038d2f55e7SToby Isaac } 31048d2f55e7SToby Isaac 31053b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 31068d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 31078d2f55e7SToby Isaac parentCell = p; 31088d2f55e7SToby Isaac } 31098d2f55e7SToby Isaac else { 31108d2f55e7SToby Isaac PetscInt *star = NULL; 31118d2f55e7SToby Isaac PetscInt numStar; 31128d2f55e7SToby Isaac 31138d2f55e7SToby Isaac parentCell = -1; 31149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star)); 31158d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 31168d2f55e7SToby Isaac PetscInt c = star[2 * i]; 31178d2f55e7SToby Isaac 31188d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 31198d2f55e7SToby Isaac parentCell = c; 31208d2f55e7SToby Isaac break; 31218d2f55e7SToby Isaac } 31228d2f55e7SToby Isaac } 31239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star)); 31248d2f55e7SToby Isaac } 3125a5b23f4aSJose E. Roman /* determine the offset of p's shape functions within parentCell's shape functions */ 31269566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds,f,&disc)); 31279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc,&classId)); 3128c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 31299566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp)); 3130c5356c36SToby Isaac } 3131c5356c36SToby Isaac else if (classId == PETSCFV_CLASSID) { 31329566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace((PetscFV)disc,&dsp)); 3133c5356c36SToby Isaac } 3134c5356c36SToby Isaac else { 31359b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported discretization object"); 3136c5356c36SToby Isaac } 31379566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dsp,&depthNumDof)); 31389566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dsp,&Nc)); 31398d2f55e7SToby Isaac { 31408d2f55e7SToby Isaac PetscInt *closure = NULL; 31418d2f55e7SToby Isaac PetscInt numClosure; 31428d2f55e7SToby Isaac 31439566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure)); 314459fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) { 31458d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 31468d2f55e7SToby Isaac 31478d2f55e7SToby Isaac pO = closure[2 * i + 1]; 314859fc6756SToby Isaac if (point == p) { 314959fc6756SToby Isaac pI = i; 315059fc6756SToby Isaac break; 315159fc6756SToby Isaac } 31529566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth,point,&pointDepth)); 31538d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 31548d2f55e7SToby Isaac } 31559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure)); 31568d2f55e7SToby Isaac } 31578d2f55e7SToby Isaac 31589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR,&pointMat)); 31599566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT,&matRows)); 316052a3aeb4SToby Isaac matCols = matRows + numSelfDof; 316152a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { 316252a3aeb4SToby Isaac matRows[i] = selfOff + i; 31633b1c2a6aSToby Isaac } 316452a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.; 31653b1c2a6aSToby Isaac { 31663b1c2a6aSToby Isaac PetscInt colOff = 0; 31673b1c2a6aSToby Isaac 31683b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 31693b1c2a6aSToby Isaac PetscInt child = children[i]; 31703b1c2a6aSToby Isaac PetscInt dof, off, j; 31713b1c2a6aSToby Isaac 31723b1c2a6aSToby Isaac if (numSecFields) { 31739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSection,child,f,&dof)); 31749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSection,child,f,&off)); 31753b1c2a6aSToby Isaac } 31763b1c2a6aSToby Isaac else { 31779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSection,child,&dof)); 31789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSection,child,&off)); 31793b1c2a6aSToby Isaac } 31803b1c2a6aSToby Isaac 318152a3aeb4SToby Isaac for (j = 0; j < dof; j++) { 318252a3aeb4SToby Isaac matCols[colOff++] = off + j; 31833b1c2a6aSToby Isaac } 31843b1c2a6aSToby Isaac } 31853b1c2a6aSToby Isaac } 31868d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 31878d2f55e7SToby Isaac PetscFE fe = (PetscFE) disc; 31888d2f55e7SToby Isaac PetscInt fSize; 318959fc6756SToby Isaac const PetscInt ***perms; 319059fc6756SToby Isaac const PetscScalar ***flips; 319159fc6756SToby Isaac const PetscInt *pperms; 319259fc6756SToby Isaac 31939566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe,&dsp)); 31949566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dsp,&fSize)); 31959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dsp, &perms, &flips)); 319659fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL; 319752a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */ 31988d2f55e7SToby Isaac PetscQuadrature q; 319952a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k; 32008d2f55e7SToby Isaac const PetscReal *points; 32018d2f55e7SToby Isaac const PetscReal *weights; 32028d2f55e7SToby Isaac PetscInt *closure = NULL; 32038d2f55e7SToby Isaac PetscInt numClosure; 320459fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i; 320559fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell; 3206ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent; 32078d2f55e7SToby Isaac 32089566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dsp,parentCellShapeDof,&q)); 32099566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,&dim,&thisNc,&numPoints,&points,&weights)); 321063a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT,thisNc,Nc); 32119566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe,1,numPoints,points,0,&Tparent)); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 32123b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 32138d2f55e7SToby Isaac PetscInt childCell = -1; 321452a3aeb4SToby Isaac PetscReal *parentValAtPoint; 3215c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 32168d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 32178d2f55e7SToby Isaac const PetscScalar *point; 3218ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild; 32198d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 32208d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 32218d2f55e7SToby Isaac PetscInt d; 32228d2f55e7SToby Isaac 32238d2f55e7SToby Isaac for (d = 0; d < dim; d++) { 32248d2f55e7SToby Isaac pointScalar[d] = points[dim * j + d]; 32258d2f55e7SToby Isaac } 32268d2f55e7SToby Isaac point = pointScalar; 32278d2f55e7SToby Isaac #else 32288d2f55e7SToby Isaac point = pointReal; 32298d2f55e7SToby Isaac #endif 32308d2f55e7SToby Isaac 3231ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc]; 32323b1c2a6aSToby Isaac 32333b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 32348d2f55e7SToby Isaac PetscInt child = children[k]; 32358d2f55e7SToby Isaac PetscInt *star = NULL; 32368d2f55e7SToby Isaac PetscInt numStar, s; 32378d2f55e7SToby Isaac 32389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star)); 32398d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 32408d2f55e7SToby Isaac PetscInt c = star[2 * s]; 32418d2f55e7SToby Isaac 32428d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 32439566063dSJacob Faibussowitsch PetscCall(DMPlexLocatePoint_Internal(refTree,dim,point,c,&childCell)); 32448d2f55e7SToby Isaac if (childCell >= 0) break; 32458d2f55e7SToby Isaac } 32469566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star)); 32478d2f55e7SToby Isaac if (childCell >= 0) break; 32488d2f55e7SToby Isaac } 324908401ef6SPierre Jolivet PetscCheck(childCell >= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not locate quadrature point"); 32509566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ)); 32519566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent)); 3252c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp); 3253c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef); 32548d2f55e7SToby Isaac 32559566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe,1,1,pointRef,0,&Tchild)); 32569566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure)); 32573b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3258c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 32598d2f55e7SToby Isaac PetscInt l; 326059fc6756SToby Isaac const PetscInt *cperms; 32618d2f55e7SToby Isaac 32629566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth,child,&childDepth)); 32638d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 326459fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) { 32658d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 32668d2f55e7SToby Isaac PetscInt pointDepth; 32678d2f55e7SToby Isaac 32688d2f55e7SToby Isaac childO = closure[2 * l + 1]; 326959fc6756SToby Isaac if (point == child) { 327059fc6756SToby Isaac cI = l; 327159fc6756SToby Isaac break; 327259fc6756SToby Isaac } 32739566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth,point,&pointDepth)); 32748d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 32758d2f55e7SToby Isaac } 32768d2f55e7SToby Isaac if (l == numClosure) { 32778d2f55e7SToby Isaac pointMatOff += childDof; 32788d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 32798d2f55e7SToby Isaac } 328059fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL; 32818d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 328259fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l; 328359fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell; 328452a3aeb4SToby Isaac PetscReal *childValAtPoint; 328552a3aeb4SToby Isaac PetscReal val = 0.; 32868d2f55e7SToby Isaac 3287ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc]; 328852a3aeb4SToby Isaac for (m = 0; m < Nc; m++) { 328952a3aeb4SToby Isaac val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m]; 329052a3aeb4SToby Isaac } 329152a3aeb4SToby Isaac 329252a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val; 32938d2f55e7SToby Isaac } 32948d2f55e7SToby Isaac pointMatOff += childDof; 32958d2f55e7SToby Isaac } 32969566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure)); 32979566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tchild)); 32988d2f55e7SToby Isaac } 32999566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tparent)); 33008d2f55e7SToby Isaac } 33018d2f55e7SToby Isaac } 3302c5356c36SToby Isaac else { /* just the volume-weighted averages of the children */ 33033b1c2a6aSToby Isaac PetscReal parentVol; 3304bfaa5bdcSToby Isaac PetscInt childCell; 33053b1c2a6aSToby Isaac 33069566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL)); 3307bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) { 330852a3aeb4SToby Isaac PetscInt child = children[i], j; 33093b1c2a6aSToby Isaac PetscReal childVol; 33103b1c2a6aSToby Isaac 33113b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 33129566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL)); 331352a3aeb4SToby Isaac for (j = 0; j < Nc; j++) { 3314bfaa5bdcSToby Isaac pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol; 331552a3aeb4SToby Isaac } 3316bfaa5bdcSToby Isaac childCell++; 33173b1c2a6aSToby Isaac } 33188d2f55e7SToby Isaac } 33193b1c2a6aSToby Isaac /* Insert pointMat into mat */ 33209566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,numSelfDof,matRows,numChildDof,matCols,pointMat,INSERT_VALUES)); 33219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT,&matRows)); 33229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR,&pointMat)); 33238d2f55e7SToby Isaac } 33248d2f55e7SToby Isaac } 33259566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0,v0parent,vtmp,J,Jparent,invJ)); 33269566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointScalar,pointRef)); 33279566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 33289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 33298d2f55e7SToby Isaac *inj = mat; 33308d2f55e7SToby Isaac PetscFunctionReturn(0); 33318d2f55e7SToby Isaac } 33328d2f55e7SToby Isaac 3333f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3334f30e825dSToby Isaac { 3335f30e825dSToby Isaac PetscDS ds; 3336f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3337f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3338f30e825dSToby Isaac PetscSection refConSec, refSection; 3339f30e825dSToby Isaac 3340f30e825dSToby Isaac PetscFunctionBegin; 33419566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree,&ds)); 33429566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds,&numFields)); 33439566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 33449566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree,&refSection)); 33459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 33469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats)); 33479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec,&maxDof)); 33489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof,&rows)); 33499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof*maxDof,&cols)); 3350f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3351f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3352f30e825dSToby Isaac 33539566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,p,&parent,NULL)); 33549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec,p,&pDof)); 33559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection,parent,&parentDof)); 3356f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3357f30e825dSToby Isaac 33589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart])); 3359f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 336052a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r; 3361f30e825dSToby Isaac 3362f30e825dSToby Isaac if (numFields > 1) { 33639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec,p,f,&cDof)); 33649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec,p,f,&cOff)); 3365f30e825dSToby Isaac } 3366f30e825dSToby Isaac else { 33679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec,p,&cDof)); 33689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec,p,&cOff)); 3369f30e825dSToby Isaac } 3370f30e825dSToby Isaac 3371f30e825dSToby Isaac for (r = 0; r < cDof; r++) { 3372f30e825dSToby Isaac rows[r] = cOff + r; 3373f30e825dSToby Isaac } 3374f30e825dSToby Isaac numCols = 0; 3375f30e825dSToby Isaac { 3376f30e825dSToby Isaac PetscInt aDof, aOff, j; 3377f30e825dSToby Isaac 3378f30e825dSToby Isaac if (numFields > 1) { 33799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection,parent,f,&aDof)); 33809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection,parent,f,&aOff)); 3381f30e825dSToby Isaac } 3382f30e825dSToby Isaac else { 33839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection,parent,&aDof)); 33849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection,parent,&aOff)); 3385f30e825dSToby Isaac } 3386f30e825dSToby Isaac 3387f30e825dSToby Isaac for (j = 0; j < aDof; j++) { 3388f30e825dSToby Isaac cols[numCols++] = aOff + j; 3389f30e825dSToby Isaac } 3390f30e825dSToby Isaac } 33919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f])); 3392f30e825dSToby Isaac /* transpose of constraint matrix */ 33939566063dSJacob Faibussowitsch PetscCall(MatGetValues(inj,numCols,cols,cDof,rows,refPointFieldMats[p-pRefStart][f])); 3394f30e825dSToby Isaac } 3395f30e825dSToby Isaac } 3396f30e825dSToby Isaac *childrenMats = refPointFieldMats; 33979566063dSJacob Faibussowitsch PetscCall(PetscFree(rows)); 33989566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 3399f30e825dSToby Isaac PetscFunctionReturn(0); 3400f30e825dSToby Isaac } 3401f30e825dSToby Isaac 3402f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3403f30e825dSToby Isaac { 3404f30e825dSToby Isaac PetscDS ds; 3405f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3406f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3407c6154584SToby Isaac PetscSection refConSec, refSection; 3408f30e825dSToby Isaac 3409f30e825dSToby Isaac PetscFunctionBegin; 3410f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3411f30e825dSToby Isaac *childrenMats = NULL; 34129566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree,&ds)); 34139566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree,&refSection)); 34149566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds,&numFields)); 34159566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 34169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 3417f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3418f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3419f30e825dSToby Isaac 34209566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,p,&parent,NULL)); 34219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec,p,&pDof)); 34229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection,parent,&parentDof)); 3423f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3424f30e825dSToby Isaac 3425f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3426f30e825dSToby Isaac PetscInt cDof; 3427f30e825dSToby Isaac 3428f30e825dSToby Isaac if (numFields > 1) { 34299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec,p,f,&cDof)); 3430f30e825dSToby Isaac } 3431f30e825dSToby Isaac else { 34329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec,p,&cDof)); 3433f30e825dSToby Isaac } 3434f30e825dSToby Isaac 34359566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f])); 3436f30e825dSToby Isaac } 34379566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart])); 3438f30e825dSToby Isaac } 34399566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats)); 3440f30e825dSToby Isaac PetscFunctionReturn(0); 3441f30e825dSToby Isaac } 3442f30e825dSToby Isaac 3443ebf164c7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree,Mat *injRef) 3444154bca37SToby Isaac { 3445ebf164c7SToby Isaac Mat cMatRef; 34466148253fSToby Isaac PetscObject injRefObj; 34478d2f55e7SToby Isaac 3448154bca37SToby Isaac PetscFunctionBegin; 34499566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,NULL,&cMatRef,NULL)); 34509566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",&injRefObj)); 3451ebf164c7SToby Isaac *injRef = (Mat) injRefObj; 3452ebf164c7SToby Isaac if (!*injRef) { 34539566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorReferenceTree(refTree,injRef)); 34549566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",(PetscObject)*injRef)); 3455ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 34569566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)*injRef)); 3457ebf164c7SToby Isaac } 3458ebf164c7SToby Isaac PetscFunctionReturn(0); 34596148253fSToby Isaac } 3460f30e825dSToby Isaac 3461c921d74cSToby Isaac 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) 3462ebf164c7SToby Isaac { 3463c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3464ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3465ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3466c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3467c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3468c921d74cSToby Isaac const PetscInt *rootDegrees; 3469c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3470ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3471ebf164c7SToby Isaac 3472ebf164c7SToby Isaac PetscFunctionBegin; 34739566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse,&pStartC,&pEndC)); 34749566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine,&pStartF,&pEndF)); 34759566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine,&localFine)); 34769566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine,&globalFine)); 34779566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec)); 34789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafIndicesSec,pStartF, pEndF)); 34799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine,&maxDof)); 34808d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 34817e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 34827e96bdafSToby Isaac const PetscInt *leaves; 34838d2f55e7SToby Isaac 34849566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL)); 34857e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 34867e96bdafSToby Isaac p = leaves ? leaves[l] : l; 34879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&dof)); 34889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 34898d2f55e7SToby Isaac if ((dof - cdof) > 0) { 34908d2f55e7SToby Isaac numPointsWithDofs++; 3491f30e825dSToby Isaac 34929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine,p,&dof)); 34939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafIndicesSec,p,dof + 1)); 34948d2f55e7SToby Isaac } 34958d2f55e7SToby Isaac } 34969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs,&pointsWithDofs)); 34979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafIndicesSec)); 34989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec,&numIndices)); 34999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1),&leafInds)); 35009566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(PetscMalloc1(numIndices,&leafVals)); 35017e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 35027e96bdafSToby Isaac p = leaves ? leaves[l] : l; 35039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&dof)); 35049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 35058d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3506f30e825dSToby Isaac PetscInt off, gOff; 3507f30e825dSToby Isaac PetscInt *pInd; 3508c921d74cSToby Isaac PetscScalar *pVal = NULL; 3509f30e825dSToby Isaac 35107e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3511f30e825dSToby Isaac 35129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec,p,&off)); 3513f30e825dSToby Isaac 3514c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3515c921d74cSToby Isaac if (gatheredValues) { 3516c921d74cSToby Isaac PetscInt i; 3517c921d74cSToby Isaac 3518c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3519c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3520c921d74cSToby Isaac } 35219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine,p,&gOff)); 3522f30e825dSToby Isaac 3523f30e825dSToby Isaac offsets[0] = 0; 3524f30e825dSToby Isaac if (numFields) { 3525f30e825dSToby Isaac PetscInt f; 3526f30e825dSToby Isaac 3527f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3528f30e825dSToby Isaac PetscInt fDof; 35299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine,p,f,&fDof)); 3530f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3531f30e825dSToby Isaac } 35329566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,-1, NULL,pInd)); 3533367003a6SStefano Zampini } else { 35349566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL, NULL,pInd)); 3535f30e825dSToby Isaac } 35369566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(VecGetValues(fineVec,dof,pInd,pVal)); 35378d2f55e7SToby Isaac } 35388d2f55e7SToby Isaac } 35399566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 35409566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 35418d2f55e7SToby Isaac } 3542f30e825dSToby Isaac 35439566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse,&pStartC,&pEndC)); 35449566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse,&localCoarse)); 35459566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse,&globalCoarse)); 3546f30e825dSToby Isaac 35476148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 35486148253fSToby Isaac MPI_Datatype threeInt; 35496148253fSToby Isaac PetscMPIInt rank; 35506148253fSToby Isaac PetscInt (*parentNodeAndIdCoarse)[3]; 35516148253fSToby Isaac PetscInt (*parentNodeAndIdFine)[3]; 35526148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 35536148253fSToby Isaac PetscSF pointSF, sfToParents; 35546148253fSToby Isaac const PetscInt *ilocal; 35556148253fSToby Isaac const PetscSFNode *iremote; 35566148253fSToby Isaac PetscSFNode *iremoteToParents; 35576148253fSToby Isaac PetscInt *ilocalToParents; 35586148253fSToby Isaac 35599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)coarse),&rank)); 35609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3,MPIU_INT,&threeInt)); 35619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&threeInt)); 35629566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndC-pStartC,&parentNodeAndIdCoarse,pEndF-pStartF,&parentNodeAndIdFine)); 35639566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(coarse,&pointSF)); 35649566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF,NULL,&nleaves,&ilocal,&iremote)); 35656148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 35666148253fSToby Isaac PetscInt parent, childId; 35679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(coarse,p,&parent,&childId)); 35686148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 35696148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 35706148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 35716148253fSToby Isaac if (nleaves > 0) { 35726148253fSToby Isaac PetscInt leaf = -1; 35736148253fSToby Isaac 35746148253fSToby Isaac if (ilocal) { 35759566063dSJacob Faibussowitsch PetscCall(PetscFindInt(parent,nleaves,ilocal,&leaf)); 35766148253fSToby Isaac } 35776148253fSToby Isaac else { 35786148253fSToby Isaac leaf = p - pStartC; 35796148253fSToby Isaac } 35806148253fSToby Isaac if (leaf >= 0) { 35816148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 35826148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 35836148253fSToby Isaac } 35846148253fSToby Isaac } 35856148253fSToby Isaac } 35866148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 35876148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 35886148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 35896148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 35906148253fSToby Isaac } 35919566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine,MPI_REPLACE)); 35929566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine,MPI_REPLACE)); 35936148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3594f30e825dSToby Isaac PetscInt dof; 3595f30e825dSToby Isaac 35969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec,p,&dof)); 3597f30e825dSToby Isaac if (dof) { 3598f30e825dSToby Isaac PetscInt off; 3599f30e825dSToby Isaac 36009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec,p,&off)); 3601c921d74cSToby Isaac if (gatheredIndices) { 3602c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3603c921d74cSToby Isaac } else if (gatheredValues) { 3604c921d74cSToby Isaac leafVals[off] = (PetscScalar) PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3605c921d74cSToby Isaac } 3606f30e825dSToby Isaac } 36076148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36086148253fSToby Isaac nleavesToParents++; 36096148253fSToby Isaac } 36106148253fSToby Isaac } 36119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents,&ilocalToParents)); 36129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents,&iremoteToParents)); 36136148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 36146148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36156148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 36166148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p-pStartF][0]; 36176148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p-pStartF][1]; 36186148253fSToby Isaac nleavesToParents++; 36196148253fSToby Isaac } 36206148253fSToby Isaac } 36219566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)coarse),&sfToParents)); 36229566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfToParents,pEndC-pStartC,nleavesToParents,ilocalToParents,PETSC_OWN_POINTER,iremoteToParents,PETSC_OWN_POINTER)); 36239566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 36246148253fSToby Isaac 36256148253fSToby Isaac coarseToFineEmbedded = sfToParents; 36266148253fSToby Isaac 36279566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentNodeAndIdCoarse,parentNodeAndIdFine)); 36289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&threeInt)); 36296148253fSToby Isaac } 3630f30e825dSToby Isaac 36316148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 36326148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 36336148253fSToby Isaac PetscSF sfDofsOnly; 36346148253fSToby Isaac 36356148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 36369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse,p,&dof)); 36379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 36386148253fSToby Isaac if ((dof - cdof) > 0) { 36396148253fSToby Isaac numPointsWithDofs++; 36406148253fSToby Isaac } 36416148253fSToby Isaac } 36429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs,&pointsWithDofs)); 36436148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 36449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse,p,&dof)); 36459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 36466148253fSToby Isaac if ((dof - cdof) > 0) { 3647e03d9830SToby Isaac pointsWithDofs[offset++] = p - pStartC; 36486148253fSToby Isaac } 36496148253fSToby Isaac } 36509566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly)); 36519566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 36529566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 36536148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 36546148253fSToby Isaac } 3655f30e825dSToby Isaac 36566148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 36579566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(coarseToFineEmbedded,&rootDegrees)); 36589566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(coarseToFineEmbedded,&rootDegrees)); 36599566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&multiRootSec)); 36609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(multiRootSec,pStartC,pEndC)); 36618d2f55e7SToby Isaac for (p = pStartC; p < pEndC; p++) { 36629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(multiRootSec,p,rootDegrees[p-pStartC])); 36638d2f55e7SToby Isaac } 36649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(multiRootSec)); 36659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(multiRootSec,&numMulti)); 36669566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec)); 3667f30e825dSToby Isaac { /* distribute the leaf section */ 3668f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3669f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 36708d2f55e7SToby Isaac 36719566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(coarseToFineEmbedded,&multi)); 36729566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(multi,&multiInv)); 36739566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(multiInv,leafIndicesSec,&remoteOffsets,rootIndicesSec)); 36749566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(multiInv,leafIndicesSec,remoteOffsets,rootIndicesSec,&indicesSF)); 36759566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 36769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&multiInv)); 36779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices)); 3678c921d74cSToby Isaac if (gatheredIndices) { 36799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices,&rootInds)); 36809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF,MPIU_INT,leafInds,rootInds,MPI_REPLACE)); 36819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF,MPIU_INT,leafInds,rootInds,MPI_REPLACE)); 3682c921d74cSToby Isaac } 3683c921d74cSToby Isaac if (gatheredValues) { 36849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices,&rootVals)); 36859566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF,MPIU_SCALAR,leafVals,rootVals,MPI_REPLACE)); 36869566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF,MPIU_SCALAR,leafVals,rootVals,MPI_REPLACE)); 3687c921d74cSToby Isaac } 36889566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF)); 36898d2f55e7SToby Isaac } 36909566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec)); 36919566063dSJacob Faibussowitsch PetscCall(PetscFree(leafInds)); 36929566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVals)); 36939566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 3694c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3695c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3696c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3697c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 3698ebf164c7SToby Isaac PetscFunctionReturn(0); 3699ebf164c7SToby Isaac } 3700ebf164c7SToby Isaac 3701ebf164c7SToby Isaac PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3702ebf164c7SToby Isaac { 3703ebf164c7SToby Isaac DM refTree; 3704c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3705ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3706ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3707ebf164c7SToby Isaac PetscSection cSecRef; 3708277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd; 3709ebf164c7SToby Isaac Mat injRef; 3710c921d74cSToby Isaac PetscInt numFields, maxDof; 3711ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3712ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3713ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3714ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3715ebf164c7SToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3716ebf164c7SToby Isaac 3717ebf164c7SToby Isaac PetscFunctionBegin; 3718ebf164c7SToby Isaac 3719ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 37209566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse,&refTree)); 37219566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&cSecRef,NULL,NULL)); 37229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd)); 37239566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree,&injRef)); 3724ebf164c7SToby Isaac 37259566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine,&pStartF,&pEndF)); 37269566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine,&localFine)); 37279566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine,&globalFine)); 37289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine,&numFields)); 37299566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse,&pStartC,&pEndC)); 37309566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse,&localCoarse)); 37319566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse,&globalCoarse)); 37329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse,&maxDof)); 3733ebf164c7SToby Isaac { 3734ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 37359566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets)); 3736ebf164c7SToby Isaac } 3737ebf164c7SToby Isaac 37389566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse,fine,coarseToFine,childIds,NULL,numFields,offsets,&multiRootSec,&rootIndicesSec,&rootIndices,NULL)); 37398d2f55e7SToby Isaac 37409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof,&parentIndices)); 3741f30e825dSToby Isaac 3742f30e825dSToby Isaac /* count indices */ 37439566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat,&rowMap,&colMap)); 37449566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 37459566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 37469566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap,&rowStart,&rowEnd)); 37479566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap,&colStart,&colEnd)); 37489566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(rowEnd-rowStart,&nnzD,rowEnd-rowStart,&nnzO)); 3749f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3750f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 37518d2f55e7SToby Isaac 37529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse,p,&dof)); 37539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 3754f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 37559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse,p,&gOff)); 37568d2f55e7SToby Isaac 37578d2f55e7SToby Isaac rowOffsets[0] = 0; 3758f30e825dSToby Isaac offsetsCopy[0] = 0; 37598d2f55e7SToby Isaac if (numFields) { 37608d2f55e7SToby Isaac PetscInt f; 37618d2f55e7SToby Isaac 3762f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3763f30e825dSToby Isaac PetscInt fDof; 37649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 3765f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 37668d2f55e7SToby Isaac } 37679566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,parentIndices)); 3768367003a6SStefano Zampini } else { 37699566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,parentIndices)); 3770f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 37718d2f55e7SToby Isaac } 3772f30e825dSToby Isaac 37739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec,p,&numLeaves)); 37749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec,p,&leafStart)); 3775f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3776f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3777f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3778f30e825dSToby Isaac const PetscInt *childIndices; 3779f30e825dSToby Isaac 37809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec,l,&numIndices)); 37819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec,l,&offset)); 3782f30e825dSToby Isaac childId = rootIndices[offset++]; 3783f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3784f30e825dSToby Isaac numIndices--; 3785f30e825dSToby Isaac 3786f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3787f30e825dSToby Isaac PetscInt i; 3788f30e825dSToby Isaac 3789f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3790f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3791f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3792f30e825dSToby Isaac if (rowIndex < 0) continue; 379308401ef6SPierre Jolivet PetscCheck(colIndex >= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unconstrained fine and constrained coarse"); 3794a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3795f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 3796f30e825dSToby Isaac } 3797f30e825dSToby Isaac else { 3798f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3799f30e825dSToby Isaac } 3800f30e825dSToby Isaac } 3801f30e825dSToby Isaac } 3802f30e825dSToby Isaac else { 3803f30e825dSToby Isaac PetscInt parentId, f, lim; 3804f30e825dSToby Isaac 38059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,childId,&parentId,NULL)); 3806f30e825dSToby Isaac 3807f30e825dSToby Isaac lim = PetscMax(1,numFields); 3808f30e825dSToby Isaac offsets[0] = 0; 38098d2f55e7SToby Isaac if (numFields) { 38108d2f55e7SToby Isaac PetscInt f; 3811f30e825dSToby Isaac 38128d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3813f30e825dSToby Isaac PetscInt fDof; 38149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef,childId,f,&fDof)); 3815f30e825dSToby Isaac 3816f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 38178d2f55e7SToby Isaac } 38188d2f55e7SToby Isaac } 38198d2f55e7SToby Isaac else { 3820f30e825dSToby Isaac PetscInt cDof; 3821f30e825dSToby Isaac 38229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef,childId,&cDof)); 3823f30e825dSToby Isaac offsets[1] = cDof; 3824f30e825dSToby Isaac } 3825f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3826f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3827f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3828f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3829f30e825dSToby Isaac 3830f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3831f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3832f30e825dSToby Isaac 3833f30e825dSToby Isaac if (colIndex < 0) continue; 3834f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3835f30e825dSToby Isaac numD++; 3836f30e825dSToby Isaac } 3837f30e825dSToby Isaac else { 3838f30e825dSToby Isaac numO++; 3839f30e825dSToby Isaac } 3840f30e825dSToby Isaac } 3841f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3842f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3843f30e825dSToby Isaac 3844f30e825dSToby Isaac if (rowIndex < 0) continue; 3845f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3846f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 38478d2f55e7SToby Isaac } 38488d2f55e7SToby Isaac } 38498d2f55e7SToby Isaac } 3850f30e825dSToby Isaac } 3851f30e825dSToby Isaac } 3852f30e825dSToby Isaac /* preallocate */ 38539566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat,1,nnzD,nnzO,NULL,NULL)); 38549566063dSJacob Faibussowitsch PetscCall(PetscFree2(nnzD,nnzO)); 3855f30e825dSToby Isaac /* insert values */ 38569566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats)); 3857f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3858f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3859f30e825dSToby Isaac 38609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse,p,&dof)); 38619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 3862f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 38639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse,p,&gOff)); 3864f30e825dSToby Isaac 3865f30e825dSToby Isaac rowOffsets[0] = 0; 3866f30e825dSToby Isaac offsetsCopy[0] = 0; 38678d2f55e7SToby Isaac if (numFields) { 38688d2f55e7SToby Isaac PetscInt f; 3869f30e825dSToby Isaac 38708d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3871f30e825dSToby Isaac PetscInt fDof; 38729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 3873f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3874f30e825dSToby Isaac } 38759566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,parentIndices)); 3876367003a6SStefano Zampini } else { 38779566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,parentIndices)); 3878f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3879f30e825dSToby Isaac } 3880f30e825dSToby Isaac 38819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec,p,&numLeaves)); 38829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec,p,&leafStart)); 3883f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3884f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3885f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3886f30e825dSToby Isaac const PetscInt *childIndices; 3887f30e825dSToby Isaac 38889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec,l,&numIndices)); 38899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec,l,&offset)); 3890f30e825dSToby Isaac childId = rootIndices[offset++]; 3891f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3892f30e825dSToby Isaac numIndices--; 3893f30e825dSToby Isaac 3894f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3895f30e825dSToby Isaac PetscInt i; 3896f30e825dSToby Isaac 3897f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 38989566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat,parentIndices[i],childIndices[i],1.,INSERT_VALUES)); 38998d2f55e7SToby Isaac } 39008d2f55e7SToby Isaac } 39018d2f55e7SToby Isaac else { 3902f30e825dSToby Isaac PetscInt parentId, f, lim; 39038d2f55e7SToby Isaac 39049566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,childId,&parentId,NULL)); 3905f30e825dSToby Isaac 3906f30e825dSToby Isaac lim = PetscMax(1,numFields); 3907f30e825dSToby Isaac offsets[0] = 0; 39088d2f55e7SToby Isaac if (numFields) { 3909f30e825dSToby Isaac PetscInt f; 39108d2f55e7SToby Isaac 3911f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3912f30e825dSToby Isaac PetscInt fDof; 39139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef,childId,f,&fDof)); 3914f30e825dSToby Isaac 3915f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 39168d2f55e7SToby Isaac } 39178d2f55e7SToby Isaac } 39188d2f55e7SToby Isaac else { 3919f30e825dSToby Isaac PetscInt cDof; 3920f30e825dSToby Isaac 39219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef,childId,&cDof)); 3922f30e825dSToby Isaac offsets[1] = cDof; 39238d2f55e7SToby Isaac } 3924f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3925f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3926f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3927f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3928f30e825dSToby Isaac 39299566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,rowOffsets[f+1]-rowOffsets[f],rowIndices,offsets[f+1]-offsets[f],colIndices,childMat,INSERT_VALUES)); 39308d2f55e7SToby Isaac } 39318d2f55e7SToby Isaac } 39328d2f55e7SToby Isaac } 39338d2f55e7SToby Isaac } 39349566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 39359566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 39369566063dSJacob Faibussowitsch PetscCall(PetscFree(parentIndices)); 39379566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats)); 39389566063dSJacob Faibussowitsch PetscCall(PetscFree(rootIndices)); 39399566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets,offsetsCopy,rowOffsets)); 3940f30e825dSToby Isaac 39419566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 39429566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 3943154bca37SToby Isaac PetscFunctionReturn(0); 3944154bca37SToby Isaac } 394538fc2455SToby Isaac 39460eb7e1eaSToby Isaac static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 3947ebf164c7SToby Isaac { 394862095d54SToby Isaac PetscSF coarseToFineEmbedded; 394962095d54SToby Isaac PetscSection globalCoarse, globalFine; 395062095d54SToby Isaac PetscSection localCoarse, localFine; 395162095d54SToby Isaac PetscSection aSec, cSec; 395262095d54SToby Isaac PetscSection rootValuesSec; 395362095d54SToby Isaac PetscSection leafValuesSec; 395462095d54SToby Isaac PetscScalar *rootValues, *leafValues; 395562095d54SToby Isaac IS aIS; 395662095d54SToby Isaac const PetscInt *anchors; 395762095d54SToby Isaac Mat cMat; 395862095d54SToby Isaac PetscInt numFields; 3959412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd; 396062095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 396162095d54SToby Isaac PetscInt *maxChildIds; 396262095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 39630eb7e1eaSToby Isaac PetscFV fv = NULL; 39640eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 39650eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 39660eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 39670eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 396862095d54SToby Isaac 3969ebf164c7SToby Isaac PetscFunctionBegin; 39709566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE)); 39719566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse,&pStartC,&pEndC)); 39729566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(coarse,0,&cellStart,&cellEnd)); 39739566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine,&pStartF,&pEndF)); 39749566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine,&globalFine)); 39759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(coarse,&dim)); 397662095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 3977e4a60869SToby Isaac PetscInt nleaves, l; 3978e4a60869SToby Isaac const PetscInt *leaves; 397962095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 398062095d54SToby Isaac 39819566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL)); 3982e4a60869SToby Isaac 3983e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 3984e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3985e4a60869SToby Isaac 39869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&dof)); 39879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 398862095d54SToby Isaac if ((dof - cdof) > 0) { 398962095d54SToby Isaac numPointsWithDofs++; 399062095d54SToby Isaac } 399162095d54SToby Isaac } 39929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs,&pointsWithDofs)); 39934833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 3994e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3995e4a60869SToby Isaac 39969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&dof)); 39979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 399862095d54SToby Isaac if ((dof - cdof) > 0) { 3999e4a60869SToby Isaac pointsWithDofs[offset++] = l; 400062095d54SToby Isaac } 400162095d54SToby Isaac } 40029566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 40039566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs)); 400462095d54SToby Isaac } 400562095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 40069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC-pStartC,&maxChildIds)); 400762095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 400862095d54SToby Isaac maxChildIds[p - pStartC] = -2; 400962095d54SToby Isaac } 40109566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX)); 40119566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX)); 401262095d54SToby Isaac 40139566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse,&localCoarse)); 40149566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse,&globalCoarse)); 401562095d54SToby Isaac 40169566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse,&aSec,&aIS)); 40179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS,&anchors)); 40189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd)); 401962095d54SToby Isaac 40209566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse,&cSec,&cMat,NULL)); 40219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec,&cStart,&cEnd)); 402262095d54SToby Isaac 402362095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 40249566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootValuesSec)); 40259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootValuesSec,pStartC,pEndC)); 40269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse,&numFields)); 402762095d54SToby Isaac { 402862095d54SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 40299566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO)); 403062095d54SToby Isaac } 40310eb7e1eaSToby Isaac if (grad) { 40320eb7e1eaSToby Isaac PetscInt i; 40330eb7e1eaSToby Isaac 40349566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeom,&cellDM)); 40359566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeom,&cellGeomArray)); 40369566063dSJacob Faibussowitsch PetscCall(VecGetDM(grad,&gradDM)); 40379566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(grad,&gradArray)); 40380eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1,numFields); i++) { 40390eb7e1eaSToby Isaac PetscObject obj; 40400eb7e1eaSToby Isaac PetscClassId id; 40410eb7e1eaSToby Isaac 40429566063dSJacob Faibussowitsch PetscCall(DMGetField(coarse, i, NULL, &obj)); 40439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj,&id)); 40440eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 40450eb7e1eaSToby Isaac fv = (PetscFV) obj; 40469566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv,&numFVcomps)); 40470eb7e1eaSToby Isaac fvField = i; 40480eb7e1eaSToby Isaac break; 40490eb7e1eaSToby Isaac } 40500eb7e1eaSToby Isaac } 40510eb7e1eaSToby Isaac } 405262095d54SToby Isaac 405362095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 405462095d54SToby Isaac PetscInt dof; 405562095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 405662095d54SToby Isaac PetscInt numValues = 0; 405762095d54SToby Isaac 40589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse,p,&dof)); 405962095d54SToby Isaac if (dof < 0) { 406062095d54SToby Isaac dof = -(dof + 1); 406162095d54SToby Isaac } 406262095d54SToby Isaac offsets[0] = 0; 406362095d54SToby Isaac newOffsets[0] = 0; 406462095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 406562095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 406662095d54SToby Isaac 40679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure)); 406862095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 406962095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 407062095d54SToby Isaac 40719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse,c,&clDof)); 407262095d54SToby Isaac numValues += clDof; 407362095d54SToby Isaac } 40749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure)); 407562095d54SToby Isaac } 407662095d54SToby Isaac else if (maxChildId == -1) { 40779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse,p,&numValues)); 407862095d54SToby Isaac } 407962095d54SToby Isaac /* we will pack the column indices with the field offsets */ 408078b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 40810eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 40820eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 40830eb7e1eaSToby Isaac } 40849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootValuesSec,p,numValues)); 408562095d54SToby Isaac } 40869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootValuesSec)); 408762095d54SToby Isaac { 408862095d54SToby Isaac PetscInt numRootValues; 408962095d54SToby Isaac const PetscScalar *coarseArray; 409062095d54SToby Isaac 40919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootValuesSec,&numRootValues)); 40929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootValues,&rootValues)); 40939566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecCoarseLocal,&coarseArray)); 409462095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 409562095d54SToby Isaac PetscInt numValues; 409662095d54SToby Isaac PetscInt pValOff; 409762095d54SToby Isaac PetscScalar *pVal; 409862095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 409962095d54SToby Isaac 41009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootValuesSec,p,&numValues)); 410162095d54SToby Isaac if (!numValues) { 410262095d54SToby Isaac continue; 410362095d54SToby Isaac } 41049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootValuesSec,p,&pValOff)); 410562095d54SToby Isaac pVal = &(rootValues[pValOff]); 410662095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 41070eb7e1eaSToby Isaac PetscInt closureSize = numValues; 41089566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(coarse,NULL,vecCoarseLocal,p,&closureSize,&pVal)); 41090eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 4110193eb951SToby Isaac PetscFVCellGeom *cg; 41116dd00756SToby Isaac PetscScalar *gradVals = NULL; 41120eb7e1eaSToby Isaac PetscInt i; 41130eb7e1eaSToby Isaac 41140eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 41150eb7e1eaSToby Isaac 41169566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(cellDM,p,cellGeomArray,(void *) &cg)); 41170eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 41180eb7e1eaSToby Isaac pVal += dim; 41199566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRead(gradDM,p,gradArray,(void *) &gradVals)); 41200eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 41210eb7e1eaSToby Isaac } 412262095d54SToby Isaac } 412378b7adb5SToby Isaac else if (maxChildId == -1) { 412478b7adb5SToby Isaac PetscInt lDof, lOff, i; 412578b7adb5SToby Isaac 41269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse,p,&lDof)); 41279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse,p,&lOff)); 412878b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 412978b7adb5SToby Isaac } 413078b7adb5SToby Isaac } 41319566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecCoarseLocal,&coarseArray)); 41329566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds)); 413362095d54SToby Isaac } 413462095d54SToby Isaac { 413562095d54SToby Isaac PetscSF valuesSF; 413662095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 413762095d54SToby Isaac 41389566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafValuesSec)); 41399566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded,rootValuesSec,&remoteOffsetsValues,leafValuesSec)); 41409566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded,rootValuesSec,remoteOffsetsValues,leafValuesSec,&valuesSF)); 41419566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded)); 41429566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsValues)); 41439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafValuesSec,&numLeafValues)); 41449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeafValues,&leafValues)); 41459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(valuesSF,MPIU_SCALAR,rootValues,leafValues,MPI_REPLACE)); 41469566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(valuesSF,MPIU_SCALAR,rootValues,leafValues,MPI_REPLACE)); 41479566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&valuesSF)); 41489566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 41499566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootValuesSec)); 415062095d54SToby Isaac } 41519566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine,&localFine)); 415262095d54SToby Isaac { 415362095d54SToby Isaac PetscInt maxDof; 415462095d54SToby Isaac PetscInt *rowIndices; 415562095d54SToby Isaac DM refTree; 415662095d54SToby Isaac PetscInt **refPointFieldN; 415762095d54SToby Isaac PetscScalar ***refPointFieldMats; 415862095d54SToby Isaac PetscSection refConSec, refAnSec; 41590eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,leafStart,leafEnd; 416062095d54SToby Isaac PetscScalar *pointWork; 416162095d54SToby Isaac 41629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine,&maxDof)); 41639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine,maxDof,MPIU_INT,&rowIndices)); 41649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine,maxDof,MPIU_SCALAR,&pointWork)); 41659566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine,&refTree)); 41669566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(fine,refTree)); 41679566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 41689566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 41699566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree,&refAnSec,NULL)); 41709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 41719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafValuesSec,&leafStart,&leafEnd)); 41729566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(fine,0,&cellStart,&cellEnd)); 41730eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 417462095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 417562095d54SToby Isaac PetscInt numValues, pValOff; 417662095d54SToby Isaac PetscInt childId; 417762095d54SToby Isaac const PetscScalar *pVal; 41780eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 417962095d54SToby Isaac 41809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine,p,&gDof)); 41819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine,p,&lDof)); 41829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine,p,&gcDof)); 418362095d54SToby Isaac if ((gDof - gcDof) <= 0) { 418462095d54SToby Isaac continue; 418562095d54SToby Isaac } 41869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine,p,&gOff)); 41879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafValuesSec,p,&numValues)); 418862095d54SToby Isaac if (!numValues) continue; 41899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafValuesSec,p,&pValOff)); 419062095d54SToby Isaac pVal = &leafValues[pValOff]; 419162095d54SToby Isaac offsets[0] = 0; 419262095d54SToby Isaac offsetsCopy[0] = 0; 419362095d54SToby Isaac newOffsets[0] = 0; 419462095d54SToby Isaac newOffsetsCopy[0] = 0; 41954833aeb0SToby Isaac childId = cids[p - pStartF]; 419662095d54SToby Isaac if (numFields) { 419762095d54SToby Isaac PetscInt f; 419862095d54SToby Isaac for (f = 0; f < numFields; f++) { 419962095d54SToby Isaac PetscInt rowDof; 420062095d54SToby Isaac 42019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine,p,f,&rowDof)); 420262095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 420362095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 420462095d54SToby Isaac /* TODO: closure indices */ 42059f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 420662095d54SToby Isaac } 42079566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1,NULL,rowIndices)); 420862095d54SToby Isaac } 420962095d54SToby Isaac else { 42104833aeb0SToby Isaac offsets[0] = 0; 42114833aeb0SToby Isaac offsets[1] = lDof; 42124833aeb0SToby Isaac newOffsets[0] = 0; 42134833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 42149566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,NULL,rowIndices)); 421562095d54SToby Isaac } 421662095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 42179566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine,numValues,rowIndices,pVal,INSERT_VALUES)); 421862095d54SToby Isaac } else { 421962095d54SToby Isaac PetscInt f; 422062095d54SToby Isaac 422178b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 422278b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 422378b7adb5SToby Isaac fvGradData = &pVal[numValues]; 422478b7adb5SToby Isaac } 422562095d54SToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 422662095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 422762095d54SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 422862095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 422962095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 423062095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 423162095d54SToby Isaac PetscInt i, j; 423262095d54SToby Isaac 4233708c7f19SToby Isaac #if 0 423463a3b9bcSJacob 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)); 4235708c7f19SToby Isaac #endif 423662095d54SToby Isaac for (i = 0; i < numRows; i++) { 423762095d54SToby Isaac PetscScalar val = 0.; 423862095d54SToby Isaac for (j = 0; j < numCols; j++) { 423962095d54SToby Isaac val += childMat[i * numCols + j] * cVal[j]; 424062095d54SToby Isaac } 424162095d54SToby Isaac rVal[i] = val; 424262095d54SToby Isaac } 42430eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 42440eb7e1eaSToby Isaac PetscReal centroid[3]; 42450eb7e1eaSToby Isaac PetscScalar diff[3]; 42460eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 42470eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 42480eb7e1eaSToby Isaac 42499566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(fine,p,NULL,centroid,NULL)); 42500eb7e1eaSToby Isaac for (i = 0; i < dim; i++) { 42510eb7e1eaSToby Isaac diff[i] = centroid[i] - parentCentroid[i]; 42520eb7e1eaSToby Isaac } 42530eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 42540eb7e1eaSToby Isaac PetscScalar val = 0.; 42550eb7e1eaSToby Isaac 425689698031SToby Isaac for (j = 0; j < dim; j++) { 42570eb7e1eaSToby Isaac val += gradient[dim * i + j] * diff[j]; 42580eb7e1eaSToby Isaac } 42590eb7e1eaSToby Isaac rVal[i] += val; 42600eb7e1eaSToby Isaac } 42610eb7e1eaSToby Isaac } 42629566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine,numRows,&rowIndices[offsets[f]],rVal,INSERT_VALUES)); 426362095d54SToby Isaac } 426462095d54SToby Isaac } 426562095d54SToby Isaac } 42669566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 42679566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine,maxDof,MPIU_SCALAR,&pointWork)); 42689566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine,maxDof,MPIU_INT,&rowIndices)); 426962095d54SToby Isaac } 42709566063dSJacob Faibussowitsch PetscCall(PetscFree(leafValues)); 42719566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafValuesSec)); 42729566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO)); 42739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS,&anchors)); 4274ebf164c7SToby Isaac PetscFunctionReturn(0); 4275ebf164c7SToby Isaac } 4276ebf164c7SToby Isaac 4277ebf164c7SToby Isaac static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4278ebf164c7SToby Isaac { 4279c921d74cSToby Isaac DM refTree; 4280c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4281c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4282c921d74cSToby Isaac PetscSection localCoarse, localFine; 4283c921d74cSToby Isaac PetscSection cSecRef; 4284c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4285d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4286c921d74cSToby Isaac Mat injRef; 4287c921d74cSToby Isaac PetscInt numFields, maxDof; 4288c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4289c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4290c921d74cSToby Isaac PetscLayout rowMap, colMap; 4291c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4292c921d74cSToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4293c921d74cSToby Isaac 4294ebf164c7SToby Isaac PetscFunctionBegin; 4295c921d74cSToby Isaac 4296c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 42979566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE)); 42989566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecCoarse,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE)); 42999566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse,&refTree)); 43009566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(coarse,refTree)); 43019566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree,&cSecRef,NULL,NULL)); 43029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd)); 43039566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree,&injRef)); 4304c921d74cSToby Isaac 43059566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine,&pStartF,&pEndF)); 43069566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine,&localFine)); 43079566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine,&globalFine)); 43089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine,&numFields)); 43099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse,&pStartC,&pEndC)); 43109566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse,&localCoarse)); 43119566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse,&globalCoarse)); 43129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse,&maxDof)); 4313c921d74cSToby Isaac { 4314c921d74cSToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 43159566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets)); 4316c921d74cSToby Isaac } 4317c921d74cSToby Isaac 43189566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse,fine,coarseToFine,cids,vecFine,numFields,offsets,&multiRootSec,&rootIndicesSec,NULL,&rootValues)); 4319c921d74cSToby Isaac 43209566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxDof,&parentIndices,maxDof,&parentValues)); 4321c921d74cSToby Isaac 4322c921d74cSToby Isaac /* count indices */ 43239566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecFine,&colMap)); 43249566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecCoarse,&rowMap)); 43259566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap)); 43269566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap)); 43279566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap,&rowStart,&rowEnd)); 43289566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap,&colStart,&colEnd)); 4329c921d74cSToby Isaac /* insert values */ 43309566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats)); 4331c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4332c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 433378b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4334c921d74cSToby Isaac 43359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse,p,&dof)); 43369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 4337c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 43389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse,p,&dof)); 43399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse,p,&gOff)); 4340c921d74cSToby Isaac 4341c921d74cSToby Isaac rowOffsets[0] = 0; 4342c921d74cSToby Isaac offsetsCopy[0] = 0; 4343c921d74cSToby Isaac if (numFields) { 4344c921d74cSToby Isaac PetscInt f; 4345c921d74cSToby Isaac 4346c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4347c921d74cSToby Isaac PetscInt fDof; 43489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 4349c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4350c921d74cSToby Isaac } 43519566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1,NULL,parentIndices)); 4352367003a6SStefano Zampini } else { 43539566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,NULL,parentIndices)); 4354c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4355c921d74cSToby Isaac } 4356c921d74cSToby Isaac 43579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec,p,&numLeaves)); 43589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec,p,&leafStart)); 4359c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 43602f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4361c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4362c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4363c921d74cSToby Isaac const PetscScalar *childValues; 4364c921d74cSToby Isaac 43659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec,l,&numIndices)); 43669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec,l,&offset)); 4367c921d74cSToby Isaac childId = (PetscInt) PetscRealPart(rootValues[offset++]); 4368c921d74cSToby Isaac childValues = &rootValues[offset]; 4369c921d74cSToby Isaac numIndices--; 4370c921d74cSToby Isaac 4371c921d74cSToby Isaac if (childId == -2) { /* skip */ 4372c921d74cSToby Isaac continue; 4373c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 43742f65e181SToby Isaac PetscInt m; 43752f65e181SToby Isaac 437678b7adb5SToby Isaac contribute = PETSC_TRUE; 43772f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4378beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4379d3bc4906SToby Isaac PetscInt parentId, f, lim; 4380d3bc4906SToby Isaac 438178b7adb5SToby Isaac contribute = PETSC_TRUE; 43829566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,childId,&parentId,NULL)); 4383d3bc4906SToby Isaac 4384d3bc4906SToby Isaac lim = PetscMax(1,numFields); 4385d3bc4906SToby Isaac offsets[0] = 0; 4386d3bc4906SToby Isaac if (numFields) { 4387d3bc4906SToby Isaac PetscInt f; 4388d3bc4906SToby Isaac 4389d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4390d3bc4906SToby Isaac PetscInt fDof; 43919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef,childId,f,&fDof)); 4392d3bc4906SToby Isaac 4393d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4394d3bc4906SToby Isaac } 4395d3bc4906SToby Isaac } 4396d3bc4906SToby Isaac else { 4397d3bc4906SToby Isaac PetscInt cDof; 4398d3bc4906SToby Isaac 43999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef,childId,&cDof)); 4400d3bc4906SToby Isaac offsets[1] = cDof; 4401d3bc4906SToby Isaac } 4402d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4403d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4404d3bc4906SToby Isaac PetscInt n = offsets[f+1]-offsets[f]; 4405e328ff09SToby Isaac PetscInt m = rowOffsets[f+1]-rowOffsets[f]; 4406d3bc4906SToby Isaac PetscInt i, j; 4407d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4408d3bc4906SToby Isaac 4409e328ff09SToby Isaac for (i = 0; i < m; i++) { 4410d3bc4906SToby Isaac PetscScalar val = 0.; 4411d3bc4906SToby Isaac for (j = 0; j < n; j++) { 4412d3bc4906SToby Isaac val += childMat[n * i + j] * colValues[j]; 4413d3bc4906SToby Isaac } 4414e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val; 4415d3bc4906SToby Isaac } 4416d3bc4906SToby Isaac } 4417c921d74cSToby Isaac } 4418c921d74cSToby Isaac } 44199566063dSJacob Faibussowitsch if (contribute) PetscCall(VecSetValues(vecCoarse,dof,parentIndices,parentValues,INSERT_VALUES)); 4420c921d74cSToby Isaac } 44219566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec)); 44229566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec)); 44239566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentIndices,parentValues)); 44249566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats)); 44259566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues)); 44269566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets,offsetsCopy,rowOffsets)); 4427ebf164c7SToby Isaac PetscFunctionReturn(0); 4428ebf164c7SToby Isaac } 4429ebf164c7SToby Isaac 4430ff1f73f7SToby Isaac /*@ 4431ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4432ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4433ff1f73f7SToby Isaac coarsening and refinement at the same time. 4434ff1f73f7SToby Isaac 4435ff1f73f7SToby Isaac collective 4436ff1f73f7SToby Isaac 4437ff1f73f7SToby Isaac Input Parameters: 4438ff1f73f7SToby Isaac + dmIn - The DMPlex mesh for the input vector 4439ff1f73f7SToby Isaac . vecIn - The input vector 4440ff1f73f7SToby Isaac . sfRefine - A star forest indicating points in the mesh dmIn (roots in the star forest) that are parents to points in 4441ff1f73f7SToby Isaac the mesh dmOut (leaves in the star forest), i.e. where dmOut is more refined than dmIn 4442ff1f73f7SToby Isaac . sfCoarsen - A star forest indicating points in the mesh dmOut (roots in the star forest) that are parents to points in 4443ff1f73f7SToby Isaac the mesh dmIn (leaves in the star forest), i.e. where dmOut is more coarsened than dmIn 4444ff1f73f7SToby Isaac . cidsRefine - The childIds of the points in dmOut. These childIds relate back to the reference tree: childid[j] = k implies 4445ff1f73f7SToby Isaac that mesh point j of dmOut was refined from a point in dmIn just as the mesh point k in the reference 4446ff1f73f7SToby Isaac tree was refined from its parent. childid[j] = -1 indicates that the point j in dmOut is exactly 4447ff1f73f7SToby Isaac equivalent to its root in dmIn, so no interpolation is necessary. childid[j] = -2 indicates that this 4448ff1f73f7SToby Isaac point j in dmOut is not a leaf of sfRefine. 4449ff1f73f7SToby Isaac . cidsCoarsen - The childIds of the points in dmIn. These childIds relate back to the reference tree: childid[j] = k implies 4450ff1f73f7SToby Isaac that mesh point j of dmIn coarsens to a point in dmOut just as the mesh point k in the reference 4451ff1f73f7SToby Isaac tree coarsens to its parent. childid[j] = -2 indicates that point j in dmOut is not a leaf in sfCoarsen. 4452ff1f73f7SToby Isaac . useBCs - PETSC_TRUE indicates that boundary values should be inserted into vecIn before transfer. 4453ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4454ff1f73f7SToby Isaac 4455ff1f73f7SToby Isaac Output Parameters: 44568966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred 4457ff1f73f7SToby Isaac projection of vecIn from dmIn to dmOut. Note that any field discretized with a PetscFV finite volume 4458ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4459ff1f73f7SToby Isaac coarse points to fine points. 4460ff1f73f7SToby Isaac 4461ff1f73f7SToby Isaac Level: developer 4462ff1f73f7SToby Isaac 4463db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()`, `PetscFVGetComputeGradients()` 4464ff1f73f7SToby Isaac @*/ 4465ff1f73f7SToby Isaac PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) 446638fc2455SToby Isaac { 446738fc2455SToby Isaac PetscFunctionBegin; 44689566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut,0.0)); 4469ff1f73f7SToby Isaac if (sfRefine) { 4470fbfa57b9SToby Isaac Vec vecInLocal; 44710eb7e1eaSToby Isaac DM dmGrad = NULL; 44720eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4473fbfa57b9SToby Isaac 44749566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn,&vecInLocal)); 44759566063dSJacob Faibussowitsch PetscCall(VecSet(vecInLocal,0.0)); 44760eb7e1eaSToby Isaac { 44770eb7e1eaSToby Isaac PetscInt numFields, i; 44780eb7e1eaSToby Isaac 44799566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dmIn, &numFields)); 44800eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 44810eb7e1eaSToby Isaac PetscObject obj; 44820eb7e1eaSToby Isaac PetscClassId classid; 44830eb7e1eaSToby Isaac 44849566063dSJacob Faibussowitsch PetscCall(DMGetField(dmIn, i, NULL, &obj)); 44859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &classid)); 44860eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 44879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dmIn,(PetscFV)obj,&cellGeom,&faceGeom,&dmGrad)); 44880eb7e1eaSToby Isaac break; 44890eb7e1eaSToby Isaac } 44900eb7e1eaSToby Isaac } 44910eb7e1eaSToby Isaac } 4492*1baa6e33SBarry Smith if (useBCs) PetscCall(DMPlexInsertBoundaryValues(dmIn,PETSC_TRUE,vecInLocal,time,faceGeom,cellGeom,NULL)); 44939566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmIn,vecIn,INSERT_VALUES,vecInLocal)); 44949566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmIn,vecIn,INSERT_VALUES,vecInLocal)); 44950eb7e1eaSToby Isaac if (dmGrad) { 44969566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmGrad,&grad)); 44979566063dSJacob Faibussowitsch PetscCall(DMPlexReconstructGradientsFVM(dmIn,vecInLocal,grad)); 44980eb7e1eaSToby Isaac } 44999566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree_Interpolate(dmIn,vecInLocal,dmOut,vecOut,sfRefine,cidsRefine,grad,cellGeom)); 45009566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn,&vecInLocal)); 45010eb7e1eaSToby Isaac if (dmGrad) { 45029566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmGrad,&grad)); 45030eb7e1eaSToby Isaac } 4504ebf164c7SToby Isaac } 4505*1baa6e33SBarry Smith if (sfCoarsen) PetscCall(DMPlexTransferVecTree_Inject(dmIn,vecIn,dmOut,vecOut,sfCoarsen,cidsCoarsen)); 45069566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(vecOut)); 45079566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(vecOut)); 450838fc2455SToby Isaac PetscFunctionReturn(0); 450938fc2455SToby Isaac } 4510