1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2d6a7ad0dSToby Isaac #include <../src/sys/utils/hash.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 5d6a7ad0dSToby Isaac #include <petscsf.h> 60c37af3bSToby Isaac #include <petscds.h> 7d6a7ad0dSToby Isaac 8d6a7ad0dSToby Isaac /** hierarchy routines */ 9d6a7ad0dSToby Isaac 10d6a7ad0dSToby Isaac #undef __FUNCT__ 11d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexSetReferenceTree" 12d6a7ad0dSToby Isaac /*@ 13d6a7ad0dSToby Isaac DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes. 14d6a7ad0dSToby Isaac 15d6a7ad0dSToby Isaac Not collective 16d6a7ad0dSToby Isaac 17d6a7ad0dSToby Isaac Input Parameters: 18d6a7ad0dSToby Isaac + dm - The DMPlex object 19d6a7ad0dSToby Isaac - ref - The reference tree DMPlex object 20d6a7ad0dSToby Isaac 210b7167a0SToby Isaac Level: intermediate 22d6a7ad0dSToby Isaac 23da43764aSToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexCreateDefaultReferenceTree() 24d6a7ad0dSToby Isaac @*/ 25d6a7ad0dSToby Isaac PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 26d6a7ad0dSToby Isaac { 27d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 28d6a7ad0dSToby Isaac PetscErrorCode ierr; 29d6a7ad0dSToby Isaac 30d6a7ad0dSToby Isaac PetscFunctionBegin; 31d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3247a1df27SMatthew G. Knepley if (ref) {PetscValidHeaderSpecific(ref, DM_CLASSID, 2);} 33d6a7ad0dSToby Isaac ierr = PetscObjectReference((PetscObject)ref);CHKERRQ(ierr); 34d6a7ad0dSToby Isaac ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 35d6a7ad0dSToby Isaac mesh->referenceTree = ref; 36d6a7ad0dSToby Isaac PetscFunctionReturn(0); 37d6a7ad0dSToby Isaac } 38d6a7ad0dSToby Isaac 39d6a7ad0dSToby Isaac #undef __FUNCT__ 40d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexGetReferenceTree" 41d6a7ad0dSToby Isaac /*@ 42d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 43d6a7ad0dSToby Isaac 44d6a7ad0dSToby Isaac Not collective 45d6a7ad0dSToby Isaac 46d6a7ad0dSToby Isaac Input Parameters: 47d6a7ad0dSToby Isaac . dm - The DMPlex object 48d6a7ad0dSToby Isaac 49d6a7ad0dSToby Isaac Output Parameters 50d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 51d6a7ad0dSToby Isaac 520b7167a0SToby Isaac Level: intermediate 53d6a7ad0dSToby Isaac 54da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexCreateDefaultReferenceTree() 55d6a7ad0dSToby Isaac @*/ 56d6a7ad0dSToby Isaac PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 57d6a7ad0dSToby Isaac { 58d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 59d6a7ad0dSToby Isaac 60d6a7ad0dSToby Isaac PetscFunctionBegin; 61d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62d6a7ad0dSToby Isaac PetscValidPointer(ref,2); 63d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 64d6a7ad0dSToby Isaac PetscFunctionReturn(0); 65d6a7ad0dSToby Isaac } 66d6a7ad0dSToby Isaac 67dcbd3bf7SToby Isaac #undef __FUNCT__ 68dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry_Default" 69dcbd3bf7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 70dcbd3bf7SToby Isaac { 71dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 72dcbd3bf7SToby Isaac PetscErrorCode ierr; 73dcbd3bf7SToby Isaac 74dcbd3bf7SToby Isaac PetscFunctionBegin; 75dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 76dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 77dcbd3bf7SToby Isaac if (childB) *childB = childA; 78dcbd3bf7SToby Isaac PetscFunctionReturn(0); 79dcbd3bf7SToby Isaac } 80dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 81dcbd3bf7SToby Isaac ierr = DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd);CHKERRQ(ierr); 82dcbd3bf7SToby Isaac if (parent >= dStart && parent <= dEnd) { 83dcbd3bf7SToby Isaac break; 84dcbd3bf7SToby Isaac } 85dcbd3bf7SToby Isaac } 86dcbd3bf7SToby Isaac if (dim > 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %d-cells",dim); 87dcbd3bf7SToby Isaac if (!dim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 88dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 89dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 90dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 91dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 92dcbd3bf7SToby Isaac 93dcbd3bf7SToby Isaac ierr = DMPlexGetSupportSize(dm,childA,&size);CHKERRQ(ierr); 94dcbd3bf7SToby Isaac ierr = DMPlexGetSupport(dm,childA,&supp);CHKERRQ(ierr); 95dcbd3bf7SToby Isaac 96dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 97dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 98dcbd3bf7SToby Isaac PetscInt sParent; 99dcbd3bf7SToby Isaac 100dcbd3bf7SToby Isaac sA = supp[i]; 101dcbd3bf7SToby Isaac if (sA == parent) continue; 102dcbd3bf7SToby Isaac ierr = DMPlexGetTreeParent(dm,sA,&sParent,NULL);CHKERRQ(ierr); 103dcbd3bf7SToby Isaac if (sParent == parent) { 104dcbd3bf7SToby Isaac break; 105dcbd3bf7SToby Isaac } 106dcbd3bf7SToby Isaac } 107dcbd3bf7SToby Isaac if (i == size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 108dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 109dcbd3bf7SToby Isaac * parentOrientB */ 110dcbd3bf7SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry_Default(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB);CHKERRQ(ierr); 111dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,sA,&sConeSize);CHKERRQ(ierr); 112dcbd3bf7SToby Isaac ierr = DMPlexGetCone(dm,sA,&coneA);CHKERRQ(ierr); 113dcbd3bf7SToby Isaac ierr = DMPlexGetCone(dm,sB,&coneB);CHKERRQ(ierr); 114dcbd3bf7SToby Isaac ierr = DMPlexGetConeOrientation(dm,sA,&oA);CHKERRQ(ierr); 115dcbd3bf7SToby Isaac ierr = DMPlexGetConeOrientation(dm,sB,&oB);CHKERRQ(ierr); 116dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 117dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 118dcbd3bf7SToby Isaac if (coneA[i] == childA) { 119dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 120dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 121dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 122dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 123dcbd3bf7SToby Isaac if (childOrientB) { 124dcbd3bf7SToby Isaac PetscInt oBtrue; 125dcbd3bf7SToby Isaac 126dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,childA,&coneSize);CHKERRQ(ierr); 127dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 128dcbd3bf7SToby Isaac if (coneSize != 0 && coneSize != 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 129dcbd3bf7SToby Isaac /* we may have to flip an edge */ 130dcbd3bf7SToby Isaac oBtrue = coneSize ? ((sOrientB >= 0) ? oB[j] : -(oB[j] + 2)) : 0; 131dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize,oA[i],oBtrue);CHKERRQ(ierr); 132dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 133dcbd3bf7SToby Isaac } 134dcbd3bf7SToby Isaac break; 135dcbd3bf7SToby Isaac } 136dcbd3bf7SToby Isaac } 137dcbd3bf7SToby Isaac if (i == sConeSize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 138dcbd3bf7SToby Isaac PetscFunctionReturn(0); 139dcbd3bf7SToby Isaac } 140dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 141dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,parent,&coneSize);CHKERRQ(ierr); 142dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 143dcbd3bf7SToby Isaac if (dim == 2) { 144dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 145dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 146dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 147dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 148dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 149dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 150947b95d8SBarry Smith } else { 151dcbd3bf7SToby Isaac ABswapVert = ABswap; 152dcbd3bf7SToby Isaac } 153dcbd3bf7SToby Isaac if (childB) { 154dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 155dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 156dcbd3bf7SToby Isaac const PetscInt *children; 157dcbd3bf7SToby Isaac 158dcbd3bf7SToby Isaac /* count which position the child is in */ 159dcbd3bf7SToby Isaac ierr = DMPlexGetTreeChildren(dm,parent,&numChildren,&children);CHKERRQ(ierr); 160dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 161dcbd3bf7SToby Isaac p = children[i]; 162dcbd3bf7SToby Isaac if (p == childA) { 163dcbd3bf7SToby Isaac posA = i; 164dcbd3bf7SToby Isaac break; 165dcbd3bf7SToby Isaac } 166dcbd3bf7SToby Isaac } 167dcbd3bf7SToby Isaac if (posA >= coneSize) { 168dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 169dcbd3bf7SToby Isaac * is invariant */ 170dcbd3bf7SToby Isaac if (dim != 2 || posA != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Expected a middle triangle, got something else"); 171dcbd3bf7SToby Isaac *childB = childA; 172dcbd3bf7SToby Isaac } 173dcbd3bf7SToby Isaac else { 174dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 175dcbd3bf7SToby Isaac PetscInt posB; 176dcbd3bf7SToby Isaac 177dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 178dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 179dcbd3bf7SToby Isaac } 180dcbd3bf7SToby Isaac } 181dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 182dcbd3bf7SToby Isaac PetscFunctionReturn(0); 183dcbd3bf7SToby Isaac } 184dcbd3bf7SToby Isaac 185dcbd3bf7SToby Isaac #undef __FUNCT__ 186dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry" 187dcbd3bf7SToby Isaac /*@ 188dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 189dcbd3bf7SToby Isaac 190dcbd3bf7SToby Isaac Input Parameters: 191dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object 192dcbd3bf7SToby Isaac . parent - the parent point 193dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 194dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 195dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 196dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 197dcbd3bf7SToby Isaac 198dcbd3bf7SToby Isaac Output Parameters: 199dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child 200ff1f73f7SToby Isaac - childB - if not NULL, the new childID for describing the child 201dcbd3bf7SToby Isaac 202dcbd3bf7SToby Isaac Level: developer 203dcbd3bf7SToby Isaac 204dcbd3bf7SToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexSetReferenceTree(), DMPlexSetTree() 205dcbd3bf7SToby Isaac @*/ 206dcbd3bf7SToby Isaac PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 207dcbd3bf7SToby Isaac { 208dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 209dcbd3bf7SToby Isaac PetscErrorCode ierr; 210dcbd3bf7SToby Isaac 211dcbd3bf7SToby Isaac PetscFunctionBegin; 212dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 213dcbd3bf7SToby Isaac if (!mesh->getchildsymmetry) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"DMPlexReferenceTreeGetChildSymmetry not implemented"); 214dcbd3bf7SToby Isaac ierr = mesh->getchildsymmetry(dm,parent,parentOrientA,childOrientA,childA,parentOrientB,childOrientB,childB);CHKERRQ(ierr); 215dcbd3bf7SToby Isaac PetscFunctionReturn(0); 216dcbd3bf7SToby Isaac } 217dcbd3bf7SToby Isaac 218776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM,PetscSection,PetscInt*,PetscInt*,PetscBool,PetscBool); 219f9f063d4SToby Isaac 220da43764aSToby Isaac #undef __FUNCT__ 2210e2cc29aSToby Isaac #define __FUNCT__ "DMPlexCreateReferenceTree_Union" 2220e2cc29aSToby Isaac PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 223da43764aSToby Isaac { 2240e2cc29aSToby Isaac MPI_Comm comm; 2250e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 226da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 227da43764aSToby Isaac DMLabel identity, identityRef; 22810f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 229da43764aSToby Isaac PetscScalar *unionCoords; 230da43764aSToby Isaac IS perm; 231da43764aSToby Isaac PetscErrorCode ierr; 232da43764aSToby Isaac 233da43764aSToby Isaac PetscFunctionBegin; 2340e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2350e2cc29aSToby Isaac ierr = DMGetDimension(K, &dim);CHKERRQ(ierr); 236da43764aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 2370e2cc29aSToby Isaac ierr = DMGetLabel(K, labelName, &identity);CHKERRQ(ierr); 2380e2cc29aSToby Isaac ierr = DMGetLabel(Kref, labelName, &identityRef);CHKERRQ(ierr); 239da43764aSToby Isaac ierr = DMPlexGetChart(Kref, &pRefStart, &pRefEnd);CHKERRQ(ierr); 240da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionSection);CHKERRQ(ierr); 241da43764aSToby Isaac ierr = PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart));CHKERRQ(ierr); 242da43764aSToby Isaac /* count points that will go in the union */ 243da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 244da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pStart, 1);CHKERRQ(ierr); 245da43764aSToby Isaac } 246da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 247da43764aSToby Isaac PetscInt q, qSize; 248da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, p, &q);CHKERRQ(ierr); 249da43764aSToby Isaac ierr = DMLabelGetStratumSize(identityRef, q, &qSize);CHKERRQ(ierr); 250da43764aSToby Isaac if (qSize > 1) { 251da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1);CHKERRQ(ierr); 252da43764aSToby Isaac } 253da43764aSToby Isaac } 254854ce69bSBarry Smith ierr = PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart,&permvals);CHKERRQ(ierr); 255da43764aSToby Isaac offset = 0; 256da43764aSToby Isaac /* stratify points in the union by topological dimension */ 257da43764aSToby Isaac for (d = 0; d <= dim; d++) { 258da43764aSToby Isaac PetscInt cStart, cEnd, c; 259da43764aSToby Isaac 260da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K, d, &cStart, &cEnd);CHKERRQ(ierr); 261da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 262da43764aSToby Isaac permvals[offset++] = c; 263da43764aSToby Isaac } 264da43764aSToby Isaac 265da43764aSToby Isaac ierr = DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd);CHKERRQ(ierr); 266da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 267da43764aSToby Isaac permvals[offset++] = c + (pEnd - pStart); 268da43764aSToby Isaac } 269da43764aSToby Isaac } 270da43764aSToby Isaac ierr = ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr); 271da43764aSToby Isaac ierr = PetscSectionSetPermutation(unionSection,perm);CHKERRQ(ierr); 272da43764aSToby Isaac ierr = PetscSectionSetUp(unionSection);CHKERRQ(ierr); 273da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionSection,&numUnionPoints);CHKERRQ(ierr); 274da43764aSToby Isaac ierr = PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints);CHKERRQ(ierr); 275da43764aSToby Isaac /* count dimension points */ 276da43764aSToby Isaac for (d = 0; d <= dim; d++) { 277da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 278da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d,&cStart,NULL);CHKERRQ(ierr); 279da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff);CHKERRQ(ierr); 280da43764aSToby Isaac if (d < dim) { 281da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d+1,&cStart,NULL);CHKERRQ(ierr); 282da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2);CHKERRQ(ierr); 283da43764aSToby Isaac } 284da43764aSToby Isaac else { 285da43764aSToby Isaac cOff2 = numUnionPoints; 286da43764aSToby Isaac } 287da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 288da43764aSToby Isaac } 289da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionConeSection);CHKERRQ(ierr); 290da43764aSToby Isaac ierr = PetscSectionSetChart(unionConeSection, 0, numUnionPoints);CHKERRQ(ierr); 291da43764aSToby Isaac /* count the cones in the union */ 292da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 293da43764aSToby Isaac PetscInt dof, uOff; 294da43764aSToby Isaac 295da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 296da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 297da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 298da43764aSToby Isaac coneSizes[uOff] = dof; 299da43764aSToby Isaac } 300da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 301da43764aSToby Isaac PetscInt dof, uDof, uOff; 302da43764aSToby Isaac 303da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 304da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 305da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 306da43764aSToby Isaac if (uDof) { 307da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 308da43764aSToby Isaac coneSizes[uOff] = dof; 309da43764aSToby Isaac } 310da43764aSToby Isaac } 311da43764aSToby Isaac ierr = PetscSectionSetUp(unionConeSection);CHKERRQ(ierr); 312da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionConeSection,&numCones);CHKERRQ(ierr); 313da43764aSToby Isaac ierr = PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations);CHKERRQ(ierr); 314da43764aSToby Isaac /* write the cones in the union */ 315da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 316da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 317da43764aSToby Isaac const PetscInt *cone, *orientation; 318da43764aSToby Isaac 319da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 320da43764aSToby Isaac ierr = DMPlexGetCone(K, p, &cone);CHKERRQ(ierr); 321da43764aSToby Isaac ierr = DMPlexGetConeOrientation(K, p, &orientation);CHKERRQ(ierr); 322da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 323da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 324da43764aSToby Isaac for (c = 0; c < dof; c++) { 325da43764aSToby Isaac PetscInt e, eOff; 326da43764aSToby Isaac e = cone[c]; 327da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 328da43764aSToby Isaac unionCones[cOff + c] = eOff; 329da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 330da43764aSToby Isaac } 331da43764aSToby Isaac } 332da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 333da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 334da43764aSToby Isaac const PetscInt *cone, *orientation; 335da43764aSToby Isaac 336da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 337da43764aSToby Isaac ierr = DMPlexGetCone(Kref, p, &cone);CHKERRQ(ierr); 338da43764aSToby Isaac ierr = DMPlexGetConeOrientation(Kref, p, &orientation);CHKERRQ(ierr); 339da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 340da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 341da43764aSToby Isaac if (uDof) { 342da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 343da43764aSToby Isaac for (c = 0; c < dof; c++) { 344da43764aSToby Isaac PetscInt e, eOff, eDof; 345da43764aSToby Isaac 346da43764aSToby Isaac e = cone[c]; 347da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof);CHKERRQ(ierr); 348da43764aSToby Isaac if (eDof) { 349da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff);CHKERRQ(ierr); 350da43764aSToby Isaac } 351da43764aSToby Isaac else { 352da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, e, &e);CHKERRQ(ierr); 353da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 354da43764aSToby Isaac } 355da43764aSToby Isaac unionCones[cOff + c] = eOff; 356da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 357da43764aSToby Isaac } 358da43764aSToby Isaac } 359da43764aSToby Isaac } 360da43764aSToby Isaac /* get the coordinates */ 361da43764aSToby Isaac { 362da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 363da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 364da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 365da43764aSToby Isaac PetscScalar *Kcoords; 366da43764aSToby Isaac 367da43764aSToby Isaac DMGetCoordinateSection(K, &KcoordsSec);CHKERRQ(ierr); 368da43764aSToby Isaac DMGetCoordinatesLocal(K, &KcoordsVec);CHKERRQ(ierr); 369da43764aSToby Isaac DMGetCoordinateSection(Kref, &KrefCoordsSec);CHKERRQ(ierr); 370da43764aSToby Isaac DMGetCoordinatesLocal(Kref, &KrefCoordsVec);CHKERRQ(ierr); 371da43764aSToby Isaac 372da43764aSToby Isaac numVerts = numDimPoints[0]; 373da43764aSToby Isaac ierr = PetscMalloc1(numVerts * dim,&unionCoords);CHKERRQ(ierr); 374da43764aSToby Isaac ierr = DMPlexGetDepthStratum(K,0,&vStart,&vEnd);CHKERRQ(ierr); 375da43764aSToby Isaac 376da43764aSToby Isaac offset = 0; 377da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 378da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pStart,&vOff);CHKERRQ(ierr); 379da43764aSToby Isaac ierr = VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords);CHKERRQ(ierr); 380da43764aSToby Isaac for (d = 0; d < dim; d++) { 381da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 382da43764aSToby Isaac } 383da43764aSToby Isaac offset++; 384da43764aSToby Isaac } 385da43764aSToby Isaac ierr = DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd);CHKERRQ(ierr); 386da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 387da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof);CHKERRQ(ierr); 388da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff);CHKERRQ(ierr); 389da43764aSToby Isaac ierr = VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords);CHKERRQ(ierr); 390da43764aSToby Isaac if (vDof) { 391da43764aSToby Isaac for (d = 0; d < dim; d++) { 392da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 393da43764aSToby Isaac } 394da43764aSToby Isaac offset++; 395da43764aSToby Isaac } 396da43764aSToby Isaac } 397da43764aSToby Isaac } 398da43764aSToby Isaac ierr = DMCreate(comm,ref);CHKERRQ(ierr); 399da43764aSToby Isaac ierr = DMSetType(*ref,DMPLEX);CHKERRQ(ierr); 40028f4b327SMatthew G. Knepley ierr = DMSetDimension(*ref,dim);CHKERRQ(ierr); 401da43764aSToby Isaac ierr = DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords);CHKERRQ(ierr); 40210f7e118SToby Isaac /* set the tree */ 40310f7e118SToby Isaac ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr); 40410f7e118SToby Isaac ierr = PetscSectionSetChart(parentSection,0,numUnionPoints);CHKERRQ(ierr); 40510f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 40610f7e118SToby Isaac PetscInt uDof, uOff; 40710f7e118SToby Isaac 40810f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 40910f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 41010f7e118SToby Isaac if (uDof) { 41110f7e118SToby Isaac PetscSectionSetDof(parentSection,uOff,1);CHKERRQ(ierr); 41210f7e118SToby Isaac } 41310f7e118SToby Isaac } 41410f7e118SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 41510f7e118SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&parentSize);CHKERRQ(ierr); 41610f7e118SToby Isaac ierr = PetscMalloc2(parentSize,&parents,parentSize,&childIDs);CHKERRQ(ierr); 41710f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 41810f7e118SToby Isaac PetscInt uDof, uOff; 41910f7e118SToby Isaac 42010f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 42110f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 42210f7e118SToby Isaac if (uDof) { 42310f7e118SToby Isaac PetscInt pOff, parent, parentU; 42410f7e118SToby Isaac PetscSectionGetOffset(parentSection,uOff,&pOff);CHKERRQ(ierr); 42510f7e118SToby Isaac DMLabelGetValue(identityRef,p,&parent);CHKERRQ(ierr); 42610f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, parent - pStart,&parentU);CHKERRQ(ierr); 42710f7e118SToby Isaac parents[pOff] = parentU; 42810f7e118SToby Isaac childIDs[pOff] = uOff; 42910f7e118SToby Isaac } 43010f7e118SToby Isaac } 431776742edSToby Isaac ierr = DMPlexSetTree_Internal(*ref,parentSection,parents,childIDs,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 43210f7e118SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 43310f7e118SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 43410f7e118SToby Isaac 435da43764aSToby Isaac /* clean up */ 436da43764aSToby Isaac ierr = PetscSectionDestroy(&unionSection);CHKERRQ(ierr); 437da43764aSToby Isaac ierr = PetscSectionDestroy(&unionConeSection);CHKERRQ(ierr); 438da43764aSToby Isaac ierr = ISDestroy(&perm);CHKERRQ(ierr); 439da43764aSToby Isaac ierr = PetscFree(unionCoords);CHKERRQ(ierr); 440da43764aSToby Isaac ierr = PetscFree2(unionCones,unionOrientations);CHKERRQ(ierr); 441da43764aSToby Isaac ierr = PetscFree2(coneSizes,numDimPoints);CHKERRQ(ierr); 4420e2cc29aSToby Isaac PetscFunctionReturn(0); 4430e2cc29aSToby Isaac } 4440e2cc29aSToby Isaac 4450e2cc29aSToby Isaac #undef __FUNCT__ 4460e2cc29aSToby Isaac #define __FUNCT__ "DMPlexCreateDefaultReferenceTree" 4470e2cc29aSToby Isaac /*@ 4480e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4490e2cc29aSToby Isaac 4500e2cc29aSToby Isaac Collective on comm 4510e2cc29aSToby Isaac 4520e2cc29aSToby Isaac Input Parameters: 4530e2cc29aSToby Isaac + comm - the MPI communicator 4540e2cc29aSToby Isaac . dim - the spatial dimension 4550e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4560e2cc29aSToby Isaac 4570e2cc29aSToby Isaac Output Parameters: 4580e2cc29aSToby Isaac . ref - the reference tree DMPlex object 4590e2cc29aSToby Isaac 4600e2cc29aSToby Isaac Level: intermediate 4610e2cc29aSToby Isaac 4620e2cc29aSToby Isaac .keywords: reference cell 4630e2cc29aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree() 4640e2cc29aSToby Isaac @*/ 4650e2cc29aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 4660e2cc29aSToby Isaac { 4670e2cc29aSToby Isaac DM_Plex *mesh; 4680e2cc29aSToby Isaac DM K, Kref; 4690e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4700e2cc29aSToby Isaac DMLabel identity; 4710e2cc29aSToby Isaac PetscErrorCode ierr; 4720e2cc29aSToby Isaac 4730e2cc29aSToby Isaac PetscFunctionBegin; 4740e2cc29aSToby Isaac #if 1 4750e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4760e2cc29aSToby Isaac #endif 4770e2cc29aSToby Isaac /* create a reference element */ 4780e2cc29aSToby Isaac ierr = DMPlexCreateReferenceCell(comm, dim, simplex, &K);CHKERRQ(ierr); 4790e2cc29aSToby Isaac ierr = DMCreateLabel(K, "identity");CHKERRQ(ierr); 4800e2cc29aSToby Isaac ierr = DMGetLabel(K, "identity", &identity);CHKERRQ(ierr); 4810e2cc29aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 4820e2cc29aSToby Isaac for (p = pStart; p < pEnd; p++) { 4830e2cc29aSToby Isaac ierr = DMLabelSetValue(identity, p, p);CHKERRQ(ierr); 4840e2cc29aSToby Isaac } 4850e2cc29aSToby Isaac /* refine it */ 4860e2cc29aSToby Isaac ierr = DMRefine(K,comm,&Kref);CHKERRQ(ierr); 4870e2cc29aSToby Isaac 4880e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4890e2cc29aSToby Isaac * points that appear in both */ 4900e2cc29aSToby Isaac ierr = DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref);CHKERRQ(ierr); 4910e2cc29aSToby Isaac mesh = (DM_Plex *) (*ref)->data; 4920e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 493da43764aSToby Isaac ierr = DMDestroy(&K);CHKERRQ(ierr); 494da43764aSToby Isaac ierr = DMDestroy(&Kref);CHKERRQ(ierr); 495da43764aSToby Isaac PetscFunctionReturn(0); 496da43764aSToby Isaac } 497da43764aSToby Isaac 498d961a43aSToby Isaac #undef __FUNCT__ 499878b19aaSToby Isaac #define __FUNCT__ "DMPlexTreeSymmetrize" 500878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 501878b19aaSToby Isaac { 502878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 503878b19aaSToby Isaac PetscSection childSec, pSec; 504878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 505878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 506878b19aaSToby Isaac PetscErrorCode ierr; 507878b19aaSToby Isaac 508878b19aaSToby Isaac PetscFunctionBegin; 509878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 510878b19aaSToby Isaac ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 511878b19aaSToby Isaac ierr = PetscFree(mesh->children);CHKERRQ(ierr); 512878b19aaSToby Isaac pSec = mesh->parentSection; 513878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 514878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(pSec,&pSize);CHKERRQ(ierr); 515878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 516878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 517878b19aaSToby Isaac 518878b19aaSToby Isaac parMax = PetscMax(parMax,par+1); 519878b19aaSToby Isaac parMin = PetscMin(parMin,par); 520878b19aaSToby Isaac } 521878b19aaSToby Isaac if (parMin > parMax) { 522878b19aaSToby Isaac parMin = -1; 523878b19aaSToby Isaac parMax = -1; 524878b19aaSToby Isaac } 525878b19aaSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec);CHKERRQ(ierr); 526878b19aaSToby Isaac ierr = PetscSectionSetChart(childSec,parMin,parMax);CHKERRQ(ierr); 527878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 528878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 529878b19aaSToby Isaac 530878b19aaSToby Isaac ierr = PetscSectionAddDof(childSec,par,1);CHKERRQ(ierr); 531878b19aaSToby Isaac } 532878b19aaSToby Isaac ierr = PetscSectionSetUp(childSec);CHKERRQ(ierr); 533878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(childSec,&cSize);CHKERRQ(ierr); 534878b19aaSToby Isaac ierr = PetscMalloc1(cSize,&children);CHKERRQ(ierr); 535878b19aaSToby Isaac ierr = PetscCalloc1(parMax-parMin,&offsets);CHKERRQ(ierr); 536878b19aaSToby Isaac ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr); 537878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 538878b19aaSToby Isaac PetscInt dof, off, i; 539878b19aaSToby Isaac 540878b19aaSToby Isaac ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 541878b19aaSToby Isaac ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr); 542878b19aaSToby Isaac for (i = 0; i < dof; i++) { 543878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 544878b19aaSToby Isaac 545878b19aaSToby Isaac ierr = PetscSectionGetOffset(childSec,par,&cOff);CHKERRQ(ierr); 546878b19aaSToby Isaac children[cOff + offsets[par-parMin]++] = p; 547878b19aaSToby Isaac } 548878b19aaSToby Isaac } 549878b19aaSToby Isaac mesh->childSection = childSec; 550878b19aaSToby Isaac mesh->children = children; 551878b19aaSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 552878b19aaSToby Isaac PetscFunctionReturn(0); 553878b19aaSToby Isaac } 554878b19aaSToby Isaac 555878b19aaSToby Isaac #undef __FUNCT__ 5566dd5a8c8SToby Isaac #define __FUNCT__ "AnchorsFlatten" 5576dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 5586dd5a8c8SToby Isaac { 5596dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5606dd5a8c8SToby Isaac const PetscInt *vals; 5616dd5a8c8SToby Isaac PetscSection secNew; 5626dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5636dd5a8c8SToby Isaac PetscBool compress; 5646dd5a8c8SToby Isaac PetscErrorCode ierr; 5656dd5a8c8SToby Isaac 5666dd5a8c8SToby Isaac PetscFunctionBegin; 5676dd5a8c8SToby Isaac ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr); 5686dd5a8c8SToby Isaac ierr = ISGetLocalSize(is,&size);CHKERRQ(ierr); 5696dd5a8c8SToby Isaac ierr = ISGetIndices(is,&vals);CHKERRQ(ierr); 5706dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew);CHKERRQ(ierr); 5716dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secNew,pStart,pEnd);CHKERRQ(ierr); 5726dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5736dd5a8c8SToby Isaac PetscInt dof; 5746dd5a8c8SToby Isaac 5756dd5a8c8SToby Isaac p = vals[i]; 5766dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5776dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5786dd5a8c8SToby Isaac if (dof) break; 5796dd5a8c8SToby Isaac } 5806dd5a8c8SToby Isaac if (i == size) { 5816dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 5826dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5836dd5a8c8SToby Isaac compress = PETSC_FALSE; 5846dd5a8c8SToby Isaac sizeNew = 0; 5856dd5a8c8SToby Isaac } 5866dd5a8c8SToby Isaac else { 5876dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5886dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5896dd5a8c8SToby Isaac PetscInt dof, off; 5906dd5a8c8SToby Isaac 5916dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5926dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 5936dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5946dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5956dd5a8c8SToby Isaac 5966dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5976dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 5986dd5a8c8SToby Isaac } 5996dd5a8c8SToby Isaac if (qDof) { 6006dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, qDof);CHKERRQ(ierr); 6016dd5a8c8SToby Isaac } 6026dd5a8c8SToby Isaac else { 6036dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, 1);CHKERRQ(ierr); 6046dd5a8c8SToby Isaac } 6056dd5a8c8SToby Isaac } 6066dd5a8c8SToby Isaac } 6076dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 6086dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secNew,&sizeNew);CHKERRQ(ierr); 6096dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsNew);CHKERRQ(ierr); 6106dd5a8c8SToby Isaac compress = PETSC_FALSE; 6116dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6126dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 6136dd5a8c8SToby Isaac 6146dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 6156dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 6166dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dofNew);CHKERRQ(ierr); 6176dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &offNew);CHKERRQ(ierr); 6186dd5a8c8SToby Isaac count = 0; 6196dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 6206dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 6216dd5a8c8SToby Isaac 6226dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 6236dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 6246dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, q, &qOff);CHKERRQ(ierr); 6256dd5a8c8SToby Isaac } 6266dd5a8c8SToby Isaac if (qDof) { 6276dd5a8c8SToby Isaac PetscInt oldCount = count; 6286dd5a8c8SToby Isaac 6296dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 6306dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 6316dd5a8c8SToby Isaac 6326dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6336dd5a8c8SToby Isaac if (valsNew[offNew + k] == r) { 6346dd5a8c8SToby Isaac break; 6356dd5a8c8SToby Isaac } 6366dd5a8c8SToby Isaac } 6376dd5a8c8SToby Isaac if (k == oldCount) { 6386dd5a8c8SToby Isaac valsNew[offNew + count++] = r; 6396dd5a8c8SToby Isaac } 6406dd5a8c8SToby Isaac } 6416dd5a8c8SToby Isaac } 6426dd5a8c8SToby Isaac else { 6436dd5a8c8SToby Isaac PetscInt k, oldCount = count; 6446dd5a8c8SToby Isaac 6456dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6466dd5a8c8SToby Isaac if (valsNew[offNew + k] == q) { 6476dd5a8c8SToby Isaac break; 6486dd5a8c8SToby Isaac } 6496dd5a8c8SToby Isaac } 6506dd5a8c8SToby Isaac if (k == oldCount) { 6516dd5a8c8SToby Isaac valsNew[offNew + count++] = q; 6526dd5a8c8SToby Isaac } 6536dd5a8c8SToby Isaac } 6546dd5a8c8SToby Isaac } 6556dd5a8c8SToby Isaac if (count < dofNew) { 6566dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secNew, p, count);CHKERRQ(ierr); 6576dd5a8c8SToby Isaac compress = PETSC_TRUE; 6586dd5a8c8SToby Isaac } 6596dd5a8c8SToby Isaac } 6606dd5a8c8SToby Isaac } 6616dd5a8c8SToby Isaac ierr = ISRestoreIndices(is,&vals);CHKERRQ(ierr); 662b2566f29SBarry Smith ierr = MPIU_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 6636dd5a8c8SToby Isaac if (!globalAnyNew) { 6646dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6656dd5a8c8SToby Isaac *sectionNew = NULL; 6666dd5a8c8SToby Isaac *isNew = NULL; 6676dd5a8c8SToby Isaac } 6686dd5a8c8SToby Isaac else { 6696dd5a8c8SToby Isaac PetscBool globalCompress; 6706dd5a8c8SToby Isaac 671b2566f29SBarry Smith ierr = MPIU_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 6726dd5a8c8SToby Isaac if (compress) { 6736dd5a8c8SToby Isaac PetscSection secComp; 6746dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6756dd5a8c8SToby Isaac 6766dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp);CHKERRQ(ierr); 6776dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secComp,pStart,pEnd);CHKERRQ(ierr); 6786dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6796dd5a8c8SToby Isaac PetscInt dof; 6806dd5a8c8SToby Isaac 6816dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6826dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secComp, p, dof);CHKERRQ(ierr); 6836dd5a8c8SToby Isaac } 6846dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secComp);CHKERRQ(ierr); 6856dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secComp,&sizeNew);CHKERRQ(ierr); 6866dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsComp);CHKERRQ(ierr); 6876dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6886dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6896dd5a8c8SToby Isaac 6906dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6916dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &off);CHKERRQ(ierr); 6926dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secComp, p, &offNew);CHKERRQ(ierr); 6936dd5a8c8SToby Isaac for (j = 0; j < dof; j++) { 6946dd5a8c8SToby Isaac valsComp[offNew + j] = valsNew[off + j]; 6956dd5a8c8SToby Isaac } 6966dd5a8c8SToby Isaac } 6976dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6986dd5a8c8SToby Isaac secNew = secComp; 6996dd5a8c8SToby Isaac ierr = PetscFree(valsNew);CHKERRQ(ierr); 7006dd5a8c8SToby Isaac valsNew = valsComp; 7016dd5a8c8SToby Isaac } 7026dd5a8c8SToby Isaac ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew);CHKERRQ(ierr); 7036dd5a8c8SToby Isaac } 7046dd5a8c8SToby Isaac PetscFunctionReturn(0); 7056dd5a8c8SToby Isaac } 7066dd5a8c8SToby Isaac 7076dd5a8c8SToby Isaac #undef __FUNCT__ 708f7c74593SToby Isaac #define __FUNCT__ "DMPlexCreateAnchors_Tree" 709f7c74593SToby Isaac static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 71066af876cSToby Isaac { 71166af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 71266af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 71366af876cSToby Isaac PetscSection aSec; 714f9f063d4SToby Isaac DMLabel canonLabel; 71566af876cSToby Isaac IS aIS; 71666af876cSToby Isaac PetscErrorCode ierr; 71766af876cSToby Isaac 71866af876cSToby Isaac PetscFunctionBegin; 71966af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 72066af876cSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 721c58f1c22SToby Isaac ierr = DMGetLabel(dm,"canonical",&canonLabel);CHKERRQ(ierr); 72266af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 72366af876cSToby Isaac PetscInt parent; 72466af876cSToby Isaac 725f9f063d4SToby Isaac if (canonLabel) { 726f9f063d4SToby Isaac PetscInt canon; 727f9f063d4SToby Isaac 728f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 729f9f063d4SToby Isaac if (p != canon) continue; 730f9f063d4SToby Isaac } 73166af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 73266af876cSToby Isaac if (parent != p) { 73366af876cSToby Isaac aMin = PetscMin(aMin,p); 73466af876cSToby Isaac aMax = PetscMax(aMax,p+1); 73566af876cSToby Isaac } 73666af876cSToby Isaac } 73766af876cSToby Isaac if (aMin > aMax) { 73866af876cSToby Isaac aMin = -1; 73966af876cSToby Isaac aMax = -1; 74066af876cSToby Isaac } 741e228b242SToby Isaac ierr = PetscSectionCreate(PETSC_COMM_SELF,&aSec);CHKERRQ(ierr); 74266af876cSToby Isaac ierr = PetscSectionSetChart(aSec,aMin,aMax);CHKERRQ(ierr); 74366af876cSToby Isaac for (p = aMin; p < aMax; p++) { 74466af876cSToby Isaac PetscInt parent, ancestor = p; 74566af876cSToby Isaac 746f9f063d4SToby Isaac if (canonLabel) { 747f9f063d4SToby Isaac PetscInt canon; 748f9f063d4SToby Isaac 749f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 750f9f063d4SToby Isaac if (p != canon) continue; 751f9f063d4SToby Isaac } 75266af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 75366af876cSToby Isaac while (parent != ancestor) { 75466af876cSToby Isaac ancestor = parent; 75566af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 75666af876cSToby Isaac } 75766af876cSToby Isaac if (ancestor != p) { 75866af876cSToby Isaac PetscInt closureSize, *closure = NULL; 75966af876cSToby Isaac 76066af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 76166af876cSToby Isaac ierr = PetscSectionSetDof(aSec,p,closureSize);CHKERRQ(ierr); 76266af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 76366af876cSToby Isaac } 76466af876cSToby Isaac } 76566af876cSToby Isaac ierr = PetscSectionSetUp(aSec);CHKERRQ(ierr); 76666af876cSToby Isaac ierr = PetscSectionGetStorageSize(aSec,&size);CHKERRQ(ierr); 76766af876cSToby Isaac ierr = PetscMalloc1(size,&anchors);CHKERRQ(ierr); 76866af876cSToby Isaac for (p = aMin; p < aMax; p++) { 76966af876cSToby Isaac PetscInt parent, ancestor = p; 77066af876cSToby Isaac 771f9f063d4SToby Isaac if (canonLabel) { 772f9f063d4SToby Isaac PetscInt canon; 773f9f063d4SToby Isaac 774f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 775f9f063d4SToby Isaac if (p != canon) continue; 776f9f063d4SToby Isaac } 77766af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 77866af876cSToby Isaac while (parent != ancestor) { 77966af876cSToby Isaac ancestor = parent; 78066af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 78166af876cSToby Isaac } 78266af876cSToby Isaac if (ancestor != p) { 78366af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 78466af876cSToby Isaac 78566af876cSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 78666af876cSToby Isaac 78766af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 78866af876cSToby Isaac for (j = 0; j < closureSize; j++) { 78966af876cSToby Isaac anchors[aOff + j] = closure[2*j]; 79066af876cSToby Isaac } 79166af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 79266af876cSToby Isaac } 79366af876cSToby Isaac } 794e228b242SToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,size,anchors,PETSC_OWN_POINTER,&aIS);CHKERRQ(ierr); 7956dd5a8c8SToby Isaac { 7966dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7976dd5a8c8SToby Isaac IS aISNew = aIS; 7986dd5a8c8SToby Isaac 7996dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aSec);CHKERRQ(ierr); 8006dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aIS);CHKERRQ(ierr); 8016dd5a8c8SToby Isaac while (aSecNew) { 8026dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 8036dd5a8c8SToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 8046dd5a8c8SToby Isaac aSec = aSecNew; 8056dd5a8c8SToby Isaac aIS = aISNew; 8066dd5a8c8SToby Isaac aSecNew = NULL; 8076dd5a8c8SToby Isaac aISNew = NULL; 8086dd5a8c8SToby Isaac ierr = AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew);CHKERRQ(ierr); 8096dd5a8c8SToby Isaac } 8106dd5a8c8SToby Isaac } 811a17985deSToby Isaac ierr = DMPlexSetAnchors(dm,aSec,aIS);CHKERRQ(ierr); 81266af876cSToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 81366af876cSToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 81466af876cSToby Isaac PetscFunctionReturn(0); 81566af876cSToby Isaac } 81666af876cSToby Isaac 81766af876cSToby Isaac #undef __FUNCT__ 8186461c1adSToby Isaac #define __FUNCT__ "DMPlexGetTrueSupportSize" 8196461c1adSToby Isaac static PetscErrorCode DMPlexGetTrueSupportSize(DM dm,PetscInt p,PetscInt *dof,PetscInt *numTrueSupp) 8206461c1adSToby Isaac { 8216461c1adSToby Isaac PetscErrorCode ierr; 8226461c1adSToby Isaac 8236461c1adSToby Isaac PetscFunctionBegin; 8246461c1adSToby Isaac if (numTrueSupp[p] == -1) { 8256461c1adSToby Isaac PetscInt i, alldof; 8266461c1adSToby Isaac const PetscInt *supp; 8276461c1adSToby Isaac PetscInt count = 0; 8286461c1adSToby Isaac 8296461c1adSToby Isaac ierr = DMPlexGetSupportSize(dm,p,&alldof);CHKERRQ(ierr); 8306461c1adSToby Isaac ierr = DMPlexGetSupport(dm,p,&supp);CHKERRQ(ierr); 8316461c1adSToby Isaac for (i = 0; i < alldof; i++) { 8326461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 8336461c1adSToby Isaac const PetscInt *cone; 8346461c1adSToby Isaac 8356461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr); 8366461c1adSToby Isaac ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr); 8376461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8386461c1adSToby Isaac if (cone[j] == p) break; 8396461c1adSToby Isaac } 8406461c1adSToby Isaac if (j < numCones) count++; 8416461c1adSToby Isaac } 8426461c1adSToby Isaac numTrueSupp[p] = count; 8436461c1adSToby Isaac } 8446461c1adSToby Isaac *dof = numTrueSupp[p]; 8456461c1adSToby Isaac PetscFunctionReturn(0); 8466461c1adSToby Isaac } 8476461c1adSToby Isaac 8486461c1adSToby Isaac #undef __FUNCT__ 849776742edSToby Isaac #define __FUNCT__ "DMPlexTreeExchangeSupports" 850776742edSToby Isaac static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 851776742edSToby Isaac { 852776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 853776742edSToby Isaac PetscSection newSupportSection; 854776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 8556461c1adSToby Isaac PetscInt *numTrueSupp; 856776742edSToby Isaac PetscInt *offsets; 857776742edSToby Isaac PetscErrorCode ierr; 858776742edSToby Isaac 859776742edSToby Isaac PetscFunctionBegin; 860776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 861776742edSToby Isaac /* symmetrize the hierarchy */ 862776742edSToby Isaac ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 863e228b242SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)),&newSupportSection);CHKERRQ(ierr); 864776742edSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 865776742edSToby Isaac ierr = PetscSectionSetChart(newSupportSection,pStart,pEnd);CHKERRQ(ierr); 866776742edSToby Isaac ierr = PetscCalloc1(pEnd,&offsets);CHKERRQ(ierr); 8676461c1adSToby Isaac ierr = PetscMalloc1(pEnd,&numTrueSupp);CHKERRQ(ierr); 8686461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 8696461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 870776742edSToby Isaac * parent(q) */ 871776742edSToby Isaac for (d = 0; d <= depth; d++) { 872776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 873776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 874776742edSToby Isaac PetscInt dof, q, qdof, parent; 875776742edSToby Isaac 8766461c1adSToby Isaac ierr = DMPlexGetTrueSupportSize(dm,p,&dof,numTrueSupp);CHKERRQ(ierr); 877776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection, p, dof);CHKERRQ(ierr); 878776742edSToby Isaac q = p; 879776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 880776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 881776742edSToby Isaac q = parent; 882776742edSToby Isaac 8836461c1adSToby Isaac ierr = DMPlexGetTrueSupportSize(dm,q,&qdof,numTrueSupp);CHKERRQ(ierr); 884776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,p,qdof);CHKERRQ(ierr); 885776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,q,dof);CHKERRQ(ierr); 886776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 887776742edSToby Isaac } 888776742edSToby Isaac } 889776742edSToby Isaac } 890776742edSToby Isaac ierr = PetscSectionSetUp(newSupportSection);CHKERRQ(ierr); 891776742edSToby Isaac ierr = PetscSectionGetStorageSize(newSupportSection,&newSize);CHKERRQ(ierr); 892776742edSToby Isaac ierr = PetscMalloc1(newSize,&newSupports);CHKERRQ(ierr); 893776742edSToby Isaac for (d = 0; d <= depth; d++) { 894776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 895776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 896776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 897776742edSToby Isaac 898776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 899776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 900776742edSToby Isaac ierr = PetscSectionGetDof(newSupportSection, p, &newDof);CHKERRQ(ierr); 901776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, p, &newOff);CHKERRQ(ierr); 902776742edSToby Isaac for (i = 0; i < dof; i++) { 9036461c1adSToby Isaac PetscInt numCones, j; 9046461c1adSToby Isaac const PetscInt *cone; 9056461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 9066461c1adSToby Isaac 9076461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr); 9086461c1adSToby Isaac ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr); 9096461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9106461c1adSToby Isaac if (cone[j] == p) break; 9116461c1adSToby Isaac } 9126461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = q; 913776742edSToby Isaac } 914776742edSToby Isaac mesh->maxSupportSize = PetscMax(mesh->maxSupportSize,newDof); 915776742edSToby Isaac 916776742edSToby Isaac q = p; 917776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 918776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 919776742edSToby Isaac q = parent; 920776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, q, &qdof);CHKERRQ(ierr); 921776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, q, &qoff);CHKERRQ(ierr); 922776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, q, &newqOff);CHKERRQ(ierr); 923776742edSToby Isaac for (i = 0; i < qdof; i++) { 9246461c1adSToby Isaac PetscInt numCones, j; 9256461c1adSToby Isaac const PetscInt *cone; 9266461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 9276461c1adSToby Isaac 9286461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr); 9296461c1adSToby Isaac ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr); 9306461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9316461c1adSToby Isaac if (cone[j] == q) break; 9326461c1adSToby Isaac } 9336461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = r; 934776742edSToby Isaac } 935776742edSToby Isaac for (i = 0; i < dof; i++) { 9366461c1adSToby Isaac PetscInt numCones, j; 9376461c1adSToby Isaac const PetscInt *cone; 9386461c1adSToby Isaac PetscInt r = mesh->supports[off + i]; 9396461c1adSToby Isaac 9406461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr); 9416461c1adSToby Isaac ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr); 9426461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9436461c1adSToby Isaac if (cone[j] == p) break; 9446461c1adSToby Isaac } 9456461c1adSToby Isaac if (j < numCones) newSupports[newqOff+offsets[q]++] = r; 946776742edSToby Isaac } 947776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 948776742edSToby Isaac } 949776742edSToby Isaac } 950776742edSToby Isaac } 951776742edSToby Isaac ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 952776742edSToby Isaac mesh->supportSection = newSupportSection; 953776742edSToby Isaac ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 954776742edSToby Isaac mesh->supports = newSupports; 955776742edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 9566461c1adSToby Isaac ierr = PetscFree(numTrueSupp);CHKERRQ(ierr); 957776742edSToby Isaac 958776742edSToby Isaac PetscFunctionReturn(0); 959776742edSToby Isaac } 960776742edSToby Isaac 961f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM,PetscSection,PetscSection,Mat); 962f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM,PetscSection,PetscSection,Mat); 963f7c74593SToby Isaac 964776742edSToby Isaac #undef __FUNCT__ 965f9f063d4SToby Isaac #define __FUNCT__ "DMPlexSetTree_Internal" 966776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 967f9f063d4SToby Isaac { 968f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 969f9f063d4SToby Isaac DM refTree; 970f9f063d4SToby Isaac PetscInt size; 971f9f063d4SToby Isaac PetscErrorCode ierr; 972f9f063d4SToby Isaac 973f9f063d4SToby Isaac PetscFunctionBegin; 974f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 975f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 976f9f063d4SToby Isaac ierr = PetscObjectReference((PetscObject)parentSection);CHKERRQ(ierr); 977f9f063d4SToby Isaac ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 978f9f063d4SToby Isaac mesh->parentSection = parentSection; 979f9f063d4SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&size);CHKERRQ(ierr); 980f9f063d4SToby Isaac if (parents != mesh->parents) { 981f9f063d4SToby Isaac ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 982f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->parents);CHKERRQ(ierr); 983f9f063d4SToby Isaac ierr = PetscMemcpy(mesh->parents, parents, size * sizeof(*parents));CHKERRQ(ierr); 984f9f063d4SToby Isaac } 985f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 986f9f063d4SToby Isaac ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 987f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->childIDs);CHKERRQ(ierr); 988f9f063d4SToby Isaac ierr = PetscMemcpy(mesh->childIDs, childIDs, size * sizeof(*childIDs));CHKERRQ(ierr); 989f9f063d4SToby Isaac } 990f9f063d4SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 991f9f063d4SToby Isaac if (refTree) { 992f9f063d4SToby Isaac DMLabel canonLabel; 993f9f063d4SToby Isaac 994c58f1c22SToby Isaac ierr = DMGetLabel(refTree,"canonical",&canonLabel);CHKERRQ(ierr); 995f9f063d4SToby Isaac if (canonLabel) { 996f9f063d4SToby Isaac PetscInt i; 997f9f063d4SToby Isaac 998f9f063d4SToby Isaac for (i = 0; i < size; i++) { 999f9f063d4SToby Isaac PetscInt canon; 1000f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon);CHKERRQ(ierr); 1001f9f063d4SToby Isaac if (canon >= 0) { 1002f9f063d4SToby Isaac mesh->childIDs[i] = canon; 1003f9f063d4SToby Isaac } 1004f9f063d4SToby Isaac } 1005f9f063d4SToby Isaac } 1006f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 1007f7c74593SToby Isaac } 1008f7c74593SToby Isaac else { 1009f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 1010f9f063d4SToby Isaac } 1011f9f063d4SToby Isaac ierr = DMPlexTreeSymmetrize(dm);CHKERRQ(ierr); 1012f9f063d4SToby Isaac if (computeCanonical) { 1013f9f063d4SToby Isaac PetscInt d, dim; 1014f9f063d4SToby Isaac 1015f9f063d4SToby Isaac /* add the canonical label */ 101628f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 1017c58f1c22SToby Isaac ierr = DMCreateLabel(dm,"canonical");CHKERRQ(ierr); 1018f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 1019f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 1020f9f063d4SToby Isaac const PetscInt *cChildren; 1021f9f063d4SToby Isaac 1022f9f063d4SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 1023f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1024f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&cNumChildren,&cChildren);CHKERRQ(ierr); 1025f9f063d4SToby Isaac if (cNumChildren) { 1026f9f063d4SToby Isaac canon = p; 1027f9f063d4SToby Isaac break; 1028f9f063d4SToby Isaac } 1029f9f063d4SToby Isaac } 1030f9f063d4SToby Isaac if (canon == -1) continue; 1031f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1032f9f063d4SToby Isaac PetscInt numChildren, i; 1033f9f063d4SToby Isaac const PetscInt *children; 1034f9f063d4SToby Isaac 1035f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&numChildren,&children);CHKERRQ(ierr); 1036f9f063d4SToby Isaac if (numChildren) { 1037f9f063d4SToby Isaac if (numChildren != cNumChildren) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"All parent points in a stratum should have the same number of children: %d != %d", numChildren, cNumChildren); 1038c58f1c22SToby Isaac ierr = DMSetLabelValue(dm,"canonical",p,canon);CHKERRQ(ierr); 1039f9f063d4SToby Isaac for (i = 0; i < numChildren; i++) { 1040c58f1c22SToby Isaac ierr = DMSetLabelValue(dm,"canonical",children[i],cChildren[i]);CHKERRQ(ierr); 1041f9f063d4SToby Isaac } 1042f9f063d4SToby Isaac } 1043f9f063d4SToby Isaac } 1044f9f063d4SToby Isaac } 1045f9f063d4SToby Isaac } 1046776742edSToby Isaac if (exchangeSupports) { 1047776742edSToby Isaac ierr = DMPlexTreeExchangeSupports(dm);CHKERRQ(ierr); 1048776742edSToby Isaac } 1049f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 1050f7c74593SToby Isaac /* reset anchors */ 1051f7c74593SToby Isaac ierr = DMPlexSetAnchors(dm,NULL,NULL);CHKERRQ(ierr); 1052f9f063d4SToby Isaac PetscFunctionReturn(0); 1053f9f063d4SToby Isaac } 1054f9f063d4SToby Isaac 1055f9f063d4SToby Isaac #undef __FUNCT__ 10560b7167a0SToby Isaac #define __FUNCT__ "DMPlexSetTree" 10570b7167a0SToby Isaac /*@ 10580b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 10590b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 10600b7167a0SToby Isaac tree root. 10610b7167a0SToby Isaac 10620b7167a0SToby Isaac Collective on dm 10630b7167a0SToby Isaac 10640b7167a0SToby Isaac Input Parameters: 10650b7167a0SToby Isaac + dm - the DMPlex object 10660b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 10670b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 10680b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 10690b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 10700b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 10710b7167a0SToby Isaac 10720b7167a0SToby Isaac Level: intermediate 10730b7167a0SToby Isaac 1074a17985deSToby Isaac .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 10750b7167a0SToby Isaac @*/ 1076b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 10770b7167a0SToby Isaac { 10780b7167a0SToby Isaac PetscErrorCode ierr; 10790b7167a0SToby Isaac 10800b7167a0SToby Isaac PetscFunctionBegin; 1081776742edSToby Isaac ierr = DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 10820b7167a0SToby Isaac PetscFunctionReturn(0); 10830b7167a0SToby Isaac } 10840b7167a0SToby Isaac 10850b7167a0SToby Isaac #undef __FUNCT__ 1086b2f41788SToby Isaac #define __FUNCT__ "DMPlexGetTree" 1087b2f41788SToby Isaac /*@ 1088b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 1089b2f41788SToby Isaac Collective on dm 1090b2f41788SToby Isaac 1091b2f41788SToby Isaac Input Parameters: 1092b2f41788SToby Isaac . dm - the DMPlex object 1093b2f41788SToby Isaac 1094b2f41788SToby Isaac Output Parameters: 1095b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1096b2f41788SToby Isaac offset indexes the parent and childID list 1097b2f41788SToby Isaac . parents - a list of the point parents 1098b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1099b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1100b2f41788SToby Isaac . childSection - the inverse of the parent section 1101b2f41788SToby Isaac - children - a list of the point children 1102b2f41788SToby Isaac 1103b2f41788SToby Isaac Level: intermediate 1104b2f41788SToby Isaac 1105a17985deSToby Isaac .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 1106b2f41788SToby Isaac @*/ 1107b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1108b2f41788SToby Isaac { 1109b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1110b2f41788SToby Isaac 1111b2f41788SToby Isaac PetscFunctionBegin; 1112b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1113b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1114b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1115b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1116b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1117b2f41788SToby Isaac if (children) *children = mesh->children; 1118b2f41788SToby Isaac PetscFunctionReturn(0); 1119b2f41788SToby Isaac } 1120b2f41788SToby Isaac 1121b2f41788SToby Isaac #undef __FUNCT__ 1122d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeParent" 1123d961a43aSToby Isaac /*@ 1124d961a43aSToby Isaac DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the Sieve DAG) 1125d961a43aSToby Isaac 1126d961a43aSToby Isaac Input Parameters: 1127d961a43aSToby Isaac + dm - the DMPlex object 1128d961a43aSToby Isaac - point - the query point 1129d961a43aSToby Isaac 1130d961a43aSToby Isaac Output Parameters: 1131d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 1132d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 1133d961a43aSToby Isaac does not have a parent 1134d961a43aSToby Isaac 1135d961a43aSToby Isaac Level: intermediate 1136d961a43aSToby Isaac 1137d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren() 1138d961a43aSToby Isaac @*/ 1139d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1140d961a43aSToby Isaac { 1141d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1142d961a43aSToby Isaac PetscSection pSec; 1143d961a43aSToby Isaac PetscErrorCode ierr; 1144d961a43aSToby Isaac 1145d961a43aSToby Isaac PetscFunctionBegin; 1146d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1147d961a43aSToby Isaac pSec = mesh->parentSection; 1148d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1149d961a43aSToby Isaac PetscInt dof; 1150d961a43aSToby Isaac 1151d961a43aSToby Isaac ierr = PetscSectionGetDof (pSec, point, &dof);CHKERRQ(ierr); 1152d961a43aSToby Isaac if (dof) { 1153d961a43aSToby Isaac PetscInt off; 1154d961a43aSToby Isaac 1155d961a43aSToby Isaac ierr = PetscSectionGetOffset (pSec, point, &off);CHKERRQ(ierr); 1156d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1157d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 1158d961a43aSToby Isaac PetscFunctionReturn(0); 1159d961a43aSToby Isaac } 1160d961a43aSToby Isaac } 1161d961a43aSToby Isaac if (parent) { 1162d961a43aSToby Isaac *parent = point; 1163d961a43aSToby Isaac } 1164d961a43aSToby Isaac if (childID) { 1165d961a43aSToby Isaac *childID = 0; 1166d961a43aSToby Isaac } 1167d961a43aSToby Isaac PetscFunctionReturn(0); 1168d961a43aSToby Isaac } 1169d961a43aSToby Isaac 1170d961a43aSToby Isaac #undef __FUNCT__ 1171d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeChildren" 1172d961a43aSToby Isaac /*@C 1173d961a43aSToby Isaac DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the Sieve DAG) 1174d961a43aSToby Isaac 1175d961a43aSToby Isaac Input Parameters: 1176d961a43aSToby Isaac + dm - the DMPlex object 1177d961a43aSToby Isaac - point - the query point 1178d961a43aSToby Isaac 1179d961a43aSToby Isaac Output Parameters: 1180d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 1181d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 1182d961a43aSToby Isaac 1183d961a43aSToby Isaac Level: intermediate 1184d961a43aSToby Isaac 1185d961a43aSToby Isaac Fortran Notes: 1186d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1187d961a43aSToby Isaac include petsc.h90 in your code. 1188d961a43aSToby Isaac 1189d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent() 1190d961a43aSToby Isaac @*/ 1191d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1192d961a43aSToby Isaac { 1193d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1194d961a43aSToby Isaac PetscSection childSec; 1195d961a43aSToby Isaac PetscInt dof = 0; 1196d961a43aSToby Isaac PetscErrorCode ierr; 1197d961a43aSToby Isaac 1198d961a43aSToby Isaac PetscFunctionBegin; 1199d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1200d961a43aSToby Isaac childSec = mesh->childSection; 1201d961a43aSToby Isaac if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 1202d961a43aSToby Isaac ierr = PetscSectionGetDof (childSec, point, &dof);CHKERRQ(ierr); 1203d961a43aSToby Isaac } 1204d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1205d961a43aSToby Isaac if (children) { 1206d961a43aSToby Isaac if (dof) { 1207d961a43aSToby Isaac PetscInt off; 1208d961a43aSToby Isaac 1209d961a43aSToby Isaac ierr = PetscSectionGetOffset (childSec, point, &off);CHKERRQ(ierr); 1210d961a43aSToby Isaac *children = &mesh->children[off]; 1211d961a43aSToby Isaac } 1212d961a43aSToby Isaac else { 1213d961a43aSToby Isaac *children = NULL; 1214d961a43aSToby Isaac } 1215d961a43aSToby Isaac } 1216d961a43aSToby Isaac PetscFunctionReturn(0); 1217d961a43aSToby Isaac } 12180c37af3bSToby Isaac 12190c37af3bSToby Isaac #undef __FUNCT__ 1220b3a4bf2aSToby Isaac #define __FUNCT__ "EvaluateBasis" 1221b3a4bf2aSToby Isaac static PetscErrorCode EvaluateBasis(PetscSpace space, PetscInt nFunctionals, PetscInt nPoints, const PetscInt *pointsPerFn, const PetscReal *points, const PetscReal *weights, PetscReal *work, Mat basisAtPoints) 1222b3a4bf2aSToby Isaac { 1223b3a4bf2aSToby Isaac PetscInt i, j, k, offset, qPoints; 1224b3a4bf2aSToby Isaac PetscErrorCode ierr; 1225b3a4bf2aSToby Isaac 1226b3a4bf2aSToby Isaac PetscFunctionBegin; 1227b3a4bf2aSToby Isaac ierr = PetscSpaceEvaluate(space,nPoints,points,work,NULL,NULL);CHKERRQ(ierr); 1228b3a4bf2aSToby Isaac for (i = 0, offset = 0; i < nFunctionals; i++) { 1229b3a4bf2aSToby Isaac qPoints = pointsPerFn[i]; 1230b3a4bf2aSToby Isaac for (j = 0; j < nFunctionals; j++) { 1231b3a4bf2aSToby Isaac PetscScalar val = 0.; 1232b3a4bf2aSToby Isaac 1233b3a4bf2aSToby Isaac for (k = 0; k < qPoints; k++) { 1234b3a4bf2aSToby Isaac val += work[(offset + k) * nFunctionals + j] * weights[k]; 1235b3a4bf2aSToby Isaac } 1236b3a4bf2aSToby Isaac ierr = MatSetValue(basisAtPoints,j,i,val,INSERT_VALUES);CHKERRQ(ierr); 1237b3a4bf2aSToby Isaac } 1238b3a4bf2aSToby Isaac offset += qPoints; 1239b3a4bf2aSToby Isaac } 1240b3a4bf2aSToby Isaac ierr = MatAssemblyBegin(basisAtPoints,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1241b3a4bf2aSToby Isaac ierr = MatAssemblyEnd(basisAtPoints,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1242b3a4bf2aSToby Isaac PetscFunctionReturn(0); 1243b3a4bf2aSToby Isaac } 1244b3a4bf2aSToby Isaac 1245b3a4bf2aSToby Isaac #undef __FUNCT__ 1246f7c74593SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_Direct" 1247f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 12480c37af3bSToby Isaac { 12490c37af3bSToby Isaac PetscDS ds; 12500c37af3bSToby Isaac PetscInt spdim; 12510c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 12520c37af3bSToby Isaac const PetscInt *anchors; 1253f7c74593SToby Isaac PetscSection aSec; 12540c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 12550c37af3bSToby Isaac IS aIS; 12560c37af3bSToby Isaac PetscErrorCode ierr; 12570c37af3bSToby Isaac 12580c37af3bSToby Isaac PetscFunctionBegin; 12590c37af3bSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 12600c37af3bSToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 12610c37af3bSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 12620c37af3bSToby Isaac ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 1263a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 12640c37af3bSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 12650c37af3bSToby Isaac ierr = PetscSectionGetChart(cSec,&conStart,&conEnd);CHKERRQ(ierr); 126628f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&spdim);CHKERRQ(ierr); 12670c37af3bSToby Isaac ierr = PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent);CHKERRQ(ierr); 12680c37af3bSToby Isaac 12690c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 12700dd1b1feSToby Isaac PetscObject disc; 12710dd1b1feSToby Isaac PetscClassId id; 1272b3a4bf2aSToby Isaac PetscSpace bspace; 1273b3a4bf2aSToby Isaac PetscDualSpace dspace; 12740c37af3bSToby Isaac PetscInt i, j, k, nPoints, offset; 12750c37af3bSToby Isaac PetscInt fSize, fComp; 1276b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 1277b3a4bf2aSToby Isaac PetscInt *sizes; 12780c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 1279085f0adfSToby Isaac const PetscInt ***perms = NULL; 1280085f0adfSToby Isaac const PetscScalar ***flips = NULL; 12810c37af3bSToby Isaac 12820dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 12830dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 12840dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1285b3a4bf2aSToby Isaac PetscFE fe = (PetscFE) disc; 1286b3a4bf2aSToby Isaac 1287b3a4bf2aSToby Isaac ierr = PetscFEGetBasisSpace(fe,&bspace);CHKERRQ(ierr); 1288b3a4bf2aSToby Isaac ierr = PetscFEGetDualSpace(fe,&dspace);CHKERRQ(ierr); 1289b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetDimension(dspace,&fSize);CHKERRQ(ierr); 12900c37af3bSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 12910dd1b1feSToby Isaac } 12920dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 1293b3a4bf2aSToby Isaac PetscFV fv = (PetscFV) disc; 1294b3a4bf2aSToby Isaac 1295b3a4bf2aSToby Isaac ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)fv),&bspace);CHKERRQ(ierr); 1296b3a4bf2aSToby Isaac ierr = PetscSpaceSetType(bspace,PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr); 1297b3a4bf2aSToby Isaac ierr = PetscSpaceSetOrder(bspace,0);CHKERRQ(ierr); 1298b3a4bf2aSToby Isaac ierr = PetscSpacePolynomialSetNumVariables(bspace,spdim);CHKERRQ(ierr); 1299b3a4bf2aSToby Isaac ierr = PetscSpaceSetUp(bspace);CHKERRQ(ierr); 1300b3a4bf2aSToby Isaac ierr = PetscFVGetDualSpace(fv,&dspace);CHKERRQ(ierr); 1301b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetDimension(dspace,&fSize);CHKERRQ(ierr); 13020dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 13030dd1b1feSToby Isaac } 13040dd1b1feSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 1305085f0adfSToby Isaac ierr = PetscDualSpaceGetSymmetries(dspace,&perms,&flips);CHKERRQ(ierr); 13060dd1b1feSToby Isaac 13070c37af3bSToby Isaac ierr = MatCreate(PETSC_COMM_SELF,&Amat);CHKERRQ(ierr); 13080c37af3bSToby Isaac ierr = MatSetSizes(Amat,fSize,fSize,fSize,fSize);CHKERRQ(ierr); 13090c37af3bSToby Isaac ierr = MatSetType(Amat,MATSEQDENSE);CHKERRQ(ierr); 13100c37af3bSToby Isaac ierr = MatSetUp(Amat);CHKERRQ(ierr); 13110c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat);CHKERRQ(ierr); 13120c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat);CHKERRQ(ierr); 13130c37af3bSToby Isaac nPoints = 0; 13140c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 13150c37af3bSToby Isaac PetscInt qPoints; 13160c37af3bSToby Isaac PetscQuadrature quad; 13170c37af3bSToby Isaac 1318b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetFunctional(dspace,i,&quad);CHKERRQ(ierr); 13190c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 13200c37af3bSToby Isaac nPoints += qPoints; 13210c37af3bSToby Isaac } 1322b3a4bf2aSToby Isaac ierr = PetscMalloc5(fSize,&sizes,nPoints,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal,fSize*nPoints,&work);CHKERRQ(ierr); 13230c37af3bSToby Isaac offset = 0; 13240c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 13250c37af3bSToby Isaac PetscInt qPoints; 13260c37af3bSToby Isaac const PetscReal *p, *w; 13270c37af3bSToby Isaac PetscQuadrature quad; 13280c37af3bSToby Isaac 1329b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetFunctional(dspace,i,&quad);CHKERRQ(ierr); 13300c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,&p,&w);CHKERRQ(ierr); 13310c37af3bSToby Isaac ierr = PetscMemcpy(weights+offset,w,qPoints*sizeof(*w));CHKERRQ(ierr); 13320c37af3bSToby Isaac ierr = PetscMemcpy(pointsRef+spdim*offset,p,spdim*qPoints*sizeof(*p));CHKERRQ(ierr); 1333b3a4bf2aSToby Isaac sizes[i] = qPoints; 13340c37af3bSToby Isaac offset += qPoints; 13350c37af3bSToby Isaac } 1336b3a4bf2aSToby Isaac ierr = EvaluateBasis(bspace,fSize,nPoints,sizes,pointsRef,weights,work,Amat);CHKERRQ(ierr); 13370c37af3bSToby Isaac ierr = MatLUFactor(Amat,NULL,NULL,NULL);CHKERRQ(ierr); 13380c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 13390c37af3bSToby Isaac PetscInt parent; 13400c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 13410c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 13420c37af3bSToby Isaac 13430c37af3bSToby Isaac ierr = DMPlexGetTreeParent(dm,c,&parent,NULL);CHKERRQ(ierr); 13440c37af3bSToby Isaac if (parent == c) continue; 13450c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13460c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13470c37af3bSToby Isaac PetscInt p = closure[2*i]; 13480c37af3bSToby Isaac PetscInt conDof; 13490c37af3bSToby Isaac 13500c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1351085f0adfSToby Isaac if (numFields) { 13520c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 13530c37af3bSToby Isaac } 13540c37af3bSToby Isaac else { 13550c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 13560c37af3bSToby Isaac } 13570c37af3bSToby Isaac if (conDof) break; 13580c37af3bSToby Isaac } 13590c37af3bSToby Isaac if (i == closureSize) { 13600c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13610c37af3bSToby Isaac continue; 13620c37af3bSToby Isaac } 13630c37af3bSToby Isaac 136473a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 136573a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent);CHKERRQ(ierr); 13660c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1367b3a4bf2aSToby Isaac CoordinatesRefToReal(spdim, spdim, v0, J, &pointsRef[i*spdim],vtmp); 1368b3a4bf2aSToby Isaac CoordinatesRealToRef(spdim, spdim, v0parent, invJparent, vtmp, &pointsReal[i*spdim]); 13690c37af3bSToby Isaac } 1370b3a4bf2aSToby Isaac ierr = EvaluateBasis(bspace,fSize,nPoints,sizes,pointsReal,weights,work,Bmat);CHKERRQ(ierr); 13710c37af3bSToby Isaac ierr = MatMatSolve(Amat,Bmat,Xmat);CHKERRQ(ierr); 13720c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 13730c37af3bSToby Isaac ierr = PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets);CHKERRQ(ierr); 13740c37af3bSToby Isaac childOffsets[0] = 0; 13750c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13760c37af3bSToby Isaac PetscInt p = closure[2*i]; 13770c37af3bSToby Isaac PetscInt dof; 13780c37af3bSToby Isaac 1379085f0adfSToby Isaac if (numFields) { 13800c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 13810c37af3bSToby Isaac } 13820c37af3bSToby Isaac else { 13830c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 13840c37af3bSToby Isaac } 13850c37af3bSToby Isaac childOffsets[i+1]=childOffsets[i]+dof / fComp; 13860c37af3bSToby Isaac } 13870c37af3bSToby Isaac parentOffsets[0] = 0; 13880c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 13890c37af3bSToby Isaac PetscInt p = closureP[2*i]; 13900c37af3bSToby Isaac PetscInt dof; 13910c37af3bSToby Isaac 1392085f0adfSToby Isaac if (numFields) { 13930c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 13940c37af3bSToby Isaac } 13950c37af3bSToby Isaac else { 13960c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 13970c37af3bSToby Isaac } 13980c37af3bSToby Isaac parentOffsets[i+1]=parentOffsets[i]+dof / fComp; 13990c37af3bSToby Isaac } 14000c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 14010c37af3bSToby Isaac PetscInt conDof, conOff, aDof, aOff; 14020c37af3bSToby Isaac PetscInt p = closure[2*i]; 14030c37af3bSToby Isaac PetscInt o = closure[2*i+1]; 1404085f0adfSToby Isaac const PetscInt *perm; 1405085f0adfSToby Isaac const PetscScalar *flip; 14060c37af3bSToby Isaac 14070c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1408085f0adfSToby Isaac if (numFields) { 14090c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 14100c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(cSec,p,f,&conOff);CHKERRQ(ierr); 14110c37af3bSToby Isaac } 14120c37af3bSToby Isaac else { 14130c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 14140c37af3bSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&conOff);CHKERRQ(ierr); 14150c37af3bSToby Isaac } 14160c37af3bSToby Isaac if (!conDof) continue; 1417085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL; 1418085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL; 14190c37af3bSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 14200c37af3bSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 14210c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 14220c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 14230c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 14240c37af3bSToby Isaac 1425085f0adfSToby Isaac if (numFields) { 14260c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,a,f,&aSecDof);CHKERRQ(ierr); 14270c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(section,a,f,&aSecOff);CHKERRQ(ierr); 14280c37af3bSToby Isaac } 14290c37af3bSToby Isaac else { 14300c37af3bSToby Isaac ierr = PetscSectionGetDof(section,a,&aSecDof);CHKERRQ(ierr); 14310c37af3bSToby Isaac ierr = PetscSectionGetOffset(section,a,&aSecOff);CHKERRQ(ierr); 14320c37af3bSToby Isaac } 14330c37af3bSToby Isaac if (!aSecDof) continue; 14340c37af3bSToby Isaac 14350c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 14360c37af3bSToby Isaac PetscInt q = closureP[2*j]; 14370c37af3bSToby Isaac PetscInt oq = closureP[2*j+1]; 1438085f0adfSToby Isaac const PetscInt *permP; 1439085f0adfSToby Isaac const PetscScalar *flipP; 1440085f0adfSToby Isaac 1441085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL; 1442085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL; 14430c37af3bSToby Isaac 14440c37af3bSToby Isaac if (q == a) { 14450c37af3bSToby Isaac PetscInt r, s, t; 14460c37af3bSToby Isaac 14470c37af3bSToby Isaac for (r = childOffsets[i]; r < childOffsets[i+1]; r++) { 1448085f0adfSToby Isaac PetscInt ri = perm ? perm[r - childOffsets[i]] : (r - childOffsets[i]); 1449085f0adfSToby Isaac 14500c37af3bSToby Isaac for (s = parentOffsets[j]; s < parentOffsets[j+1]; s++) { 1451085f0adfSToby Isaac PetscInt sj = permP ? permP[s - parentOffsets[j]] : (s - parentOffsets[j]); 14520c37af3bSToby Isaac PetscScalar val; 14530c37af3bSToby Isaac PetscInt insertCol, insertRow; 14540c37af3bSToby Isaac 1455085f0adfSToby Isaac ierr = MatGetValue(Xmat,parentOffsets[j] + sj,childOffsets[i] + ri,&val);CHKERRQ(ierr); 1456085f0adfSToby Isaac if (flip) val *= flip [ri]; 1457085f0adfSToby Isaac if (flipP) val *= flipP[sj]; 14580c37af3bSToby Isaac insertRow = conOff + fComp * (r - childOffsets[i]); 14590c37af3bSToby Isaac insertCol = aSecOff + fComp * (s - parentOffsets[j]); 14600c37af3bSToby Isaac for (t = 0; t < fComp; t++) { 14610c37af3bSToby Isaac ierr = MatSetValue(cMat,insertRow + t,insertCol + t,val,INSERT_VALUES);CHKERRQ(ierr); 14620c37af3bSToby Isaac } 14630c37af3bSToby Isaac } 14640c37af3bSToby Isaac } 14650c37af3bSToby Isaac } 14660c37af3bSToby Isaac } 14670c37af3bSToby Isaac } 14680c37af3bSToby Isaac } 14690c37af3bSToby Isaac ierr = PetscFree2(childOffsets,parentOffsets);CHKERRQ(ierr); 14700c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 14710c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 14720c37af3bSToby Isaac } 14730c37af3bSToby Isaac ierr = MatDestroy(&Amat);CHKERRQ(ierr); 14740c37af3bSToby Isaac ierr = MatDestroy(&Bmat);CHKERRQ(ierr); 14750c37af3bSToby Isaac ierr = MatDestroy(&Xmat);CHKERRQ(ierr); 1476b3a4bf2aSToby Isaac ierr = PetscFree5(sizes,weights,pointsRef,pointsReal,work);CHKERRQ(ierr); 1477b3a4bf2aSToby Isaac if (id == PETSCFV_CLASSID) { 1478b3a4bf2aSToby Isaac ierr = PetscSpaceDestroy(&bspace);CHKERRQ(ierr); 1479b3a4bf2aSToby Isaac } 14800c37af3bSToby Isaac } 14810c37af3bSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14820c37af3bSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14830c37af3bSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent);CHKERRQ(ierr); 14840c37af3bSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 14850c37af3bSToby Isaac 14860c37af3bSToby Isaac PetscFunctionReturn(0); 14870c37af3bSToby Isaac } 148895a0b26dSToby Isaac 148995a0b26dSToby Isaac #undef __FUNCT__ 149021968bf8SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildrenMatrices" 149121968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 149295a0b26dSToby Isaac { 1493f7c74593SToby Isaac Mat refCmat; 149421968bf8SToby Isaac PetscDS ds; 1495085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 149621968bf8SToby Isaac PetscScalar ***refPointFieldMats; 149721968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 149821968bf8SToby Isaac IS refAnIS; 149921968bf8SToby Isaac const PetscInt *refAnchors; 1500085f0adfSToby Isaac const PetscInt **perms; 1501085f0adfSToby Isaac const PetscScalar **flips; 150295a0b26dSToby Isaac PetscErrorCode ierr; 150395a0b26dSToby Isaac 150495a0b26dSToby Isaac PetscFunctionBegin; 150521968bf8SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 150695a0b26dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 1507085f0adfSToby Isaac maxFields = PetscMax(1,numFields); 1508f7c74593SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 1509a17985deSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 151095a0b26dSToby Isaac ierr = ISGetIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 151195a0b26dSToby Isaac ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr); 151295a0b26dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 151395a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr); 151495a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldN);CHKERRQ(ierr); 151595a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 151695a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 151795a0b26dSToby Isaac ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr); 151895a0b26dSToby Isaac ierr = PetscMalloc1(maxDof*maxAnDof,&cols);CHKERRQ(ierr); 151995a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 152095a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 152195a0b26dSToby Isaac 152295a0b26dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 152395a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 152495a0b26dSToby Isaac if (!pDof || parent == p) continue; 152595a0b26dSToby Isaac 1526085f0adfSToby Isaac ierr = PetscMalloc1(maxFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr); 1527085f0adfSToby Isaac ierr = PetscCalloc1(maxFields,&refPointFieldN[p-pRefStart]);CHKERRQ(ierr); 152895a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1529085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1530085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i; 153195a0b26dSToby Isaac 1532085f0adfSToby Isaac if (f < numFields) { 153395a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 153495a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr); 1535085f0adfSToby Isaac ierr = PetscSectionGetFieldPointSyms(refSection,f,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1536085f0adfSToby Isaac } else { 153795a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 153895a0b26dSToby Isaac ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr); 1539085f0adfSToby Isaac ierr = PetscSectionGetPointSyms(refSection,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 154095a0b26dSToby Isaac } 154195a0b26dSToby Isaac 154295a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 154395a0b26dSToby Isaac rows[r] = cOff + r; 154495a0b26dSToby Isaac } 154595a0b26dSToby Isaac numCols = 0; 154695a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 154795a0b26dSToby Isaac PetscInt q = closure[2*i]; 154895a0b26dSToby Isaac PetscInt aDof, aOff, j; 1549085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 155095a0b26dSToby Isaac 1551085f0adfSToby Isaac if (numFields) { 155295a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refSection,q,f,&aDof);CHKERRQ(ierr); 155395a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,q,f,&aOff);CHKERRQ(ierr); 155495a0b26dSToby Isaac } 155595a0b26dSToby Isaac else { 155695a0b26dSToby Isaac ierr = PetscSectionGetDof(refSection,q,&aDof);CHKERRQ(ierr); 155795a0b26dSToby Isaac ierr = PetscSectionGetOffset(refSection,q,&aOff);CHKERRQ(ierr); 155895a0b26dSToby Isaac } 155995a0b26dSToby Isaac 156095a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 1561085f0adfSToby Isaac cols[numCols++] = aOff + (perm ? perm[j] : j); 156295a0b26dSToby Isaac } 156395a0b26dSToby Isaac } 156495a0b26dSToby Isaac refPointFieldN[p-pRefStart][f] = numCols; 156595a0b26dSToby Isaac ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 156695a0b26dSToby Isaac ierr = MatGetValues(refCmat,cDof,rows,numCols,cols,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 1567085f0adfSToby Isaac if (flips) { 1568085f0adfSToby Isaac PetscInt colOff = 0; 1569085f0adfSToby Isaac 1570085f0adfSToby Isaac for (i = 0; i < closureSize; i++) { 1571085f0adfSToby Isaac PetscInt q = closure[2*i]; 1572085f0adfSToby Isaac PetscInt aDof, aOff, j; 1573085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 1574085f0adfSToby Isaac 1575085f0adfSToby Isaac if (numFields) { 1576085f0adfSToby Isaac ierr = PetscSectionGetFieldDof(refSection,q,f,&aDof);CHKERRQ(ierr); 1577085f0adfSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,q,f,&aOff);CHKERRQ(ierr); 1578085f0adfSToby Isaac } 1579085f0adfSToby Isaac else { 1580085f0adfSToby Isaac ierr = PetscSectionGetDof(refSection,q,&aDof);CHKERRQ(ierr); 1581085f0adfSToby Isaac ierr = PetscSectionGetOffset(refSection,q,&aOff);CHKERRQ(ierr); 1582085f0adfSToby Isaac } 1583085f0adfSToby Isaac if (flip) { 1584085f0adfSToby Isaac PetscInt k; 1585085f0adfSToby Isaac for (k = 0; k < cDof; k++) { 1586085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1587085f0adfSToby Isaac refPointFieldMats[p-pRefStart][f][k * numCols + colOff + j] *= flip[j]; 1588085f0adfSToby Isaac } 1589085f0adfSToby Isaac } 1590085f0adfSToby Isaac } 1591085f0adfSToby Isaac colOff += aDof; 1592085f0adfSToby Isaac } 1593085f0adfSToby Isaac } 1594085f0adfSToby Isaac if (numFields) { 1595085f0adfSToby Isaac ierr = PetscSectionRestoreFieldPointSyms(refSection,f,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1596085f0adfSToby Isaac } else { 1597085f0adfSToby Isaac ierr = PetscSectionRestorePointSyms(refSection,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1598085f0adfSToby Isaac } 159995a0b26dSToby Isaac } 160095a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 160195a0b26dSToby Isaac } 160221968bf8SToby Isaac *childrenMats = refPointFieldMats; 160321968bf8SToby Isaac *childrenN = refPointFieldN; 160421968bf8SToby Isaac ierr = ISRestoreIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 160521968bf8SToby Isaac ierr = PetscFree(rows);CHKERRQ(ierr); 160621968bf8SToby Isaac ierr = PetscFree(cols);CHKERRQ(ierr); 160721968bf8SToby Isaac PetscFunctionReturn(0); 160821968bf8SToby Isaac } 160921968bf8SToby Isaac 161021968bf8SToby Isaac #undef __FUNCT__ 161121968bf8SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeRestoreChildrenMatrices" 161221968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 161321968bf8SToby Isaac { 161421968bf8SToby Isaac PetscDS ds; 161521968bf8SToby Isaac PetscInt **refPointFieldN; 161621968bf8SToby Isaac PetscScalar ***refPointFieldMats; 1617085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f; 161821968bf8SToby Isaac PetscSection refConSec; 161921968bf8SToby Isaac PetscErrorCode ierr; 162021968bf8SToby Isaac 162121968bf8SToby Isaac PetscFunctionBegin; 162221968bf8SToby Isaac refPointFieldN = *childrenN; 162321968bf8SToby Isaac *childrenN = NULL; 162421968bf8SToby Isaac refPointFieldMats = *childrenMats; 162521968bf8SToby Isaac *childrenMats = NULL; 162621968bf8SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 162721968bf8SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 1628085f0adfSToby Isaac maxFields = PetscMax(1,numFields);CHKERRQ(ierr); 162921968bf8SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 1630e44e4e7fSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 163121968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 163221968bf8SToby Isaac PetscInt parent, pDof; 163321968bf8SToby Isaac 163421968bf8SToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 163521968bf8SToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 163621968bf8SToby Isaac if (!pDof || parent == p) continue; 163721968bf8SToby Isaac 1638085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 163921968bf8SToby Isaac PetscInt cDof; 164021968bf8SToby Isaac 1641085f0adfSToby Isaac if (numFields) { 164221968bf8SToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 164321968bf8SToby Isaac } 164421968bf8SToby Isaac else { 164521968bf8SToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 164621968bf8SToby Isaac } 164721968bf8SToby Isaac 164821968bf8SToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr); 164921968bf8SToby Isaac } 165021968bf8SToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr); 165121968bf8SToby Isaac ierr = PetscFree(refPointFieldN[p - pRefStart]);CHKERRQ(ierr); 165221968bf8SToby Isaac } 165321968bf8SToby Isaac ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr); 165421968bf8SToby Isaac ierr = PetscFree(refPointFieldN);CHKERRQ(ierr); 165521968bf8SToby Isaac PetscFunctionReturn(0); 165621968bf8SToby Isaac } 165721968bf8SToby Isaac 165821968bf8SToby Isaac #undef __FUNCT__ 165921968bf8SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_FromReference" 166021968bf8SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 166121968bf8SToby Isaac { 166221968bf8SToby Isaac DM refTree; 166321968bf8SToby Isaac PetscDS ds; 166421968bf8SToby Isaac Mat refCmat; 1665085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 166621968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 166721968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 166821968bf8SToby Isaac IS refAnIS, anIS; 166921968bf8SToby Isaac const PetscInt *anchors; 167021968bf8SToby Isaac PetscErrorCode ierr; 167121968bf8SToby Isaac 167221968bf8SToby Isaac PetscFunctionBegin; 167321968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 167421968bf8SToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 167521968bf8SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 1676085f0adfSToby Isaac maxFields = PetscMax(1,numFields); 167721968bf8SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 167821968bf8SToby Isaac ierr = DMSetDS(refTree,ds);CHKERRQ(ierr); 167921968bf8SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 168021968bf8SToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 168121968bf8SToby Isaac ierr = DMPlexGetAnchors(dm,&anSec,&anIS);CHKERRQ(ierr); 168221968bf8SToby Isaac ierr = ISGetIndices(anIS,&anchors);CHKERRQ(ierr); 168321968bf8SToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 168421968bf8SToby Isaac ierr = PetscSectionGetChart(conSec,&conStart,&conEnd);CHKERRQ(ierr); 168521968bf8SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 168621968bf8SToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 168721968bf8SToby Isaac ierr = PetscMalloc1(maxDof*maxDof*maxAnDof,&pointWork);CHKERRQ(ierr); 168821968bf8SToby Isaac 168921968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 169021968bf8SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 169195a0b26dSToby Isaac 169295a0b26dSToby Isaac /* step 2: compute the preorder */ 169395a0b26dSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 169495a0b26dSToby Isaac ierr = PetscMalloc2(pEnd-pStart,&perm,pEnd-pStart,&iperm);CHKERRQ(ierr); 169595a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 169695a0b26dSToby Isaac perm[p - pStart] = p; 169795a0b26dSToby Isaac iperm[p - pStart] = p-pStart; 169895a0b26dSToby Isaac } 169995a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 170095a0b26dSToby Isaac PetscInt point = perm[p]; 170195a0b26dSToby Isaac PetscInt parent; 170295a0b26dSToby Isaac 170395a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 170495a0b26dSToby Isaac if (parent == point) { 170595a0b26dSToby Isaac p++; 170695a0b26dSToby Isaac } 170795a0b26dSToby Isaac else { 170895a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 170995a0b26dSToby Isaac 171095a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 171195a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 171295a0b26dSToby Isaac PetscInt q = closure[2*i]; 171395a0b26dSToby Isaac if (iperm[q-pStart] > iperm[point-pStart]) { 171495a0b26dSToby Isaac /* swap */ 171595a0b26dSToby Isaac perm[p] = q; 171695a0b26dSToby Isaac perm[iperm[q-pStart]] = point; 171795a0b26dSToby Isaac iperm[point-pStart] = iperm[q-pStart]; 171895a0b26dSToby Isaac iperm[q-pStart] = p; 171995a0b26dSToby Isaac break; 172095a0b26dSToby Isaac } 172195a0b26dSToby Isaac } 172295a0b26dSToby Isaac size = closureSize; 172395a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 172495a0b26dSToby Isaac if (i == size) { 172595a0b26dSToby Isaac p++; 172695a0b26dSToby Isaac } 172795a0b26dSToby Isaac } 172895a0b26dSToby Isaac } 172995a0b26dSToby Isaac 173095a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 173195a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 173295a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 173395a0b26dSToby Isaac * values outside of the Mat first. 173495a0b26dSToby Isaac */ 173595a0b26dSToby Isaac { 173695a0b26dSToby Isaac PetscInt nRows, row, nnz; 173795a0b26dSToby Isaac PetscBool done; 173895a0b26dSToby Isaac const PetscInt *ia, *ja; 173995a0b26dSToby Isaac PetscScalar *vals; 174095a0b26dSToby Isaac 174195a0b26dSToby Isaac ierr = MatGetRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 174295a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not get RowIJ of constraint matrix"); 174395a0b26dSToby Isaac nnz = ia[nRows]; 174495a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 174595a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 174695a0b26dSToby Isaac ierr = PetscMalloc1(nnz,&vals);CHKERRQ(ierr); 174795a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 174895a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 174995a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 175095a0b26dSToby Isaac 175195a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,&childid);CHKERRQ(ierr); 175295a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 175395a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&pointDof);CHKERRQ(ierr); 175495a0b26dSToby Isaac if (!pointDof) continue; 175595a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1756085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1757085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 175895a0b26dSToby Isaac PetscScalar *pointMat; 1759085f0adfSToby Isaac const PetscInt **perms; 1760085f0adfSToby Isaac const PetscScalar **flips; 176195a0b26dSToby Isaac 1762085f0adfSToby Isaac if (numFields) { 176395a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,point,f,&cDof);CHKERRQ(ierr); 176495a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,point,f,&cOff);CHKERRQ(ierr); 176595a0b26dSToby Isaac } 176695a0b26dSToby Isaac else { 176795a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&cDof);CHKERRQ(ierr); 176895a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,point,&cOff);CHKERRQ(ierr); 176995a0b26dSToby Isaac } 177095a0b26dSToby Isaac if (!cDof) continue; 1771085f0adfSToby Isaac if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,closureSize,closure,&perms,&flips);CHKERRQ(ierr);} 1772085f0adfSToby Isaac else {ierr = PetscSectionGetPointSyms(section,closureSize,closure,&perms,&flips);CHKERRQ(ierr);} 177395a0b26dSToby Isaac 177495a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 177595a0b26dSToby Isaac #if defined(PETSC_USE_DEBUG) 177695a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 177795a0b26dSToby Isaac if (cDof > 1 && r) { 177821968bf8SToby Isaac if ((ia[cOff+r+1]-ia[cOff+r]) != (ia[cOff+r]-ia[cOff+r-1])) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Two point rows have different nnz: %D vs. %D", (ia[cOff+r+1]-ia[cOff+r]), (ia[cOff+r]-ia[cOff+r-1])); 177995a0b26dSToby Isaac } 178095a0b26dSToby Isaac } 178195a0b26dSToby Isaac #endif 178295a0b26dSToby Isaac /* zero rows */ 178395a0b26dSToby Isaac for (i = ia[cOff] ; i< ia[cOff+cDof];i++) { 178495a0b26dSToby Isaac vals[i] = 0.; 178595a0b26dSToby Isaac } 178695a0b26dSToby Isaac matOffset = ia[cOff]; 178795a0b26dSToby Isaac numFillCols = ia[cOff+1] - matOffset; 178895a0b26dSToby Isaac pointMat = refPointFieldMats[childid-pRefStart][f]; 178995a0b26dSToby Isaac numCols = refPointFieldN[childid-pRefStart][f]; 179095a0b26dSToby Isaac offset = 0; 179195a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 179295a0b26dSToby Isaac PetscInt q = closure[2*i]; 179395a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 1794085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1795085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 179695a0b26dSToby Isaac 179795a0b26dSToby Isaac qConDof = qConOff = 0; 1798085f0adfSToby Isaac if (numFields) { 179995a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(section,q,f,&aDof);CHKERRQ(ierr); 180095a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(section,q,f,&aOff);CHKERRQ(ierr); 180195a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 180295a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,q,f,&qConDof);CHKERRQ(ierr); 180395a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,q,f,&qConOff);CHKERRQ(ierr); 180495a0b26dSToby Isaac } 180595a0b26dSToby Isaac } 180695a0b26dSToby Isaac else { 180795a0b26dSToby Isaac ierr = PetscSectionGetDof(section,q,&aDof);CHKERRQ(ierr); 180895a0b26dSToby Isaac ierr = PetscSectionGetOffset(section,q,&aOff);CHKERRQ(ierr); 180995a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 181095a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,q,&qConDof);CHKERRQ(ierr); 181195a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,q,&qConOff);CHKERRQ(ierr); 181295a0b26dSToby Isaac } 181395a0b26dSToby Isaac } 181495a0b26dSToby Isaac if (!aDof) continue; 181595a0b26dSToby Isaac if (qConDof) { 181695a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 181795a0b26dSToby Isaac * be filled, thanks to preordering */ 181895a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 181995a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 182095a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 182195a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 182295a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 182395a0b26dSToby Isaac PetscScalar inVal = 0; 182495a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1825085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 182695a0b26dSToby Isaac 1827085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 182895a0b26dSToby Isaac } 182995a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 183095a0b26dSToby Isaac } 183195a0b26dSToby Isaac } 183295a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 183395a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 183495a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 183595a0b26dSToby Isaac for (;k < numFillCols; k++) { 183695a0b26dSToby Isaac if (ja[matOffset + k] == col) { 183795a0b26dSToby Isaac break; 183895a0b26dSToby Isaac } 183995a0b26dSToby Isaac } 184095a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, col); 184195a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 184295a0b26dSToby Isaac vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 184395a0b26dSToby Isaac } 184495a0b26dSToby Isaac } 184595a0b26dSToby Isaac } 184695a0b26dSToby Isaac else { 184795a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 184895a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 184995a0b26dSToby Isaac if (ja[matOffset + k] == aOff) { 185095a0b26dSToby Isaac break; 185195a0b26dSToby Isaac } 185295a0b26dSToby Isaac } 185395a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, aOff); 185495a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1855085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1856085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1857085f0adfSToby Isaac 1858085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 185995a0b26dSToby Isaac } 186095a0b26dSToby Isaac } 186195a0b26dSToby Isaac } 186295a0b26dSToby Isaac offset += aDof; 186395a0b26dSToby Isaac } 1864085f0adfSToby Isaac if (numFields) { 1865085f0adfSToby Isaac ierr = PetscSectionRestoreFieldPointSyms(section,f,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1866085f0adfSToby Isaac } else { 1867085f0adfSToby Isaac ierr = PetscSectionRestorePointSyms(section,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1868085f0adfSToby Isaac } 186995a0b26dSToby Isaac } 187095a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 187195a0b26dSToby Isaac } 187295a0b26dSToby Isaac for (row = 0; row < nRows; row++) { 187395a0b26dSToby Isaac ierr = MatSetValues(cMat,1,&row,ia[row+1]-ia[row],&ja[ia[row]],&vals[ia[row]],INSERT_VALUES);CHKERRQ(ierr); 187495a0b26dSToby Isaac } 187595a0b26dSToby Isaac ierr = MatRestoreRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 187695a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not restore RowIJ of constraint matrix"); 187795a0b26dSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 187895a0b26dSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 187995a0b26dSToby Isaac ierr = PetscFree(vals);CHKERRQ(ierr); 188095a0b26dSToby Isaac } 188195a0b26dSToby Isaac 188295a0b26dSToby Isaac /* clean up */ 188395a0b26dSToby Isaac ierr = ISRestoreIndices(anIS,&anchors);CHKERRQ(ierr); 188495a0b26dSToby Isaac ierr = PetscFree2(perm,iperm);CHKERRQ(ierr); 188595a0b26dSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 188621968bf8SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 188795a0b26dSToby Isaac PetscFunctionReturn(0); 188895a0b26dSToby Isaac } 188995a0b26dSToby Isaac 18906f5f1567SToby Isaac #undef __FUNCT__ 18916f5f1567SToby Isaac #define __FUNCT__ "DMPlexTreeRefineCell" 18926f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 18936f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 18946f5f1567SToby Isaac PetscErrorCode DMPlexTreeRefineCell (DM dm, PetscInt cell, DM *ncdm) 18956f5f1567SToby Isaac { 18966f5f1567SToby Isaac DM K; 1897420f55faSMatthew G. Knepley PetscMPIInt rank; 18986f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 18996f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 19006f5f1567SToby Isaac PetscInt *Kembedding; 19016f5f1567SToby Isaac PetscInt *cellClosure=NULL, nc; 19026f5f1567SToby Isaac PetscScalar *newVertexCoords; 19036f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 19046f5f1567SToby Isaac PetscSection parentSection; 19056f5f1567SToby Isaac PetscErrorCode ierr; 19066f5f1567SToby Isaac 19076f5f1567SToby Isaac PetscFunctionBegin; 19086f5f1567SToby Isaac ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr); 190928f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 19106f5f1567SToby Isaac ierr = DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm);CHKERRQ(ierr); 191128f4b327SMatthew G. Knepley ierr = DMSetDimension(*ncdm,dim);CHKERRQ(ierr); 19126f5f1567SToby Isaac 19136f5f1567SToby Isaac ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 19146f5f1567SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&parentSection);CHKERRQ(ierr); 19156f5f1567SToby Isaac ierr = DMPlexGetReferenceTree(dm,&K);CHKERRQ(ierr); 19166f5f1567SToby Isaac if (!rank) { 19176f5f1567SToby Isaac /* compute the new charts */ 19186f5f1567SToby Isaac ierr = PetscMalloc5(dim+1,&pNewCount,dim+1,&pNewStart,dim+1,&pNewEnd,dim+1,&pOldStart,dim+1,&pOldEnd);CHKERRQ(ierr); 19196f5f1567SToby Isaac offset = 0; 19206f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19216f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 19226f5f1567SToby Isaac 19236f5f1567SToby Isaac pNewStart[d] = offset; 19246f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pOldStart[d],&pOldEnd[d]);CHKERRQ(ierr); 19256f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 19266f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 19276f5f1567SToby Isaac /* adding the new points */ 19286f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 19296f5f1567SToby Isaac if (!d) { 19306f5f1567SToby Isaac /* removing the cell */ 19316f5f1567SToby Isaac pNewCount[d]--; 19326f5f1567SToby Isaac } 19336f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19346f5f1567SToby Isaac PetscInt parent; 19356f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&parent,NULL);CHKERRQ(ierr); 19366f5f1567SToby Isaac if (parent == k) { 19376f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 19386f5f1567SToby Isaac pNewCount[d]--; 19396f5f1567SToby Isaac } 19406f5f1567SToby Isaac } 19416f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 19426f5f1567SToby Isaac offset = pNewEnd[d]; 19436f5f1567SToby Isaac 19446f5f1567SToby Isaac } 19456f5f1567SToby Isaac if (cell < pOldStart[0] || cell >= pOldEnd[0]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"%d not in cell range [%d, %d)", cell, pOldStart[0], pOldEnd[0]); 19466f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 19476f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 19486f5f1567SToby Isaac 19496f5f1567SToby Isaac ierr = PetscMalloc1(pNewEnd[dim],&newConeSizes);CHKERRQ(ierr); 19506f5f1567SToby Isaac { 19516f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 19526f5f1567SToby Isaac 19536f5f1567SToby Isaac ierr = DMPlexGetChart(K,&kStart,&kEnd);CHKERRQ(ierr); 19546f5f1567SToby Isaac ierr = PetscMalloc4(kEnd-kStart,&Kembedding,kEnd-kStart,&perm,kEnd-kStart,&iperm,kEnd-kStart,&preOrient);CHKERRQ(ierr); 19556f5f1567SToby Isaac 19566f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19576f5f1567SToby Isaac perm[k - kStart] = k; 19586f5f1567SToby Isaac iperm [k - kStart] = k - kStart; 19596f5f1567SToby Isaac preOrient[k - kStart] = 0; 19606f5f1567SToby Isaac } 19616f5f1567SToby Isaac 19626f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 19636f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 19646f5f1567SToby Isaac PetscInt parentOrientA = closureK[2*j+1]; 19656f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2*j+1]; 19666f5f1567SToby Isaac PetscInt p, q; 19676f5f1567SToby Isaac 19686f5f1567SToby Isaac p = closureK[2*j]; 19696f5f1567SToby Isaac q = cellClosure[2*j]; 19706f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19716f5f1567SToby Isaac if (q >= pOldStart[d] && q < pOldEnd[d]) { 19726f5f1567SToby Isaac Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 19736f5f1567SToby Isaac } 19746f5f1567SToby Isaac } 19756f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 19766f5f1567SToby Isaac PetscInt numChildren, i; 19776f5f1567SToby Isaac const PetscInt *children; 19786f5f1567SToby Isaac 19796f5f1567SToby Isaac ierr = DMPlexGetTreeChildren(K,p,&numChildren,&children);CHKERRQ(ierr); 19806f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 19816f5f1567SToby Isaac PetscInt kPerm, oPerm; 19826f5f1567SToby Isaac 19836f5f1567SToby Isaac k = children[i]; 19846f5f1567SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry(K,p,parentOrientA,0,k,parentOrientB,&oPerm,&kPerm);CHKERRQ(ierr); 19856f5f1567SToby Isaac /* perm = what refTree position I'm in */ 19866f5f1567SToby Isaac perm[kPerm-kStart] = k; 19876f5f1567SToby Isaac /* iperm = who is at this position */ 19886f5f1567SToby Isaac iperm[k-kStart] = kPerm-kStart; 19896f5f1567SToby Isaac preOrient[kPerm-kStart] = oPerm; 19906f5f1567SToby Isaac } 19916f5f1567SToby Isaac } 19926f5f1567SToby Isaac } 19936f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 19946f5f1567SToby Isaac } 19956f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,0,pNewEnd[dim]);CHKERRQ(ierr); 19966f5f1567SToby Isaac offset = 0; 19976f5f1567SToby Isaac numNewCones = 0; 19986f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19996f5f1567SToby Isaac PetscInt kStart, kEnd, k; 20006f5f1567SToby Isaac PetscInt p; 20016f5f1567SToby Isaac PetscInt size; 20026f5f1567SToby Isaac 20036f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 20046f5f1567SToby Isaac /* skip cell 0 */ 20056f5f1567SToby Isaac if (p == cell) continue; 20066f5f1567SToby Isaac /* old cones to new cones */ 20076f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 20086f5f1567SToby Isaac newConeSizes[offset++] = size; 20096f5f1567SToby Isaac numNewCones += size; 20106f5f1567SToby Isaac } 20116f5f1567SToby Isaac 20126f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 20136f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20146f5f1567SToby Isaac PetscInt kParent; 20156f5f1567SToby Isaac 20166f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 20176f5f1567SToby Isaac if (kParent != k) { 20186f5f1567SToby Isaac Kembedding[k] = offset; 20196f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 20206f5f1567SToby Isaac newConeSizes[offset++] = size; 20216f5f1567SToby Isaac numNewCones += size; 20226f5f1567SToby Isaac if (kParent != 0) { 20236f5f1567SToby Isaac ierr = PetscSectionSetDof(parentSection,Kembedding[k],1);CHKERRQ(ierr); 20246f5f1567SToby Isaac } 20256f5f1567SToby Isaac } 20266f5f1567SToby Isaac } 20276f5f1567SToby Isaac } 20286f5f1567SToby Isaac 20296f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 20306f5f1567SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&numPointsWithParents);CHKERRQ(ierr); 20316f5f1567SToby Isaac ierr = PetscMalloc2(numNewCones,&newCones,numNewCones,&newOrientations);CHKERRQ(ierr); 20326f5f1567SToby Isaac ierr = PetscMalloc2(numPointsWithParents,&parents,numPointsWithParents,&childIDs);CHKERRQ(ierr); 20336f5f1567SToby Isaac 20346f5f1567SToby Isaac /* fill new cones */ 20356f5f1567SToby Isaac offset = 0; 20366f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20376f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 20386f5f1567SToby Isaac PetscInt p; 20396f5f1567SToby Isaac PetscInt size; 20406f5f1567SToby Isaac const PetscInt *cone, *orientation; 20416f5f1567SToby Isaac 20426f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 20436f5f1567SToby Isaac /* skip cell 0 */ 20446f5f1567SToby Isaac if (p == cell) continue; 20456f5f1567SToby Isaac /* old cones to new cones */ 20466f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 20476f5f1567SToby Isaac ierr = DMPlexGetCone(dm,p,&cone);CHKERRQ(ierr); 20486f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(dm,p,&orientation);CHKERRQ(ierr); 20496f5f1567SToby Isaac for (l = 0; l < size; l++) { 20506f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 20516f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 20526f5f1567SToby Isaac } 20536f5f1567SToby Isaac } 20546f5f1567SToby Isaac 20556f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 20566f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20576f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 20586f5f1567SToby Isaac PetscInt preO = preOrient[k]; 20596f5f1567SToby Isaac 20606f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 20616f5f1567SToby Isaac if (kParent != k) { 20626f5f1567SToby Isaac /* embed new cones */ 20636f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 20646f5f1567SToby Isaac ierr = DMPlexGetCone(K,kPerm,&cone);CHKERRQ(ierr); 20656f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(K,kPerm,&orientation);CHKERRQ(ierr); 20666f5f1567SToby Isaac for (l = 0; l < size; l++) { 20676f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size -(preO + 1) - l) % size); 20686f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 20696f5f1567SToby Isaac 20706f5f1567SToby Isaac q = iperm[cone[m]]; 20716f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 20726f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,q,&lSize);CHKERRQ(ierr); 20736f5f1567SToby Isaac oTrue = orientation[m]; 20746f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 20756f5f1567SToby Isaac newO = DihedralCompose(lSize,oTrue,preOrient[q]); 20766f5f1567SToby Isaac newOrientations[offset++] = newO; 20776f5f1567SToby Isaac } 20786f5f1567SToby Isaac if (kParent != 0) { 20796f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 20806f5f1567SToby Isaac ierr = PetscSectionGetOffset(parentSection,Kembedding[k],&pOffset);CHKERRQ(ierr); 20816f5f1567SToby Isaac parents[pOffset] = newPoint; 20826f5f1567SToby Isaac childIDs[pOffset] = k; 20836f5f1567SToby Isaac } 20846f5f1567SToby Isaac } 20856f5f1567SToby Isaac } 20866f5f1567SToby Isaac } 20876f5f1567SToby Isaac 20886f5f1567SToby Isaac ierr = PetscMalloc1(dim*(pNewEnd[dim]-pNewStart[dim]),&newVertexCoords);CHKERRQ(ierr); 20896f5f1567SToby Isaac 20906f5f1567SToby Isaac /* fill coordinates */ 20916f5f1567SToby Isaac offset = 0; 20926f5f1567SToby Isaac { 2093d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 20946f5f1567SToby Isaac PetscSection vSection; 20956f5f1567SToby Isaac PetscInt v; 20966f5f1567SToby Isaac Vec coords; 20976f5f1567SToby Isaac PetscScalar *coordvals; 20986f5f1567SToby Isaac PetscInt dof, off; 2099c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 21006f5f1567SToby Isaac 21016f5f1567SToby Isaac #if defined(PETSC_USE_DEBUG) 2102d90620a3SMatthew G. Knepley { 2103d90620a3SMatthew G. Knepley PetscInt k; 21046f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 21056f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 210673a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 21076f5f1567SToby Isaac if (detJ <= 0.) SETERRQ1 (PETSC_COMM_SELF,PETSC_ERR_PLIB,"reference tree cell %d has bad determinant",k); 21086f5f1567SToby Isaac } 2109d90620a3SMatthew G. Knepley } 21106f5f1567SToby Isaac #endif 211173a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 21126f5f1567SToby Isaac ierr = DMGetCoordinateSection(dm,&vSection);CHKERRQ(ierr); 21136f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coords);CHKERRQ(ierr); 21146f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 21156f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 21166f5f1567SToby Isaac 21176f5f1567SToby Isaac ierr = PetscSectionGetDof(vSection,v,&dof);CHKERRQ(ierr); 21186f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,v,&off);CHKERRQ(ierr); 21196f5f1567SToby Isaac for (l = 0; l < dof; l++) { 21206f5f1567SToby Isaac newVertexCoords[offset++] = coordvals[off + l]; 21216f5f1567SToby Isaac } 21226f5f1567SToby Isaac } 21236f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 21246f5f1567SToby Isaac 21256f5f1567SToby Isaac ierr = DMGetCoordinateSection(K,&vSection);CHKERRQ(ierr); 21266f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(K,&coords);CHKERRQ(ierr); 21276f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 21286f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 21296f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 21309bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 21316f5f1567SToby Isaac PetscInt vPerm = perm[v]; 21326f5f1567SToby Isaac PetscInt kParent; 21336f5f1567SToby Isaac 21346f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,v,&kParent,NULL);CHKERRQ(ierr); 21356f5f1567SToby Isaac if (kParent != v) { 21366f5f1567SToby Isaac /* this is a new vertex */ 21376f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,vPerm,&off);CHKERRQ(ierr); 21389bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off+l]); 21399bc368c7SMatthew G. Knepley CoordinatesRefToReal(dim, dim, v0, J, coord, newCoord);CHKERRQ(ierr); 21409bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset+l] = newCoord[l]; 21416f5f1567SToby Isaac offset += dim; 21426f5f1567SToby Isaac } 21436f5f1567SToby Isaac } 21446f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 21456f5f1567SToby Isaac } 21466f5f1567SToby Isaac 21476f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 21486f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 21496f5f1567SToby Isaac PetscInt tmp; 21506f5f1567SToby Isaac 21516f5f1567SToby Isaac tmp = pNewCount[d]; 21526f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 21536f5f1567SToby Isaac pNewCount[dim - d] = tmp; 21546f5f1567SToby Isaac } 21556f5f1567SToby Isaac 21566f5f1567SToby Isaac ierr = DMPlexCreateFromDAG(*ncdm,dim,pNewCount,newConeSizes,newCones,newOrientations,newVertexCoords);CHKERRQ(ierr); 21576f5f1567SToby Isaac ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr); 21586f5f1567SToby Isaac ierr = DMPlexSetTree(*ncdm,parentSection,parents,childIDs);CHKERRQ(ierr); 21596f5f1567SToby Isaac 21606f5f1567SToby Isaac /* clean up */ 21616f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 21626f5f1567SToby Isaac ierr = PetscFree5(pNewCount,pNewStart,pNewEnd,pOldStart,pOldEnd);CHKERRQ(ierr); 21636f5f1567SToby Isaac ierr = PetscFree(newConeSizes);CHKERRQ(ierr); 21646f5f1567SToby Isaac ierr = PetscFree2(newCones,newOrientations);CHKERRQ(ierr); 21656f5f1567SToby Isaac ierr = PetscFree(newVertexCoords);CHKERRQ(ierr); 21666f5f1567SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 21676f5f1567SToby Isaac ierr = PetscFree4(Kembedding,perm,iperm,preOrient);CHKERRQ(ierr); 21686f5f1567SToby Isaac } 21696f5f1567SToby Isaac else { 21706f5f1567SToby Isaac PetscInt p, counts[4]; 21716f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 21726f5f1567SToby Isaac Vec coordVec; 21736f5f1567SToby Isaac PetscScalar *coords; 21746f5f1567SToby Isaac 21756f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 21766f5f1567SToby Isaac PetscInt dStart, dEnd; 21776f5f1567SToby Isaac 21786f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 21796f5f1567SToby Isaac counts[d] = dEnd - dStart; 21806f5f1567SToby Isaac } 21816f5f1567SToby Isaac ierr = PetscMalloc1(pEnd-pStart,&coneSizes);CHKERRQ(ierr); 21826f5f1567SToby Isaac for (p = pStart; p < pEnd; p++) { 21836f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&coneSizes[p-pStart]);CHKERRQ(ierr); 21846f5f1567SToby Isaac } 21856f5f1567SToby Isaac ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 21866f5f1567SToby Isaac ierr = DMPlexGetConeOrientations(dm, &orientations);CHKERRQ(ierr); 21876f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coordVec);CHKERRQ(ierr); 21886f5f1567SToby Isaac ierr = VecGetArray(coordVec,&coords);CHKERRQ(ierr); 21896f5f1567SToby Isaac 21906f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,pStart,pEnd);CHKERRQ(ierr); 21916f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 21926f5f1567SToby Isaac ierr = DMPlexCreateFromDAG(*ncdm,dim,counts,coneSizes,cones,orientations,NULL);CHKERRQ(ierr); 21936f5f1567SToby Isaac ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr); 21946f5f1567SToby Isaac ierr = DMPlexSetTree(*ncdm,parentSection,NULL,NULL);CHKERRQ(ierr); 21956f5f1567SToby Isaac ierr = VecRestoreArray(coordVec,&coords);CHKERRQ(ierr); 21966f5f1567SToby Isaac } 21976f5f1567SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 21986f5f1567SToby Isaac 21996f5f1567SToby Isaac PetscFunctionReturn(0); 22006f5f1567SToby Isaac } 22016ecaa68aSToby Isaac 22026ecaa68aSToby Isaac #undef __FUNCT__ 22036ecaa68aSToby Isaac #define __FUNCT__ "DMPlexComputeInterpolatorTree" 22046ecaa68aSToby Isaac PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 22056ecaa68aSToby Isaac { 22066ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 22076ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 22086ecaa68aSToby Isaac PetscSection localCoarse, localFine; 22096ecaa68aSToby Isaac PetscSection aSec, cSec; 22106ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 221146bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 221246bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 221346bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 22146ecaa68aSToby Isaac IS aIS; 22156ecaa68aSToby Isaac const PetscInt *anchors; 22166ecaa68aSToby Isaac Mat cMat; 22174acb8e1eSToby Isaac PetscInt numFields, maxFields; 22186ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 22196ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 22201c58ffc4SToby Isaac PetscInt *maxChildIds; 2221e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 22224acb8e1eSToby Isaac const PetscInt ***perms; 22234acb8e1eSToby Isaac const PetscScalar ***flips; 22246ecaa68aSToby Isaac PetscErrorCode ierr; 22256ecaa68aSToby Isaac 22266ecaa68aSToby Isaac PetscFunctionBegin; 22276ecaa68aSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 22286ecaa68aSToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 22296ecaa68aSToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 22306ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 223189698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 223289698031SToby Isaac const PetscInt *leaves; 22336ecaa68aSToby Isaac 223489698031SToby Isaac ierr = PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 223589698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 223689698031SToby Isaac p = leaves ? leaves[l] : l; 22376ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 22386ecaa68aSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 22396ecaa68aSToby Isaac if ((dof - cdof) > 0) { 22406ecaa68aSToby Isaac numPointsWithDofs++; 22416ecaa68aSToby Isaac } 22426ecaa68aSToby Isaac } 22436ecaa68aSToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 22447cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 224589698031SToby Isaac p = leaves ? leaves[l] : l; 22466ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 22476ecaa68aSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 22486ecaa68aSToby Isaac if ((dof - cdof) > 0) { 224989698031SToby Isaac pointsWithDofs[offset++] = l; 22506ecaa68aSToby Isaac } 22516ecaa68aSToby Isaac } 22526ecaa68aSToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 2253ec92bd66SToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 22546ecaa68aSToby Isaac } 22556ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 22566ecaa68aSToby Isaac ierr = PetscMalloc1(pEndC-pStartC,&maxChildIds);CHKERRQ(ierr); 22576ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22588d2f55e7SToby Isaac maxChildIds[p - pStartC] = -2; 22596ecaa68aSToby Isaac } 22606ecaa68aSToby Isaac ierr = PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 22616ecaa68aSToby Isaac ierr = PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 226246bdb399SToby Isaac 22636ecaa68aSToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 22646ecaa68aSToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 226546bdb399SToby Isaac 22666ecaa68aSToby Isaac ierr = DMPlexGetAnchors(coarse,&aSec,&aIS);CHKERRQ(ierr); 22676ecaa68aSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 22686ecaa68aSToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 226946bdb399SToby Isaac 22706ecaa68aSToby Isaac ierr = DMGetDefaultConstraints(coarse,&cSec,&cMat);CHKERRQ(ierr); 22716ecaa68aSToby Isaac ierr = PetscSectionGetChart(cSec,&cStart,&cEnd);CHKERRQ(ierr); 227246bdb399SToby Isaac 227346bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 22746ecaa68aSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec);CHKERRQ(ierr); 22756ecaa68aSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootMatricesSec);CHKERRQ(ierr); 22766ecaa68aSToby Isaac ierr = PetscSectionSetChart(rootIndicesSec,pStartC,pEndC);CHKERRQ(ierr); 22776ecaa68aSToby Isaac ierr = PetscSectionSetChart(rootMatricesSec,pStartC,pEndC);CHKERRQ(ierr); 2278708c7f19SToby Isaac ierr = PetscSectionGetNumFields(localCoarse,&numFields);CHKERRQ(ierr); 22794acb8e1eSToby Isaac maxFields = PetscMax(1,numFields) + 1; 2280e44e4e7fSToby Isaac ierr = PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO);CHKERRQ(ierr); 2281*1a834cf9SToby Isaac ierr = PetscMalloc2(maxFields,&perms,maxFields,&flips);CHKERRQ(ierr); 2282*1a834cf9SToby Isaac ierr = PetscMemzero((void *) perms, maxFields * sizeof(const PetscInt **));CHKERRQ(ierr); 2283*1a834cf9SToby Isaac ierr = PetscMemzero((void *) flips, maxFields * sizeof(const PetscScalar **));CHKERRQ(ierr); 228446bdb399SToby Isaac 228546bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 22868d2f55e7SToby Isaac PetscInt dof, matSize = 0; 22876ecaa68aSToby Isaac PetscInt aDof = 0; 22886ecaa68aSToby Isaac PetscInt cDof = 0; 22896ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22906ecaa68aSToby Isaac PetscInt numRowIndices = 0; 22916ecaa68aSToby Isaac PetscInt numColIndices = 0; 2292f13f9184SToby Isaac PetscInt f; 22936ecaa68aSToby Isaac 22946ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 22951cfc5b76SToby Isaac if (dof < 0) { 22961cfc5b76SToby Isaac dof = -(dof + 1); 22971cfc5b76SToby Isaac } 22986ecaa68aSToby Isaac if (p >= aStart && p < aEnd) { 22996ecaa68aSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 23006ecaa68aSToby Isaac } 23016ecaa68aSToby Isaac if (p >= cStart && p < cEnd) { 23026ecaa68aSToby Isaac ierr = PetscSectionGetDof(cSec,p,&cDof);CHKERRQ(ierr); 23036ecaa68aSToby Isaac } 2304f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2305f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 23066ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2307f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 23086ecaa68aSToby Isaac 23096ecaa68aSToby Isaac ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 231046bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 23116ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 23126ecaa68aSToby Isaac 23136ecaa68aSToby Isaac ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr); 23146ecaa68aSToby Isaac numRowIndices += clDof; 23156ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23166ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&clDof);CHKERRQ(ierr); 23176ecaa68aSToby Isaac offsets[f + 1] += clDof; 23186ecaa68aSToby Isaac } 23196ecaa68aSToby Isaac } 23206ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23216ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23226ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 23236ecaa68aSToby Isaac } 232446bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 23254acb8e1eSToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,NULL,NULL,NULL,&numColIndices,NULL,NULL,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 23266ecaa68aSToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 23276ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 23286ecaa68aSToby Isaac numColIndices = numRowIndices; 23296ecaa68aSToby Isaac matSize = 0; 23306ecaa68aSToby Isaac } 233146bdb399SToby Isaac else if (numFields) { /* we send one submat for each field: sum their sizes */ 23326ecaa68aSToby Isaac matSize = 0; 23336ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23346ecaa68aSToby Isaac PetscInt numRow, numCol; 23356ecaa68aSToby Isaac 23366ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2337f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 23386ecaa68aSToby Isaac matSize += numRow * numCol; 23396ecaa68aSToby Isaac } 23406ecaa68aSToby Isaac } 23416ecaa68aSToby Isaac else { 23426ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 23436ecaa68aSToby Isaac } 2344f13f9184SToby Isaac } else if (maxChildId == -1) { 23458d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2346f13f9184SToby Isaac PetscInt aOff, a; 23476ecaa68aSToby Isaac 23486ecaa68aSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 23496ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23506ecaa68aSToby Isaac PetscInt fDof; 23516ecaa68aSToby Isaac 23526ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 235321968bf8SToby Isaac offsets[f+1] = fDof; 23546ecaa68aSToby Isaac } 23556ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23566ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 23576ecaa68aSToby Isaac 23586ecaa68aSToby Isaac ierr = PetscSectionGetDof(localCoarse,anchor,&aLocalDof);CHKERRQ(ierr); 23596ecaa68aSToby Isaac numColIndices += aLocalDof; 23606ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23616ecaa68aSToby Isaac PetscInt fDof; 23626ecaa68aSToby Isaac 23636ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 236421968bf8SToby Isaac newOffsets[f+1] += fDof; 23656ecaa68aSToby Isaac } 23666ecaa68aSToby Isaac } 23676ecaa68aSToby Isaac if (numFields) { 23686ecaa68aSToby Isaac matSize = 0; 23696ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 237021968bf8SToby Isaac matSize += offsets[f+1] * newOffsets[f+1]; 23716ecaa68aSToby Isaac } 23726ecaa68aSToby Isaac } 23736ecaa68aSToby Isaac else { 23746ecaa68aSToby Isaac matSize = numColIndices * dof; 23756ecaa68aSToby Isaac } 23766ecaa68aSToby Isaac } 23776ecaa68aSToby Isaac else { /* no children, and no constraints on dofs: just get the global indices */ 23786ecaa68aSToby Isaac numColIndices = dof; 23796ecaa68aSToby Isaac matSize = 0; 23806ecaa68aSToby Isaac } 23818d2f55e7SToby Isaac } 238246bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 23836ecaa68aSToby Isaac ierr = PetscSectionSetDof(rootIndicesSec,p,numColIndices ? numColIndices+2*numFields : 0);CHKERRQ(ierr); 23846ecaa68aSToby Isaac ierr = PetscSectionSetDof(rootMatricesSec,p,matSize);CHKERRQ(ierr); 23856ecaa68aSToby Isaac } 23866ecaa68aSToby Isaac ierr = PetscSectionSetUp(rootIndicesSec);CHKERRQ(ierr); 23876ecaa68aSToby Isaac ierr = PetscSectionSetUp(rootMatricesSec);CHKERRQ(ierr); 23886ecaa68aSToby Isaac { 23896ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 23906ecaa68aSToby Isaac 23916ecaa68aSToby Isaac ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr); 23926ecaa68aSToby Isaac ierr = PetscSectionGetStorageSize(rootMatricesSec,&numRootMatrices);CHKERRQ(ierr); 23936ecaa68aSToby Isaac ierr = PetscMalloc2(numRootIndices,&rootIndices,numRootMatrices,&rootMatrices);CHKERRQ(ierr); 23946ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 23956ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2396f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 23976ecaa68aSToby Isaac PetscInt *pInd; 23986ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 23996ecaa68aSToby Isaac PetscScalar *pMat = NULL; 24006ecaa68aSToby Isaac 24016ecaa68aSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,p,&numColIndices);CHKERRQ(ierr); 24026ecaa68aSToby Isaac if (!numColIndices) { 24036ecaa68aSToby Isaac continue; 24046ecaa68aSToby Isaac } 2405f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2406f13f9184SToby Isaac offsets[f] = 0; 2407f13f9184SToby Isaac newOffsets[f] = 0; 2408f13f9184SToby Isaac offsetsCopy[f] = 0; 2409f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2410f13f9184SToby Isaac } 24116ecaa68aSToby Isaac numColIndices -= 2 * numFields; 24126ecaa68aSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,p,&pIndOff);CHKERRQ(ierr); 24136ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 24146ecaa68aSToby Isaac ierr = PetscSectionGetDof(rootMatricesSec,p,&matSize);CHKERRQ(ierr); 24156ecaa68aSToby Isaac if (matSize) { 24166ecaa68aSToby Isaac ierr = PetscSectionGetOffset(rootMatricesSec,p,&pMatOff);CHKERRQ(ierr); 24176ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 24186ecaa68aSToby Isaac } 24196ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 24201cfc5b76SToby Isaac if (dof < 0) { 24211cfc5b76SToby Isaac dof = -(dof + 1); 24221cfc5b76SToby Isaac } 24236ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 24246ecaa68aSToby Isaac PetscInt i, j; 24256ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 24266ecaa68aSToby Isaac 24276ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 24286ecaa68aSToby Isaac PetscInt numIndices, *indices; 24296ecaa68aSToby Isaac ierr = DMPlexGetClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr); 24306ecaa68aSToby Isaac if (numIndices != numColIndices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"mismatching constraint indices calculations"); 24316ecaa68aSToby Isaac for (i = 0; i < numColIndices; i++) { 24326ecaa68aSToby Isaac pInd[i] = indices[i]; 24336ecaa68aSToby Isaac } 24346ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 243546bdb399SToby Isaac pInd[numColIndices + i] = offsets[i+1]; 243646bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i+1]; 24376ecaa68aSToby Isaac } 243846bdb399SToby Isaac ierr = DMPlexRestoreClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr); 24396ecaa68aSToby Isaac } 24406ecaa68aSToby Isaac else { 24416ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 24426ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 24436ecaa68aSToby Isaac PetscInt numPoints,*points; 24446ecaa68aSToby Isaac 24456ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numRowIndices * numRowIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr); 24466ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 24476ecaa68aSToby Isaac for (j = 0; j < numRowIndices; j++) { 24486ecaa68aSToby Isaac pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 24496ecaa68aSToby Isaac } 24506ecaa68aSToby Isaac } 24516ecaa68aSToby Isaac ierr = DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 24524acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24534acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionGetFieldPointSyms(localCoarse,f,closureSize,closure,&perms[f],&flips[f]);CHKERRQ(ierr);} 24544acb8e1eSToby Isaac else {ierr = PetscSectionGetPointSyms(localCoarse,closureSize,closure,&perms[f],&flips[f]);CHKERRQ(ierr);} 24554acb8e1eSToby Isaac } 24566ecaa68aSToby Isaac if (numFields) { 24576ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 24586ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 24596ecaa68aSToby Isaac 24606ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24616ecaa68aSToby Isaac PetscInt fDof; 24626ecaa68aSToby Isaac 24636ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&fDof);CHKERRQ(ierr); 24646ecaa68aSToby Isaac offsets[f + 1] += fDof; 24656ecaa68aSToby Isaac } 24666ecaa68aSToby Isaac } 24676ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24686ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 24696ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 24706ecaa68aSToby Isaac } 24716ecaa68aSToby Isaac } 24724acb8e1eSToby Isaac /* TODO : flips here ? */ 24736ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 24744acb8e1eSToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,perms,pMatIn,&numPoints,NULL,&points,&pMatModified,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 24754acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24764acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(localCoarse,f,closureSize,closure,&perms[f],&flips[f]);CHKERRQ(ierr);} 24774acb8e1eSToby Isaac else {ierr = PetscSectionRestorePointSyms(localCoarse,closureSize,closure,&perms[f],&flips[f]);CHKERRQ(ierr);} 24784acb8e1eSToby Isaac } 24794acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24804acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionGetFieldPointSyms(localCoarse,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 24814acb8e1eSToby Isaac else {ierr = PetscSectionGetPointSyms(localCoarse,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 24824acb8e1eSToby Isaac } 24836ecaa68aSToby Isaac if (!numFields) { 24846ecaa68aSToby Isaac for (i = 0; i < numRowIndices * numColIndices; i++) { 24856ecaa68aSToby Isaac pMat[i] = pMatModified[i]; 24866ecaa68aSToby Isaac } 24876ecaa68aSToby Isaac } 24886ecaa68aSToby Isaac else { 2489f13f9184SToby Isaac PetscInt i, j, count; 24906ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24916ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f+1]; i++) { 24926ecaa68aSToby Isaac for (j = newOffsets[f]; j < newOffsets[f+1]; j++, count++) { 24936ecaa68aSToby Isaac pMat[count] = pMatModified[i * numColIndices + j]; 24946ecaa68aSToby Isaac } 24956ecaa68aSToby Isaac } 24966ecaa68aSToby Isaac } 24976ecaa68aSToby Isaac } 24986ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatModified);CHKERRQ(ierr); 24996ecaa68aSToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 25006ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr); 25016ecaa68aSToby Isaac if (numFields) { 250246bdb399SToby Isaac for (f = 0; f < numFields; f++) { 250346bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 250446bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 25056ecaa68aSToby Isaac } 25064acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 25074acb8e1eSToby Isaac PetscInt globalOff, c = points[2*cl]; 25086ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 25094acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, pInd); 25106ecaa68aSToby Isaac } 25116ecaa68aSToby Isaac } else { 25124acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 25134acb8e1eSToby Isaac PetscInt c = points[2*cl], globalOff; 25144acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 25154acb8e1eSToby Isaac 25166ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 25174acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, perm, pInd); 25186ecaa68aSToby Isaac } 25196ecaa68aSToby Isaac } 25204acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 25214acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(localCoarse,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 25224acb8e1eSToby Isaac else {ierr = PetscSectionRestorePointSyms(localCoarse,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 25234acb8e1eSToby Isaac } 252428552ed4SToby Isaac ierr = DMRestoreWorkArray(coarse,numPoints,PETSC_SCALAR,&points);CHKERRQ(ierr); 25256ecaa68aSToby Isaac } 25266ecaa68aSToby Isaac } 25276ecaa68aSToby Isaac else if (matSize) { 25286ecaa68aSToby Isaac PetscInt cOff; 25296ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 25306ecaa68aSToby Isaac 25316ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 2532628cbfb8SToby Isaac if (numRowIndices != dof) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Miscounted dofs"); 25336ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr); 25346ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr); 25356ecaa68aSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&cOff);CHKERRQ(ierr); 25366ecaa68aSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 25376ecaa68aSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 25386ecaa68aSToby Isaac if (numFields) { 25396ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25406ecaa68aSToby Isaac PetscInt fDof; 2541f13f9184SToby Isaac 25426ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&fDof);CHKERRQ(ierr); 25436ecaa68aSToby Isaac offsets[f + 1] = fDof; 25446ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25456ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25466ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 25476ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 25486ecaa68aSToby Isaac } 25496ecaa68aSToby Isaac } 25506ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25516ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 25526ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 25536ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 25546ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 25556ecaa68aSToby Isaac } 25564acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(cSec,p,cOff,offsetsCopy,PETSC_TRUE,NULL,-1,rowIndices);CHKERRQ(ierr); 25576ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25586ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25596ecaa68aSToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 25604acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(localCoarse,anchor,lOff,newOffsetsCopy,PETSC_TRUE,NULL,-1,colIndices);CHKERRQ(ierr); 25616ecaa68aSToby Isaac } 25626ecaa68aSToby Isaac } 25636ecaa68aSToby Isaac else { 25644acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(cSec,p,cOff,offsetsCopy,PETSC_TRUE,NULL,rowIndices);CHKERRQ(ierr); 25656ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25666ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25676ecaa68aSToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 25684acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(localCoarse,anchor,lOff,newOffsetsCopy,PETSC_TRUE,NULL,colIndices);CHKERRQ(ierr); 25696ecaa68aSToby Isaac } 25706ecaa68aSToby Isaac } 25716ecaa68aSToby Isaac if (numFields) { 2572f13f9184SToby Isaac PetscInt count, a; 2573f13f9184SToby Isaac 25746ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 25756ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 25766ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 25776ecaa68aSToby Isaac ierr = MatGetValues(cMat,iSize,&rowIndices[offsets[f]],jSize,&colIndices[newOffsets[f]],&pMat[count]);CHKERRQ(ierr); 25786ecaa68aSToby Isaac count += iSize * jSize; 257946bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 258046bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 25816ecaa68aSToby Isaac } 25826ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25836ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25846ecaa68aSToby Isaac PetscInt gOff; 25856ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 25864acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,NULL,-1,pInd);CHKERRQ(ierr); 25876ecaa68aSToby Isaac } 25886ecaa68aSToby Isaac } 25896ecaa68aSToby Isaac else { 25906ecaa68aSToby Isaac PetscInt a; 25916ecaa68aSToby Isaac ierr = MatGetValues(cMat,numRowIndices,rowIndices,numColIndices,colIndices,pMat);CHKERRQ(ierr); 25926ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25936ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25946ecaa68aSToby Isaac PetscInt gOff; 25956ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 25964acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,NULL,pInd);CHKERRQ(ierr); 25976ecaa68aSToby Isaac } 25986ecaa68aSToby Isaac } 25996ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr); 26006ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr); 26016ecaa68aSToby Isaac } 26026ecaa68aSToby Isaac else { 26036ecaa68aSToby Isaac PetscInt gOff; 26046ecaa68aSToby Isaac 26056ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 26066ecaa68aSToby Isaac if (numFields) { 26076ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 26086ecaa68aSToby Isaac PetscInt fDof; 26096ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 26106ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 26116ecaa68aSToby Isaac } 26126ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 261346bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 261446bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f+1]; 26156ecaa68aSToby Isaac } 26164acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,-1,pInd);CHKERRQ(ierr); 26176ecaa68aSToby Isaac } 26186ecaa68aSToby Isaac else { 26194acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,pInd);CHKERRQ(ierr); 26206ecaa68aSToby Isaac } 26216ecaa68aSToby Isaac } 26226ecaa68aSToby Isaac } 2623e44e4e7fSToby Isaac ierr = PetscFree(maxChildIds);CHKERRQ(ierr); 26246ecaa68aSToby Isaac } 262546bdb399SToby Isaac { 262646bdb399SToby Isaac PetscSF indicesSF, matricesSF; 262746bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 262846bdb399SToby Isaac 262946bdb399SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr); 263046bdb399SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafMatricesSec);CHKERRQ(ierr); 263146bdb399SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootIndicesSec,&remoteOffsetsIndices,leafIndicesSec);CHKERRQ(ierr); 263246bdb399SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootMatricesSec,&remoteOffsetsMatrices,leafMatricesSec);CHKERRQ(ierr); 263346bdb399SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootIndicesSec,remoteOffsetsIndices,leafIndicesSec,&indicesSF);CHKERRQ(ierr); 263446bdb399SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootMatricesSec,remoteOffsetsMatrices,leafMatricesSec,&matricesSF);CHKERRQ(ierr); 2635e44e4e7fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 263646bdb399SToby Isaac ierr = PetscFree(remoteOffsetsIndices);CHKERRQ(ierr); 263746bdb399SToby Isaac ierr = PetscFree(remoteOffsetsMatrices);CHKERRQ(ierr); 263846bdb399SToby Isaac ierr = PetscSectionGetStorageSize(leafIndicesSec,&numLeafIndices);CHKERRQ(ierr); 263946bdb399SToby Isaac ierr = PetscSectionGetStorageSize(leafMatricesSec,&numLeafMatrices);CHKERRQ(ierr); 264046bdb399SToby Isaac ierr = PetscMalloc2(numLeafIndices,&leafIndices,numLeafMatrices,&leafMatrices);CHKERRQ(ierr); 264146bdb399SToby Isaac ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr); 2642267d4f3fSToby Isaac ierr = PetscSFBcastBegin(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices);CHKERRQ(ierr); 264346bdb399SToby Isaac ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr); 2644267d4f3fSToby Isaac ierr = PetscSFBcastEnd(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices);CHKERRQ(ierr); 264546bdb399SToby Isaac ierr = PetscSFDestroy(&matricesSF);CHKERRQ(ierr); 264646bdb399SToby Isaac ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr); 264746bdb399SToby Isaac ierr = PetscFree2(rootIndices,rootMatrices);CHKERRQ(ierr); 264846bdb399SToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 264946bdb399SToby Isaac ierr = PetscSectionDestroy(&rootMatricesSec);CHKERRQ(ierr); 265046bdb399SToby Isaac } 265146bdb399SToby Isaac /* count to preallocate */ 265246bdb399SToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 265346bdb399SToby Isaac { 265446bdb399SToby Isaac PetscInt nGlobal; 265546bdb399SToby Isaac PetscInt *dnnz, *onnz; 2656b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2657b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 26581c58ffc4SToby Isaac PetscInt maxDof; 26591c58ffc4SToby Isaac PetscInt *rowIndices; 26601c58ffc4SToby Isaac DM refTree; 26611c58ffc4SToby Isaac PetscInt **refPointFieldN; 26621c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 26631c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 26640eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,maxConDof,maxColumns,leafStart,leafEnd; 26651c58ffc4SToby Isaac PetscScalar *pointWork; 266646bdb399SToby Isaac 266746bdb399SToby Isaac ierr = PetscSectionGetConstrainedStorageSize(globalFine,&nGlobal);CHKERRQ(ierr); 266846bdb399SToby Isaac ierr = PetscCalloc2(nGlobal,&dnnz,nGlobal,&onnz);CHKERRQ(ierr); 2669b9a5774bSToby Isaac ierr = MatGetLayouts(mat,&rowMap,&colMap);CHKERRQ(ierr); 2670b9a5774bSToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 26711c58ffc4SToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 2672b9a5774bSToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 267346bdb399SToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 26741c58ffc4SToby Isaac ierr = PetscSectionGetMaxDof(globalFine,&maxDof);CHKERRQ(ierr); 26750eb7e1eaSToby Isaac ierr = PetscSectionGetChart(leafIndicesSec,&leafStart,&leafEnd);CHKERRQ(ierr); 26761c58ffc4SToby Isaac ierr = DMGetWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 26770eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 267846bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 267946bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 268046bdb399SToby Isaac PetscInt matSize; 268121968bf8SToby Isaac PetscInt i; 268246bdb399SToby Isaac 268346bdb399SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 268446bdb399SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 268546bdb399SToby Isaac if ((gDof - gcDof) <= 0) { 268646bdb399SToby Isaac continue; 268746bdb399SToby Isaac } 268846bdb399SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 268946bdb399SToby Isaac if (gOff < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"I though having global dofs meant a non-negative offset"); 2690b9a5774bSToby Isaac if ((gOff < rowStart) || ((gOff + gDof - gcDof) > rowEnd)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"I thought the row map would constrain the global dofs"); 269146bdb399SToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 269246bdb399SToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 269346bdb399SToby Isaac numColIndices -= 2 * numFields; 26941c58ffc4SToby Isaac if (numColIndices <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"global fine dof with no dofs to interpolate from"); 269546bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 269621968bf8SToby Isaac offsets[0] = 0; 269721968bf8SToby Isaac offsetsCopy[0] = 0; 269821968bf8SToby Isaac newOffsets[0] = 0; 269921968bf8SToby Isaac newOffsetsCopy[0] = 0; 270046bdb399SToby Isaac if (numFields) { 270121968bf8SToby Isaac PetscInt f; 270246bdb399SToby Isaac for (f = 0; f < numFields; f++) { 270346bdb399SToby Isaac PetscInt rowDof; 270446bdb399SToby Isaac 270546bdb399SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 270621968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 270721968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 270821968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 270921968bf8SToby Isaac numD[f] = 0; 271021968bf8SToby Isaac numO[f] = 0; 271146bdb399SToby Isaac } 27124acb8e1eSToby Isaac ierr = DMPlexGetIndicesPointFields_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1,rowIndices);CHKERRQ(ierr); 271346bdb399SToby Isaac for (f = 0; f < numFields; f++) { 271421968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 271521968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 271646bdb399SToby Isaac 271746bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 271846bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 271946bdb399SToby Isaac 272046bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 272121968bf8SToby Isaac numD[f]++; 272246bdb399SToby Isaac } 272346bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 272421968bf8SToby Isaac numO[f]++; 272546bdb399SToby Isaac } 272646bdb399SToby Isaac } 272746bdb399SToby Isaac } 272846bdb399SToby Isaac } 272946bdb399SToby Isaac else { 27304acb8e1eSToby Isaac ierr = DMPlexGetIndicesPoint_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,NULL,rowIndices);CHKERRQ(ierr); 273121968bf8SToby Isaac numD[0] = 0; 273221968bf8SToby Isaac numO[0] = 0; 273346bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 273446bdb399SToby Isaac PetscInt gInd = pInd[i]; 273546bdb399SToby Isaac 273646bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 273721968bf8SToby Isaac numD[0]++; 273846bdb399SToby Isaac } 273946bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 274021968bf8SToby Isaac numO[0]++; 274146bdb399SToby Isaac } 274246bdb399SToby Isaac } 274346bdb399SToby Isaac } 274446bdb399SToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 274546bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 274646bdb399SToby Isaac PetscInt childId; 274746bdb399SToby Isaac 274846bdb399SToby Isaac childId = childIds[p-pStartF]; 274921968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 275046bdb399SToby Isaac if (numFields) { 2751b9a5774bSToby Isaac PetscInt f; 2752b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 275321968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 275446bdb399SToby Isaac for (row = 0; row < numRows; row++) { 275521968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 275621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 275746bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 2758b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2759b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 276046bdb399SToby Isaac } 276146bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 2762b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2763b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 276446bdb399SToby Isaac } 276546bdb399SToby Isaac else { /* constrained */ 276646bdb399SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 276746bdb399SToby Isaac } 276846bdb399SToby Isaac } 276946bdb399SToby Isaac } 277046bdb399SToby Isaac } 277146bdb399SToby Isaac else { 2772b9a5774bSToby Isaac PetscInt i; 2773b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 277446bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 277546bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 277646bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 2777b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2778b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 277946bdb399SToby Isaac } 278046bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 2781b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2782b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 278346bdb399SToby Isaac } 278446bdb399SToby Isaac else { /* constrained */ 278546bdb399SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 278646bdb399SToby Isaac } 278746bdb399SToby Isaac } 278846bdb399SToby Isaac } 278946bdb399SToby Isaac } 279046bdb399SToby Isaac else { /* interpolate from all */ 279146bdb399SToby Isaac if (numFields) { 2792b9a5774bSToby Isaac PetscInt f; 2793b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 279421968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 279546bdb399SToby Isaac for (row = 0; row < numRows; row++) { 279621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 279746bdb399SToby Isaac if (gIndFine >= 0) { 2798b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2799b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2800b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 280146bdb399SToby Isaac } 280246bdb399SToby Isaac } 280346bdb399SToby Isaac } 280446bdb399SToby Isaac } 280546bdb399SToby Isaac else { 2806b9a5774bSToby Isaac PetscInt i; 2807b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 280846bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 280946bdb399SToby Isaac if (gIndFine >= 0) { 2810b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2811b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2812b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 281346bdb399SToby Isaac } 281446bdb399SToby Isaac } 281546bdb399SToby Isaac } 281646bdb399SToby Isaac } 281746bdb399SToby Isaac } 281846bdb399SToby Isaac else { /* interpolate from all */ 281946bdb399SToby Isaac if (numFields) { 2820b9a5774bSToby Isaac PetscInt f; 2821b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 282221968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 282346bdb399SToby Isaac for (row = 0; row < numRows; row++) { 282421968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 282546bdb399SToby Isaac if (gIndFine >= 0) { 2826b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2827b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2828b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 282946bdb399SToby Isaac } 283046bdb399SToby Isaac } 283146bdb399SToby Isaac } 283246bdb399SToby Isaac } 283346bdb399SToby Isaac else { /* every dof get a full row */ 2834b9a5774bSToby Isaac PetscInt i; 2835b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 283646bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 283746bdb399SToby Isaac if (gIndFine >= 0) { 2838b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2839b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2840b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 284146bdb399SToby Isaac } 284246bdb399SToby Isaac } 284346bdb399SToby Isaac } 284446bdb399SToby Isaac } 284546bdb399SToby Isaac } 284646bdb399SToby Isaac ierr = MatXAIJSetPreallocation(mat,1,dnnz,onnz,NULL,NULL);CHKERRQ(ierr); 284746bdb399SToby Isaac ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 284821968bf8SToby Isaac 284921968bf8SToby Isaac ierr = DMPlexGetReferenceTree(fine,&refTree);CHKERRQ(ierr); 285021968bf8SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 2851e44e4e7fSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 2852e44e4e7fSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,NULL);CHKERRQ(ierr); 2853e44e4e7fSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 28541c58ffc4SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxConDof);CHKERRQ(ierr); 28557c0540e0SToby Isaac ierr = PetscSectionGetMaxDof(leafIndicesSec,&maxColumns);CHKERRQ(ierr); 28567c0540e0SToby Isaac ierr = PetscMalloc1(maxConDof*maxColumns,&pointWork);CHKERRQ(ierr); 28570eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2858e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2859e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2860e44e4e7fSToby Isaac PetscInt matSize; 2861e44e4e7fSToby Isaac PetscInt childId; 2862e44e4e7fSToby Isaac 2863e44e4e7fSToby Isaac 2864e44e4e7fSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 2865e44e4e7fSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 2866e44e4e7fSToby Isaac if ((gDof - gcDof) <= 0) { 2867e44e4e7fSToby Isaac continue; 2868e44e4e7fSToby Isaac } 2869e44e4e7fSToby Isaac childId = childIds[p-pStartF]; 2870e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 2871e44e4e7fSToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 2872e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 2873e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2874e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2875e44e4e7fSToby Isaac offsets[0] = 0; 2876e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2877e44e4e7fSToby Isaac newOffsets[0] = 0; 2878e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2879e44e4e7fSToby Isaac rowOffsets[0] = 0; 2880e44e4e7fSToby Isaac if (numFields) { 2881e44e4e7fSToby Isaac PetscInt f; 2882e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2883e44e4e7fSToby Isaac PetscInt rowDof; 2884e44e4e7fSToby Isaac 2885e44e4e7fSToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 2886e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2887e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2888e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2889e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2890e44e4e7fSToby Isaac } 28914acb8e1eSToby Isaac ierr = DMPlexGetIndicesPointFields_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1,rowIndices);CHKERRQ(ierr); 2892e44e4e7fSToby Isaac } 28931c58ffc4SToby Isaac else { 28944acb8e1eSToby Isaac ierr = DMPlexGetIndicesPoint_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,NULL,rowIndices);CHKERRQ(ierr); 28951c58ffc4SToby Isaac } 2896e44e4e7fSToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 2897e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2898e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2899e44e4e7fSToby Isaac if (numFields) { 2900e44e4e7fSToby Isaac PetscInt f; 2901e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2902e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 2903e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 2904e44e4e7fSToby Isaac ierr = MatSetValue(mat,rowIndices[offsets[f]+row],pInd[newOffsets[f]+row],1.,INSERT_VALUES);CHKERRQ(ierr); 290521968bf8SToby Isaac } 290621968bf8SToby Isaac } 2907e44e4e7fSToby Isaac } 2908e44e4e7fSToby Isaac else { 2909e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 2910e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 2911e44e4e7fSToby Isaac ierr = MatSetValue(mat,rowIndices[row],pInd[row],1.,INSERT_VALUES);CHKERRQ(ierr); 2912e44e4e7fSToby Isaac } 2913e44e4e7fSToby Isaac } 2914e44e4e7fSToby Isaac } 2915e44e4e7fSToby Isaac else { /* interpolate from all */ 2916e44e4e7fSToby Isaac if (numFields) { 2917e44e4e7fSToby Isaac PetscInt f; 2918e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2919e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 2920e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2921e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],refPointFieldMats[childId - pRefStart][f],INSERT_VALUES);CHKERRQ(ierr); 2922e44e4e7fSToby Isaac } 2923e44e4e7fSToby Isaac } 2924e44e4e7fSToby Isaac else { 2925e44e4e7fSToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,refPointFieldMats[childId - pRefStart][0],INSERT_VALUES);CHKERRQ(ierr); 2926e44e4e7fSToby Isaac } 2927e44e4e7fSToby Isaac } 2928e44e4e7fSToby Isaac } 2929e44e4e7fSToby Isaac else { /* interpolate from all */ 2930e44e4e7fSToby Isaac PetscInt pMatOff; 2931e44e4e7fSToby Isaac PetscScalar *pMat; 2932e44e4e7fSToby Isaac 2933e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(leafMatricesSec,p,&pMatOff);CHKERRQ(ierr); 2934e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2935e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2936e44e4e7fSToby Isaac if (numFields) { 2937e44e4e7fSToby Isaac PetscInt f, count; 2938e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2939e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2940e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2941e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2942e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2943e44e4e7fSToby Isaac 2944e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],inMat,INSERT_VALUES);CHKERRQ(ierr); 2945e44e4e7fSToby Isaac count += numCols * numInRows; 2946e44e4e7fSToby Isaac } 2947e44e4e7fSToby Isaac } 2948e44e4e7fSToby Isaac else { 2949e44e4e7fSToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,pMat,INSERT_VALUES);CHKERRQ(ierr); 2950e44e4e7fSToby Isaac } 2951e44e4e7fSToby Isaac } 2952e44e4e7fSToby Isaac else { /* multiply the incoming matrix by the child interpolation */ 2953e44e4e7fSToby Isaac if (numFields) { 2954e44e4e7fSToby Isaac PetscInt f, count; 2955e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2956e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2957e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2958e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2959e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2960e44e4e7fSToby Isaac PetscInt i, j, k; 2961e44e4e7fSToby Isaac if (refPointFieldN[childId - pRefStart][f] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2962e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2963e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2964e44e4e7fSToby Isaac PetscScalar val = 0.; 2965e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2966e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2967e44e4e7fSToby Isaac } 2968e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2969e44e4e7fSToby Isaac } 2970e44e4e7fSToby Isaac } 2971e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],pointWork,INSERT_VALUES);CHKERRQ(ierr); 2972e44e4e7fSToby Isaac count += numCols * numInRows; 2973e44e4e7fSToby Isaac } 2974e44e4e7fSToby Isaac } 2975267d4f3fSToby Isaac else { /* every dof gets a full row */ 2976e44e4e7fSToby Isaac PetscInt numRows = gDof; 2977e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2978e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2979e44e4e7fSToby Isaac PetscInt i, j, k; 2980e44e4e7fSToby Isaac if (refPointFieldN[childId - pRefStart][0] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2981e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2982e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2983e44e4e7fSToby Isaac PetscScalar val = 0.; 2984e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2985e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2986e44e4e7fSToby Isaac } 2987e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2988e44e4e7fSToby Isaac } 2989e44e4e7fSToby Isaac } 2990e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,rowIndices,numCols,pInd,pointWork,INSERT_VALUES);CHKERRQ(ierr); 2991e44e4e7fSToby Isaac } 2992e44e4e7fSToby Isaac } 2993e44e4e7fSToby Isaac } 2994e44e4e7fSToby Isaac } 29951c58ffc4SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 29961c58ffc4SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 2997e44e4e7fSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 2998e44e4e7fSToby Isaac } 2999e44e4e7fSToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3000e44e4e7fSToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3001e44e4e7fSToby Isaac ierr = PetscSectionDestroy(&leafIndicesSec);CHKERRQ(ierr); 3002e44e4e7fSToby Isaac ierr = PetscSectionDestroy(&leafMatricesSec);CHKERRQ(ierr); 3003e44e4e7fSToby Isaac ierr = PetscFree2(leafIndices,leafMatrices);CHKERRQ(ierr); 30044acb8e1eSToby Isaac ierr = PetscFree2(perms,flips);CHKERRQ(ierr); 3005e44e4e7fSToby Isaac ierr = PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO);CHKERRQ(ierr); 30066ecaa68aSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 30076ecaa68aSToby Isaac PetscFunctionReturn(0); 30086ecaa68aSToby Isaac } 3009154bca37SToby Isaac 3010154bca37SToby Isaac #undef __FUNCT__ 30118d2f55e7SToby Isaac #define __FUNCT__ "DMPlexComputeInjectorReferenceTree" 30128d2f55e7SToby Isaac /* 30138d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 30148d2f55e7SToby Isaac * 30158d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 30168d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 30178d2f55e7SToby Isaac * for each fine dof \phi^f_j; 30188d2f55e7SToby Isaac * a_{i,j} = 0; 30198d2f55e7SToby Isaac * for each fine dof \phi^f_k: 30208d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 30218d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 30228d2f55e7SToby Isaac */ 30238d2f55e7SToby Isaac PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 30248d2f55e7SToby Isaac { 30258d2f55e7SToby Isaac PetscDS ds; 30268d2f55e7SToby Isaac PetscSection section, cSection; 30278d2f55e7SToby Isaac DMLabel canonical, depth; 30288d2f55e7SToby Isaac Mat cMat, mat; 30298d2f55e7SToby Isaac PetscInt *nnz; 30308d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 30318d2f55e7SToby Isaac PetscInt m, n; 30328d2f55e7SToby Isaac PetscScalar *pointScalar; 30338d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 30348d2f55e7SToby Isaac PetscErrorCode ierr; 30358d2f55e7SToby Isaac 30368d2f55e7SToby Isaac PetscFunctionBegin; 30378d2f55e7SToby Isaac ierr = DMGetDefaultSection(refTree,§ion);CHKERRQ(ierr); 30388d2f55e7SToby Isaac ierr = DMGetDimension(refTree, &dim);CHKERRQ(ierr); 30398d2f55e7SToby Isaac ierr = PetscMalloc6(dim,&v0,dim,&v0parent,dim,&vtmp,dim*dim,&J,dim*dim,&Jparent,dim*dim,&invJ);CHKERRQ(ierr); 30408d2f55e7SToby Isaac ierr = PetscMalloc2(dim,&pointScalar,dim,&pointRef);CHKERRQ(ierr); 30418d2f55e7SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 30428d2f55e7SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 30438d2f55e7SToby Isaac ierr = PetscSectionGetNumFields(section,&numSecFields);CHKERRQ(ierr); 30448d2f55e7SToby Isaac ierr = DMGetLabel(refTree,"canonical",&canonical);CHKERRQ(ierr); 30458d2f55e7SToby Isaac ierr = DMGetLabel(refTree,"depth",&depth);CHKERRQ(ierr); 30468d2f55e7SToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSection,&cMat);CHKERRQ(ierr); 30478d2f55e7SToby Isaac ierr = DMPlexGetChart(refTree, &pStart, &pEnd);CHKERRQ(ierr); 30488d2f55e7SToby Isaac ierr = DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd);CHKERRQ(ierr); 30498d2f55e7SToby Isaac ierr = MatGetSize(cMat,&n,&m);CHKERRQ(ierr); /* the injector has transpose sizes from the constraint matrix */ 30508d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 30518d2f55e7SToby Isaac ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr); 30528d2f55e7SToby 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 */ 30538d2f55e7SToby Isaac const PetscInt *children; 30548d2f55e7SToby Isaac PetscInt numChildren; 30558d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30568d2f55e7SToby Isaac 30578d2f55e7SToby Isaac if (canonical) { 30588d2f55e7SToby Isaac PetscInt pCanonical; 30598d2f55e7SToby Isaac ierr = DMLabelGetValue(canonical,p,&pCanonical);CHKERRQ(ierr); 30608d2f55e7SToby Isaac if (p != pCanonical) continue; 30618d2f55e7SToby Isaac } 30628d2f55e7SToby Isaac ierr = DMPlexGetTreeChildren(refTree,p,&numChildren,&children);CHKERRQ(ierr); 30638d2f55e7SToby Isaac if (!numChildren) continue; 30648d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30658d2f55e7SToby Isaac PetscInt child = children[i]; 30668d2f55e7SToby Isaac PetscInt dof; 30678d2f55e7SToby Isaac 30688d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,child,&dof);CHKERRQ(ierr); 30698d2f55e7SToby Isaac numChildDof += dof; 30708d2f55e7SToby Isaac } 30718d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,p,&numSelfDof);CHKERRQ(ierr); 30728d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30738d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 30748d2f55e7SToby Isaac PetscInt selfOff; 30758d2f55e7SToby Isaac 30768d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 30778d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30788d2f55e7SToby Isaac PetscInt child = children[i]; 30798d2f55e7SToby Isaac PetscInt dof; 30808d2f55e7SToby Isaac 30818d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,child,f,&dof);CHKERRQ(ierr); 30828d2f55e7SToby Isaac numChildDof += dof; 30838d2f55e7SToby Isaac } 30848d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&numSelfDof);CHKERRQ(ierr); 30858d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(section,p,f,&selfOff);CHKERRQ(ierr); 30868d2f55e7SToby Isaac } 30878d2f55e7SToby Isaac else { 30888d2f55e7SToby Isaac ierr = PetscSectionGetOffset(section,p,&selfOff);CHKERRQ(ierr); 30898d2f55e7SToby Isaac } 30908d2f55e7SToby Isaac for (i = 0; i < numSelfDof; i++) { 30918d2f55e7SToby Isaac nnz[selfOff + i] = numChildDof; 30928d2f55e7SToby Isaac } 30938d2f55e7SToby Isaac } 30948d2f55e7SToby Isaac } 30958d2f55e7SToby Isaac ierr = MatCreateAIJ(PETSC_COMM_SELF,m,n,m,n,-1,nnz,-1,NULL,&mat);CHKERRQ(ierr); 30968d2f55e7SToby Isaac ierr = PetscFree(nnz);CHKERRQ(ierr); 30978d2f55e7SToby Isaac /* Setp 2: compute entries */ 30988d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 30998d2f55e7SToby Isaac const PetscInt *children; 31008d2f55e7SToby Isaac PetscInt numChildren; 31018d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 31028d2f55e7SToby Isaac 31038d2f55e7SToby Isaac /* same conditions about when entries occur */ 31048d2f55e7SToby Isaac if (canonical) { 31058d2f55e7SToby Isaac PetscInt pCanonical; 31068d2f55e7SToby Isaac ierr = DMLabelGetValue(canonical,p,&pCanonical);CHKERRQ(ierr); 31078d2f55e7SToby Isaac if (p != pCanonical) continue; 31088d2f55e7SToby Isaac } 31098d2f55e7SToby Isaac ierr = DMPlexGetTreeChildren(refTree,p,&numChildren,&children);CHKERRQ(ierr); 31108d2f55e7SToby Isaac if (!numChildren) continue; 31118d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 31128d2f55e7SToby Isaac PetscInt child = children[i]; 31138d2f55e7SToby Isaac PetscInt dof; 31148d2f55e7SToby Isaac 31158d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,child,&dof);CHKERRQ(ierr); 31168d2f55e7SToby Isaac numChildDof += dof; 31178d2f55e7SToby Isaac } 31188d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,p,&numSelfDof);CHKERRQ(ierr); 31198d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 31208d2f55e7SToby Isaac 31218d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 31228d2f55e7SToby Isaac PetscInt selfOff, fComp, numSelfShapes, numChildShapes, parentCell; 31238d2f55e7SToby Isaac PetscInt cellShapeOff; 31248d2f55e7SToby Isaac PetscObject disc; 31258d2f55e7SToby Isaac PetscDualSpace dsp; 31268d2f55e7SToby Isaac PetscClassId classId; 31278d2f55e7SToby Isaac PetscScalar *pointMat; 31283b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 31298d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 31308d2f55e7SToby Isaac const PetscInt *depthNumDof; 31318d2f55e7SToby Isaac 31328d2f55e7SToby Isaac if (numSecFields) { 31338d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 31348d2f55e7SToby Isaac PetscInt child = children[i]; 31358d2f55e7SToby Isaac PetscInt dof; 31368d2f55e7SToby Isaac 31378d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,child,f,&dof);CHKERRQ(ierr); 31388d2f55e7SToby Isaac numChildDof += dof; 31398d2f55e7SToby Isaac } 31408d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&numSelfDof);CHKERRQ(ierr); 31418d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(section,p,f,&selfOff);CHKERRQ(ierr); 31428d2f55e7SToby Isaac ierr = PetscSectionGetFieldComponents(section,f,&fComp);CHKERRQ(ierr); 31438d2f55e7SToby Isaac } 31448d2f55e7SToby Isaac else { 31458d2f55e7SToby Isaac ierr = PetscSectionGetOffset(section,p,&selfOff);CHKERRQ(ierr); 31468d2f55e7SToby Isaac fComp = 1; 31478d2f55e7SToby Isaac } 31488d2f55e7SToby Isaac numSelfShapes = numSelfDof / fComp; 31498d2f55e7SToby Isaac numChildShapes = numChildDof / fComp; 31508d2f55e7SToby Isaac 31513b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 31528d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 31538d2f55e7SToby Isaac parentCell = p; 31548d2f55e7SToby Isaac } 31558d2f55e7SToby Isaac else { 31568d2f55e7SToby Isaac PetscInt *star = NULL; 31578d2f55e7SToby Isaac PetscInt numStar; 31588d2f55e7SToby Isaac 31598d2f55e7SToby Isaac parentCell = -1; 31608d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 31618d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 31628d2f55e7SToby Isaac PetscInt c = star[2 * i]; 31638d2f55e7SToby Isaac 31648d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 31658d2f55e7SToby Isaac parentCell = c; 31668d2f55e7SToby Isaac break; 31678d2f55e7SToby Isaac } 31688d2f55e7SToby Isaac } 31698d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 31708d2f55e7SToby Isaac } 31718d2f55e7SToby Isaac /* determine the offset of p's shape functions withing parentCell's shape functions */ 3172c5356c36SToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 3173c5356c36SToby Isaac ierr = PetscObjectGetClassId(disc,&classId);CHKERRQ(ierr); 3174c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 3175c5356c36SToby Isaac ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 3176c5356c36SToby Isaac } 3177c5356c36SToby Isaac else if (classId == PETSCFV_CLASSID) { 3178c5356c36SToby Isaac ierr = PetscFVGetDualSpace((PetscFV)disc,&dsp);CHKERRQ(ierr); 3179c5356c36SToby Isaac } 3180c5356c36SToby Isaac else { 3181c5356c36SToby Isaac SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported discretization object");CHKERRQ(ierr); 3182c5356c36SToby Isaac } 31838d2f55e7SToby Isaac ierr = PetscDualSpaceGetNumDof(dsp,&depthNumDof);CHKERRQ(ierr); 31848d2f55e7SToby Isaac { 31858d2f55e7SToby Isaac PetscInt *closure = NULL; 31868d2f55e7SToby Isaac PetscInt numClosure; 31878d2f55e7SToby Isaac 31888d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 31898d2f55e7SToby Isaac for (i = 0, cellShapeOff = 0; i < numClosure; i++) { 31908d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 31918d2f55e7SToby Isaac 31928d2f55e7SToby Isaac pO = closure[2 * i + 1]; 31938d2f55e7SToby Isaac if (point == p) break; 31948d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,point,&pointDepth);CHKERRQ(ierr); 31958d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 31968d2f55e7SToby Isaac } 31978d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 31988d2f55e7SToby Isaac } 31998d2f55e7SToby Isaac 32008d2f55e7SToby Isaac ierr = DMGetWorkArray(refTree, numSelfShapes * numChildShapes, PETSC_SCALAR,&pointMat);CHKERRQ(ierr); 32013b1c2a6aSToby Isaac ierr = DMGetWorkArray(refTree, numSelfShapes + numChildShapes, PETSC_INT,&matRows);CHKERRQ(ierr); 32023b1c2a6aSToby Isaac matCols = matRows + numSelfShapes; 32033b1c2a6aSToby Isaac for (i = 0; i < numSelfShapes; i++) { 32043b1c2a6aSToby Isaac matRows[i] = selfOff + i * fComp; 32053b1c2a6aSToby Isaac } 32063b1c2a6aSToby Isaac { 32073b1c2a6aSToby Isaac PetscInt colOff = 0; 32083b1c2a6aSToby Isaac 32093b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 32103b1c2a6aSToby Isaac PetscInt child = children[i]; 32113b1c2a6aSToby Isaac PetscInt dof, off, j; 32123b1c2a6aSToby Isaac 32133b1c2a6aSToby Isaac if (numSecFields) { 3214c5356c36SToby Isaac ierr = PetscSectionGetFieldDof(cSection,child,f,&dof);CHKERRQ(ierr); 3215c5356c36SToby Isaac ierr = PetscSectionGetFieldOffset(cSection,child,f,&off);CHKERRQ(ierr); 32163b1c2a6aSToby Isaac } 32173b1c2a6aSToby Isaac else { 3218c5356c36SToby Isaac ierr = PetscSectionGetDof(cSection,child,&dof);CHKERRQ(ierr); 3219c5356c36SToby Isaac ierr = PetscSectionGetOffset(cSection,child,&off);CHKERRQ(ierr); 32203b1c2a6aSToby Isaac } 32213b1c2a6aSToby Isaac 32223b1c2a6aSToby Isaac for (j = 0; j < dof / fComp; j++) { 32233b1c2a6aSToby Isaac matCols[colOff++] = off + j * fComp; 32243b1c2a6aSToby Isaac } 32253b1c2a6aSToby Isaac } 32263b1c2a6aSToby Isaac } 32278d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 32288d2f55e7SToby Isaac PetscFE fe = (PetscFE) disc; 32298d2f55e7SToby Isaac PetscInt fSize; 32308d2f55e7SToby Isaac 32318d2f55e7SToby Isaac ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr); 32323b1c2a6aSToby Isaac ierr = PetscDualSpaceGetDimension(dsp,&fSize);CHKERRQ(ierr); 32338d2f55e7SToby Isaac for (i = 0; i < numSelfShapes; i++) { /* for every shape function */ 32348d2f55e7SToby Isaac PetscQuadrature q; 32358d2f55e7SToby Isaac PetscInt dim, numPoints, j, k; 32368d2f55e7SToby Isaac const PetscReal *points; 32378d2f55e7SToby Isaac const PetscReal *weights; 32388d2f55e7SToby Isaac PetscInt *closure = NULL; 32398d2f55e7SToby Isaac PetscInt numClosure; 32403b1c2a6aSToby Isaac PetscInt parentCellShapeDof = cellShapeOff + (pO < 0 ? (numSelfShapes - 1 - i) : i); 32418d2f55e7SToby Isaac PetscReal *Bparent; 32428d2f55e7SToby Isaac 32433b1c2a6aSToby Isaac ierr = PetscDualSpaceGetFunctional(dsp,parentCellShapeDof,&q);CHKERRQ(ierr); 32443b1c2a6aSToby Isaac ierr = PetscQuadratureGetData(q,&dim,&numPoints,&points,&weights);CHKERRQ(ierr); 32453b1c2a6aSToby Isaac ierr = PetscFEGetTabulation(fe,numPoints,points,&Bparent,NULL,NULL);CHKERRQ(ierr); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 32468d2f55e7SToby Isaac for (k = 0; k < numChildShapes; k++) { 32478d2f55e7SToby Isaac pointMat[numChildShapes * i + k] = 0.; 32488d2f55e7SToby Isaac } 32493b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 32508d2f55e7SToby Isaac PetscInt childCell = -1; 32513b1c2a6aSToby Isaac PetscReal parentValAtPoint; 32528d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 32538d2f55e7SToby Isaac const PetscScalar *point; 32548d2f55e7SToby Isaac PetscReal *Bchild; 32558d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 32568d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 32578d2f55e7SToby Isaac PetscInt d; 32588d2f55e7SToby Isaac 32598d2f55e7SToby Isaac for (d = 0; d < dim; d++) { 32608d2f55e7SToby Isaac pointScalar[d] = points[dim * j + d]; 32618d2f55e7SToby Isaac } 32628d2f55e7SToby Isaac point = pointScalar; 32638d2f55e7SToby Isaac #else 32648d2f55e7SToby Isaac point = pointReal; 32658d2f55e7SToby Isaac #endif 32668d2f55e7SToby Isaac 32673b1c2a6aSToby Isaac parentValAtPoint = Bparent[(fSize * j + parentCellShapeDof) * fComp]; 32683b1c2a6aSToby Isaac 32693b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 32708d2f55e7SToby Isaac PetscInt child = children[k]; 32718d2f55e7SToby Isaac PetscInt *star = NULL; 32728d2f55e7SToby Isaac PetscInt numStar, s; 32738d2f55e7SToby Isaac 32748d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 32758d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 32768d2f55e7SToby Isaac PetscInt c = star[2 * s]; 32778d2f55e7SToby Isaac 32788d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 32798d2f55e7SToby Isaac ierr = DMPlexLocatePoint_Internal(refTree,dim,point,c,&childCell);CHKERRQ(ierr); 32808d2f55e7SToby Isaac if (childCell >= 0) break; 32818d2f55e7SToby Isaac } 32828d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 32838d2f55e7SToby Isaac if (childCell >= 0) break; 32848d2f55e7SToby Isaac } 32858d2f55e7SToby Isaac if (childCell < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not locate quadrature point");CHKERRQ(ierr); 32868d2f55e7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 32878d2f55e7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent);CHKERRQ(ierr); 32888d2f55e7SToby Isaac CoordinatesRefToReal(dim, dim, v0parent, Jparent, pointReal, vtmp); 32898d2f55e7SToby Isaac CoordinatesRealToRef(dim, dim, v0, invJ, vtmp, pointRef); 32908d2f55e7SToby Isaac 32918d2f55e7SToby Isaac ierr = PetscFEGetTabulation(fe,1,pointRef,&Bchild,NULL,NULL);CHKERRQ(ierr); 32928d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 32933b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3294c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 32958d2f55e7SToby Isaac PetscInt l; 32968d2f55e7SToby Isaac 32978d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,child,&childDepth);CHKERRQ(ierr); 32988d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 32998d2f55e7SToby Isaac for (l = 0, childCellShapeOff = 0; l < numClosure; l++) { 33008d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 33018d2f55e7SToby Isaac PetscInt pointDepth; 33028d2f55e7SToby Isaac 33038d2f55e7SToby Isaac childO = closure[2 * l + 1]; 33048d2f55e7SToby Isaac if (point == child) break; 33058d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,point,&pointDepth);CHKERRQ(ierr); 33068d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 33078d2f55e7SToby Isaac } 33088d2f55e7SToby Isaac if (l == numClosure) { 33098d2f55e7SToby Isaac pointMatOff += childDof; 33108d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 33118d2f55e7SToby Isaac } 33128d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 33133b1c2a6aSToby Isaac PetscInt childCellDof = childCellShapeOff + (childO ? (childDof - 1 - l) : l); 33143b1c2a6aSToby Isaac PetscReal childValAtPoint = Bchild[childCellDof * fComp]; 33158d2f55e7SToby Isaac 33163b1c2a6aSToby Isaac pointMat[i * numChildShapes + pointMatOff + l] += weights[j] * parentValAtPoint * childValAtPoint; 33178d2f55e7SToby Isaac } 33188d2f55e7SToby Isaac pointMatOff += childDof; 33198d2f55e7SToby Isaac } 33208d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 33218d2f55e7SToby Isaac ierr = PetscFERestoreTabulation(fe,1,pointRef,&Bchild,NULL,NULL);CHKERRQ(ierr); 33228d2f55e7SToby Isaac } 33238d2f55e7SToby Isaac ierr = PetscFERestoreTabulation(fe,numPoints,points,&Bparent,NULL,NULL);CHKERRQ(ierr); 33248d2f55e7SToby Isaac } 33258d2f55e7SToby Isaac } 3326c5356c36SToby Isaac else { /* just the volume-weighted averages of the children */ 33273b1c2a6aSToby Isaac PetscInt childShapeOff; 33283b1c2a6aSToby Isaac PetscReal parentVol; 33293b1c2a6aSToby Isaac 33303b1c2a6aSToby Isaac ierr = DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL);CHKERRQ(ierr); 33313b1c2a6aSToby Isaac for (i = 0, childShapeOff = 0; i < numChildren; i++) { 33323b1c2a6aSToby Isaac PetscInt child = children[i]; 33333b1c2a6aSToby Isaac PetscReal childVol; 33343b1c2a6aSToby Isaac 33353b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 33363b1c2a6aSToby Isaac ierr = DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL);CHKERRQ(ierr); 33373b1c2a6aSToby Isaac pointMat[childShapeOff] = childVol / parentVol; 33383b1c2a6aSToby Isaac childShapeOff++; 33393b1c2a6aSToby Isaac } 33408d2f55e7SToby Isaac } 33413b1c2a6aSToby Isaac /* Insert pointMat into mat */ 33423b1c2a6aSToby Isaac for (i = 0; i < fComp; i++) { 33433b1c2a6aSToby Isaac PetscInt j; 33443b1c2a6aSToby Isaac ierr = MatSetValues(mat,numSelfShapes,matRows,numChildShapes,matCols,pointMat,INSERT_VALUES);CHKERRQ(ierr); 33453b1c2a6aSToby Isaac 33463b1c2a6aSToby Isaac for (j = 0; j < numSelfShapes; j++) { 33473b1c2a6aSToby Isaac matRows[j]++; 33483b1c2a6aSToby Isaac } 33493b1c2a6aSToby Isaac for (j = 0; j < numChildShapes; j++) { 33503b1c2a6aSToby Isaac matCols[j]++; 33513b1c2a6aSToby Isaac } 33523b1c2a6aSToby Isaac } 33533b1c2a6aSToby Isaac ierr = DMRestoreWorkArray(refTree, numSelfShapes + numChildShapes, PETSC_INT,&matRows);CHKERRQ(ierr); 33548d2f55e7SToby Isaac ierr = DMRestoreWorkArray(refTree, numSelfShapes * numChildShapes, PETSC_SCALAR,&pointMat);CHKERRQ(ierr); 33558d2f55e7SToby Isaac } 33568d2f55e7SToby Isaac } 33573b1c2a6aSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJ);CHKERRQ(ierr); 33588d2f55e7SToby Isaac ierr = PetscFree2(pointScalar,pointRef);CHKERRQ(ierr); 33593b1c2a6aSToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 33603b1c2a6aSToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 33618d2f55e7SToby Isaac *inj = mat; 33628d2f55e7SToby Isaac PetscFunctionReturn(0); 33638d2f55e7SToby Isaac } 33648d2f55e7SToby Isaac 33658d2f55e7SToby Isaac #undef __FUNCT__ 3366f30e825dSToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildrenMatrices_Injection" 3367f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3368f30e825dSToby Isaac { 3369f30e825dSToby Isaac PetscDS ds; 3370f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3371f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3372f30e825dSToby Isaac PetscSection refConSec, refSection; 3373f30e825dSToby Isaac PetscErrorCode ierr; 3374f30e825dSToby Isaac 3375f30e825dSToby Isaac PetscFunctionBegin; 3376f30e825dSToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 3377f30e825dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 3378f30e825dSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 3379f30e825dSToby Isaac ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr); 3380f30e825dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3381f30e825dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr); 3382f30e825dSToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 3383f30e825dSToby Isaac ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr); 3384f30e825dSToby Isaac ierr = PetscMalloc1(maxDof*maxDof,&cols);CHKERRQ(ierr); 3385f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3386f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3387f30e825dSToby Isaac 3388f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 3389f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 3390c6154584SToby Isaac ierr = PetscSectionGetDof(refSection,parent,&parentDof);CHKERRQ(ierr); 3391f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3392f30e825dSToby Isaac 3393f30e825dSToby Isaac ierr = PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr); 3394f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3395f30e825dSToby Isaac PetscInt cDof, cOff, numCols, r, fComp; 3396f30e825dSToby Isaac PetscObject disc; 3397f30e825dSToby Isaac PetscClassId id; 3398f30e825dSToby Isaac PetscFE fe = NULL; 3399f30e825dSToby Isaac PetscFV fv = NULL; 3400f30e825dSToby Isaac 3401f30e825dSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 3402f30e825dSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 3403f30e825dSToby Isaac if (id == PETSCFE_CLASSID) { 3404f30e825dSToby Isaac fe = (PetscFE) disc; 3405f30e825dSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 3406f30e825dSToby Isaac } 3407f30e825dSToby Isaac else if (id == PETSCFV_CLASSID) { 3408f30e825dSToby Isaac fv = (PetscFV) disc; 3409f30e825dSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 3410f30e825dSToby Isaac } 3411f30e825dSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 3412f30e825dSToby Isaac 3413f30e825dSToby Isaac if (numFields > 1) { 3414f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 3415f30e825dSToby Isaac ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr); 3416f30e825dSToby Isaac } 3417f30e825dSToby Isaac else { 3418f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 3419f30e825dSToby Isaac ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr); 3420f30e825dSToby Isaac } 3421f30e825dSToby Isaac 3422f30e825dSToby Isaac for (r = 0; r < cDof; r++) { 3423f30e825dSToby Isaac rows[r] = cOff + r; 3424f30e825dSToby Isaac } 3425f30e825dSToby Isaac numCols = 0; 3426f30e825dSToby Isaac { 3427f30e825dSToby Isaac PetscInt aDof, aOff, j; 3428f30e825dSToby Isaac 3429f30e825dSToby Isaac if (numFields > 1) { 3430f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refSection,parent,f,&aDof);CHKERRQ(ierr); 3431f30e825dSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,parent,f,&aOff);CHKERRQ(ierr); 3432f30e825dSToby Isaac } 3433f30e825dSToby Isaac else { 3434f30e825dSToby Isaac ierr = PetscSectionGetDof(refSection,parent,&aDof);CHKERRQ(ierr); 3435f30e825dSToby Isaac ierr = PetscSectionGetOffset(refSection,parent,&aOff);CHKERRQ(ierr); 3436f30e825dSToby Isaac } 3437f30e825dSToby Isaac 3438f30e825dSToby Isaac for (j = 0; j < aDof; j++) { 3439f30e825dSToby Isaac cols[numCols++] = aOff + j; 3440f30e825dSToby Isaac } 3441f30e825dSToby Isaac } 3442f30e825dSToby Isaac ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 3443f30e825dSToby Isaac /* transpose of constraint matrix */ 3444f30e825dSToby Isaac ierr = MatGetValues(inj,numCols,cols,cDof,rows,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 3445f30e825dSToby Isaac } 3446f30e825dSToby Isaac } 3447f30e825dSToby Isaac *childrenMats = refPointFieldMats; 3448f30e825dSToby Isaac ierr = PetscFree(rows);CHKERRQ(ierr); 3449f30e825dSToby Isaac ierr = PetscFree(cols);CHKERRQ(ierr); 3450f30e825dSToby Isaac PetscFunctionReturn(0); 3451f30e825dSToby Isaac } 3452f30e825dSToby Isaac 3453f30e825dSToby Isaac #undef __FUNCT__ 3454f30e825dSToby Isaac #define __FUNCT__ "DMPlexReferenceTreeRestoreChildrenMatrices_Injection" 3455f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3456f30e825dSToby Isaac { 3457f30e825dSToby Isaac PetscDS ds; 3458f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3459f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3460c6154584SToby Isaac PetscSection refConSec, refSection; 3461f30e825dSToby Isaac PetscErrorCode ierr; 3462f30e825dSToby Isaac 3463f30e825dSToby Isaac PetscFunctionBegin; 3464f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3465f30e825dSToby Isaac *childrenMats = NULL; 3466f30e825dSToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 3467c6154584SToby Isaac ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr); 3468f30e825dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 3469f30e825dSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 3470f30e825dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3471f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3472f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3473f30e825dSToby Isaac 3474f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 3475f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 3476c6154584SToby Isaac ierr = PetscSectionGetDof(refSection,parent,&parentDof);CHKERRQ(ierr); 3477f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3478f30e825dSToby Isaac 3479f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3480f30e825dSToby Isaac PetscInt cDof; 3481f30e825dSToby Isaac 3482f30e825dSToby Isaac if (numFields > 1) { 3483f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 3484f30e825dSToby Isaac } 3485f30e825dSToby Isaac else { 3486f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 3487f30e825dSToby Isaac } 3488f30e825dSToby Isaac 3489f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr); 3490f30e825dSToby Isaac } 3491f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr); 3492f30e825dSToby Isaac } 3493f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr); 3494f30e825dSToby Isaac PetscFunctionReturn(0); 3495f30e825dSToby Isaac } 3496f30e825dSToby Isaac 3497f30e825dSToby Isaac #undef __FUNCT__ 3498ebf164c7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetInjector" 3499ebf164c7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree,Mat *injRef) 3500154bca37SToby Isaac { 3501ebf164c7SToby Isaac Mat cMatRef; 35026148253fSToby Isaac PetscObject injRefObj; 35038d2f55e7SToby Isaac PetscErrorCode ierr; 35048d2f55e7SToby Isaac 3505154bca37SToby Isaac PetscFunctionBegin; 3506ebf164c7SToby Isaac ierr = DMGetDefaultConstraints(refTree,NULL,&cMatRef);CHKERRQ(ierr); 35076148253fSToby Isaac ierr = PetscObjectQuery((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",&injRefObj);CHKERRQ(ierr); 3508ebf164c7SToby Isaac *injRef = (Mat) injRefObj; 3509ebf164c7SToby Isaac if (!*injRef) { 3510ebf164c7SToby Isaac ierr = DMPlexComputeInjectorReferenceTree(refTree,injRef);CHKERRQ(ierr); 3511ebf164c7SToby Isaac ierr = PetscObjectCompose((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",(PetscObject)*injRef);CHKERRQ(ierr); 3512ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 3513ebf164c7SToby Isaac ierr = PetscObjectDereference((PetscObject)*injRef);CHKERRQ(ierr); 3514ebf164c7SToby Isaac } 3515ebf164c7SToby Isaac PetscFunctionReturn(0); 35166148253fSToby Isaac } 3517f30e825dSToby Isaac 3518ebf164c7SToby Isaac #undef __FUNCT__ 3519c921d74cSToby Isaac #define __FUNCT__ "DMPlexTransferInjectorTree" 3520c921d74cSToby 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) 3521ebf164c7SToby Isaac { 3522c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3523ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3524ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3525c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3526c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3527c921d74cSToby Isaac const PetscInt *rootDegrees; 3528c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3529ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3530ebf164c7SToby Isaac PetscErrorCode ierr; 3531ebf164c7SToby Isaac 3532ebf164c7SToby Isaac PetscFunctionBegin; 3533ebf164c7SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 35348d2f55e7SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 3535f30e825dSToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 35368d2f55e7SToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 3537f30e825dSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr); 3538f30e825dSToby Isaac ierr = PetscSectionSetChart(leafIndicesSec,pStartF, pEndF);CHKERRQ(ierr); 3539c921d74cSToby Isaac ierr = PetscSectionGetMaxDof(localFine,&maxDof);CHKERRQ(ierr); 35408d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 35417e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 35427e96bdafSToby Isaac const PetscInt *leaves; 35438d2f55e7SToby Isaac 35447e96bdafSToby Isaac ierr = PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 35457e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 35467e96bdafSToby Isaac p = leaves ? leaves[l] : l; 35478d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 35488d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 35498d2f55e7SToby Isaac if ((dof - cdof) > 0) { 35508d2f55e7SToby Isaac numPointsWithDofs++; 3551f30e825dSToby Isaac 3552f30e825dSToby Isaac ierr = PetscSectionGetDof(localFine,p,&dof);CHKERRQ(ierr); 3553f30e825dSToby Isaac ierr = PetscSectionSetDof(leafIndicesSec,p,dof + 1);CHKERRQ(ierr); 35548d2f55e7SToby Isaac } 35558d2f55e7SToby Isaac } 35568d2f55e7SToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 3557f30e825dSToby Isaac ierr = PetscSectionSetUp(leafIndicesSec);CHKERRQ(ierr); 3558f30e825dSToby Isaac ierr = PetscSectionGetStorageSize(leafIndicesSec,&numIndices);CHKERRQ(ierr); 3559c921d74cSToby Isaac ierr = PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1),&leafInds);CHKERRQ(ierr); 3560c921d74cSToby Isaac if (gatheredValues) {ierr = PetscMalloc1(numIndices,&leafVals);CHKERRQ(ierr);} 35617e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 35627e96bdafSToby Isaac p = leaves ? leaves[l] : l; 35638d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 35648d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 35658d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3566f30e825dSToby Isaac PetscInt off, gOff; 3567f30e825dSToby Isaac PetscInt *pInd; 3568c921d74cSToby Isaac PetscScalar *pVal = NULL; 3569f30e825dSToby Isaac 35707e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3571f30e825dSToby Isaac 3572f30e825dSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&off);CHKERRQ(ierr); 3573f30e825dSToby Isaac 3574c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3575c921d74cSToby Isaac if (gatheredValues) { 3576c921d74cSToby Isaac PetscInt i; 3577c921d74cSToby Isaac 3578c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3579c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3580c921d74cSToby Isaac } 3581f30e825dSToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 3582f30e825dSToby Isaac 3583f30e825dSToby Isaac offsets[0] = 0; 3584f30e825dSToby Isaac if (numFields) { 3585f30e825dSToby Isaac PetscInt f; 3586f30e825dSToby Isaac 3587f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3588f30e825dSToby Isaac PetscInt fDof; 3589f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&fDof);CHKERRQ(ierr); 3590f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3591f30e825dSToby Isaac } 35924acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(localFine,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,-1,pInd);CHKERRQ(ierr); 3593f30e825dSToby Isaac } 3594f30e825dSToby Isaac else { 35954acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(localFine,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,pInd);CHKERRQ(ierr); 3596f30e825dSToby Isaac } 3597c921d74cSToby Isaac if (gatheredValues) {ierr = VecGetValues(fineVec,dof,pInd,pVal);CHKERRQ(ierr);} 35988d2f55e7SToby Isaac } 35998d2f55e7SToby Isaac } 36008d2f55e7SToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 3601f30e825dSToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 36028d2f55e7SToby Isaac } 3603f30e825dSToby Isaac 3604f30e825dSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 3605f30e825dSToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 3606f30e825dSToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 3607f30e825dSToby Isaac 36086148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 36096148253fSToby Isaac MPI_Datatype threeInt; 36106148253fSToby Isaac PetscMPIInt rank; 36116148253fSToby Isaac PetscInt (*parentNodeAndIdCoarse)[3]; 36126148253fSToby Isaac PetscInt (*parentNodeAndIdFine)[3]; 36136148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 36146148253fSToby Isaac PetscSF pointSF, sfToParents; 36156148253fSToby Isaac const PetscInt *ilocal; 36166148253fSToby Isaac const PetscSFNode *iremote; 36176148253fSToby Isaac PetscSFNode *iremoteToParents; 36186148253fSToby Isaac PetscInt *ilocalToParents; 36196148253fSToby Isaac 36206148253fSToby Isaac ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)coarse),&rank);CHKERRQ(ierr); 36216148253fSToby Isaac ierr = MPI_Type_contiguous(3,MPIU_INT,&threeInt);CHKERRQ(ierr); 36226148253fSToby Isaac ierr = MPI_Type_commit(&threeInt);CHKERRQ(ierr); 36236148253fSToby Isaac ierr = PetscMalloc2(pEndC-pStartC,&parentNodeAndIdCoarse,pEndF-pStartF,&parentNodeAndIdFine);CHKERRQ(ierr); 36246148253fSToby Isaac ierr = DMGetPointSF(coarse,&pointSF);CHKERRQ(ierr); 36256148253fSToby Isaac ierr = PetscSFGetGraph(pointSF,NULL,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 36266148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 36276148253fSToby Isaac PetscInt parent, childId; 36286148253fSToby Isaac ierr = DMPlexGetTreeParent(coarse,p,&parent,&childId);CHKERRQ(ierr); 36296148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 36306148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 36316148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 36326148253fSToby Isaac if (nleaves > 0) { 36336148253fSToby Isaac PetscInt leaf = -1; 36346148253fSToby Isaac 36356148253fSToby Isaac if (ilocal) { 36366148253fSToby Isaac ierr = PetscFindInt(parent,nleaves,ilocal,&leaf);CHKERRQ(ierr); 36376148253fSToby Isaac } 36386148253fSToby Isaac else { 36396148253fSToby Isaac leaf = p - pStartC; 36406148253fSToby Isaac } 36416148253fSToby Isaac if (leaf >= 0) { 36426148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 36436148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 36446148253fSToby Isaac } 36456148253fSToby Isaac } 36466148253fSToby Isaac } 36476148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 36486148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 36496148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 36506148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 36516148253fSToby Isaac } 36526148253fSToby Isaac ierr = PetscSFBcastBegin(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine);CHKERRQ(ierr); 36536148253fSToby Isaac ierr = PetscSFBcastEnd(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine);CHKERRQ(ierr); 36546148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3655f30e825dSToby Isaac PetscInt dof; 3656f30e825dSToby Isaac 3657f30e825dSToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&dof);CHKERRQ(ierr); 3658f30e825dSToby Isaac if (dof) { 3659f30e825dSToby Isaac PetscInt off; 3660f30e825dSToby Isaac 3661f30e825dSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&off);CHKERRQ(ierr); 3662c921d74cSToby Isaac if (gatheredIndices) { 3663c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3664c921d74cSToby Isaac } else if (gatheredValues) { 3665c921d74cSToby Isaac leafVals[off] = (PetscScalar) PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3666c921d74cSToby Isaac } 3667f30e825dSToby Isaac } 36686148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36696148253fSToby Isaac nleavesToParents++; 36706148253fSToby Isaac } 36716148253fSToby Isaac } 36726148253fSToby Isaac ierr = PetscMalloc1(nleavesToParents,&ilocalToParents);CHKERRQ(ierr); 36736148253fSToby Isaac ierr = PetscMalloc1(nleavesToParents,&iremoteToParents);CHKERRQ(ierr); 36746148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 36756148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36766148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 36776148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p-pStartF][0]; 36786148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p-pStartF][1]; 36796148253fSToby Isaac nleavesToParents++; 36806148253fSToby Isaac } 36816148253fSToby Isaac } 36826148253fSToby Isaac ierr = PetscSFCreate(PetscObjectComm((PetscObject)coarse),&sfToParents);CHKERRQ(ierr); 36836148253fSToby Isaac ierr = PetscSFSetGraph(sfToParents,pEndC-pStartC,nleavesToParents,ilocalToParents,PETSC_OWN_POINTER,iremoteToParents,PETSC_OWN_POINTER);CHKERRQ(ierr); 36846148253fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 36856148253fSToby Isaac 36866148253fSToby Isaac coarseToFineEmbedded = sfToParents; 36876148253fSToby Isaac 36886148253fSToby Isaac ierr = PetscFree2(parentNodeAndIdCoarse,parentNodeAndIdFine);CHKERRQ(ierr); 36896148253fSToby Isaac ierr = MPI_Type_free(&threeInt);CHKERRQ(ierr); 36906148253fSToby Isaac } 3691f30e825dSToby Isaac 36926148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 36936148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 36946148253fSToby Isaac PetscSF sfDofsOnly; 36956148253fSToby Isaac 36966148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 36976148253fSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 36986148253fSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 36996148253fSToby Isaac if ((dof - cdof) > 0) { 37006148253fSToby Isaac numPointsWithDofs++; 37016148253fSToby Isaac } 37026148253fSToby Isaac } 37036148253fSToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 37046148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 37056148253fSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 37066148253fSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 37076148253fSToby Isaac if ((dof - cdof) > 0) { 3708e03d9830SToby Isaac pointsWithDofs[offset++] = p - pStartC; 37096148253fSToby Isaac } 37106148253fSToby Isaac } 37116148253fSToby Isaac ierr = PetscSFCreateEmbeddedSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly);CHKERRQ(ierr); 37126148253fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 3713f30e825dSToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 37146148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 37156148253fSToby Isaac } 3716f30e825dSToby Isaac 37176148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 3718f30e825dSToby Isaac ierr = PetscSFComputeDegreeBegin(coarseToFineEmbedded,&rootDegrees);CHKERRQ(ierr); 3719f30e825dSToby Isaac ierr = PetscSFComputeDegreeEnd(coarseToFineEmbedded,&rootDegrees);CHKERRQ(ierr); 3720f30e825dSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&multiRootSec);CHKERRQ(ierr); 3721f30e825dSToby Isaac ierr = PetscSectionSetChart(multiRootSec,pStartC,pEndC);CHKERRQ(ierr); 37228d2f55e7SToby Isaac for (p = pStartC; p < pEndC; p++) { 3723f30e825dSToby Isaac ierr = PetscSectionSetDof(multiRootSec,p,rootDegrees[p-pStartC]);CHKERRQ(ierr); 37248d2f55e7SToby Isaac } 3725f30e825dSToby Isaac ierr = PetscSectionSetUp(multiRootSec);CHKERRQ(ierr); 3726f30e825dSToby Isaac ierr = PetscSectionGetStorageSize(multiRootSec,&numMulti);CHKERRQ(ierr); 37278d2f55e7SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec);CHKERRQ(ierr); 3728f30e825dSToby Isaac { /* distribute the leaf section */ 3729f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3730f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 37318d2f55e7SToby Isaac 3732f30e825dSToby Isaac ierr = PetscSFGetMultiSF(coarseToFineEmbedded,&multi);CHKERRQ(ierr); 3733f30e825dSToby Isaac ierr = PetscSFCreateInverseSF(multi,&multiInv);CHKERRQ(ierr); 3734f30e825dSToby Isaac ierr = PetscSFDistributeSection(multiInv,leafIndicesSec,&remoteOffsets,rootIndicesSec);CHKERRQ(ierr); 3735f30e825dSToby Isaac ierr = PetscSFCreateSectionSF(multiInv,leafIndicesSec,remoteOffsets,rootIndicesSec,&indicesSF);CHKERRQ(ierr); 3736f30e825dSToby Isaac ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 3737f30e825dSToby Isaac ierr = PetscSFDestroy(&multiInv);CHKERRQ(ierr); 37388d2f55e7SToby Isaac ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr); 3739c921d74cSToby Isaac if (gatheredIndices) { 3740c921d74cSToby Isaac ierr = PetscMalloc1(numRootIndices,&rootInds);CHKERRQ(ierr); 3741c921d74cSToby Isaac ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,leafInds,rootInds);CHKERRQ(ierr); 3742c921d74cSToby Isaac ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,leafInds,rootInds);CHKERRQ(ierr); 3743c921d74cSToby Isaac } 3744c921d74cSToby Isaac if (gatheredValues) { 3745c921d74cSToby Isaac ierr = PetscMalloc1(numRootIndices,&rootVals);CHKERRQ(ierr); 3746c921d74cSToby Isaac ierr = PetscSFBcastBegin(indicesSF,MPIU_SCALAR,leafVals,rootVals);CHKERRQ(ierr); 3747c921d74cSToby Isaac ierr = PetscSFBcastEnd(indicesSF,MPIU_SCALAR,leafVals,rootVals);CHKERRQ(ierr); 3748c921d74cSToby Isaac } 37498d2f55e7SToby Isaac ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr); 37508d2f55e7SToby Isaac } 3751ec92bd66SToby Isaac ierr = PetscSectionDestroy(&leafIndicesSec);CHKERRQ(ierr); 3752c921d74cSToby Isaac ierr = PetscFree(leafInds);CHKERRQ(ierr); 3753c921d74cSToby Isaac ierr = PetscFree(leafVals);CHKERRQ(ierr); 3754f30e825dSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 3755c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3756c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3757c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3758c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 3759ebf164c7SToby Isaac PetscFunctionReturn(0); 3760ebf164c7SToby Isaac } 3761ebf164c7SToby Isaac 3762ebf164c7SToby Isaac #undef __FUNCT__ 3763ebf164c7SToby Isaac #define __FUNCT__ "DMPlexComputeInjectorTree" 3764ebf164c7SToby Isaac PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3765ebf164c7SToby Isaac { 3766ebf164c7SToby Isaac DM refTree; 3767c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3768ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3769ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3770ebf164c7SToby Isaac PetscSection cSecRef; 3771c921d74cSToby Isaac PetscInt *rootIndices, *parentIndices, pRefStart, pRefEnd; 3772ebf164c7SToby Isaac Mat injRef; 3773c921d74cSToby Isaac PetscInt numFields, maxDof; 3774ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3775ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3776ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3777ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3778ebf164c7SToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3779ebf164c7SToby Isaac PetscErrorCode ierr; 3780ebf164c7SToby Isaac 3781ebf164c7SToby Isaac PetscFunctionBegin; 3782ebf164c7SToby Isaac 3783ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 3784ebf164c7SToby Isaac ierr = DMPlexGetReferenceTree(coarse,&refTree);CHKERRQ(ierr); 3785ebf164c7SToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSecRef,NULL);CHKERRQ(ierr); 3786ebf164c7SToby Isaac ierr = PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3787ebf164c7SToby Isaac ierr = DMPlexReferenceTreeGetInjector(refTree,&injRef);CHKERRQ(ierr); 3788ebf164c7SToby Isaac 3789ebf164c7SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 3790ebf164c7SToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 3791ebf164c7SToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 3792ebf164c7SToby Isaac ierr = PetscSectionGetNumFields(localFine,&numFields);CHKERRQ(ierr); 3793ebf164c7SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 3794ebf164c7SToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 3795ebf164c7SToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 3796ebf164c7SToby Isaac ierr = PetscSectionGetMaxDof(localCoarse,&maxDof);CHKERRQ(ierr); 3797ebf164c7SToby Isaac { 3798ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 3799ebf164c7SToby Isaac ierr = PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets);CHKERRQ(ierr); 3800ebf164c7SToby Isaac } 3801ebf164c7SToby Isaac 3802c921d74cSToby Isaac ierr = DMPlexTransferInjectorTree(coarse,fine,coarseToFine,childIds,NULL,numFields,offsets,&multiRootSec,&rootIndicesSec,&rootIndices,NULL);CHKERRQ(ierr); 38038d2f55e7SToby Isaac 3804f30e825dSToby Isaac ierr = PetscMalloc1(maxDof,&parentIndices);CHKERRQ(ierr); 3805f30e825dSToby Isaac 3806f30e825dSToby Isaac /* count indices */ 38078d2f55e7SToby Isaac ierr = MatGetLayouts(mat,&rowMap,&colMap);CHKERRQ(ierr); 3808c6154584SToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 3809c6154584SToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 38108d2f55e7SToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 38118d2f55e7SToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 3812f30e825dSToby Isaac ierr = PetscCalloc2(rowEnd-rowStart,&nnzD,rowEnd-rowStart,&nnzO);CHKERRQ(ierr); 3813f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3814f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 38158d2f55e7SToby Isaac 3816f30e825dSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 3817f30e825dSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 3818f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 3819f30e825dSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 38208d2f55e7SToby Isaac 38218d2f55e7SToby Isaac rowOffsets[0] = 0; 3822f30e825dSToby Isaac offsetsCopy[0] = 0; 38238d2f55e7SToby Isaac if (numFields) { 38248d2f55e7SToby Isaac PetscInt f; 38258d2f55e7SToby Isaac 3826f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3827f30e825dSToby Isaac PetscInt fDof; 3828f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 3829f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 38308d2f55e7SToby Isaac } 38314acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1,parentIndices);CHKERRQ(ierr); 38328d2f55e7SToby Isaac } 38338d2f55e7SToby Isaac else { 38344acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,parentIndices);CHKERRQ(ierr); 3835f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 38368d2f55e7SToby Isaac } 3837f30e825dSToby Isaac 3838f30e825dSToby Isaac ierr = PetscSectionGetDof(multiRootSec,p,&numLeaves);CHKERRQ(ierr); 3839f30e825dSToby Isaac ierr = PetscSectionGetOffset(multiRootSec,p,&leafStart);CHKERRQ(ierr); 3840f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3841f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3842f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3843f30e825dSToby Isaac const PetscInt *childIndices; 3844f30e825dSToby Isaac 3845f30e825dSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,l,&numIndices);CHKERRQ(ierr); 3846f30e825dSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,l,&offset);CHKERRQ(ierr); 3847f30e825dSToby Isaac childId = rootIndices[offset++]; 3848f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3849f30e825dSToby Isaac numIndices--; 3850f30e825dSToby Isaac 3851f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3852f30e825dSToby Isaac PetscInt i; 3853f30e825dSToby Isaac 3854f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3855f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3856f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3857f30e825dSToby Isaac if (rowIndex < 0) continue; 3858f30e825dSToby Isaac if (colIndex < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unconstrained fine and constrained coarse"); 3859a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3860f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 3861f30e825dSToby Isaac } 3862f30e825dSToby Isaac else { 3863f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3864f30e825dSToby Isaac } 3865f30e825dSToby Isaac } 3866f30e825dSToby Isaac } 3867f30e825dSToby Isaac else { 3868f30e825dSToby Isaac PetscInt parentId, f, lim; 3869f30e825dSToby Isaac 3870f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,childId,&parentId,NULL);CHKERRQ(ierr); 3871f30e825dSToby Isaac 3872f30e825dSToby Isaac lim = PetscMax(1,numFields); 3873f30e825dSToby Isaac offsets[0] = 0; 38748d2f55e7SToby Isaac if (numFields) { 38758d2f55e7SToby Isaac PetscInt f; 3876f30e825dSToby Isaac 38778d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3878f30e825dSToby Isaac PetscInt fDof; 3879f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(cSecRef,childId,f,&fDof);CHKERRQ(ierr); 3880f30e825dSToby Isaac 3881f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 38828d2f55e7SToby Isaac } 38838d2f55e7SToby Isaac } 38848d2f55e7SToby Isaac else { 3885f30e825dSToby Isaac PetscInt cDof; 3886f30e825dSToby Isaac 3887f30e825dSToby Isaac ierr = PetscSectionGetDof(cSecRef,childId,&cDof);CHKERRQ(ierr); 3888f30e825dSToby Isaac offsets[1] = cDof; 3889f30e825dSToby Isaac } 3890f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3891f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3892f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3893f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3894f30e825dSToby Isaac 3895f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3896f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3897f30e825dSToby Isaac 3898f30e825dSToby Isaac if (colIndex < 0) continue; 3899f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3900f30e825dSToby Isaac numD++; 3901f30e825dSToby Isaac } 3902f30e825dSToby Isaac else { 3903f30e825dSToby Isaac numO++; 3904f30e825dSToby Isaac } 3905f30e825dSToby Isaac } 3906f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3907f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3908f30e825dSToby Isaac 3909f30e825dSToby Isaac if (rowIndex < 0) continue; 3910f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3911f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 39128d2f55e7SToby Isaac } 39138d2f55e7SToby Isaac } 39148d2f55e7SToby Isaac } 3915f30e825dSToby Isaac } 3916f30e825dSToby Isaac } 3917f30e825dSToby Isaac /* preallocate */ 3918f30e825dSToby Isaac ierr = MatXAIJSetPreallocation(mat,1,nnzD,nnzO,NULL,NULL);CHKERRQ(ierr); 3919f30e825dSToby Isaac ierr = PetscFree2(nnzD,nnzO);CHKERRQ(ierr); 3920f30e825dSToby Isaac /* insert values */ 3921f30e825dSToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 3922f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3923f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3924f30e825dSToby Isaac 3925f30e825dSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 3926f30e825dSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 3927f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 3928f30e825dSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 3929f30e825dSToby Isaac 3930f30e825dSToby Isaac rowOffsets[0] = 0; 3931f30e825dSToby Isaac offsetsCopy[0] = 0; 39328d2f55e7SToby Isaac if (numFields) { 39338d2f55e7SToby Isaac PetscInt f; 3934f30e825dSToby Isaac 39358d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3936f30e825dSToby Isaac PetscInt fDof; 3937f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 3938f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3939f30e825dSToby Isaac } 39404acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1,parentIndices);CHKERRQ(ierr); 3941f30e825dSToby Isaac } 3942f30e825dSToby Isaac else { 39434acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,parentIndices);CHKERRQ(ierr); 3944f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3945f30e825dSToby Isaac } 3946f30e825dSToby Isaac 3947f30e825dSToby Isaac ierr = PetscSectionGetDof(multiRootSec,p,&numLeaves);CHKERRQ(ierr); 3948f30e825dSToby Isaac ierr = PetscSectionGetOffset(multiRootSec,p,&leafStart);CHKERRQ(ierr); 3949f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3950f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3951f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3952f30e825dSToby Isaac const PetscInt *childIndices; 3953f30e825dSToby Isaac 3954f30e825dSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,l,&numIndices);CHKERRQ(ierr); 3955f30e825dSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,l,&offset);CHKERRQ(ierr); 3956f30e825dSToby Isaac childId = rootIndices[offset++]; 3957f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3958f30e825dSToby Isaac numIndices--; 3959f30e825dSToby Isaac 3960f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3961f30e825dSToby Isaac PetscInt i; 3962f30e825dSToby Isaac 3963f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3964f30e825dSToby Isaac ierr = MatSetValue(mat,parentIndices[i],childIndices[i],1.,INSERT_VALUES);CHKERRQ(ierr); 39658d2f55e7SToby Isaac } 39668d2f55e7SToby Isaac } 39678d2f55e7SToby Isaac else { 3968f30e825dSToby Isaac PetscInt parentId, f, lim; 39698d2f55e7SToby Isaac 3970f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,childId,&parentId,NULL);CHKERRQ(ierr); 3971f30e825dSToby Isaac 3972f30e825dSToby Isaac lim = PetscMax(1,numFields); 3973f30e825dSToby Isaac offsets[0] = 0; 39748d2f55e7SToby Isaac if (numFields) { 3975f30e825dSToby Isaac PetscInt f; 39768d2f55e7SToby Isaac 3977f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3978f30e825dSToby Isaac PetscInt fDof; 3979f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(cSecRef,childId,f,&fDof);CHKERRQ(ierr); 3980f30e825dSToby Isaac 3981f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 39828d2f55e7SToby Isaac } 39838d2f55e7SToby Isaac } 39848d2f55e7SToby Isaac else { 3985f30e825dSToby Isaac PetscInt cDof; 3986f30e825dSToby Isaac 3987f30e825dSToby Isaac ierr = PetscSectionGetDof(cSecRef,childId,&cDof);CHKERRQ(ierr); 3988f30e825dSToby Isaac offsets[1] = cDof; 39898d2f55e7SToby Isaac } 3990f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3991f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3992f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3993f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3994f30e825dSToby Isaac 3995f30e825dSToby Isaac ierr = MatSetValues(mat,rowOffsets[f+1]-rowOffsets[f],rowIndices,offsets[f+1]-offsets[f],colIndices,childMat,INSERT_VALUES);CHKERRQ(ierr); 39968d2f55e7SToby Isaac } 39978d2f55e7SToby Isaac } 39988d2f55e7SToby Isaac } 39998d2f55e7SToby Isaac } 4000ec92bd66SToby Isaac ierr = PetscSectionDestroy(&multiRootSec);CHKERRQ(ierr); 4001ec92bd66SToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 4002ec92bd66SToby Isaac ierr = PetscFree(parentIndices);CHKERRQ(ierr); 4003f30e825dSToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 4004f30e825dSToby Isaac ierr = PetscFree(rootIndices);CHKERRQ(ierr); 4005f30e825dSToby Isaac ierr = PetscFree3(offsets,offsetsCopy,rowOffsets);CHKERRQ(ierr); 4006f30e825dSToby Isaac 40078d2f55e7SToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 40088d2f55e7SToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4009154bca37SToby Isaac PetscFunctionReturn(0); 4010154bca37SToby Isaac } 401138fc2455SToby Isaac 401238fc2455SToby Isaac #undef __FUNCT__ 4013ebf164c7SToby Isaac #define __FUNCT__ "DMPlexTransferVecTree_Interpolate" 40140eb7e1eaSToby Isaac static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 4015ebf164c7SToby Isaac { 40164833aeb0SToby Isaac PetscDS ds; 401762095d54SToby Isaac PetscSF coarseToFineEmbedded; 401862095d54SToby Isaac PetscSection globalCoarse, globalFine; 401962095d54SToby Isaac PetscSection localCoarse, localFine; 402062095d54SToby Isaac PetscSection aSec, cSec; 402162095d54SToby Isaac PetscSection rootValuesSec; 402262095d54SToby Isaac PetscSection leafValuesSec; 402362095d54SToby Isaac PetscScalar *rootValues, *leafValues; 402462095d54SToby Isaac IS aIS; 402562095d54SToby Isaac const PetscInt *anchors; 402662095d54SToby Isaac Mat cMat; 402762095d54SToby Isaac PetscInt numFields; 402889698031SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd, cellEndInterior; 402962095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 403062095d54SToby Isaac PetscInt *maxChildIds; 403162095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 40320eb7e1eaSToby Isaac PetscFV fv = NULL; 40330eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 40340eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 40350eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 40360eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 403762095d54SToby Isaac PetscErrorCode ierr; 403862095d54SToby Isaac 4039ebf164c7SToby Isaac PetscFunctionBegin; 4040708c7f19SToby Isaac ierr = VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 404162095d54SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 40420eb7e1eaSToby Isaac ierr = DMPlexGetHeightStratum(coarse,0,&cellStart,&cellEnd);CHKERRQ(ierr); 404389698031SToby Isaac ierr = DMPlexGetHybridBounds(coarse,&cellEndInterior,NULL,NULL,NULL);CHKERRQ(ierr); 404489698031SToby Isaac cellEnd = (cellEndInterior < 0) ? cellEnd : cellEndInterior; 404562095d54SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 404662095d54SToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 40470eb7e1eaSToby Isaac ierr = DMGetCoordinateDim(coarse,&dim);CHKERRQ(ierr); 404862095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 4049e4a60869SToby Isaac PetscInt nleaves, l; 4050e4a60869SToby Isaac const PetscInt *leaves; 405162095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 405262095d54SToby Isaac 4053e4a60869SToby Isaac ierr = PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 4054e4a60869SToby Isaac 4055e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 4056e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 4057e4a60869SToby Isaac 405862095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 405962095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 406062095d54SToby Isaac if ((dof - cdof) > 0) { 406162095d54SToby Isaac numPointsWithDofs++; 406262095d54SToby Isaac } 406362095d54SToby Isaac } 406462095d54SToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 40654833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 4066e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 4067e4a60869SToby Isaac 406862095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 406962095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 407062095d54SToby Isaac if ((dof - cdof) > 0) { 4071e4a60869SToby Isaac pointsWithDofs[offset++] = l; 407262095d54SToby Isaac } 407362095d54SToby Isaac } 407462095d54SToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 407562095d54SToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 407662095d54SToby Isaac } 407762095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 407862095d54SToby Isaac ierr = PetscMalloc1(pEndC-pStartC,&maxChildIds);CHKERRQ(ierr); 407962095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 408062095d54SToby Isaac maxChildIds[p - pStartC] = -2; 408162095d54SToby Isaac } 408262095d54SToby Isaac ierr = PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 408362095d54SToby Isaac ierr = PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 408462095d54SToby Isaac 408562095d54SToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 408662095d54SToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 408762095d54SToby Isaac 408862095d54SToby Isaac ierr = DMPlexGetAnchors(coarse,&aSec,&aIS);CHKERRQ(ierr); 408962095d54SToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 409062095d54SToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 409162095d54SToby Isaac 409262095d54SToby Isaac ierr = DMGetDefaultConstraints(coarse,&cSec,&cMat);CHKERRQ(ierr); 409362095d54SToby Isaac ierr = PetscSectionGetChart(cSec,&cStart,&cEnd);CHKERRQ(ierr); 409462095d54SToby Isaac 409562095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 409662095d54SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootValuesSec);CHKERRQ(ierr); 409762095d54SToby Isaac ierr = PetscSectionSetChart(rootValuesSec,pStartC,pEndC);CHKERRQ(ierr); 4098708c7f19SToby Isaac ierr = PetscSectionGetNumFields(localCoarse,&numFields);CHKERRQ(ierr); 409962095d54SToby Isaac { 410062095d54SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 410162095d54SToby Isaac ierr = PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO);CHKERRQ(ierr); 410262095d54SToby Isaac } 41030eb7e1eaSToby Isaac if (grad) { 41040eb7e1eaSToby Isaac PetscInt i; 41050eb7e1eaSToby Isaac 41060eb7e1eaSToby Isaac ierr = VecGetDM(cellGeom,&cellDM);CHKERRQ(ierr); 41070eb7e1eaSToby Isaac ierr = VecGetArrayRead(cellGeom,&cellGeomArray);CHKERRQ(ierr); 41080eb7e1eaSToby Isaac ierr = VecGetDM(grad,&gradDM);CHKERRQ(ierr); 41090eb7e1eaSToby Isaac ierr = VecGetArrayRead(grad,&gradArray);CHKERRQ(ierr); 41100eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1,numFields); i++) { 41110eb7e1eaSToby Isaac PetscObject obj; 41120eb7e1eaSToby Isaac PetscClassId id; 41130eb7e1eaSToby Isaac 41140eb7e1eaSToby Isaac ierr = DMGetField(coarse, i, &obj);CHKERRQ(ierr); 41150eb7e1eaSToby Isaac ierr = PetscObjectGetClassId(obj,&id);CHKERRQ(ierr); 41160eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 41170eb7e1eaSToby Isaac fv = (PetscFV) obj; 41180eb7e1eaSToby Isaac ierr = PetscFVGetNumComponents(fv,&numFVcomps);CHKERRQ(ierr); 41190eb7e1eaSToby Isaac fvField = i; 41200eb7e1eaSToby Isaac break; 41210eb7e1eaSToby Isaac } 41220eb7e1eaSToby Isaac } 41230eb7e1eaSToby Isaac } 412462095d54SToby Isaac 412562095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 412662095d54SToby Isaac PetscInt dof; 412762095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 412862095d54SToby Isaac PetscInt numValues = 0; 412962095d54SToby Isaac 413062095d54SToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 413162095d54SToby Isaac if (dof < 0) { 413262095d54SToby Isaac dof = -(dof + 1); 413362095d54SToby Isaac } 413462095d54SToby Isaac offsets[0] = 0; 413562095d54SToby Isaac newOffsets[0] = 0; 413662095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 413762095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 413862095d54SToby Isaac 41394833aeb0SToby Isaac ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 414062095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 414162095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 414262095d54SToby Isaac 414362095d54SToby Isaac ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr); 414462095d54SToby Isaac numValues += clDof; 414562095d54SToby Isaac } 41464833aeb0SToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 414762095d54SToby Isaac } 414862095d54SToby Isaac else if (maxChildId == -1) { 414962095d54SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&numValues);CHKERRQ(ierr); 415062095d54SToby Isaac } 415162095d54SToby Isaac /* we will pack the column indices with the field offsets */ 415278b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 41530eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 41540eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 41550eb7e1eaSToby Isaac } 415662095d54SToby Isaac ierr = PetscSectionSetDof(rootValuesSec,p,numValues);CHKERRQ(ierr); 415762095d54SToby Isaac } 415862095d54SToby Isaac ierr = PetscSectionSetUp(rootValuesSec);CHKERRQ(ierr); 415962095d54SToby Isaac { 416062095d54SToby Isaac PetscInt numRootValues; 416162095d54SToby Isaac const PetscScalar *coarseArray; 416262095d54SToby Isaac 416362095d54SToby Isaac ierr = PetscSectionGetStorageSize(rootValuesSec,&numRootValues);CHKERRQ(ierr); 416462095d54SToby Isaac ierr = PetscMalloc1(numRootValues,&rootValues);CHKERRQ(ierr); 416562095d54SToby Isaac ierr = VecGetArrayRead(vecCoarseLocal,&coarseArray);CHKERRQ(ierr); 416662095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 416762095d54SToby Isaac PetscInt numValues; 416862095d54SToby Isaac PetscInt pValOff; 416962095d54SToby Isaac PetscScalar *pVal; 417062095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 417162095d54SToby Isaac 417262095d54SToby Isaac ierr = PetscSectionGetDof(rootValuesSec,p,&numValues);CHKERRQ(ierr); 417362095d54SToby Isaac if (!numValues) { 417462095d54SToby Isaac continue; 417562095d54SToby Isaac } 417662095d54SToby Isaac ierr = PetscSectionGetOffset(rootValuesSec,p,&pValOff);CHKERRQ(ierr); 417762095d54SToby Isaac pVal = &(rootValues[pValOff]); 417862095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 41790eb7e1eaSToby Isaac PetscInt closureSize = numValues; 41800eb7e1eaSToby Isaac ierr = DMPlexVecGetClosure(coarse,NULL,vecCoarseLocal,p,&closureSize,&pVal);CHKERRQ(ierr); 41810eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 4182193eb951SToby Isaac PetscFVCellGeom *cg; 41836dd00756SToby Isaac PetscScalar *gradVals = NULL; 41840eb7e1eaSToby Isaac PetscInt i; 41850eb7e1eaSToby Isaac 41860eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 41870eb7e1eaSToby Isaac 4188193eb951SToby Isaac ierr = DMPlexPointLocalRead(cellDM,p,cellGeomArray,(void *) &cg);CHKERRQ(ierr); 41890eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 41900eb7e1eaSToby Isaac pVal += dim; 4191193eb951SToby Isaac ierr = DMPlexPointGlobalRead(gradDM,p,gradArray,(void *) &gradVals);CHKERRQ(ierr); 41920eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 41930eb7e1eaSToby Isaac } 419462095d54SToby Isaac } 419578b7adb5SToby Isaac else if (maxChildId == -1) { 419678b7adb5SToby Isaac PetscInt lDof, lOff, i; 419778b7adb5SToby Isaac 419878b7adb5SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&lDof);CHKERRQ(ierr); 419978b7adb5SToby Isaac ierr = PetscSectionGetOffset(localCoarse,p,&lOff);CHKERRQ(ierr); 420078b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 420178b7adb5SToby Isaac } 420278b7adb5SToby Isaac } 420362095d54SToby Isaac ierr = VecRestoreArrayRead(vecCoarseLocal,&coarseArray);CHKERRQ(ierr); 420462095d54SToby Isaac ierr = PetscFree(maxChildIds);CHKERRQ(ierr); 420562095d54SToby Isaac } 420662095d54SToby Isaac { 420762095d54SToby Isaac PetscSF valuesSF; 420862095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 420962095d54SToby Isaac 421062095d54SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafValuesSec);CHKERRQ(ierr); 421162095d54SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootValuesSec,&remoteOffsetsValues,leafValuesSec);CHKERRQ(ierr); 421262095d54SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootValuesSec,remoteOffsetsValues,leafValuesSec,&valuesSF);CHKERRQ(ierr); 421362095d54SToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 421462095d54SToby Isaac ierr = PetscFree(remoteOffsetsValues);CHKERRQ(ierr); 421562095d54SToby Isaac ierr = PetscSectionGetStorageSize(leafValuesSec,&numLeafValues);CHKERRQ(ierr); 421662095d54SToby Isaac ierr = PetscMalloc1(numLeafValues,&leafValues);CHKERRQ(ierr); 421762095d54SToby Isaac ierr = PetscSFBcastBegin(valuesSF,MPIU_SCALAR,rootValues,leafValues);CHKERRQ(ierr); 421862095d54SToby Isaac ierr = PetscSFBcastEnd(valuesSF,MPIU_SCALAR,rootValues,leafValues);CHKERRQ(ierr); 421962095d54SToby Isaac ierr = PetscSFDestroy(&valuesSF);CHKERRQ(ierr); 422062095d54SToby Isaac ierr = PetscFree(rootValues);CHKERRQ(ierr); 422162095d54SToby Isaac ierr = PetscSectionDestroy(&rootValuesSec);CHKERRQ(ierr); 422262095d54SToby Isaac } 422362095d54SToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 422462095d54SToby Isaac { 422562095d54SToby Isaac PetscInt maxDof; 422662095d54SToby Isaac PetscInt *rowIndices; 422762095d54SToby Isaac DM refTree; 422862095d54SToby Isaac PetscInt **refPointFieldN; 422962095d54SToby Isaac PetscScalar ***refPointFieldMats; 423062095d54SToby Isaac PetscSection refConSec, refAnSec; 42310eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,leafStart,leafEnd; 423262095d54SToby Isaac PetscScalar *pointWork; 423362095d54SToby Isaac 423462095d54SToby Isaac ierr = PetscSectionGetMaxDof(globalFine,&maxDof);CHKERRQ(ierr); 423562095d54SToby Isaac ierr = DMGetWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 423662095d54SToby Isaac ierr = DMGetWorkArray(fine,maxDof,PETSC_SCALAR,&pointWork);CHKERRQ(ierr); 423762095d54SToby Isaac ierr = DMPlexGetReferenceTree(fine,&refTree);CHKERRQ(ierr); 42384833aeb0SToby Isaac ierr = DMGetDS(fine,&ds);CHKERRQ(ierr); 42394833aeb0SToby Isaac ierr = DMSetDS(refTree,ds);CHKERRQ(ierr); 424062095d54SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 424162095d54SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 424262095d54SToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,NULL);CHKERRQ(ierr); 424362095d54SToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 42440eb7e1eaSToby Isaac ierr = PetscSectionGetChart(leafValuesSec,&leafStart,&leafEnd);CHKERRQ(ierr); 42450eb7e1eaSToby Isaac ierr = DMPlexGetHeightStratum(fine,0,&cellStart,&cellEnd);CHKERRQ(ierr); 424689698031SToby Isaac ierr = DMPlexGetHybridBounds(fine,&cellEndInterior,NULL,NULL,NULL);CHKERRQ(ierr); 424789698031SToby Isaac cellEnd = (cellEndInterior < 0) ? cellEnd : cellEndInterior; 42480eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 424962095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 425062095d54SToby Isaac PetscInt numValues, pValOff; 425162095d54SToby Isaac PetscInt childId; 425262095d54SToby Isaac const PetscScalar *pVal; 42530eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 425462095d54SToby Isaac 425562095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 425662095d54SToby Isaac ierr = PetscSectionGetDof(localFine,p,&lDof);CHKERRQ(ierr); 425762095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 425862095d54SToby Isaac if ((gDof - gcDof) <= 0) { 425962095d54SToby Isaac continue; 426062095d54SToby Isaac } 426162095d54SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 426262095d54SToby Isaac ierr = PetscSectionGetDof(leafValuesSec,p,&numValues);CHKERRQ(ierr); 426362095d54SToby Isaac if (!numValues) continue; 426462095d54SToby Isaac ierr = PetscSectionGetOffset(leafValuesSec,p,&pValOff);CHKERRQ(ierr); 426562095d54SToby Isaac pVal = &leafValues[pValOff]; 426662095d54SToby Isaac offsets[0] = 0; 426762095d54SToby Isaac offsetsCopy[0] = 0; 426862095d54SToby Isaac newOffsets[0] = 0; 426962095d54SToby Isaac newOffsetsCopy[0] = 0; 42704833aeb0SToby Isaac childId = cids[p - pStartF]; 427162095d54SToby Isaac if (numFields) { 427262095d54SToby Isaac PetscInt f; 427362095d54SToby Isaac for (f = 0; f < numFields; f++) { 427462095d54SToby Isaac PetscInt rowDof; 427562095d54SToby Isaac 427662095d54SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 427762095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 427862095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 427962095d54SToby Isaac /* TODO: closure indices */ 42809f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 428162095d54SToby Isaac } 42824acb8e1eSToby Isaac ierr = DMPlexGetIndicesPointFields_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1,rowIndices);CHKERRQ(ierr); 428362095d54SToby Isaac } 428462095d54SToby Isaac else { 42854833aeb0SToby Isaac offsets[0] = 0; 42864833aeb0SToby Isaac offsets[1] = lDof; 42874833aeb0SToby Isaac newOffsets[0] = 0; 42884833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 42894acb8e1eSToby Isaac ierr = DMPlexGetIndicesPoint_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,NULL,rowIndices);CHKERRQ(ierr); 429062095d54SToby Isaac } 429162095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 42922f65e181SToby Isaac ierr = VecSetValues(vecFine,numValues,rowIndices,pVal,INSERT_VALUES);CHKERRQ(ierr); 429362095d54SToby Isaac } else { 429462095d54SToby Isaac PetscInt f; 429562095d54SToby Isaac 429678b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 429778b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 429878b7adb5SToby Isaac fvGradData = &pVal[numValues]; 429978b7adb5SToby Isaac } 430062095d54SToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 430162095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 430262095d54SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 430362095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 430462095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 430562095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 430662095d54SToby Isaac PetscInt i, j; 430762095d54SToby Isaac 4308708c7f19SToby Isaac #if 0 4309708c7f19SToby Isaac ierr = PetscInfo6(coarse,"field %D, numFields %D, childId %D, numRows %D, numCols %D, refPointFieldN %D\n",f,numFields,childId,numRows,numCols,refPointFieldN[childId - pRefStart][f]);CHKERRQ(ierr); 4310708c7f19SToby Isaac #endif 431162095d54SToby Isaac for (i = 0; i < numRows; i++) { 431262095d54SToby Isaac PetscScalar val = 0.; 431362095d54SToby Isaac for (j = 0; j < numCols; j++) { 431462095d54SToby Isaac val += childMat[i * numCols + j] * cVal[j]; 431562095d54SToby Isaac } 431662095d54SToby Isaac rVal[i] = val; 431762095d54SToby Isaac } 43180eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 43190eb7e1eaSToby Isaac PetscReal centroid[3]; 43200eb7e1eaSToby Isaac PetscScalar diff[3]; 43210eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 43220eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 43230eb7e1eaSToby Isaac 43240eb7e1eaSToby Isaac ierr = DMPlexComputeCellGeometryFVM(fine,p,NULL,centroid,NULL);CHKERRQ(ierr); 43250eb7e1eaSToby Isaac for (i = 0; i < dim; i++) { 43260eb7e1eaSToby Isaac diff[i] = centroid[i] - parentCentroid[i]; 43270eb7e1eaSToby Isaac } 43280eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 43290eb7e1eaSToby Isaac PetscScalar val = 0.; 43300eb7e1eaSToby Isaac 433189698031SToby Isaac for (j = 0; j < dim; j++) { 43320eb7e1eaSToby Isaac val += gradient[dim * i + j] * diff[j]; 43330eb7e1eaSToby Isaac } 43340eb7e1eaSToby Isaac rVal[i] += val; 43350eb7e1eaSToby Isaac } 43360eb7e1eaSToby Isaac } 43372f65e181SToby Isaac ierr = VecSetValues(vecFine,numRows,&rowIndices[offsets[f]],rVal,INSERT_VALUES);CHKERRQ(ierr); 433862095d54SToby Isaac } 433962095d54SToby Isaac } 434062095d54SToby Isaac } 434162095d54SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 434262095d54SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 434362095d54SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,PETSC_SCALAR,&pointWork);CHKERRQ(ierr); 434462095d54SToby Isaac } 43454fe3dfefSToby Isaac ierr = PetscFree(leafValues);CHKERRQ(ierr); 434662095d54SToby Isaac ierr = PetscSectionDestroy(&leafValuesSec);CHKERRQ(ierr); 434762095d54SToby Isaac ierr = PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO);CHKERRQ(ierr); 434862095d54SToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4349ebf164c7SToby Isaac PetscFunctionReturn(0); 4350ebf164c7SToby Isaac } 4351ebf164c7SToby Isaac 4352ebf164c7SToby Isaac #undef __FUNCT__ 4353ebf164c7SToby Isaac #define __FUNCT__ "DMPlexTransferVecTree_Inject" 4354ebf164c7SToby Isaac static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4355ebf164c7SToby Isaac { 43564833aeb0SToby Isaac PetscDS ds; 4357c921d74cSToby Isaac DM refTree; 4358c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4359c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4360c921d74cSToby Isaac PetscSection localCoarse, localFine; 4361c921d74cSToby Isaac PetscSection cSecRef; 4362c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4363d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4364c921d74cSToby Isaac Mat injRef; 4365c921d74cSToby Isaac PetscInt numFields, maxDof; 4366c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4367c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4368c921d74cSToby Isaac PetscLayout rowMap, colMap; 4369c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4370c921d74cSToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4371c921d74cSToby Isaac PetscErrorCode ierr; 4372c921d74cSToby Isaac 4373ebf164c7SToby Isaac PetscFunctionBegin; 4374c921d74cSToby Isaac 4375c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 4376708c7f19SToby Isaac ierr = VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 4377708c7f19SToby Isaac ierr = VecSetOption(vecCoarse,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 4378c921d74cSToby Isaac ierr = DMPlexGetReferenceTree(coarse,&refTree);CHKERRQ(ierr); 43794833aeb0SToby Isaac ierr = DMGetDS(coarse,&ds);CHKERRQ(ierr); 43804833aeb0SToby Isaac ierr = DMSetDS(refTree,ds);CHKERRQ(ierr); 4381c921d74cSToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSecRef,NULL);CHKERRQ(ierr); 4382c921d74cSToby Isaac ierr = PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd);CHKERRQ(ierr); 4383c921d74cSToby Isaac ierr = DMPlexReferenceTreeGetInjector(refTree,&injRef);CHKERRQ(ierr); 4384c921d74cSToby Isaac 4385c921d74cSToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 4386c921d74cSToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 4387c921d74cSToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 4388c921d74cSToby Isaac ierr = PetscSectionGetNumFields(localFine,&numFields);CHKERRQ(ierr); 4389c921d74cSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 4390c921d74cSToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 4391c921d74cSToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 4392c921d74cSToby Isaac ierr = PetscSectionGetMaxDof(localCoarse,&maxDof);CHKERRQ(ierr); 4393c921d74cSToby Isaac { 4394c921d74cSToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 4395c921d74cSToby Isaac ierr = PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets);CHKERRQ(ierr); 4396c921d74cSToby Isaac } 4397c921d74cSToby Isaac 4398c921d74cSToby Isaac ierr = DMPlexTransferInjectorTree(coarse,fine,coarseToFine,cids,vecFine,numFields,offsets,&multiRootSec,&rootIndicesSec,NULL,&rootValues);CHKERRQ(ierr); 4399c921d74cSToby Isaac 4400d3bc4906SToby Isaac ierr = PetscMalloc2(maxDof,&parentIndices,maxDof,&parentValues);CHKERRQ(ierr); 4401c921d74cSToby Isaac 4402c921d74cSToby Isaac /* count indices */ 440362095d54SToby Isaac ierr = VecGetLayout(vecFine,&colMap);CHKERRQ(ierr); 440462095d54SToby Isaac ierr = VecGetLayout(vecCoarse,&rowMap);CHKERRQ(ierr); 4405c921d74cSToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 4406c921d74cSToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 4407c921d74cSToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 4408c921d74cSToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 4409c921d74cSToby Isaac /* insert values */ 4410c921d74cSToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 4411c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4412c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 441378b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4414c921d74cSToby Isaac 4415c921d74cSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 4416c921d74cSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 4417c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 44182f65e181SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&dof);CHKERRQ(ierr); 4419c921d74cSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 4420c921d74cSToby Isaac 4421c921d74cSToby Isaac rowOffsets[0] = 0; 4422c921d74cSToby Isaac offsetsCopy[0] = 0; 4423c921d74cSToby Isaac if (numFields) { 4424c921d74cSToby Isaac PetscInt f; 4425c921d74cSToby Isaac 4426c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4427c921d74cSToby Isaac PetscInt fDof; 4428c921d74cSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 4429c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4430c921d74cSToby Isaac } 44314acb8e1eSToby Isaac DMPlexGetIndicesPointFields_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1,parentIndices);CHKERRQ(ierr); 4432c921d74cSToby Isaac } 4433c921d74cSToby Isaac else { 44344acb8e1eSToby Isaac DMPlexGetIndicesPoint_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,parentIndices);CHKERRQ(ierr); 4435c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4436c921d74cSToby Isaac } 4437c921d74cSToby Isaac 4438c921d74cSToby Isaac ierr = PetscSectionGetDof(multiRootSec,p,&numLeaves);CHKERRQ(ierr); 4439c921d74cSToby Isaac ierr = PetscSectionGetOffset(multiRootSec,p,&leafStart);CHKERRQ(ierr); 4440c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 44412f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4442c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4443c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4444c921d74cSToby Isaac const PetscScalar *childValues; 4445c921d74cSToby Isaac 4446c921d74cSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,l,&numIndices);CHKERRQ(ierr); 4447c921d74cSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,l,&offset);CHKERRQ(ierr); 4448c921d74cSToby Isaac childId = (PetscInt) PetscRealPart(rootValues[offset++]); 4449c921d74cSToby Isaac childValues = &rootValues[offset]; 4450c921d74cSToby Isaac numIndices--; 4451c921d74cSToby Isaac 4452c921d74cSToby Isaac if (childId == -2) { /* skip */ 4453c921d74cSToby Isaac continue; 4454c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 44552f65e181SToby Isaac PetscInt m; 44562f65e181SToby Isaac 445778b7adb5SToby Isaac contribute = PETSC_TRUE; 44582f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4459beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4460d3bc4906SToby Isaac PetscInt parentId, f, lim; 4461d3bc4906SToby Isaac 446278b7adb5SToby Isaac contribute = PETSC_TRUE; 4463d3bc4906SToby Isaac ierr = DMPlexGetTreeParent(refTree,childId,&parentId,NULL);CHKERRQ(ierr); 4464d3bc4906SToby Isaac 4465d3bc4906SToby Isaac lim = PetscMax(1,numFields); 4466d3bc4906SToby Isaac offsets[0] = 0; 4467d3bc4906SToby Isaac if (numFields) { 4468d3bc4906SToby Isaac PetscInt f; 4469d3bc4906SToby Isaac 4470d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4471d3bc4906SToby Isaac PetscInt fDof; 4472d3bc4906SToby Isaac ierr = PetscSectionGetFieldDof(cSecRef,childId,f,&fDof);CHKERRQ(ierr); 4473d3bc4906SToby Isaac 4474d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4475d3bc4906SToby Isaac } 4476d3bc4906SToby Isaac } 4477d3bc4906SToby Isaac else { 4478d3bc4906SToby Isaac PetscInt cDof; 4479d3bc4906SToby Isaac 4480d3bc4906SToby Isaac ierr = PetscSectionGetDof(cSecRef,childId,&cDof);CHKERRQ(ierr); 4481d3bc4906SToby Isaac offsets[1] = cDof; 4482d3bc4906SToby Isaac } 4483d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4484d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4485d3bc4906SToby Isaac PetscInt n = offsets[f+1]-offsets[f]; 4486d3bc4906SToby Isaac PetscInt i, j; 4487d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4488d3bc4906SToby Isaac 44892f65e181SToby Isaac for (i = rowOffsets[f]; i < rowOffsets[f + 1]; i++) { 4490d3bc4906SToby Isaac PetscScalar val = 0.; 4491d3bc4906SToby Isaac for (j = 0; j < n; j++) { 4492d3bc4906SToby Isaac val += childMat[n * i + j] * colValues[j]; 4493d3bc4906SToby Isaac } 4494beedf8abSToby Isaac parentValues[i] += val; 4495d3bc4906SToby Isaac } 4496d3bc4906SToby Isaac } 4497c921d74cSToby Isaac } 4498c921d74cSToby Isaac } 449978b7adb5SToby Isaac if (contribute) {ierr = VecSetValues(vecCoarse,dof,parentIndices,parentValues,INSERT_VALUES);CHKERRQ(ierr);} 4500c921d74cSToby Isaac } 4501c921d74cSToby Isaac ierr = PetscSectionDestroy(&multiRootSec);CHKERRQ(ierr); 4502c921d74cSToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 4503d3bc4906SToby Isaac ierr = PetscFree2(parentIndices,parentValues);CHKERRQ(ierr); 4504c921d74cSToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 4505c921d74cSToby Isaac ierr = PetscFree(rootValues);CHKERRQ(ierr); 4506c921d74cSToby Isaac ierr = PetscFree3(offsets,offsetsCopy,rowOffsets);CHKERRQ(ierr); 4507ebf164c7SToby Isaac PetscFunctionReturn(0); 4508ebf164c7SToby Isaac } 4509ebf164c7SToby Isaac 4510ebf164c7SToby Isaac #undef __FUNCT__ 451138fc2455SToby Isaac #define __FUNCT__ "DMPlexTransferVecTree" 4512ff1f73f7SToby Isaac /*@ 4513ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4514ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4515ff1f73f7SToby Isaac coarsening and refinement at the same time. 4516ff1f73f7SToby Isaac 4517ff1f73f7SToby Isaac collective 4518ff1f73f7SToby Isaac 4519ff1f73f7SToby Isaac Input Parameters: 4520ff1f73f7SToby Isaac + dmIn - The DMPlex mesh for the input vector 4521ff1f73f7SToby Isaac . vecIn - The input vector 4522ff1f73f7SToby Isaac . sfRefine - A star forest indicating points in the mesh dmIn (roots in the star forest) that are parents to points in 4523ff1f73f7SToby Isaac the mesh dmOut (leaves in the star forest), i.e. where dmOut is more refined than dmIn 4524ff1f73f7SToby Isaac . sfCoarsen - A star forest indicating points in the mesh dmOut (roots in the star forest) that are parents to points in 4525ff1f73f7SToby Isaac the mesh dmIn (leaves in the star forest), i.e. where dmOut is more coarsened than dmIn 4526ff1f73f7SToby Isaac . cidsRefine - The childIds of the points in dmOut. These childIds relate back to the reference tree: childid[j] = k implies 4527ff1f73f7SToby Isaac that mesh point j of dmOut was refined from a point in dmIn just as the mesh point k in the reference 4528ff1f73f7SToby Isaac tree was refined from its parent. childid[j] = -1 indicates that the point j in dmOut is exactly 4529ff1f73f7SToby Isaac equivalent to its root in dmIn, so no interpolation is necessary. childid[j] = -2 indicates that this 4530ff1f73f7SToby Isaac point j in dmOut is not a leaf of sfRefine. 4531ff1f73f7SToby Isaac . cidsCoarsen - The childIds of the points in dmIn. These childIds relate back to the reference tree: childid[j] = k implies 4532ff1f73f7SToby Isaac that mesh point j of dmIn coarsens to a point in dmOut just as the mesh point k in the reference 4533ff1f73f7SToby Isaac tree coarsens to its parent. childid[j] = -2 indicates that point j in dmOut is not a leaf in sfCoarsen. 4534ff1f73f7SToby Isaac . useBCs - PETSC_TRUE indicates that boundary values should be inserted into vecIn before transfer. 4535ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4536ff1f73f7SToby Isaac 4537ff1f73f7SToby Isaac Output Parameters: 4538ff1f73f7SToby Isaac . vecOut - Using interpolation and injection operators calculated on the reference tree, the transfered 4539ff1f73f7SToby Isaac projection of vecIn from dmIn to dmOut. Note that any field discretized with a PetscFV finite volume 4540ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4541ff1f73f7SToby Isaac coarse points to fine points. 4542ff1f73f7SToby Isaac 4543ff1f73f7SToby Isaac Level: developer 4544ff1f73f7SToby Isaac 4545ff1f73f7SToby Isaac .seealso(): DMPlexSetReferenceTree(), DMPlexGetReferenceTree(), PetscFVGetComputeGradients() 4546ff1f73f7SToby Isaac @*/ 4547ff1f73f7SToby Isaac PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) 454838fc2455SToby Isaac { 4549ebf164c7SToby Isaac PetscErrorCode ierr; 4550ebf164c7SToby Isaac 455138fc2455SToby Isaac PetscFunctionBegin; 455278b7adb5SToby Isaac ierr = VecSet(vecOut,0.0);CHKERRQ(ierr); 4553ff1f73f7SToby Isaac if (sfRefine) { 4554fbfa57b9SToby Isaac Vec vecInLocal; 45550eb7e1eaSToby Isaac DM dmGrad = NULL; 45560eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4557fbfa57b9SToby Isaac 4558fbfa57b9SToby Isaac ierr = DMGetLocalVector(dmIn,&vecInLocal);CHKERRQ(ierr); 4559fbfa57b9SToby Isaac ierr = VecSet(vecInLocal,0.0);CHKERRQ(ierr); 45600eb7e1eaSToby Isaac { 45610eb7e1eaSToby Isaac PetscInt numFields, i; 45620eb7e1eaSToby Isaac 45630eb7e1eaSToby Isaac ierr = DMGetNumFields(dmIn, &numFields);CHKERRQ(ierr); 45640eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 45650eb7e1eaSToby Isaac PetscObject obj; 45660eb7e1eaSToby Isaac PetscClassId classid; 45670eb7e1eaSToby Isaac 45680eb7e1eaSToby Isaac ierr = DMGetField(dmIn, i, &obj);CHKERRQ(ierr); 45690eb7e1eaSToby Isaac ierr = PetscObjectGetClassId(obj, &classid);CHKERRQ(ierr); 45700eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 45710eb7e1eaSToby Isaac ierr = DMPlexGetDataFVM(dmIn,(PetscFV)obj,&cellGeom,&faceGeom,&dmGrad);CHKERRQ(ierr); 45720eb7e1eaSToby Isaac break; 45730eb7e1eaSToby Isaac } 45740eb7e1eaSToby Isaac } 45750eb7e1eaSToby Isaac } 45760eb7e1eaSToby Isaac if (useBCs) { 45770eb7e1eaSToby Isaac ierr = DMPlexInsertBoundaryValues(dmIn,PETSC_TRUE,vecInLocal,time,faceGeom,cellGeom,NULL);CHKERRQ(ierr); 45780eb7e1eaSToby Isaac } 4579fbfa57b9SToby Isaac ierr = DMGlobalToLocalBegin(dmIn,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 4580fbfa57b9SToby Isaac ierr = DMGlobalToLocalEnd(dmIn,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 45810eb7e1eaSToby Isaac if (dmGrad) { 45820eb7e1eaSToby Isaac ierr = DMGetGlobalVector(dmGrad,&grad);CHKERRQ(ierr); 45830eb7e1eaSToby Isaac ierr = DMPlexReconstructGradientsFVM(dmIn,vecInLocal,grad);CHKERRQ(ierr); 45840eb7e1eaSToby Isaac } 4585ff1f73f7SToby Isaac ierr = DMPlexTransferVecTree_Interpolate(dmIn,vecInLocal,dmOut,vecOut,sfRefine,cidsRefine,grad,cellGeom);CHKERRQ(ierr); 4586fbfa57b9SToby Isaac ierr = DMRestoreLocalVector(dmIn,&vecInLocal);CHKERRQ(ierr); 45870eb7e1eaSToby Isaac if (dmGrad) { 45880eb7e1eaSToby Isaac ierr = DMRestoreGlobalVector(dmGrad,&grad);CHKERRQ(ierr); 45890eb7e1eaSToby Isaac } 4590ebf164c7SToby Isaac } 4591ff1f73f7SToby Isaac if (sfCoarsen) { 4592ff1f73f7SToby Isaac ierr = DMPlexTransferVecTree_Inject(dmIn,vecIn,dmOut,vecOut,sfCoarsen,cidsCoarsen);CHKERRQ(ierr); 4593ebf164c7SToby Isaac } 45942f65e181SToby Isaac ierr = VecAssemblyBegin(vecOut);CHKERRQ(ierr); 45952f65e181SToby Isaac ierr = VecAssemblyEnd(vecOut);CHKERRQ(ierr); 459638fc2455SToby Isaac PetscFunctionReturn(0); 459738fc2455SToby Isaac } 4598