1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2d6a7ad0dSToby Isaac #include <../src/sys/utils/hash.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 5d6a7ad0dSToby Isaac #include <petscsf.h> 60c37af3bSToby Isaac #include <petscds.h> 7d6a7ad0dSToby Isaac 8d6a7ad0dSToby Isaac /** hierarchy routines */ 9d6a7ad0dSToby Isaac 10d6a7ad0dSToby Isaac #undef __FUNCT__ 11d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexSetReferenceTree" 12d6a7ad0dSToby Isaac /*@ 13d6a7ad0dSToby Isaac DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes. 14d6a7ad0dSToby Isaac 15d6a7ad0dSToby Isaac Not collective 16d6a7ad0dSToby Isaac 17d6a7ad0dSToby Isaac Input Parameters: 18d6a7ad0dSToby Isaac + dm - The DMPlex object 19d6a7ad0dSToby Isaac - ref - The reference tree DMPlex object 20d6a7ad0dSToby Isaac 210b7167a0SToby Isaac Level: intermediate 22d6a7ad0dSToby Isaac 23da43764aSToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexCreateDefaultReferenceTree() 24d6a7ad0dSToby Isaac @*/ 25d6a7ad0dSToby Isaac PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 26d6a7ad0dSToby Isaac { 27d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 28d6a7ad0dSToby Isaac PetscErrorCode ierr; 29d6a7ad0dSToby Isaac 30d6a7ad0dSToby Isaac PetscFunctionBegin; 31d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3247a1df27SMatthew G. Knepley if (ref) {PetscValidHeaderSpecific(ref, DM_CLASSID, 2);} 33d6a7ad0dSToby Isaac ierr = PetscObjectReference((PetscObject)ref);CHKERRQ(ierr); 34d6a7ad0dSToby Isaac ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 35d6a7ad0dSToby Isaac mesh->referenceTree = ref; 36d6a7ad0dSToby Isaac PetscFunctionReturn(0); 37d6a7ad0dSToby Isaac } 38d6a7ad0dSToby Isaac 39d6a7ad0dSToby Isaac #undef __FUNCT__ 40d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexGetReferenceTree" 41d6a7ad0dSToby Isaac /*@ 42d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 43d6a7ad0dSToby Isaac 44d6a7ad0dSToby Isaac Not collective 45d6a7ad0dSToby Isaac 46d6a7ad0dSToby Isaac Input Parameters: 47d6a7ad0dSToby Isaac . dm - The DMPlex object 48d6a7ad0dSToby Isaac 49d6a7ad0dSToby Isaac Output Parameters 50d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 51d6a7ad0dSToby Isaac 520b7167a0SToby Isaac Level: intermediate 53d6a7ad0dSToby Isaac 54da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexCreateDefaultReferenceTree() 55d6a7ad0dSToby Isaac @*/ 56d6a7ad0dSToby Isaac PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 57d6a7ad0dSToby Isaac { 58d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 59d6a7ad0dSToby Isaac 60d6a7ad0dSToby Isaac PetscFunctionBegin; 61d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62d6a7ad0dSToby Isaac PetscValidPointer(ref,2); 63d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 64d6a7ad0dSToby Isaac PetscFunctionReturn(0); 65d6a7ad0dSToby Isaac } 66d6a7ad0dSToby Isaac 67dcbd3bf7SToby Isaac #undef __FUNCT__ 68dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry_Default" 69dcbd3bf7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 70dcbd3bf7SToby Isaac { 71dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 72dcbd3bf7SToby Isaac PetscErrorCode ierr; 73dcbd3bf7SToby Isaac 74dcbd3bf7SToby Isaac PetscFunctionBegin; 75dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 76dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 77dcbd3bf7SToby Isaac if (childB) *childB = childA; 78dcbd3bf7SToby Isaac PetscFunctionReturn(0); 79dcbd3bf7SToby Isaac } 80dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 81dcbd3bf7SToby Isaac ierr = DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd);CHKERRQ(ierr); 82dcbd3bf7SToby Isaac if (parent >= dStart && parent <= dEnd) { 83dcbd3bf7SToby Isaac break; 84dcbd3bf7SToby Isaac } 85dcbd3bf7SToby Isaac } 86dcbd3bf7SToby Isaac if (dim > 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %d-cells",dim); 87dcbd3bf7SToby Isaac if (!dim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 88dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 89dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 90dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 91dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 92dcbd3bf7SToby Isaac 93dcbd3bf7SToby Isaac ierr = DMPlexGetSupportSize(dm,childA,&size);CHKERRQ(ierr); 94dcbd3bf7SToby Isaac ierr = DMPlexGetSupport(dm,childA,&supp);CHKERRQ(ierr); 95dcbd3bf7SToby Isaac 96dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 97dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 98dcbd3bf7SToby Isaac PetscInt sParent; 99dcbd3bf7SToby Isaac 100dcbd3bf7SToby Isaac sA = supp[i]; 101dcbd3bf7SToby Isaac if (sA == parent) continue; 102dcbd3bf7SToby Isaac ierr = DMPlexGetTreeParent(dm,sA,&sParent,NULL);CHKERRQ(ierr); 103dcbd3bf7SToby Isaac if (sParent == parent) { 104dcbd3bf7SToby Isaac break; 105dcbd3bf7SToby Isaac } 106dcbd3bf7SToby Isaac } 107dcbd3bf7SToby Isaac if (i == size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 108dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 109dcbd3bf7SToby Isaac * parentOrientB */ 110dcbd3bf7SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry_Default(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB);CHKERRQ(ierr); 111dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,sA,&sConeSize);CHKERRQ(ierr); 112dcbd3bf7SToby Isaac ierr = DMPlexGetCone(dm,sA,&coneA);CHKERRQ(ierr); 113dcbd3bf7SToby Isaac ierr = DMPlexGetCone(dm,sB,&coneB);CHKERRQ(ierr); 114dcbd3bf7SToby Isaac ierr = DMPlexGetConeOrientation(dm,sA,&oA);CHKERRQ(ierr); 115dcbd3bf7SToby Isaac ierr = DMPlexGetConeOrientation(dm,sB,&oB);CHKERRQ(ierr); 116dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 117dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 118dcbd3bf7SToby Isaac if (coneA[i] == childA) { 119dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 120dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 121dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 122dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 123dcbd3bf7SToby Isaac if (childOrientB) { 124dcbd3bf7SToby Isaac PetscInt oBtrue; 125dcbd3bf7SToby Isaac 126dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,childA,&coneSize);CHKERRQ(ierr); 127dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 128dcbd3bf7SToby Isaac if (coneSize != 0 && coneSize != 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 129dcbd3bf7SToby Isaac /* we may have to flip an edge */ 130dcbd3bf7SToby Isaac oBtrue = coneSize ? ((sOrientB >= 0) ? oB[j] : -(oB[j] + 2)) : 0; 131dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize,oA[i],oBtrue);CHKERRQ(ierr); 132dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 133dcbd3bf7SToby Isaac } 134dcbd3bf7SToby Isaac break; 135dcbd3bf7SToby Isaac } 136dcbd3bf7SToby Isaac } 137dcbd3bf7SToby Isaac if (i == sConeSize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 138dcbd3bf7SToby Isaac PetscFunctionReturn(0); 139dcbd3bf7SToby Isaac } 140dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 141dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,parent,&coneSize);CHKERRQ(ierr); 142dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 143dcbd3bf7SToby Isaac if (dim == 2) { 144dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 145dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 146dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 147dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 148dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 149dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 150947b95d8SBarry Smith } else { 151dcbd3bf7SToby Isaac ABswapVert = ABswap; 152dcbd3bf7SToby Isaac } 153dcbd3bf7SToby Isaac if (childB) { 154dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 155dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 156dcbd3bf7SToby Isaac const PetscInt *children; 157dcbd3bf7SToby Isaac 158dcbd3bf7SToby Isaac /* count which position the child is in */ 159dcbd3bf7SToby Isaac ierr = DMPlexGetTreeChildren(dm,parent,&numChildren,&children);CHKERRQ(ierr); 160dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 161dcbd3bf7SToby Isaac p = children[i]; 162dcbd3bf7SToby Isaac if (p == childA) { 163dcbd3bf7SToby Isaac posA = i; 164dcbd3bf7SToby Isaac break; 165dcbd3bf7SToby Isaac } 166dcbd3bf7SToby Isaac } 167dcbd3bf7SToby Isaac if (posA >= coneSize) { 168dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 169dcbd3bf7SToby Isaac * is invariant */ 170dcbd3bf7SToby Isaac if (dim != 2 || posA != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Expected a middle triangle, got something else"); 171dcbd3bf7SToby Isaac *childB = childA; 172dcbd3bf7SToby Isaac } 173dcbd3bf7SToby Isaac else { 174dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 175dcbd3bf7SToby Isaac PetscInt posB; 176dcbd3bf7SToby Isaac 177dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 178dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 179dcbd3bf7SToby Isaac } 180dcbd3bf7SToby Isaac } 181dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 182dcbd3bf7SToby Isaac PetscFunctionReturn(0); 183dcbd3bf7SToby Isaac } 184dcbd3bf7SToby Isaac 185dcbd3bf7SToby Isaac #undef __FUNCT__ 186dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry" 187dcbd3bf7SToby Isaac /*@ 188dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 189dcbd3bf7SToby Isaac 190dcbd3bf7SToby Isaac Input Parameters: 191dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object 192dcbd3bf7SToby Isaac . parent - the parent point 193dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 194dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 195dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 196dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 197dcbd3bf7SToby Isaac 198dcbd3bf7SToby Isaac Output Parameters: 199dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child 200dcbd3bf7SToby Isaac . childB - if not NULL, the new childID for describing the child 201dcbd3bf7SToby Isaac 202dcbd3bf7SToby Isaac Level: developer 203dcbd3bf7SToby Isaac 204dcbd3bf7SToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexSetReferenceTree(), DMPlexSetTree() 205dcbd3bf7SToby Isaac @*/ 206dcbd3bf7SToby Isaac PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 207dcbd3bf7SToby Isaac { 208dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 209dcbd3bf7SToby Isaac PetscErrorCode ierr; 210dcbd3bf7SToby Isaac 211dcbd3bf7SToby Isaac PetscFunctionBegin; 212dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 213dcbd3bf7SToby Isaac if (!mesh->getchildsymmetry) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"DMPlexReferenceTreeGetChildSymmetry not implemented"); 214dcbd3bf7SToby Isaac ierr = mesh->getchildsymmetry(dm,parent,parentOrientA,childOrientA,childA,parentOrientB,childOrientB,childB);CHKERRQ(ierr); 215dcbd3bf7SToby Isaac PetscFunctionReturn(0); 216dcbd3bf7SToby Isaac } 217dcbd3bf7SToby Isaac 218776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM,PetscSection,PetscInt*,PetscInt*,PetscBool,PetscBool); 219f9f063d4SToby Isaac 220da43764aSToby Isaac #undef __FUNCT__ 2210e2cc29aSToby Isaac #define __FUNCT__ "DMPlexCreateReferenceTree_Union" 2220e2cc29aSToby Isaac PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 223da43764aSToby Isaac { 2240e2cc29aSToby Isaac MPI_Comm comm; 2250e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 226da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 227da43764aSToby Isaac DMLabel identity, identityRef; 22810f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 229da43764aSToby Isaac PetscScalar *unionCoords; 230da43764aSToby Isaac IS perm; 231da43764aSToby Isaac PetscErrorCode ierr; 232da43764aSToby Isaac 233da43764aSToby Isaac PetscFunctionBegin; 2340e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2350e2cc29aSToby Isaac ierr = DMGetDimension(K, &dim);CHKERRQ(ierr); 236da43764aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 2370e2cc29aSToby Isaac ierr = DMGetLabel(K, labelName, &identity);CHKERRQ(ierr); 2380e2cc29aSToby Isaac ierr = DMGetLabel(Kref, labelName, &identityRef);CHKERRQ(ierr); 239da43764aSToby Isaac ierr = DMPlexGetChart(Kref, &pRefStart, &pRefEnd);CHKERRQ(ierr); 240da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionSection);CHKERRQ(ierr); 241da43764aSToby Isaac ierr = PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart));CHKERRQ(ierr); 242da43764aSToby Isaac /* count points that will go in the union */ 243da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 244da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pStart, 1);CHKERRQ(ierr); 245da43764aSToby Isaac } 246da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 247da43764aSToby Isaac PetscInt q, qSize; 248da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, p, &q);CHKERRQ(ierr); 249da43764aSToby Isaac ierr = DMLabelGetStratumSize(identityRef, q, &qSize);CHKERRQ(ierr); 250da43764aSToby Isaac if (qSize > 1) { 251da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1);CHKERRQ(ierr); 252da43764aSToby Isaac } 253da43764aSToby Isaac } 254854ce69bSBarry Smith ierr = PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart,&permvals);CHKERRQ(ierr); 255da43764aSToby Isaac offset = 0; 256da43764aSToby Isaac /* stratify points in the union by topological dimension */ 257da43764aSToby Isaac for (d = 0; d <= dim; d++) { 258da43764aSToby Isaac PetscInt cStart, cEnd, c; 259da43764aSToby Isaac 260da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K, d, &cStart, &cEnd);CHKERRQ(ierr); 261da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 262da43764aSToby Isaac permvals[offset++] = c; 263da43764aSToby Isaac } 264da43764aSToby Isaac 265da43764aSToby Isaac ierr = DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd);CHKERRQ(ierr); 266da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 267da43764aSToby Isaac permvals[offset++] = c + (pEnd - pStart); 268da43764aSToby Isaac } 269da43764aSToby Isaac } 270da43764aSToby Isaac ierr = ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr); 271da43764aSToby Isaac ierr = PetscSectionSetPermutation(unionSection,perm);CHKERRQ(ierr); 272da43764aSToby Isaac ierr = PetscSectionSetUp(unionSection);CHKERRQ(ierr); 273da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionSection,&numUnionPoints);CHKERRQ(ierr); 274da43764aSToby Isaac ierr = PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints);CHKERRQ(ierr); 275da43764aSToby Isaac /* count dimension points */ 276da43764aSToby Isaac for (d = 0; d <= dim; d++) { 277da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 278da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d,&cStart,NULL);CHKERRQ(ierr); 279da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff);CHKERRQ(ierr); 280da43764aSToby Isaac if (d < dim) { 281da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d+1,&cStart,NULL);CHKERRQ(ierr); 282da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2);CHKERRQ(ierr); 283da43764aSToby Isaac } 284da43764aSToby Isaac else { 285da43764aSToby Isaac cOff2 = numUnionPoints; 286da43764aSToby Isaac } 287da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 288da43764aSToby Isaac } 289da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionConeSection);CHKERRQ(ierr); 290da43764aSToby Isaac ierr = PetscSectionSetChart(unionConeSection, 0, numUnionPoints);CHKERRQ(ierr); 291da43764aSToby Isaac /* count the cones in the union */ 292da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 293da43764aSToby Isaac PetscInt dof, uOff; 294da43764aSToby Isaac 295da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 296da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 297da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 298da43764aSToby Isaac coneSizes[uOff] = dof; 299da43764aSToby Isaac } 300da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 301da43764aSToby Isaac PetscInt dof, uDof, uOff; 302da43764aSToby Isaac 303da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 304da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 305da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 306da43764aSToby Isaac if (uDof) { 307da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 308da43764aSToby Isaac coneSizes[uOff] = dof; 309da43764aSToby Isaac } 310da43764aSToby Isaac } 311da43764aSToby Isaac ierr = PetscSectionSetUp(unionConeSection);CHKERRQ(ierr); 312da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionConeSection,&numCones);CHKERRQ(ierr); 313da43764aSToby Isaac ierr = PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations);CHKERRQ(ierr); 314da43764aSToby Isaac /* write the cones in the union */ 315da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 316da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 317da43764aSToby Isaac const PetscInt *cone, *orientation; 318da43764aSToby Isaac 319da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 320da43764aSToby Isaac ierr = DMPlexGetCone(K, p, &cone);CHKERRQ(ierr); 321da43764aSToby Isaac ierr = DMPlexGetConeOrientation(K, p, &orientation);CHKERRQ(ierr); 322da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 323da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 324da43764aSToby Isaac for (c = 0; c < dof; c++) { 325da43764aSToby Isaac PetscInt e, eOff; 326da43764aSToby Isaac e = cone[c]; 327da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 328da43764aSToby Isaac unionCones[cOff + c] = eOff; 329da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 330da43764aSToby Isaac } 331da43764aSToby Isaac } 332da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 333da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 334da43764aSToby Isaac const PetscInt *cone, *orientation; 335da43764aSToby Isaac 336da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 337da43764aSToby Isaac ierr = DMPlexGetCone(Kref, p, &cone);CHKERRQ(ierr); 338da43764aSToby Isaac ierr = DMPlexGetConeOrientation(Kref, p, &orientation);CHKERRQ(ierr); 339da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 340da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 341da43764aSToby Isaac if (uDof) { 342da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 343da43764aSToby Isaac for (c = 0; c < dof; c++) { 344da43764aSToby Isaac PetscInt e, eOff, eDof; 345da43764aSToby Isaac 346da43764aSToby Isaac e = cone[c]; 347da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof);CHKERRQ(ierr); 348da43764aSToby Isaac if (eDof) { 349da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff);CHKERRQ(ierr); 350da43764aSToby Isaac } 351da43764aSToby Isaac else { 352da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, e, &e);CHKERRQ(ierr); 353da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 354da43764aSToby Isaac } 355da43764aSToby Isaac unionCones[cOff + c] = eOff; 356da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 357da43764aSToby Isaac } 358da43764aSToby Isaac } 359da43764aSToby Isaac } 360da43764aSToby Isaac /* get the coordinates */ 361da43764aSToby Isaac { 362da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 363da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 364da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 365da43764aSToby Isaac PetscScalar *Kcoords; 366da43764aSToby Isaac 367da43764aSToby Isaac DMGetCoordinateSection(K, &KcoordsSec);CHKERRQ(ierr); 368da43764aSToby Isaac DMGetCoordinatesLocal(K, &KcoordsVec);CHKERRQ(ierr); 369da43764aSToby Isaac DMGetCoordinateSection(Kref, &KrefCoordsSec);CHKERRQ(ierr); 370da43764aSToby Isaac DMGetCoordinatesLocal(Kref, &KrefCoordsVec);CHKERRQ(ierr); 371da43764aSToby Isaac 372da43764aSToby Isaac numVerts = numDimPoints[0]; 373da43764aSToby Isaac ierr = PetscMalloc1(numVerts * dim,&unionCoords);CHKERRQ(ierr); 374da43764aSToby Isaac ierr = DMPlexGetDepthStratum(K,0,&vStart,&vEnd);CHKERRQ(ierr); 375da43764aSToby Isaac 376da43764aSToby Isaac offset = 0; 377da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 378da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pStart,&vOff);CHKERRQ(ierr); 379da43764aSToby Isaac ierr = VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords);CHKERRQ(ierr); 380da43764aSToby Isaac for (d = 0; d < dim; d++) { 381da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 382da43764aSToby Isaac } 383da43764aSToby Isaac offset++; 384da43764aSToby Isaac } 385da43764aSToby Isaac ierr = DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd);CHKERRQ(ierr); 386da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 387da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof);CHKERRQ(ierr); 388da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff);CHKERRQ(ierr); 389da43764aSToby Isaac ierr = VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords);CHKERRQ(ierr); 390da43764aSToby Isaac if (vDof) { 391da43764aSToby Isaac for (d = 0; d < dim; d++) { 392da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 393da43764aSToby Isaac } 394da43764aSToby Isaac offset++; 395da43764aSToby Isaac } 396da43764aSToby Isaac } 397da43764aSToby Isaac } 398da43764aSToby Isaac ierr = DMCreate(comm,ref);CHKERRQ(ierr); 399da43764aSToby Isaac ierr = DMSetType(*ref,DMPLEX);CHKERRQ(ierr); 40028f4b327SMatthew G. Knepley ierr = DMSetDimension(*ref,dim);CHKERRQ(ierr); 401da43764aSToby Isaac ierr = DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords);CHKERRQ(ierr); 40210f7e118SToby Isaac /* set the tree */ 40310f7e118SToby Isaac ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr); 40410f7e118SToby Isaac ierr = PetscSectionSetChart(parentSection,0,numUnionPoints);CHKERRQ(ierr); 40510f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 40610f7e118SToby Isaac PetscInt uDof, uOff; 40710f7e118SToby Isaac 40810f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 40910f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 41010f7e118SToby Isaac if (uDof) { 41110f7e118SToby Isaac PetscSectionSetDof(parentSection,uOff,1);CHKERRQ(ierr); 41210f7e118SToby Isaac } 41310f7e118SToby Isaac } 41410f7e118SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 41510f7e118SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&parentSize);CHKERRQ(ierr); 41610f7e118SToby Isaac ierr = PetscMalloc2(parentSize,&parents,parentSize,&childIDs);CHKERRQ(ierr); 41710f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 41810f7e118SToby Isaac PetscInt uDof, uOff; 41910f7e118SToby Isaac 42010f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 42110f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 42210f7e118SToby Isaac if (uDof) { 42310f7e118SToby Isaac PetscInt pOff, parent, parentU; 42410f7e118SToby Isaac PetscSectionGetOffset(parentSection,uOff,&pOff);CHKERRQ(ierr); 42510f7e118SToby Isaac DMLabelGetValue(identityRef,p,&parent);CHKERRQ(ierr); 42610f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, parent - pStart,&parentU);CHKERRQ(ierr); 42710f7e118SToby Isaac parents[pOff] = parentU; 42810f7e118SToby Isaac childIDs[pOff] = uOff; 42910f7e118SToby Isaac } 43010f7e118SToby Isaac } 431776742edSToby Isaac ierr = DMPlexSetTree_Internal(*ref,parentSection,parents,childIDs,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 43210f7e118SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 43310f7e118SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 43410f7e118SToby Isaac 435da43764aSToby Isaac /* clean up */ 436da43764aSToby Isaac ierr = PetscSectionDestroy(&unionSection);CHKERRQ(ierr); 437da43764aSToby Isaac ierr = PetscSectionDestroy(&unionConeSection);CHKERRQ(ierr); 438da43764aSToby Isaac ierr = ISDestroy(&perm);CHKERRQ(ierr); 439da43764aSToby Isaac ierr = PetscFree(unionCoords);CHKERRQ(ierr); 440da43764aSToby Isaac ierr = PetscFree2(unionCones,unionOrientations);CHKERRQ(ierr); 441da43764aSToby Isaac ierr = PetscFree2(coneSizes,numDimPoints);CHKERRQ(ierr); 4420e2cc29aSToby Isaac PetscFunctionReturn(0); 4430e2cc29aSToby Isaac } 4440e2cc29aSToby Isaac 4450e2cc29aSToby Isaac #undef __FUNCT__ 4460e2cc29aSToby Isaac #define __FUNCT__ "DMPlexCreateDefaultReferenceTree" 4470e2cc29aSToby Isaac /*@ 4480e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4490e2cc29aSToby Isaac 4500e2cc29aSToby Isaac Collective on comm 4510e2cc29aSToby Isaac 4520e2cc29aSToby Isaac Input Parameters: 4530e2cc29aSToby Isaac + comm - the MPI communicator 4540e2cc29aSToby Isaac . dim - the spatial dimension 4550e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4560e2cc29aSToby Isaac 4570e2cc29aSToby Isaac Output Parameters: 4580e2cc29aSToby Isaac . ref - the reference tree DMPlex object 4590e2cc29aSToby Isaac 4600e2cc29aSToby Isaac Level: intermediate 4610e2cc29aSToby Isaac 4620e2cc29aSToby Isaac .keywords: reference cell 4630e2cc29aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree() 4640e2cc29aSToby Isaac @*/ 4650e2cc29aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 4660e2cc29aSToby Isaac { 4670e2cc29aSToby Isaac DM_Plex *mesh; 4680e2cc29aSToby Isaac DM K, Kref; 4690e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4700e2cc29aSToby Isaac DMLabel identity; 4710e2cc29aSToby Isaac PetscErrorCode ierr; 4720e2cc29aSToby Isaac 4730e2cc29aSToby Isaac PetscFunctionBegin; 4740e2cc29aSToby Isaac #if 1 4750e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4760e2cc29aSToby Isaac #endif 4770e2cc29aSToby Isaac /* create a reference element */ 4780e2cc29aSToby Isaac ierr = DMPlexCreateReferenceCell(comm, dim, simplex, &K);CHKERRQ(ierr); 4790e2cc29aSToby Isaac ierr = DMCreateLabel(K, "identity");CHKERRQ(ierr); 4800e2cc29aSToby Isaac ierr = DMGetLabel(K, "identity", &identity);CHKERRQ(ierr); 4810e2cc29aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 4820e2cc29aSToby Isaac for (p = pStart; p < pEnd; p++) { 4830e2cc29aSToby Isaac ierr = DMLabelSetValue(identity, p, p);CHKERRQ(ierr); 4840e2cc29aSToby Isaac } 4850e2cc29aSToby Isaac /* refine it */ 4860e2cc29aSToby Isaac ierr = DMRefine(K,comm,&Kref);CHKERRQ(ierr); 4870e2cc29aSToby Isaac 4880e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4890e2cc29aSToby Isaac * points that appear in both */ 4900e2cc29aSToby Isaac ierr = DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref);CHKERRQ(ierr); 4910e2cc29aSToby Isaac mesh = (DM_Plex *) (*ref)->data; 4920e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 493da43764aSToby Isaac ierr = DMDestroy(&K);CHKERRQ(ierr); 494da43764aSToby Isaac ierr = DMDestroy(&Kref);CHKERRQ(ierr); 495da43764aSToby Isaac PetscFunctionReturn(0); 496da43764aSToby Isaac } 497da43764aSToby Isaac 498d961a43aSToby Isaac #undef __FUNCT__ 499878b19aaSToby Isaac #define __FUNCT__ "DMPlexTreeSymmetrize" 500878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 501878b19aaSToby Isaac { 502878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 503878b19aaSToby Isaac PetscSection childSec, pSec; 504878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 505878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 506878b19aaSToby Isaac PetscErrorCode ierr; 507878b19aaSToby Isaac 508878b19aaSToby Isaac PetscFunctionBegin; 509878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 510878b19aaSToby Isaac ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 511878b19aaSToby Isaac ierr = PetscFree(mesh->children);CHKERRQ(ierr); 512878b19aaSToby Isaac pSec = mesh->parentSection; 513878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 514878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(pSec,&pSize);CHKERRQ(ierr); 515878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 516878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 517878b19aaSToby Isaac 518878b19aaSToby Isaac parMax = PetscMax(parMax,par+1); 519878b19aaSToby Isaac parMin = PetscMin(parMin,par); 520878b19aaSToby Isaac } 521878b19aaSToby Isaac if (parMin > parMax) { 522878b19aaSToby Isaac parMin = -1; 523878b19aaSToby Isaac parMax = -1; 524878b19aaSToby Isaac } 525878b19aaSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec);CHKERRQ(ierr); 526878b19aaSToby Isaac ierr = PetscSectionSetChart(childSec,parMin,parMax);CHKERRQ(ierr); 527878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 528878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 529878b19aaSToby Isaac 530878b19aaSToby Isaac ierr = PetscSectionAddDof(childSec,par,1);CHKERRQ(ierr); 531878b19aaSToby Isaac } 532878b19aaSToby Isaac ierr = PetscSectionSetUp(childSec);CHKERRQ(ierr); 533878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(childSec,&cSize);CHKERRQ(ierr); 534878b19aaSToby Isaac ierr = PetscMalloc1(cSize,&children);CHKERRQ(ierr); 535878b19aaSToby Isaac ierr = PetscCalloc1(parMax-parMin,&offsets);CHKERRQ(ierr); 536878b19aaSToby Isaac ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr); 537878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 538878b19aaSToby Isaac PetscInt dof, off, i; 539878b19aaSToby Isaac 540878b19aaSToby Isaac ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 541878b19aaSToby Isaac ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr); 542878b19aaSToby Isaac for (i = 0; i < dof; i++) { 543878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 544878b19aaSToby Isaac 545878b19aaSToby Isaac ierr = PetscSectionGetOffset(childSec,par,&cOff);CHKERRQ(ierr); 546878b19aaSToby Isaac children[cOff + offsets[par-parMin]++] = p; 547878b19aaSToby Isaac } 548878b19aaSToby Isaac } 549878b19aaSToby Isaac mesh->childSection = childSec; 550878b19aaSToby Isaac mesh->children = children; 551878b19aaSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 552878b19aaSToby Isaac PetscFunctionReturn(0); 553878b19aaSToby Isaac } 554878b19aaSToby Isaac 555878b19aaSToby Isaac #undef __FUNCT__ 5566dd5a8c8SToby Isaac #define __FUNCT__ "AnchorsFlatten" 5576dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 5586dd5a8c8SToby Isaac { 5596dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5606dd5a8c8SToby Isaac const PetscInt *vals; 5616dd5a8c8SToby Isaac PetscSection secNew; 5626dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5636dd5a8c8SToby Isaac PetscBool compress; 5646dd5a8c8SToby Isaac PetscErrorCode ierr; 5656dd5a8c8SToby Isaac 5666dd5a8c8SToby Isaac PetscFunctionBegin; 5676dd5a8c8SToby Isaac ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr); 5686dd5a8c8SToby Isaac ierr = ISGetLocalSize(is,&size);CHKERRQ(ierr); 5696dd5a8c8SToby Isaac ierr = ISGetIndices(is,&vals);CHKERRQ(ierr); 5706dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew);CHKERRQ(ierr); 5716dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secNew,pStart,pEnd);CHKERRQ(ierr); 5726dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5736dd5a8c8SToby Isaac PetscInt dof; 5746dd5a8c8SToby Isaac 5756dd5a8c8SToby Isaac p = vals[i]; 5766dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5776dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5786dd5a8c8SToby Isaac if (dof) break; 5796dd5a8c8SToby Isaac } 5806dd5a8c8SToby Isaac if (i == size) { 5816dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 5826dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5836dd5a8c8SToby Isaac compress = PETSC_FALSE; 5846dd5a8c8SToby Isaac sizeNew = 0; 5856dd5a8c8SToby Isaac } 5866dd5a8c8SToby Isaac else { 5876dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5886dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5896dd5a8c8SToby Isaac PetscInt dof, off; 5906dd5a8c8SToby Isaac 5916dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5926dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 5936dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5946dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5956dd5a8c8SToby Isaac 5966dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5976dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 5986dd5a8c8SToby Isaac } 5996dd5a8c8SToby Isaac if (qDof) { 6006dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, qDof);CHKERRQ(ierr); 6016dd5a8c8SToby Isaac } 6026dd5a8c8SToby Isaac else { 6036dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, 1);CHKERRQ(ierr); 6046dd5a8c8SToby Isaac } 6056dd5a8c8SToby Isaac } 6066dd5a8c8SToby Isaac } 6076dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 6086dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secNew,&sizeNew);CHKERRQ(ierr); 6096dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsNew);CHKERRQ(ierr); 6106dd5a8c8SToby Isaac compress = PETSC_FALSE; 6116dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6126dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 6136dd5a8c8SToby Isaac 6146dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 6156dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 6166dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dofNew);CHKERRQ(ierr); 6176dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &offNew);CHKERRQ(ierr); 6186dd5a8c8SToby Isaac count = 0; 6196dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 6206dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 6216dd5a8c8SToby Isaac 6226dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 6236dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 6246dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, q, &qOff);CHKERRQ(ierr); 6256dd5a8c8SToby Isaac } 6266dd5a8c8SToby Isaac if (qDof) { 6276dd5a8c8SToby Isaac PetscInt oldCount = count; 6286dd5a8c8SToby Isaac 6296dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 6306dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 6316dd5a8c8SToby Isaac 6326dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6336dd5a8c8SToby Isaac if (valsNew[offNew + k] == r) { 6346dd5a8c8SToby Isaac break; 6356dd5a8c8SToby Isaac } 6366dd5a8c8SToby Isaac } 6376dd5a8c8SToby Isaac if (k == oldCount) { 6386dd5a8c8SToby Isaac valsNew[offNew + count++] = r; 6396dd5a8c8SToby Isaac } 6406dd5a8c8SToby Isaac } 6416dd5a8c8SToby Isaac } 6426dd5a8c8SToby Isaac else { 6436dd5a8c8SToby Isaac PetscInt k, oldCount = count; 6446dd5a8c8SToby Isaac 6456dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6466dd5a8c8SToby Isaac if (valsNew[offNew + k] == q) { 6476dd5a8c8SToby Isaac break; 6486dd5a8c8SToby Isaac } 6496dd5a8c8SToby Isaac } 6506dd5a8c8SToby Isaac if (k == oldCount) { 6516dd5a8c8SToby Isaac valsNew[offNew + count++] = q; 6526dd5a8c8SToby Isaac } 6536dd5a8c8SToby Isaac } 6546dd5a8c8SToby Isaac } 6556dd5a8c8SToby Isaac if (count < dofNew) { 6566dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secNew, p, count);CHKERRQ(ierr); 6576dd5a8c8SToby Isaac compress = PETSC_TRUE; 6586dd5a8c8SToby Isaac } 6596dd5a8c8SToby Isaac } 6606dd5a8c8SToby Isaac } 6616dd5a8c8SToby Isaac ierr = ISRestoreIndices(is,&vals);CHKERRQ(ierr); 662b2566f29SBarry Smith ierr = MPIU_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 6636dd5a8c8SToby Isaac if (!globalAnyNew) { 6646dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6656dd5a8c8SToby Isaac *sectionNew = NULL; 6666dd5a8c8SToby Isaac *isNew = NULL; 6676dd5a8c8SToby Isaac } 6686dd5a8c8SToby Isaac else { 6696dd5a8c8SToby Isaac PetscBool globalCompress; 6706dd5a8c8SToby Isaac 671b2566f29SBarry Smith ierr = MPIU_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 6726dd5a8c8SToby Isaac if (compress) { 6736dd5a8c8SToby Isaac PetscSection secComp; 6746dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6756dd5a8c8SToby Isaac 6766dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp);CHKERRQ(ierr); 6776dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secComp,pStart,pEnd);CHKERRQ(ierr); 6786dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6796dd5a8c8SToby Isaac PetscInt dof; 6806dd5a8c8SToby Isaac 6816dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6826dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secComp, p, dof);CHKERRQ(ierr); 6836dd5a8c8SToby Isaac } 6846dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secComp);CHKERRQ(ierr); 6856dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secComp,&sizeNew);CHKERRQ(ierr); 6866dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsComp);CHKERRQ(ierr); 6876dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6886dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6896dd5a8c8SToby Isaac 6906dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6916dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &off);CHKERRQ(ierr); 6926dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secComp, p, &offNew);CHKERRQ(ierr); 6936dd5a8c8SToby Isaac for (j = 0; j < dof; j++) { 6946dd5a8c8SToby Isaac valsComp[offNew + j] = valsNew[off + j]; 6956dd5a8c8SToby Isaac } 6966dd5a8c8SToby Isaac } 6976dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6986dd5a8c8SToby Isaac secNew = secComp; 6996dd5a8c8SToby Isaac ierr = PetscFree(valsNew);CHKERRQ(ierr); 7006dd5a8c8SToby Isaac valsNew = valsComp; 7016dd5a8c8SToby Isaac } 7026dd5a8c8SToby Isaac ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew);CHKERRQ(ierr); 7036dd5a8c8SToby Isaac } 7046dd5a8c8SToby Isaac PetscFunctionReturn(0); 7056dd5a8c8SToby Isaac } 7066dd5a8c8SToby Isaac 7076dd5a8c8SToby Isaac #undef __FUNCT__ 708f7c74593SToby Isaac #define __FUNCT__ "DMPlexCreateAnchors_Tree" 709f7c74593SToby Isaac static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 71066af876cSToby Isaac { 71166af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 71266af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 71366af876cSToby Isaac PetscSection aSec; 714f9f063d4SToby Isaac DMLabel canonLabel; 71566af876cSToby Isaac IS aIS; 71666af876cSToby Isaac PetscErrorCode ierr; 71766af876cSToby Isaac 71866af876cSToby Isaac PetscFunctionBegin; 71966af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 72066af876cSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 721c58f1c22SToby Isaac ierr = DMGetLabel(dm,"canonical",&canonLabel);CHKERRQ(ierr); 72266af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 72366af876cSToby Isaac PetscInt parent; 72466af876cSToby Isaac 725f9f063d4SToby Isaac if (canonLabel) { 726f9f063d4SToby Isaac PetscInt canon; 727f9f063d4SToby Isaac 728f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 729f9f063d4SToby Isaac if (p != canon) continue; 730f9f063d4SToby Isaac } 73166af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 73266af876cSToby Isaac if (parent != p) { 73366af876cSToby Isaac aMin = PetscMin(aMin,p); 73466af876cSToby Isaac aMax = PetscMax(aMax,p+1); 73566af876cSToby Isaac } 73666af876cSToby Isaac } 73766af876cSToby Isaac if (aMin > aMax) { 73866af876cSToby Isaac aMin = -1; 73966af876cSToby Isaac aMax = -1; 74066af876cSToby Isaac } 741e228b242SToby Isaac ierr = PetscSectionCreate(PETSC_COMM_SELF,&aSec);CHKERRQ(ierr); 74266af876cSToby Isaac ierr = PetscSectionSetChart(aSec,aMin,aMax);CHKERRQ(ierr); 74366af876cSToby Isaac for (p = aMin; p < aMax; p++) { 74466af876cSToby Isaac PetscInt parent, ancestor = p; 74566af876cSToby Isaac 746f9f063d4SToby Isaac if (canonLabel) { 747f9f063d4SToby Isaac PetscInt canon; 748f9f063d4SToby Isaac 749f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 750f9f063d4SToby Isaac if (p != canon) continue; 751f9f063d4SToby Isaac } 75266af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 75366af876cSToby Isaac while (parent != ancestor) { 75466af876cSToby Isaac ancestor = parent; 75566af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 75666af876cSToby Isaac } 75766af876cSToby Isaac if (ancestor != p) { 75866af876cSToby Isaac PetscInt closureSize, *closure = NULL; 75966af876cSToby Isaac 76066af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 76166af876cSToby Isaac ierr = PetscSectionSetDof(aSec,p,closureSize);CHKERRQ(ierr); 76266af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 76366af876cSToby Isaac } 76466af876cSToby Isaac } 76566af876cSToby Isaac ierr = PetscSectionSetUp(aSec);CHKERRQ(ierr); 76666af876cSToby Isaac ierr = PetscSectionGetStorageSize(aSec,&size);CHKERRQ(ierr); 76766af876cSToby Isaac ierr = PetscMalloc1(size,&anchors);CHKERRQ(ierr); 76866af876cSToby Isaac for (p = aMin; p < aMax; p++) { 76966af876cSToby Isaac PetscInt parent, ancestor = p; 77066af876cSToby Isaac 771f9f063d4SToby Isaac if (canonLabel) { 772f9f063d4SToby Isaac PetscInt canon; 773f9f063d4SToby Isaac 774f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 775f9f063d4SToby Isaac if (p != canon) continue; 776f9f063d4SToby Isaac } 77766af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 77866af876cSToby Isaac while (parent != ancestor) { 77966af876cSToby Isaac ancestor = parent; 78066af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 78166af876cSToby Isaac } 78266af876cSToby Isaac if (ancestor != p) { 78366af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 78466af876cSToby Isaac 78566af876cSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 78666af876cSToby Isaac 78766af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 78866af876cSToby Isaac for (j = 0; j < closureSize; j++) { 78966af876cSToby Isaac anchors[aOff + j] = closure[2*j]; 79066af876cSToby Isaac } 79166af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 79266af876cSToby Isaac } 79366af876cSToby Isaac } 794e228b242SToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,size,anchors,PETSC_OWN_POINTER,&aIS);CHKERRQ(ierr); 7956dd5a8c8SToby Isaac { 7966dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7976dd5a8c8SToby Isaac IS aISNew = aIS; 7986dd5a8c8SToby Isaac 7996dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aSec);CHKERRQ(ierr); 8006dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aIS);CHKERRQ(ierr); 8016dd5a8c8SToby Isaac while (aSecNew) { 8026dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 8036dd5a8c8SToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 8046dd5a8c8SToby Isaac aSec = aSecNew; 8056dd5a8c8SToby Isaac aIS = aISNew; 8066dd5a8c8SToby Isaac aSecNew = NULL; 8076dd5a8c8SToby Isaac aISNew = NULL; 8086dd5a8c8SToby Isaac ierr = AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew);CHKERRQ(ierr); 8096dd5a8c8SToby Isaac } 8106dd5a8c8SToby Isaac } 811a17985deSToby Isaac ierr = DMPlexSetAnchors(dm,aSec,aIS);CHKERRQ(ierr); 81266af876cSToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 81366af876cSToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 81466af876cSToby Isaac PetscFunctionReturn(0); 81566af876cSToby Isaac } 81666af876cSToby Isaac 81766af876cSToby Isaac #undef __FUNCT__ 8186461c1adSToby Isaac #define __FUNCT__ "DMPlexGetTrueSupportSize" 8196461c1adSToby Isaac static PetscErrorCode DMPlexGetTrueSupportSize(DM dm,PetscInt p,PetscInt *dof,PetscInt *numTrueSupp) 8206461c1adSToby Isaac { 8216461c1adSToby Isaac PetscErrorCode ierr; 8226461c1adSToby Isaac 8236461c1adSToby Isaac PetscFunctionBegin; 8246461c1adSToby Isaac if (numTrueSupp[p] == -1) { 8256461c1adSToby Isaac PetscInt i, alldof; 8266461c1adSToby Isaac const PetscInt *supp; 8276461c1adSToby Isaac PetscInt count = 0; 8286461c1adSToby Isaac 8296461c1adSToby Isaac ierr = DMPlexGetSupportSize(dm,p,&alldof);CHKERRQ(ierr); 8306461c1adSToby Isaac ierr = DMPlexGetSupport(dm,p,&supp);CHKERRQ(ierr); 8316461c1adSToby Isaac for (i = 0; i < alldof; i++) { 8326461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 8336461c1adSToby Isaac const PetscInt *cone; 8346461c1adSToby Isaac 8356461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr); 8366461c1adSToby Isaac ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr); 8376461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8386461c1adSToby Isaac if (cone[j] == p) break; 8396461c1adSToby Isaac } 8406461c1adSToby Isaac if (j < numCones) count++; 8416461c1adSToby Isaac } 8426461c1adSToby Isaac numTrueSupp[p] = count; 8436461c1adSToby Isaac } 8446461c1adSToby Isaac *dof = numTrueSupp[p]; 8456461c1adSToby Isaac PetscFunctionReturn(0); 8466461c1adSToby Isaac } 8476461c1adSToby Isaac 8486461c1adSToby Isaac #undef __FUNCT__ 849776742edSToby Isaac #define __FUNCT__ "DMPlexTreeExchangeSupports" 850776742edSToby Isaac static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 851776742edSToby Isaac { 852776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 853776742edSToby Isaac PetscSection newSupportSection; 854776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 8556461c1adSToby Isaac PetscInt *numTrueSupp; 856776742edSToby Isaac PetscInt *offsets; 857776742edSToby Isaac PetscErrorCode ierr; 858776742edSToby Isaac 859776742edSToby Isaac PetscFunctionBegin; 860776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 861776742edSToby Isaac /* symmetrize the hierarchy */ 862776742edSToby Isaac ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 863e228b242SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)),&newSupportSection);CHKERRQ(ierr); 864776742edSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 865776742edSToby Isaac ierr = PetscSectionSetChart(newSupportSection,pStart,pEnd);CHKERRQ(ierr); 866776742edSToby Isaac ierr = PetscCalloc1(pEnd,&offsets);CHKERRQ(ierr); 8676461c1adSToby Isaac ierr = PetscMalloc1(pEnd,&numTrueSupp);CHKERRQ(ierr); 8686461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 8696461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 870776742edSToby Isaac * parent(q) */ 871776742edSToby Isaac for (d = 0; d <= depth; d++) { 872776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 873776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 874776742edSToby Isaac PetscInt dof, q, qdof, parent; 875776742edSToby Isaac 8766461c1adSToby Isaac ierr = DMPlexGetTrueSupportSize(dm,p,&dof,numTrueSupp);CHKERRQ(ierr); 877776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection, p, dof);CHKERRQ(ierr); 878776742edSToby Isaac q = p; 879776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 880776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 881776742edSToby Isaac q = parent; 882776742edSToby Isaac 8836461c1adSToby Isaac ierr = DMPlexGetTrueSupportSize(dm,q,&qdof,numTrueSupp);CHKERRQ(ierr); 884776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,p,qdof);CHKERRQ(ierr); 885776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,q,dof);CHKERRQ(ierr); 886776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 887776742edSToby Isaac } 888776742edSToby Isaac } 889776742edSToby Isaac } 890776742edSToby Isaac ierr = PetscSectionSetUp(newSupportSection);CHKERRQ(ierr); 891776742edSToby Isaac ierr = PetscSectionGetStorageSize(newSupportSection,&newSize);CHKERRQ(ierr); 892776742edSToby Isaac ierr = PetscMalloc1(newSize,&newSupports);CHKERRQ(ierr); 893776742edSToby Isaac for (d = 0; d <= depth; d++) { 894776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 895776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 896776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 897776742edSToby Isaac 898776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 899776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 900776742edSToby Isaac ierr = PetscSectionGetDof(newSupportSection, p, &newDof);CHKERRQ(ierr); 901776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, p, &newOff);CHKERRQ(ierr); 902776742edSToby Isaac for (i = 0; i < dof; i++) { 9036461c1adSToby Isaac PetscInt numCones, j; 9046461c1adSToby Isaac const PetscInt *cone; 9056461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 9066461c1adSToby Isaac 9076461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr); 9086461c1adSToby Isaac ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr); 9096461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9106461c1adSToby Isaac if (cone[j] == p) break; 9116461c1adSToby Isaac } 9126461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = q; 913776742edSToby Isaac } 914776742edSToby Isaac mesh->maxSupportSize = PetscMax(mesh->maxSupportSize,newDof); 915776742edSToby Isaac 916776742edSToby Isaac q = p; 917776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 918776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 919776742edSToby Isaac q = parent; 920776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, q, &qdof);CHKERRQ(ierr); 921776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, q, &qoff);CHKERRQ(ierr); 922776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, q, &newqOff);CHKERRQ(ierr); 923776742edSToby Isaac for (i = 0; i < qdof; i++) { 9246461c1adSToby Isaac PetscInt numCones, j; 9256461c1adSToby Isaac const PetscInt *cone; 9266461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 9276461c1adSToby Isaac 9286461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr); 9296461c1adSToby Isaac ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr); 9306461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9316461c1adSToby Isaac if (cone[j] == q) break; 9326461c1adSToby Isaac } 9336461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = r; 934776742edSToby Isaac } 935776742edSToby Isaac for (i = 0; i < dof; i++) { 9366461c1adSToby Isaac PetscInt numCones, j; 9376461c1adSToby Isaac const PetscInt *cone; 9386461c1adSToby Isaac PetscInt r = mesh->supports[off + i]; 9396461c1adSToby Isaac 9406461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr); 9416461c1adSToby Isaac ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr); 9426461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9436461c1adSToby Isaac if (cone[j] == p) break; 9446461c1adSToby Isaac } 9456461c1adSToby Isaac if (j < numCones) newSupports[newqOff+offsets[q]++] = r; 946776742edSToby Isaac } 947776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 948776742edSToby Isaac } 949776742edSToby Isaac } 950776742edSToby Isaac } 951776742edSToby Isaac ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 952776742edSToby Isaac mesh->supportSection = newSupportSection; 953776742edSToby Isaac ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 954776742edSToby Isaac mesh->supports = newSupports; 955776742edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 9566461c1adSToby Isaac ierr = PetscFree(numTrueSupp);CHKERRQ(ierr); 957776742edSToby Isaac 958776742edSToby Isaac PetscFunctionReturn(0); 959776742edSToby Isaac } 960776742edSToby Isaac 961f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM,PetscSection,PetscSection,Mat); 962f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM,PetscSection,PetscSection,Mat); 963f7c74593SToby Isaac 964776742edSToby Isaac #undef __FUNCT__ 965f9f063d4SToby Isaac #define __FUNCT__ "DMPlexSetTree_Internal" 966776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 967f9f063d4SToby Isaac { 968f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 969f9f063d4SToby Isaac DM refTree; 970f9f063d4SToby Isaac PetscInt size; 971f9f063d4SToby Isaac PetscErrorCode ierr; 972f9f063d4SToby Isaac 973f9f063d4SToby Isaac PetscFunctionBegin; 974f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 975f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 976f9f063d4SToby Isaac ierr = PetscObjectReference((PetscObject)parentSection);CHKERRQ(ierr); 977f9f063d4SToby Isaac ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 978f9f063d4SToby Isaac mesh->parentSection = parentSection; 979f9f063d4SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&size);CHKERRQ(ierr); 980f9f063d4SToby Isaac if (parents != mesh->parents) { 981f9f063d4SToby Isaac ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 982f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->parents);CHKERRQ(ierr); 983f9f063d4SToby Isaac ierr = PetscMemcpy(mesh->parents, parents, size * sizeof(*parents));CHKERRQ(ierr); 984f9f063d4SToby Isaac } 985f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 986f9f063d4SToby Isaac ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 987f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->childIDs);CHKERRQ(ierr); 988f9f063d4SToby Isaac ierr = PetscMemcpy(mesh->childIDs, childIDs, size * sizeof(*childIDs));CHKERRQ(ierr); 989f9f063d4SToby Isaac } 990f9f063d4SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 991f9f063d4SToby Isaac if (refTree) { 992f9f063d4SToby Isaac DMLabel canonLabel; 993f9f063d4SToby Isaac 994c58f1c22SToby Isaac ierr = DMGetLabel(refTree,"canonical",&canonLabel);CHKERRQ(ierr); 995f9f063d4SToby Isaac if (canonLabel) { 996f9f063d4SToby Isaac PetscInt i; 997f9f063d4SToby Isaac 998f9f063d4SToby Isaac for (i = 0; i < size; i++) { 999f9f063d4SToby Isaac PetscInt canon; 1000f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon);CHKERRQ(ierr); 1001f9f063d4SToby Isaac if (canon >= 0) { 1002f9f063d4SToby Isaac mesh->childIDs[i] = canon; 1003f9f063d4SToby Isaac } 1004f9f063d4SToby Isaac } 1005f9f063d4SToby Isaac } 1006f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 1007f7c74593SToby Isaac } 1008f7c74593SToby Isaac else { 1009f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 1010f9f063d4SToby Isaac } 1011f9f063d4SToby Isaac ierr = DMPlexTreeSymmetrize(dm);CHKERRQ(ierr); 1012f9f063d4SToby Isaac if (computeCanonical) { 1013f9f063d4SToby Isaac PetscInt d, dim; 1014f9f063d4SToby Isaac 1015f9f063d4SToby Isaac /* add the canonical label */ 101628f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 1017c58f1c22SToby Isaac ierr = DMCreateLabel(dm,"canonical");CHKERRQ(ierr); 1018f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 1019f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 1020f9f063d4SToby Isaac const PetscInt *cChildren; 1021f9f063d4SToby Isaac 1022f9f063d4SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 1023f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1024f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&cNumChildren,&cChildren);CHKERRQ(ierr); 1025f9f063d4SToby Isaac if (cNumChildren) { 1026f9f063d4SToby Isaac canon = p; 1027f9f063d4SToby Isaac break; 1028f9f063d4SToby Isaac } 1029f9f063d4SToby Isaac } 1030f9f063d4SToby Isaac if (canon == -1) continue; 1031f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1032f9f063d4SToby Isaac PetscInt numChildren, i; 1033f9f063d4SToby Isaac const PetscInt *children; 1034f9f063d4SToby Isaac 1035f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&numChildren,&children);CHKERRQ(ierr); 1036f9f063d4SToby Isaac if (numChildren) { 1037f9f063d4SToby Isaac if (numChildren != cNumChildren) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"All parent points in a stratum should have the same number of children: %d != %d", numChildren, cNumChildren); 1038c58f1c22SToby Isaac ierr = DMSetLabelValue(dm,"canonical",p,canon);CHKERRQ(ierr); 1039f9f063d4SToby Isaac for (i = 0; i < numChildren; i++) { 1040c58f1c22SToby Isaac ierr = DMSetLabelValue(dm,"canonical",children[i],cChildren[i]);CHKERRQ(ierr); 1041f9f063d4SToby Isaac } 1042f9f063d4SToby Isaac } 1043f9f063d4SToby Isaac } 1044f9f063d4SToby Isaac } 1045f9f063d4SToby Isaac } 1046776742edSToby Isaac if (exchangeSupports) { 1047776742edSToby Isaac ierr = DMPlexTreeExchangeSupports(dm);CHKERRQ(ierr); 1048776742edSToby Isaac } 1049f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 1050f7c74593SToby Isaac /* reset anchors */ 1051f7c74593SToby Isaac ierr = DMPlexSetAnchors(dm,NULL,NULL);CHKERRQ(ierr); 1052f9f063d4SToby Isaac PetscFunctionReturn(0); 1053f9f063d4SToby Isaac } 1054f9f063d4SToby Isaac 1055f9f063d4SToby Isaac #undef __FUNCT__ 10560b7167a0SToby Isaac #define __FUNCT__ "DMPlexSetTree" 10570b7167a0SToby Isaac /*@ 10580b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 10590b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 10600b7167a0SToby Isaac tree root. 10610b7167a0SToby Isaac 10620b7167a0SToby Isaac Collective on dm 10630b7167a0SToby Isaac 10640b7167a0SToby Isaac Input Parameters: 10650b7167a0SToby Isaac + dm - the DMPlex object 10660b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 10670b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 10680b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 10690b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 10700b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 10710b7167a0SToby Isaac 10720b7167a0SToby Isaac Level: intermediate 10730b7167a0SToby Isaac 1074a17985deSToby Isaac .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 10750b7167a0SToby Isaac @*/ 1076b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 10770b7167a0SToby Isaac { 10780b7167a0SToby Isaac PetscErrorCode ierr; 10790b7167a0SToby Isaac 10800b7167a0SToby Isaac PetscFunctionBegin; 1081776742edSToby Isaac ierr = DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 10820b7167a0SToby Isaac PetscFunctionReturn(0); 10830b7167a0SToby Isaac } 10840b7167a0SToby Isaac 10850b7167a0SToby Isaac #undef __FUNCT__ 1086b2f41788SToby Isaac #define __FUNCT__ "DMPlexGetTree" 1087b2f41788SToby Isaac /*@ 1088b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 1089b2f41788SToby Isaac Collective on dm 1090b2f41788SToby Isaac 1091b2f41788SToby Isaac Input Parameters: 1092b2f41788SToby Isaac . dm - the DMPlex object 1093b2f41788SToby Isaac 1094b2f41788SToby Isaac Output Parameters: 1095b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1096b2f41788SToby Isaac offset indexes the parent and childID list 1097b2f41788SToby Isaac . parents - a list of the point parents 1098b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1099b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1100b2f41788SToby Isaac . childSection - the inverse of the parent section 1101b2f41788SToby Isaac - children - a list of the point children 1102b2f41788SToby Isaac 1103b2f41788SToby Isaac Level: intermediate 1104b2f41788SToby Isaac 1105a17985deSToby Isaac .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 1106b2f41788SToby Isaac @*/ 1107b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1108b2f41788SToby Isaac { 1109b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1110b2f41788SToby Isaac 1111b2f41788SToby Isaac PetscFunctionBegin; 1112b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1113b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1114b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1115b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1116b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1117b2f41788SToby Isaac if (children) *children = mesh->children; 1118b2f41788SToby Isaac PetscFunctionReturn(0); 1119b2f41788SToby Isaac } 1120b2f41788SToby Isaac 1121b2f41788SToby Isaac #undef __FUNCT__ 1122d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeParent" 1123d961a43aSToby Isaac /*@ 1124d961a43aSToby Isaac DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the Sieve DAG) 1125d961a43aSToby Isaac 1126d961a43aSToby Isaac Input Parameters: 1127d961a43aSToby Isaac + dm - the DMPlex object 1128d961a43aSToby Isaac - point - the query point 1129d961a43aSToby Isaac 1130d961a43aSToby Isaac Output Parameters: 1131d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 1132d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 1133d961a43aSToby Isaac does not have a parent 1134d961a43aSToby Isaac 1135d961a43aSToby Isaac Level: intermediate 1136d961a43aSToby Isaac 1137d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren() 1138d961a43aSToby Isaac @*/ 1139d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1140d961a43aSToby Isaac { 1141d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1142d961a43aSToby Isaac PetscSection pSec; 1143d961a43aSToby Isaac PetscErrorCode ierr; 1144d961a43aSToby Isaac 1145d961a43aSToby Isaac PetscFunctionBegin; 1146d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1147d961a43aSToby Isaac pSec = mesh->parentSection; 1148d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1149d961a43aSToby Isaac PetscInt dof; 1150d961a43aSToby Isaac 1151d961a43aSToby Isaac ierr = PetscSectionGetDof (pSec, point, &dof);CHKERRQ(ierr); 1152d961a43aSToby Isaac if (dof) { 1153d961a43aSToby Isaac PetscInt off; 1154d961a43aSToby Isaac 1155d961a43aSToby Isaac ierr = PetscSectionGetOffset (pSec, point, &off);CHKERRQ(ierr); 1156d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1157d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 1158d961a43aSToby Isaac PetscFunctionReturn(0); 1159d961a43aSToby Isaac } 1160d961a43aSToby Isaac } 1161d961a43aSToby Isaac if (parent) { 1162d961a43aSToby Isaac *parent = point; 1163d961a43aSToby Isaac } 1164d961a43aSToby Isaac if (childID) { 1165d961a43aSToby Isaac *childID = 0; 1166d961a43aSToby Isaac } 1167d961a43aSToby Isaac PetscFunctionReturn(0); 1168d961a43aSToby Isaac } 1169d961a43aSToby Isaac 1170d961a43aSToby Isaac #undef __FUNCT__ 1171d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeChildren" 1172d961a43aSToby Isaac /*@C 1173d961a43aSToby Isaac DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the Sieve DAG) 1174d961a43aSToby Isaac 1175d961a43aSToby Isaac Input Parameters: 1176d961a43aSToby Isaac + dm - the DMPlex object 1177d961a43aSToby Isaac - point - the query point 1178d961a43aSToby Isaac 1179d961a43aSToby Isaac Output Parameters: 1180d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 1181d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 1182d961a43aSToby Isaac 1183d961a43aSToby Isaac Level: intermediate 1184d961a43aSToby Isaac 1185d961a43aSToby Isaac Fortran Notes: 1186d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1187d961a43aSToby Isaac include petsc.h90 in your code. 1188d961a43aSToby Isaac 1189d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent() 1190d961a43aSToby Isaac @*/ 1191d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1192d961a43aSToby Isaac { 1193d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1194d961a43aSToby Isaac PetscSection childSec; 1195d961a43aSToby Isaac PetscInt dof = 0; 1196d961a43aSToby Isaac PetscErrorCode ierr; 1197d961a43aSToby Isaac 1198d961a43aSToby Isaac PetscFunctionBegin; 1199d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1200d961a43aSToby Isaac childSec = mesh->childSection; 1201d961a43aSToby Isaac if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 1202d961a43aSToby Isaac ierr = PetscSectionGetDof (childSec, point, &dof);CHKERRQ(ierr); 1203d961a43aSToby Isaac } 1204d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1205d961a43aSToby Isaac if (children) { 1206d961a43aSToby Isaac if (dof) { 1207d961a43aSToby Isaac PetscInt off; 1208d961a43aSToby Isaac 1209d961a43aSToby Isaac ierr = PetscSectionGetOffset (childSec, point, &off);CHKERRQ(ierr); 1210d961a43aSToby Isaac *children = &mesh->children[off]; 1211d961a43aSToby Isaac } 1212d961a43aSToby Isaac else { 1213d961a43aSToby Isaac *children = NULL; 1214d961a43aSToby Isaac } 1215d961a43aSToby Isaac } 1216d961a43aSToby Isaac PetscFunctionReturn(0); 1217d961a43aSToby Isaac } 12180c37af3bSToby Isaac 12190c37af3bSToby Isaac #undef __FUNCT__ 1220*b3a4bf2aSToby Isaac #define __FUNCT__ "EvaluateBasis" 1221*b3a4bf2aSToby Isaac static PetscErrorCode EvaluateBasis(PetscSpace space, PetscInt nFunctionals, PetscInt nPoints, const PetscInt *pointsPerFn, const PetscReal *points, const PetscReal *weights, PetscReal *work, Mat basisAtPoints) 1222*b3a4bf2aSToby Isaac { 1223*b3a4bf2aSToby Isaac PetscInt i, j, k, offset, qPoints; 1224*b3a4bf2aSToby Isaac PetscErrorCode ierr; 1225*b3a4bf2aSToby Isaac 1226*b3a4bf2aSToby Isaac PetscFunctionBegin; 1227*b3a4bf2aSToby Isaac ierr = PetscSpaceEvaluate(space,nPoints,points,work,NULL,NULL);CHKERRQ(ierr); 1228*b3a4bf2aSToby Isaac for (i = 0, offset = 0; i < nFunctionals; i++) { 1229*b3a4bf2aSToby Isaac qPoints = pointsPerFn[i]; 1230*b3a4bf2aSToby Isaac for (j = 0; j < nFunctionals; j++) { 1231*b3a4bf2aSToby Isaac PetscScalar val = 0.; 1232*b3a4bf2aSToby Isaac 1233*b3a4bf2aSToby Isaac for (k = 0; k < qPoints; k++) { 1234*b3a4bf2aSToby Isaac val += work[(offset + k) * nFunctionals + j] * weights[k]; 1235*b3a4bf2aSToby Isaac } 1236*b3a4bf2aSToby Isaac ierr = MatSetValue(basisAtPoints,j,i,val,INSERT_VALUES);CHKERRQ(ierr); 1237*b3a4bf2aSToby Isaac } 1238*b3a4bf2aSToby Isaac offset += qPoints; 1239*b3a4bf2aSToby Isaac } 1240*b3a4bf2aSToby Isaac ierr = MatAssemblyBegin(basisAtPoints,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1241*b3a4bf2aSToby Isaac ierr = MatAssemblyEnd(basisAtPoints,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1242*b3a4bf2aSToby Isaac PetscFunctionReturn(0); 1243*b3a4bf2aSToby Isaac } 1244*b3a4bf2aSToby Isaac 1245*b3a4bf2aSToby Isaac #undef __FUNCT__ 1246f7c74593SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_Direct" 1247f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 12480c37af3bSToby Isaac { 12490c37af3bSToby Isaac PetscDS ds; 12500c37af3bSToby Isaac PetscInt spdim; 12510c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 12520c37af3bSToby Isaac const PetscInt *anchors; 1253f7c74593SToby Isaac PetscSection aSec; 12540c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 12550c37af3bSToby Isaac IS aIS; 12560c37af3bSToby Isaac PetscErrorCode ierr; 12570c37af3bSToby Isaac 12580c37af3bSToby Isaac PetscFunctionBegin; 12590c37af3bSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 12600c37af3bSToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 12610c37af3bSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 12620c37af3bSToby Isaac ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 1263a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 12640c37af3bSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 12650c37af3bSToby Isaac ierr = PetscSectionGetChart(cSec,&conStart,&conEnd);CHKERRQ(ierr); 126628f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&spdim);CHKERRQ(ierr); 12670c37af3bSToby Isaac ierr = PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent);CHKERRQ(ierr); 12680c37af3bSToby Isaac 12690c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 12700dd1b1feSToby Isaac PetscObject disc; 12710dd1b1feSToby Isaac PetscClassId id; 1272*b3a4bf2aSToby Isaac PetscSpace bspace; 1273*b3a4bf2aSToby Isaac PetscDualSpace dspace; 12740c37af3bSToby Isaac PetscInt i, j, k, nPoints, offset; 12750c37af3bSToby Isaac PetscInt fSize, fComp; 1276*b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 1277*b3a4bf2aSToby Isaac PetscInt *sizes; 12780c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 12790c37af3bSToby Isaac 12800dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 12810dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 12820dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1283*b3a4bf2aSToby Isaac PetscFE fe = (PetscFE) disc; 1284*b3a4bf2aSToby Isaac 1285*b3a4bf2aSToby Isaac ierr = PetscFEGetBasisSpace(fe,&bspace);CHKERRQ(ierr); 1286*b3a4bf2aSToby Isaac ierr = PetscFEGetDualSpace(fe,&dspace);CHKERRQ(ierr); 1287*b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetDimension(dspace,&fSize);CHKERRQ(ierr); 12880c37af3bSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 12890dd1b1feSToby Isaac } 12900dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 1291*b3a4bf2aSToby Isaac PetscFV fv = (PetscFV) disc; 1292*b3a4bf2aSToby Isaac 1293*b3a4bf2aSToby Isaac ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)fv),&bspace);CHKERRQ(ierr); 1294*b3a4bf2aSToby Isaac ierr = PetscSpaceSetType(bspace,PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr); 1295*b3a4bf2aSToby Isaac ierr = PetscSpaceSetOrder(bspace,0);CHKERRQ(ierr); 1296*b3a4bf2aSToby Isaac ierr = PetscSpacePolynomialSetNumVariables(bspace,spdim);CHKERRQ(ierr); 1297*b3a4bf2aSToby Isaac ierr = PetscSpaceSetUp(bspace);CHKERRQ(ierr); 1298*b3a4bf2aSToby Isaac ierr = PetscFVGetDualSpace(fv,&dspace);CHKERRQ(ierr); 1299*b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetDimension(dspace,&fSize);CHKERRQ(ierr); 13000dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 13010dd1b1feSToby Isaac } 13020dd1b1feSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 13030dd1b1feSToby Isaac 13040c37af3bSToby Isaac ierr = MatCreate(PETSC_COMM_SELF,&Amat);CHKERRQ(ierr); 13050c37af3bSToby Isaac ierr = MatSetSizes(Amat,fSize,fSize,fSize,fSize);CHKERRQ(ierr); 13060c37af3bSToby Isaac ierr = MatSetType(Amat,MATSEQDENSE);CHKERRQ(ierr); 13070c37af3bSToby Isaac ierr = MatSetUp(Amat);CHKERRQ(ierr); 13080c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat);CHKERRQ(ierr); 13090c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat);CHKERRQ(ierr); 13100c37af3bSToby Isaac nPoints = 0; 13110c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 13120c37af3bSToby Isaac PetscInt qPoints; 13130c37af3bSToby Isaac PetscQuadrature quad; 13140c37af3bSToby Isaac 1315*b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetFunctional(dspace,i,&quad);CHKERRQ(ierr); 13160c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 13170c37af3bSToby Isaac nPoints += qPoints; 13180c37af3bSToby Isaac } 1319*b3a4bf2aSToby Isaac ierr = PetscMalloc5(fSize,&sizes,nPoints,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal,fSize*nPoints,&work);CHKERRQ(ierr); 13200c37af3bSToby Isaac offset = 0; 13210c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 13220c37af3bSToby Isaac PetscInt qPoints; 13230c37af3bSToby Isaac const PetscReal *p, *w; 13240c37af3bSToby Isaac PetscQuadrature quad; 13250c37af3bSToby Isaac 1326*b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetFunctional(dspace,i,&quad);CHKERRQ(ierr); 13270c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,&p,&w);CHKERRQ(ierr); 13280c37af3bSToby Isaac ierr = PetscMemcpy(weights+offset,w,qPoints*sizeof(*w));CHKERRQ(ierr); 13290c37af3bSToby Isaac ierr = PetscMemcpy(pointsRef+spdim*offset,p,spdim*qPoints*sizeof(*p));CHKERRQ(ierr); 1330*b3a4bf2aSToby Isaac sizes[i] = qPoints; 13310c37af3bSToby Isaac offset += qPoints; 13320c37af3bSToby Isaac } 1333*b3a4bf2aSToby Isaac ierr = EvaluateBasis(bspace,fSize,nPoints,sizes,pointsRef,weights,work,Amat);CHKERRQ(ierr); 13340c37af3bSToby Isaac ierr = MatLUFactor(Amat,NULL,NULL,NULL);CHKERRQ(ierr); 13350c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 13360c37af3bSToby Isaac PetscInt parent; 13370c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 13380c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 13390c37af3bSToby Isaac 13400c37af3bSToby Isaac ierr = DMPlexGetTreeParent(dm,c,&parent,NULL);CHKERRQ(ierr); 13410c37af3bSToby Isaac if (parent == c) continue; 13420c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13430c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13440c37af3bSToby Isaac PetscInt p = closure[2*i]; 13450c37af3bSToby Isaac PetscInt conDof; 13460c37af3bSToby Isaac 13470c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 13480c37af3bSToby Isaac if (numFields > 1) { 13490c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 13500c37af3bSToby Isaac } 13510c37af3bSToby Isaac else { 13520c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 13530c37af3bSToby Isaac } 13540c37af3bSToby Isaac if (conDof) break; 13550c37af3bSToby Isaac } 13560c37af3bSToby Isaac if (i == closureSize) { 13570c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13580c37af3bSToby Isaac continue; 13590c37af3bSToby Isaac } 13600c37af3bSToby Isaac 136173a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 136273a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent);CHKERRQ(ierr); 13630c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1364*b3a4bf2aSToby Isaac CoordinatesRefToReal(spdim, spdim, v0, J, &pointsRef[i*spdim],vtmp); 1365*b3a4bf2aSToby Isaac CoordinatesRealToRef(spdim, spdim, v0parent, invJparent, vtmp, &pointsReal[i*spdim]); 13660c37af3bSToby Isaac } 1367*b3a4bf2aSToby Isaac ierr = EvaluateBasis(bspace,fSize,nPoints,sizes,pointsReal,weights,work,Bmat);CHKERRQ(ierr); 13680c37af3bSToby Isaac ierr = MatMatSolve(Amat,Bmat,Xmat);CHKERRQ(ierr); 13690c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 13700c37af3bSToby Isaac ierr = PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets);CHKERRQ(ierr); 13710c37af3bSToby Isaac childOffsets[0] = 0; 13720c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13730c37af3bSToby Isaac PetscInt p = closure[2*i]; 13740c37af3bSToby Isaac PetscInt dof; 13750c37af3bSToby Isaac 13760c37af3bSToby Isaac if (numFields > 1) { 13770c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 13780c37af3bSToby Isaac } 13790c37af3bSToby Isaac else { 13800c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 13810c37af3bSToby Isaac } 13820c37af3bSToby Isaac childOffsets[i+1]=childOffsets[i]+dof / fComp; 13830c37af3bSToby Isaac } 13840c37af3bSToby Isaac parentOffsets[0] = 0; 13850c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 13860c37af3bSToby Isaac PetscInt p = closureP[2*i]; 13870c37af3bSToby Isaac PetscInt dof; 13880c37af3bSToby Isaac 13890c37af3bSToby Isaac if (numFields > 1) { 13900c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 13910c37af3bSToby Isaac } 13920c37af3bSToby Isaac else { 13930c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 13940c37af3bSToby Isaac } 13950c37af3bSToby Isaac parentOffsets[i+1]=parentOffsets[i]+dof / fComp; 13960c37af3bSToby Isaac } 13970c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13980c37af3bSToby Isaac PetscInt conDof, conOff, aDof, aOff; 13990c37af3bSToby Isaac PetscInt p = closure[2*i]; 14000c37af3bSToby Isaac PetscInt o = closure[2*i+1]; 14010c37af3bSToby Isaac 14020c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 14030c37af3bSToby Isaac if (numFields > 1) { 14040c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 14050c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(cSec,p,f,&conOff);CHKERRQ(ierr); 14060c37af3bSToby Isaac } 14070c37af3bSToby Isaac else { 14080c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 14090c37af3bSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&conOff);CHKERRQ(ierr); 14100c37af3bSToby Isaac } 14110c37af3bSToby Isaac if (!conDof) continue; 14120c37af3bSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 14130c37af3bSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 14140c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 14150c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 14160c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 14170c37af3bSToby Isaac 14180c37af3bSToby Isaac if (numFields > 1) { 14190c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,a,f,&aSecDof);CHKERRQ(ierr); 14200c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(section,a,f,&aSecOff);CHKERRQ(ierr); 14210c37af3bSToby Isaac } 14220c37af3bSToby Isaac else { 14230c37af3bSToby Isaac ierr = PetscSectionGetDof(section,a,&aSecDof);CHKERRQ(ierr); 14240c37af3bSToby Isaac ierr = PetscSectionGetOffset(section,a,&aSecOff);CHKERRQ(ierr); 14250c37af3bSToby Isaac } 14260c37af3bSToby Isaac if (!aSecDof) continue; 14270c37af3bSToby Isaac 14280c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 14290c37af3bSToby Isaac PetscInt q = closureP[2*j]; 14300c37af3bSToby Isaac PetscInt oq = closureP[2*j+1]; 14310c37af3bSToby Isaac 14320c37af3bSToby Isaac if (q == a) { 14330c37af3bSToby Isaac PetscInt r, s, t; 14340c37af3bSToby Isaac 14350c37af3bSToby Isaac for (r = childOffsets[i]; r < childOffsets[i+1]; r++) { 14360c37af3bSToby Isaac for (s = parentOffsets[j]; s < parentOffsets[j+1]; s++) { 14370c37af3bSToby Isaac PetscScalar val; 14380c37af3bSToby Isaac PetscInt insertCol, insertRow; 14390c37af3bSToby Isaac 1440*b3a4bf2aSToby Isaac ierr = MatGetValue(Xmat,s,r,&val);CHKERRQ(ierr); 14410c37af3bSToby Isaac if (o >= 0) { 14420c37af3bSToby Isaac insertRow = conOff + fComp * (r - childOffsets[i]); 14430c37af3bSToby Isaac } 14440c37af3bSToby Isaac else { 14450c37af3bSToby Isaac insertRow = conOff + fComp * (childOffsets[i + 1] - 1 - r); 14460c37af3bSToby Isaac } 14470c37af3bSToby Isaac if (oq >= 0) { 14480c37af3bSToby Isaac insertCol = aSecOff + fComp * (s - parentOffsets[j]); 14490c37af3bSToby Isaac } 14500c37af3bSToby Isaac else { 14510c37af3bSToby Isaac insertCol = aSecOff + fComp * (parentOffsets[j + 1] - 1 - s); 14520c37af3bSToby Isaac } 14530c37af3bSToby Isaac for (t = 0; t < fComp; t++) { 14540c37af3bSToby Isaac ierr = MatSetValue(cMat,insertRow + t,insertCol + t,val,INSERT_VALUES);CHKERRQ(ierr); 14550c37af3bSToby Isaac } 14560c37af3bSToby Isaac } 14570c37af3bSToby Isaac } 14580c37af3bSToby Isaac } 14590c37af3bSToby Isaac } 14600c37af3bSToby Isaac } 14610c37af3bSToby Isaac } 14620c37af3bSToby Isaac ierr = PetscFree2(childOffsets,parentOffsets);CHKERRQ(ierr); 14630c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 14640c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 14650c37af3bSToby Isaac } 14660c37af3bSToby Isaac ierr = MatDestroy(&Amat);CHKERRQ(ierr); 14670c37af3bSToby Isaac ierr = MatDestroy(&Bmat);CHKERRQ(ierr); 14680c37af3bSToby Isaac ierr = MatDestroy(&Xmat);CHKERRQ(ierr); 1469*b3a4bf2aSToby Isaac ierr = PetscFree5(sizes,weights,pointsRef,pointsReal,work);CHKERRQ(ierr); 1470*b3a4bf2aSToby Isaac if (id == PETSCFV_CLASSID) { 1471*b3a4bf2aSToby Isaac ierr = PetscSpaceDestroy(&bspace);CHKERRQ(ierr); 1472*b3a4bf2aSToby Isaac } 14730c37af3bSToby Isaac } 14740c37af3bSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14750c37af3bSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14760c37af3bSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent);CHKERRQ(ierr); 14770c37af3bSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 14780c37af3bSToby Isaac 14790c37af3bSToby Isaac PetscFunctionReturn(0); 14800c37af3bSToby Isaac } 148195a0b26dSToby Isaac 148295a0b26dSToby Isaac #undef __FUNCT__ 148321968bf8SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildrenMatrices" 148421968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 148595a0b26dSToby Isaac { 1486f7c74593SToby Isaac Mat refCmat; 148721968bf8SToby Isaac PetscDS ds; 148821968bf8SToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 148921968bf8SToby Isaac PetscScalar ***refPointFieldMats; 149021968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 149121968bf8SToby Isaac IS refAnIS; 149221968bf8SToby Isaac const PetscInt *refAnchors; 149395a0b26dSToby Isaac PetscErrorCode ierr; 149495a0b26dSToby Isaac 149595a0b26dSToby Isaac PetscFunctionBegin; 149621968bf8SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 149795a0b26dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 1498f7c74593SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 1499a17985deSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 150095a0b26dSToby Isaac ierr = ISGetIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 150195a0b26dSToby Isaac ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr); 150295a0b26dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 150395a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr); 150495a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldN);CHKERRQ(ierr); 150595a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 150695a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 150795a0b26dSToby Isaac ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr); 150895a0b26dSToby Isaac ierr = PetscMalloc1(maxDof*maxAnDof,&cols);CHKERRQ(ierr); 150995a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 151095a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 151195a0b26dSToby Isaac 151295a0b26dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 151395a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 151495a0b26dSToby Isaac if (!pDof || parent == p) continue; 151595a0b26dSToby Isaac 151695a0b26dSToby Isaac ierr = PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr); 151795a0b26dSToby Isaac ierr = PetscCalloc1(numFields,&refPointFieldN[p-pRefStart]);CHKERRQ(ierr); 151895a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 151995a0b26dSToby Isaac for (f = 0; f < numFields; f++) { 152095a0b26dSToby Isaac PetscInt cDof, cOff, numCols, r, i, fComp; 15210dd1b1feSToby Isaac PetscObject disc; 15220dd1b1feSToby Isaac PetscClassId id; 15230dd1b1feSToby Isaac PetscFE fe = NULL; 15240dd1b1feSToby Isaac PetscFV fv = NULL; 152595a0b26dSToby Isaac 15260dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 15270dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 15280dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 15290dd1b1feSToby Isaac fe = (PetscFE) disc; 153095a0b26dSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 15310dd1b1feSToby Isaac } 15320dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 15330dd1b1feSToby Isaac fv = (PetscFV) disc; 15340dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 15350dd1b1feSToby Isaac } 15360dd1b1feSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 153795a0b26dSToby Isaac 153895a0b26dSToby Isaac if (numFields > 1) { 153995a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 154095a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr); 154195a0b26dSToby Isaac } 154295a0b26dSToby Isaac else { 154395a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 154495a0b26dSToby Isaac ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr); 154595a0b26dSToby Isaac } 154695a0b26dSToby Isaac 154795a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 154895a0b26dSToby Isaac rows[r] = cOff + r; 154995a0b26dSToby Isaac } 155095a0b26dSToby Isaac numCols = 0; 155195a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 155295a0b26dSToby Isaac PetscInt q = closure[2*i]; 155395a0b26dSToby Isaac PetscInt o = closure[2*i+1]; 155495a0b26dSToby Isaac PetscInt aDof, aOff, j; 155595a0b26dSToby Isaac 155695a0b26dSToby Isaac if (numFields > 1) { 155795a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refSection,q,f,&aDof);CHKERRQ(ierr); 155895a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,q,f,&aOff);CHKERRQ(ierr); 155995a0b26dSToby Isaac } 156095a0b26dSToby Isaac else { 156195a0b26dSToby Isaac ierr = PetscSectionGetDof(refSection,q,&aDof);CHKERRQ(ierr); 156295a0b26dSToby Isaac ierr = PetscSectionGetOffset(refSection,q,&aOff);CHKERRQ(ierr); 156395a0b26dSToby Isaac } 156495a0b26dSToby Isaac 156595a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 156695a0b26dSToby Isaac PetscInt node = (o >= 0) ? (j / fComp) : ((aDof - 1 - j) / fComp); 156795a0b26dSToby Isaac PetscInt comp = (j % fComp); 156895a0b26dSToby Isaac 156995a0b26dSToby Isaac cols[numCols++] = aOff + node * fComp + comp; 157095a0b26dSToby Isaac } 157195a0b26dSToby Isaac } 157295a0b26dSToby Isaac refPointFieldN[p-pRefStart][f] = numCols; 157395a0b26dSToby Isaac ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 157495a0b26dSToby Isaac ierr = MatGetValues(refCmat,cDof,rows,numCols,cols,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 157595a0b26dSToby Isaac } 157695a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 157795a0b26dSToby Isaac } 157821968bf8SToby Isaac *childrenMats = refPointFieldMats; 157921968bf8SToby Isaac *childrenN = refPointFieldN; 158021968bf8SToby Isaac ierr = ISRestoreIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 158121968bf8SToby Isaac ierr = PetscFree(rows);CHKERRQ(ierr); 158221968bf8SToby Isaac ierr = PetscFree(cols);CHKERRQ(ierr); 158321968bf8SToby Isaac PetscFunctionReturn(0); 158421968bf8SToby Isaac } 158521968bf8SToby Isaac 158621968bf8SToby Isaac #undef __FUNCT__ 158721968bf8SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeRestoreChildrenMatrices" 158821968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 158921968bf8SToby Isaac { 159021968bf8SToby Isaac PetscDS ds; 159121968bf8SToby Isaac PetscInt **refPointFieldN; 159221968bf8SToby Isaac PetscScalar ***refPointFieldMats; 159321968bf8SToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 159421968bf8SToby Isaac PetscSection refConSec; 159521968bf8SToby Isaac PetscErrorCode ierr; 159621968bf8SToby Isaac 159721968bf8SToby Isaac PetscFunctionBegin; 159821968bf8SToby Isaac refPointFieldN = *childrenN; 159921968bf8SToby Isaac *childrenN = NULL; 160021968bf8SToby Isaac refPointFieldMats = *childrenMats; 160121968bf8SToby Isaac *childrenMats = NULL; 160221968bf8SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 160321968bf8SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 160421968bf8SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 1605e44e4e7fSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 160621968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 160721968bf8SToby Isaac PetscInt parent, pDof; 160821968bf8SToby Isaac 160921968bf8SToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 161021968bf8SToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 161121968bf8SToby Isaac if (!pDof || parent == p) continue; 161221968bf8SToby Isaac 161321968bf8SToby Isaac for (f = 0; f < numFields; f++) { 161421968bf8SToby Isaac PetscInt cDof; 161521968bf8SToby Isaac 161621968bf8SToby Isaac if (numFields > 1) { 161721968bf8SToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 161821968bf8SToby Isaac } 161921968bf8SToby Isaac else { 162021968bf8SToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 162121968bf8SToby Isaac } 162221968bf8SToby Isaac 162321968bf8SToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr); 162421968bf8SToby Isaac } 162521968bf8SToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr); 162621968bf8SToby Isaac ierr = PetscFree(refPointFieldN[p - pRefStart]);CHKERRQ(ierr); 162721968bf8SToby Isaac } 162821968bf8SToby Isaac ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr); 162921968bf8SToby Isaac ierr = PetscFree(refPointFieldN);CHKERRQ(ierr); 163021968bf8SToby Isaac PetscFunctionReturn(0); 163121968bf8SToby Isaac } 163221968bf8SToby Isaac 163321968bf8SToby Isaac #undef __FUNCT__ 163421968bf8SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_FromReference" 163521968bf8SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 163621968bf8SToby Isaac { 163721968bf8SToby Isaac DM refTree; 163821968bf8SToby Isaac PetscDS ds; 163921968bf8SToby Isaac Mat refCmat; 164021968bf8SToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 164121968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 164221968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 164321968bf8SToby Isaac IS refAnIS, anIS; 164421968bf8SToby Isaac const PetscInt *anchors; 164521968bf8SToby Isaac PetscErrorCode ierr; 164621968bf8SToby Isaac 164721968bf8SToby Isaac PetscFunctionBegin; 164821968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 164921968bf8SToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 165021968bf8SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 165121968bf8SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 165221968bf8SToby Isaac ierr = DMSetDS(refTree,ds);CHKERRQ(ierr); 165321968bf8SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 165421968bf8SToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 165521968bf8SToby Isaac ierr = DMPlexGetAnchors(dm,&anSec,&anIS);CHKERRQ(ierr); 165621968bf8SToby Isaac ierr = ISGetIndices(anIS,&anchors);CHKERRQ(ierr); 165721968bf8SToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 165821968bf8SToby Isaac ierr = PetscSectionGetChart(conSec,&conStart,&conEnd);CHKERRQ(ierr); 165921968bf8SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 166021968bf8SToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 166121968bf8SToby Isaac ierr = PetscMalloc1(maxDof*maxDof*maxAnDof,&pointWork);CHKERRQ(ierr); 166221968bf8SToby Isaac 166321968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 166421968bf8SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 166595a0b26dSToby Isaac 166695a0b26dSToby Isaac /* step 2: compute the preorder */ 166795a0b26dSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 166895a0b26dSToby Isaac ierr = PetscMalloc2(pEnd-pStart,&perm,pEnd-pStart,&iperm);CHKERRQ(ierr); 166995a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 167095a0b26dSToby Isaac perm[p - pStart] = p; 167195a0b26dSToby Isaac iperm[p - pStart] = p-pStart; 167295a0b26dSToby Isaac } 167395a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 167495a0b26dSToby Isaac PetscInt point = perm[p]; 167595a0b26dSToby Isaac PetscInt parent; 167695a0b26dSToby Isaac 167795a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 167895a0b26dSToby Isaac if (parent == point) { 167995a0b26dSToby Isaac p++; 168095a0b26dSToby Isaac } 168195a0b26dSToby Isaac else { 168295a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 168395a0b26dSToby Isaac 168495a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 168595a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 168695a0b26dSToby Isaac PetscInt q = closure[2*i]; 168795a0b26dSToby Isaac if (iperm[q-pStart] > iperm[point-pStart]) { 168895a0b26dSToby Isaac /* swap */ 168995a0b26dSToby Isaac perm[p] = q; 169095a0b26dSToby Isaac perm[iperm[q-pStart]] = point; 169195a0b26dSToby Isaac iperm[point-pStart] = iperm[q-pStart]; 169295a0b26dSToby Isaac iperm[q-pStart] = p; 169395a0b26dSToby Isaac break; 169495a0b26dSToby Isaac } 169595a0b26dSToby Isaac } 169695a0b26dSToby Isaac size = closureSize; 169795a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 169895a0b26dSToby Isaac if (i == size) { 169995a0b26dSToby Isaac p++; 170095a0b26dSToby Isaac } 170195a0b26dSToby Isaac } 170295a0b26dSToby Isaac } 170395a0b26dSToby Isaac 170495a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 170595a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 170695a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 170795a0b26dSToby Isaac * values outside of the Mat first. 170895a0b26dSToby Isaac */ 170995a0b26dSToby Isaac { 171095a0b26dSToby Isaac PetscInt nRows, row, nnz; 171195a0b26dSToby Isaac PetscBool done; 171295a0b26dSToby Isaac const PetscInt *ia, *ja; 171395a0b26dSToby Isaac PetscScalar *vals; 171495a0b26dSToby Isaac 171595a0b26dSToby Isaac ierr = MatGetRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 171695a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not get RowIJ of constraint matrix"); 171795a0b26dSToby Isaac nnz = ia[nRows]; 171895a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 171995a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 172095a0b26dSToby Isaac ierr = PetscMalloc1(nnz,&vals);CHKERRQ(ierr); 172195a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 172295a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 172395a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 172495a0b26dSToby Isaac 172595a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,&childid);CHKERRQ(ierr); 172695a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 172795a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&pointDof);CHKERRQ(ierr); 172895a0b26dSToby Isaac if (!pointDof) continue; 172995a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 173095a0b26dSToby Isaac for (f = 0; f < numFields; f++) { 17319fc93327SToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, fComp = -1, matOffset, offset; 173295a0b26dSToby Isaac PetscScalar *pointMat; 17330dd1b1feSToby Isaac PetscObject disc; 17340dd1b1feSToby Isaac PetscClassId id; 17350dd1b1feSToby Isaac PetscFE fe = NULL; 17360dd1b1feSToby Isaac PetscFV fv = NULL; 173795a0b26dSToby Isaac 17380dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 17390dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 17400dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 17410dd1b1feSToby Isaac fe = (PetscFE) disc; 174295a0b26dSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 17430dd1b1feSToby Isaac } 17440dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 17450dd1b1feSToby Isaac fv = (PetscFV) disc; 17460dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 17470dd1b1feSToby Isaac } 17489fc93327SToby Isaac else { 17499fc93327SToby Isaac SETERRQ(PetscObjectComm((PetscObject)disc),PETSC_ERR_SUP,"Unsupported discretization"); 17509fc93327SToby Isaac } 175195a0b26dSToby Isaac 175295a0b26dSToby Isaac if (numFields > 1) { 175395a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,point,f,&cDof);CHKERRQ(ierr); 175495a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,point,f,&cOff);CHKERRQ(ierr); 175595a0b26dSToby Isaac } 175695a0b26dSToby Isaac else { 175795a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&cDof);CHKERRQ(ierr); 175895a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,point,&cOff);CHKERRQ(ierr); 175995a0b26dSToby Isaac } 176095a0b26dSToby Isaac if (!cDof) continue; 176195a0b26dSToby Isaac 176295a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 176395a0b26dSToby Isaac #if defined(PETSC_USE_DEBUG) 176495a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 176595a0b26dSToby Isaac if (cDof > 1 && r) { 176621968bf8SToby Isaac if ((ia[cOff+r+1]-ia[cOff+r]) != (ia[cOff+r]-ia[cOff+r-1])) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Two point rows have different nnz: %D vs. %D", (ia[cOff+r+1]-ia[cOff+r]), (ia[cOff+r]-ia[cOff+r-1])); 176795a0b26dSToby Isaac } 176895a0b26dSToby Isaac } 176995a0b26dSToby Isaac #endif 177095a0b26dSToby Isaac /* zero rows */ 177195a0b26dSToby Isaac for (i = ia[cOff] ; i< ia[cOff+cDof];i++) { 177295a0b26dSToby Isaac vals[i] = 0.; 177395a0b26dSToby Isaac } 177495a0b26dSToby Isaac matOffset = ia[cOff]; 177595a0b26dSToby Isaac numFillCols = ia[cOff+1] - matOffset; 177695a0b26dSToby Isaac pointMat = refPointFieldMats[childid-pRefStart][f]; 177795a0b26dSToby Isaac numCols = refPointFieldN[childid-pRefStart][f]; 177895a0b26dSToby Isaac offset = 0; 177995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 178095a0b26dSToby Isaac PetscInt q = closure[2*i]; 178195a0b26dSToby Isaac PetscInt o = closure[2*i+1]; 178295a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 178395a0b26dSToby Isaac 178495a0b26dSToby Isaac qConDof = qConOff = 0; 178595a0b26dSToby Isaac if (numFields > 1) { 178695a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(section,q,f,&aDof);CHKERRQ(ierr); 178795a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(section,q,f,&aOff);CHKERRQ(ierr); 178895a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 178995a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,q,f,&qConDof);CHKERRQ(ierr); 179095a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,q,f,&qConOff);CHKERRQ(ierr); 179195a0b26dSToby Isaac } 179295a0b26dSToby Isaac } 179395a0b26dSToby Isaac else { 179495a0b26dSToby Isaac ierr = PetscSectionGetDof(section,q,&aDof);CHKERRQ(ierr); 179595a0b26dSToby Isaac ierr = PetscSectionGetOffset(section,q,&aOff);CHKERRQ(ierr); 179695a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 179795a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,q,&qConDof);CHKERRQ(ierr); 179895a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,q,&qConOff);CHKERRQ(ierr); 179995a0b26dSToby Isaac } 180095a0b26dSToby Isaac } 180195a0b26dSToby Isaac if (!aDof) continue; 180295a0b26dSToby Isaac if (qConDof) { 180395a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 180495a0b26dSToby Isaac * be filled, thanks to preordering */ 180595a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 180695a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 180795a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 180895a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 180995a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 181095a0b26dSToby Isaac PetscScalar inVal = 0; 181195a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 181295a0b26dSToby Isaac PetscInt node = (o >= 0) ? (k / fComp) : ((aDof - 1 - k) / fComp); 181395a0b26dSToby Isaac PetscInt comp = (k % fComp); 181495a0b26dSToby Isaac PetscInt col = node * fComp + comp; 181595a0b26dSToby Isaac 181695a0b26dSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j]; 181795a0b26dSToby Isaac } 181895a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 181995a0b26dSToby Isaac } 182095a0b26dSToby Isaac } 182195a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 182295a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 182395a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 182495a0b26dSToby Isaac for (;k < numFillCols; k++) { 182595a0b26dSToby Isaac if (ja[matOffset + k] == col) { 182695a0b26dSToby Isaac break; 182795a0b26dSToby Isaac } 182895a0b26dSToby Isaac } 182995a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, col); 183095a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 183195a0b26dSToby Isaac vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 183295a0b26dSToby Isaac } 183395a0b26dSToby Isaac } 183495a0b26dSToby Isaac } 183595a0b26dSToby Isaac else { 183695a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 183795a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 183895a0b26dSToby Isaac if (ja[matOffset + k] == aOff) { 183995a0b26dSToby Isaac break; 184095a0b26dSToby Isaac } 184195a0b26dSToby Isaac } 184295a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, aOff); 184395a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 184495a0b26dSToby Isaac PetscInt node = (o >= 0) ? (j / fComp) : ((aDof - 1 - j) / fComp); 184595a0b26dSToby Isaac PetscInt comp = (j % fComp); 184695a0b26dSToby Isaac PetscInt col = node * fComp + comp; 184795a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 184895a0b26dSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + col]; 184995a0b26dSToby Isaac } 185095a0b26dSToby Isaac } 185195a0b26dSToby Isaac } 185295a0b26dSToby Isaac offset += aDof; 185395a0b26dSToby Isaac } 185495a0b26dSToby Isaac } 185595a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 185695a0b26dSToby Isaac } 185795a0b26dSToby Isaac for (row = 0; row < nRows; row++) { 185895a0b26dSToby Isaac ierr = MatSetValues(cMat,1,&row,ia[row+1]-ia[row],&ja[ia[row]],&vals[ia[row]],INSERT_VALUES);CHKERRQ(ierr); 185995a0b26dSToby Isaac } 186095a0b26dSToby Isaac ierr = MatRestoreRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 186195a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not restore RowIJ of constraint matrix"); 186295a0b26dSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 186395a0b26dSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 186495a0b26dSToby Isaac ierr = PetscFree(vals);CHKERRQ(ierr); 186595a0b26dSToby Isaac } 186695a0b26dSToby Isaac 186795a0b26dSToby Isaac /* clean up */ 186895a0b26dSToby Isaac ierr = ISRestoreIndices(anIS,&anchors);CHKERRQ(ierr); 186995a0b26dSToby Isaac ierr = PetscFree2(perm,iperm);CHKERRQ(ierr); 187095a0b26dSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 187121968bf8SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 187295a0b26dSToby Isaac PetscFunctionReturn(0); 187395a0b26dSToby Isaac } 187495a0b26dSToby Isaac 18756f5f1567SToby Isaac #undef __FUNCT__ 18766f5f1567SToby Isaac #define __FUNCT__ "DMPlexTreeRefineCell" 18776f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 18786f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 18796f5f1567SToby Isaac PetscErrorCode DMPlexTreeRefineCell (DM dm, PetscInt cell, DM *ncdm) 18806f5f1567SToby Isaac { 18816f5f1567SToby Isaac DM K; 1882420f55faSMatthew G. Knepley PetscMPIInt rank; 18836f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 18846f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 18856f5f1567SToby Isaac PetscInt *Kembedding; 18866f5f1567SToby Isaac PetscInt *cellClosure=NULL, nc; 18876f5f1567SToby Isaac PetscScalar *newVertexCoords; 18886f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 18896f5f1567SToby Isaac PetscSection parentSection; 18906f5f1567SToby Isaac PetscErrorCode ierr; 18916f5f1567SToby Isaac 18926f5f1567SToby Isaac PetscFunctionBegin; 18936f5f1567SToby Isaac ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr); 189428f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 18956f5f1567SToby Isaac ierr = DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm);CHKERRQ(ierr); 189628f4b327SMatthew G. Knepley ierr = DMSetDimension(*ncdm,dim);CHKERRQ(ierr); 18976f5f1567SToby Isaac 18986f5f1567SToby Isaac ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 18996f5f1567SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&parentSection);CHKERRQ(ierr); 19006f5f1567SToby Isaac ierr = DMPlexGetReferenceTree(dm,&K);CHKERRQ(ierr); 19016f5f1567SToby Isaac if (!rank) { 19026f5f1567SToby Isaac /* compute the new charts */ 19036f5f1567SToby Isaac ierr = PetscMalloc5(dim+1,&pNewCount,dim+1,&pNewStart,dim+1,&pNewEnd,dim+1,&pOldStart,dim+1,&pOldEnd);CHKERRQ(ierr); 19046f5f1567SToby Isaac offset = 0; 19056f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19066f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 19076f5f1567SToby Isaac 19086f5f1567SToby Isaac pNewStart[d] = offset; 19096f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pOldStart[d],&pOldEnd[d]);CHKERRQ(ierr); 19106f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 19116f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 19126f5f1567SToby Isaac /* adding the new points */ 19136f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 19146f5f1567SToby Isaac if (!d) { 19156f5f1567SToby Isaac /* removing the cell */ 19166f5f1567SToby Isaac pNewCount[d]--; 19176f5f1567SToby Isaac } 19186f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19196f5f1567SToby Isaac PetscInt parent; 19206f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&parent,NULL);CHKERRQ(ierr); 19216f5f1567SToby Isaac if (parent == k) { 19226f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 19236f5f1567SToby Isaac pNewCount[d]--; 19246f5f1567SToby Isaac } 19256f5f1567SToby Isaac } 19266f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 19276f5f1567SToby Isaac offset = pNewEnd[d]; 19286f5f1567SToby Isaac 19296f5f1567SToby Isaac } 19306f5f1567SToby 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]); 19316f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 19326f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 19336f5f1567SToby Isaac 19346f5f1567SToby Isaac ierr = PetscMalloc1(pNewEnd[dim],&newConeSizes);CHKERRQ(ierr); 19356f5f1567SToby Isaac { 19366f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 19376f5f1567SToby Isaac 19386f5f1567SToby Isaac ierr = DMPlexGetChart(K,&kStart,&kEnd);CHKERRQ(ierr); 19396f5f1567SToby Isaac ierr = PetscMalloc4(kEnd-kStart,&Kembedding,kEnd-kStart,&perm,kEnd-kStart,&iperm,kEnd-kStart,&preOrient);CHKERRQ(ierr); 19406f5f1567SToby Isaac 19416f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19426f5f1567SToby Isaac perm[k - kStart] = k; 19436f5f1567SToby Isaac iperm [k - kStart] = k - kStart; 19446f5f1567SToby Isaac preOrient[k - kStart] = 0; 19456f5f1567SToby Isaac } 19466f5f1567SToby Isaac 19476f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 19486f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 19496f5f1567SToby Isaac PetscInt parentOrientA = closureK[2*j+1]; 19506f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2*j+1]; 19516f5f1567SToby Isaac PetscInt p, q; 19526f5f1567SToby Isaac 19536f5f1567SToby Isaac p = closureK[2*j]; 19546f5f1567SToby Isaac q = cellClosure[2*j]; 19556f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19566f5f1567SToby Isaac if (q >= pOldStart[d] && q < pOldEnd[d]) { 19576f5f1567SToby Isaac Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 19586f5f1567SToby Isaac } 19596f5f1567SToby Isaac } 19606f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 19616f5f1567SToby Isaac PetscInt numChildren, i; 19626f5f1567SToby Isaac const PetscInt *children; 19636f5f1567SToby Isaac 19646f5f1567SToby Isaac ierr = DMPlexGetTreeChildren(K,p,&numChildren,&children);CHKERRQ(ierr); 19656f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 19666f5f1567SToby Isaac PetscInt kPerm, oPerm; 19676f5f1567SToby Isaac 19686f5f1567SToby Isaac k = children[i]; 19696f5f1567SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry(K,p,parentOrientA,0,k,parentOrientB,&oPerm,&kPerm);CHKERRQ(ierr); 19706f5f1567SToby Isaac /* perm = what refTree position I'm in */ 19716f5f1567SToby Isaac perm[kPerm-kStart] = k; 19726f5f1567SToby Isaac /* iperm = who is at this position */ 19736f5f1567SToby Isaac iperm[k-kStart] = kPerm-kStart; 19746f5f1567SToby Isaac preOrient[kPerm-kStart] = oPerm; 19756f5f1567SToby Isaac } 19766f5f1567SToby Isaac } 19776f5f1567SToby Isaac } 19786f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 19796f5f1567SToby Isaac } 19806f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,0,pNewEnd[dim]);CHKERRQ(ierr); 19816f5f1567SToby Isaac offset = 0; 19826f5f1567SToby Isaac numNewCones = 0; 19836f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19846f5f1567SToby Isaac PetscInt kStart, kEnd, k; 19856f5f1567SToby Isaac PetscInt p; 19866f5f1567SToby Isaac PetscInt size; 19876f5f1567SToby Isaac 19886f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19896f5f1567SToby Isaac /* skip cell 0 */ 19906f5f1567SToby Isaac if (p == cell) continue; 19916f5f1567SToby Isaac /* old cones to new cones */ 19926f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 19936f5f1567SToby Isaac newConeSizes[offset++] = size; 19946f5f1567SToby Isaac numNewCones += size; 19956f5f1567SToby Isaac } 19966f5f1567SToby Isaac 19976f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 19986f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19996f5f1567SToby Isaac PetscInt kParent; 20006f5f1567SToby Isaac 20016f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 20026f5f1567SToby Isaac if (kParent != k) { 20036f5f1567SToby Isaac Kembedding[k] = offset; 20046f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 20056f5f1567SToby Isaac newConeSizes[offset++] = size; 20066f5f1567SToby Isaac numNewCones += size; 20076f5f1567SToby Isaac if (kParent != 0) { 20086f5f1567SToby Isaac ierr = PetscSectionSetDof(parentSection,Kembedding[k],1);CHKERRQ(ierr); 20096f5f1567SToby Isaac } 20106f5f1567SToby Isaac } 20116f5f1567SToby Isaac } 20126f5f1567SToby Isaac } 20136f5f1567SToby Isaac 20146f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 20156f5f1567SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&numPointsWithParents);CHKERRQ(ierr); 20166f5f1567SToby Isaac ierr = PetscMalloc2(numNewCones,&newCones,numNewCones,&newOrientations);CHKERRQ(ierr); 20176f5f1567SToby Isaac ierr = PetscMalloc2(numPointsWithParents,&parents,numPointsWithParents,&childIDs);CHKERRQ(ierr); 20186f5f1567SToby Isaac 20196f5f1567SToby Isaac /* fill new cones */ 20206f5f1567SToby Isaac offset = 0; 20216f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20226f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 20236f5f1567SToby Isaac PetscInt p; 20246f5f1567SToby Isaac PetscInt size; 20256f5f1567SToby Isaac const PetscInt *cone, *orientation; 20266f5f1567SToby Isaac 20276f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 20286f5f1567SToby Isaac /* skip cell 0 */ 20296f5f1567SToby Isaac if (p == cell) continue; 20306f5f1567SToby Isaac /* old cones to new cones */ 20316f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 20326f5f1567SToby Isaac ierr = DMPlexGetCone(dm,p,&cone);CHKERRQ(ierr); 20336f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(dm,p,&orientation);CHKERRQ(ierr); 20346f5f1567SToby Isaac for (l = 0; l < size; l++) { 20356f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 20366f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 20376f5f1567SToby Isaac } 20386f5f1567SToby Isaac } 20396f5f1567SToby Isaac 20406f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 20416f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20426f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 20436f5f1567SToby Isaac PetscInt preO = preOrient[k]; 20446f5f1567SToby Isaac 20456f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 20466f5f1567SToby Isaac if (kParent != k) { 20476f5f1567SToby Isaac /* embed new cones */ 20486f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 20496f5f1567SToby Isaac ierr = DMPlexGetCone(K,kPerm,&cone);CHKERRQ(ierr); 20506f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(K,kPerm,&orientation);CHKERRQ(ierr); 20516f5f1567SToby Isaac for (l = 0; l < size; l++) { 20526f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size -(preO + 1) - l) % size); 20536f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 20546f5f1567SToby Isaac 20556f5f1567SToby Isaac q = iperm[cone[m]]; 20566f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 20576f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,q,&lSize);CHKERRQ(ierr); 20586f5f1567SToby Isaac oTrue = orientation[m]; 20596f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 20606f5f1567SToby Isaac newO = DihedralCompose(lSize,oTrue,preOrient[q]); 20616f5f1567SToby Isaac newOrientations[offset++] = newO; 20626f5f1567SToby Isaac } 20636f5f1567SToby Isaac if (kParent != 0) { 20646f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 20656f5f1567SToby Isaac ierr = PetscSectionGetOffset(parentSection,Kembedding[k],&pOffset);CHKERRQ(ierr); 20666f5f1567SToby Isaac parents[pOffset] = newPoint; 20676f5f1567SToby Isaac childIDs[pOffset] = k; 20686f5f1567SToby Isaac } 20696f5f1567SToby Isaac } 20706f5f1567SToby Isaac } 20716f5f1567SToby Isaac } 20726f5f1567SToby Isaac 20736f5f1567SToby Isaac ierr = PetscMalloc1(dim*(pNewEnd[dim]-pNewStart[dim]),&newVertexCoords);CHKERRQ(ierr); 20746f5f1567SToby Isaac 20756f5f1567SToby Isaac /* fill coordinates */ 20766f5f1567SToby Isaac offset = 0; 20776f5f1567SToby Isaac { 2078d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 20796f5f1567SToby Isaac PetscSection vSection; 20806f5f1567SToby Isaac PetscInt v; 20816f5f1567SToby Isaac Vec coords; 20826f5f1567SToby Isaac PetscScalar *coordvals; 20836f5f1567SToby Isaac PetscInt dof, off; 2084c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 20856f5f1567SToby Isaac 20866f5f1567SToby Isaac #if defined(PETSC_USE_DEBUG) 2087d90620a3SMatthew G. Knepley { 2088d90620a3SMatthew G. Knepley PetscInt k; 20896f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 20906f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 209173a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 20926f5f1567SToby Isaac if (detJ <= 0.) SETERRQ1 (PETSC_COMM_SELF,PETSC_ERR_PLIB,"reference tree cell %d has bad determinant",k); 20936f5f1567SToby Isaac } 2094d90620a3SMatthew G. Knepley } 20956f5f1567SToby Isaac #endif 209673a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 20976f5f1567SToby Isaac ierr = DMGetCoordinateSection(dm,&vSection);CHKERRQ(ierr); 20986f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coords);CHKERRQ(ierr); 20996f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 21006f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 21016f5f1567SToby Isaac 21026f5f1567SToby Isaac ierr = PetscSectionGetDof(vSection,v,&dof);CHKERRQ(ierr); 21036f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,v,&off);CHKERRQ(ierr); 21046f5f1567SToby Isaac for (l = 0; l < dof; l++) { 21056f5f1567SToby Isaac newVertexCoords[offset++] = coordvals[off + l]; 21066f5f1567SToby Isaac } 21076f5f1567SToby Isaac } 21086f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 21096f5f1567SToby Isaac 21106f5f1567SToby Isaac ierr = DMGetCoordinateSection(K,&vSection);CHKERRQ(ierr); 21116f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(K,&coords);CHKERRQ(ierr); 21126f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 21136f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 21146f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 21159bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 21166f5f1567SToby Isaac PetscInt vPerm = perm[v]; 21176f5f1567SToby Isaac PetscInt kParent; 21186f5f1567SToby Isaac 21196f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,v,&kParent,NULL);CHKERRQ(ierr); 21206f5f1567SToby Isaac if (kParent != v) { 21216f5f1567SToby Isaac /* this is a new vertex */ 21226f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,vPerm,&off);CHKERRQ(ierr); 21239bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off+l]); 21249bc368c7SMatthew G. Knepley CoordinatesRefToReal(dim, dim, v0, J, coord, newCoord);CHKERRQ(ierr); 21259bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset+l] = newCoord[l]; 21266f5f1567SToby Isaac offset += dim; 21276f5f1567SToby Isaac } 21286f5f1567SToby Isaac } 21296f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 21306f5f1567SToby Isaac } 21316f5f1567SToby Isaac 21326f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 21336f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 21346f5f1567SToby Isaac PetscInt tmp; 21356f5f1567SToby Isaac 21366f5f1567SToby Isaac tmp = pNewCount[d]; 21376f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 21386f5f1567SToby Isaac pNewCount[dim - d] = tmp; 21396f5f1567SToby Isaac } 21406f5f1567SToby Isaac 21416f5f1567SToby Isaac ierr = DMPlexCreateFromDAG(*ncdm,dim,pNewCount,newConeSizes,newCones,newOrientations,newVertexCoords);CHKERRQ(ierr); 21426f5f1567SToby Isaac ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr); 21436f5f1567SToby Isaac ierr = DMPlexSetTree(*ncdm,parentSection,parents,childIDs);CHKERRQ(ierr); 21446f5f1567SToby Isaac 21456f5f1567SToby Isaac /* clean up */ 21466f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 21476f5f1567SToby Isaac ierr = PetscFree5(pNewCount,pNewStart,pNewEnd,pOldStart,pOldEnd);CHKERRQ(ierr); 21486f5f1567SToby Isaac ierr = PetscFree(newConeSizes);CHKERRQ(ierr); 21496f5f1567SToby Isaac ierr = PetscFree2(newCones,newOrientations);CHKERRQ(ierr); 21506f5f1567SToby Isaac ierr = PetscFree(newVertexCoords);CHKERRQ(ierr); 21516f5f1567SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 21526f5f1567SToby Isaac ierr = PetscFree4(Kembedding,perm,iperm,preOrient);CHKERRQ(ierr); 21536f5f1567SToby Isaac } 21546f5f1567SToby Isaac else { 21556f5f1567SToby Isaac PetscInt p, counts[4]; 21566f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 21576f5f1567SToby Isaac Vec coordVec; 21586f5f1567SToby Isaac PetscScalar *coords; 21596f5f1567SToby Isaac 21606f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 21616f5f1567SToby Isaac PetscInt dStart, dEnd; 21626f5f1567SToby Isaac 21636f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 21646f5f1567SToby Isaac counts[d] = dEnd - dStart; 21656f5f1567SToby Isaac } 21666f5f1567SToby Isaac ierr = PetscMalloc1(pEnd-pStart,&coneSizes);CHKERRQ(ierr); 21676f5f1567SToby Isaac for (p = pStart; p < pEnd; p++) { 21686f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&coneSizes[p-pStart]);CHKERRQ(ierr); 21696f5f1567SToby Isaac } 21706f5f1567SToby Isaac ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 21716f5f1567SToby Isaac ierr = DMPlexGetConeOrientations(dm, &orientations);CHKERRQ(ierr); 21726f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coordVec);CHKERRQ(ierr); 21736f5f1567SToby Isaac ierr = VecGetArray(coordVec,&coords);CHKERRQ(ierr); 21746f5f1567SToby Isaac 21756f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,pStart,pEnd);CHKERRQ(ierr); 21766f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 21776f5f1567SToby Isaac ierr = DMPlexCreateFromDAG(*ncdm,dim,counts,coneSizes,cones,orientations,NULL);CHKERRQ(ierr); 21786f5f1567SToby Isaac ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr); 21796f5f1567SToby Isaac ierr = DMPlexSetTree(*ncdm,parentSection,NULL,NULL);CHKERRQ(ierr); 21806f5f1567SToby Isaac ierr = VecRestoreArray(coordVec,&coords);CHKERRQ(ierr); 21816f5f1567SToby Isaac } 21826f5f1567SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 21836f5f1567SToby Isaac 21846f5f1567SToby Isaac PetscFunctionReturn(0); 21856f5f1567SToby Isaac } 21866ecaa68aSToby Isaac 21876ecaa68aSToby Isaac #undef __FUNCT__ 21886ecaa68aSToby Isaac #define __FUNCT__ "DMPlexComputeInterpolatorTree" 21896ecaa68aSToby Isaac PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 21906ecaa68aSToby Isaac { 21916ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 21926ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 21936ecaa68aSToby Isaac PetscSection localCoarse, localFine; 21946ecaa68aSToby Isaac PetscSection aSec, cSec; 21956ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 219646bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 219746bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 219846bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 21996ecaa68aSToby Isaac IS aIS; 22006ecaa68aSToby Isaac const PetscInt *anchors; 22016ecaa68aSToby Isaac Mat cMat; 22026ecaa68aSToby Isaac PetscInt numFields; 22036ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 22046ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 22051c58ffc4SToby Isaac PetscInt *maxChildIds; 2206e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 22076ecaa68aSToby Isaac PetscErrorCode ierr; 22086ecaa68aSToby Isaac 22096ecaa68aSToby Isaac PetscFunctionBegin; 22106ecaa68aSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 22116ecaa68aSToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 22126ecaa68aSToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 22136ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 221489698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 221589698031SToby Isaac const PetscInt *leaves; 22166ecaa68aSToby Isaac 221789698031SToby Isaac ierr = PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 221889698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 221989698031SToby Isaac p = leaves ? leaves[l] : l; 22206ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 22216ecaa68aSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 22226ecaa68aSToby Isaac if ((dof - cdof) > 0) { 22236ecaa68aSToby Isaac numPointsWithDofs++; 22246ecaa68aSToby Isaac } 22256ecaa68aSToby Isaac } 22266ecaa68aSToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 22277cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 222889698031SToby Isaac p = leaves ? leaves[l] : l; 22296ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 22306ecaa68aSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 22316ecaa68aSToby Isaac if ((dof - cdof) > 0) { 223289698031SToby Isaac pointsWithDofs[offset++] = l; 22336ecaa68aSToby Isaac } 22346ecaa68aSToby Isaac } 22356ecaa68aSToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 2236ec92bd66SToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 22376ecaa68aSToby Isaac } 22386ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 22396ecaa68aSToby Isaac ierr = PetscMalloc1(pEndC-pStartC,&maxChildIds);CHKERRQ(ierr); 22406ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22418d2f55e7SToby Isaac maxChildIds[p - pStartC] = -2; 22426ecaa68aSToby Isaac } 22436ecaa68aSToby Isaac ierr = PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 22446ecaa68aSToby Isaac ierr = PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 224546bdb399SToby Isaac 22466ecaa68aSToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 22476ecaa68aSToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 224846bdb399SToby Isaac 22496ecaa68aSToby Isaac ierr = DMPlexGetAnchors(coarse,&aSec,&aIS);CHKERRQ(ierr); 22506ecaa68aSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 22516ecaa68aSToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 225246bdb399SToby Isaac 22536ecaa68aSToby Isaac ierr = DMGetDefaultConstraints(coarse,&cSec,&cMat);CHKERRQ(ierr); 22546ecaa68aSToby Isaac ierr = PetscSectionGetChart(cSec,&cStart,&cEnd);CHKERRQ(ierr); 225546bdb399SToby Isaac 225646bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 22576ecaa68aSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec);CHKERRQ(ierr); 22586ecaa68aSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootMatricesSec);CHKERRQ(ierr); 22596ecaa68aSToby Isaac ierr = PetscSectionSetChart(rootIndicesSec,pStartC,pEndC);CHKERRQ(ierr); 22606ecaa68aSToby Isaac ierr = PetscSectionSetChart(rootMatricesSec,pStartC,pEndC);CHKERRQ(ierr); 2261708c7f19SToby Isaac ierr = PetscSectionGetNumFields(localCoarse,&numFields);CHKERRQ(ierr); 226221968bf8SToby Isaac { 2263267d4f3fSToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 2264e44e4e7fSToby Isaac ierr = PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO);CHKERRQ(ierr); 226521968bf8SToby Isaac } 226646bdb399SToby Isaac 226746bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 22688d2f55e7SToby Isaac PetscInt dof, matSize = 0; 22696ecaa68aSToby Isaac PetscInt aDof = 0; 22706ecaa68aSToby Isaac PetscInt cDof = 0; 22716ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22726ecaa68aSToby Isaac PetscInt numRowIndices = 0; 22736ecaa68aSToby Isaac PetscInt numColIndices = 0; 2274f13f9184SToby Isaac PetscInt f; 22756ecaa68aSToby Isaac 22766ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 22771cfc5b76SToby Isaac if (dof < 0) { 22781cfc5b76SToby Isaac dof = -(dof + 1); 22791cfc5b76SToby Isaac } 22806ecaa68aSToby Isaac if (p >= aStart && p < aEnd) { 22816ecaa68aSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 22826ecaa68aSToby Isaac } 22836ecaa68aSToby Isaac if (p >= cStart && p < cEnd) { 22846ecaa68aSToby Isaac ierr = PetscSectionGetDof(cSec,p,&cDof);CHKERRQ(ierr); 22856ecaa68aSToby Isaac } 2286f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2287f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 22886ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2289f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 22906ecaa68aSToby Isaac 22916ecaa68aSToby Isaac ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 229246bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 22936ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 22946ecaa68aSToby Isaac 22956ecaa68aSToby Isaac ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr); 22966ecaa68aSToby Isaac numRowIndices += clDof; 22976ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22986ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&clDof);CHKERRQ(ierr); 22996ecaa68aSToby Isaac offsets[f + 1] += clDof; 23006ecaa68aSToby Isaac } 23016ecaa68aSToby Isaac } 23026ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23036ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23046ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 23056ecaa68aSToby Isaac } 230646bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 23076ecaa68aSToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,NULL,NULL,&numColIndices,NULL,NULL,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 23086ecaa68aSToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 23096ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 23106ecaa68aSToby Isaac numColIndices = numRowIndices; 23116ecaa68aSToby Isaac matSize = 0; 23126ecaa68aSToby Isaac } 231346bdb399SToby Isaac else if (numFields) { /* we send one submat for each field: sum their sizes */ 23146ecaa68aSToby Isaac matSize = 0; 23156ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23166ecaa68aSToby Isaac PetscInt numRow, numCol; 23176ecaa68aSToby Isaac 23186ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2319f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 23206ecaa68aSToby Isaac matSize += numRow * numCol; 23216ecaa68aSToby Isaac } 23226ecaa68aSToby Isaac } 23236ecaa68aSToby Isaac else { 23246ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 23256ecaa68aSToby Isaac } 2326f13f9184SToby Isaac } else if (maxChildId == -1) { 23278d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2328f13f9184SToby Isaac PetscInt aOff, a; 23296ecaa68aSToby Isaac 23306ecaa68aSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 23316ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23326ecaa68aSToby Isaac PetscInt fDof; 23336ecaa68aSToby Isaac 23346ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 233521968bf8SToby Isaac offsets[f+1] = fDof; 23366ecaa68aSToby Isaac } 23376ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23386ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 23396ecaa68aSToby Isaac 23406ecaa68aSToby Isaac ierr = PetscSectionGetDof(localCoarse,anchor,&aLocalDof);CHKERRQ(ierr); 23416ecaa68aSToby Isaac numColIndices += aLocalDof; 23426ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23436ecaa68aSToby Isaac PetscInt fDof; 23446ecaa68aSToby Isaac 23456ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 234621968bf8SToby Isaac newOffsets[f+1] += fDof; 23476ecaa68aSToby Isaac } 23486ecaa68aSToby Isaac } 23496ecaa68aSToby Isaac if (numFields) { 23506ecaa68aSToby Isaac matSize = 0; 23516ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 235221968bf8SToby Isaac matSize += offsets[f+1] * newOffsets[f+1]; 23536ecaa68aSToby Isaac } 23546ecaa68aSToby Isaac } 23556ecaa68aSToby Isaac else { 23566ecaa68aSToby Isaac matSize = numColIndices * dof; 23576ecaa68aSToby Isaac } 23586ecaa68aSToby Isaac } 23596ecaa68aSToby Isaac else { /* no children, and no constraints on dofs: just get the global indices */ 23606ecaa68aSToby Isaac numColIndices = dof; 23616ecaa68aSToby Isaac matSize = 0; 23626ecaa68aSToby Isaac } 23638d2f55e7SToby Isaac } 236446bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 23656ecaa68aSToby Isaac ierr = PetscSectionSetDof(rootIndicesSec,p,numColIndices ? numColIndices+2*numFields : 0);CHKERRQ(ierr); 23666ecaa68aSToby Isaac ierr = PetscSectionSetDof(rootMatricesSec,p,matSize);CHKERRQ(ierr); 23676ecaa68aSToby Isaac } 23686ecaa68aSToby Isaac ierr = PetscSectionSetUp(rootIndicesSec);CHKERRQ(ierr); 23696ecaa68aSToby Isaac ierr = PetscSectionSetUp(rootMatricesSec);CHKERRQ(ierr); 23706ecaa68aSToby Isaac { 23716ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 23726ecaa68aSToby Isaac 23736ecaa68aSToby Isaac ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr); 23746ecaa68aSToby Isaac ierr = PetscSectionGetStorageSize(rootMatricesSec,&numRootMatrices);CHKERRQ(ierr); 23756ecaa68aSToby Isaac ierr = PetscMalloc2(numRootIndices,&rootIndices,numRootMatrices,&rootMatrices);CHKERRQ(ierr); 23766ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 23776ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2378f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 23796ecaa68aSToby Isaac PetscInt *pInd; 23806ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 23816ecaa68aSToby Isaac PetscScalar *pMat = NULL; 23826ecaa68aSToby Isaac 23836ecaa68aSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,p,&numColIndices);CHKERRQ(ierr); 23846ecaa68aSToby Isaac if (!numColIndices) { 23856ecaa68aSToby Isaac continue; 23866ecaa68aSToby Isaac } 2387f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2388f13f9184SToby Isaac offsets[f] = 0; 2389f13f9184SToby Isaac newOffsets[f] = 0; 2390f13f9184SToby Isaac offsetsCopy[f] = 0; 2391f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2392f13f9184SToby Isaac } 23936ecaa68aSToby Isaac numColIndices -= 2 * numFields; 23946ecaa68aSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,p,&pIndOff);CHKERRQ(ierr); 23956ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 23966ecaa68aSToby Isaac ierr = PetscSectionGetDof(rootMatricesSec,p,&matSize);CHKERRQ(ierr); 23976ecaa68aSToby Isaac if (matSize) { 23986ecaa68aSToby Isaac ierr = PetscSectionGetOffset(rootMatricesSec,p,&pMatOff);CHKERRQ(ierr); 23996ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 24006ecaa68aSToby Isaac } 24016ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 24021cfc5b76SToby Isaac if (dof < 0) { 24031cfc5b76SToby Isaac dof = -(dof + 1); 24041cfc5b76SToby Isaac } 24056ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 24066ecaa68aSToby Isaac PetscInt i, j; 24076ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 24086ecaa68aSToby Isaac 24096ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 24106ecaa68aSToby Isaac PetscInt numIndices, *indices; 24116ecaa68aSToby Isaac ierr = DMPlexGetClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr); 24126ecaa68aSToby Isaac if (numIndices != numColIndices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"mismatching constraint indices calculations"); 24136ecaa68aSToby Isaac for (i = 0; i < numColIndices; i++) { 24146ecaa68aSToby Isaac pInd[i] = indices[i]; 24156ecaa68aSToby Isaac } 24166ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 241746bdb399SToby Isaac pInd[numColIndices + i] = offsets[i+1]; 241846bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i+1]; 24196ecaa68aSToby Isaac } 242046bdb399SToby Isaac ierr = DMPlexRestoreClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr); 24216ecaa68aSToby Isaac } 24226ecaa68aSToby Isaac else { 24236ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 24246ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 24256ecaa68aSToby Isaac PetscInt numPoints,*points; 24266ecaa68aSToby Isaac 24276ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numRowIndices * numRowIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr); 24286ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 24296ecaa68aSToby Isaac for (j = 0; j < numRowIndices; j++) { 24306ecaa68aSToby Isaac pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 24316ecaa68aSToby Isaac } 24326ecaa68aSToby Isaac } 24336ecaa68aSToby Isaac ierr = DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 24346ecaa68aSToby Isaac if (numFields) { 24356ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 24366ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 24376ecaa68aSToby Isaac 24386ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24396ecaa68aSToby Isaac PetscInt fDof; 24406ecaa68aSToby Isaac 24416ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&fDof);CHKERRQ(ierr); 24426ecaa68aSToby Isaac offsets[f + 1] += fDof; 24436ecaa68aSToby Isaac } 24446ecaa68aSToby Isaac } 24456ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24466ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 24476ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 24486ecaa68aSToby Isaac } 24496ecaa68aSToby Isaac } 24506ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 2451267d4f3fSToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,pMatIn,&numPoints,NULL,&points,&pMatModified,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 24526ecaa68aSToby Isaac if (!numFields) { 24536ecaa68aSToby Isaac for (i = 0; i < numRowIndices * numColIndices; i++) { 24546ecaa68aSToby Isaac pMat[i] = pMatModified[i]; 24556ecaa68aSToby Isaac } 24566ecaa68aSToby Isaac } 24576ecaa68aSToby Isaac else { 2458f13f9184SToby Isaac PetscInt i, j, count; 24596ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24606ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f+1]; i++) { 24616ecaa68aSToby Isaac for (j = newOffsets[f]; j < newOffsets[f+1]; j++, count++) { 24626ecaa68aSToby Isaac pMat[count] = pMatModified[i * numColIndices + j]; 24636ecaa68aSToby Isaac } 24646ecaa68aSToby Isaac } 24656ecaa68aSToby Isaac } 24666ecaa68aSToby Isaac } 24676ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatModified);CHKERRQ(ierr); 24686ecaa68aSToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 24696ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr); 24706ecaa68aSToby Isaac if (numFields) { 247146bdb399SToby Isaac for (f = 0; f < numFields; f++) { 247246bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 247346bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 24746ecaa68aSToby Isaac } 24756ecaa68aSToby Isaac for (cl = 0; cl < numPoints*2; cl += 2) { 24766ecaa68aSToby Isaac PetscInt o = points[cl+1], globalOff, c = points[cl]; 24776ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 2478415ce65aSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, o, pInd); 24796ecaa68aSToby Isaac } 24806ecaa68aSToby Isaac } else { 24816ecaa68aSToby Isaac for (cl = 0; cl < numPoints*2; cl += 2) { 24826ecaa68aSToby Isaac PetscInt o = points[cl+1], c = points[cl], globalOff; 24836ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 2484415ce65aSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, o, pInd); 24856ecaa68aSToby Isaac } 24866ecaa68aSToby Isaac } 248728552ed4SToby Isaac ierr = DMRestoreWorkArray(coarse,numPoints,PETSC_SCALAR,&points);CHKERRQ(ierr); 24886ecaa68aSToby Isaac } 24896ecaa68aSToby Isaac } 24906ecaa68aSToby Isaac else if (matSize) { 24916ecaa68aSToby Isaac PetscInt cOff; 24926ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 24936ecaa68aSToby Isaac 24946ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 2495628cbfb8SToby Isaac if (numRowIndices != dof) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Miscounted dofs"); 24966ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr); 24976ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr); 24986ecaa68aSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&cOff);CHKERRQ(ierr); 24996ecaa68aSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 25006ecaa68aSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 25016ecaa68aSToby Isaac if (numFields) { 25026ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25036ecaa68aSToby Isaac PetscInt fDof; 2504f13f9184SToby Isaac 25056ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&fDof);CHKERRQ(ierr); 25066ecaa68aSToby Isaac offsets[f + 1] = fDof; 25076ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25086ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25096ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 25106ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 25116ecaa68aSToby Isaac } 25126ecaa68aSToby Isaac } 25136ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25146ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 25156ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 25166ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 25176ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 25186ecaa68aSToby Isaac } 2519415ce65aSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(cSec,p,cOff,offsetsCopy,PETSC_TRUE,0,rowIndices);CHKERRQ(ierr); 25206ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25216ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25226ecaa68aSToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 2523415ce65aSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(localCoarse,anchor,lOff,newOffsetsCopy,PETSC_TRUE,0,colIndices);CHKERRQ(ierr); 25246ecaa68aSToby Isaac } 25256ecaa68aSToby Isaac } 25266ecaa68aSToby Isaac else { 2527415ce65aSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(cSec,p,cOff,offsetsCopy,PETSC_TRUE,0,rowIndices);CHKERRQ(ierr); 25286ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25296ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25306ecaa68aSToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 2531415ce65aSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(localCoarse,anchor,lOff,newOffsetsCopy,PETSC_TRUE,0,colIndices);CHKERRQ(ierr); 25326ecaa68aSToby Isaac } 25336ecaa68aSToby Isaac } 25346ecaa68aSToby Isaac if (numFields) { 2535f13f9184SToby Isaac PetscInt count, a; 2536f13f9184SToby Isaac 25376ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 25386ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 25396ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 25406ecaa68aSToby Isaac ierr = MatGetValues(cMat,iSize,&rowIndices[offsets[f]],jSize,&colIndices[newOffsets[f]],&pMat[count]);CHKERRQ(ierr); 25416ecaa68aSToby Isaac count += iSize * jSize; 254246bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 254346bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 25446ecaa68aSToby Isaac } 25456ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25466ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25476ecaa68aSToby Isaac PetscInt gOff; 25486ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 2549415ce65aSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 25506ecaa68aSToby Isaac } 25516ecaa68aSToby Isaac } 25526ecaa68aSToby Isaac else { 25536ecaa68aSToby Isaac PetscInt a; 25546ecaa68aSToby Isaac ierr = MatGetValues(cMat,numRowIndices,rowIndices,numColIndices,colIndices,pMat);CHKERRQ(ierr); 25556ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25566ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25576ecaa68aSToby Isaac PetscInt gOff; 25586ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 2559415ce65aSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 25606ecaa68aSToby Isaac } 25616ecaa68aSToby Isaac } 25626ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr); 25636ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr); 25646ecaa68aSToby Isaac } 25656ecaa68aSToby Isaac else { 25666ecaa68aSToby Isaac PetscInt gOff; 25676ecaa68aSToby Isaac 25686ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 25696ecaa68aSToby Isaac if (numFields) { 25706ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25716ecaa68aSToby Isaac PetscInt fDof; 25726ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 25736ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 25746ecaa68aSToby Isaac } 25756ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 257646bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 257746bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f+1]; 25786ecaa68aSToby Isaac } 2579415ce65aSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 25806ecaa68aSToby Isaac } 25816ecaa68aSToby Isaac else { 2582415ce65aSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 25836ecaa68aSToby Isaac } 25846ecaa68aSToby Isaac } 25856ecaa68aSToby Isaac } 2586e44e4e7fSToby Isaac ierr = PetscFree(maxChildIds);CHKERRQ(ierr); 25876ecaa68aSToby Isaac } 258846bdb399SToby Isaac { 258946bdb399SToby Isaac PetscSF indicesSF, matricesSF; 259046bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 259146bdb399SToby Isaac 259246bdb399SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr); 259346bdb399SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafMatricesSec);CHKERRQ(ierr); 259446bdb399SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootIndicesSec,&remoteOffsetsIndices,leafIndicesSec);CHKERRQ(ierr); 259546bdb399SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootMatricesSec,&remoteOffsetsMatrices,leafMatricesSec);CHKERRQ(ierr); 259646bdb399SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootIndicesSec,remoteOffsetsIndices,leafIndicesSec,&indicesSF);CHKERRQ(ierr); 259746bdb399SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootMatricesSec,remoteOffsetsMatrices,leafMatricesSec,&matricesSF);CHKERRQ(ierr); 2598e44e4e7fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 259946bdb399SToby Isaac ierr = PetscFree(remoteOffsetsIndices);CHKERRQ(ierr); 260046bdb399SToby Isaac ierr = PetscFree(remoteOffsetsMatrices);CHKERRQ(ierr); 260146bdb399SToby Isaac ierr = PetscSectionGetStorageSize(leafIndicesSec,&numLeafIndices);CHKERRQ(ierr); 260246bdb399SToby Isaac ierr = PetscSectionGetStorageSize(leafMatricesSec,&numLeafMatrices);CHKERRQ(ierr); 260346bdb399SToby Isaac ierr = PetscMalloc2(numLeafIndices,&leafIndices,numLeafMatrices,&leafMatrices);CHKERRQ(ierr); 260446bdb399SToby Isaac ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr); 2605267d4f3fSToby Isaac ierr = PetscSFBcastBegin(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices);CHKERRQ(ierr); 260646bdb399SToby Isaac ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr); 2607267d4f3fSToby Isaac ierr = PetscSFBcastEnd(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices);CHKERRQ(ierr); 260846bdb399SToby Isaac ierr = PetscSFDestroy(&matricesSF);CHKERRQ(ierr); 260946bdb399SToby Isaac ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr); 261046bdb399SToby Isaac ierr = PetscFree2(rootIndices,rootMatrices);CHKERRQ(ierr); 261146bdb399SToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 261246bdb399SToby Isaac ierr = PetscSectionDestroy(&rootMatricesSec);CHKERRQ(ierr); 261346bdb399SToby Isaac } 261446bdb399SToby Isaac /* count to preallocate */ 261546bdb399SToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 261646bdb399SToby Isaac { 261746bdb399SToby Isaac PetscInt nGlobal; 261846bdb399SToby Isaac PetscInt *dnnz, *onnz; 2619b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2620b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 26211c58ffc4SToby Isaac PetscInt maxDof; 26221c58ffc4SToby Isaac PetscInt *rowIndices; 26231c58ffc4SToby Isaac DM refTree; 26241c58ffc4SToby Isaac PetscInt **refPointFieldN; 26251c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 26261c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 26270eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,maxConDof,maxColumns,leafStart,leafEnd; 26281c58ffc4SToby Isaac PetscScalar *pointWork; 262946bdb399SToby Isaac 263046bdb399SToby Isaac ierr = PetscSectionGetConstrainedStorageSize(globalFine,&nGlobal);CHKERRQ(ierr); 263146bdb399SToby Isaac ierr = PetscCalloc2(nGlobal,&dnnz,nGlobal,&onnz);CHKERRQ(ierr); 2632b9a5774bSToby Isaac ierr = MatGetLayouts(mat,&rowMap,&colMap);CHKERRQ(ierr); 2633b9a5774bSToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 26341c58ffc4SToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 2635b9a5774bSToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 263646bdb399SToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 26371c58ffc4SToby Isaac ierr = PetscSectionGetMaxDof(globalFine,&maxDof);CHKERRQ(ierr); 26380eb7e1eaSToby Isaac ierr = PetscSectionGetChart(leafIndicesSec,&leafStart,&leafEnd);CHKERRQ(ierr); 26391c58ffc4SToby Isaac ierr = DMGetWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 26400eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 264146bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 264246bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 264346bdb399SToby Isaac PetscInt matSize; 264421968bf8SToby Isaac PetscInt i; 264546bdb399SToby Isaac 264646bdb399SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 264746bdb399SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 264846bdb399SToby Isaac if ((gDof - gcDof) <= 0) { 264946bdb399SToby Isaac continue; 265046bdb399SToby Isaac } 265146bdb399SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 265246bdb399SToby Isaac if (gOff < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"I though having global dofs meant a non-negative offset"); 2653b9a5774bSToby Isaac if ((gOff < rowStart) || ((gOff + gDof - gcDof) > rowEnd)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"I thought the row map would constrain the global dofs"); 265446bdb399SToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 265546bdb399SToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 265646bdb399SToby Isaac numColIndices -= 2 * numFields; 26571c58ffc4SToby Isaac if (numColIndices <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"global fine dof with no dofs to interpolate from"); 265846bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 265921968bf8SToby Isaac offsets[0] = 0; 266021968bf8SToby Isaac offsetsCopy[0] = 0; 266121968bf8SToby Isaac newOffsets[0] = 0; 266221968bf8SToby Isaac newOffsetsCopy[0] = 0; 266346bdb399SToby Isaac if (numFields) { 266421968bf8SToby Isaac PetscInt f; 266546bdb399SToby Isaac for (f = 0; f < numFields; f++) { 266646bdb399SToby Isaac PetscInt rowDof; 266746bdb399SToby Isaac 266846bdb399SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 266921968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 267021968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 267121968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 267221968bf8SToby Isaac numD[f] = 0; 267321968bf8SToby Isaac numO[f] = 0; 267446bdb399SToby Isaac } 2675415ce65aSMatthew G. Knepley ierr = DMPlexGetIndicesPointFields_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 267646bdb399SToby Isaac for (f = 0; f < numFields; f++) { 267721968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 267821968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 267946bdb399SToby Isaac 268046bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 268146bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 268246bdb399SToby Isaac 268346bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 268421968bf8SToby Isaac numD[f]++; 268546bdb399SToby Isaac } 268646bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 268721968bf8SToby Isaac numO[f]++; 268846bdb399SToby Isaac } 268946bdb399SToby Isaac } 269046bdb399SToby Isaac } 269146bdb399SToby Isaac } 269246bdb399SToby Isaac else { 2693415ce65aSMatthew G. Knepley ierr = DMPlexGetIndicesPoint_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 269421968bf8SToby Isaac numD[0] = 0; 269521968bf8SToby Isaac numO[0] = 0; 269646bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 269746bdb399SToby Isaac PetscInt gInd = pInd[i]; 269846bdb399SToby Isaac 269946bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 270021968bf8SToby Isaac numD[0]++; 270146bdb399SToby Isaac } 270246bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 270321968bf8SToby Isaac numO[0]++; 270446bdb399SToby Isaac } 270546bdb399SToby Isaac } 270646bdb399SToby Isaac } 270746bdb399SToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 270846bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 270946bdb399SToby Isaac PetscInt childId; 271046bdb399SToby Isaac 271146bdb399SToby Isaac childId = childIds[p-pStartF]; 271221968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 271346bdb399SToby Isaac if (numFields) { 2714b9a5774bSToby Isaac PetscInt f; 2715b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 271621968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 271746bdb399SToby Isaac for (row = 0; row < numRows; row++) { 271821968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 271921968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 272046bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 2721b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2722b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 272346bdb399SToby Isaac } 272446bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 2725b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2726b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 272746bdb399SToby Isaac } 272846bdb399SToby Isaac else { /* constrained */ 272946bdb399SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 273046bdb399SToby Isaac } 273146bdb399SToby Isaac } 273246bdb399SToby Isaac } 273346bdb399SToby Isaac } 273446bdb399SToby Isaac else { 2735b9a5774bSToby Isaac PetscInt i; 2736b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 273746bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 273846bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 273946bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 2740b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2741b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 274246bdb399SToby Isaac } 274346bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 2744b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2745b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 274646bdb399SToby Isaac } 274746bdb399SToby Isaac else { /* constrained */ 274846bdb399SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 274946bdb399SToby Isaac } 275046bdb399SToby Isaac } 275146bdb399SToby Isaac } 275246bdb399SToby Isaac } 275346bdb399SToby Isaac else { /* interpolate from all */ 275446bdb399SToby Isaac if (numFields) { 2755b9a5774bSToby Isaac PetscInt f; 2756b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 275721968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 275846bdb399SToby Isaac for (row = 0; row < numRows; row++) { 275921968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 276046bdb399SToby Isaac if (gIndFine >= 0) { 2761b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2762b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2763b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 276446bdb399SToby Isaac } 276546bdb399SToby Isaac } 276646bdb399SToby Isaac } 276746bdb399SToby Isaac } 276846bdb399SToby Isaac else { 2769b9a5774bSToby Isaac PetscInt i; 2770b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 277146bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 277246bdb399SToby Isaac if (gIndFine >= 0) { 2773b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2774b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2775b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 277646bdb399SToby Isaac } 277746bdb399SToby Isaac } 277846bdb399SToby Isaac } 277946bdb399SToby Isaac } 278046bdb399SToby Isaac } 278146bdb399SToby Isaac else { /* interpolate from all */ 278246bdb399SToby Isaac if (numFields) { 2783b9a5774bSToby Isaac PetscInt f; 2784b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 278521968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 278646bdb399SToby Isaac for (row = 0; row < numRows; row++) { 278721968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 278846bdb399SToby Isaac if (gIndFine >= 0) { 2789b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2790b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2791b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 279246bdb399SToby Isaac } 279346bdb399SToby Isaac } 279446bdb399SToby Isaac } 279546bdb399SToby Isaac } 279646bdb399SToby Isaac else { /* every dof get a full row */ 2797b9a5774bSToby Isaac PetscInt i; 2798b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 279946bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 280046bdb399SToby Isaac if (gIndFine >= 0) { 2801b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2802b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2803b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 280446bdb399SToby Isaac } 280546bdb399SToby Isaac } 280646bdb399SToby Isaac } 280746bdb399SToby Isaac } 280846bdb399SToby Isaac } 280946bdb399SToby Isaac ierr = MatXAIJSetPreallocation(mat,1,dnnz,onnz,NULL,NULL);CHKERRQ(ierr); 281046bdb399SToby Isaac ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 281121968bf8SToby Isaac 281221968bf8SToby Isaac ierr = DMPlexGetReferenceTree(fine,&refTree);CHKERRQ(ierr); 281321968bf8SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 2814e44e4e7fSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 2815e44e4e7fSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,NULL);CHKERRQ(ierr); 2816e44e4e7fSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 28171c58ffc4SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxConDof);CHKERRQ(ierr); 28187c0540e0SToby Isaac ierr = PetscSectionGetMaxDof(leafIndicesSec,&maxColumns);CHKERRQ(ierr); 28197c0540e0SToby Isaac ierr = PetscMalloc1(maxConDof*maxColumns,&pointWork);CHKERRQ(ierr); 28200eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2821e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2822e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2823e44e4e7fSToby Isaac PetscInt matSize; 2824e44e4e7fSToby Isaac PetscInt childId; 2825e44e4e7fSToby Isaac 2826e44e4e7fSToby Isaac 2827e44e4e7fSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 2828e44e4e7fSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 2829e44e4e7fSToby Isaac if ((gDof - gcDof) <= 0) { 2830e44e4e7fSToby Isaac continue; 2831e44e4e7fSToby Isaac } 2832e44e4e7fSToby Isaac childId = childIds[p-pStartF]; 2833e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 2834e44e4e7fSToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 2835e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 2836e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2837e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2838e44e4e7fSToby Isaac offsets[0] = 0; 2839e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2840e44e4e7fSToby Isaac newOffsets[0] = 0; 2841e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2842e44e4e7fSToby Isaac rowOffsets[0] = 0; 2843e44e4e7fSToby Isaac if (numFields) { 2844e44e4e7fSToby Isaac PetscInt f; 2845e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2846e44e4e7fSToby Isaac PetscInt rowDof; 2847e44e4e7fSToby Isaac 2848e44e4e7fSToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 2849e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2850e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2851e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2852e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2853e44e4e7fSToby Isaac } 2854415ce65aSMatthew G. Knepley ierr = DMPlexGetIndicesPointFields_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 2855e44e4e7fSToby Isaac } 28561c58ffc4SToby Isaac else { 2857415ce65aSMatthew G. Knepley ierr = DMPlexGetIndicesPoint_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 28581c58ffc4SToby Isaac } 2859e44e4e7fSToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 2860e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2861e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2862e44e4e7fSToby Isaac if (numFields) { 2863e44e4e7fSToby Isaac PetscInt f; 2864e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2865e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 2866e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 2867e44e4e7fSToby Isaac ierr = MatSetValue(mat,rowIndices[offsets[f]+row],pInd[newOffsets[f]+row],1.,INSERT_VALUES);CHKERRQ(ierr); 286821968bf8SToby Isaac } 286921968bf8SToby Isaac } 2870e44e4e7fSToby Isaac } 2871e44e4e7fSToby Isaac else { 2872e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 2873e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 2874e44e4e7fSToby Isaac ierr = MatSetValue(mat,rowIndices[row],pInd[row],1.,INSERT_VALUES);CHKERRQ(ierr); 2875e44e4e7fSToby Isaac } 2876e44e4e7fSToby Isaac } 2877e44e4e7fSToby Isaac } 2878e44e4e7fSToby Isaac else { /* interpolate from all */ 2879e44e4e7fSToby Isaac if (numFields) { 2880e44e4e7fSToby Isaac PetscInt f; 2881e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2882e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 2883e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2884e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],refPointFieldMats[childId - pRefStart][f],INSERT_VALUES);CHKERRQ(ierr); 2885e44e4e7fSToby Isaac } 2886e44e4e7fSToby Isaac } 2887e44e4e7fSToby Isaac else { 2888e44e4e7fSToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,refPointFieldMats[childId - pRefStart][0],INSERT_VALUES);CHKERRQ(ierr); 2889e44e4e7fSToby Isaac } 2890e44e4e7fSToby Isaac } 2891e44e4e7fSToby Isaac } 2892e44e4e7fSToby Isaac else { /* interpolate from all */ 2893e44e4e7fSToby Isaac PetscInt pMatOff; 2894e44e4e7fSToby Isaac PetscScalar *pMat; 2895e44e4e7fSToby Isaac 2896e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(leafMatricesSec,p,&pMatOff);CHKERRQ(ierr); 2897e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2898e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2899e44e4e7fSToby Isaac if (numFields) { 2900e44e4e7fSToby Isaac PetscInt f, count; 2901e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2902e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2903e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2904e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2905e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2906e44e4e7fSToby Isaac 2907e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],inMat,INSERT_VALUES);CHKERRQ(ierr); 2908e44e4e7fSToby Isaac count += numCols * numInRows; 2909e44e4e7fSToby Isaac } 2910e44e4e7fSToby Isaac } 2911e44e4e7fSToby Isaac else { 2912e44e4e7fSToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,pMat,INSERT_VALUES);CHKERRQ(ierr); 2913e44e4e7fSToby Isaac } 2914e44e4e7fSToby Isaac } 2915e44e4e7fSToby Isaac else { /* multiply the incoming matrix by the child interpolation */ 2916e44e4e7fSToby Isaac if (numFields) { 2917e44e4e7fSToby Isaac PetscInt f, count; 2918e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2919e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2920e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2921e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2922e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2923e44e4e7fSToby Isaac PetscInt i, j, k; 2924e44e4e7fSToby Isaac if (refPointFieldN[childId - pRefStart][f] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2925e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2926e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2927e44e4e7fSToby Isaac PetscScalar val = 0.; 2928e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2929e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2930e44e4e7fSToby Isaac } 2931e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2932e44e4e7fSToby Isaac } 2933e44e4e7fSToby Isaac } 2934e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],pointWork,INSERT_VALUES);CHKERRQ(ierr); 2935e44e4e7fSToby Isaac count += numCols * numInRows; 2936e44e4e7fSToby Isaac } 2937e44e4e7fSToby Isaac } 2938267d4f3fSToby Isaac else { /* every dof gets a full row */ 2939e44e4e7fSToby Isaac PetscInt numRows = gDof; 2940e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2941e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2942e44e4e7fSToby Isaac PetscInt i, j, k; 2943e44e4e7fSToby Isaac if (refPointFieldN[childId - pRefStart][0] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2944e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2945e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2946e44e4e7fSToby Isaac PetscScalar val = 0.; 2947e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2948e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2949e44e4e7fSToby Isaac } 2950e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2951e44e4e7fSToby Isaac } 2952e44e4e7fSToby Isaac } 2953e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,rowIndices,numCols,pInd,pointWork,INSERT_VALUES);CHKERRQ(ierr); 2954e44e4e7fSToby Isaac } 2955e44e4e7fSToby Isaac } 2956e44e4e7fSToby Isaac } 2957e44e4e7fSToby Isaac } 29581c58ffc4SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 29591c58ffc4SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 2960e44e4e7fSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 2961e44e4e7fSToby Isaac } 2962e44e4e7fSToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2963e44e4e7fSToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2964e44e4e7fSToby Isaac ierr = PetscSectionDestroy(&leafIndicesSec);CHKERRQ(ierr); 2965e44e4e7fSToby Isaac ierr = PetscSectionDestroy(&leafMatricesSec);CHKERRQ(ierr); 2966e44e4e7fSToby Isaac ierr = PetscFree2(leafIndices,leafMatrices);CHKERRQ(ierr); 2967e44e4e7fSToby Isaac ierr = PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO);CHKERRQ(ierr); 29686ecaa68aSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 29696ecaa68aSToby Isaac PetscFunctionReturn(0); 29706ecaa68aSToby Isaac } 2971154bca37SToby Isaac 2972154bca37SToby Isaac #undef __FUNCT__ 29738d2f55e7SToby Isaac #define __FUNCT__ "DMPlexComputeInjectorReferenceTree" 29748d2f55e7SToby Isaac /* 29758d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 29768d2f55e7SToby Isaac * 29778d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 29788d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 29798d2f55e7SToby Isaac * for each fine dof \phi^f_j; 29808d2f55e7SToby Isaac * a_{i,j} = 0; 29818d2f55e7SToby Isaac * for each fine dof \phi^f_k: 29828d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 29838d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 29848d2f55e7SToby Isaac */ 29858d2f55e7SToby Isaac PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 29868d2f55e7SToby Isaac { 29878d2f55e7SToby Isaac PetscDS ds; 29888d2f55e7SToby Isaac PetscSection section, cSection; 29898d2f55e7SToby Isaac DMLabel canonical, depth; 29908d2f55e7SToby Isaac Mat cMat, mat; 29918d2f55e7SToby Isaac PetscInt *nnz; 29928d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 29938d2f55e7SToby Isaac PetscInt m, n; 29948d2f55e7SToby Isaac PetscScalar *pointScalar; 29958d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 29968d2f55e7SToby Isaac PetscErrorCode ierr; 29978d2f55e7SToby Isaac 29988d2f55e7SToby Isaac PetscFunctionBegin; 29998d2f55e7SToby Isaac ierr = DMGetDefaultSection(refTree,§ion);CHKERRQ(ierr); 30008d2f55e7SToby Isaac ierr = DMGetDimension(refTree, &dim);CHKERRQ(ierr); 30018d2f55e7SToby Isaac ierr = PetscMalloc6(dim,&v0,dim,&v0parent,dim,&vtmp,dim*dim,&J,dim*dim,&Jparent,dim*dim,&invJ);CHKERRQ(ierr); 30028d2f55e7SToby Isaac ierr = PetscMalloc2(dim,&pointScalar,dim,&pointRef);CHKERRQ(ierr); 30038d2f55e7SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 30048d2f55e7SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 30058d2f55e7SToby Isaac ierr = PetscSectionGetNumFields(section,&numSecFields);CHKERRQ(ierr); 30068d2f55e7SToby Isaac ierr = DMGetLabel(refTree,"canonical",&canonical);CHKERRQ(ierr); 30078d2f55e7SToby Isaac ierr = DMGetLabel(refTree,"depth",&depth);CHKERRQ(ierr); 30088d2f55e7SToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSection,&cMat);CHKERRQ(ierr); 30098d2f55e7SToby Isaac ierr = DMPlexGetChart(refTree, &pStart, &pEnd);CHKERRQ(ierr); 30108d2f55e7SToby Isaac ierr = DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd);CHKERRQ(ierr); 30118d2f55e7SToby Isaac ierr = MatGetSize(cMat,&n,&m);CHKERRQ(ierr); /* the injector has transpose sizes from the constraint matrix */ 30128d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 30138d2f55e7SToby Isaac ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr); 30148d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { /* a point will have non-zeros if it is canonical, it has dofs, and its children have dofs */ 30158d2f55e7SToby Isaac const PetscInt *children; 30168d2f55e7SToby Isaac PetscInt numChildren; 30178d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30188d2f55e7SToby Isaac 30198d2f55e7SToby Isaac if (canonical) { 30208d2f55e7SToby Isaac PetscInt pCanonical; 30218d2f55e7SToby Isaac ierr = DMLabelGetValue(canonical,p,&pCanonical);CHKERRQ(ierr); 30228d2f55e7SToby Isaac if (p != pCanonical) continue; 30238d2f55e7SToby Isaac } 30248d2f55e7SToby Isaac ierr = DMPlexGetTreeChildren(refTree,p,&numChildren,&children);CHKERRQ(ierr); 30258d2f55e7SToby Isaac if (!numChildren) continue; 30268d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30278d2f55e7SToby Isaac PetscInt child = children[i]; 30288d2f55e7SToby Isaac PetscInt dof; 30298d2f55e7SToby Isaac 30308d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,child,&dof);CHKERRQ(ierr); 30318d2f55e7SToby Isaac numChildDof += dof; 30328d2f55e7SToby Isaac } 30338d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,p,&numSelfDof);CHKERRQ(ierr); 30348d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30358d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 30368d2f55e7SToby Isaac PetscInt selfOff; 30378d2f55e7SToby Isaac 30388d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 30398d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30408d2f55e7SToby Isaac PetscInt child = children[i]; 30418d2f55e7SToby Isaac PetscInt dof; 30428d2f55e7SToby Isaac 30438d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,child,f,&dof);CHKERRQ(ierr); 30448d2f55e7SToby Isaac numChildDof += dof; 30458d2f55e7SToby Isaac } 30468d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&numSelfDof);CHKERRQ(ierr); 30478d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(section,p,f,&selfOff);CHKERRQ(ierr); 30488d2f55e7SToby Isaac } 30498d2f55e7SToby Isaac else { 30508d2f55e7SToby Isaac ierr = PetscSectionGetOffset(section,p,&selfOff);CHKERRQ(ierr); 30518d2f55e7SToby Isaac } 30528d2f55e7SToby Isaac for (i = 0; i < numSelfDof; i++) { 30538d2f55e7SToby Isaac nnz[selfOff + i] = numChildDof; 30548d2f55e7SToby Isaac } 30558d2f55e7SToby Isaac } 30568d2f55e7SToby Isaac } 30578d2f55e7SToby Isaac ierr = MatCreateAIJ(PETSC_COMM_SELF,m,n,m,n,-1,nnz,-1,NULL,&mat);CHKERRQ(ierr); 30588d2f55e7SToby Isaac ierr = PetscFree(nnz);CHKERRQ(ierr); 30598d2f55e7SToby Isaac /* Setp 2: compute entries */ 30608d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 30618d2f55e7SToby Isaac const PetscInt *children; 30628d2f55e7SToby Isaac PetscInt numChildren; 30638d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30648d2f55e7SToby Isaac 30658d2f55e7SToby Isaac /* same conditions about when entries occur */ 30668d2f55e7SToby Isaac if (canonical) { 30678d2f55e7SToby Isaac PetscInt pCanonical; 30688d2f55e7SToby Isaac ierr = DMLabelGetValue(canonical,p,&pCanonical);CHKERRQ(ierr); 30698d2f55e7SToby Isaac if (p != pCanonical) continue; 30708d2f55e7SToby Isaac } 30718d2f55e7SToby Isaac ierr = DMPlexGetTreeChildren(refTree,p,&numChildren,&children);CHKERRQ(ierr); 30728d2f55e7SToby Isaac if (!numChildren) continue; 30738d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30748d2f55e7SToby Isaac PetscInt child = children[i]; 30758d2f55e7SToby Isaac PetscInt dof; 30768d2f55e7SToby Isaac 30778d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,child,&dof);CHKERRQ(ierr); 30788d2f55e7SToby Isaac numChildDof += dof; 30798d2f55e7SToby Isaac } 30808d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,p,&numSelfDof);CHKERRQ(ierr); 30818d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30828d2f55e7SToby Isaac 30838d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 30848d2f55e7SToby Isaac PetscInt selfOff, fComp, numSelfShapes, numChildShapes, parentCell; 30858d2f55e7SToby Isaac PetscInt cellShapeOff; 30868d2f55e7SToby Isaac PetscObject disc; 30878d2f55e7SToby Isaac PetscDualSpace dsp; 30888d2f55e7SToby Isaac PetscClassId classId; 30898d2f55e7SToby Isaac PetscScalar *pointMat; 30903b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 30918d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 30928d2f55e7SToby Isaac const PetscInt *depthNumDof; 30938d2f55e7SToby Isaac 30948d2f55e7SToby Isaac if (numSecFields) { 30958d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30968d2f55e7SToby Isaac PetscInt child = children[i]; 30978d2f55e7SToby Isaac PetscInt dof; 30988d2f55e7SToby Isaac 30998d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,child,f,&dof);CHKERRQ(ierr); 31008d2f55e7SToby Isaac numChildDof += dof; 31018d2f55e7SToby Isaac } 31028d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&numSelfDof);CHKERRQ(ierr); 31038d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(section,p,f,&selfOff);CHKERRQ(ierr); 31048d2f55e7SToby Isaac ierr = PetscSectionGetFieldComponents(section,f,&fComp);CHKERRQ(ierr); 31058d2f55e7SToby Isaac } 31068d2f55e7SToby Isaac else { 31078d2f55e7SToby Isaac ierr = PetscSectionGetOffset(section,p,&selfOff);CHKERRQ(ierr); 31088d2f55e7SToby Isaac fComp = 1; 31098d2f55e7SToby Isaac } 31108d2f55e7SToby Isaac numSelfShapes = numSelfDof / fComp; 31118d2f55e7SToby Isaac numChildShapes = numChildDof / fComp; 31128d2f55e7SToby Isaac 31133b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 31148d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 31158d2f55e7SToby Isaac parentCell = p; 31168d2f55e7SToby Isaac } 31178d2f55e7SToby Isaac else { 31188d2f55e7SToby Isaac PetscInt *star = NULL; 31198d2f55e7SToby Isaac PetscInt numStar; 31208d2f55e7SToby Isaac 31218d2f55e7SToby Isaac parentCell = -1; 31228d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 31238d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 31248d2f55e7SToby Isaac PetscInt c = star[2 * i]; 31258d2f55e7SToby Isaac 31268d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 31278d2f55e7SToby Isaac parentCell = c; 31288d2f55e7SToby Isaac break; 31298d2f55e7SToby Isaac } 31308d2f55e7SToby Isaac } 31318d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 31328d2f55e7SToby Isaac } 31338d2f55e7SToby Isaac /* determine the offset of p's shape functions withing parentCell's shape functions */ 3134c5356c36SToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 3135c5356c36SToby Isaac ierr = PetscObjectGetClassId(disc,&classId);CHKERRQ(ierr); 3136c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 3137c5356c36SToby Isaac ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 3138c5356c36SToby Isaac } 3139c5356c36SToby Isaac else if (classId == PETSCFV_CLASSID) { 3140c5356c36SToby Isaac ierr = PetscFVGetDualSpace((PetscFV)disc,&dsp);CHKERRQ(ierr); 3141c5356c36SToby Isaac } 3142c5356c36SToby Isaac else { 3143c5356c36SToby Isaac SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported discretization object");CHKERRQ(ierr); 3144c5356c36SToby Isaac } 31458d2f55e7SToby Isaac ierr = PetscDualSpaceGetNumDof(dsp,&depthNumDof);CHKERRQ(ierr); 31468d2f55e7SToby Isaac { 31478d2f55e7SToby Isaac PetscInt *closure = NULL; 31488d2f55e7SToby Isaac PetscInt numClosure; 31498d2f55e7SToby Isaac 31508d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 31518d2f55e7SToby Isaac for (i = 0, cellShapeOff = 0; i < numClosure; i++) { 31528d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 31538d2f55e7SToby Isaac 31548d2f55e7SToby Isaac pO = closure[2 * i + 1]; 31558d2f55e7SToby Isaac if (point == p) break; 31568d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,point,&pointDepth);CHKERRQ(ierr); 31578d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 31588d2f55e7SToby Isaac } 31598d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 31608d2f55e7SToby Isaac } 31618d2f55e7SToby Isaac 31628d2f55e7SToby Isaac ierr = DMGetWorkArray(refTree, numSelfShapes * numChildShapes, PETSC_SCALAR,&pointMat);CHKERRQ(ierr); 31633b1c2a6aSToby Isaac ierr = DMGetWorkArray(refTree, numSelfShapes + numChildShapes, PETSC_INT,&matRows);CHKERRQ(ierr); 31643b1c2a6aSToby Isaac matCols = matRows + numSelfShapes; 31653b1c2a6aSToby Isaac for (i = 0; i < numSelfShapes; i++) { 31663b1c2a6aSToby Isaac matRows[i] = selfOff + i * fComp; 31673b1c2a6aSToby Isaac } 31683b1c2a6aSToby Isaac { 31693b1c2a6aSToby Isaac PetscInt colOff = 0; 31703b1c2a6aSToby Isaac 31713b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 31723b1c2a6aSToby Isaac PetscInt child = children[i]; 31733b1c2a6aSToby Isaac PetscInt dof, off, j; 31743b1c2a6aSToby Isaac 31753b1c2a6aSToby Isaac if (numSecFields) { 3176c5356c36SToby Isaac ierr = PetscSectionGetFieldDof(cSection,child,f,&dof);CHKERRQ(ierr); 3177c5356c36SToby Isaac ierr = PetscSectionGetFieldOffset(cSection,child,f,&off);CHKERRQ(ierr); 31783b1c2a6aSToby Isaac } 31793b1c2a6aSToby Isaac else { 3180c5356c36SToby Isaac ierr = PetscSectionGetDof(cSection,child,&dof);CHKERRQ(ierr); 3181c5356c36SToby Isaac ierr = PetscSectionGetOffset(cSection,child,&off);CHKERRQ(ierr); 31823b1c2a6aSToby Isaac } 31833b1c2a6aSToby Isaac 31843b1c2a6aSToby Isaac for (j = 0; j < dof / fComp; j++) { 31853b1c2a6aSToby Isaac matCols[colOff++] = off + j * fComp; 31863b1c2a6aSToby Isaac } 31873b1c2a6aSToby Isaac } 31883b1c2a6aSToby Isaac } 31898d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 31908d2f55e7SToby Isaac PetscFE fe = (PetscFE) disc; 31918d2f55e7SToby Isaac PetscInt fSize; 31928d2f55e7SToby Isaac 31938d2f55e7SToby Isaac ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr); 31943b1c2a6aSToby Isaac ierr = PetscDualSpaceGetDimension(dsp,&fSize);CHKERRQ(ierr); 31958d2f55e7SToby Isaac for (i = 0; i < numSelfShapes; i++) { /* for every shape function */ 31968d2f55e7SToby Isaac PetscQuadrature q; 31978d2f55e7SToby Isaac PetscInt dim, numPoints, j, k; 31988d2f55e7SToby Isaac const PetscReal *points; 31998d2f55e7SToby Isaac const PetscReal *weights; 32008d2f55e7SToby Isaac PetscInt *closure = NULL; 32018d2f55e7SToby Isaac PetscInt numClosure; 32023b1c2a6aSToby Isaac PetscInt parentCellShapeDof = cellShapeOff + (pO < 0 ? (numSelfShapes - 1 - i) : i); 32038d2f55e7SToby Isaac PetscReal *Bparent; 32048d2f55e7SToby Isaac 32053b1c2a6aSToby Isaac ierr = PetscDualSpaceGetFunctional(dsp,parentCellShapeDof,&q);CHKERRQ(ierr); 32063b1c2a6aSToby Isaac ierr = PetscQuadratureGetData(q,&dim,&numPoints,&points,&weights);CHKERRQ(ierr); 32073b1c2a6aSToby Isaac ierr = PetscFEGetTabulation(fe,numPoints,points,&Bparent,NULL,NULL);CHKERRQ(ierr); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 32088d2f55e7SToby Isaac for (k = 0; k < numChildShapes; k++) { 32098d2f55e7SToby Isaac pointMat[numChildShapes * i + k] = 0.; 32108d2f55e7SToby Isaac } 32113b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 32128d2f55e7SToby Isaac PetscInt childCell = -1; 32133b1c2a6aSToby Isaac PetscReal parentValAtPoint; 32148d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 32158d2f55e7SToby Isaac const PetscScalar *point; 32168d2f55e7SToby Isaac PetscReal *Bchild; 32178d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 32188d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 32198d2f55e7SToby Isaac PetscInt d; 32208d2f55e7SToby Isaac 32218d2f55e7SToby Isaac for (d = 0; d < dim; d++) { 32228d2f55e7SToby Isaac pointScalar[d] = points[dim * j + d]; 32238d2f55e7SToby Isaac } 32248d2f55e7SToby Isaac point = pointScalar; 32258d2f55e7SToby Isaac #else 32268d2f55e7SToby Isaac point = pointReal; 32278d2f55e7SToby Isaac #endif 32288d2f55e7SToby Isaac 32293b1c2a6aSToby Isaac parentValAtPoint = Bparent[(fSize * j + parentCellShapeDof) * fComp]; 32303b1c2a6aSToby Isaac 32313b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 32328d2f55e7SToby Isaac PetscInt child = children[k]; 32338d2f55e7SToby Isaac PetscInt *star = NULL; 32348d2f55e7SToby Isaac PetscInt numStar, s; 32358d2f55e7SToby Isaac 32368d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 32378d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 32388d2f55e7SToby Isaac PetscInt c = star[2 * s]; 32398d2f55e7SToby Isaac 32408d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 32418d2f55e7SToby Isaac ierr = DMPlexLocatePoint_Internal(refTree,dim,point,c,&childCell);CHKERRQ(ierr); 32428d2f55e7SToby Isaac if (childCell >= 0) break; 32438d2f55e7SToby Isaac } 32448d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 32458d2f55e7SToby Isaac if (childCell >= 0) break; 32468d2f55e7SToby Isaac } 32478d2f55e7SToby Isaac if (childCell < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not locate quadrature point");CHKERRQ(ierr); 32488d2f55e7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 32498d2f55e7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent);CHKERRQ(ierr); 32508d2f55e7SToby Isaac CoordinatesRefToReal(dim, dim, v0parent, Jparent, pointReal, vtmp); 32518d2f55e7SToby Isaac CoordinatesRealToRef(dim, dim, v0, invJ, vtmp, pointRef); 32528d2f55e7SToby Isaac 32538d2f55e7SToby Isaac ierr = PetscFEGetTabulation(fe,1,pointRef,&Bchild,NULL,NULL);CHKERRQ(ierr); 32548d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 32553b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3256c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 32578d2f55e7SToby Isaac PetscInt l; 32588d2f55e7SToby Isaac 32598d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,child,&childDepth);CHKERRQ(ierr); 32608d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 32618d2f55e7SToby Isaac for (l = 0, childCellShapeOff = 0; l < numClosure; l++) { 32628d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 32638d2f55e7SToby Isaac PetscInt pointDepth; 32648d2f55e7SToby Isaac 32658d2f55e7SToby Isaac childO = closure[2 * l + 1]; 32668d2f55e7SToby Isaac if (point == child) break; 32678d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,point,&pointDepth);CHKERRQ(ierr); 32688d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 32698d2f55e7SToby Isaac } 32708d2f55e7SToby Isaac if (l == numClosure) { 32718d2f55e7SToby Isaac pointMatOff += childDof; 32728d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 32738d2f55e7SToby Isaac } 32748d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 32753b1c2a6aSToby Isaac PetscInt childCellDof = childCellShapeOff + (childO ? (childDof - 1 - l) : l); 32763b1c2a6aSToby Isaac PetscReal childValAtPoint = Bchild[childCellDof * fComp]; 32778d2f55e7SToby Isaac 32783b1c2a6aSToby Isaac pointMat[i * numChildShapes + pointMatOff + l] += weights[j] * parentValAtPoint * childValAtPoint; 32798d2f55e7SToby Isaac } 32808d2f55e7SToby Isaac pointMatOff += childDof; 32818d2f55e7SToby Isaac } 32828d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 32838d2f55e7SToby Isaac ierr = PetscFERestoreTabulation(fe,1,pointRef,&Bchild,NULL,NULL);CHKERRQ(ierr); 32848d2f55e7SToby Isaac } 32858d2f55e7SToby Isaac ierr = PetscFERestoreTabulation(fe,numPoints,points,&Bparent,NULL,NULL);CHKERRQ(ierr); 32868d2f55e7SToby Isaac } 32878d2f55e7SToby Isaac } 3288c5356c36SToby Isaac else { /* just the volume-weighted averages of the children */ 32893b1c2a6aSToby Isaac PetscInt childShapeOff; 32903b1c2a6aSToby Isaac PetscReal parentVol; 32913b1c2a6aSToby Isaac 32923b1c2a6aSToby Isaac ierr = DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL);CHKERRQ(ierr); 32933b1c2a6aSToby Isaac for (i = 0, childShapeOff = 0; i < numChildren; i++) { 32943b1c2a6aSToby Isaac PetscInt child = children[i]; 32953b1c2a6aSToby Isaac PetscReal childVol; 32963b1c2a6aSToby Isaac 32973b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 32983b1c2a6aSToby Isaac ierr = DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL);CHKERRQ(ierr); 32993b1c2a6aSToby Isaac pointMat[childShapeOff] = childVol / parentVol; 33003b1c2a6aSToby Isaac childShapeOff++; 33013b1c2a6aSToby Isaac } 33028d2f55e7SToby Isaac } 33033b1c2a6aSToby Isaac /* Insert pointMat into mat */ 33043b1c2a6aSToby Isaac for (i = 0; i < fComp; i++) { 33053b1c2a6aSToby Isaac PetscInt j; 33063b1c2a6aSToby Isaac ierr = MatSetValues(mat,numSelfShapes,matRows,numChildShapes,matCols,pointMat,INSERT_VALUES);CHKERRQ(ierr); 33073b1c2a6aSToby Isaac 33083b1c2a6aSToby Isaac for (j = 0; j < numSelfShapes; j++) { 33093b1c2a6aSToby Isaac matRows[j]++; 33103b1c2a6aSToby Isaac } 33113b1c2a6aSToby Isaac for (j = 0; j < numChildShapes; j++) { 33123b1c2a6aSToby Isaac matCols[j]++; 33133b1c2a6aSToby Isaac } 33143b1c2a6aSToby Isaac } 33153b1c2a6aSToby Isaac ierr = DMRestoreWorkArray(refTree, numSelfShapes + numChildShapes, PETSC_INT,&matRows);CHKERRQ(ierr); 33168d2f55e7SToby Isaac ierr = DMRestoreWorkArray(refTree, numSelfShapes * numChildShapes, PETSC_SCALAR,&pointMat);CHKERRQ(ierr); 33178d2f55e7SToby Isaac } 33188d2f55e7SToby Isaac } 33193b1c2a6aSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJ);CHKERRQ(ierr); 33208d2f55e7SToby Isaac ierr = PetscFree2(pointScalar,pointRef);CHKERRQ(ierr); 33213b1c2a6aSToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 33223b1c2a6aSToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 33238d2f55e7SToby Isaac *inj = mat; 33248d2f55e7SToby Isaac PetscFunctionReturn(0); 33258d2f55e7SToby Isaac } 33268d2f55e7SToby Isaac 33278d2f55e7SToby Isaac #undef __FUNCT__ 3328f30e825dSToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildrenMatrices_Injection" 3329f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3330f30e825dSToby Isaac { 3331f30e825dSToby Isaac PetscDS ds; 3332f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3333f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3334f30e825dSToby Isaac PetscSection refConSec, refSection; 3335f30e825dSToby Isaac PetscErrorCode ierr; 3336f30e825dSToby Isaac 3337f30e825dSToby Isaac PetscFunctionBegin; 3338f30e825dSToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 3339f30e825dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 3340f30e825dSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 3341f30e825dSToby Isaac ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr); 3342f30e825dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3343f30e825dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr); 3344f30e825dSToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 3345f30e825dSToby Isaac ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr); 3346f30e825dSToby Isaac ierr = PetscMalloc1(maxDof*maxDof,&cols);CHKERRQ(ierr); 3347f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3348f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3349f30e825dSToby Isaac 3350f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 3351f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 3352c6154584SToby Isaac ierr = PetscSectionGetDof(refSection,parent,&parentDof);CHKERRQ(ierr); 3353f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3354f30e825dSToby Isaac 3355f30e825dSToby Isaac ierr = PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr); 3356f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3357f30e825dSToby Isaac PetscInt cDof, cOff, numCols, r, fComp; 3358f30e825dSToby Isaac PetscObject disc; 3359f30e825dSToby Isaac PetscClassId id; 3360f30e825dSToby Isaac PetscFE fe = NULL; 3361f30e825dSToby Isaac PetscFV fv = NULL; 3362f30e825dSToby Isaac 3363f30e825dSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 3364f30e825dSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 3365f30e825dSToby Isaac if (id == PETSCFE_CLASSID) { 3366f30e825dSToby Isaac fe = (PetscFE) disc; 3367f30e825dSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 3368f30e825dSToby Isaac } 3369f30e825dSToby Isaac else if (id == PETSCFV_CLASSID) { 3370f30e825dSToby Isaac fv = (PetscFV) disc; 3371f30e825dSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 3372f30e825dSToby Isaac } 3373f30e825dSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 3374f30e825dSToby Isaac 3375f30e825dSToby Isaac if (numFields > 1) { 3376f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 3377f30e825dSToby Isaac ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr); 3378f30e825dSToby Isaac } 3379f30e825dSToby Isaac else { 3380f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 3381f30e825dSToby Isaac ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr); 3382f30e825dSToby Isaac } 3383f30e825dSToby Isaac 3384f30e825dSToby Isaac for (r = 0; r < cDof; r++) { 3385f30e825dSToby Isaac rows[r] = cOff + r; 3386f30e825dSToby Isaac } 3387f30e825dSToby Isaac numCols = 0; 3388f30e825dSToby Isaac { 3389f30e825dSToby Isaac PetscInt aDof, aOff, j; 3390f30e825dSToby Isaac 3391f30e825dSToby Isaac if (numFields > 1) { 3392f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refSection,parent,f,&aDof);CHKERRQ(ierr); 3393f30e825dSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,parent,f,&aOff);CHKERRQ(ierr); 3394f30e825dSToby Isaac } 3395f30e825dSToby Isaac else { 3396f30e825dSToby Isaac ierr = PetscSectionGetDof(refSection,parent,&aDof);CHKERRQ(ierr); 3397f30e825dSToby Isaac ierr = PetscSectionGetOffset(refSection,parent,&aOff);CHKERRQ(ierr); 3398f30e825dSToby Isaac } 3399f30e825dSToby Isaac 3400f30e825dSToby Isaac for (j = 0; j < aDof; j++) { 3401f30e825dSToby Isaac cols[numCols++] = aOff + j; 3402f30e825dSToby Isaac } 3403f30e825dSToby Isaac } 3404f30e825dSToby Isaac ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 3405f30e825dSToby Isaac /* transpose of constraint matrix */ 3406f30e825dSToby Isaac ierr = MatGetValues(inj,numCols,cols,cDof,rows,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 3407f30e825dSToby Isaac } 3408f30e825dSToby Isaac } 3409f30e825dSToby Isaac *childrenMats = refPointFieldMats; 3410f30e825dSToby Isaac ierr = PetscFree(rows);CHKERRQ(ierr); 3411f30e825dSToby Isaac ierr = PetscFree(cols);CHKERRQ(ierr); 3412f30e825dSToby Isaac PetscFunctionReturn(0); 3413f30e825dSToby Isaac } 3414f30e825dSToby Isaac 3415f30e825dSToby Isaac #undef __FUNCT__ 3416f30e825dSToby Isaac #define __FUNCT__ "DMPlexReferenceTreeRestoreChildrenMatrices_Injection" 3417f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3418f30e825dSToby Isaac { 3419f30e825dSToby Isaac PetscDS ds; 3420f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3421f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3422c6154584SToby Isaac PetscSection refConSec, refSection; 3423f30e825dSToby Isaac PetscErrorCode ierr; 3424f30e825dSToby Isaac 3425f30e825dSToby Isaac PetscFunctionBegin; 3426f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3427f30e825dSToby Isaac *childrenMats = NULL; 3428f30e825dSToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 3429c6154584SToby Isaac ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr); 3430f30e825dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 3431f30e825dSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 3432f30e825dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3433f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3434f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3435f30e825dSToby Isaac 3436f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 3437f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 3438c6154584SToby Isaac ierr = PetscSectionGetDof(refSection,parent,&parentDof);CHKERRQ(ierr); 3439f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3440f30e825dSToby Isaac 3441f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3442f30e825dSToby Isaac PetscInt cDof; 3443f30e825dSToby Isaac 3444f30e825dSToby Isaac if (numFields > 1) { 3445f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 3446f30e825dSToby Isaac } 3447f30e825dSToby Isaac else { 3448f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 3449f30e825dSToby Isaac } 3450f30e825dSToby Isaac 3451f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr); 3452f30e825dSToby Isaac } 3453f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr); 3454f30e825dSToby Isaac } 3455f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr); 3456f30e825dSToby Isaac PetscFunctionReturn(0); 3457f30e825dSToby Isaac } 3458f30e825dSToby Isaac 3459f30e825dSToby Isaac #undef __FUNCT__ 3460ebf164c7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetInjector" 3461ebf164c7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree,Mat *injRef) 3462154bca37SToby Isaac { 3463ebf164c7SToby Isaac Mat cMatRef; 34646148253fSToby Isaac PetscObject injRefObj; 34658d2f55e7SToby Isaac PetscErrorCode ierr; 34668d2f55e7SToby Isaac 3467154bca37SToby Isaac PetscFunctionBegin; 3468ebf164c7SToby Isaac ierr = DMGetDefaultConstraints(refTree,NULL,&cMatRef);CHKERRQ(ierr); 34696148253fSToby Isaac ierr = PetscObjectQuery((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",&injRefObj);CHKERRQ(ierr); 3470ebf164c7SToby Isaac *injRef = (Mat) injRefObj; 3471ebf164c7SToby Isaac if (!*injRef) { 3472ebf164c7SToby Isaac ierr = DMPlexComputeInjectorReferenceTree(refTree,injRef);CHKERRQ(ierr); 3473ebf164c7SToby Isaac ierr = PetscObjectCompose((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",(PetscObject)*injRef);CHKERRQ(ierr); 3474ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 3475ebf164c7SToby Isaac ierr = PetscObjectDereference((PetscObject)*injRef);CHKERRQ(ierr); 3476ebf164c7SToby Isaac } 3477ebf164c7SToby Isaac PetscFunctionReturn(0); 34786148253fSToby Isaac } 3479f30e825dSToby Isaac 3480ebf164c7SToby Isaac #undef __FUNCT__ 3481c921d74cSToby Isaac #define __FUNCT__ "DMPlexTransferInjectorTree" 3482c921d74cSToby Isaac static PetscErrorCode DMPlexTransferInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, const PetscInt *childIds, Vec fineVec, PetscInt numFields, PetscInt *offsets, PetscSection *rootMultiSec, PetscSection *multiLeafSec, PetscInt **gatheredIndices, PetscScalar **gatheredValues) 3483ebf164c7SToby Isaac { 3484c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3485ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3486ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3487c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3488c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3489c921d74cSToby Isaac const PetscInt *rootDegrees; 3490c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3491ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3492ebf164c7SToby Isaac PetscErrorCode ierr; 3493ebf164c7SToby Isaac 3494ebf164c7SToby Isaac PetscFunctionBegin; 3495ebf164c7SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 34968d2f55e7SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 3497f30e825dSToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 34988d2f55e7SToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 3499f30e825dSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr); 3500f30e825dSToby Isaac ierr = PetscSectionSetChart(leafIndicesSec,pStartF, pEndF);CHKERRQ(ierr); 3501c921d74cSToby Isaac ierr = PetscSectionGetMaxDof(localFine,&maxDof);CHKERRQ(ierr); 35028d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 35037e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 35047e96bdafSToby Isaac const PetscInt *leaves; 35058d2f55e7SToby Isaac 35067e96bdafSToby Isaac ierr = PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 35077e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 35087e96bdafSToby Isaac p = leaves ? leaves[l] : l; 35098d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 35108d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 35118d2f55e7SToby Isaac if ((dof - cdof) > 0) { 35128d2f55e7SToby Isaac numPointsWithDofs++; 3513f30e825dSToby Isaac 3514f30e825dSToby Isaac ierr = PetscSectionGetDof(localFine,p,&dof);CHKERRQ(ierr); 3515f30e825dSToby Isaac ierr = PetscSectionSetDof(leafIndicesSec,p,dof + 1);CHKERRQ(ierr); 35168d2f55e7SToby Isaac } 35178d2f55e7SToby Isaac } 35188d2f55e7SToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 3519f30e825dSToby Isaac ierr = PetscSectionSetUp(leafIndicesSec);CHKERRQ(ierr); 3520f30e825dSToby Isaac ierr = PetscSectionGetStorageSize(leafIndicesSec,&numIndices);CHKERRQ(ierr); 3521c921d74cSToby Isaac ierr = PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1),&leafInds);CHKERRQ(ierr); 3522c921d74cSToby Isaac if (gatheredValues) {ierr = PetscMalloc1(numIndices,&leafVals);CHKERRQ(ierr);} 35237e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 35247e96bdafSToby Isaac p = leaves ? leaves[l] : l; 35258d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 35268d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 35278d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3528f30e825dSToby Isaac PetscInt off, gOff; 3529f30e825dSToby Isaac PetscInt *pInd; 3530c921d74cSToby Isaac PetscScalar *pVal = NULL; 3531f30e825dSToby Isaac 35327e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3533f30e825dSToby Isaac 3534f30e825dSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&off);CHKERRQ(ierr); 3535f30e825dSToby Isaac 3536c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3537c921d74cSToby Isaac if (gatheredValues) { 3538c921d74cSToby Isaac PetscInt i; 3539c921d74cSToby Isaac 3540c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3541c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3542c921d74cSToby Isaac } 3543f30e825dSToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 3544f30e825dSToby Isaac 3545f30e825dSToby Isaac offsets[0] = 0; 3546f30e825dSToby Isaac if (numFields) { 3547f30e825dSToby Isaac PetscInt f; 3548f30e825dSToby Isaac 3549f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3550f30e825dSToby Isaac PetscInt fDof; 3551f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&fDof);CHKERRQ(ierr); 3552f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3553f30e825dSToby Isaac } 3554415ce65aSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(localFine,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 3555f30e825dSToby Isaac } 3556f30e825dSToby Isaac else { 3557415ce65aSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(localFine,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 3558f30e825dSToby Isaac } 3559c921d74cSToby Isaac if (gatheredValues) {ierr = VecGetValues(fineVec,dof,pInd,pVal);CHKERRQ(ierr);} 35608d2f55e7SToby Isaac } 35618d2f55e7SToby Isaac } 35628d2f55e7SToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 3563f30e825dSToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 35648d2f55e7SToby Isaac } 3565f30e825dSToby Isaac 3566f30e825dSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 3567f30e825dSToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 3568f30e825dSToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 3569f30e825dSToby Isaac 35706148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 35716148253fSToby Isaac MPI_Datatype threeInt; 35726148253fSToby Isaac PetscMPIInt rank; 35736148253fSToby Isaac PetscInt (*parentNodeAndIdCoarse)[3]; 35746148253fSToby Isaac PetscInt (*parentNodeAndIdFine)[3]; 35756148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 35766148253fSToby Isaac PetscSF pointSF, sfToParents; 35776148253fSToby Isaac const PetscInt *ilocal; 35786148253fSToby Isaac const PetscSFNode *iremote; 35796148253fSToby Isaac PetscSFNode *iremoteToParents; 35806148253fSToby Isaac PetscInt *ilocalToParents; 35816148253fSToby Isaac 35826148253fSToby Isaac ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)coarse),&rank);CHKERRQ(ierr); 35836148253fSToby Isaac ierr = MPI_Type_contiguous(3,MPIU_INT,&threeInt);CHKERRQ(ierr); 35846148253fSToby Isaac ierr = MPI_Type_commit(&threeInt);CHKERRQ(ierr); 35856148253fSToby Isaac ierr = PetscMalloc2(pEndC-pStartC,&parentNodeAndIdCoarse,pEndF-pStartF,&parentNodeAndIdFine);CHKERRQ(ierr); 35866148253fSToby Isaac ierr = DMGetPointSF(coarse,&pointSF);CHKERRQ(ierr); 35876148253fSToby Isaac ierr = PetscSFGetGraph(pointSF,NULL,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 35886148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 35896148253fSToby Isaac PetscInt parent, childId; 35906148253fSToby Isaac ierr = DMPlexGetTreeParent(coarse,p,&parent,&childId);CHKERRQ(ierr); 35916148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 35926148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 35936148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 35946148253fSToby Isaac if (nleaves > 0) { 35956148253fSToby Isaac PetscInt leaf = -1; 35966148253fSToby Isaac 35976148253fSToby Isaac if (ilocal) { 35986148253fSToby Isaac ierr = PetscFindInt(parent,nleaves,ilocal,&leaf);CHKERRQ(ierr); 35996148253fSToby Isaac } 36006148253fSToby Isaac else { 36016148253fSToby Isaac leaf = p - pStartC; 36026148253fSToby Isaac } 36036148253fSToby Isaac if (leaf >= 0) { 36046148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 36056148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 36066148253fSToby Isaac } 36076148253fSToby Isaac } 36086148253fSToby Isaac } 36096148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 36106148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 36116148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 36126148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 36136148253fSToby Isaac } 36146148253fSToby Isaac ierr = PetscSFBcastBegin(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine);CHKERRQ(ierr); 36156148253fSToby Isaac ierr = PetscSFBcastEnd(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine);CHKERRQ(ierr); 36166148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3617f30e825dSToby Isaac PetscInt dof; 3618f30e825dSToby Isaac 3619f30e825dSToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&dof);CHKERRQ(ierr); 3620f30e825dSToby Isaac if (dof) { 3621f30e825dSToby Isaac PetscInt off; 3622f30e825dSToby Isaac 3623f30e825dSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&off);CHKERRQ(ierr); 3624c921d74cSToby Isaac if (gatheredIndices) { 3625c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3626c921d74cSToby Isaac } else if (gatheredValues) { 3627c921d74cSToby Isaac leafVals[off] = (PetscScalar) PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3628c921d74cSToby Isaac } 3629f30e825dSToby Isaac } 36306148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36316148253fSToby Isaac nleavesToParents++; 36326148253fSToby Isaac } 36336148253fSToby Isaac } 36346148253fSToby Isaac ierr = PetscMalloc1(nleavesToParents,&ilocalToParents);CHKERRQ(ierr); 36356148253fSToby Isaac ierr = PetscMalloc1(nleavesToParents,&iremoteToParents);CHKERRQ(ierr); 36366148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 36376148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36386148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 36396148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p-pStartF][0]; 36406148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p-pStartF][1]; 36416148253fSToby Isaac nleavesToParents++; 36426148253fSToby Isaac } 36436148253fSToby Isaac } 36446148253fSToby Isaac ierr = PetscSFCreate(PetscObjectComm((PetscObject)coarse),&sfToParents);CHKERRQ(ierr); 36456148253fSToby Isaac ierr = PetscSFSetGraph(sfToParents,pEndC-pStartC,nleavesToParents,ilocalToParents,PETSC_OWN_POINTER,iremoteToParents,PETSC_OWN_POINTER);CHKERRQ(ierr); 36466148253fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 36476148253fSToby Isaac 36486148253fSToby Isaac coarseToFineEmbedded = sfToParents; 36496148253fSToby Isaac 36506148253fSToby Isaac ierr = PetscFree2(parentNodeAndIdCoarse,parentNodeAndIdFine);CHKERRQ(ierr); 36516148253fSToby Isaac ierr = MPI_Type_free(&threeInt);CHKERRQ(ierr); 36526148253fSToby Isaac } 3653f30e825dSToby Isaac 36546148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 36556148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 36566148253fSToby Isaac PetscSF sfDofsOnly; 36576148253fSToby Isaac 36586148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 36596148253fSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 36606148253fSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 36616148253fSToby Isaac if ((dof - cdof) > 0) { 36626148253fSToby Isaac numPointsWithDofs++; 36636148253fSToby Isaac } 36646148253fSToby Isaac } 36656148253fSToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 36666148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 36676148253fSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 36686148253fSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 36696148253fSToby Isaac if ((dof - cdof) > 0) { 3670e03d9830SToby Isaac pointsWithDofs[offset++] = p - pStartC; 36716148253fSToby Isaac } 36726148253fSToby Isaac } 36736148253fSToby Isaac ierr = PetscSFCreateEmbeddedSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly);CHKERRQ(ierr); 36746148253fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 3675f30e825dSToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 36766148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 36776148253fSToby Isaac } 3678f30e825dSToby Isaac 36796148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 3680f30e825dSToby Isaac ierr = PetscSFComputeDegreeBegin(coarseToFineEmbedded,&rootDegrees);CHKERRQ(ierr); 3681f30e825dSToby Isaac ierr = PetscSFComputeDegreeEnd(coarseToFineEmbedded,&rootDegrees);CHKERRQ(ierr); 3682f30e825dSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&multiRootSec);CHKERRQ(ierr); 3683f30e825dSToby Isaac ierr = PetscSectionSetChart(multiRootSec,pStartC,pEndC);CHKERRQ(ierr); 36848d2f55e7SToby Isaac for (p = pStartC; p < pEndC; p++) { 3685f30e825dSToby Isaac ierr = PetscSectionSetDof(multiRootSec,p,rootDegrees[p-pStartC]);CHKERRQ(ierr); 36868d2f55e7SToby Isaac } 3687f30e825dSToby Isaac ierr = PetscSectionSetUp(multiRootSec);CHKERRQ(ierr); 3688f30e825dSToby Isaac ierr = PetscSectionGetStorageSize(multiRootSec,&numMulti);CHKERRQ(ierr); 36898d2f55e7SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec);CHKERRQ(ierr); 3690f30e825dSToby Isaac { /* distribute the leaf section */ 3691f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3692f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 36938d2f55e7SToby Isaac 3694f30e825dSToby Isaac ierr = PetscSFGetMultiSF(coarseToFineEmbedded,&multi);CHKERRQ(ierr); 3695f30e825dSToby Isaac ierr = PetscSFCreateInverseSF(multi,&multiInv);CHKERRQ(ierr); 3696f30e825dSToby Isaac ierr = PetscSFDistributeSection(multiInv,leafIndicesSec,&remoteOffsets,rootIndicesSec);CHKERRQ(ierr); 3697f30e825dSToby Isaac ierr = PetscSFCreateSectionSF(multiInv,leafIndicesSec,remoteOffsets,rootIndicesSec,&indicesSF);CHKERRQ(ierr); 3698f30e825dSToby Isaac ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 3699f30e825dSToby Isaac ierr = PetscSFDestroy(&multiInv);CHKERRQ(ierr); 37008d2f55e7SToby Isaac ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr); 3701c921d74cSToby Isaac if (gatheredIndices) { 3702c921d74cSToby Isaac ierr = PetscMalloc1(numRootIndices,&rootInds);CHKERRQ(ierr); 3703c921d74cSToby Isaac ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,leafInds,rootInds);CHKERRQ(ierr); 3704c921d74cSToby Isaac ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,leafInds,rootInds);CHKERRQ(ierr); 3705c921d74cSToby Isaac } 3706c921d74cSToby Isaac if (gatheredValues) { 3707c921d74cSToby Isaac ierr = PetscMalloc1(numRootIndices,&rootVals);CHKERRQ(ierr); 3708c921d74cSToby Isaac ierr = PetscSFBcastBegin(indicesSF,MPIU_SCALAR,leafVals,rootVals);CHKERRQ(ierr); 3709c921d74cSToby Isaac ierr = PetscSFBcastEnd(indicesSF,MPIU_SCALAR,leafVals,rootVals);CHKERRQ(ierr); 3710c921d74cSToby Isaac } 37118d2f55e7SToby Isaac ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr); 37128d2f55e7SToby Isaac } 3713ec92bd66SToby Isaac ierr = PetscSectionDestroy(&leafIndicesSec);CHKERRQ(ierr); 3714c921d74cSToby Isaac ierr = PetscFree(leafInds);CHKERRQ(ierr); 3715c921d74cSToby Isaac ierr = PetscFree(leafVals);CHKERRQ(ierr); 3716f30e825dSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 3717c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3718c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3719c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3720c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 3721ebf164c7SToby Isaac PetscFunctionReturn(0); 3722ebf164c7SToby Isaac } 3723ebf164c7SToby Isaac 3724ebf164c7SToby Isaac #undef __FUNCT__ 3725ebf164c7SToby Isaac #define __FUNCT__ "DMPlexComputeInjectorTree" 3726ebf164c7SToby Isaac PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3727ebf164c7SToby Isaac { 3728ebf164c7SToby Isaac DM refTree; 3729c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3730ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3731ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3732ebf164c7SToby Isaac PetscSection cSecRef; 3733c921d74cSToby Isaac PetscInt *rootIndices, *parentIndices, pRefStart, pRefEnd; 3734ebf164c7SToby Isaac Mat injRef; 3735c921d74cSToby Isaac PetscInt numFields, maxDof; 3736ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3737ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3738ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3739ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3740ebf164c7SToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3741ebf164c7SToby Isaac PetscErrorCode ierr; 3742ebf164c7SToby Isaac 3743ebf164c7SToby Isaac PetscFunctionBegin; 3744ebf164c7SToby Isaac 3745ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 3746ebf164c7SToby Isaac ierr = DMPlexGetReferenceTree(coarse,&refTree);CHKERRQ(ierr); 3747ebf164c7SToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSecRef,NULL);CHKERRQ(ierr); 3748ebf164c7SToby Isaac ierr = PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3749ebf164c7SToby Isaac ierr = DMPlexReferenceTreeGetInjector(refTree,&injRef);CHKERRQ(ierr); 3750ebf164c7SToby Isaac 3751ebf164c7SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 3752ebf164c7SToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 3753ebf164c7SToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 3754ebf164c7SToby Isaac ierr = PetscSectionGetNumFields(localFine,&numFields);CHKERRQ(ierr); 3755ebf164c7SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 3756ebf164c7SToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 3757ebf164c7SToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 3758ebf164c7SToby Isaac ierr = PetscSectionGetMaxDof(localCoarse,&maxDof);CHKERRQ(ierr); 3759ebf164c7SToby Isaac { 3760ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 3761ebf164c7SToby Isaac ierr = PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets);CHKERRQ(ierr); 3762ebf164c7SToby Isaac } 3763ebf164c7SToby Isaac 3764c921d74cSToby Isaac ierr = DMPlexTransferInjectorTree(coarse,fine,coarseToFine,childIds,NULL,numFields,offsets,&multiRootSec,&rootIndicesSec,&rootIndices,NULL);CHKERRQ(ierr); 37658d2f55e7SToby Isaac 3766f30e825dSToby Isaac ierr = PetscMalloc1(maxDof,&parentIndices);CHKERRQ(ierr); 3767f30e825dSToby Isaac 3768f30e825dSToby Isaac /* count indices */ 37698d2f55e7SToby Isaac ierr = MatGetLayouts(mat,&rowMap,&colMap);CHKERRQ(ierr); 3770c6154584SToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 3771c6154584SToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 37728d2f55e7SToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 37738d2f55e7SToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 3774f30e825dSToby Isaac ierr = PetscCalloc2(rowEnd-rowStart,&nnzD,rowEnd-rowStart,&nnzO);CHKERRQ(ierr); 3775f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3776f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 37778d2f55e7SToby Isaac 3778f30e825dSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 3779f30e825dSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 3780f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 3781f30e825dSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 37828d2f55e7SToby Isaac 37838d2f55e7SToby Isaac rowOffsets[0] = 0; 3784f30e825dSToby Isaac offsetsCopy[0] = 0; 37858d2f55e7SToby Isaac if (numFields) { 37868d2f55e7SToby Isaac PetscInt f; 37878d2f55e7SToby Isaac 3788f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3789f30e825dSToby Isaac PetscInt fDof; 3790f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 3791f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 37928d2f55e7SToby Isaac } 3793415ce65aSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,0,parentIndices);CHKERRQ(ierr); 37948d2f55e7SToby Isaac } 37958d2f55e7SToby Isaac else { 3796415ce65aSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,0,parentIndices);CHKERRQ(ierr); 3797f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 37988d2f55e7SToby Isaac } 3799f30e825dSToby Isaac 3800f30e825dSToby Isaac ierr = PetscSectionGetDof(multiRootSec,p,&numLeaves);CHKERRQ(ierr); 3801f30e825dSToby Isaac ierr = PetscSectionGetOffset(multiRootSec,p,&leafStart);CHKERRQ(ierr); 3802f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3803f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3804f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3805f30e825dSToby Isaac const PetscInt *childIndices; 3806f30e825dSToby Isaac 3807f30e825dSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,l,&numIndices);CHKERRQ(ierr); 3808f30e825dSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,l,&offset);CHKERRQ(ierr); 3809f30e825dSToby Isaac childId = rootIndices[offset++]; 3810f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3811f30e825dSToby Isaac numIndices--; 3812f30e825dSToby Isaac 3813f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3814f30e825dSToby Isaac PetscInt i; 3815f30e825dSToby Isaac 3816f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3817f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3818f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3819f30e825dSToby Isaac if (rowIndex < 0) continue; 3820f30e825dSToby Isaac if (colIndex < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unconstrained fine and constrained coarse"); 3821a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3822f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 3823f30e825dSToby Isaac } 3824f30e825dSToby Isaac else { 3825f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3826f30e825dSToby Isaac } 3827f30e825dSToby Isaac } 3828f30e825dSToby Isaac } 3829f30e825dSToby Isaac else { 3830f30e825dSToby Isaac PetscInt parentId, f, lim; 3831f30e825dSToby Isaac 3832f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,childId,&parentId,NULL);CHKERRQ(ierr); 3833f30e825dSToby Isaac 3834f30e825dSToby Isaac lim = PetscMax(1,numFields); 3835f30e825dSToby Isaac offsets[0] = 0; 38368d2f55e7SToby Isaac if (numFields) { 38378d2f55e7SToby Isaac PetscInt f; 3838f30e825dSToby Isaac 38398d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3840f30e825dSToby Isaac PetscInt fDof; 3841f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(cSecRef,childId,f,&fDof);CHKERRQ(ierr); 3842f30e825dSToby Isaac 3843f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 38448d2f55e7SToby Isaac } 38458d2f55e7SToby Isaac } 38468d2f55e7SToby Isaac else { 3847f30e825dSToby Isaac PetscInt cDof; 3848f30e825dSToby Isaac 3849f30e825dSToby Isaac ierr = PetscSectionGetDof(cSecRef,childId,&cDof);CHKERRQ(ierr); 3850f30e825dSToby Isaac offsets[1] = cDof; 3851f30e825dSToby Isaac } 3852f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3853f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3854f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3855f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3856f30e825dSToby Isaac 3857f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3858f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3859f30e825dSToby Isaac 3860f30e825dSToby Isaac if (colIndex < 0) continue; 3861f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3862f30e825dSToby Isaac numD++; 3863f30e825dSToby Isaac } 3864f30e825dSToby Isaac else { 3865f30e825dSToby Isaac numO++; 3866f30e825dSToby Isaac } 3867f30e825dSToby Isaac } 3868f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3869f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3870f30e825dSToby Isaac 3871f30e825dSToby Isaac if (rowIndex < 0) continue; 3872f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3873f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 38748d2f55e7SToby Isaac } 38758d2f55e7SToby Isaac } 38768d2f55e7SToby Isaac } 3877f30e825dSToby Isaac } 3878f30e825dSToby Isaac } 3879f30e825dSToby Isaac /* preallocate */ 3880f30e825dSToby Isaac ierr = MatXAIJSetPreallocation(mat,1,nnzD,nnzO,NULL,NULL);CHKERRQ(ierr); 3881f30e825dSToby Isaac ierr = PetscFree2(nnzD,nnzO);CHKERRQ(ierr); 3882f30e825dSToby Isaac /* insert values */ 3883f30e825dSToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 3884f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3885f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3886f30e825dSToby Isaac 3887f30e825dSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 3888f30e825dSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 3889f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 3890f30e825dSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 3891f30e825dSToby Isaac 3892f30e825dSToby Isaac rowOffsets[0] = 0; 3893f30e825dSToby Isaac offsetsCopy[0] = 0; 38948d2f55e7SToby Isaac if (numFields) { 38958d2f55e7SToby Isaac PetscInt f; 3896f30e825dSToby Isaac 38978d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3898f30e825dSToby Isaac PetscInt fDof; 3899f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 3900f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3901f30e825dSToby Isaac } 3902415ce65aSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,0,parentIndices);CHKERRQ(ierr); 3903f30e825dSToby Isaac } 3904f30e825dSToby Isaac else { 3905415ce65aSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,0,parentIndices);CHKERRQ(ierr); 3906f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3907f30e825dSToby Isaac } 3908f30e825dSToby Isaac 3909f30e825dSToby Isaac ierr = PetscSectionGetDof(multiRootSec,p,&numLeaves);CHKERRQ(ierr); 3910f30e825dSToby Isaac ierr = PetscSectionGetOffset(multiRootSec,p,&leafStart);CHKERRQ(ierr); 3911f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3912f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3913f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3914f30e825dSToby Isaac const PetscInt *childIndices; 3915f30e825dSToby Isaac 3916f30e825dSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,l,&numIndices);CHKERRQ(ierr); 3917f30e825dSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,l,&offset);CHKERRQ(ierr); 3918f30e825dSToby Isaac childId = rootIndices[offset++]; 3919f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3920f30e825dSToby Isaac numIndices--; 3921f30e825dSToby Isaac 3922f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3923f30e825dSToby Isaac PetscInt i; 3924f30e825dSToby Isaac 3925f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3926f30e825dSToby Isaac ierr = MatSetValue(mat,parentIndices[i],childIndices[i],1.,INSERT_VALUES);CHKERRQ(ierr); 39278d2f55e7SToby Isaac } 39288d2f55e7SToby Isaac } 39298d2f55e7SToby Isaac else { 3930f30e825dSToby Isaac PetscInt parentId, f, lim; 39318d2f55e7SToby Isaac 3932f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,childId,&parentId,NULL);CHKERRQ(ierr); 3933f30e825dSToby Isaac 3934f30e825dSToby Isaac lim = PetscMax(1,numFields); 3935f30e825dSToby Isaac offsets[0] = 0; 39368d2f55e7SToby Isaac if (numFields) { 3937f30e825dSToby Isaac PetscInt f; 39388d2f55e7SToby Isaac 3939f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3940f30e825dSToby Isaac PetscInt fDof; 3941f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(cSecRef,childId,f,&fDof);CHKERRQ(ierr); 3942f30e825dSToby Isaac 3943f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 39448d2f55e7SToby Isaac } 39458d2f55e7SToby Isaac } 39468d2f55e7SToby Isaac else { 3947f30e825dSToby Isaac PetscInt cDof; 3948f30e825dSToby Isaac 3949f30e825dSToby Isaac ierr = PetscSectionGetDof(cSecRef,childId,&cDof);CHKERRQ(ierr); 3950f30e825dSToby Isaac offsets[1] = cDof; 39518d2f55e7SToby Isaac } 3952f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3953f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3954f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3955f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3956f30e825dSToby Isaac 3957f30e825dSToby Isaac ierr = MatSetValues(mat,rowOffsets[f+1]-rowOffsets[f],rowIndices,offsets[f+1]-offsets[f],colIndices,childMat,INSERT_VALUES);CHKERRQ(ierr); 39588d2f55e7SToby Isaac } 39598d2f55e7SToby Isaac } 39608d2f55e7SToby Isaac } 39618d2f55e7SToby Isaac } 3962ec92bd66SToby Isaac ierr = PetscSectionDestroy(&multiRootSec);CHKERRQ(ierr); 3963ec92bd66SToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 3964ec92bd66SToby Isaac ierr = PetscFree(parentIndices);CHKERRQ(ierr); 3965f30e825dSToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 3966f30e825dSToby Isaac ierr = PetscFree(rootIndices);CHKERRQ(ierr); 3967f30e825dSToby Isaac ierr = PetscFree3(offsets,offsetsCopy,rowOffsets);CHKERRQ(ierr); 3968f30e825dSToby Isaac 39698d2f55e7SToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 39708d2f55e7SToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3971154bca37SToby Isaac PetscFunctionReturn(0); 3972154bca37SToby Isaac } 397338fc2455SToby Isaac 397438fc2455SToby Isaac #undef __FUNCT__ 3975ebf164c7SToby Isaac #define __FUNCT__ "DMPlexTransferVecTree_Interpolate" 39760eb7e1eaSToby Isaac static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 3977ebf164c7SToby Isaac { 39784833aeb0SToby Isaac PetscDS ds; 397962095d54SToby Isaac PetscSF coarseToFineEmbedded; 398062095d54SToby Isaac PetscSection globalCoarse, globalFine; 398162095d54SToby Isaac PetscSection localCoarse, localFine; 398262095d54SToby Isaac PetscSection aSec, cSec; 398362095d54SToby Isaac PetscSection rootValuesSec; 398462095d54SToby Isaac PetscSection leafValuesSec; 398562095d54SToby Isaac PetscScalar *rootValues, *leafValues; 398662095d54SToby Isaac IS aIS; 398762095d54SToby Isaac const PetscInt *anchors; 398862095d54SToby Isaac Mat cMat; 398962095d54SToby Isaac PetscInt numFields; 399089698031SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd, cellEndInterior; 399162095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 399262095d54SToby Isaac PetscInt *maxChildIds; 399362095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 39940eb7e1eaSToby Isaac PetscFV fv = NULL; 39950eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 39960eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 39970eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 39980eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 399962095d54SToby Isaac PetscErrorCode ierr; 400062095d54SToby Isaac 4001ebf164c7SToby Isaac PetscFunctionBegin; 4002708c7f19SToby Isaac ierr = VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 400362095d54SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 40040eb7e1eaSToby Isaac ierr = DMPlexGetHeightStratum(coarse,0,&cellStart,&cellEnd);CHKERRQ(ierr); 400589698031SToby Isaac ierr = DMPlexGetHybridBounds(coarse,&cellEndInterior,NULL,NULL,NULL);CHKERRQ(ierr); 400689698031SToby Isaac cellEnd = (cellEndInterior < 0) ? cellEnd : cellEndInterior; 400762095d54SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 400862095d54SToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 40090eb7e1eaSToby Isaac ierr = DMGetCoordinateDim(coarse,&dim);CHKERRQ(ierr); 401062095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 4011e4a60869SToby Isaac PetscInt nleaves, l; 4012e4a60869SToby Isaac const PetscInt *leaves; 401362095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 401462095d54SToby Isaac 4015e4a60869SToby Isaac ierr = PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 4016e4a60869SToby Isaac 4017e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 4018e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 4019e4a60869SToby Isaac 402062095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 402162095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 402262095d54SToby Isaac if ((dof - cdof) > 0) { 402362095d54SToby Isaac numPointsWithDofs++; 402462095d54SToby Isaac } 402562095d54SToby Isaac } 402662095d54SToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 40274833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 4028e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 4029e4a60869SToby Isaac 403062095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 403162095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 403262095d54SToby Isaac if ((dof - cdof) > 0) { 4033e4a60869SToby Isaac pointsWithDofs[offset++] = l; 403462095d54SToby Isaac } 403562095d54SToby Isaac } 403662095d54SToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 403762095d54SToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 403862095d54SToby Isaac } 403962095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 404062095d54SToby Isaac ierr = PetscMalloc1(pEndC-pStartC,&maxChildIds);CHKERRQ(ierr); 404162095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 404262095d54SToby Isaac maxChildIds[p - pStartC] = -2; 404362095d54SToby Isaac } 404462095d54SToby Isaac ierr = PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 404562095d54SToby Isaac ierr = PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 404662095d54SToby Isaac 404762095d54SToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 404862095d54SToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 404962095d54SToby Isaac 405062095d54SToby Isaac ierr = DMPlexGetAnchors(coarse,&aSec,&aIS);CHKERRQ(ierr); 405162095d54SToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 405262095d54SToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 405362095d54SToby Isaac 405462095d54SToby Isaac ierr = DMGetDefaultConstraints(coarse,&cSec,&cMat);CHKERRQ(ierr); 405562095d54SToby Isaac ierr = PetscSectionGetChart(cSec,&cStart,&cEnd);CHKERRQ(ierr); 405662095d54SToby Isaac 405762095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 405862095d54SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootValuesSec);CHKERRQ(ierr); 405962095d54SToby Isaac ierr = PetscSectionSetChart(rootValuesSec,pStartC,pEndC);CHKERRQ(ierr); 4060708c7f19SToby Isaac ierr = PetscSectionGetNumFields(localCoarse,&numFields);CHKERRQ(ierr); 406162095d54SToby Isaac { 406262095d54SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 406362095d54SToby Isaac ierr = PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO);CHKERRQ(ierr); 406462095d54SToby Isaac } 40650eb7e1eaSToby Isaac if (grad) { 40660eb7e1eaSToby Isaac PetscInt i; 40670eb7e1eaSToby Isaac 40680eb7e1eaSToby Isaac ierr = VecGetDM(cellGeom,&cellDM);CHKERRQ(ierr); 40690eb7e1eaSToby Isaac ierr = VecGetArrayRead(cellGeom,&cellGeomArray);CHKERRQ(ierr); 40700eb7e1eaSToby Isaac ierr = VecGetDM(grad,&gradDM);CHKERRQ(ierr); 40710eb7e1eaSToby Isaac ierr = VecGetArrayRead(grad,&gradArray);CHKERRQ(ierr); 40720eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1,numFields); i++) { 40730eb7e1eaSToby Isaac PetscObject obj; 40740eb7e1eaSToby Isaac PetscClassId id; 40750eb7e1eaSToby Isaac 40760eb7e1eaSToby Isaac ierr = DMGetField(coarse, i, &obj);CHKERRQ(ierr); 40770eb7e1eaSToby Isaac ierr = PetscObjectGetClassId(obj,&id);CHKERRQ(ierr); 40780eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 40790eb7e1eaSToby Isaac fv = (PetscFV) obj; 40800eb7e1eaSToby Isaac ierr = PetscFVGetNumComponents(fv,&numFVcomps);CHKERRQ(ierr); 40810eb7e1eaSToby Isaac fvField = i; 40820eb7e1eaSToby Isaac break; 40830eb7e1eaSToby Isaac } 40840eb7e1eaSToby Isaac } 40850eb7e1eaSToby Isaac } 408662095d54SToby Isaac 408762095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 408862095d54SToby Isaac PetscInt dof; 408962095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 409062095d54SToby Isaac PetscInt numValues = 0; 409162095d54SToby Isaac 409262095d54SToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 409362095d54SToby Isaac if (dof < 0) { 409462095d54SToby Isaac dof = -(dof + 1); 409562095d54SToby Isaac } 409662095d54SToby Isaac offsets[0] = 0; 409762095d54SToby Isaac newOffsets[0] = 0; 409862095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 409962095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 410062095d54SToby Isaac 41014833aeb0SToby Isaac ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 410262095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 410362095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 410462095d54SToby Isaac 410562095d54SToby Isaac ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr); 410662095d54SToby Isaac numValues += clDof; 410762095d54SToby Isaac } 41084833aeb0SToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 410962095d54SToby Isaac } 411062095d54SToby Isaac else if (maxChildId == -1) { 411162095d54SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&numValues);CHKERRQ(ierr); 411262095d54SToby Isaac } 411362095d54SToby Isaac /* we will pack the column indices with the field offsets */ 411478b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 41150eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 41160eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 41170eb7e1eaSToby Isaac } 411862095d54SToby Isaac ierr = PetscSectionSetDof(rootValuesSec,p,numValues);CHKERRQ(ierr); 411962095d54SToby Isaac } 412062095d54SToby Isaac ierr = PetscSectionSetUp(rootValuesSec);CHKERRQ(ierr); 412162095d54SToby Isaac { 412262095d54SToby Isaac PetscInt numRootValues; 412362095d54SToby Isaac const PetscScalar *coarseArray; 412462095d54SToby Isaac 412562095d54SToby Isaac ierr = PetscSectionGetStorageSize(rootValuesSec,&numRootValues);CHKERRQ(ierr); 412662095d54SToby Isaac ierr = PetscMalloc1(numRootValues,&rootValues);CHKERRQ(ierr); 412762095d54SToby Isaac ierr = VecGetArrayRead(vecCoarseLocal,&coarseArray);CHKERRQ(ierr); 412862095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 412962095d54SToby Isaac PetscInt numValues; 413062095d54SToby Isaac PetscInt pValOff; 413162095d54SToby Isaac PetscScalar *pVal; 413262095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 413362095d54SToby Isaac 413462095d54SToby Isaac ierr = PetscSectionGetDof(rootValuesSec,p,&numValues);CHKERRQ(ierr); 413562095d54SToby Isaac if (!numValues) { 413662095d54SToby Isaac continue; 413762095d54SToby Isaac } 413862095d54SToby Isaac ierr = PetscSectionGetOffset(rootValuesSec,p,&pValOff);CHKERRQ(ierr); 413962095d54SToby Isaac pVal = &(rootValues[pValOff]); 414062095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 41410eb7e1eaSToby Isaac PetscInt closureSize = numValues; 41420eb7e1eaSToby Isaac ierr = DMPlexVecGetClosure(coarse,NULL,vecCoarseLocal,p,&closureSize,&pVal);CHKERRQ(ierr); 41430eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 4144193eb951SToby Isaac PetscFVCellGeom *cg; 41456dd00756SToby Isaac PetscScalar *gradVals = NULL; 41460eb7e1eaSToby Isaac PetscInt i; 41470eb7e1eaSToby Isaac 41480eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 41490eb7e1eaSToby Isaac 4150193eb951SToby Isaac ierr = DMPlexPointLocalRead(cellDM,p,cellGeomArray,(void *) &cg);CHKERRQ(ierr); 41510eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 41520eb7e1eaSToby Isaac pVal += dim; 4153193eb951SToby Isaac ierr = DMPlexPointGlobalRead(gradDM,p,gradArray,(void *) &gradVals);CHKERRQ(ierr); 41540eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 41550eb7e1eaSToby Isaac } 415662095d54SToby Isaac } 415778b7adb5SToby Isaac else if (maxChildId == -1) { 415878b7adb5SToby Isaac PetscInt lDof, lOff, i; 415978b7adb5SToby Isaac 416078b7adb5SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&lDof);CHKERRQ(ierr); 416178b7adb5SToby Isaac ierr = PetscSectionGetOffset(localCoarse,p,&lOff);CHKERRQ(ierr); 416278b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 416378b7adb5SToby Isaac } 416478b7adb5SToby Isaac } 416562095d54SToby Isaac ierr = VecRestoreArrayRead(vecCoarseLocal,&coarseArray);CHKERRQ(ierr); 416662095d54SToby Isaac ierr = PetscFree(maxChildIds);CHKERRQ(ierr); 416762095d54SToby Isaac } 416862095d54SToby Isaac { 416962095d54SToby Isaac PetscSF valuesSF; 417062095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 417162095d54SToby Isaac 417262095d54SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafValuesSec);CHKERRQ(ierr); 417362095d54SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootValuesSec,&remoteOffsetsValues,leafValuesSec);CHKERRQ(ierr); 417462095d54SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootValuesSec,remoteOffsetsValues,leafValuesSec,&valuesSF);CHKERRQ(ierr); 417562095d54SToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 417662095d54SToby Isaac ierr = PetscFree(remoteOffsetsValues);CHKERRQ(ierr); 417762095d54SToby Isaac ierr = PetscSectionGetStorageSize(leafValuesSec,&numLeafValues);CHKERRQ(ierr); 417862095d54SToby Isaac ierr = PetscMalloc1(numLeafValues,&leafValues);CHKERRQ(ierr); 417962095d54SToby Isaac ierr = PetscSFBcastBegin(valuesSF,MPIU_SCALAR,rootValues,leafValues);CHKERRQ(ierr); 418062095d54SToby Isaac ierr = PetscSFBcastEnd(valuesSF,MPIU_SCALAR,rootValues,leafValues);CHKERRQ(ierr); 418162095d54SToby Isaac ierr = PetscSFDestroy(&valuesSF);CHKERRQ(ierr); 418262095d54SToby Isaac ierr = PetscFree(rootValues);CHKERRQ(ierr); 418362095d54SToby Isaac ierr = PetscSectionDestroy(&rootValuesSec);CHKERRQ(ierr); 418462095d54SToby Isaac } 418562095d54SToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 418662095d54SToby Isaac { 418762095d54SToby Isaac PetscInt maxDof; 418862095d54SToby Isaac PetscInt *rowIndices; 418962095d54SToby Isaac DM refTree; 419062095d54SToby Isaac PetscInt **refPointFieldN; 419162095d54SToby Isaac PetscScalar ***refPointFieldMats; 419262095d54SToby Isaac PetscSection refConSec, refAnSec; 41930eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,leafStart,leafEnd; 419462095d54SToby Isaac PetscScalar *pointWork; 419562095d54SToby Isaac 419662095d54SToby Isaac ierr = PetscSectionGetMaxDof(globalFine,&maxDof);CHKERRQ(ierr); 419762095d54SToby Isaac ierr = DMGetWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 419862095d54SToby Isaac ierr = DMGetWorkArray(fine,maxDof,PETSC_SCALAR,&pointWork);CHKERRQ(ierr); 419962095d54SToby Isaac ierr = DMPlexGetReferenceTree(fine,&refTree);CHKERRQ(ierr); 42004833aeb0SToby Isaac ierr = DMGetDS(fine,&ds);CHKERRQ(ierr); 42014833aeb0SToby Isaac ierr = DMSetDS(refTree,ds);CHKERRQ(ierr); 420262095d54SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 420362095d54SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 420462095d54SToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,NULL);CHKERRQ(ierr); 420562095d54SToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 42060eb7e1eaSToby Isaac ierr = PetscSectionGetChart(leafValuesSec,&leafStart,&leafEnd);CHKERRQ(ierr); 42070eb7e1eaSToby Isaac ierr = DMPlexGetHeightStratum(fine,0,&cellStart,&cellEnd);CHKERRQ(ierr); 420889698031SToby Isaac ierr = DMPlexGetHybridBounds(fine,&cellEndInterior,NULL,NULL,NULL);CHKERRQ(ierr); 420989698031SToby Isaac cellEnd = (cellEndInterior < 0) ? cellEnd : cellEndInterior; 42100eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 421162095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 421262095d54SToby Isaac PetscInt numValues, pValOff; 421362095d54SToby Isaac PetscInt childId; 421462095d54SToby Isaac const PetscScalar *pVal; 42150eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 421662095d54SToby Isaac 421762095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 421862095d54SToby Isaac ierr = PetscSectionGetDof(localFine,p,&lDof);CHKERRQ(ierr); 421962095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 422062095d54SToby Isaac if ((gDof - gcDof) <= 0) { 422162095d54SToby Isaac continue; 422262095d54SToby Isaac } 422362095d54SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 422462095d54SToby Isaac ierr = PetscSectionGetDof(leafValuesSec,p,&numValues);CHKERRQ(ierr); 422562095d54SToby Isaac if (!numValues) continue; 422662095d54SToby Isaac ierr = PetscSectionGetOffset(leafValuesSec,p,&pValOff);CHKERRQ(ierr); 422762095d54SToby Isaac pVal = &leafValues[pValOff]; 422862095d54SToby Isaac offsets[0] = 0; 422962095d54SToby Isaac offsetsCopy[0] = 0; 423062095d54SToby Isaac newOffsets[0] = 0; 423162095d54SToby Isaac newOffsetsCopy[0] = 0; 42324833aeb0SToby Isaac childId = cids[p - pStartF]; 423362095d54SToby Isaac if (numFields) { 423462095d54SToby Isaac PetscInt f; 423562095d54SToby Isaac for (f = 0; f < numFields; f++) { 423662095d54SToby Isaac PetscInt rowDof; 423762095d54SToby Isaac 423862095d54SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 423962095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 424062095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 424162095d54SToby Isaac /* TODO: closure indices */ 42429f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 424362095d54SToby Isaac } 4244e9e67eccSMatthew G. Knepley ierr = DMPlexGetIndicesPointFields_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 424562095d54SToby Isaac } 424662095d54SToby Isaac else { 42474833aeb0SToby Isaac offsets[0] = 0; 42484833aeb0SToby Isaac offsets[1] = lDof; 42494833aeb0SToby Isaac newOffsets[0] = 0; 42504833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 4251e9e67eccSMatthew G. Knepley ierr = DMPlexGetIndicesPoint_Internal(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 425262095d54SToby Isaac } 425362095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 42542f65e181SToby Isaac ierr = VecSetValues(vecFine,numValues,rowIndices,pVal,INSERT_VALUES);CHKERRQ(ierr); 425562095d54SToby Isaac } else { 425662095d54SToby Isaac PetscInt f; 425762095d54SToby Isaac 425878b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 425978b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 426078b7adb5SToby Isaac fvGradData = &pVal[numValues]; 426178b7adb5SToby Isaac } 426262095d54SToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 426362095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 426462095d54SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 426562095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 426662095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 426762095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 426862095d54SToby Isaac PetscInt i, j; 426962095d54SToby Isaac 4270708c7f19SToby Isaac #if 0 4271708c7f19SToby Isaac ierr = PetscInfo6(coarse,"field %D, numFields %D, childId %D, numRows %D, numCols %D, refPointFieldN %D\n",f,numFields,childId,numRows,numCols,refPointFieldN[childId - pRefStart][f]);CHKERRQ(ierr); 4272708c7f19SToby Isaac #endif 427362095d54SToby Isaac for (i = 0; i < numRows; i++) { 427462095d54SToby Isaac PetscScalar val = 0.; 427562095d54SToby Isaac for (j = 0; j < numCols; j++) { 427662095d54SToby Isaac val += childMat[i * numCols + j] * cVal[j]; 427762095d54SToby Isaac } 427862095d54SToby Isaac rVal[i] = val; 427962095d54SToby Isaac } 42800eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 42810eb7e1eaSToby Isaac PetscReal centroid[3]; 42820eb7e1eaSToby Isaac PetscScalar diff[3]; 42830eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 42840eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 42850eb7e1eaSToby Isaac 42860eb7e1eaSToby Isaac ierr = DMPlexComputeCellGeometryFVM(fine,p,NULL,centroid,NULL);CHKERRQ(ierr); 42870eb7e1eaSToby Isaac for (i = 0; i < dim; i++) { 42880eb7e1eaSToby Isaac diff[i] = centroid[i] - parentCentroid[i]; 42890eb7e1eaSToby Isaac } 42900eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 42910eb7e1eaSToby Isaac PetscScalar val = 0.; 42920eb7e1eaSToby Isaac 429389698031SToby Isaac for (j = 0; j < dim; j++) { 42940eb7e1eaSToby Isaac val += gradient[dim * i + j] * diff[j]; 42950eb7e1eaSToby Isaac } 42960eb7e1eaSToby Isaac rVal[i] += val; 42970eb7e1eaSToby Isaac } 42980eb7e1eaSToby Isaac } 42992f65e181SToby Isaac ierr = VecSetValues(vecFine,numRows,&rowIndices[offsets[f]],rVal,INSERT_VALUES);CHKERRQ(ierr); 430062095d54SToby Isaac } 430162095d54SToby Isaac } 430262095d54SToby Isaac } 430362095d54SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 430462095d54SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 430562095d54SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,PETSC_SCALAR,&pointWork);CHKERRQ(ierr); 430662095d54SToby Isaac } 43074fe3dfefSToby Isaac ierr = PetscFree(leafValues);CHKERRQ(ierr); 430862095d54SToby Isaac ierr = PetscSectionDestroy(&leafValuesSec);CHKERRQ(ierr); 430962095d54SToby Isaac ierr = PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO);CHKERRQ(ierr); 431062095d54SToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4311ebf164c7SToby Isaac PetscFunctionReturn(0); 4312ebf164c7SToby Isaac } 4313ebf164c7SToby Isaac 4314ebf164c7SToby Isaac #undef __FUNCT__ 4315ebf164c7SToby Isaac #define __FUNCT__ "DMPlexTransferVecTree_Inject" 4316ebf164c7SToby Isaac static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4317ebf164c7SToby Isaac { 43184833aeb0SToby Isaac PetscDS ds; 4319c921d74cSToby Isaac DM refTree; 4320c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4321c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4322c921d74cSToby Isaac PetscSection localCoarse, localFine; 4323c921d74cSToby Isaac PetscSection cSecRef; 4324c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4325d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4326c921d74cSToby Isaac Mat injRef; 4327c921d74cSToby Isaac PetscInt numFields, maxDof; 4328c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4329c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4330c921d74cSToby Isaac PetscLayout rowMap, colMap; 4331c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4332c921d74cSToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4333c921d74cSToby Isaac PetscErrorCode ierr; 4334c921d74cSToby Isaac 4335ebf164c7SToby Isaac PetscFunctionBegin; 4336c921d74cSToby Isaac 4337c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 4338708c7f19SToby Isaac ierr = VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 4339708c7f19SToby Isaac ierr = VecSetOption(vecCoarse,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 4340c921d74cSToby Isaac ierr = DMPlexGetReferenceTree(coarse,&refTree);CHKERRQ(ierr); 43414833aeb0SToby Isaac ierr = DMGetDS(coarse,&ds);CHKERRQ(ierr); 43424833aeb0SToby Isaac ierr = DMSetDS(refTree,ds);CHKERRQ(ierr); 4343c921d74cSToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSecRef,NULL);CHKERRQ(ierr); 4344c921d74cSToby Isaac ierr = PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd);CHKERRQ(ierr); 4345c921d74cSToby Isaac ierr = DMPlexReferenceTreeGetInjector(refTree,&injRef);CHKERRQ(ierr); 4346c921d74cSToby Isaac 4347c921d74cSToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 4348c921d74cSToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 4349c921d74cSToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 4350c921d74cSToby Isaac ierr = PetscSectionGetNumFields(localFine,&numFields);CHKERRQ(ierr); 4351c921d74cSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 4352c921d74cSToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 4353c921d74cSToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 4354c921d74cSToby Isaac ierr = PetscSectionGetMaxDof(localCoarse,&maxDof);CHKERRQ(ierr); 4355c921d74cSToby Isaac { 4356c921d74cSToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 4357c921d74cSToby Isaac ierr = PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets);CHKERRQ(ierr); 4358c921d74cSToby Isaac } 4359c921d74cSToby Isaac 4360c921d74cSToby Isaac ierr = DMPlexTransferInjectorTree(coarse,fine,coarseToFine,cids,vecFine,numFields,offsets,&multiRootSec,&rootIndicesSec,NULL,&rootValues);CHKERRQ(ierr); 4361c921d74cSToby Isaac 4362d3bc4906SToby Isaac ierr = PetscMalloc2(maxDof,&parentIndices,maxDof,&parentValues);CHKERRQ(ierr); 4363c921d74cSToby Isaac 4364c921d74cSToby Isaac /* count indices */ 436562095d54SToby Isaac ierr = VecGetLayout(vecFine,&colMap);CHKERRQ(ierr); 436662095d54SToby Isaac ierr = VecGetLayout(vecCoarse,&rowMap);CHKERRQ(ierr); 4367c921d74cSToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 4368c921d74cSToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 4369c921d74cSToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 4370c921d74cSToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 4371c921d74cSToby Isaac /* insert values */ 4372c921d74cSToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 4373c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4374c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 437578b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4376c921d74cSToby Isaac 4377c921d74cSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 4378c921d74cSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 4379c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 43802f65e181SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&dof);CHKERRQ(ierr); 4381c921d74cSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 4382c921d74cSToby Isaac 4383c921d74cSToby Isaac rowOffsets[0] = 0; 4384c921d74cSToby Isaac offsetsCopy[0] = 0; 4385c921d74cSToby Isaac if (numFields) { 4386c921d74cSToby Isaac PetscInt f; 4387c921d74cSToby Isaac 4388c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4389c921d74cSToby Isaac PetscInt fDof; 4390c921d74cSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 4391c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4392c921d74cSToby Isaac } 4393e9e67eccSMatthew G. Knepley DMPlexGetIndicesPointFields_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,0,parentIndices);CHKERRQ(ierr); 4394c921d74cSToby Isaac } 4395c921d74cSToby Isaac else { 4396e9e67eccSMatthew G. Knepley DMPlexGetIndicesPoint_Internal(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,0,parentIndices);CHKERRQ(ierr); 4397c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4398c921d74cSToby Isaac } 4399c921d74cSToby Isaac 4400c921d74cSToby Isaac ierr = PetscSectionGetDof(multiRootSec,p,&numLeaves);CHKERRQ(ierr); 4401c921d74cSToby Isaac ierr = PetscSectionGetOffset(multiRootSec,p,&leafStart);CHKERRQ(ierr); 4402c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 44032f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4404c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4405c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4406c921d74cSToby Isaac const PetscScalar *childValues; 4407c921d74cSToby Isaac 4408c921d74cSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,l,&numIndices);CHKERRQ(ierr); 4409c921d74cSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,l,&offset);CHKERRQ(ierr); 4410c921d74cSToby Isaac childId = (PetscInt) PetscRealPart(rootValues[offset++]); 4411c921d74cSToby Isaac childValues = &rootValues[offset]; 4412c921d74cSToby Isaac numIndices--; 4413c921d74cSToby Isaac 4414c921d74cSToby Isaac if (childId == -2) { /* skip */ 4415c921d74cSToby Isaac continue; 4416c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 44172f65e181SToby Isaac PetscInt m; 44182f65e181SToby Isaac 441978b7adb5SToby Isaac contribute = PETSC_TRUE; 44202f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4421beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4422d3bc4906SToby Isaac PetscInt parentId, f, lim; 4423d3bc4906SToby Isaac 442478b7adb5SToby Isaac contribute = PETSC_TRUE; 4425d3bc4906SToby Isaac ierr = DMPlexGetTreeParent(refTree,childId,&parentId,NULL);CHKERRQ(ierr); 4426d3bc4906SToby Isaac 4427d3bc4906SToby Isaac lim = PetscMax(1,numFields); 4428d3bc4906SToby Isaac offsets[0] = 0; 4429d3bc4906SToby Isaac if (numFields) { 4430d3bc4906SToby Isaac PetscInt f; 4431d3bc4906SToby Isaac 4432d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4433d3bc4906SToby Isaac PetscInt fDof; 4434d3bc4906SToby Isaac ierr = PetscSectionGetFieldDof(cSecRef,childId,f,&fDof);CHKERRQ(ierr); 4435d3bc4906SToby Isaac 4436d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4437d3bc4906SToby Isaac } 4438d3bc4906SToby Isaac } 4439d3bc4906SToby Isaac else { 4440d3bc4906SToby Isaac PetscInt cDof; 4441d3bc4906SToby Isaac 4442d3bc4906SToby Isaac ierr = PetscSectionGetDof(cSecRef,childId,&cDof);CHKERRQ(ierr); 4443d3bc4906SToby Isaac offsets[1] = cDof; 4444d3bc4906SToby Isaac } 4445d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4446d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4447d3bc4906SToby Isaac PetscInt n = offsets[f+1]-offsets[f]; 4448d3bc4906SToby Isaac PetscInt i, j; 4449d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4450d3bc4906SToby Isaac 44512f65e181SToby Isaac for (i = rowOffsets[f]; i < rowOffsets[f + 1]; i++) { 4452d3bc4906SToby Isaac PetscScalar val = 0.; 4453d3bc4906SToby Isaac for (j = 0; j < n; j++) { 4454d3bc4906SToby Isaac val += childMat[n * i + j] * colValues[j]; 4455d3bc4906SToby Isaac } 4456beedf8abSToby Isaac parentValues[i] += val; 4457d3bc4906SToby Isaac } 4458d3bc4906SToby Isaac } 4459c921d74cSToby Isaac } 4460c921d74cSToby Isaac } 446178b7adb5SToby Isaac if (contribute) {ierr = VecSetValues(vecCoarse,dof,parentIndices,parentValues,INSERT_VALUES);CHKERRQ(ierr);} 4462c921d74cSToby Isaac } 4463c921d74cSToby Isaac ierr = PetscSectionDestroy(&multiRootSec);CHKERRQ(ierr); 4464c921d74cSToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 4465d3bc4906SToby Isaac ierr = PetscFree2(parentIndices,parentValues);CHKERRQ(ierr); 4466c921d74cSToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 4467c921d74cSToby Isaac ierr = PetscFree(rootValues);CHKERRQ(ierr); 4468c921d74cSToby Isaac ierr = PetscFree3(offsets,offsetsCopy,rowOffsets);CHKERRQ(ierr); 4469ebf164c7SToby Isaac PetscFunctionReturn(0); 4470ebf164c7SToby Isaac } 4471ebf164c7SToby Isaac 4472ebf164c7SToby Isaac #undef __FUNCT__ 447338fc2455SToby Isaac #define __FUNCT__ "DMPlexTransferVecTree" 44740eb7e1eaSToby Isaac PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfIn, PetscSF sfOut, PetscInt *cidsIn, PetscInt *cidsOut, PetscBool useBCs, PetscReal time) 447538fc2455SToby Isaac { 4476ebf164c7SToby Isaac PetscErrorCode ierr; 4477ebf164c7SToby Isaac 447838fc2455SToby Isaac PetscFunctionBegin; 447978b7adb5SToby Isaac ierr = VecSet(vecOut,0.0);CHKERRQ(ierr); 4480ebf164c7SToby Isaac if (sfIn) { 4481fbfa57b9SToby Isaac Vec vecInLocal; 44820eb7e1eaSToby Isaac DM dmGrad = NULL; 44830eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4484fbfa57b9SToby Isaac 4485fbfa57b9SToby Isaac ierr = DMGetLocalVector(dmIn,&vecInLocal);CHKERRQ(ierr); 4486fbfa57b9SToby Isaac ierr = VecSet(vecInLocal,0.0);CHKERRQ(ierr); 44870eb7e1eaSToby Isaac { 44880eb7e1eaSToby Isaac PetscInt numFields, i; 44890eb7e1eaSToby Isaac 44900eb7e1eaSToby Isaac ierr = DMGetNumFields(dmIn, &numFields);CHKERRQ(ierr); 44910eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 44920eb7e1eaSToby Isaac PetscObject obj; 44930eb7e1eaSToby Isaac PetscClassId classid; 44940eb7e1eaSToby Isaac 44950eb7e1eaSToby Isaac ierr = DMGetField(dmIn, i, &obj);CHKERRQ(ierr); 44960eb7e1eaSToby Isaac ierr = PetscObjectGetClassId(obj, &classid);CHKERRQ(ierr); 44970eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 44980eb7e1eaSToby Isaac ierr = DMPlexGetDataFVM(dmIn,(PetscFV)obj,&cellGeom,&faceGeom,&dmGrad);CHKERRQ(ierr); 44990eb7e1eaSToby Isaac break; 45000eb7e1eaSToby Isaac } 45010eb7e1eaSToby Isaac } 45020eb7e1eaSToby Isaac } 45030eb7e1eaSToby Isaac if (useBCs) { 45040eb7e1eaSToby Isaac ierr = DMPlexInsertBoundaryValues(dmIn,PETSC_TRUE,vecInLocal,time,faceGeom,cellGeom,NULL);CHKERRQ(ierr); 45050eb7e1eaSToby Isaac } 4506fbfa57b9SToby Isaac ierr = DMGlobalToLocalBegin(dmIn,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 4507fbfa57b9SToby Isaac ierr = DMGlobalToLocalEnd(dmIn,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 45080eb7e1eaSToby Isaac if (dmGrad) { 45090eb7e1eaSToby Isaac ierr = DMGetGlobalVector(dmGrad,&grad);CHKERRQ(ierr); 45100eb7e1eaSToby Isaac ierr = DMPlexReconstructGradientsFVM(dmIn,vecInLocal,grad);CHKERRQ(ierr); 45110eb7e1eaSToby Isaac } 45120eb7e1eaSToby Isaac ierr = DMPlexTransferVecTree_Interpolate(dmIn,vecInLocal,dmOut,vecOut,sfIn,cidsIn,grad,cellGeom);CHKERRQ(ierr); 4513fbfa57b9SToby Isaac ierr = DMRestoreLocalVector(dmIn,&vecInLocal);CHKERRQ(ierr); 45140eb7e1eaSToby Isaac if (dmGrad) { 45150eb7e1eaSToby Isaac ierr = DMRestoreGlobalVector(dmGrad,&grad);CHKERRQ(ierr); 45160eb7e1eaSToby Isaac } 4517ebf164c7SToby Isaac } 4518ebf164c7SToby Isaac if (sfOut) { 4519ebf164c7SToby Isaac ierr = DMPlexTransferVecTree_Inject(dmIn,vecIn,dmOut,vecOut,sfOut,cidsOut);CHKERRQ(ierr); 4520ebf164c7SToby Isaac } 45212f65e181SToby Isaac ierr = VecAssemblyBegin(vecOut);CHKERRQ(ierr); 45222f65e181SToby Isaac ierr = VecAssemblyEnd(vecOut);CHKERRQ(ierr); 452338fc2455SToby Isaac PetscFunctionReturn(0); 452438fc2455SToby Isaac } 4525