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); 150dcbd3bf7SToby Isaac } 151dcbd3bf7SToby Isaac else { 152dcbd3bf7SToby Isaac oAvert = parentOrientA; 153dcbd3bf7SToby Isaac oBvert = parentOrientB; 154dcbd3bf7SToby Isaac ABswapVert = ABswap; 155dcbd3bf7SToby Isaac } 156dcbd3bf7SToby Isaac if (childB) { 157dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 158dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 159dcbd3bf7SToby Isaac const PetscInt *children; 160dcbd3bf7SToby Isaac 161dcbd3bf7SToby Isaac /* count which position the child is in */ 162dcbd3bf7SToby Isaac ierr = DMPlexGetTreeChildren(dm,parent,&numChildren,&children);CHKERRQ(ierr); 163dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 164dcbd3bf7SToby Isaac p = children[i]; 165dcbd3bf7SToby Isaac if (p == childA) { 166dcbd3bf7SToby Isaac posA = i; 167dcbd3bf7SToby Isaac break; 168dcbd3bf7SToby Isaac } 169dcbd3bf7SToby Isaac } 170dcbd3bf7SToby Isaac if (posA >= coneSize) { 171dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 172dcbd3bf7SToby Isaac * is invariant */ 173dcbd3bf7SToby Isaac if (dim != 2 || posA != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Expected a middle triangle, got something else"); 174dcbd3bf7SToby Isaac *childB = childA; 175dcbd3bf7SToby Isaac } 176dcbd3bf7SToby Isaac else { 177dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 178dcbd3bf7SToby Isaac PetscInt posB; 179dcbd3bf7SToby Isaac 180dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 181dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 182dcbd3bf7SToby Isaac } 183dcbd3bf7SToby Isaac } 184dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 185dcbd3bf7SToby Isaac PetscFunctionReturn(0); 186dcbd3bf7SToby Isaac } 187dcbd3bf7SToby Isaac 188dcbd3bf7SToby Isaac #undef __FUNCT__ 189dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry" 190dcbd3bf7SToby Isaac /*@ 191dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 192dcbd3bf7SToby Isaac 193dcbd3bf7SToby Isaac Input Parameters: 194dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object 195dcbd3bf7SToby Isaac . parent - the parent point 196dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 197dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 198dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 199dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 200dcbd3bf7SToby Isaac 201dcbd3bf7SToby Isaac Output Parameters: 202dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child 203dcbd3bf7SToby Isaac . childB - if not NULL, the new childID for describing the child 204dcbd3bf7SToby Isaac 205dcbd3bf7SToby Isaac Level: developer 206dcbd3bf7SToby Isaac 207dcbd3bf7SToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexSetReferenceTree(), DMPlexSetTree() 208dcbd3bf7SToby Isaac @*/ 209dcbd3bf7SToby Isaac PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 210dcbd3bf7SToby Isaac { 211dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 212dcbd3bf7SToby Isaac PetscErrorCode ierr; 213dcbd3bf7SToby Isaac 214dcbd3bf7SToby Isaac PetscFunctionBegin; 215dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 216dcbd3bf7SToby Isaac if (!mesh->getchildsymmetry) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"DMPlexReferenceTreeGetChildSymmetry not implemented"); 217dcbd3bf7SToby Isaac ierr = mesh->getchildsymmetry(dm,parent,parentOrientA,childOrientA,childA,parentOrientB,childOrientB,childB);CHKERRQ(ierr); 218dcbd3bf7SToby Isaac PetscFunctionReturn(0); 219dcbd3bf7SToby Isaac } 220dcbd3bf7SToby Isaac 221776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM,PetscSection,PetscInt*,PetscInt*,PetscBool,PetscBool); 222f9f063d4SToby Isaac 223da43764aSToby Isaac #undef __FUNCT__ 224da43764aSToby Isaac #define __FUNCT__ "DMPlexCreateDefaultReferenceTree" 225da43764aSToby Isaac /*@ 226da43764aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 227da43764aSToby Isaac 228da43764aSToby Isaac Collective on comm 229da43764aSToby Isaac 230da43764aSToby Isaac Input Parameters: 231da43764aSToby Isaac + comm - the MPI communicator 232da43764aSToby Isaac . dim - the spatial dimension 233da43764aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 234da43764aSToby Isaac 235da43764aSToby Isaac Output Parameters: 236da43764aSToby Isaac . ref - the reference tree DMPlex object 237da43764aSToby Isaac 2380b7167a0SToby Isaac Level: intermediate 239da43764aSToby Isaac 240da43764aSToby Isaac .keywords: reference cell 241da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree() 242da43764aSToby Isaac @*/ 243da43764aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 244da43764aSToby Isaac { 245dcbd3bf7SToby Isaac DM_Plex *mesh; 246da43764aSToby Isaac DM K, Kref; 24710f7e118SToby Isaac PetscInt p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 248da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 249da43764aSToby Isaac DMLabel identity, identityRef; 25010f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 251da43764aSToby Isaac PetscScalar *unionCoords; 252da43764aSToby Isaac IS perm; 253da43764aSToby Isaac PetscErrorCode ierr; 254da43764aSToby Isaac 255da43764aSToby Isaac PetscFunctionBegin; 256e228b242SToby Isaac #if 1 257e228b242SToby Isaac comm = PETSC_COMM_SELF; 258e228b242SToby Isaac #endif 259da43764aSToby Isaac /* create a reference element */ 260da43764aSToby Isaac ierr = DMPlexCreateReferenceCell(comm, dim, simplex, &K);CHKERRQ(ierr); 261da43764aSToby Isaac ierr = DMPlexCreateLabel(K, "identity");CHKERRQ(ierr); 262da43764aSToby Isaac ierr = DMPlexGetLabel(K, "identity", &identity);CHKERRQ(ierr); 263da43764aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 264da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 265da43764aSToby Isaac ierr = DMLabelSetValue(identity, p, p);CHKERRQ(ierr); 266da43764aSToby Isaac } 267da43764aSToby Isaac /* refine it */ 268da43764aSToby Isaac ierr = DMRefine(K,comm,&Kref);CHKERRQ(ierr); 269da43764aSToby Isaac 270da43764aSToby Isaac /* the reference tree is the union of these two, without duplicating 271da43764aSToby Isaac * points that appear in both */ 272da43764aSToby Isaac ierr = DMPlexGetLabel(Kref, "identity", &identityRef);CHKERRQ(ierr); 273da43764aSToby Isaac ierr = DMPlexGetChart(Kref, &pRefStart, &pRefEnd);CHKERRQ(ierr); 274da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionSection);CHKERRQ(ierr); 275da43764aSToby Isaac ierr = PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart));CHKERRQ(ierr); 276da43764aSToby Isaac /* count points that will go in the union */ 277da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 278da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pStart, 1);CHKERRQ(ierr); 279da43764aSToby Isaac } 280da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 281da43764aSToby Isaac PetscInt q, qSize; 282da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, p, &q);CHKERRQ(ierr); 283da43764aSToby Isaac ierr = DMLabelGetStratumSize(identityRef, q, &qSize);CHKERRQ(ierr); 284da43764aSToby Isaac if (qSize > 1) { 285da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1);CHKERRQ(ierr); 286da43764aSToby Isaac } 287da43764aSToby Isaac } 288854ce69bSBarry Smith ierr = PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart,&permvals);CHKERRQ(ierr); 289da43764aSToby Isaac offset = 0; 290da43764aSToby Isaac /* stratify points in the union by topological dimension */ 291da43764aSToby Isaac for (d = 0; d <= dim; d++) { 292da43764aSToby Isaac PetscInt cStart, cEnd, c; 293da43764aSToby Isaac 294da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K, d, &cStart, &cEnd);CHKERRQ(ierr); 295da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 296da43764aSToby Isaac permvals[offset++] = c; 297da43764aSToby Isaac } 298da43764aSToby Isaac 299da43764aSToby Isaac ierr = DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd);CHKERRQ(ierr); 300da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 301da43764aSToby Isaac permvals[offset++] = c + (pEnd - pStart); 302da43764aSToby Isaac } 303da43764aSToby Isaac } 304da43764aSToby Isaac ierr = ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr); 305da43764aSToby Isaac ierr = PetscSectionSetPermutation(unionSection,perm);CHKERRQ(ierr); 306da43764aSToby Isaac ierr = PetscSectionSetUp(unionSection);CHKERRQ(ierr); 307da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionSection,&numUnionPoints);CHKERRQ(ierr); 308da43764aSToby Isaac ierr = PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints);CHKERRQ(ierr); 309da43764aSToby Isaac /* count dimension points */ 310da43764aSToby Isaac for (d = 0; d <= dim; d++) { 311da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 312da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d,&cStart,NULL);CHKERRQ(ierr); 313da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff);CHKERRQ(ierr); 314da43764aSToby Isaac if (d < dim) { 315da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d+1,&cStart,NULL);CHKERRQ(ierr); 316da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2);CHKERRQ(ierr); 317da43764aSToby Isaac } 318da43764aSToby Isaac else { 319da43764aSToby Isaac cOff2 = numUnionPoints; 320da43764aSToby Isaac } 321da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 322da43764aSToby Isaac } 323da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionConeSection);CHKERRQ(ierr); 324da43764aSToby Isaac ierr = PetscSectionSetChart(unionConeSection, 0, numUnionPoints);CHKERRQ(ierr); 325da43764aSToby Isaac /* count the cones in the union */ 326da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 327da43764aSToby Isaac PetscInt dof, uOff; 328da43764aSToby Isaac 329da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 330da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 331da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 332da43764aSToby Isaac coneSizes[uOff] = dof; 333da43764aSToby Isaac } 334da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 335da43764aSToby Isaac PetscInt dof, uDof, uOff; 336da43764aSToby Isaac 337da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 338da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 339da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 340da43764aSToby Isaac if (uDof) { 341da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 342da43764aSToby Isaac coneSizes[uOff] = dof; 343da43764aSToby Isaac } 344da43764aSToby Isaac } 345da43764aSToby Isaac ierr = PetscSectionSetUp(unionConeSection);CHKERRQ(ierr); 346da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionConeSection,&numCones);CHKERRQ(ierr); 347da43764aSToby Isaac ierr = PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations);CHKERRQ(ierr); 348da43764aSToby Isaac /* write the cones in the union */ 349da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 350da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 351da43764aSToby Isaac const PetscInt *cone, *orientation; 352da43764aSToby Isaac 353da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 354da43764aSToby Isaac ierr = DMPlexGetCone(K, p, &cone);CHKERRQ(ierr); 355da43764aSToby Isaac ierr = DMPlexGetConeOrientation(K, p, &orientation);CHKERRQ(ierr); 356da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 357da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 358da43764aSToby Isaac for (c = 0; c < dof; c++) { 359da43764aSToby Isaac PetscInt e, eOff; 360da43764aSToby Isaac e = cone[c]; 361da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 362da43764aSToby Isaac unionCones[cOff + c] = eOff; 363da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 364da43764aSToby Isaac } 365da43764aSToby Isaac } 366da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 367da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 368da43764aSToby Isaac const PetscInt *cone, *orientation; 369da43764aSToby Isaac 370da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 371da43764aSToby Isaac ierr = DMPlexGetCone(Kref, p, &cone);CHKERRQ(ierr); 372da43764aSToby Isaac ierr = DMPlexGetConeOrientation(Kref, p, &orientation);CHKERRQ(ierr); 373da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 374da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 375da43764aSToby Isaac if (uDof) { 376da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 377da43764aSToby Isaac for (c = 0; c < dof; c++) { 378da43764aSToby Isaac PetscInt e, eOff, eDof; 379da43764aSToby Isaac 380da43764aSToby Isaac e = cone[c]; 381da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof);CHKERRQ(ierr); 382da43764aSToby Isaac if (eDof) { 383da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff);CHKERRQ(ierr); 384da43764aSToby Isaac } 385da43764aSToby Isaac else { 386da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, e, &e);CHKERRQ(ierr); 387da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 388da43764aSToby Isaac } 389da43764aSToby Isaac unionCones[cOff + c] = eOff; 390da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 391da43764aSToby Isaac } 392da43764aSToby Isaac } 393da43764aSToby Isaac } 394da43764aSToby Isaac /* get the coordinates */ 395da43764aSToby Isaac { 396da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 397da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 398da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 399da43764aSToby Isaac PetscScalar *Kcoords; 400da43764aSToby Isaac 401da43764aSToby Isaac DMGetCoordinateSection(K, &KcoordsSec);CHKERRQ(ierr); 402da43764aSToby Isaac DMGetCoordinatesLocal(K, &KcoordsVec);CHKERRQ(ierr); 403da43764aSToby Isaac DMGetCoordinateSection(Kref, &KrefCoordsSec);CHKERRQ(ierr); 404da43764aSToby Isaac DMGetCoordinatesLocal(Kref, &KrefCoordsVec);CHKERRQ(ierr); 405da43764aSToby Isaac 406da43764aSToby Isaac numVerts = numDimPoints[0]; 407da43764aSToby Isaac ierr = PetscMalloc1(numVerts * dim,&unionCoords);CHKERRQ(ierr); 408da43764aSToby Isaac ierr = DMPlexGetDepthStratum(K,0,&vStart,&vEnd);CHKERRQ(ierr); 409da43764aSToby Isaac 410da43764aSToby Isaac offset = 0; 411da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 412da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pStart,&vOff);CHKERRQ(ierr); 413da43764aSToby Isaac ierr = VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords);CHKERRQ(ierr); 414da43764aSToby Isaac for (d = 0; d < dim; d++) { 415da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 416da43764aSToby Isaac } 417da43764aSToby Isaac offset++; 418da43764aSToby Isaac } 419da43764aSToby Isaac ierr = DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd);CHKERRQ(ierr); 420da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 421da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof);CHKERRQ(ierr); 422da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff);CHKERRQ(ierr); 423da43764aSToby Isaac ierr = VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords);CHKERRQ(ierr); 424da43764aSToby Isaac if (vDof) { 425da43764aSToby Isaac for (d = 0; d < dim; d++) { 426da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 427da43764aSToby Isaac } 428da43764aSToby Isaac offset++; 429da43764aSToby Isaac } 430da43764aSToby Isaac } 431da43764aSToby Isaac } 432da43764aSToby Isaac ierr = DMCreate(comm,ref);CHKERRQ(ierr); 433da43764aSToby Isaac ierr = DMSetType(*ref,DMPLEX);CHKERRQ(ierr); 43428f4b327SMatthew G. Knepley ierr = DMSetDimension(*ref,dim);CHKERRQ(ierr); 435da43764aSToby Isaac ierr = DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords);CHKERRQ(ierr); 43610f7e118SToby Isaac /* set the tree */ 43710f7e118SToby Isaac ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr); 43810f7e118SToby Isaac ierr = PetscSectionSetChart(parentSection,0,numUnionPoints);CHKERRQ(ierr); 43910f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 44010f7e118SToby Isaac PetscInt uDof, uOff; 44110f7e118SToby Isaac 44210f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 44310f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 44410f7e118SToby Isaac if (uDof) { 44510f7e118SToby Isaac PetscSectionSetDof(parentSection,uOff,1);CHKERRQ(ierr); 44610f7e118SToby Isaac } 44710f7e118SToby Isaac } 44810f7e118SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 44910f7e118SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&parentSize);CHKERRQ(ierr); 45010f7e118SToby Isaac ierr = PetscMalloc2(parentSize,&parents,parentSize,&childIDs);CHKERRQ(ierr); 45110f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 45210f7e118SToby Isaac PetscInt uDof, uOff; 45310f7e118SToby Isaac 45410f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 45510f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 45610f7e118SToby Isaac if (uDof) { 45710f7e118SToby Isaac PetscInt pOff, parent, parentU; 45810f7e118SToby Isaac PetscSectionGetOffset(parentSection,uOff,&pOff);CHKERRQ(ierr); 45910f7e118SToby Isaac DMLabelGetValue(identityRef,p,&parent);CHKERRQ(ierr); 46010f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, parent - pStart,&parentU);CHKERRQ(ierr); 46110f7e118SToby Isaac parents[pOff] = parentU; 46210f7e118SToby Isaac childIDs[pOff] = uOff; 46310f7e118SToby Isaac } 46410f7e118SToby Isaac } 465776742edSToby Isaac ierr = DMPlexSetTree_Internal(*ref,parentSection,parents,childIDs,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 466dcbd3bf7SToby Isaac mesh = (DM_Plex *) (*ref)->data; 467dcbd3bf7SToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 46810f7e118SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 46910f7e118SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 47010f7e118SToby Isaac 471da43764aSToby Isaac /* clean up */ 472da43764aSToby Isaac ierr = PetscSectionDestroy(&unionSection);CHKERRQ(ierr); 473da43764aSToby Isaac ierr = PetscSectionDestroy(&unionConeSection);CHKERRQ(ierr); 474da43764aSToby Isaac ierr = ISDestroy(&perm);CHKERRQ(ierr); 475da43764aSToby Isaac ierr = PetscFree(unionCoords);CHKERRQ(ierr); 476da43764aSToby Isaac ierr = PetscFree2(unionCones,unionOrientations);CHKERRQ(ierr); 477da43764aSToby Isaac ierr = PetscFree2(coneSizes,numDimPoints);CHKERRQ(ierr); 478da43764aSToby Isaac ierr = DMDestroy(&K);CHKERRQ(ierr); 479da43764aSToby Isaac ierr = DMDestroy(&Kref);CHKERRQ(ierr); 480da43764aSToby Isaac PetscFunctionReturn(0); 481da43764aSToby Isaac } 482da43764aSToby Isaac 483d961a43aSToby Isaac #undef __FUNCT__ 484878b19aaSToby Isaac #define __FUNCT__ "DMPlexTreeSymmetrize" 485878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 486878b19aaSToby Isaac { 487878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 488878b19aaSToby Isaac PetscSection childSec, pSec; 489878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 490878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 491878b19aaSToby Isaac PetscErrorCode ierr; 492878b19aaSToby Isaac 493878b19aaSToby Isaac PetscFunctionBegin; 494878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 495878b19aaSToby Isaac ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 496878b19aaSToby Isaac ierr = PetscFree(mesh->children);CHKERRQ(ierr); 497878b19aaSToby Isaac pSec = mesh->parentSection; 498878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 499878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(pSec,&pSize);CHKERRQ(ierr); 500878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 501878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 502878b19aaSToby Isaac 503878b19aaSToby Isaac parMax = PetscMax(parMax,par+1); 504878b19aaSToby Isaac parMin = PetscMin(parMin,par); 505878b19aaSToby Isaac } 506878b19aaSToby Isaac if (parMin > parMax) { 507878b19aaSToby Isaac parMin = -1; 508878b19aaSToby Isaac parMax = -1; 509878b19aaSToby Isaac } 510878b19aaSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec);CHKERRQ(ierr); 511878b19aaSToby Isaac ierr = PetscSectionSetChart(childSec,parMin,parMax);CHKERRQ(ierr); 512878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 513878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 514878b19aaSToby Isaac 515878b19aaSToby Isaac ierr = PetscSectionAddDof(childSec,par,1);CHKERRQ(ierr); 516878b19aaSToby Isaac } 517878b19aaSToby Isaac ierr = PetscSectionSetUp(childSec);CHKERRQ(ierr); 518878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(childSec,&cSize);CHKERRQ(ierr); 519878b19aaSToby Isaac ierr = PetscMalloc1(cSize,&children);CHKERRQ(ierr); 520878b19aaSToby Isaac ierr = PetscCalloc1(parMax-parMin,&offsets);CHKERRQ(ierr); 521878b19aaSToby Isaac ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr); 522878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 523878b19aaSToby Isaac PetscInt dof, off, i; 524878b19aaSToby Isaac 525878b19aaSToby Isaac ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 526878b19aaSToby Isaac ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr); 527878b19aaSToby Isaac for (i = 0; i < dof; i++) { 528878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 529878b19aaSToby Isaac 530878b19aaSToby Isaac ierr = PetscSectionGetOffset(childSec,par,&cOff);CHKERRQ(ierr); 531878b19aaSToby Isaac children[cOff + offsets[par-parMin]++] = p; 532878b19aaSToby Isaac } 533878b19aaSToby Isaac } 534878b19aaSToby Isaac mesh->childSection = childSec; 535878b19aaSToby Isaac mesh->children = children; 536878b19aaSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 537878b19aaSToby Isaac PetscFunctionReturn(0); 538878b19aaSToby Isaac } 539878b19aaSToby Isaac 540878b19aaSToby Isaac #undef __FUNCT__ 5416dd5a8c8SToby Isaac #define __FUNCT__ "AnchorsFlatten" 5426dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 5436dd5a8c8SToby Isaac { 5446dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5456dd5a8c8SToby Isaac const PetscInt *vals; 5466dd5a8c8SToby Isaac PetscSection secNew; 5476dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5486dd5a8c8SToby Isaac PetscBool compress; 5496dd5a8c8SToby Isaac PetscErrorCode ierr; 5506dd5a8c8SToby Isaac 5516dd5a8c8SToby Isaac PetscFunctionBegin; 5526dd5a8c8SToby Isaac ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr); 5536dd5a8c8SToby Isaac ierr = ISGetLocalSize(is,&size);CHKERRQ(ierr); 5546dd5a8c8SToby Isaac ierr = ISGetIndices(is,&vals);CHKERRQ(ierr); 5556dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew);CHKERRQ(ierr); 5566dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secNew,pStart,pEnd);CHKERRQ(ierr); 5576dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5586dd5a8c8SToby Isaac PetscInt dof; 5596dd5a8c8SToby Isaac 5606dd5a8c8SToby Isaac p = vals[i]; 5616dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5626dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5636dd5a8c8SToby Isaac if (dof) break; 5646dd5a8c8SToby Isaac } 5656dd5a8c8SToby Isaac if (i == size) { 5666dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 5676dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5686dd5a8c8SToby Isaac compress = PETSC_FALSE; 5696dd5a8c8SToby Isaac sizeNew = 0; 5706dd5a8c8SToby Isaac } 5716dd5a8c8SToby Isaac else { 5726dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5736dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5746dd5a8c8SToby Isaac PetscInt dof, off; 5756dd5a8c8SToby Isaac 5766dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5776dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 5786dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5796dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5806dd5a8c8SToby Isaac 5816dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5826dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 5836dd5a8c8SToby Isaac } 5846dd5a8c8SToby Isaac if (qDof) { 5856dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, qDof);CHKERRQ(ierr); 5866dd5a8c8SToby Isaac } 5876dd5a8c8SToby Isaac else { 5886dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, 1);CHKERRQ(ierr); 5896dd5a8c8SToby Isaac } 5906dd5a8c8SToby Isaac } 5916dd5a8c8SToby Isaac } 5926dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 5936dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secNew,&sizeNew);CHKERRQ(ierr); 5946dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsNew);CHKERRQ(ierr); 5956dd5a8c8SToby Isaac compress = PETSC_FALSE; 5966dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5976dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 5986dd5a8c8SToby Isaac 5996dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 6006dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 6016dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dofNew);CHKERRQ(ierr); 6026dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &offNew);CHKERRQ(ierr); 6036dd5a8c8SToby Isaac count = 0; 6046dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 6056dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 6066dd5a8c8SToby Isaac 6076dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 6086dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 6096dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, q, &qOff);CHKERRQ(ierr); 6106dd5a8c8SToby Isaac } 6116dd5a8c8SToby Isaac if (qDof) { 6126dd5a8c8SToby Isaac PetscInt oldCount = count; 6136dd5a8c8SToby Isaac 6146dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 6156dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 6166dd5a8c8SToby Isaac 6176dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6186dd5a8c8SToby Isaac if (valsNew[offNew + k] == r) { 6196dd5a8c8SToby Isaac break; 6206dd5a8c8SToby Isaac } 6216dd5a8c8SToby Isaac } 6226dd5a8c8SToby Isaac if (k == oldCount) { 6236dd5a8c8SToby Isaac valsNew[offNew + count++] = r; 6246dd5a8c8SToby Isaac } 6256dd5a8c8SToby Isaac } 6266dd5a8c8SToby Isaac } 6276dd5a8c8SToby Isaac else { 6286dd5a8c8SToby Isaac PetscInt k, oldCount = count; 6296dd5a8c8SToby Isaac 6306dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6316dd5a8c8SToby Isaac if (valsNew[offNew + k] == q) { 6326dd5a8c8SToby Isaac break; 6336dd5a8c8SToby Isaac } 6346dd5a8c8SToby Isaac } 6356dd5a8c8SToby Isaac if (k == oldCount) { 6366dd5a8c8SToby Isaac valsNew[offNew + count++] = q; 6376dd5a8c8SToby Isaac } 6386dd5a8c8SToby Isaac } 6396dd5a8c8SToby Isaac } 6406dd5a8c8SToby Isaac if (count < dofNew) { 6416dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secNew, p, count);CHKERRQ(ierr); 6426dd5a8c8SToby Isaac compress = PETSC_TRUE; 6436dd5a8c8SToby Isaac } 6446dd5a8c8SToby Isaac } 6456dd5a8c8SToby Isaac } 6466dd5a8c8SToby Isaac ierr = ISRestoreIndices(is,&vals);CHKERRQ(ierr); 6476dd5a8c8SToby Isaac ierr = MPI_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 6486dd5a8c8SToby Isaac if (!globalAnyNew) { 6496dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6506dd5a8c8SToby Isaac *sectionNew = NULL; 6516dd5a8c8SToby Isaac *isNew = NULL; 6526dd5a8c8SToby Isaac } 6536dd5a8c8SToby Isaac else { 6546dd5a8c8SToby Isaac PetscBool globalCompress; 6556dd5a8c8SToby Isaac 6566dd5a8c8SToby Isaac ierr = MPI_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 6576dd5a8c8SToby Isaac if (compress) { 6586dd5a8c8SToby Isaac PetscSection secComp; 6596dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6606dd5a8c8SToby Isaac 6616dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp);CHKERRQ(ierr); 6626dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secComp,pStart,pEnd);CHKERRQ(ierr); 6636dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6646dd5a8c8SToby Isaac PetscInt dof; 6656dd5a8c8SToby Isaac 6666dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6676dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secComp, p, dof);CHKERRQ(ierr); 6686dd5a8c8SToby Isaac } 6696dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secComp);CHKERRQ(ierr); 6706dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secComp,&sizeNew);CHKERRQ(ierr); 6716dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsComp);CHKERRQ(ierr); 6726dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6736dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6746dd5a8c8SToby Isaac 6756dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6766dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &off);CHKERRQ(ierr); 6776dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secComp, p, &offNew);CHKERRQ(ierr); 6786dd5a8c8SToby Isaac for (j = 0; j < dof; j++) { 6796dd5a8c8SToby Isaac valsComp[offNew + j] = valsNew[off + j]; 6806dd5a8c8SToby Isaac } 6816dd5a8c8SToby Isaac } 6826dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6836dd5a8c8SToby Isaac secNew = secComp; 6846dd5a8c8SToby Isaac ierr = PetscFree(valsNew);CHKERRQ(ierr); 6856dd5a8c8SToby Isaac valsNew = valsComp; 6866dd5a8c8SToby Isaac } 6876dd5a8c8SToby Isaac ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew);CHKERRQ(ierr); 6886dd5a8c8SToby Isaac } 6896dd5a8c8SToby Isaac PetscFunctionReturn(0); 6906dd5a8c8SToby Isaac } 6916dd5a8c8SToby Isaac 6926dd5a8c8SToby Isaac #undef __FUNCT__ 693f7c74593SToby Isaac #define __FUNCT__ "DMPlexCreateAnchors_Tree" 694f7c74593SToby Isaac static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 69566af876cSToby Isaac { 69666af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 69766af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 69866af876cSToby Isaac PetscSection aSec; 699f9f063d4SToby Isaac DMLabel canonLabel; 70066af876cSToby Isaac IS aIS; 70166af876cSToby Isaac PetscErrorCode ierr; 70266af876cSToby Isaac 70366af876cSToby Isaac PetscFunctionBegin; 70466af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 70566af876cSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 706f9f063d4SToby Isaac ierr = DMPlexGetLabel(dm,"canonical",&canonLabel);CHKERRQ(ierr); 70766af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 70866af876cSToby Isaac PetscInt parent; 70966af876cSToby Isaac 710f9f063d4SToby Isaac if (canonLabel) { 711f9f063d4SToby Isaac PetscInt canon; 712f9f063d4SToby Isaac 713f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 714f9f063d4SToby Isaac if (p != canon) continue; 715f9f063d4SToby Isaac } 71666af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 71766af876cSToby Isaac if (parent != p) { 71866af876cSToby Isaac aMin = PetscMin(aMin,p); 71966af876cSToby Isaac aMax = PetscMax(aMax,p+1); 72066af876cSToby Isaac } 72166af876cSToby Isaac } 72266af876cSToby Isaac if (aMin > aMax) { 72366af876cSToby Isaac aMin = -1; 72466af876cSToby Isaac aMax = -1; 72566af876cSToby Isaac } 726e228b242SToby Isaac ierr = PetscSectionCreate(PETSC_COMM_SELF,&aSec);CHKERRQ(ierr); 72766af876cSToby Isaac ierr = PetscSectionSetChart(aSec,aMin,aMax);CHKERRQ(ierr); 72866af876cSToby Isaac for (p = aMin; p < aMax; p++) { 72966af876cSToby Isaac PetscInt parent, ancestor = p; 73066af876cSToby Isaac 731f9f063d4SToby Isaac if (canonLabel) { 732f9f063d4SToby Isaac PetscInt canon; 733f9f063d4SToby Isaac 734f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 735f9f063d4SToby Isaac if (p != canon) continue; 736f9f063d4SToby Isaac } 73766af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 73866af876cSToby Isaac while (parent != ancestor) { 73966af876cSToby Isaac ancestor = parent; 74066af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 74166af876cSToby Isaac } 74266af876cSToby Isaac if (ancestor != p) { 74366af876cSToby Isaac PetscInt closureSize, *closure = NULL; 74466af876cSToby Isaac 74566af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 74666af876cSToby Isaac ierr = PetscSectionSetDof(aSec,p,closureSize);CHKERRQ(ierr); 74766af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 74866af876cSToby Isaac } 74966af876cSToby Isaac } 75066af876cSToby Isaac ierr = PetscSectionSetUp(aSec);CHKERRQ(ierr); 75166af876cSToby Isaac ierr = PetscSectionGetStorageSize(aSec,&size);CHKERRQ(ierr); 75266af876cSToby Isaac ierr = PetscMalloc1(size,&anchors);CHKERRQ(ierr); 75366af876cSToby Isaac for (p = aMin; p < aMax; p++) { 75466af876cSToby Isaac PetscInt parent, ancestor = p; 75566af876cSToby Isaac 756f9f063d4SToby Isaac if (canonLabel) { 757f9f063d4SToby Isaac PetscInt canon; 758f9f063d4SToby Isaac 759f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 760f9f063d4SToby Isaac if (p != canon) continue; 761f9f063d4SToby Isaac } 76266af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 76366af876cSToby Isaac while (parent != ancestor) { 76466af876cSToby Isaac ancestor = parent; 76566af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 76666af876cSToby Isaac } 76766af876cSToby Isaac if (ancestor != p) { 76866af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 76966af876cSToby Isaac 77066af876cSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 77166af876cSToby Isaac 77266af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 77366af876cSToby Isaac for (j = 0; j < closureSize; j++) { 77466af876cSToby Isaac anchors[aOff + j] = closure[2*j]; 77566af876cSToby Isaac } 77666af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 77766af876cSToby Isaac } 77866af876cSToby Isaac } 779e228b242SToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,size,anchors,PETSC_OWN_POINTER,&aIS);CHKERRQ(ierr); 7806dd5a8c8SToby Isaac { 7816dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7826dd5a8c8SToby Isaac IS aISNew = aIS; 7836dd5a8c8SToby Isaac 7846dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aSec);CHKERRQ(ierr); 7856dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aIS);CHKERRQ(ierr); 7866dd5a8c8SToby Isaac while (aSecNew) { 7876dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 7886dd5a8c8SToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 7896dd5a8c8SToby Isaac aSec = aSecNew; 7906dd5a8c8SToby Isaac aIS = aISNew; 7916dd5a8c8SToby Isaac aSecNew = NULL; 7926dd5a8c8SToby Isaac aISNew = NULL; 7936dd5a8c8SToby Isaac ierr = AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew);CHKERRQ(ierr); 7946dd5a8c8SToby Isaac } 7956dd5a8c8SToby Isaac } 796a17985deSToby Isaac ierr = DMPlexSetAnchors(dm,aSec,aIS);CHKERRQ(ierr); 79766af876cSToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 79866af876cSToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 79966af876cSToby Isaac PetscFunctionReturn(0); 80066af876cSToby Isaac } 80166af876cSToby Isaac 80266af876cSToby Isaac #undef __FUNCT__ 803776742edSToby Isaac #define __FUNCT__ "DMPlexTreeExchangeSupports" 804776742edSToby Isaac static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 805776742edSToby Isaac { 806776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 807776742edSToby Isaac PetscSection newSupportSection; 808776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 809776742edSToby Isaac PetscInt *offsets; 810776742edSToby Isaac PetscErrorCode ierr; 811776742edSToby Isaac 812776742edSToby Isaac PetscFunctionBegin; 813776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 814776742edSToby Isaac /* symmetrize the hierarchy */ 815776742edSToby Isaac ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 816e228b242SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)),&newSupportSection);CHKERRQ(ierr); 817776742edSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 818776742edSToby Isaac ierr = PetscSectionSetChart(newSupportSection,pStart,pEnd);CHKERRQ(ierr); 819776742edSToby Isaac ierr = PetscCalloc1(pEnd,&offsets);CHKERRQ(ierr); 820776742edSToby Isaac /* if a point is in the support of q, it should be in the support of 821776742edSToby Isaac * parent(q) */ 822776742edSToby Isaac for (d = 0; d <= depth; d++) { 823776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 824776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 825776742edSToby Isaac PetscInt dof, q, qdof, parent; 826776742edSToby Isaac 827776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 828776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection, p, dof);CHKERRQ(ierr); 829776742edSToby Isaac q = p; 830776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 831776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 832776742edSToby Isaac q = parent; 833776742edSToby Isaac 834776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, q, &qdof);CHKERRQ(ierr); 835776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,p,qdof);CHKERRQ(ierr); 836776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,q,dof);CHKERRQ(ierr); 837776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 838776742edSToby Isaac } 839776742edSToby Isaac } 840776742edSToby Isaac } 841776742edSToby Isaac ierr = PetscSectionSetUp(newSupportSection);CHKERRQ(ierr); 842776742edSToby Isaac ierr = PetscSectionGetStorageSize(newSupportSection,&newSize);CHKERRQ(ierr); 843776742edSToby Isaac ierr = PetscMalloc1(newSize,&newSupports);CHKERRQ(ierr); 844776742edSToby Isaac for (d = 0; d <= depth; d++) { 845776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 846776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 847776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 848776742edSToby Isaac 849776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 850776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 851776742edSToby Isaac ierr = PetscSectionGetDof(newSupportSection, p, &newDof);CHKERRQ(ierr); 852776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, p, &newOff);CHKERRQ(ierr); 853776742edSToby Isaac for (i = 0; i < dof; i++) { 854776742edSToby Isaac newSupports[newOff+offsets[p]++] = mesh->supports[off + i]; 855776742edSToby Isaac } 856776742edSToby Isaac mesh->maxSupportSize = PetscMax(mesh->maxSupportSize,newDof); 857776742edSToby Isaac 858776742edSToby Isaac q = p; 859776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 860776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 861776742edSToby Isaac q = parent; 862776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, q, &qdof);CHKERRQ(ierr); 863776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, q, &qoff);CHKERRQ(ierr); 864776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, q, &newqOff);CHKERRQ(ierr); 865776742edSToby Isaac for (i = 0; i < qdof; i++) { 866776742edSToby Isaac newSupports[newOff+offsets[p]++] = mesh->supports[qoff + i]; 867776742edSToby Isaac } 868776742edSToby Isaac for (i = 0; i < dof; i++) { 869776742edSToby Isaac newSupports[newqOff+offsets[q]++] = mesh->supports[off + i]; 870776742edSToby Isaac } 871776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 872776742edSToby Isaac } 873776742edSToby Isaac } 874776742edSToby Isaac } 875776742edSToby Isaac ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 876776742edSToby Isaac mesh->supportSection = newSupportSection; 877776742edSToby Isaac ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 878776742edSToby Isaac mesh->supports = newSupports; 879776742edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 880776742edSToby Isaac 881776742edSToby Isaac PetscFunctionReturn(0); 882776742edSToby Isaac } 883776742edSToby Isaac 884f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM,PetscSection,PetscSection,Mat); 885f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM,PetscSection,PetscSection,Mat); 886f7c74593SToby Isaac 887776742edSToby Isaac #undef __FUNCT__ 888f9f063d4SToby Isaac #define __FUNCT__ "DMPlexSetTree_Internal" 889776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 890f9f063d4SToby Isaac { 891f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 892f9f063d4SToby Isaac DM refTree; 893f9f063d4SToby Isaac PetscInt size; 894f9f063d4SToby Isaac PetscErrorCode ierr; 895f9f063d4SToby Isaac 896f9f063d4SToby Isaac PetscFunctionBegin; 897f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 898f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 899f9f063d4SToby Isaac ierr = PetscObjectReference((PetscObject)parentSection);CHKERRQ(ierr); 900f9f063d4SToby Isaac ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 901f9f063d4SToby Isaac mesh->parentSection = parentSection; 902f9f063d4SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&size);CHKERRQ(ierr); 903f9f063d4SToby Isaac if (parents != mesh->parents) { 904f9f063d4SToby Isaac ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 905f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->parents);CHKERRQ(ierr); 906f9f063d4SToby Isaac ierr = PetscMemcpy(mesh->parents, parents, size * sizeof(*parents));CHKERRQ(ierr); 907f9f063d4SToby Isaac } 908f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 909f9f063d4SToby Isaac ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 910f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->childIDs);CHKERRQ(ierr); 911f9f063d4SToby Isaac ierr = PetscMemcpy(mesh->childIDs, childIDs, size * sizeof(*childIDs));CHKERRQ(ierr); 912f9f063d4SToby Isaac } 913f9f063d4SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 914f9f063d4SToby Isaac if (refTree) { 915f9f063d4SToby Isaac DMLabel canonLabel; 916f9f063d4SToby Isaac 917f9f063d4SToby Isaac ierr = DMPlexGetLabel(refTree,"canonical",&canonLabel);CHKERRQ(ierr); 918f9f063d4SToby Isaac if (canonLabel) { 919f9f063d4SToby Isaac PetscInt i; 920f9f063d4SToby Isaac 921f9f063d4SToby Isaac for (i = 0; i < size; i++) { 922f9f063d4SToby Isaac PetscInt canon; 923f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon);CHKERRQ(ierr); 924f9f063d4SToby Isaac if (canon >= 0) { 925f9f063d4SToby Isaac mesh->childIDs[i] = canon; 926f9f063d4SToby Isaac } 927f9f063d4SToby Isaac } 928f9f063d4SToby Isaac } 929f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 930f7c74593SToby Isaac } 931f7c74593SToby Isaac else { 932f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 933f9f063d4SToby Isaac } 934f9f063d4SToby Isaac ierr = DMPlexTreeSymmetrize(dm);CHKERRQ(ierr); 935f9f063d4SToby Isaac if (computeCanonical) { 936f9f063d4SToby Isaac PetscInt d, dim; 937f9f063d4SToby Isaac 938f9f063d4SToby Isaac /* add the canonical label */ 93928f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 940f9f063d4SToby Isaac ierr = DMPlexCreateLabel(dm,"canonical");CHKERRQ(ierr); 941f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 942f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 943f9f063d4SToby Isaac const PetscInt *cChildren; 944f9f063d4SToby Isaac 945f9f063d4SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 946f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 947f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&cNumChildren,&cChildren);CHKERRQ(ierr); 948f9f063d4SToby Isaac if (cNumChildren) { 949f9f063d4SToby Isaac canon = p; 950f9f063d4SToby Isaac break; 951f9f063d4SToby Isaac } 952f9f063d4SToby Isaac } 953f9f063d4SToby Isaac if (canon == -1) continue; 954f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 955f9f063d4SToby Isaac PetscInt numChildren, i; 956f9f063d4SToby Isaac const PetscInt *children; 957f9f063d4SToby Isaac 958f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&numChildren,&children);CHKERRQ(ierr); 959f9f063d4SToby Isaac if (numChildren) { 960f9f063d4SToby 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); 961f9f063d4SToby Isaac ierr = DMPlexSetLabelValue(dm,"canonical",p,canon);CHKERRQ(ierr); 962f9f063d4SToby Isaac for (i = 0; i < numChildren; i++) { 963f9f063d4SToby Isaac ierr = DMPlexSetLabelValue(dm,"canonical",children[i],cChildren[i]);CHKERRQ(ierr); 964f9f063d4SToby Isaac } 965f9f063d4SToby Isaac } 966f9f063d4SToby Isaac } 967f9f063d4SToby Isaac } 968f9f063d4SToby Isaac } 969776742edSToby Isaac if (exchangeSupports) { 970776742edSToby Isaac ierr = DMPlexTreeExchangeSupports(dm);CHKERRQ(ierr); 971776742edSToby Isaac } 972f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 973f7c74593SToby Isaac /* reset anchors */ 974f7c74593SToby Isaac ierr = DMPlexSetAnchors(dm,NULL,NULL);CHKERRQ(ierr); 975f9f063d4SToby Isaac PetscFunctionReturn(0); 976f9f063d4SToby Isaac } 977f9f063d4SToby Isaac 978f9f063d4SToby Isaac #undef __FUNCT__ 9790b7167a0SToby Isaac #define __FUNCT__ "DMPlexSetTree" 9800b7167a0SToby Isaac /*@ 9810b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 9820b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 9830b7167a0SToby Isaac tree root. 9840b7167a0SToby Isaac 9850b7167a0SToby Isaac Collective on dm 9860b7167a0SToby Isaac 9870b7167a0SToby Isaac Input Parameters: 9880b7167a0SToby Isaac + dm - the DMPlex object 9890b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 9900b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 9910b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 9920b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 9930b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 9940b7167a0SToby Isaac 9950b7167a0SToby Isaac Level: intermediate 9960b7167a0SToby Isaac 997a17985deSToby Isaac .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 9980b7167a0SToby Isaac @*/ 999b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 10000b7167a0SToby Isaac { 10010b7167a0SToby Isaac PetscErrorCode ierr; 10020b7167a0SToby Isaac 10030b7167a0SToby Isaac PetscFunctionBegin; 1004776742edSToby Isaac ierr = DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 10050b7167a0SToby Isaac PetscFunctionReturn(0); 10060b7167a0SToby Isaac } 10070b7167a0SToby Isaac 10080b7167a0SToby Isaac #undef __FUNCT__ 1009b2f41788SToby Isaac #define __FUNCT__ "DMPlexGetTree" 1010b2f41788SToby Isaac /*@ 1011b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 1012b2f41788SToby Isaac Collective on dm 1013b2f41788SToby Isaac 1014b2f41788SToby Isaac Input Parameters: 1015b2f41788SToby Isaac . dm - the DMPlex object 1016b2f41788SToby Isaac 1017b2f41788SToby Isaac Output Parameters: 1018b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1019b2f41788SToby Isaac offset indexes the parent and childID list 1020b2f41788SToby Isaac . parents - a list of the point parents 1021b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1022b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1023b2f41788SToby Isaac . childSection - the inverse of the parent section 1024b2f41788SToby Isaac - children - a list of the point children 1025b2f41788SToby Isaac 1026b2f41788SToby Isaac Level: intermediate 1027b2f41788SToby Isaac 1028a17985deSToby Isaac .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 1029b2f41788SToby Isaac @*/ 1030b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1031b2f41788SToby Isaac { 1032b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1033b2f41788SToby Isaac 1034b2f41788SToby Isaac PetscFunctionBegin; 1035b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1036b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1037b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1038b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1039b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1040b2f41788SToby Isaac if (children) *children = mesh->children; 1041b2f41788SToby Isaac PetscFunctionReturn(0); 1042b2f41788SToby Isaac } 1043b2f41788SToby Isaac 1044b2f41788SToby Isaac #undef __FUNCT__ 1045d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeParent" 1046d961a43aSToby Isaac /*@ 1047d961a43aSToby Isaac DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the Sieve DAG) 1048d961a43aSToby Isaac 1049d961a43aSToby Isaac Input Parameters: 1050d961a43aSToby Isaac + dm - the DMPlex object 1051d961a43aSToby Isaac - point - the query point 1052d961a43aSToby Isaac 1053d961a43aSToby Isaac Output Parameters: 1054d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 1055d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 1056d961a43aSToby Isaac does not have a parent 1057d961a43aSToby Isaac 1058d961a43aSToby Isaac Level: intermediate 1059d961a43aSToby Isaac 1060d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren() 1061d961a43aSToby Isaac @*/ 1062d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1063d961a43aSToby Isaac { 1064d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1065d961a43aSToby Isaac PetscSection pSec; 1066d961a43aSToby Isaac PetscErrorCode ierr; 1067d961a43aSToby Isaac 1068d961a43aSToby Isaac PetscFunctionBegin; 1069d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1070d961a43aSToby Isaac pSec = mesh->parentSection; 1071d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1072d961a43aSToby Isaac PetscInt dof; 1073d961a43aSToby Isaac 1074d961a43aSToby Isaac ierr = PetscSectionGetDof (pSec, point, &dof);CHKERRQ(ierr); 1075d961a43aSToby Isaac if (dof) { 1076d961a43aSToby Isaac PetscInt off; 1077d961a43aSToby Isaac 1078d961a43aSToby Isaac ierr = PetscSectionGetOffset (pSec, point, &off);CHKERRQ(ierr); 1079d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1080d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 1081d961a43aSToby Isaac PetscFunctionReturn(0); 1082d961a43aSToby Isaac } 1083d961a43aSToby Isaac } 1084d961a43aSToby Isaac if (parent) { 1085d961a43aSToby Isaac *parent = point; 1086d961a43aSToby Isaac } 1087d961a43aSToby Isaac if (childID) { 1088d961a43aSToby Isaac *childID = 0; 1089d961a43aSToby Isaac } 1090d961a43aSToby Isaac PetscFunctionReturn(0); 1091d961a43aSToby Isaac } 1092d961a43aSToby Isaac 1093d961a43aSToby Isaac #undef __FUNCT__ 1094d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeChildren" 1095d961a43aSToby Isaac /*@C 1096d961a43aSToby Isaac DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the Sieve DAG) 1097d961a43aSToby Isaac 1098d961a43aSToby Isaac Input Parameters: 1099d961a43aSToby Isaac + dm - the DMPlex object 1100d961a43aSToby Isaac - point - the query point 1101d961a43aSToby Isaac 1102d961a43aSToby Isaac Output Parameters: 1103d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 1104d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 1105d961a43aSToby Isaac 1106d961a43aSToby Isaac Level: intermediate 1107d961a43aSToby Isaac 1108d961a43aSToby Isaac Fortran Notes: 1109d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1110d961a43aSToby Isaac include petsc.h90 in your code. 1111d961a43aSToby Isaac 1112d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent() 1113d961a43aSToby Isaac @*/ 1114d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1115d961a43aSToby Isaac { 1116d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1117d961a43aSToby Isaac PetscSection childSec; 1118d961a43aSToby Isaac PetscInt dof = 0; 1119d961a43aSToby Isaac PetscErrorCode ierr; 1120d961a43aSToby Isaac 1121d961a43aSToby Isaac PetscFunctionBegin; 1122d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1123d961a43aSToby Isaac childSec = mesh->childSection; 1124d961a43aSToby Isaac if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 1125d961a43aSToby Isaac ierr = PetscSectionGetDof (childSec, point, &dof);CHKERRQ(ierr); 1126d961a43aSToby Isaac } 1127d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1128d961a43aSToby Isaac if (children) { 1129d961a43aSToby Isaac if (dof) { 1130d961a43aSToby Isaac PetscInt off; 1131d961a43aSToby Isaac 1132d961a43aSToby Isaac ierr = PetscSectionGetOffset (childSec, point, &off);CHKERRQ(ierr); 1133d961a43aSToby Isaac *children = &mesh->children[off]; 1134d961a43aSToby Isaac } 1135d961a43aSToby Isaac else { 1136d961a43aSToby Isaac *children = NULL; 1137d961a43aSToby Isaac } 1138d961a43aSToby Isaac } 1139d961a43aSToby Isaac PetscFunctionReturn(0); 1140d961a43aSToby Isaac } 11410c37af3bSToby Isaac 11420c37af3bSToby Isaac #undef __FUNCT__ 1143f7c74593SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_Direct" 1144f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 11450c37af3bSToby Isaac { 11460c37af3bSToby Isaac PetscDS ds; 11470c37af3bSToby Isaac PetscInt spdim; 11480c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 11490c37af3bSToby Isaac const PetscInt *anchors; 1150f7c74593SToby Isaac PetscSection aSec; 11510c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 11520c37af3bSToby Isaac IS aIS; 11530c37af3bSToby Isaac PetscErrorCode ierr; 11540c37af3bSToby Isaac 11550c37af3bSToby Isaac PetscFunctionBegin; 11560c37af3bSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 11570c37af3bSToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 11580c37af3bSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 11590c37af3bSToby Isaac ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 1160a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 11610c37af3bSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 11620c37af3bSToby Isaac ierr = PetscSectionGetChart(cSec,&conStart,&conEnd);CHKERRQ(ierr); 116328f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&spdim);CHKERRQ(ierr); 11640c37af3bSToby Isaac ierr = PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent);CHKERRQ(ierr); 11650c37af3bSToby Isaac 11660c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 1167*0dd1b1feSToby Isaac PetscObject disc; 1168*0dd1b1feSToby Isaac PetscFE fe = NULL; 1169*0dd1b1feSToby Isaac PetscFV fv = NULL; 1170*0dd1b1feSToby Isaac PetscClassId id; 11710c37af3bSToby Isaac PetscDualSpace space; 11720c37af3bSToby Isaac PetscInt i, j, k, nPoints, offset; 11730c37af3bSToby Isaac PetscInt fSize, fComp; 1174c111c6b7SMatthew G. Knepley PetscReal *B = NULL; 11750c37af3bSToby Isaac PetscReal *weights, *pointsRef, *pointsReal; 11760c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 11770c37af3bSToby Isaac 1178*0dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 1179*0dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 1180*0dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1181*0dd1b1feSToby Isaac fe = (PetscFE) disc; 11820c37af3bSToby Isaac ierr = PetscFEGetDualSpace(fe,&space);CHKERRQ(ierr); 11830c37af3bSToby Isaac ierr = PetscDualSpaceGetDimension(space,&fSize);CHKERRQ(ierr); 11840c37af3bSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 1185*0dd1b1feSToby Isaac } 1186*0dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 1187*0dd1b1feSToby Isaac fv = (PetscFV) disc; 1188*0dd1b1feSToby Isaac ierr = PetscFVGetDualSpace(fv,&space);CHKERRQ(ierr); 1189*0dd1b1feSToby Isaac ierr = PetscDualSpaceGetDimension(space,&fSize);CHKERRQ(ierr); 1190*0dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 1191*0dd1b1feSToby Isaac } 1192*0dd1b1feSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 1193*0dd1b1feSToby Isaac 11940c37af3bSToby Isaac ierr = MatCreate(PETSC_COMM_SELF,&Amat);CHKERRQ(ierr); 11950c37af3bSToby Isaac ierr = MatSetSizes(Amat,fSize,fSize,fSize,fSize);CHKERRQ(ierr); 11960c37af3bSToby Isaac ierr = MatSetType(Amat,MATSEQDENSE);CHKERRQ(ierr); 11970c37af3bSToby Isaac ierr = MatSetUp(Amat);CHKERRQ(ierr); 11980c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat);CHKERRQ(ierr); 11990c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat);CHKERRQ(ierr); 12000c37af3bSToby Isaac nPoints = 0; 12010c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12020c37af3bSToby Isaac PetscInt qPoints; 12030c37af3bSToby Isaac PetscQuadrature quad; 12040c37af3bSToby Isaac 12050c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 12060c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 12070c37af3bSToby Isaac nPoints += qPoints; 12080c37af3bSToby Isaac } 12090c37af3bSToby Isaac ierr = PetscMalloc3(nPoints,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal);CHKERRQ(ierr); 12100c37af3bSToby Isaac offset = 0; 12110c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12120c37af3bSToby Isaac PetscInt qPoints; 12130c37af3bSToby Isaac const PetscReal *p, *w; 12140c37af3bSToby Isaac PetscQuadrature quad; 12150c37af3bSToby Isaac 12160c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 12170c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,&p,&w);CHKERRQ(ierr); 12180c37af3bSToby Isaac ierr = PetscMemcpy(weights+offset,w,qPoints*sizeof(*w));CHKERRQ(ierr); 12190c37af3bSToby Isaac ierr = PetscMemcpy(pointsRef+spdim*offset,p,spdim*qPoints*sizeof(*p));CHKERRQ(ierr); 12200c37af3bSToby Isaac offset += qPoints; 12210c37af3bSToby Isaac } 1222*0dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 12230c37af3bSToby Isaac ierr = PetscFEGetTabulation(fe,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 1224*0dd1b1feSToby Isaac } 1225*0dd1b1feSToby Isaac else { 1226*0dd1b1feSToby Isaac ierr = PetscFVGetTabulation(fv,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 1227*0dd1b1feSToby Isaac } 12280c37af3bSToby Isaac offset = 0; 12290c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12300c37af3bSToby Isaac PetscInt qPoints; 12310c37af3bSToby Isaac PetscQuadrature quad; 12320c37af3bSToby Isaac 12330c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 12340c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 12350c37af3bSToby Isaac for (j = 0; j < fSize; j++) { 12360c37af3bSToby Isaac PetscScalar val = 0.; 12370c37af3bSToby Isaac 12380c37af3bSToby Isaac for (k = 0; k < qPoints; k++) { 12390c37af3bSToby Isaac val += B[((offset + k) * fSize + j) * fComp] * weights[k]; 12400c37af3bSToby Isaac } 12410c37af3bSToby Isaac ierr = MatSetValue(Amat,i,j,val,INSERT_VALUES);CHKERRQ(ierr); 12420c37af3bSToby Isaac } 12430c37af3bSToby Isaac offset += qPoints; 12440c37af3bSToby Isaac } 1245*0dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 12460c37af3bSToby Isaac ierr = PetscFERestoreTabulation(fe,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 1247*0dd1b1feSToby Isaac } 1248*0dd1b1feSToby Isaac else { 1249*0dd1b1feSToby Isaac ierr = PetscFVRestoreTabulation(fv,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 1250*0dd1b1feSToby Isaac } 12510c37af3bSToby Isaac ierr = MatAssemblyBegin(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 12520c37af3bSToby Isaac ierr = MatAssemblyEnd(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 12530c37af3bSToby Isaac ierr = MatLUFactor(Amat,NULL,NULL,NULL);CHKERRQ(ierr); 12540c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 12550c37af3bSToby Isaac PetscInt parent; 12560c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 12570c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 12580c37af3bSToby Isaac 12590c37af3bSToby Isaac ierr = DMPlexGetTreeParent(dm,c,&parent,NULL);CHKERRQ(ierr); 12600c37af3bSToby Isaac if (parent == c) continue; 12610c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 12620c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 12630c37af3bSToby Isaac PetscInt p = closure[2*i]; 12640c37af3bSToby Isaac PetscInt conDof; 12650c37af3bSToby Isaac 12660c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 12670c37af3bSToby Isaac if (numFields > 1) { 12680c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 12690c37af3bSToby Isaac } 12700c37af3bSToby Isaac else { 12710c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 12720c37af3bSToby Isaac } 12730c37af3bSToby Isaac if (conDof) break; 12740c37af3bSToby Isaac } 12750c37af3bSToby Isaac if (i == closureSize) { 12760c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 12770c37af3bSToby Isaac continue; 12780c37af3bSToby Isaac } 12790c37af3bSToby Isaac 128073a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 128173a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent);CHKERRQ(ierr); 12820c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 12830c37af3bSToby Isaac CoordinatesRefToReal(spdim, spdim, v0, J, &pointsRef[i*spdim],vtmp);CHKERRQ(ierr); 12840c37af3bSToby Isaac CoordinatesRealToRef(spdim, spdim, v0parent, invJparent, vtmp, &pointsReal[i*spdim]);CHKERRQ(ierr); 12850c37af3bSToby Isaac } 1286*0dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 12870c37af3bSToby Isaac ierr = PetscFEGetTabulation(fe,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 1288*0dd1b1feSToby Isaac } 1289*0dd1b1feSToby Isaac else { 1290*0dd1b1feSToby Isaac ierr = PetscFVGetTabulation(fv,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 1291*0dd1b1feSToby Isaac } 12920c37af3bSToby Isaac offset = 0; 12930c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12940c37af3bSToby Isaac PetscInt qPoints; 12950c37af3bSToby Isaac PetscQuadrature quad; 12960c37af3bSToby Isaac 12970c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 12980c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 12990c37af3bSToby Isaac for (j = 0; j < fSize; j++) { 13000c37af3bSToby Isaac PetscScalar val = 0.; 13010c37af3bSToby Isaac 13020c37af3bSToby Isaac for (k = 0; k < qPoints; k++) { 13030c37af3bSToby Isaac val += B[((offset + k) * fSize + j) * fComp] * weights[k]; 13040c37af3bSToby Isaac } 13050c37af3bSToby Isaac MatSetValue(Bmat,i,j,val,INSERT_VALUES);CHKERRQ(ierr); 13060c37af3bSToby Isaac } 13070c37af3bSToby Isaac offset += qPoints; 13080c37af3bSToby Isaac } 1309*0dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 13100c37af3bSToby Isaac ierr = PetscFERestoreTabulation(fe,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 1311*0dd1b1feSToby Isaac } 1312*0dd1b1feSToby Isaac else { 1313*0dd1b1feSToby Isaac ierr = PetscFVRestoreTabulation(fv,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 1314*0dd1b1feSToby Isaac } 13150c37af3bSToby Isaac ierr = MatAssemblyBegin(Bmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 13160c37af3bSToby Isaac ierr = MatAssemblyEnd(Bmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 13170c37af3bSToby Isaac ierr = MatMatSolve(Amat,Bmat,Xmat);CHKERRQ(ierr); 13180c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 13190c37af3bSToby Isaac ierr = PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets);CHKERRQ(ierr); 13200c37af3bSToby Isaac childOffsets[0] = 0; 13210c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13220c37af3bSToby Isaac PetscInt p = closure[2*i]; 13230c37af3bSToby Isaac PetscInt dof; 13240c37af3bSToby Isaac 13250c37af3bSToby Isaac if (numFields > 1) { 13260c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 13270c37af3bSToby Isaac } 13280c37af3bSToby Isaac else { 13290c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 13300c37af3bSToby Isaac } 13310c37af3bSToby Isaac childOffsets[i+1]=childOffsets[i]+dof / fComp; 13320c37af3bSToby Isaac } 13330c37af3bSToby Isaac parentOffsets[0] = 0; 13340c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 13350c37af3bSToby Isaac PetscInt p = closureP[2*i]; 13360c37af3bSToby Isaac PetscInt dof; 13370c37af3bSToby Isaac 13380c37af3bSToby Isaac if (numFields > 1) { 13390c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 13400c37af3bSToby Isaac } 13410c37af3bSToby Isaac else { 13420c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 13430c37af3bSToby Isaac } 13440c37af3bSToby Isaac parentOffsets[i+1]=parentOffsets[i]+dof / fComp; 13450c37af3bSToby Isaac } 13460c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13470c37af3bSToby Isaac PetscInt conDof, conOff, aDof, aOff; 13480c37af3bSToby Isaac PetscInt p = closure[2*i]; 13490c37af3bSToby Isaac PetscInt o = closure[2*i+1]; 13500c37af3bSToby Isaac 13510c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 13520c37af3bSToby Isaac if (numFields > 1) { 13530c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 13540c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(cSec,p,f,&conOff);CHKERRQ(ierr); 13550c37af3bSToby Isaac } 13560c37af3bSToby Isaac else { 13570c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 13580c37af3bSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&conOff);CHKERRQ(ierr); 13590c37af3bSToby Isaac } 13600c37af3bSToby Isaac if (!conDof) continue; 13610c37af3bSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 13620c37af3bSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 13630c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 13640c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 13650c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 13660c37af3bSToby Isaac 13670c37af3bSToby Isaac if (numFields > 1) { 13680c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,a,f,&aSecDof);CHKERRQ(ierr); 13690c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(section,a,f,&aSecOff);CHKERRQ(ierr); 13700c37af3bSToby Isaac } 13710c37af3bSToby Isaac else { 13720c37af3bSToby Isaac ierr = PetscSectionGetDof(section,a,&aSecDof);CHKERRQ(ierr); 13730c37af3bSToby Isaac ierr = PetscSectionGetOffset(section,a,&aSecOff);CHKERRQ(ierr); 13740c37af3bSToby Isaac } 13750c37af3bSToby Isaac if (!aSecDof) continue; 13760c37af3bSToby Isaac 13770c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 13780c37af3bSToby Isaac PetscInt q = closureP[2*j]; 13790c37af3bSToby Isaac PetscInt oq = closureP[2*j+1]; 13800c37af3bSToby Isaac 13810c37af3bSToby Isaac if (q == a) { 13820c37af3bSToby Isaac PetscInt r, s, t; 13830c37af3bSToby Isaac 13840c37af3bSToby Isaac for (r = childOffsets[i]; r < childOffsets[i+1]; r++) { 13850c37af3bSToby Isaac for (s = parentOffsets[j]; s < parentOffsets[j+1]; s++) { 13860c37af3bSToby Isaac PetscScalar val; 13870c37af3bSToby Isaac PetscInt insertCol, insertRow; 13880c37af3bSToby Isaac 13890c37af3bSToby Isaac ierr = MatGetValue(Xmat,r,s,&val);CHKERRQ(ierr); 13900c37af3bSToby Isaac if (o >= 0) { 13910c37af3bSToby Isaac insertRow = conOff + fComp * (r - childOffsets[i]); 13920c37af3bSToby Isaac } 13930c37af3bSToby Isaac else { 13940c37af3bSToby Isaac insertRow = conOff + fComp * (childOffsets[i + 1] - 1 - r); 13950c37af3bSToby Isaac } 13960c37af3bSToby Isaac if (oq >= 0) { 13970c37af3bSToby Isaac insertCol = aSecOff + fComp * (s - parentOffsets[j]); 13980c37af3bSToby Isaac } 13990c37af3bSToby Isaac else { 14000c37af3bSToby Isaac insertCol = aSecOff + fComp * (parentOffsets[j + 1] - 1 - s); 14010c37af3bSToby Isaac } 14020c37af3bSToby Isaac for (t = 0; t < fComp; t++) { 14030c37af3bSToby Isaac ierr = MatSetValue(cMat,insertRow + t,insertCol + t,val,INSERT_VALUES);CHKERRQ(ierr); 14040c37af3bSToby Isaac } 14050c37af3bSToby Isaac } 14060c37af3bSToby Isaac } 14070c37af3bSToby Isaac } 14080c37af3bSToby Isaac } 14090c37af3bSToby Isaac } 14100c37af3bSToby Isaac } 14110c37af3bSToby Isaac ierr = PetscFree2(childOffsets,parentOffsets);CHKERRQ(ierr); 14120c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 14130c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 14140c37af3bSToby Isaac } 14150c37af3bSToby Isaac ierr = MatDestroy(&Amat);CHKERRQ(ierr); 14160c37af3bSToby Isaac ierr = MatDestroy(&Bmat);CHKERRQ(ierr); 14170c37af3bSToby Isaac ierr = MatDestroy(&Xmat);CHKERRQ(ierr); 14180c37af3bSToby Isaac ierr = PetscFree3(weights,pointsRef,pointsReal);CHKERRQ(ierr); 14190c37af3bSToby Isaac } 14200c37af3bSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14210c37af3bSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14220c37af3bSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent);CHKERRQ(ierr); 14230c37af3bSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 14240c37af3bSToby Isaac 14250c37af3bSToby Isaac PetscFunctionReturn(0); 14260c37af3bSToby Isaac } 142795a0b26dSToby Isaac 142895a0b26dSToby Isaac #undef __FUNCT__ 1429f7c74593SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_FromReference" 1430f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 143195a0b26dSToby Isaac { 143295a0b26dSToby Isaac DM refTree; 143395a0b26dSToby Isaac PetscDS ds; 1434f7c74593SToby Isaac Mat refCmat; 143595a0b26dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 143695a0b26dSToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 1437f7c74593SToby Isaac PetscSection refConSec, refAnSec, anSec, refSection; 143895a0b26dSToby Isaac IS refAnIS, anIS; 143995a0b26dSToby Isaac const PetscInt *refAnchors, *anchors; 144095a0b26dSToby Isaac PetscErrorCode ierr; 144195a0b26dSToby Isaac 144295a0b26dSToby Isaac PetscFunctionBegin; 144395a0b26dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 144495a0b26dSToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 144595a0b26dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 144695a0b26dSToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 144795a0b26dSToby Isaac ierr = DMSetDS(refTree,ds);CHKERRQ(ierr); 1448f7c74593SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 144995a0b26dSToby Isaac ierr = DMPlexGetChart(refTree,&pRefStart,&pRefEnd);CHKERRQ(ierr); 1450a17985deSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 1451a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&anSec,&anIS);CHKERRQ(ierr); 145295a0b26dSToby Isaac ierr = ISGetIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 145395a0b26dSToby Isaac ierr = ISGetIndices(anIS,&anchors);CHKERRQ(ierr); 145495a0b26dSToby Isaac ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr); 145595a0b26dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 145695a0b26dSToby Isaac ierr = PetscSectionGetChart(conSec,&conStart,&conEnd);CHKERRQ(ierr); 145795a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr); 145895a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldN);CHKERRQ(ierr); 145995a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 146095a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 146195a0b26dSToby Isaac ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr); 146295a0b26dSToby Isaac ierr = PetscMalloc1(maxDof*maxAnDof,&cols);CHKERRQ(ierr); 146395a0b26dSToby Isaac ierr = PetscMalloc1(maxDof*maxDof*maxAnDof,&pointWork);CHKERRQ(ierr); 146495a0b26dSToby Isaac 146595a0b26dSToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 146695a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 146795a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 146895a0b26dSToby Isaac 146995a0b26dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 147095a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 147195a0b26dSToby Isaac if (!pDof || parent == p) continue; 147295a0b26dSToby Isaac 147395a0b26dSToby Isaac ierr = PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr); 147495a0b26dSToby Isaac ierr = PetscCalloc1(numFields,&refPointFieldN[p-pRefStart]);CHKERRQ(ierr); 147595a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 147695a0b26dSToby Isaac for (f = 0; f < numFields; f++) { 147795a0b26dSToby Isaac PetscInt cDof, cOff, numCols, r, i, fComp; 1478*0dd1b1feSToby Isaac PetscObject disc; 1479*0dd1b1feSToby Isaac PetscClassId id; 1480*0dd1b1feSToby Isaac PetscFE fe = NULL; 1481*0dd1b1feSToby Isaac PetscFV fv = NULL; 148295a0b26dSToby Isaac 1483*0dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 1484*0dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 1485*0dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1486*0dd1b1feSToby Isaac fe = (PetscFE) disc; 148795a0b26dSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 1488*0dd1b1feSToby Isaac } 1489*0dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 1490*0dd1b1feSToby Isaac fv = (PetscFV) disc; 1491*0dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 1492*0dd1b1feSToby Isaac } 1493*0dd1b1feSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 149495a0b26dSToby Isaac 149595a0b26dSToby Isaac if (numFields > 1) { 149695a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 149795a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr); 149895a0b26dSToby Isaac } 149995a0b26dSToby Isaac else { 150095a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 150195a0b26dSToby Isaac ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr); 150295a0b26dSToby Isaac } 150395a0b26dSToby Isaac 150495a0b26dSToby Isaac if (!cDof) continue; 150595a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 150695a0b26dSToby Isaac rows[r] = cOff + r; 150795a0b26dSToby Isaac } 150895a0b26dSToby Isaac numCols = 0; 150995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 151095a0b26dSToby Isaac PetscInt q = closure[2*i]; 151195a0b26dSToby Isaac PetscInt o = closure[2*i+1]; 151295a0b26dSToby Isaac PetscInt aDof, aOff, j; 151395a0b26dSToby Isaac 151495a0b26dSToby Isaac if (numFields > 1) { 151595a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refSection,q,f,&aDof);CHKERRQ(ierr); 151695a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,q,f,&aOff);CHKERRQ(ierr); 151795a0b26dSToby Isaac } 151895a0b26dSToby Isaac else { 151995a0b26dSToby Isaac ierr = PetscSectionGetDof(refSection,q,&aDof);CHKERRQ(ierr); 152095a0b26dSToby Isaac ierr = PetscSectionGetOffset(refSection,q,&aOff);CHKERRQ(ierr); 152195a0b26dSToby Isaac } 152295a0b26dSToby Isaac 152395a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 152495a0b26dSToby Isaac PetscInt node = (o >= 0) ? (j / fComp) : ((aDof - 1 - j) / fComp); 152595a0b26dSToby Isaac PetscInt comp = (j % fComp); 152695a0b26dSToby Isaac 152795a0b26dSToby Isaac cols[numCols++] = aOff + node * fComp + comp; 152895a0b26dSToby Isaac } 152995a0b26dSToby Isaac } 153095a0b26dSToby Isaac refPointFieldN[p-pRefStart][f] = numCols; 153195a0b26dSToby Isaac ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 153295a0b26dSToby Isaac ierr = MatGetValues(refCmat,cDof,rows,numCols,cols,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 153395a0b26dSToby Isaac } 153495a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 153595a0b26dSToby Isaac } 153695a0b26dSToby Isaac 153795a0b26dSToby Isaac /* step 2: compute the preorder */ 153895a0b26dSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 153995a0b26dSToby Isaac ierr = PetscMalloc2(pEnd-pStart,&perm,pEnd-pStart,&iperm);CHKERRQ(ierr); 154095a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 154195a0b26dSToby Isaac perm[p - pStart] = p; 154295a0b26dSToby Isaac iperm[p - pStart] = p-pStart; 154395a0b26dSToby Isaac } 154495a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 154595a0b26dSToby Isaac PetscInt point = perm[p]; 154695a0b26dSToby Isaac PetscInt parent; 154795a0b26dSToby Isaac 154895a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 154995a0b26dSToby Isaac if (parent == point) { 155095a0b26dSToby Isaac p++; 155195a0b26dSToby Isaac } 155295a0b26dSToby Isaac else { 155395a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 155495a0b26dSToby Isaac 155595a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 155695a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 155795a0b26dSToby Isaac PetscInt q = closure[2*i]; 155895a0b26dSToby Isaac if (iperm[q-pStart] > iperm[point-pStart]) { 155995a0b26dSToby Isaac /* swap */ 156095a0b26dSToby Isaac perm[p] = q; 156195a0b26dSToby Isaac perm[iperm[q-pStart]] = point; 156295a0b26dSToby Isaac iperm[point-pStart] = iperm[q-pStart]; 156395a0b26dSToby Isaac iperm[q-pStart] = p; 156495a0b26dSToby Isaac break; 156595a0b26dSToby Isaac } 156695a0b26dSToby Isaac } 156795a0b26dSToby Isaac size = closureSize; 156895a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 156995a0b26dSToby Isaac if (i == size) { 157095a0b26dSToby Isaac p++; 157195a0b26dSToby Isaac } 157295a0b26dSToby Isaac } 157395a0b26dSToby Isaac } 157495a0b26dSToby Isaac 157595a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 157695a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 157795a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 157895a0b26dSToby Isaac * values outside of the Mat first. 157995a0b26dSToby Isaac */ 158095a0b26dSToby Isaac { 158195a0b26dSToby Isaac PetscInt nRows, row, nnz; 158295a0b26dSToby Isaac PetscBool done; 158395a0b26dSToby Isaac const PetscInt *ia, *ja; 158495a0b26dSToby Isaac PetscScalar *vals; 158595a0b26dSToby Isaac 158695a0b26dSToby Isaac ierr = MatGetRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 158795a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not get RowIJ of constraint matrix"); 158895a0b26dSToby Isaac nnz = ia[nRows]; 158995a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 159095a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 159195a0b26dSToby Isaac ierr = PetscMalloc1(nnz,&vals);CHKERRQ(ierr); 159295a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 159395a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 159495a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 159595a0b26dSToby Isaac 159695a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,&childid);CHKERRQ(ierr); 159795a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 159895a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&pointDof);CHKERRQ(ierr); 159995a0b26dSToby Isaac if (!pointDof) continue; 160095a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 160195a0b26dSToby Isaac for (f = 0; f < numFields; f++) { 160295a0b26dSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, fComp, matOffset, offset; 160395a0b26dSToby Isaac PetscScalar *pointMat; 1604*0dd1b1feSToby Isaac PetscObject disc; 1605*0dd1b1feSToby Isaac PetscClassId id; 1606*0dd1b1feSToby Isaac PetscFE fe = NULL; 1607*0dd1b1feSToby Isaac PetscFV fv = NULL; 160895a0b26dSToby Isaac 1609*0dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 1610*0dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 1611*0dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1612*0dd1b1feSToby Isaac fe = (PetscFE) disc; 161395a0b26dSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 1614*0dd1b1feSToby Isaac } 1615*0dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 1616*0dd1b1feSToby Isaac fv = (PetscFV) disc; 1617*0dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 1618*0dd1b1feSToby Isaac } 161995a0b26dSToby Isaac 162095a0b26dSToby Isaac if (numFields > 1) { 162195a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,point,f,&cDof);CHKERRQ(ierr); 162295a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,point,f,&cOff);CHKERRQ(ierr); 162395a0b26dSToby Isaac } 162495a0b26dSToby Isaac else { 162595a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&cDof);CHKERRQ(ierr); 162695a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,point,&cOff);CHKERRQ(ierr); 162795a0b26dSToby Isaac } 162895a0b26dSToby Isaac if (!cDof) continue; 162995a0b26dSToby Isaac 163095a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 163195a0b26dSToby Isaac #if defined(PETSC_USE_DEBUG) 163295a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 163395a0b26dSToby Isaac if (cDof > 1 && r) { 163495a0b26dSToby Isaac if ((ia[cOff+r+1]-ia[cOff+r]) != (ia[cOff+r]-ia[cOff+r-1])) { 163595a0b26dSToby Isaac SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Two point rows have different nnz: %d vs. %d", (ia[rows[r]+1]-ia[rows[r]]), (ia[rows[r]]-ia[rows[r]-1])); 163695a0b26dSToby Isaac } 163795a0b26dSToby Isaac } 163895a0b26dSToby Isaac } 163995a0b26dSToby Isaac #endif 164095a0b26dSToby Isaac /* zero rows */ 164195a0b26dSToby Isaac for (i = ia[cOff] ; i< ia[cOff+cDof];i++) { 164295a0b26dSToby Isaac vals[i] = 0.; 164395a0b26dSToby Isaac } 164495a0b26dSToby Isaac matOffset = ia[cOff]; 164595a0b26dSToby Isaac numFillCols = ia[cOff+1] - matOffset; 164695a0b26dSToby Isaac pointMat = refPointFieldMats[childid-pRefStart][f]; 164795a0b26dSToby Isaac numCols = refPointFieldN[childid-pRefStart][f]; 164895a0b26dSToby Isaac offset = 0; 164995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 165095a0b26dSToby Isaac PetscInt q = closure[2*i]; 165195a0b26dSToby Isaac PetscInt o = closure[2*i+1]; 165295a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 165395a0b26dSToby Isaac 165495a0b26dSToby Isaac qConDof = qConOff = 0; 165595a0b26dSToby Isaac if (numFields > 1) { 165695a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(section,q,f,&aDof);CHKERRQ(ierr); 165795a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(section,q,f,&aOff);CHKERRQ(ierr); 165895a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 165995a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,q,f,&qConDof);CHKERRQ(ierr); 166095a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,q,f,&qConOff);CHKERRQ(ierr); 166195a0b26dSToby Isaac } 166295a0b26dSToby Isaac } 166395a0b26dSToby Isaac else { 166495a0b26dSToby Isaac ierr = PetscSectionGetDof(section,q,&aDof);CHKERRQ(ierr); 166595a0b26dSToby Isaac ierr = PetscSectionGetOffset(section,q,&aOff);CHKERRQ(ierr); 166695a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 166795a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,q,&qConDof);CHKERRQ(ierr); 166895a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,q,&qConOff);CHKERRQ(ierr); 166995a0b26dSToby Isaac } 167095a0b26dSToby Isaac } 167195a0b26dSToby Isaac if (!aDof) continue; 167295a0b26dSToby Isaac if (qConDof) { 167395a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 167495a0b26dSToby Isaac * be filled, thanks to preordering */ 167595a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 167695a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 167795a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 167895a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 167995a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 168095a0b26dSToby Isaac PetscScalar inVal = 0; 168195a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 168295a0b26dSToby Isaac PetscInt node = (o >= 0) ? (k / fComp) : ((aDof - 1 - k) / fComp); 168395a0b26dSToby Isaac PetscInt comp = (k % fComp); 168495a0b26dSToby Isaac PetscInt col = node * fComp + comp; 168595a0b26dSToby Isaac 168695a0b26dSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j]; 168795a0b26dSToby Isaac } 168895a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 168995a0b26dSToby Isaac } 169095a0b26dSToby Isaac } 169195a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 169295a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 169395a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 169495a0b26dSToby Isaac for (;k < numFillCols; k++) { 169595a0b26dSToby Isaac if (ja[matOffset + k] == col) { 169695a0b26dSToby Isaac break; 169795a0b26dSToby Isaac } 169895a0b26dSToby Isaac } 169995a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, col); 170095a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 170195a0b26dSToby Isaac vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 170295a0b26dSToby Isaac } 170395a0b26dSToby Isaac } 170495a0b26dSToby Isaac } 170595a0b26dSToby Isaac else { 170695a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 170795a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 170895a0b26dSToby Isaac if (ja[matOffset + k] == aOff) { 170995a0b26dSToby Isaac break; 171095a0b26dSToby Isaac } 171195a0b26dSToby Isaac } 171295a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, aOff); 171395a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 171495a0b26dSToby Isaac PetscInt node = (o >= 0) ? (j / fComp) : ((aDof - 1 - j) / fComp); 171595a0b26dSToby Isaac PetscInt comp = (j % fComp); 171695a0b26dSToby Isaac PetscInt col = node * fComp + comp; 171795a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 171895a0b26dSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + col]; 171995a0b26dSToby Isaac } 172095a0b26dSToby Isaac } 172195a0b26dSToby Isaac } 172295a0b26dSToby Isaac offset += aDof; 172395a0b26dSToby Isaac } 172495a0b26dSToby Isaac } 172595a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 172695a0b26dSToby Isaac } 172795a0b26dSToby Isaac for (row = 0; row < nRows; row++) { 172895a0b26dSToby Isaac ierr = MatSetValues(cMat,1,&row,ia[row+1]-ia[row],&ja[ia[row]],&vals[ia[row]],INSERT_VALUES);CHKERRQ(ierr); 172995a0b26dSToby Isaac } 173095a0b26dSToby Isaac ierr = MatRestoreRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 173195a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not restore RowIJ of constraint matrix"); 173295a0b26dSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 173395a0b26dSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 173495a0b26dSToby Isaac ierr = PetscFree(vals);CHKERRQ(ierr); 173595a0b26dSToby Isaac } 173695a0b26dSToby Isaac 173795a0b26dSToby Isaac /* clean up */ 173895a0b26dSToby Isaac ierr = ISRestoreIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 173995a0b26dSToby Isaac ierr = ISRestoreIndices(anIS,&anchors);CHKERRQ(ierr); 174095a0b26dSToby Isaac ierr = PetscFree2(perm,iperm);CHKERRQ(ierr); 174195a0b26dSToby Isaac ierr = PetscFree(rows);CHKERRQ(ierr); 174295a0b26dSToby Isaac ierr = PetscFree(cols);CHKERRQ(ierr); 174395a0b26dSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 174495a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 174595a0b26dSToby Isaac PetscInt parent, pDof; 174695a0b26dSToby Isaac 174795a0b26dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 174895a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 174995a0b26dSToby Isaac if (!pDof || parent == p) continue; 175095a0b26dSToby Isaac 175195a0b26dSToby Isaac for (f = 0; f < numFields; f++) { 175295a0b26dSToby Isaac PetscInt cDof; 175395a0b26dSToby Isaac 175495a0b26dSToby Isaac if (numFields > 1) { 175595a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 175695a0b26dSToby Isaac } 175795a0b26dSToby Isaac else { 175895a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 175995a0b26dSToby Isaac } 176095a0b26dSToby Isaac 176195a0b26dSToby Isaac if (!cDof) continue; 176295a0b26dSToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr); 176395a0b26dSToby Isaac } 176495a0b26dSToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr); 176595a0b26dSToby Isaac ierr = PetscFree(refPointFieldN[p - pRefStart]);CHKERRQ(ierr); 176695a0b26dSToby Isaac } 176795a0b26dSToby Isaac ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr); 176895a0b26dSToby Isaac ierr = PetscFree(refPointFieldN);CHKERRQ(ierr); 176995a0b26dSToby Isaac PetscFunctionReturn(0); 177095a0b26dSToby Isaac } 177195a0b26dSToby Isaac 17726f5f1567SToby Isaac #undef __FUNCT__ 17736f5f1567SToby Isaac #define __FUNCT__ "DMPlexTreeRefineCell" 17746f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 17756f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 17766f5f1567SToby Isaac PetscErrorCode DMPlexTreeRefineCell (DM dm, PetscInt cell, DM *ncdm) 17776f5f1567SToby Isaac { 17786f5f1567SToby Isaac DM K; 1779420f55faSMatthew G. Knepley PetscMPIInt rank; 17806f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 17816f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 17826f5f1567SToby Isaac PetscInt *Kembedding; 17836f5f1567SToby Isaac PetscInt *cellClosure=NULL, nc; 17846f5f1567SToby Isaac PetscScalar *newVertexCoords; 17856f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 17866f5f1567SToby Isaac PetscSection parentSection; 17876f5f1567SToby Isaac PetscErrorCode ierr; 17886f5f1567SToby Isaac 17896f5f1567SToby Isaac PetscFunctionBegin; 17906f5f1567SToby Isaac ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr); 179128f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 17926f5f1567SToby Isaac ierr = DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm);CHKERRQ(ierr); 179328f4b327SMatthew G. Knepley ierr = DMSetDimension(*ncdm,dim);CHKERRQ(ierr); 17946f5f1567SToby Isaac 17956f5f1567SToby Isaac ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 17966f5f1567SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&parentSection);CHKERRQ(ierr); 17976f5f1567SToby Isaac ierr = DMPlexGetReferenceTree(dm,&K);CHKERRQ(ierr); 17986f5f1567SToby Isaac if (!rank) { 17996f5f1567SToby Isaac /* compute the new charts */ 18006f5f1567SToby Isaac ierr = PetscMalloc5(dim+1,&pNewCount,dim+1,&pNewStart,dim+1,&pNewEnd,dim+1,&pOldStart,dim+1,&pOldEnd);CHKERRQ(ierr); 18016f5f1567SToby Isaac offset = 0; 18026f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18036f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 18046f5f1567SToby Isaac 18056f5f1567SToby Isaac pNewStart[d] = offset; 18066f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pOldStart[d],&pOldEnd[d]);CHKERRQ(ierr); 18076f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 18086f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 18096f5f1567SToby Isaac /* adding the new points */ 18106f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 18116f5f1567SToby Isaac if (!d) { 18126f5f1567SToby Isaac /* removing the cell */ 18136f5f1567SToby Isaac pNewCount[d]--; 18146f5f1567SToby Isaac } 18156f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18166f5f1567SToby Isaac PetscInt parent; 18176f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&parent,NULL);CHKERRQ(ierr); 18186f5f1567SToby Isaac if (parent == k) { 18196f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 18206f5f1567SToby Isaac pNewCount[d]--; 18216f5f1567SToby Isaac } 18226f5f1567SToby Isaac } 18236f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 18246f5f1567SToby Isaac offset = pNewEnd[d]; 18256f5f1567SToby Isaac 18266f5f1567SToby Isaac } 18276f5f1567SToby 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]); 18286f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 18296f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 18306f5f1567SToby Isaac 18316f5f1567SToby Isaac ierr = PetscMalloc1(pNewEnd[dim],&newConeSizes);CHKERRQ(ierr); 18326f5f1567SToby Isaac { 18336f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 18346f5f1567SToby Isaac 18356f5f1567SToby Isaac ierr = DMPlexGetChart(K,&kStart,&kEnd);CHKERRQ(ierr); 18366f5f1567SToby Isaac ierr = PetscMalloc4(kEnd-kStart,&Kembedding,kEnd-kStart,&perm,kEnd-kStart,&iperm,kEnd-kStart,&preOrient);CHKERRQ(ierr); 18376f5f1567SToby Isaac 18386f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18396f5f1567SToby Isaac perm[k - kStart] = k; 18406f5f1567SToby Isaac iperm [k - kStart] = k - kStart; 18416f5f1567SToby Isaac preOrient[k - kStart] = 0; 18426f5f1567SToby Isaac } 18436f5f1567SToby Isaac 18446f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 18456f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 18466f5f1567SToby Isaac PetscInt parentOrientA = closureK[2*j+1]; 18476f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2*j+1]; 18486f5f1567SToby Isaac PetscInt p, q; 18496f5f1567SToby Isaac 18506f5f1567SToby Isaac p = closureK[2*j]; 18516f5f1567SToby Isaac q = cellClosure[2*j]; 18526f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18536f5f1567SToby Isaac if (q >= pOldStart[d] && q < pOldEnd[d]) { 18546f5f1567SToby Isaac Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 18556f5f1567SToby Isaac } 18566f5f1567SToby Isaac } 18576f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 18586f5f1567SToby Isaac PetscInt numChildren, i; 18596f5f1567SToby Isaac const PetscInt *children; 18606f5f1567SToby Isaac 18616f5f1567SToby Isaac ierr = DMPlexGetTreeChildren(K,p,&numChildren,&children);CHKERRQ(ierr); 18626f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 18636f5f1567SToby Isaac PetscInt kPerm, oPerm; 18646f5f1567SToby Isaac 18656f5f1567SToby Isaac k = children[i]; 18666f5f1567SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry(K,p,parentOrientA,0,k,parentOrientB,&oPerm,&kPerm);CHKERRQ(ierr); 18676f5f1567SToby Isaac /* perm = what refTree position I'm in */ 18686f5f1567SToby Isaac perm[kPerm-kStart] = k; 18696f5f1567SToby Isaac /* iperm = who is at this position */ 18706f5f1567SToby Isaac iperm[k-kStart] = kPerm-kStart; 18716f5f1567SToby Isaac preOrient[kPerm-kStart] = oPerm; 18726f5f1567SToby Isaac } 18736f5f1567SToby Isaac } 18746f5f1567SToby Isaac } 18756f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 18766f5f1567SToby Isaac } 18776f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,0,pNewEnd[dim]);CHKERRQ(ierr); 18786f5f1567SToby Isaac offset = 0; 18796f5f1567SToby Isaac numNewCones = 0; 18806f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18816f5f1567SToby Isaac PetscInt kStart, kEnd, k; 18826f5f1567SToby Isaac PetscInt p; 18836f5f1567SToby Isaac PetscInt size; 18846f5f1567SToby Isaac 18856f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 18866f5f1567SToby Isaac /* skip cell 0 */ 18876f5f1567SToby Isaac if (p == cell) continue; 18886f5f1567SToby Isaac /* old cones to new cones */ 18896f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 18906f5f1567SToby Isaac newConeSizes[offset++] = size; 18916f5f1567SToby Isaac numNewCones += size; 18926f5f1567SToby Isaac } 18936f5f1567SToby Isaac 18946f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 18956f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18966f5f1567SToby Isaac PetscInt kParent; 18976f5f1567SToby Isaac 18986f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 18996f5f1567SToby Isaac if (kParent != k) { 19006f5f1567SToby Isaac Kembedding[k] = offset; 19016f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 19026f5f1567SToby Isaac newConeSizes[offset++] = size; 19036f5f1567SToby Isaac numNewCones += size; 19046f5f1567SToby Isaac if (kParent != 0) { 19056f5f1567SToby Isaac ierr = PetscSectionSetDof(parentSection,Kembedding[k],1);CHKERRQ(ierr); 19066f5f1567SToby Isaac } 19076f5f1567SToby Isaac } 19086f5f1567SToby Isaac } 19096f5f1567SToby Isaac } 19106f5f1567SToby Isaac 19116f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 19126f5f1567SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&numPointsWithParents);CHKERRQ(ierr); 19136f5f1567SToby Isaac ierr = PetscMalloc2(numNewCones,&newCones,numNewCones,&newOrientations);CHKERRQ(ierr); 19146f5f1567SToby Isaac ierr = PetscMalloc2(numPointsWithParents,&parents,numPointsWithParents,&childIDs);CHKERRQ(ierr); 19156f5f1567SToby Isaac 19166f5f1567SToby Isaac /* fill new cones */ 19176f5f1567SToby Isaac offset = 0; 19186f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19196f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 19206f5f1567SToby Isaac PetscInt p; 19216f5f1567SToby Isaac PetscInt size; 19226f5f1567SToby Isaac const PetscInt *cone, *orientation; 19236f5f1567SToby Isaac 19246f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19256f5f1567SToby Isaac /* skip cell 0 */ 19266f5f1567SToby Isaac if (p == cell) continue; 19276f5f1567SToby Isaac /* old cones to new cones */ 19286f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 19296f5f1567SToby Isaac ierr = DMPlexGetCone(dm,p,&cone);CHKERRQ(ierr); 19306f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(dm,p,&orientation);CHKERRQ(ierr); 19316f5f1567SToby Isaac for (l = 0; l < size; l++) { 19326f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 19336f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 19346f5f1567SToby Isaac } 19356f5f1567SToby Isaac } 19366f5f1567SToby Isaac 19376f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 19386f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19396f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 19406f5f1567SToby Isaac PetscInt preO = preOrient[k]; 19416f5f1567SToby Isaac 19426f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 19436f5f1567SToby Isaac if (kParent != k) { 19446f5f1567SToby Isaac /* embed new cones */ 19456f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 19466f5f1567SToby Isaac ierr = DMPlexGetCone(K,kPerm,&cone);CHKERRQ(ierr); 19476f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(K,kPerm,&orientation);CHKERRQ(ierr); 19486f5f1567SToby Isaac for (l = 0; l < size; l++) { 19496f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size -(preO + 1) - l) % size); 19506f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 19516f5f1567SToby Isaac 19526f5f1567SToby Isaac q = iperm[cone[m]]; 19536f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 19546f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,q,&lSize);CHKERRQ(ierr); 19556f5f1567SToby Isaac oTrue = orientation[m]; 19566f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 19576f5f1567SToby Isaac newO = DihedralCompose(lSize,oTrue,preOrient[q]); 19586f5f1567SToby Isaac newOrientations[offset++] = newO; 19596f5f1567SToby Isaac } 19606f5f1567SToby Isaac if (kParent != 0) { 19616f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 19626f5f1567SToby Isaac ierr = PetscSectionGetOffset(parentSection,Kembedding[k],&pOffset);CHKERRQ(ierr); 19636f5f1567SToby Isaac parents[pOffset] = newPoint; 19646f5f1567SToby Isaac childIDs[pOffset] = k; 19656f5f1567SToby Isaac } 19666f5f1567SToby Isaac } 19676f5f1567SToby Isaac } 19686f5f1567SToby Isaac } 19696f5f1567SToby Isaac 19706f5f1567SToby Isaac ierr = PetscMalloc1(dim*(pNewEnd[dim]-pNewStart[dim]),&newVertexCoords);CHKERRQ(ierr); 19716f5f1567SToby Isaac 19726f5f1567SToby Isaac /* fill coordinates */ 19736f5f1567SToby Isaac offset = 0; 19746f5f1567SToby Isaac { 1975d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 19766f5f1567SToby Isaac PetscSection vSection; 19776f5f1567SToby Isaac PetscInt v; 19786f5f1567SToby Isaac Vec coords; 19796f5f1567SToby Isaac PetscScalar *coordvals; 19806f5f1567SToby Isaac PetscInt dof, off; 1981c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 19826f5f1567SToby Isaac 19836f5f1567SToby Isaac #if defined(PETSC_USE_DEBUG) 1984d90620a3SMatthew G. Knepley { 1985d90620a3SMatthew G. Knepley PetscInt k; 19866f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 19876f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 198873a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 19896f5f1567SToby Isaac if (detJ <= 0.) SETERRQ1 (PETSC_COMM_SELF,PETSC_ERR_PLIB,"reference tree cell %d has bad determinant",k); 19906f5f1567SToby Isaac } 1991d90620a3SMatthew G. Knepley } 19926f5f1567SToby Isaac #endif 199373a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 19946f5f1567SToby Isaac ierr = DMGetCoordinateSection(dm,&vSection);CHKERRQ(ierr); 19956f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coords);CHKERRQ(ierr); 19966f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 19976f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 19986f5f1567SToby Isaac 19996f5f1567SToby Isaac ierr = PetscSectionGetDof(vSection,v,&dof);CHKERRQ(ierr); 20006f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,v,&off);CHKERRQ(ierr); 20016f5f1567SToby Isaac for (l = 0; l < dof; l++) { 20026f5f1567SToby Isaac newVertexCoords[offset++] = coordvals[off + l]; 20036f5f1567SToby Isaac } 20046f5f1567SToby Isaac } 20056f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 20066f5f1567SToby Isaac 20076f5f1567SToby Isaac ierr = DMGetCoordinateSection(K,&vSection);CHKERRQ(ierr); 20086f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(K,&coords);CHKERRQ(ierr); 20096f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 20106f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 20116f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 20129bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 20136f5f1567SToby Isaac PetscInt vPerm = perm[v]; 20146f5f1567SToby Isaac PetscInt kParent; 20156f5f1567SToby Isaac 20166f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,v,&kParent,NULL);CHKERRQ(ierr); 20176f5f1567SToby Isaac if (kParent != v) { 20186f5f1567SToby Isaac /* this is a new vertex */ 20196f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,vPerm,&off);CHKERRQ(ierr); 20209bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off+l]); 20219bc368c7SMatthew G. Knepley CoordinatesRefToReal(dim, dim, v0, J, coord, newCoord);CHKERRQ(ierr); 20229bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset+l] = newCoord[l]; 20236f5f1567SToby Isaac offset += dim; 20246f5f1567SToby Isaac } 20256f5f1567SToby Isaac } 20266f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 20276f5f1567SToby Isaac } 20286f5f1567SToby Isaac 20296f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 20306f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 20316f5f1567SToby Isaac PetscInt tmp; 20326f5f1567SToby Isaac 20336f5f1567SToby Isaac tmp = pNewCount[d]; 20346f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 20356f5f1567SToby Isaac pNewCount[dim - d] = tmp; 20366f5f1567SToby Isaac } 20376f5f1567SToby Isaac 20386f5f1567SToby Isaac ierr = DMPlexCreateFromDAG(*ncdm,dim,pNewCount,newConeSizes,newCones,newOrientations,newVertexCoords);CHKERRQ(ierr); 20396f5f1567SToby Isaac ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr); 20406f5f1567SToby Isaac ierr = DMPlexSetTree(*ncdm,parentSection,parents,childIDs);CHKERRQ(ierr); 20416f5f1567SToby Isaac 20426f5f1567SToby Isaac /* clean up */ 20436f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 20446f5f1567SToby Isaac ierr = PetscFree5(pNewCount,pNewStart,pNewEnd,pOldStart,pOldEnd);CHKERRQ(ierr); 20456f5f1567SToby Isaac ierr = PetscFree(newConeSizes);CHKERRQ(ierr); 20466f5f1567SToby Isaac ierr = PetscFree2(newCones,newOrientations);CHKERRQ(ierr); 20476f5f1567SToby Isaac ierr = PetscFree(newVertexCoords);CHKERRQ(ierr); 20486f5f1567SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 20496f5f1567SToby Isaac ierr = PetscFree4(Kembedding,perm,iperm,preOrient);CHKERRQ(ierr); 20506f5f1567SToby Isaac } 20516f5f1567SToby Isaac else { 20526f5f1567SToby Isaac PetscInt p, counts[4]; 20536f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 20546f5f1567SToby Isaac Vec coordVec; 20556f5f1567SToby Isaac PetscScalar *coords; 20566f5f1567SToby Isaac 20576f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20586f5f1567SToby Isaac PetscInt dStart, dEnd; 20596f5f1567SToby Isaac 20606f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 20616f5f1567SToby Isaac counts[d] = dEnd - dStart; 20626f5f1567SToby Isaac } 20636f5f1567SToby Isaac ierr = PetscMalloc1(pEnd-pStart,&coneSizes);CHKERRQ(ierr); 20646f5f1567SToby Isaac for (p = pStart; p < pEnd; p++) { 20656f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&coneSizes[p-pStart]);CHKERRQ(ierr); 20666f5f1567SToby Isaac } 20676f5f1567SToby Isaac ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 20686f5f1567SToby Isaac ierr = DMPlexGetConeOrientations(dm, &orientations);CHKERRQ(ierr); 20696f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coordVec);CHKERRQ(ierr); 20706f5f1567SToby Isaac ierr = VecGetArray(coordVec,&coords);CHKERRQ(ierr); 20716f5f1567SToby Isaac 20726f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,pStart,pEnd);CHKERRQ(ierr); 20736f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 20746f5f1567SToby Isaac ierr = DMPlexCreateFromDAG(*ncdm,dim,counts,coneSizes,cones,orientations,NULL);CHKERRQ(ierr); 20756f5f1567SToby Isaac ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr); 20766f5f1567SToby Isaac ierr = DMPlexSetTree(*ncdm,parentSection,NULL,NULL);CHKERRQ(ierr); 20776f5f1567SToby Isaac ierr = VecRestoreArray(coordVec,&coords);CHKERRQ(ierr); 20786f5f1567SToby Isaac } 20796f5f1567SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 20806f5f1567SToby Isaac 20816f5f1567SToby Isaac PetscFunctionReturn(0); 20826f5f1567SToby Isaac } 2083