1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/isimpl.h> 3af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 4d6a7ad0dSToby Isaac #include <petscsf.h> 50c37af3bSToby Isaac #include <petscds.h> 6d6a7ad0dSToby Isaac 7*0e3d61c9SBarry Smith /* hierarchy routines */ 8d6a7ad0dSToby Isaac 9d6a7ad0dSToby Isaac /*@ 10d6a7ad0dSToby Isaac DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes. 11d6a7ad0dSToby Isaac 12d6a7ad0dSToby Isaac Not collective 13d6a7ad0dSToby Isaac 14d6a7ad0dSToby Isaac Input Parameters: 15d6a7ad0dSToby Isaac + dm - The DMPlex object 16d6a7ad0dSToby Isaac - ref - The reference tree DMPlex object 17d6a7ad0dSToby Isaac 180b7167a0SToby Isaac Level: intermediate 19d6a7ad0dSToby Isaac 20da43764aSToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexCreateDefaultReferenceTree() 21d6a7ad0dSToby Isaac @*/ 22d6a7ad0dSToby Isaac PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 23d6a7ad0dSToby Isaac { 24d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 25d6a7ad0dSToby Isaac PetscErrorCode ierr; 26d6a7ad0dSToby Isaac 27d6a7ad0dSToby Isaac PetscFunctionBegin; 28d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2947a1df27SMatthew G. Knepley if (ref) {PetscValidHeaderSpecific(ref, DM_CLASSID, 2);} 30d6a7ad0dSToby Isaac ierr = PetscObjectReference((PetscObject)ref);CHKERRQ(ierr); 31d6a7ad0dSToby Isaac ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 32d6a7ad0dSToby Isaac mesh->referenceTree = ref; 33d6a7ad0dSToby Isaac PetscFunctionReturn(0); 34d6a7ad0dSToby Isaac } 35d6a7ad0dSToby Isaac 36d6a7ad0dSToby Isaac /*@ 37d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 38d6a7ad0dSToby Isaac 39d6a7ad0dSToby Isaac Not collective 40d6a7ad0dSToby Isaac 41d6a7ad0dSToby Isaac Input Parameters: 42d6a7ad0dSToby Isaac . dm - The DMPlex object 43d6a7ad0dSToby Isaac 447a7aea1fSJed Brown Output Parameters: 45d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 46d6a7ad0dSToby Isaac 470b7167a0SToby Isaac Level: intermediate 48d6a7ad0dSToby Isaac 49da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexCreateDefaultReferenceTree() 50d6a7ad0dSToby Isaac @*/ 51d6a7ad0dSToby Isaac PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 52d6a7ad0dSToby Isaac { 53d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 54d6a7ad0dSToby Isaac 55d6a7ad0dSToby Isaac PetscFunctionBegin; 56d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 57d6a7ad0dSToby Isaac PetscValidPointer(ref,2); 58d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 59d6a7ad0dSToby Isaac PetscFunctionReturn(0); 60d6a7ad0dSToby Isaac } 61d6a7ad0dSToby Isaac 62dcbd3bf7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 63dcbd3bf7SToby Isaac { 64dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 65dcbd3bf7SToby Isaac PetscErrorCode ierr; 66dcbd3bf7SToby Isaac 67dcbd3bf7SToby Isaac PetscFunctionBegin; 68dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 69dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 70dcbd3bf7SToby Isaac if (childB) *childB = childA; 71dcbd3bf7SToby Isaac PetscFunctionReturn(0); 72dcbd3bf7SToby Isaac } 73dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 74dcbd3bf7SToby Isaac ierr = DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd);CHKERRQ(ierr); 75dcbd3bf7SToby Isaac if (parent >= dStart && parent <= dEnd) { 76dcbd3bf7SToby Isaac break; 77dcbd3bf7SToby Isaac } 78dcbd3bf7SToby Isaac } 79dcbd3bf7SToby Isaac if (dim > 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %d-cells",dim); 80dcbd3bf7SToby Isaac if (!dim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 81dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 82dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 83dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 84dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 85dcbd3bf7SToby Isaac 86dcbd3bf7SToby Isaac ierr = DMPlexGetSupportSize(dm,childA,&size);CHKERRQ(ierr); 87dcbd3bf7SToby Isaac ierr = DMPlexGetSupport(dm,childA,&supp);CHKERRQ(ierr); 88dcbd3bf7SToby Isaac 89dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 90dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 91dcbd3bf7SToby Isaac PetscInt sParent; 92dcbd3bf7SToby Isaac 93dcbd3bf7SToby Isaac sA = supp[i]; 94dcbd3bf7SToby Isaac if (sA == parent) continue; 95dcbd3bf7SToby Isaac ierr = DMPlexGetTreeParent(dm,sA,&sParent,NULL);CHKERRQ(ierr); 96dcbd3bf7SToby Isaac if (sParent == parent) { 97dcbd3bf7SToby Isaac break; 98dcbd3bf7SToby Isaac } 99dcbd3bf7SToby Isaac } 100dcbd3bf7SToby Isaac if (i == size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 101dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 102dcbd3bf7SToby Isaac * parentOrientB */ 103dcbd3bf7SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry_Default(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB);CHKERRQ(ierr); 104dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,sA,&sConeSize);CHKERRQ(ierr); 105dcbd3bf7SToby Isaac ierr = DMPlexGetCone(dm,sA,&coneA);CHKERRQ(ierr); 106dcbd3bf7SToby Isaac ierr = DMPlexGetCone(dm,sB,&coneB);CHKERRQ(ierr); 107dcbd3bf7SToby Isaac ierr = DMPlexGetConeOrientation(dm,sA,&oA);CHKERRQ(ierr); 108dcbd3bf7SToby Isaac ierr = DMPlexGetConeOrientation(dm,sB,&oB);CHKERRQ(ierr); 109dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 110dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 111dcbd3bf7SToby Isaac if (coneA[i] == childA) { 112dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 113dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 114dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 115dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 116dcbd3bf7SToby Isaac if (childOrientB) { 117dcbd3bf7SToby Isaac PetscInt oBtrue; 118dcbd3bf7SToby Isaac 119dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,childA,&coneSize);CHKERRQ(ierr); 120dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 121dcbd3bf7SToby Isaac if (coneSize != 0 && coneSize != 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 122dcbd3bf7SToby Isaac /* we may have to flip an edge */ 123dcbd3bf7SToby Isaac oBtrue = coneSize ? ((sOrientB >= 0) ? oB[j] : -(oB[j] + 2)) : 0; 124367003a6SStefano Zampini ABswap = DihedralSwap(coneSize,oA[i],oBtrue); 125dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 126dcbd3bf7SToby Isaac } 127dcbd3bf7SToby Isaac break; 128dcbd3bf7SToby Isaac } 129dcbd3bf7SToby Isaac } 130dcbd3bf7SToby Isaac if (i == sConeSize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 131dcbd3bf7SToby Isaac PetscFunctionReturn(0); 132dcbd3bf7SToby Isaac } 133dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 134dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,parent,&coneSize);CHKERRQ(ierr); 135dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 136dcbd3bf7SToby Isaac if (dim == 2) { 137dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 138dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 139dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 140dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 141dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 142dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 143947b95d8SBarry Smith } else { 144dcbd3bf7SToby Isaac ABswapVert = ABswap; 145dcbd3bf7SToby Isaac } 146dcbd3bf7SToby Isaac if (childB) { 147dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 148dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 149dcbd3bf7SToby Isaac const PetscInt *children; 150dcbd3bf7SToby Isaac 151dcbd3bf7SToby Isaac /* count which position the child is in */ 152dcbd3bf7SToby Isaac ierr = DMPlexGetTreeChildren(dm,parent,&numChildren,&children);CHKERRQ(ierr); 153dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 154dcbd3bf7SToby Isaac p = children[i]; 155dcbd3bf7SToby Isaac if (p == childA) { 156dcbd3bf7SToby Isaac posA = i; 157dcbd3bf7SToby Isaac break; 158dcbd3bf7SToby Isaac } 159dcbd3bf7SToby Isaac } 160dcbd3bf7SToby Isaac if (posA >= coneSize) { 161dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 162dcbd3bf7SToby Isaac * is invariant */ 163dcbd3bf7SToby Isaac if (dim != 2 || posA != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Expected a middle triangle, got something else"); 164dcbd3bf7SToby Isaac *childB = childA; 165dcbd3bf7SToby Isaac } 166dcbd3bf7SToby Isaac else { 167dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 168dcbd3bf7SToby Isaac PetscInt posB; 169dcbd3bf7SToby Isaac 170dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 171dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 172dcbd3bf7SToby Isaac } 173dcbd3bf7SToby Isaac } 174dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 175dcbd3bf7SToby Isaac PetscFunctionReturn(0); 176dcbd3bf7SToby Isaac } 177dcbd3bf7SToby Isaac 178dcbd3bf7SToby Isaac /*@ 179dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 180dcbd3bf7SToby Isaac 181dcbd3bf7SToby Isaac Input Parameters: 182dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object 183dcbd3bf7SToby Isaac . parent - the parent point 184dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 185dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 186dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 187dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 188dcbd3bf7SToby Isaac 189dcbd3bf7SToby Isaac Output Parameters: 190dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child 191ff1f73f7SToby Isaac - childB - if not NULL, the new childID for describing the child 192dcbd3bf7SToby Isaac 193dcbd3bf7SToby Isaac Level: developer 194dcbd3bf7SToby Isaac 195dcbd3bf7SToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexSetReferenceTree(), DMPlexSetTree() 196dcbd3bf7SToby Isaac @*/ 197dcbd3bf7SToby Isaac PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 198dcbd3bf7SToby Isaac { 199dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 200dcbd3bf7SToby Isaac PetscErrorCode ierr; 201dcbd3bf7SToby Isaac 202dcbd3bf7SToby Isaac PetscFunctionBegin; 203dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 204dcbd3bf7SToby Isaac if (!mesh->getchildsymmetry) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"DMPlexReferenceTreeGetChildSymmetry not implemented"); 205dcbd3bf7SToby Isaac ierr = mesh->getchildsymmetry(dm,parent,parentOrientA,childOrientA,childA,parentOrientB,childOrientB,childB);CHKERRQ(ierr); 206dcbd3bf7SToby Isaac PetscFunctionReturn(0); 207dcbd3bf7SToby Isaac } 208dcbd3bf7SToby Isaac 209776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM,PetscSection,PetscInt*,PetscInt*,PetscBool,PetscBool); 210f9f063d4SToby Isaac 211f2c1aa1dSLisandro Dalcin PetscErrorCode DMPlexCreateReferenceTree_SetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 212f2c1aa1dSLisandro Dalcin { 213f2c1aa1dSLisandro Dalcin PetscErrorCode ierr; 214f2c1aa1dSLisandro Dalcin 215f2c1aa1dSLisandro Dalcin PetscFunctionBegin; 216f2c1aa1dSLisandro Dalcin ierr = DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 217f2c1aa1dSLisandro Dalcin PetscFunctionReturn(0); 218f2c1aa1dSLisandro Dalcin } 219f2c1aa1dSLisandro Dalcin 2200e2cc29aSToby Isaac PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 221da43764aSToby Isaac { 2220e2cc29aSToby Isaac MPI_Comm comm; 2230e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 224da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 225da43764aSToby Isaac DMLabel identity, identityRef; 22610f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 227da43764aSToby Isaac PetscScalar *unionCoords; 228da43764aSToby Isaac IS perm; 229da43764aSToby Isaac PetscErrorCode ierr; 230da43764aSToby Isaac 231da43764aSToby Isaac PetscFunctionBegin; 2320e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2330e2cc29aSToby Isaac ierr = DMGetDimension(K, &dim);CHKERRQ(ierr); 234da43764aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 2350e2cc29aSToby Isaac ierr = DMGetLabel(K, labelName, &identity);CHKERRQ(ierr); 2360e2cc29aSToby Isaac ierr = DMGetLabel(Kref, labelName, &identityRef);CHKERRQ(ierr); 237da43764aSToby Isaac ierr = DMPlexGetChart(Kref, &pRefStart, &pRefEnd);CHKERRQ(ierr); 238da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionSection);CHKERRQ(ierr); 239da43764aSToby Isaac ierr = PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart));CHKERRQ(ierr); 240da43764aSToby Isaac /* count points that will go in the union */ 241da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 242da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pStart, 1);CHKERRQ(ierr); 243da43764aSToby Isaac } 244da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 245da43764aSToby Isaac PetscInt q, qSize; 246da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, p, &q);CHKERRQ(ierr); 247da43764aSToby Isaac ierr = DMLabelGetStratumSize(identityRef, q, &qSize);CHKERRQ(ierr); 248da43764aSToby Isaac if (qSize > 1) { 249da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1);CHKERRQ(ierr); 250da43764aSToby Isaac } 251da43764aSToby Isaac } 252854ce69bSBarry Smith ierr = PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart,&permvals);CHKERRQ(ierr); 253da43764aSToby Isaac offset = 0; 254da43764aSToby Isaac /* stratify points in the union by topological dimension */ 255da43764aSToby Isaac for (d = 0; d <= dim; d++) { 256da43764aSToby Isaac PetscInt cStart, cEnd, c; 257da43764aSToby Isaac 258da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K, d, &cStart, &cEnd);CHKERRQ(ierr); 259da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 260da43764aSToby Isaac permvals[offset++] = c; 261da43764aSToby Isaac } 262da43764aSToby Isaac 263da43764aSToby Isaac ierr = DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd);CHKERRQ(ierr); 264da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 265da43764aSToby Isaac permvals[offset++] = c + (pEnd - pStart); 266da43764aSToby Isaac } 267da43764aSToby Isaac } 268da43764aSToby Isaac ierr = ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr); 269da43764aSToby Isaac ierr = PetscSectionSetPermutation(unionSection,perm);CHKERRQ(ierr); 270da43764aSToby Isaac ierr = PetscSectionSetUp(unionSection);CHKERRQ(ierr); 271da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionSection,&numUnionPoints);CHKERRQ(ierr); 272da43764aSToby Isaac ierr = PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints);CHKERRQ(ierr); 273da43764aSToby Isaac /* count dimension points */ 274da43764aSToby Isaac for (d = 0; d <= dim; d++) { 275da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 276da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d,&cStart,NULL);CHKERRQ(ierr); 277da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff);CHKERRQ(ierr); 278da43764aSToby Isaac if (d < dim) { 279da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d+1,&cStart,NULL);CHKERRQ(ierr); 280da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2);CHKERRQ(ierr); 281da43764aSToby Isaac } 282da43764aSToby Isaac else { 283da43764aSToby Isaac cOff2 = numUnionPoints; 284da43764aSToby Isaac } 285da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 286da43764aSToby Isaac } 287da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionConeSection);CHKERRQ(ierr); 288da43764aSToby Isaac ierr = PetscSectionSetChart(unionConeSection, 0, numUnionPoints);CHKERRQ(ierr); 289da43764aSToby Isaac /* count the cones in the union */ 290da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 291da43764aSToby Isaac PetscInt dof, uOff; 292da43764aSToby Isaac 293da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 294da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 295da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 296da43764aSToby Isaac coneSizes[uOff] = dof; 297da43764aSToby Isaac } 298da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 299da43764aSToby Isaac PetscInt dof, uDof, uOff; 300da43764aSToby Isaac 301da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 302da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 303da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 304da43764aSToby Isaac if (uDof) { 305da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 306da43764aSToby Isaac coneSizes[uOff] = dof; 307da43764aSToby Isaac } 308da43764aSToby Isaac } 309da43764aSToby Isaac ierr = PetscSectionSetUp(unionConeSection);CHKERRQ(ierr); 310da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionConeSection,&numCones);CHKERRQ(ierr); 311da43764aSToby Isaac ierr = PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations);CHKERRQ(ierr); 312da43764aSToby Isaac /* write the cones in the union */ 313da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 314da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 315da43764aSToby Isaac const PetscInt *cone, *orientation; 316da43764aSToby Isaac 317da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 318da43764aSToby Isaac ierr = DMPlexGetCone(K, p, &cone);CHKERRQ(ierr); 319da43764aSToby Isaac ierr = DMPlexGetConeOrientation(K, p, &orientation);CHKERRQ(ierr); 320da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 321da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 322da43764aSToby Isaac for (c = 0; c < dof; c++) { 323da43764aSToby Isaac PetscInt e, eOff; 324da43764aSToby Isaac e = cone[c]; 325da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 326da43764aSToby Isaac unionCones[cOff + c] = eOff; 327da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 328da43764aSToby Isaac } 329da43764aSToby Isaac } 330da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 331da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 332da43764aSToby Isaac const PetscInt *cone, *orientation; 333da43764aSToby Isaac 334da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 335da43764aSToby Isaac ierr = DMPlexGetCone(Kref, p, &cone);CHKERRQ(ierr); 336da43764aSToby Isaac ierr = DMPlexGetConeOrientation(Kref, p, &orientation);CHKERRQ(ierr); 337da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 338da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 339da43764aSToby Isaac if (uDof) { 340da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 341da43764aSToby Isaac for (c = 0; c < dof; c++) { 342da43764aSToby Isaac PetscInt e, eOff, eDof; 343da43764aSToby Isaac 344da43764aSToby Isaac e = cone[c]; 345da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof);CHKERRQ(ierr); 346da43764aSToby Isaac if (eDof) { 347da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff);CHKERRQ(ierr); 348da43764aSToby Isaac } 349da43764aSToby Isaac else { 350da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, e, &e);CHKERRQ(ierr); 351da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 352da43764aSToby Isaac } 353da43764aSToby Isaac unionCones[cOff + c] = eOff; 354da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 355da43764aSToby Isaac } 356da43764aSToby Isaac } 357da43764aSToby Isaac } 358da43764aSToby Isaac /* get the coordinates */ 359da43764aSToby Isaac { 360da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 361da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 362da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 363da43764aSToby Isaac PetscScalar *Kcoords; 364da43764aSToby Isaac 365367003a6SStefano Zampini ierr = DMGetCoordinateSection(K, &KcoordsSec);CHKERRQ(ierr); 366367003a6SStefano Zampini ierr = DMGetCoordinatesLocal(K, &KcoordsVec);CHKERRQ(ierr); 367367003a6SStefano Zampini ierr = DMGetCoordinateSection(Kref, &KrefCoordsSec);CHKERRQ(ierr); 368367003a6SStefano Zampini ierr = DMGetCoordinatesLocal(Kref, &KrefCoordsVec);CHKERRQ(ierr); 369da43764aSToby Isaac 370da43764aSToby Isaac numVerts = numDimPoints[0]; 371da43764aSToby Isaac ierr = PetscMalloc1(numVerts * dim,&unionCoords);CHKERRQ(ierr); 372da43764aSToby Isaac ierr = DMPlexGetDepthStratum(K,0,&vStart,&vEnd);CHKERRQ(ierr); 373da43764aSToby Isaac 374da43764aSToby Isaac offset = 0; 375da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 376da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pStart,&vOff);CHKERRQ(ierr); 377da43764aSToby Isaac ierr = VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords);CHKERRQ(ierr); 378da43764aSToby Isaac for (d = 0; d < dim; d++) { 379da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 380da43764aSToby Isaac } 381da43764aSToby Isaac offset++; 382da43764aSToby Isaac } 383da43764aSToby Isaac ierr = DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd);CHKERRQ(ierr); 384da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 385da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof);CHKERRQ(ierr); 386da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff);CHKERRQ(ierr); 387da43764aSToby Isaac ierr = VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords);CHKERRQ(ierr); 388da43764aSToby Isaac if (vDof) { 389da43764aSToby Isaac for (d = 0; d < dim; d++) { 390da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 391da43764aSToby Isaac } 392da43764aSToby Isaac offset++; 393da43764aSToby Isaac } 394da43764aSToby Isaac } 395da43764aSToby Isaac } 396da43764aSToby Isaac ierr = DMCreate(comm,ref);CHKERRQ(ierr); 397da43764aSToby Isaac ierr = DMSetType(*ref,DMPLEX);CHKERRQ(ierr); 39828f4b327SMatthew G. Knepley ierr = DMSetDimension(*ref,dim);CHKERRQ(ierr); 399da43764aSToby Isaac ierr = DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords);CHKERRQ(ierr); 40010f7e118SToby Isaac /* set the tree */ 40110f7e118SToby Isaac ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr); 40210f7e118SToby Isaac ierr = PetscSectionSetChart(parentSection,0,numUnionPoints);CHKERRQ(ierr); 40310f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 40410f7e118SToby Isaac PetscInt uDof, uOff; 40510f7e118SToby Isaac 40610f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 40710f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 40810f7e118SToby Isaac if (uDof) { 409367003a6SStefano Zampini ierr = PetscSectionSetDof(parentSection,uOff,1);CHKERRQ(ierr); 41010f7e118SToby Isaac } 41110f7e118SToby Isaac } 41210f7e118SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 41310f7e118SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&parentSize);CHKERRQ(ierr); 41410f7e118SToby Isaac ierr = PetscMalloc2(parentSize,&parents,parentSize,&childIDs);CHKERRQ(ierr); 41510f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 41610f7e118SToby Isaac PetscInt uDof, uOff; 41710f7e118SToby Isaac 41810f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 41910f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 42010f7e118SToby Isaac if (uDof) { 42110f7e118SToby Isaac PetscInt pOff, parent, parentU; 422367003a6SStefano Zampini ierr = PetscSectionGetOffset(parentSection,uOff,&pOff);CHKERRQ(ierr); 423367003a6SStefano Zampini ierr = DMLabelGetValue(identityRef,p,&parent);CHKERRQ(ierr); 42410f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, parent - pStart,&parentU);CHKERRQ(ierr); 42510f7e118SToby Isaac parents[pOff] = parentU; 42610f7e118SToby Isaac childIDs[pOff] = uOff; 42710f7e118SToby Isaac } 42810f7e118SToby Isaac } 429f2c1aa1dSLisandro Dalcin ierr = DMPlexCreateReferenceTree_SetTree(*ref,parentSection,parents,childIDs);CHKERRQ(ierr); 43010f7e118SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 43110f7e118SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 43210f7e118SToby Isaac 433da43764aSToby Isaac /* clean up */ 434da43764aSToby Isaac ierr = PetscSectionDestroy(&unionSection);CHKERRQ(ierr); 435da43764aSToby Isaac ierr = PetscSectionDestroy(&unionConeSection);CHKERRQ(ierr); 436da43764aSToby Isaac ierr = ISDestroy(&perm);CHKERRQ(ierr); 437da43764aSToby Isaac ierr = PetscFree(unionCoords);CHKERRQ(ierr); 438da43764aSToby Isaac ierr = PetscFree2(unionCones,unionOrientations);CHKERRQ(ierr); 439da43764aSToby Isaac ierr = PetscFree2(coneSizes,numDimPoints);CHKERRQ(ierr); 4400e2cc29aSToby Isaac PetscFunctionReturn(0); 4410e2cc29aSToby Isaac } 4420e2cc29aSToby Isaac 4430e2cc29aSToby Isaac /*@ 4440e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4450e2cc29aSToby Isaac 446d083f849SBarry Smith Collective 4470e2cc29aSToby Isaac 4480e2cc29aSToby Isaac Input Parameters: 4490e2cc29aSToby Isaac + comm - the MPI communicator 4500e2cc29aSToby Isaac . dim - the spatial dimension 4510e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4520e2cc29aSToby Isaac 4530e2cc29aSToby Isaac Output Parameters: 4540e2cc29aSToby Isaac . ref - the reference tree DMPlex object 4550e2cc29aSToby Isaac 4560e2cc29aSToby Isaac Level: intermediate 4570e2cc29aSToby Isaac 4580e2cc29aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree() 4590e2cc29aSToby Isaac @*/ 4600e2cc29aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 4610e2cc29aSToby Isaac { 4620e2cc29aSToby Isaac DM_Plex *mesh; 4630e2cc29aSToby Isaac DM K, Kref; 4640e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4650e2cc29aSToby Isaac DMLabel identity; 4660e2cc29aSToby Isaac PetscErrorCode ierr; 4670e2cc29aSToby Isaac 4680e2cc29aSToby Isaac PetscFunctionBegin; 4690e2cc29aSToby Isaac #if 1 4700e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4710e2cc29aSToby Isaac #endif 4720e2cc29aSToby Isaac /* create a reference element */ 4739318fe57SMatthew G. Knepley ierr = DMPlexCreateReferenceCell(comm, DMPolytopeTypeSimpleShape(dim, simplex), &K);CHKERRQ(ierr); 4740e2cc29aSToby Isaac ierr = DMCreateLabel(K, "identity");CHKERRQ(ierr); 4750e2cc29aSToby Isaac ierr = DMGetLabel(K, "identity", &identity);CHKERRQ(ierr); 4760e2cc29aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 4770e2cc29aSToby Isaac for (p = pStart; p < pEnd; p++) { 4780e2cc29aSToby Isaac ierr = DMLabelSetValue(identity, p, p);CHKERRQ(ierr); 4790e2cc29aSToby Isaac } 4800e2cc29aSToby Isaac /* refine it */ 4810e2cc29aSToby Isaac ierr = DMRefine(K,comm,&Kref);CHKERRQ(ierr); 4820e2cc29aSToby Isaac 4830e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4840e2cc29aSToby Isaac * points that appear in both */ 4850e2cc29aSToby Isaac ierr = DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref);CHKERRQ(ierr); 4860e2cc29aSToby Isaac mesh = (DM_Plex *) (*ref)->data; 4870e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 488da43764aSToby Isaac ierr = DMDestroy(&K);CHKERRQ(ierr); 489da43764aSToby Isaac ierr = DMDestroy(&Kref);CHKERRQ(ierr); 490da43764aSToby Isaac PetscFunctionReturn(0); 491da43764aSToby Isaac } 492da43764aSToby Isaac 493878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 494878b19aaSToby Isaac { 495878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 496878b19aaSToby Isaac PetscSection childSec, pSec; 497878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 498878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 499878b19aaSToby Isaac PetscErrorCode ierr; 500878b19aaSToby Isaac 501878b19aaSToby Isaac PetscFunctionBegin; 502878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 503878b19aaSToby Isaac ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 504878b19aaSToby Isaac ierr = PetscFree(mesh->children);CHKERRQ(ierr); 505878b19aaSToby Isaac pSec = mesh->parentSection; 506878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 507878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(pSec,&pSize);CHKERRQ(ierr); 508878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 509878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 510878b19aaSToby Isaac 511878b19aaSToby Isaac parMax = PetscMax(parMax,par+1); 512878b19aaSToby Isaac parMin = PetscMin(parMin,par); 513878b19aaSToby Isaac } 514878b19aaSToby Isaac if (parMin > parMax) { 515878b19aaSToby Isaac parMin = -1; 516878b19aaSToby Isaac parMax = -1; 517878b19aaSToby Isaac } 518878b19aaSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec);CHKERRQ(ierr); 519878b19aaSToby Isaac ierr = PetscSectionSetChart(childSec,parMin,parMax);CHKERRQ(ierr); 520878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 521878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 522878b19aaSToby Isaac 523878b19aaSToby Isaac ierr = PetscSectionAddDof(childSec,par,1);CHKERRQ(ierr); 524878b19aaSToby Isaac } 525878b19aaSToby Isaac ierr = PetscSectionSetUp(childSec);CHKERRQ(ierr); 526878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(childSec,&cSize);CHKERRQ(ierr); 527878b19aaSToby Isaac ierr = PetscMalloc1(cSize,&children);CHKERRQ(ierr); 528878b19aaSToby Isaac ierr = PetscCalloc1(parMax-parMin,&offsets);CHKERRQ(ierr); 529878b19aaSToby Isaac ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr); 530878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 531878b19aaSToby Isaac PetscInt dof, off, i; 532878b19aaSToby Isaac 533878b19aaSToby Isaac ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 534878b19aaSToby Isaac ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr); 535878b19aaSToby Isaac for (i = 0; i < dof; i++) { 536878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 537878b19aaSToby Isaac 538878b19aaSToby Isaac ierr = PetscSectionGetOffset(childSec,par,&cOff);CHKERRQ(ierr); 539878b19aaSToby Isaac children[cOff + offsets[par-parMin]++] = p; 540878b19aaSToby Isaac } 541878b19aaSToby Isaac } 542878b19aaSToby Isaac mesh->childSection = childSec; 543878b19aaSToby Isaac mesh->children = children; 544878b19aaSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 545878b19aaSToby Isaac PetscFunctionReturn(0); 546878b19aaSToby Isaac } 547878b19aaSToby Isaac 5486dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 5496dd5a8c8SToby Isaac { 5506dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5516dd5a8c8SToby Isaac const PetscInt *vals; 5526dd5a8c8SToby Isaac PetscSection secNew; 5536dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5546dd5a8c8SToby Isaac PetscBool compress; 5556dd5a8c8SToby Isaac PetscErrorCode ierr; 5566dd5a8c8SToby Isaac 5576dd5a8c8SToby Isaac PetscFunctionBegin; 5586dd5a8c8SToby Isaac ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr); 5596dd5a8c8SToby Isaac ierr = ISGetLocalSize(is,&size);CHKERRQ(ierr); 5606dd5a8c8SToby Isaac ierr = ISGetIndices(is,&vals);CHKERRQ(ierr); 5616dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew);CHKERRQ(ierr); 5626dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secNew,pStart,pEnd);CHKERRQ(ierr); 5636dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5646dd5a8c8SToby Isaac PetscInt dof; 5656dd5a8c8SToby Isaac 5666dd5a8c8SToby Isaac p = vals[i]; 5676dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5686dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5696dd5a8c8SToby Isaac if (dof) break; 5706dd5a8c8SToby Isaac } 5716dd5a8c8SToby Isaac if (i == size) { 5726dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 5736dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5746dd5a8c8SToby Isaac compress = PETSC_FALSE; 5756dd5a8c8SToby Isaac sizeNew = 0; 5766dd5a8c8SToby Isaac } 5776dd5a8c8SToby Isaac else { 5786dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5796dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5806dd5a8c8SToby Isaac PetscInt dof, off; 5816dd5a8c8SToby Isaac 5826dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5836dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 5846dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5856dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5866dd5a8c8SToby Isaac 5876dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5886dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 5896dd5a8c8SToby Isaac } 5906dd5a8c8SToby Isaac if (qDof) { 5916dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, qDof);CHKERRQ(ierr); 5926dd5a8c8SToby Isaac } 5936dd5a8c8SToby Isaac else { 5946dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, 1);CHKERRQ(ierr); 5956dd5a8c8SToby Isaac } 5966dd5a8c8SToby Isaac } 5976dd5a8c8SToby Isaac } 5986dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 5996dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secNew,&sizeNew);CHKERRQ(ierr); 6006dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsNew);CHKERRQ(ierr); 6016dd5a8c8SToby Isaac compress = PETSC_FALSE; 6026dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6036dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 6046dd5a8c8SToby Isaac 6056dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 6066dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 6076dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dofNew);CHKERRQ(ierr); 6086dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &offNew);CHKERRQ(ierr); 6096dd5a8c8SToby Isaac count = 0; 6106dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 6116dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 6126dd5a8c8SToby Isaac 6136dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 6146dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 6156dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, q, &qOff);CHKERRQ(ierr); 6166dd5a8c8SToby Isaac } 6176dd5a8c8SToby Isaac if (qDof) { 6186dd5a8c8SToby Isaac PetscInt oldCount = count; 6196dd5a8c8SToby Isaac 6206dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 6216dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 6226dd5a8c8SToby Isaac 6236dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6246dd5a8c8SToby Isaac if (valsNew[offNew + k] == r) { 6256dd5a8c8SToby Isaac break; 6266dd5a8c8SToby Isaac } 6276dd5a8c8SToby Isaac } 6286dd5a8c8SToby Isaac if (k == oldCount) { 6296dd5a8c8SToby Isaac valsNew[offNew + count++] = r; 6306dd5a8c8SToby Isaac } 6316dd5a8c8SToby Isaac } 6326dd5a8c8SToby Isaac } 6336dd5a8c8SToby Isaac else { 6346dd5a8c8SToby Isaac PetscInt k, oldCount = count; 6356dd5a8c8SToby Isaac 6366dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6376dd5a8c8SToby Isaac if (valsNew[offNew + k] == q) { 6386dd5a8c8SToby Isaac break; 6396dd5a8c8SToby Isaac } 6406dd5a8c8SToby Isaac } 6416dd5a8c8SToby Isaac if (k == oldCount) { 6426dd5a8c8SToby Isaac valsNew[offNew + count++] = q; 6436dd5a8c8SToby Isaac } 6446dd5a8c8SToby Isaac } 6456dd5a8c8SToby Isaac } 6466dd5a8c8SToby Isaac if (count < dofNew) { 6476dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secNew, p, count);CHKERRQ(ierr); 6486dd5a8c8SToby Isaac compress = PETSC_TRUE; 6496dd5a8c8SToby Isaac } 6506dd5a8c8SToby Isaac } 6516dd5a8c8SToby Isaac } 6526dd5a8c8SToby Isaac ierr = ISRestoreIndices(is,&vals);CHKERRQ(ierr); 653820f2d46SBarry Smith ierr = MPIU_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRMPI(ierr); 6546dd5a8c8SToby Isaac if (!globalAnyNew) { 6556dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6566dd5a8c8SToby Isaac *sectionNew = NULL; 6576dd5a8c8SToby Isaac *isNew = NULL; 6586dd5a8c8SToby Isaac } 6596dd5a8c8SToby Isaac else { 6606dd5a8c8SToby Isaac PetscBool globalCompress; 6616dd5a8c8SToby Isaac 662820f2d46SBarry Smith ierr = MPIU_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRMPI(ierr); 6636dd5a8c8SToby Isaac if (compress) { 6646dd5a8c8SToby Isaac PetscSection secComp; 6656dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6666dd5a8c8SToby Isaac 6676dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp);CHKERRQ(ierr); 6686dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secComp,pStart,pEnd);CHKERRQ(ierr); 6696dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6706dd5a8c8SToby Isaac PetscInt dof; 6716dd5a8c8SToby Isaac 6726dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6736dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secComp, p, dof);CHKERRQ(ierr); 6746dd5a8c8SToby Isaac } 6756dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secComp);CHKERRQ(ierr); 6766dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secComp,&sizeNew);CHKERRQ(ierr); 6776dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsComp);CHKERRQ(ierr); 6786dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6796dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6806dd5a8c8SToby Isaac 6816dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6826dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &off);CHKERRQ(ierr); 6836dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secComp, p, &offNew);CHKERRQ(ierr); 6846dd5a8c8SToby Isaac for (j = 0; j < dof; j++) { 6856dd5a8c8SToby Isaac valsComp[offNew + j] = valsNew[off + j]; 6866dd5a8c8SToby Isaac } 6876dd5a8c8SToby Isaac } 6886dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6896dd5a8c8SToby Isaac secNew = secComp; 6906dd5a8c8SToby Isaac ierr = PetscFree(valsNew);CHKERRQ(ierr); 6916dd5a8c8SToby Isaac valsNew = valsComp; 6926dd5a8c8SToby Isaac } 6936dd5a8c8SToby Isaac ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew);CHKERRQ(ierr); 6946dd5a8c8SToby Isaac } 6956dd5a8c8SToby Isaac PetscFunctionReturn(0); 6966dd5a8c8SToby Isaac } 6976dd5a8c8SToby Isaac 698f7c74593SToby Isaac static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 69966af876cSToby Isaac { 70066af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 70166af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 70266af876cSToby Isaac PetscSection aSec; 703f9f063d4SToby Isaac DMLabel canonLabel; 70466af876cSToby Isaac IS aIS; 70566af876cSToby Isaac PetscErrorCode ierr; 70666af876cSToby Isaac 70766af876cSToby Isaac PetscFunctionBegin; 70866af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 70966af876cSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 710c58f1c22SToby Isaac ierr = DMGetLabel(dm,"canonical",&canonLabel);CHKERRQ(ierr); 71166af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 71266af876cSToby Isaac PetscInt parent; 71366af876cSToby Isaac 714f9f063d4SToby Isaac if (canonLabel) { 715f9f063d4SToby Isaac PetscInt canon; 716f9f063d4SToby Isaac 717f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 718f9f063d4SToby Isaac if (p != canon) continue; 719f9f063d4SToby Isaac } 72066af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 72166af876cSToby Isaac if (parent != p) { 72266af876cSToby Isaac aMin = PetscMin(aMin,p); 72366af876cSToby Isaac aMax = PetscMax(aMax,p+1); 72466af876cSToby Isaac } 72566af876cSToby Isaac } 72666af876cSToby Isaac if (aMin > aMax) { 72766af876cSToby Isaac aMin = -1; 72866af876cSToby Isaac aMax = -1; 72966af876cSToby Isaac } 730e228b242SToby Isaac ierr = PetscSectionCreate(PETSC_COMM_SELF,&aSec);CHKERRQ(ierr); 73166af876cSToby Isaac ierr = PetscSectionSetChart(aSec,aMin,aMax);CHKERRQ(ierr); 73266af876cSToby Isaac for (p = aMin; p < aMax; p++) { 73366af876cSToby Isaac PetscInt parent, ancestor = p; 73466af876cSToby Isaac 735f9f063d4SToby Isaac if (canonLabel) { 736f9f063d4SToby Isaac PetscInt canon; 737f9f063d4SToby Isaac 738f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 739f9f063d4SToby Isaac if (p != canon) continue; 740f9f063d4SToby Isaac } 74166af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 74266af876cSToby Isaac while (parent != ancestor) { 74366af876cSToby Isaac ancestor = parent; 74466af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 74566af876cSToby Isaac } 74666af876cSToby Isaac if (ancestor != p) { 74766af876cSToby Isaac PetscInt closureSize, *closure = NULL; 74866af876cSToby Isaac 74966af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 75066af876cSToby Isaac ierr = PetscSectionSetDof(aSec,p,closureSize);CHKERRQ(ierr); 75166af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 75266af876cSToby Isaac } 75366af876cSToby Isaac } 75466af876cSToby Isaac ierr = PetscSectionSetUp(aSec);CHKERRQ(ierr); 75566af876cSToby Isaac ierr = PetscSectionGetStorageSize(aSec,&size);CHKERRQ(ierr); 75666af876cSToby Isaac ierr = PetscMalloc1(size,&anchors);CHKERRQ(ierr); 75766af876cSToby Isaac for (p = aMin; p < aMax; p++) { 75866af876cSToby Isaac PetscInt parent, ancestor = p; 75966af876cSToby Isaac 760f9f063d4SToby Isaac if (canonLabel) { 761f9f063d4SToby Isaac PetscInt canon; 762f9f063d4SToby Isaac 763f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 764f9f063d4SToby Isaac if (p != canon) continue; 765f9f063d4SToby Isaac } 76666af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 76766af876cSToby Isaac while (parent != ancestor) { 76866af876cSToby Isaac ancestor = parent; 76966af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 77066af876cSToby Isaac } 77166af876cSToby Isaac if (ancestor != p) { 77266af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 77366af876cSToby Isaac 77466af876cSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 77566af876cSToby Isaac 77666af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 77766af876cSToby Isaac for (j = 0; j < closureSize; j++) { 77866af876cSToby Isaac anchors[aOff + j] = closure[2*j]; 77966af876cSToby Isaac } 78066af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 78166af876cSToby Isaac } 78266af876cSToby Isaac } 783e228b242SToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,size,anchors,PETSC_OWN_POINTER,&aIS);CHKERRQ(ierr); 7846dd5a8c8SToby Isaac { 7856dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7866dd5a8c8SToby Isaac IS aISNew = aIS; 7876dd5a8c8SToby Isaac 7886dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aSec);CHKERRQ(ierr); 7896dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aIS);CHKERRQ(ierr); 7906dd5a8c8SToby Isaac while (aSecNew) { 7916dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 7926dd5a8c8SToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 7936dd5a8c8SToby Isaac aSec = aSecNew; 7946dd5a8c8SToby Isaac aIS = aISNew; 7956dd5a8c8SToby Isaac aSecNew = NULL; 7966dd5a8c8SToby Isaac aISNew = NULL; 7976dd5a8c8SToby Isaac ierr = AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew);CHKERRQ(ierr); 7986dd5a8c8SToby Isaac } 7996dd5a8c8SToby Isaac } 800a17985deSToby Isaac ierr = DMPlexSetAnchors(dm,aSec,aIS);CHKERRQ(ierr); 80166af876cSToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 80266af876cSToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 80366af876cSToby Isaac PetscFunctionReturn(0); 80466af876cSToby Isaac } 80566af876cSToby Isaac 8066461c1adSToby Isaac static PetscErrorCode DMPlexGetTrueSupportSize(DM dm,PetscInt p,PetscInt *dof,PetscInt *numTrueSupp) 8076461c1adSToby Isaac { 8086461c1adSToby Isaac PetscErrorCode ierr; 8096461c1adSToby Isaac 8106461c1adSToby Isaac PetscFunctionBegin; 8116461c1adSToby Isaac if (numTrueSupp[p] == -1) { 8126461c1adSToby Isaac PetscInt i, alldof; 8136461c1adSToby Isaac const PetscInt *supp; 8146461c1adSToby Isaac PetscInt count = 0; 8156461c1adSToby Isaac 8166461c1adSToby Isaac ierr = DMPlexGetSupportSize(dm,p,&alldof);CHKERRQ(ierr); 8176461c1adSToby Isaac ierr = DMPlexGetSupport(dm,p,&supp);CHKERRQ(ierr); 8186461c1adSToby Isaac for (i = 0; i < alldof; i++) { 8196461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 8206461c1adSToby Isaac const PetscInt *cone; 8216461c1adSToby Isaac 8226461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr); 8236461c1adSToby Isaac ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr); 8246461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8256461c1adSToby Isaac if (cone[j] == p) break; 8266461c1adSToby Isaac } 8276461c1adSToby Isaac if (j < numCones) count++; 8286461c1adSToby Isaac } 8296461c1adSToby Isaac numTrueSupp[p] = count; 8306461c1adSToby Isaac } 8316461c1adSToby Isaac *dof = numTrueSupp[p]; 8326461c1adSToby Isaac PetscFunctionReturn(0); 8336461c1adSToby Isaac } 8346461c1adSToby Isaac 835776742edSToby Isaac static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 836776742edSToby Isaac { 837776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 838776742edSToby Isaac PetscSection newSupportSection; 839776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 8406461c1adSToby Isaac PetscInt *numTrueSupp; 841776742edSToby Isaac PetscInt *offsets; 842776742edSToby Isaac PetscErrorCode ierr; 843776742edSToby Isaac 844776742edSToby Isaac PetscFunctionBegin; 845776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 846776742edSToby Isaac /* symmetrize the hierarchy */ 847776742edSToby Isaac ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 848e228b242SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)),&newSupportSection);CHKERRQ(ierr); 849776742edSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 850776742edSToby Isaac ierr = PetscSectionSetChart(newSupportSection,pStart,pEnd);CHKERRQ(ierr); 851776742edSToby Isaac ierr = PetscCalloc1(pEnd,&offsets);CHKERRQ(ierr); 8526461c1adSToby Isaac ierr = PetscMalloc1(pEnd,&numTrueSupp);CHKERRQ(ierr); 8536461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 8546461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 855776742edSToby Isaac * parent(q) */ 856776742edSToby Isaac for (d = 0; d <= depth; d++) { 857776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 858776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 859776742edSToby Isaac PetscInt dof, q, qdof, parent; 860776742edSToby Isaac 8616461c1adSToby Isaac ierr = DMPlexGetTrueSupportSize(dm,p,&dof,numTrueSupp);CHKERRQ(ierr); 862776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection, p, dof);CHKERRQ(ierr); 863776742edSToby Isaac q = p; 864776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 865776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 866776742edSToby Isaac q = parent; 867776742edSToby Isaac 8686461c1adSToby Isaac ierr = DMPlexGetTrueSupportSize(dm,q,&qdof,numTrueSupp);CHKERRQ(ierr); 869776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,p,qdof);CHKERRQ(ierr); 870776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,q,dof);CHKERRQ(ierr); 871776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 872776742edSToby Isaac } 873776742edSToby Isaac } 874776742edSToby Isaac } 875776742edSToby Isaac ierr = PetscSectionSetUp(newSupportSection);CHKERRQ(ierr); 876776742edSToby Isaac ierr = PetscSectionGetStorageSize(newSupportSection,&newSize);CHKERRQ(ierr); 877776742edSToby Isaac ierr = PetscMalloc1(newSize,&newSupports);CHKERRQ(ierr); 878776742edSToby Isaac for (d = 0; d <= depth; d++) { 879776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 880776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 881776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 882776742edSToby Isaac 883776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 884776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 885776742edSToby Isaac ierr = PetscSectionGetDof(newSupportSection, p, &newDof);CHKERRQ(ierr); 886776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, p, &newOff);CHKERRQ(ierr); 887776742edSToby Isaac for (i = 0; i < dof; i++) { 8886461c1adSToby Isaac PetscInt numCones, j; 8896461c1adSToby Isaac const PetscInt *cone; 8906461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 8916461c1adSToby Isaac 8926461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr); 8936461c1adSToby Isaac ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr); 8946461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8956461c1adSToby Isaac if (cone[j] == p) break; 8966461c1adSToby Isaac } 8976461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = q; 898776742edSToby Isaac } 899776742edSToby Isaac mesh->maxSupportSize = PetscMax(mesh->maxSupportSize,newDof); 900776742edSToby Isaac 901776742edSToby Isaac q = p; 902776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 903776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 904776742edSToby Isaac q = parent; 905776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, q, &qdof);CHKERRQ(ierr); 906776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, q, &qoff);CHKERRQ(ierr); 907776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, q, &newqOff);CHKERRQ(ierr); 908776742edSToby Isaac for (i = 0; i < qdof; i++) { 9096461c1adSToby Isaac PetscInt numCones, j; 9106461c1adSToby Isaac const PetscInt *cone; 9116461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 9126461c1adSToby Isaac 9136461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr); 9146461c1adSToby Isaac ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr); 9156461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9166461c1adSToby Isaac if (cone[j] == q) break; 9176461c1adSToby Isaac } 9186461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = r; 919776742edSToby Isaac } 920776742edSToby Isaac for (i = 0; i < dof; i++) { 9216461c1adSToby Isaac PetscInt numCones, j; 9226461c1adSToby Isaac const PetscInt *cone; 9236461c1adSToby Isaac PetscInt r = mesh->supports[off + i]; 9246461c1adSToby Isaac 9256461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr); 9266461c1adSToby Isaac ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr); 9276461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9286461c1adSToby Isaac if (cone[j] == p) break; 9296461c1adSToby Isaac } 9306461c1adSToby Isaac if (j < numCones) newSupports[newqOff+offsets[q]++] = r; 931776742edSToby Isaac } 932776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 933776742edSToby Isaac } 934776742edSToby Isaac } 935776742edSToby Isaac } 936776742edSToby Isaac ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 937776742edSToby Isaac mesh->supportSection = newSupportSection; 938776742edSToby Isaac ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 939776742edSToby Isaac mesh->supports = newSupports; 940776742edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 9416461c1adSToby Isaac ierr = PetscFree(numTrueSupp);CHKERRQ(ierr); 942776742edSToby Isaac 943776742edSToby Isaac PetscFunctionReturn(0); 944776742edSToby Isaac } 945776742edSToby Isaac 946f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM,PetscSection,PetscSection,Mat); 947f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM,PetscSection,PetscSection,Mat); 948f7c74593SToby Isaac 949776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 950f9f063d4SToby Isaac { 951f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 952f9f063d4SToby Isaac DM refTree; 953f9f063d4SToby Isaac PetscInt size; 954f9f063d4SToby Isaac PetscErrorCode ierr; 955f9f063d4SToby Isaac 956f9f063d4SToby Isaac PetscFunctionBegin; 957f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 958f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 959f9f063d4SToby Isaac ierr = PetscObjectReference((PetscObject)parentSection);CHKERRQ(ierr); 960f9f063d4SToby Isaac ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 961f9f063d4SToby Isaac mesh->parentSection = parentSection; 962f9f063d4SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&size);CHKERRQ(ierr); 963f9f063d4SToby Isaac if (parents != mesh->parents) { 964f9f063d4SToby Isaac ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 965f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->parents);CHKERRQ(ierr); 966580bdb30SBarry Smith ierr = PetscArraycpy(mesh->parents, parents, size);CHKERRQ(ierr); 967f9f063d4SToby Isaac } 968f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 969f9f063d4SToby Isaac ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 970f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->childIDs);CHKERRQ(ierr); 971580bdb30SBarry Smith ierr = PetscArraycpy(mesh->childIDs, childIDs, size);CHKERRQ(ierr); 972f9f063d4SToby Isaac } 973f9f063d4SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 974f9f063d4SToby Isaac if (refTree) { 975f9f063d4SToby Isaac DMLabel canonLabel; 976f9f063d4SToby Isaac 977c58f1c22SToby Isaac ierr = DMGetLabel(refTree,"canonical",&canonLabel);CHKERRQ(ierr); 978f9f063d4SToby Isaac if (canonLabel) { 979f9f063d4SToby Isaac PetscInt i; 980f9f063d4SToby Isaac 981f9f063d4SToby Isaac for (i = 0; i < size; i++) { 982f9f063d4SToby Isaac PetscInt canon; 983f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon);CHKERRQ(ierr); 984f9f063d4SToby Isaac if (canon >= 0) { 985f9f063d4SToby Isaac mesh->childIDs[i] = canon; 986f9f063d4SToby Isaac } 987f9f063d4SToby Isaac } 988f9f063d4SToby Isaac } 989f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 9906e0288c8SStefano Zampini } else { 991f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 992f9f063d4SToby Isaac } 993f9f063d4SToby Isaac ierr = DMPlexTreeSymmetrize(dm);CHKERRQ(ierr); 994f9f063d4SToby Isaac if (computeCanonical) { 995f9f063d4SToby Isaac PetscInt d, dim; 996f9f063d4SToby Isaac 997f9f063d4SToby Isaac /* add the canonical label */ 99828f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 999c58f1c22SToby Isaac ierr = DMCreateLabel(dm,"canonical");CHKERRQ(ierr); 1000f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 1001f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 1002f9f063d4SToby Isaac const PetscInt *cChildren; 1003f9f063d4SToby Isaac 1004f9f063d4SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 1005f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1006f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&cNumChildren,&cChildren);CHKERRQ(ierr); 1007f9f063d4SToby Isaac if (cNumChildren) { 1008f9f063d4SToby Isaac canon = p; 1009f9f063d4SToby Isaac break; 1010f9f063d4SToby Isaac } 1011f9f063d4SToby Isaac } 1012f9f063d4SToby Isaac if (canon == -1) continue; 1013f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1014f9f063d4SToby Isaac PetscInt numChildren, i; 1015f9f063d4SToby Isaac const PetscInt *children; 1016f9f063d4SToby Isaac 1017f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&numChildren,&children);CHKERRQ(ierr); 1018f9f063d4SToby Isaac if (numChildren) { 1019f9f063d4SToby 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); 1020c58f1c22SToby Isaac ierr = DMSetLabelValue(dm,"canonical",p,canon);CHKERRQ(ierr); 1021f9f063d4SToby Isaac for (i = 0; i < numChildren; i++) { 1022c58f1c22SToby Isaac ierr = DMSetLabelValue(dm,"canonical",children[i],cChildren[i]);CHKERRQ(ierr); 1023f9f063d4SToby Isaac } 1024f9f063d4SToby Isaac } 1025f9f063d4SToby Isaac } 1026f9f063d4SToby Isaac } 1027f9f063d4SToby Isaac } 1028776742edSToby Isaac if (exchangeSupports) { 1029776742edSToby Isaac ierr = DMPlexTreeExchangeSupports(dm);CHKERRQ(ierr); 1030776742edSToby Isaac } 1031f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 1032f7c74593SToby Isaac /* reset anchors */ 1033f7c74593SToby Isaac ierr = DMPlexSetAnchors(dm,NULL,NULL);CHKERRQ(ierr); 1034f9f063d4SToby Isaac PetscFunctionReturn(0); 1035f9f063d4SToby Isaac } 1036f9f063d4SToby Isaac 10370b7167a0SToby Isaac /*@ 10380b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 10390b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 10400b7167a0SToby Isaac tree root. 10410b7167a0SToby Isaac 10420b7167a0SToby Isaac Collective on dm 10430b7167a0SToby Isaac 10440b7167a0SToby Isaac Input Parameters: 10450b7167a0SToby Isaac + dm - the DMPlex object 10460b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 10470b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 10480b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 10490b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 10500b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 10510b7167a0SToby Isaac 10520b7167a0SToby Isaac Level: intermediate 10530b7167a0SToby Isaac 1054a17985deSToby Isaac .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 10550b7167a0SToby Isaac @*/ 1056b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 10570b7167a0SToby Isaac { 10580b7167a0SToby Isaac PetscErrorCode ierr; 10590b7167a0SToby Isaac 10600b7167a0SToby Isaac PetscFunctionBegin; 1061776742edSToby Isaac ierr = DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 10620b7167a0SToby Isaac PetscFunctionReturn(0); 10630b7167a0SToby Isaac } 10640b7167a0SToby Isaac 1065b2f41788SToby Isaac /*@ 1066b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 1067b2f41788SToby Isaac Collective on dm 1068b2f41788SToby Isaac 1069b2f41788SToby Isaac Input Parameters: 1070b2f41788SToby Isaac . dm - the DMPlex object 1071b2f41788SToby Isaac 1072b2f41788SToby Isaac Output Parameters: 1073b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1074b2f41788SToby Isaac offset indexes the parent and childID list 1075b2f41788SToby Isaac . parents - a list of the point parents 1076b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1077b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1078b2f41788SToby Isaac . childSection - the inverse of the parent section 1079b2f41788SToby Isaac - children - a list of the point children 1080b2f41788SToby Isaac 1081b2f41788SToby Isaac Level: intermediate 1082b2f41788SToby Isaac 1083a17985deSToby Isaac .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 1084b2f41788SToby Isaac @*/ 1085b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1086b2f41788SToby Isaac { 1087b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1088b2f41788SToby Isaac 1089b2f41788SToby Isaac PetscFunctionBegin; 1090b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1091b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1092b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1093b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1094b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1095b2f41788SToby Isaac if (children) *children = mesh->children; 1096b2f41788SToby Isaac PetscFunctionReturn(0); 1097b2f41788SToby Isaac } 1098b2f41788SToby Isaac 1099d961a43aSToby Isaac /*@ 1100eaf898f9SPatrick Sanan DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the DAG) 1101d961a43aSToby Isaac 1102d961a43aSToby Isaac Input Parameters: 1103d961a43aSToby Isaac + dm - the DMPlex object 1104d961a43aSToby Isaac - point - the query point 1105d961a43aSToby Isaac 1106d961a43aSToby Isaac Output Parameters: 1107d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 1108d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 1109d961a43aSToby Isaac does not have a parent 1110d961a43aSToby Isaac 1111d961a43aSToby Isaac Level: intermediate 1112d961a43aSToby Isaac 1113d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren() 1114d961a43aSToby Isaac @*/ 1115d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1116d961a43aSToby Isaac { 1117d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1118d961a43aSToby Isaac PetscSection pSec; 1119d961a43aSToby Isaac PetscErrorCode ierr; 1120d961a43aSToby Isaac 1121d961a43aSToby Isaac PetscFunctionBegin; 1122d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1123d961a43aSToby Isaac pSec = mesh->parentSection; 1124d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1125d961a43aSToby Isaac PetscInt dof; 1126d961a43aSToby Isaac 1127d961a43aSToby Isaac ierr = PetscSectionGetDof (pSec, point, &dof);CHKERRQ(ierr); 1128d961a43aSToby Isaac if (dof) { 1129d961a43aSToby Isaac PetscInt off; 1130d961a43aSToby Isaac 1131d961a43aSToby Isaac ierr = PetscSectionGetOffset (pSec, point, &off);CHKERRQ(ierr); 1132d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1133d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 1134d961a43aSToby Isaac PetscFunctionReturn(0); 1135d961a43aSToby Isaac } 1136d961a43aSToby Isaac } 1137d961a43aSToby Isaac if (parent) { 1138d961a43aSToby Isaac *parent = point; 1139d961a43aSToby Isaac } 1140d961a43aSToby Isaac if (childID) { 1141d961a43aSToby Isaac *childID = 0; 1142d961a43aSToby Isaac } 1143d961a43aSToby Isaac PetscFunctionReturn(0); 1144d961a43aSToby Isaac } 1145d961a43aSToby Isaac 1146d961a43aSToby Isaac /*@C 1147eaf898f9SPatrick Sanan DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the DAG) 1148d961a43aSToby Isaac 1149d961a43aSToby Isaac Input Parameters: 1150d961a43aSToby Isaac + dm - the DMPlex object 1151d961a43aSToby Isaac - point - the query point 1152d961a43aSToby Isaac 1153d961a43aSToby Isaac Output Parameters: 1154d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 1155d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 1156d961a43aSToby Isaac 1157d961a43aSToby Isaac Level: intermediate 1158d961a43aSToby Isaac 1159d961a43aSToby Isaac Fortran Notes: 1160d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1161d961a43aSToby Isaac include petsc.h90 in your code. 1162d961a43aSToby Isaac 1163d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent() 1164d961a43aSToby Isaac @*/ 1165d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1166d961a43aSToby Isaac { 1167d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1168d961a43aSToby Isaac PetscSection childSec; 1169d961a43aSToby Isaac PetscInt dof = 0; 1170d961a43aSToby Isaac PetscErrorCode ierr; 1171d961a43aSToby Isaac 1172d961a43aSToby Isaac PetscFunctionBegin; 1173d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1174d961a43aSToby Isaac childSec = mesh->childSection; 1175d961a43aSToby Isaac if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 1176d961a43aSToby Isaac ierr = PetscSectionGetDof (childSec, point, &dof);CHKERRQ(ierr); 1177d961a43aSToby Isaac } 1178d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1179d961a43aSToby Isaac if (children) { 1180d961a43aSToby Isaac if (dof) { 1181d961a43aSToby Isaac PetscInt off; 1182d961a43aSToby Isaac 1183d961a43aSToby Isaac ierr = PetscSectionGetOffset (childSec, point, &off);CHKERRQ(ierr); 1184d961a43aSToby Isaac *children = &mesh->children[off]; 1185d961a43aSToby Isaac } 1186d961a43aSToby Isaac else { 1187d961a43aSToby Isaac *children = NULL; 1188d961a43aSToby Isaac } 1189d961a43aSToby Isaac } 1190d961a43aSToby Isaac PetscFunctionReturn(0); 1191d961a43aSToby Isaac } 11920c37af3bSToby Isaac 119352a3aeb4SToby Isaac static PetscErrorCode EvaluateBasis(PetscSpace space, PetscInt nBasis, PetscInt nFunctionals, PetscInt nComps, PetscInt nPoints, const PetscInt *pointsPerFn, const PetscReal *points, const PetscReal *weights, PetscReal *work, Mat basisAtPoints) 1194b3a4bf2aSToby Isaac { 119552a3aeb4SToby Isaac PetscInt f, b, p, c, offset, qPoints; 1196b3a4bf2aSToby Isaac PetscErrorCode ierr; 1197b3a4bf2aSToby Isaac 1198b3a4bf2aSToby Isaac PetscFunctionBegin; 1199b3a4bf2aSToby Isaac ierr = PetscSpaceEvaluate(space,nPoints,points,work,NULL,NULL);CHKERRQ(ierr); 120052a3aeb4SToby Isaac for (f = 0, offset = 0; f < nFunctionals; f++) { 120152a3aeb4SToby Isaac qPoints = pointsPerFn[f]; 120252a3aeb4SToby Isaac for (b = 0; b < nBasis; b++) { 1203b3a4bf2aSToby Isaac PetscScalar val = 0.; 1204b3a4bf2aSToby Isaac 120552a3aeb4SToby Isaac for (p = 0; p < qPoints; p++) { 120652a3aeb4SToby Isaac for (c = 0; c < nComps; c++) { 120752a3aeb4SToby Isaac val += work[((offset + p) * nBasis + b) * nComps + c] * weights[(offset + p) * nComps + c]; 1208b3a4bf2aSToby Isaac } 120952a3aeb4SToby Isaac } 121052a3aeb4SToby Isaac ierr = MatSetValue(basisAtPoints,b,f,val,INSERT_VALUES);CHKERRQ(ierr); 1211b3a4bf2aSToby Isaac } 1212b3a4bf2aSToby Isaac offset += qPoints; 1213b3a4bf2aSToby Isaac } 1214b3a4bf2aSToby Isaac ierr = MatAssemblyBegin(basisAtPoints,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1215b3a4bf2aSToby Isaac ierr = MatAssemblyEnd(basisAtPoints,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1216b3a4bf2aSToby Isaac PetscFunctionReturn(0); 1217b3a4bf2aSToby Isaac } 1218b3a4bf2aSToby Isaac 1219f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 12200c37af3bSToby Isaac { 12210c37af3bSToby Isaac PetscDS ds; 12220c37af3bSToby Isaac PetscInt spdim; 12230c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 12240c37af3bSToby Isaac const PetscInt *anchors; 1225f7c74593SToby Isaac PetscSection aSec; 12260c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 12270c37af3bSToby Isaac IS aIS; 12280c37af3bSToby Isaac PetscErrorCode ierr; 12290c37af3bSToby Isaac 12300c37af3bSToby Isaac PetscFunctionBegin; 12310c37af3bSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 12320c37af3bSToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 12330c37af3bSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 12340c37af3bSToby Isaac ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 1235a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 12360c37af3bSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 12370c37af3bSToby Isaac ierr = PetscSectionGetChart(cSec,&conStart,&conEnd);CHKERRQ(ierr); 123828f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&spdim);CHKERRQ(ierr); 12390c37af3bSToby Isaac ierr = PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent);CHKERRQ(ierr); 12400c37af3bSToby Isaac 12410c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 12420dd1b1feSToby Isaac PetscObject disc; 12430dd1b1feSToby Isaac PetscClassId id; 1244b3a4bf2aSToby Isaac PetscSpace bspace; 1245b3a4bf2aSToby Isaac PetscDualSpace dspace; 12469c3cf19fSMatthew G. Knepley PetscInt i, j, k, nPoints, Nc, offset; 124752a3aeb4SToby Isaac PetscInt fSize, maxDof; 1248b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 12491683a169SBarry Smith PetscScalar *scwork; 12501683a169SBarry Smith const PetscScalar *X; 12512c44ad04SToby Isaac PetscInt *sizes, *workIndRow, *workIndCol; 12520c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 12532c44ad04SToby Isaac const PetscInt *numDof = NULL; 1254085f0adfSToby Isaac const PetscInt ***perms = NULL; 1255085f0adfSToby Isaac const PetscScalar ***flips = NULL; 12560c37af3bSToby Isaac 12570dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 12580dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 12590dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1260b3a4bf2aSToby Isaac PetscFE fe = (PetscFE) disc; 1261b3a4bf2aSToby Isaac 1262b3a4bf2aSToby Isaac ierr = PetscFEGetBasisSpace(fe,&bspace);CHKERRQ(ierr); 1263b3a4bf2aSToby Isaac ierr = PetscFEGetDualSpace(fe,&dspace);CHKERRQ(ierr); 1264b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetDimension(dspace,&fSize);CHKERRQ(ierr); 126552a3aeb4SToby Isaac ierr = PetscFEGetNumComponents(fe,&Nc);CHKERRQ(ierr); 12660dd1b1feSToby Isaac } 12670dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 1268b3a4bf2aSToby Isaac PetscFV fv = (PetscFV) disc; 1269b3a4bf2aSToby Isaac 127052a3aeb4SToby Isaac ierr = PetscFVGetNumComponents(fv,&Nc);CHKERRQ(ierr); 1271b3a4bf2aSToby Isaac ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)fv),&bspace);CHKERRQ(ierr); 1272b3a4bf2aSToby Isaac ierr = PetscSpaceSetType(bspace,PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr); 1273d39dd5f5SToby Isaac ierr = PetscSpaceSetDegree(bspace,0,PETSC_DETERMINE);CHKERRQ(ierr); 127452a3aeb4SToby Isaac ierr = PetscSpaceSetNumComponents(bspace,Nc);CHKERRQ(ierr); 1275157782e2SToby Isaac ierr = PetscSpaceSetNumVariables(bspace,spdim);CHKERRQ(ierr); 1276b3a4bf2aSToby Isaac ierr = PetscSpaceSetUp(bspace);CHKERRQ(ierr); 1277b3a4bf2aSToby Isaac ierr = PetscFVGetDualSpace(fv,&dspace);CHKERRQ(ierr); 1278b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetDimension(dspace,&fSize);CHKERRQ(ierr); 12790dd1b1feSToby Isaac } 12800dd1b1feSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 12812c44ad04SToby Isaac ierr = PetscDualSpaceGetNumDof(dspace,&numDof);CHKERRQ(ierr); 12822c44ad04SToby Isaac for (i = 0, maxDof = 0; i <= spdim; i++) {maxDof = PetscMax(maxDof,numDof[i]);} 1283085f0adfSToby Isaac ierr = PetscDualSpaceGetSymmetries(dspace,&perms,&flips);CHKERRQ(ierr); 12840dd1b1feSToby Isaac 12850c37af3bSToby Isaac ierr = MatCreate(PETSC_COMM_SELF,&Amat);CHKERRQ(ierr); 12860c37af3bSToby Isaac ierr = MatSetSizes(Amat,fSize,fSize,fSize,fSize);CHKERRQ(ierr); 12870c37af3bSToby Isaac ierr = MatSetType(Amat,MATSEQDENSE);CHKERRQ(ierr); 12880c37af3bSToby Isaac ierr = MatSetUp(Amat);CHKERRQ(ierr); 12890c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat);CHKERRQ(ierr); 12900c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat);CHKERRQ(ierr); 12910c37af3bSToby Isaac nPoints = 0; 12920c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 129352a3aeb4SToby Isaac PetscInt qPoints, thisNc; 12940c37af3bSToby Isaac PetscQuadrature quad; 12950c37af3bSToby Isaac 1296b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetFunctional(dspace,i,&quad);CHKERRQ(ierr); 129752a3aeb4SToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&thisNc,&qPoints,NULL,NULL);CHKERRQ(ierr); 129852a3aeb4SToby Isaac if (thisNc != Nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Functional dim %D does not much basis dim %D\n",thisNc,Nc); 12990c37af3bSToby Isaac nPoints += qPoints; 13000c37af3bSToby Isaac } 130152a3aeb4SToby Isaac ierr = PetscMalloc7(fSize,&sizes,nPoints*Nc,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal,nPoints*fSize*Nc,&work,maxDof,&workIndRow,maxDof,&workIndCol);CHKERRQ(ierr); 13022c44ad04SToby Isaac ierr = PetscMalloc1(maxDof * maxDof,&scwork);CHKERRQ(ierr); 13030c37af3bSToby Isaac offset = 0; 13040c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 13050c37af3bSToby Isaac PetscInt qPoints; 13060c37af3bSToby Isaac const PetscReal *p, *w; 13070c37af3bSToby Isaac PetscQuadrature quad; 13080c37af3bSToby Isaac 1309b3a4bf2aSToby Isaac ierr = PetscDualSpaceGetFunctional(dspace,i,&quad);CHKERRQ(ierr); 131052a3aeb4SToby Isaac ierr = PetscQuadratureGetData(quad,NULL,NULL,&qPoints,&p,&w);CHKERRQ(ierr); 1311580bdb30SBarry Smith ierr = PetscArraycpy(weights+Nc*offset,w,Nc*qPoints);CHKERRQ(ierr); 1312580bdb30SBarry Smith ierr = PetscArraycpy(pointsRef+spdim*offset,p,spdim*qPoints);CHKERRQ(ierr); 1313b3a4bf2aSToby Isaac sizes[i] = qPoints; 13140c37af3bSToby Isaac offset += qPoints; 13150c37af3bSToby Isaac } 131652a3aeb4SToby Isaac ierr = EvaluateBasis(bspace,fSize,fSize,Nc,nPoints,sizes,pointsRef,weights,work,Amat);CHKERRQ(ierr); 13170c37af3bSToby Isaac ierr = MatLUFactor(Amat,NULL,NULL,NULL);CHKERRQ(ierr); 13180c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 13190c37af3bSToby Isaac PetscInt parent; 13200c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 13210c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 13220c37af3bSToby Isaac 13230c37af3bSToby Isaac ierr = DMPlexGetTreeParent(dm,c,&parent,NULL);CHKERRQ(ierr); 13240c37af3bSToby Isaac if (parent == c) continue; 13250c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13260c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13270c37af3bSToby Isaac PetscInt p = closure[2*i]; 13280c37af3bSToby Isaac PetscInt conDof; 13290c37af3bSToby Isaac 13300c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1331085f0adfSToby Isaac if (numFields) { 13320c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 13330c37af3bSToby Isaac } 13340c37af3bSToby Isaac else { 13350c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 13360c37af3bSToby Isaac } 13370c37af3bSToby Isaac if (conDof) break; 13380c37af3bSToby Isaac } 13390c37af3bSToby Isaac if (i == closureSize) { 13400c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13410c37af3bSToby Isaac continue; 13420c37af3bSToby Isaac } 13430c37af3bSToby Isaac 134473a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 134573a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent);CHKERRQ(ierr); 13460c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1347c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 1348c330f8ffSToby Isaac 1349c330f8ffSToby Isaac CoordinatesRefToReal(spdim, spdim, xi0, v0, J, &pointsRef[i*spdim],vtmp); 1350c330f8ffSToby Isaac CoordinatesRealToRef(spdim, spdim, xi0, v0parent, invJparent, vtmp, &pointsReal[i*spdim]); 13510c37af3bSToby Isaac } 135252a3aeb4SToby Isaac ierr = EvaluateBasis(bspace,fSize,fSize,Nc,nPoints,sizes,pointsReal,weights,work,Bmat);CHKERRQ(ierr); 13530c37af3bSToby Isaac ierr = MatMatSolve(Amat,Bmat,Xmat);CHKERRQ(ierr); 13541683a169SBarry Smith ierr = MatDenseGetArrayRead(Xmat,&X);CHKERRQ(ierr); 13550c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 13560c37af3bSToby Isaac ierr = PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets);CHKERRQ(ierr); 13570c37af3bSToby Isaac childOffsets[0] = 0; 13580c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13590c37af3bSToby Isaac PetscInt p = closure[2*i]; 13600c37af3bSToby Isaac PetscInt dof; 13610c37af3bSToby Isaac 1362085f0adfSToby Isaac if (numFields) { 13630c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 13640c37af3bSToby Isaac } 13650c37af3bSToby Isaac else { 13660c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 13670c37af3bSToby Isaac } 136852a3aeb4SToby Isaac childOffsets[i+1]=childOffsets[i]+dof; 13690c37af3bSToby Isaac } 13700c37af3bSToby Isaac parentOffsets[0] = 0; 13710c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 13720c37af3bSToby Isaac PetscInt p = closureP[2*i]; 13730c37af3bSToby Isaac PetscInt dof; 13740c37af3bSToby Isaac 1375085f0adfSToby Isaac if (numFields) { 13760c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 13770c37af3bSToby Isaac } 13780c37af3bSToby Isaac else { 13790c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 13800c37af3bSToby Isaac } 138152a3aeb4SToby Isaac parentOffsets[i+1]=parentOffsets[i]+dof; 13820c37af3bSToby Isaac } 13830c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13842c44ad04SToby Isaac PetscInt conDof, conOff, aDof, aOff, nWork; 13850c37af3bSToby Isaac PetscInt p = closure[2*i]; 13860c37af3bSToby Isaac PetscInt o = closure[2*i+1]; 1387085f0adfSToby Isaac const PetscInt *perm; 1388085f0adfSToby Isaac const PetscScalar *flip; 13890c37af3bSToby Isaac 13900c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1391085f0adfSToby Isaac if (numFields) { 13920c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 13930c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(cSec,p,f,&conOff);CHKERRQ(ierr); 13940c37af3bSToby Isaac } 13950c37af3bSToby Isaac else { 13960c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 13970c37af3bSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&conOff);CHKERRQ(ierr); 13980c37af3bSToby Isaac } 13990c37af3bSToby Isaac if (!conDof) continue; 1400085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL; 1401085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL; 14020c37af3bSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 14030c37af3bSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 14042c44ad04SToby Isaac nWork = childOffsets[i+1]-childOffsets[i]; 14050c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 14060c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 14070c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 14080c37af3bSToby Isaac 1409085f0adfSToby Isaac if (numFields) { 14100c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,a,f,&aSecDof);CHKERRQ(ierr); 14110c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(section,a,f,&aSecOff);CHKERRQ(ierr); 14120c37af3bSToby Isaac } 14130c37af3bSToby Isaac else { 14140c37af3bSToby Isaac ierr = PetscSectionGetDof(section,a,&aSecDof);CHKERRQ(ierr); 14150c37af3bSToby Isaac ierr = PetscSectionGetOffset(section,a,&aSecOff);CHKERRQ(ierr); 14160c37af3bSToby Isaac } 14170c37af3bSToby Isaac if (!aSecDof) continue; 14180c37af3bSToby Isaac 14190c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 14200c37af3bSToby Isaac PetscInt q = closureP[2*j]; 14210c37af3bSToby Isaac PetscInt oq = closureP[2*j+1]; 14222c44ad04SToby Isaac 14232c44ad04SToby Isaac if (q == a) { 142452a3aeb4SToby Isaac PetscInt r, s, nWorkP; 1425085f0adfSToby Isaac const PetscInt *permP; 1426085f0adfSToby Isaac const PetscScalar *flipP; 1427085f0adfSToby Isaac 1428085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL; 1429085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL; 14302c44ad04SToby Isaac nWorkP = parentOffsets[j+1]-parentOffsets[j]; 14312c44ad04SToby Isaac /* get a copy of the child-to-anchor portion of the matrix, and transpose so that rows correspond to the 14321683a169SBarry Smith * child and columns correspond to the anchor: BUT the maxrix returned by MatDenseGetArrayRead() is 14332c44ad04SToby Isaac * column-major, so transpose-transpose = do nothing */ 14342c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14352c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14362c44ad04SToby Isaac scwork[r * nWorkP + s] = X[fSize * (r + childOffsets[i]) + (s + parentOffsets[j])]; 14372c44ad04SToby Isaac } 14382c44ad04SToby Isaac } 143952a3aeb4SToby Isaac for (r = 0; r < nWork; r++) {workIndRow[perm ? perm[r] : r] = conOff + r;} 144052a3aeb4SToby Isaac for (s = 0; s < nWorkP; s++) {workIndCol[permP ? permP[s] : s] = aSecOff + s;} 14412c44ad04SToby Isaac if (flip) { 14422c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14432c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14442c44ad04SToby Isaac scwork[r * nWorkP + s] *= flip[r]; 14452c44ad04SToby Isaac } 14462c44ad04SToby Isaac } 14472c44ad04SToby Isaac } 14482c44ad04SToby Isaac if (flipP) { 14492c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14502c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14512c44ad04SToby Isaac scwork[r * nWorkP + s] *= flipP[s]; 14522c44ad04SToby Isaac } 14532c44ad04SToby Isaac } 14542c44ad04SToby Isaac } 14552c44ad04SToby Isaac ierr = MatSetValues(cMat,nWork,workIndRow,nWorkP,workIndCol,scwork,INSERT_VALUES);CHKERRQ(ierr); 14562c44ad04SToby Isaac break; 14570c37af3bSToby Isaac } 14580c37af3bSToby Isaac } 14590c37af3bSToby Isaac } 14600c37af3bSToby Isaac } 14611683a169SBarry Smith ierr = MatDenseRestoreArrayRead(Xmat,&X);CHKERRQ(ierr); 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); 14692c44ad04SToby Isaac ierr = PetscFree(scwork);CHKERRQ(ierr); 14702c44ad04SToby Isaac ierr = PetscFree7(sizes,weights,pointsRef,pointsReal,work,workIndRow,workIndCol);CHKERRQ(ierr); 1471b3a4bf2aSToby Isaac if (id == PETSCFV_CLASSID) { 1472b3a4bf2aSToby Isaac ierr = PetscSpaceDestroy(&bspace);CHKERRQ(ierr); 1473b3a4bf2aSToby Isaac } 14740c37af3bSToby Isaac } 14750c37af3bSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14760c37af3bSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14770c37af3bSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent);CHKERRQ(ierr); 14780c37af3bSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 14790c37af3bSToby Isaac 14800c37af3bSToby Isaac PetscFunctionReturn(0); 14810c37af3bSToby Isaac } 148295a0b26dSToby Isaac 148321968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 148495a0b26dSToby Isaac { 1485f7c74593SToby Isaac Mat refCmat; 148621968bf8SToby Isaac PetscDS ds; 1487085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 148821968bf8SToby Isaac PetscScalar ***refPointFieldMats; 148921968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 149021968bf8SToby Isaac IS refAnIS; 149121968bf8SToby Isaac const PetscInt *refAnchors; 1492085f0adfSToby Isaac const PetscInt **perms; 1493085f0adfSToby Isaac const PetscScalar **flips; 149495a0b26dSToby Isaac PetscErrorCode ierr; 149595a0b26dSToby Isaac 149695a0b26dSToby Isaac PetscFunctionBegin; 149721968bf8SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 149895a0b26dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 1499085f0adfSToby Isaac maxFields = PetscMax(1,numFields); 1500f7c74593SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 1501a17985deSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 150295a0b26dSToby Isaac ierr = ISGetIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 150392fd8e1eSJed Brown ierr = DMGetLocalSection(refTree,&refSection);CHKERRQ(ierr); 150495a0b26dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 150595a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr); 150695a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldN);CHKERRQ(ierr); 150795a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 150895a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 150995a0b26dSToby Isaac ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr); 151095a0b26dSToby Isaac ierr = PetscMalloc1(maxDof*maxAnDof,&cols);CHKERRQ(ierr); 151195a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 151295a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 151395a0b26dSToby Isaac 151495a0b26dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 151595a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 151695a0b26dSToby Isaac if (!pDof || parent == p) continue; 151795a0b26dSToby Isaac 1518085f0adfSToby Isaac ierr = PetscMalloc1(maxFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr); 1519085f0adfSToby Isaac ierr = PetscCalloc1(maxFields,&refPointFieldN[p-pRefStart]);CHKERRQ(ierr); 152095a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1521085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1522085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i; 152395a0b26dSToby Isaac 1524085f0adfSToby Isaac if (f < numFields) { 152595a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 152695a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr); 1527085f0adfSToby Isaac ierr = PetscSectionGetFieldPointSyms(refSection,f,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1528085f0adfSToby Isaac } else { 152995a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 153095a0b26dSToby Isaac ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr); 1531085f0adfSToby Isaac ierr = PetscSectionGetPointSyms(refSection,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 153295a0b26dSToby Isaac } 153395a0b26dSToby Isaac 153495a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 153595a0b26dSToby Isaac rows[r] = cOff + r; 153695a0b26dSToby Isaac } 153795a0b26dSToby Isaac numCols = 0; 153895a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 153995a0b26dSToby Isaac PetscInt q = closure[2*i]; 154095a0b26dSToby Isaac PetscInt aDof, aOff, j; 1541085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 154295a0b26dSToby Isaac 1543085f0adfSToby Isaac if (numFields) { 154495a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refSection,q,f,&aDof);CHKERRQ(ierr); 154595a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,q,f,&aOff);CHKERRQ(ierr); 154695a0b26dSToby Isaac } 154795a0b26dSToby Isaac else { 154895a0b26dSToby Isaac ierr = PetscSectionGetDof(refSection,q,&aDof);CHKERRQ(ierr); 154995a0b26dSToby Isaac ierr = PetscSectionGetOffset(refSection,q,&aOff);CHKERRQ(ierr); 155095a0b26dSToby Isaac } 155195a0b26dSToby Isaac 155295a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 1553085f0adfSToby Isaac cols[numCols++] = aOff + (perm ? perm[j] : j); 155495a0b26dSToby Isaac } 155595a0b26dSToby Isaac } 155695a0b26dSToby Isaac refPointFieldN[p-pRefStart][f] = numCols; 155795a0b26dSToby Isaac ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 155895a0b26dSToby Isaac ierr = MatGetValues(refCmat,cDof,rows,numCols,cols,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 1559085f0adfSToby Isaac if (flips) { 1560085f0adfSToby Isaac PetscInt colOff = 0; 1561085f0adfSToby Isaac 1562085f0adfSToby Isaac for (i = 0; i < closureSize; i++) { 1563085f0adfSToby Isaac PetscInt q = closure[2*i]; 1564085f0adfSToby Isaac PetscInt aDof, aOff, j; 1565085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 1566085f0adfSToby Isaac 1567085f0adfSToby Isaac if (numFields) { 1568085f0adfSToby Isaac ierr = PetscSectionGetFieldDof(refSection,q,f,&aDof);CHKERRQ(ierr); 1569085f0adfSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,q,f,&aOff);CHKERRQ(ierr); 1570085f0adfSToby Isaac } 1571085f0adfSToby Isaac else { 1572085f0adfSToby Isaac ierr = PetscSectionGetDof(refSection,q,&aDof);CHKERRQ(ierr); 1573085f0adfSToby Isaac ierr = PetscSectionGetOffset(refSection,q,&aOff);CHKERRQ(ierr); 1574085f0adfSToby Isaac } 1575085f0adfSToby Isaac if (flip) { 1576085f0adfSToby Isaac PetscInt k; 1577085f0adfSToby Isaac for (k = 0; k < cDof; k++) { 1578085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1579085f0adfSToby Isaac refPointFieldMats[p-pRefStart][f][k * numCols + colOff + j] *= flip[j]; 1580085f0adfSToby Isaac } 1581085f0adfSToby Isaac } 1582085f0adfSToby Isaac } 1583085f0adfSToby Isaac colOff += aDof; 1584085f0adfSToby Isaac } 1585085f0adfSToby Isaac } 1586085f0adfSToby Isaac if (numFields) { 1587085f0adfSToby Isaac ierr = PetscSectionRestoreFieldPointSyms(refSection,f,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1588085f0adfSToby Isaac } else { 1589085f0adfSToby Isaac ierr = PetscSectionRestorePointSyms(refSection,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1590085f0adfSToby Isaac } 159195a0b26dSToby Isaac } 159295a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 159395a0b26dSToby Isaac } 159421968bf8SToby Isaac *childrenMats = refPointFieldMats; 159521968bf8SToby Isaac *childrenN = refPointFieldN; 159621968bf8SToby Isaac ierr = ISRestoreIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 159721968bf8SToby Isaac ierr = PetscFree(rows);CHKERRQ(ierr); 159821968bf8SToby Isaac ierr = PetscFree(cols);CHKERRQ(ierr); 159921968bf8SToby Isaac PetscFunctionReturn(0); 160021968bf8SToby Isaac } 160121968bf8SToby Isaac 160221968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 160321968bf8SToby Isaac { 160421968bf8SToby Isaac PetscDS ds; 160521968bf8SToby Isaac PetscInt **refPointFieldN; 160621968bf8SToby Isaac PetscScalar ***refPointFieldMats; 1607085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f; 160821968bf8SToby Isaac PetscSection refConSec; 160921968bf8SToby Isaac PetscErrorCode ierr; 161021968bf8SToby Isaac 161121968bf8SToby Isaac PetscFunctionBegin; 161221968bf8SToby Isaac refPointFieldN = *childrenN; 161321968bf8SToby Isaac *childrenN = NULL; 161421968bf8SToby Isaac refPointFieldMats = *childrenMats; 161521968bf8SToby Isaac *childrenMats = NULL; 161621968bf8SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 161721968bf8SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 1618367003a6SStefano Zampini maxFields = PetscMax(1,numFields); 161921968bf8SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 1620e44e4e7fSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 162121968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 162221968bf8SToby Isaac PetscInt parent, pDof; 162321968bf8SToby Isaac 162421968bf8SToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 162521968bf8SToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 162621968bf8SToby Isaac if (!pDof || parent == p) continue; 162721968bf8SToby Isaac 1628085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 162921968bf8SToby Isaac PetscInt cDof; 163021968bf8SToby Isaac 1631085f0adfSToby Isaac if (numFields) { 163221968bf8SToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 163321968bf8SToby Isaac } 163421968bf8SToby Isaac else { 163521968bf8SToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 163621968bf8SToby Isaac } 163721968bf8SToby Isaac 163821968bf8SToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr); 163921968bf8SToby Isaac } 164021968bf8SToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr); 164121968bf8SToby Isaac ierr = PetscFree(refPointFieldN[p - pRefStart]);CHKERRQ(ierr); 164221968bf8SToby Isaac } 164321968bf8SToby Isaac ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr); 164421968bf8SToby Isaac ierr = PetscFree(refPointFieldN);CHKERRQ(ierr); 164521968bf8SToby Isaac PetscFunctionReturn(0); 164621968bf8SToby Isaac } 164721968bf8SToby Isaac 164821968bf8SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 164921968bf8SToby Isaac { 165021968bf8SToby Isaac DM refTree; 165121968bf8SToby Isaac PetscDS ds; 165221968bf8SToby Isaac Mat refCmat; 1653085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 165421968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 165521968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 165621968bf8SToby Isaac IS refAnIS, anIS; 165721968bf8SToby Isaac const PetscInt *anchors; 165821968bf8SToby Isaac PetscErrorCode ierr; 165921968bf8SToby Isaac 166021968bf8SToby Isaac PetscFunctionBegin; 166121968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 166221968bf8SToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 166321968bf8SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 1664085f0adfSToby Isaac maxFields = PetscMax(1,numFields); 166521968bf8SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 1666e5e52638SMatthew G. Knepley ierr = DMCopyDisc(dm,refTree);CHKERRQ(ierr); 166721968bf8SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 166821968bf8SToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 166921968bf8SToby Isaac ierr = DMPlexGetAnchors(dm,&anSec,&anIS);CHKERRQ(ierr); 167021968bf8SToby Isaac ierr = ISGetIndices(anIS,&anchors);CHKERRQ(ierr); 167121968bf8SToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 167221968bf8SToby Isaac ierr = PetscSectionGetChart(conSec,&conStart,&conEnd);CHKERRQ(ierr); 167321968bf8SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 167421968bf8SToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 167521968bf8SToby Isaac ierr = PetscMalloc1(maxDof*maxDof*maxAnDof,&pointWork);CHKERRQ(ierr); 167621968bf8SToby Isaac 167721968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 167821968bf8SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 167995a0b26dSToby Isaac 168095a0b26dSToby Isaac /* step 2: compute the preorder */ 168195a0b26dSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 168295a0b26dSToby Isaac ierr = PetscMalloc2(pEnd-pStart,&perm,pEnd-pStart,&iperm);CHKERRQ(ierr); 168395a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 168495a0b26dSToby Isaac perm[p - pStart] = p; 168595a0b26dSToby Isaac iperm[p - pStart] = p-pStart; 168695a0b26dSToby Isaac } 168795a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 168895a0b26dSToby Isaac PetscInt point = perm[p]; 168995a0b26dSToby Isaac PetscInt parent; 169095a0b26dSToby Isaac 169195a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 169295a0b26dSToby Isaac if (parent == point) { 169395a0b26dSToby Isaac p++; 169495a0b26dSToby Isaac } 169595a0b26dSToby Isaac else { 169695a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 169795a0b26dSToby Isaac 169895a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 169995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 170095a0b26dSToby Isaac PetscInt q = closure[2*i]; 170195a0b26dSToby Isaac if (iperm[q-pStart] > iperm[point-pStart]) { 170295a0b26dSToby Isaac /* swap */ 170395a0b26dSToby Isaac perm[p] = q; 170495a0b26dSToby Isaac perm[iperm[q-pStart]] = point; 170595a0b26dSToby Isaac iperm[point-pStart] = iperm[q-pStart]; 170695a0b26dSToby Isaac iperm[q-pStart] = p; 170795a0b26dSToby Isaac break; 170895a0b26dSToby Isaac } 170995a0b26dSToby Isaac } 171095a0b26dSToby Isaac size = closureSize; 171195a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 171295a0b26dSToby Isaac if (i == size) { 171395a0b26dSToby Isaac p++; 171495a0b26dSToby Isaac } 171595a0b26dSToby Isaac } 171695a0b26dSToby Isaac } 171795a0b26dSToby Isaac 171895a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 171995a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 172095a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 172195a0b26dSToby Isaac * values outside of the Mat first. 172295a0b26dSToby Isaac */ 172395a0b26dSToby Isaac { 172495a0b26dSToby Isaac PetscInt nRows, row, nnz; 172595a0b26dSToby Isaac PetscBool done; 172695a0b26dSToby Isaac const PetscInt *ia, *ja; 172795a0b26dSToby Isaac PetscScalar *vals; 172895a0b26dSToby Isaac 172995a0b26dSToby Isaac ierr = MatGetRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 173095a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not get RowIJ of constraint matrix"); 173195a0b26dSToby Isaac nnz = ia[nRows]; 173295a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 173395a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 173495a0b26dSToby Isaac ierr = PetscMalloc1(nnz,&vals);CHKERRQ(ierr); 173595a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 173695a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 173795a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 173895a0b26dSToby Isaac 173995a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,&childid);CHKERRQ(ierr); 174095a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 174195a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&pointDof);CHKERRQ(ierr); 174295a0b26dSToby Isaac if (!pointDof) continue; 174395a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1744085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1745085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 174695a0b26dSToby Isaac PetscScalar *pointMat; 1747085f0adfSToby Isaac const PetscInt **perms; 1748085f0adfSToby Isaac const PetscScalar **flips; 174995a0b26dSToby Isaac 1750085f0adfSToby Isaac if (numFields) { 175195a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,point,f,&cDof);CHKERRQ(ierr); 175295a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,point,f,&cOff);CHKERRQ(ierr); 175395a0b26dSToby Isaac } 175495a0b26dSToby Isaac else { 175595a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&cDof);CHKERRQ(ierr); 175695a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,point,&cOff);CHKERRQ(ierr); 175795a0b26dSToby Isaac } 175895a0b26dSToby Isaac if (!cDof) continue; 1759085f0adfSToby Isaac if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,closureSize,closure,&perms,&flips);CHKERRQ(ierr);} 1760085f0adfSToby Isaac else {ierr = PetscSectionGetPointSyms(section,closureSize,closure,&perms,&flips);CHKERRQ(ierr);} 176195a0b26dSToby Isaac 176295a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 176376bd3646SJed Brown if (PetscDefined(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 } 176976bd3646SJed Brown } 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 aDof, aOff, j, k, qConDof, qConOff; 1782085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1783085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 178495a0b26dSToby Isaac 178595a0b26dSToby Isaac qConDof = qConOff = 0; 1786085f0adfSToby Isaac if (numFields) { 178795a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(section,q,f,&aDof);CHKERRQ(ierr); 178895a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(section,q,f,&aOff);CHKERRQ(ierr); 178995a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 179095a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,q,f,&qConDof);CHKERRQ(ierr); 179195a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,q,f,&qConOff);CHKERRQ(ierr); 179295a0b26dSToby Isaac } 179395a0b26dSToby Isaac } 179495a0b26dSToby Isaac else { 179595a0b26dSToby Isaac ierr = PetscSectionGetDof(section,q,&aDof);CHKERRQ(ierr); 179695a0b26dSToby Isaac ierr = PetscSectionGetOffset(section,q,&aOff);CHKERRQ(ierr); 179795a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 179895a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,q,&qConDof);CHKERRQ(ierr); 179995a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,q,&qConOff);CHKERRQ(ierr); 180095a0b26dSToby Isaac } 180195a0b26dSToby Isaac } 180295a0b26dSToby Isaac if (!aDof) continue; 180395a0b26dSToby Isaac if (qConDof) { 180495a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 180595a0b26dSToby Isaac * be filled, thanks to preordering */ 180695a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 180795a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 180895a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 180995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 181095a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 181195a0b26dSToby Isaac PetscScalar inVal = 0; 181295a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1813085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 181495a0b26dSToby Isaac 1815085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 181695a0b26dSToby Isaac } 181795a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 181895a0b26dSToby Isaac } 181995a0b26dSToby Isaac } 182095a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 182195a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 182295a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 182395a0b26dSToby Isaac for (;k < numFillCols; k++) { 182495a0b26dSToby Isaac if (ja[matOffset + k] == col) { 182595a0b26dSToby Isaac break; 182695a0b26dSToby Isaac } 182795a0b26dSToby Isaac } 182895a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, col); 182995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 183095a0b26dSToby Isaac vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 183195a0b26dSToby Isaac } 183295a0b26dSToby Isaac } 183395a0b26dSToby Isaac } 183495a0b26dSToby Isaac else { 183595a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 183695a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 183795a0b26dSToby Isaac if (ja[matOffset + k] == aOff) { 183895a0b26dSToby Isaac break; 183995a0b26dSToby Isaac } 184095a0b26dSToby Isaac } 184195a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, aOff); 184295a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1843085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1844085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1845085f0adfSToby Isaac 1846085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 184795a0b26dSToby Isaac } 184895a0b26dSToby Isaac } 184995a0b26dSToby Isaac } 185095a0b26dSToby Isaac offset += aDof; 185195a0b26dSToby Isaac } 1852085f0adfSToby Isaac if (numFields) { 1853085f0adfSToby Isaac ierr = PetscSectionRestoreFieldPointSyms(section,f,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1854085f0adfSToby Isaac } else { 1855085f0adfSToby Isaac ierr = PetscSectionRestorePointSyms(section,closureSize,closure,&perms,&flips);CHKERRQ(ierr); 1856085f0adfSToby Isaac } 185795a0b26dSToby Isaac } 185895a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 185995a0b26dSToby Isaac } 186095a0b26dSToby Isaac for (row = 0; row < nRows; row++) { 186195a0b26dSToby Isaac ierr = MatSetValues(cMat,1,&row,ia[row+1]-ia[row],&ja[ia[row]],&vals[ia[row]],INSERT_VALUES);CHKERRQ(ierr); 186295a0b26dSToby Isaac } 186395a0b26dSToby Isaac ierr = MatRestoreRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 186495a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not restore RowIJ of constraint matrix"); 186595a0b26dSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 186695a0b26dSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 186795a0b26dSToby Isaac ierr = PetscFree(vals);CHKERRQ(ierr); 186895a0b26dSToby Isaac } 186995a0b26dSToby Isaac 187095a0b26dSToby Isaac /* clean up */ 187195a0b26dSToby Isaac ierr = ISRestoreIndices(anIS,&anchors);CHKERRQ(ierr); 187295a0b26dSToby Isaac ierr = PetscFree2(perm,iperm);CHKERRQ(ierr); 187395a0b26dSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 187421968bf8SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 187595a0b26dSToby Isaac PetscFunctionReturn(0); 187695a0b26dSToby Isaac } 187795a0b26dSToby Isaac 18786f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 18796f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 18806f5f1567SToby Isaac PetscErrorCode DMPlexTreeRefineCell (DM dm, PetscInt cell, DM *ncdm) 18816f5f1567SToby Isaac { 18826f5f1567SToby Isaac DM K; 1883420f55faSMatthew G. Knepley PetscMPIInt rank; 18846f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 18856f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 18866f5f1567SToby Isaac PetscInt *Kembedding; 18876f5f1567SToby Isaac PetscInt *cellClosure=NULL, nc; 18886f5f1567SToby Isaac PetscScalar *newVertexCoords; 18896f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 18906f5f1567SToby Isaac PetscSection parentSection; 18916f5f1567SToby Isaac PetscErrorCode ierr; 18926f5f1567SToby Isaac 18936f5f1567SToby Isaac PetscFunctionBegin; 1894ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr); 189528f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 18966f5f1567SToby Isaac ierr = DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm);CHKERRQ(ierr); 189728f4b327SMatthew G. Knepley ierr = DMSetDimension(*ncdm,dim);CHKERRQ(ierr); 18986f5f1567SToby Isaac 18996f5f1567SToby Isaac ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 19006f5f1567SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&parentSection);CHKERRQ(ierr); 19016f5f1567SToby Isaac ierr = DMPlexGetReferenceTree(dm,&K);CHKERRQ(ierr); 19026f5f1567SToby Isaac if (!rank) { 19036f5f1567SToby Isaac /* compute the new charts */ 19046f5f1567SToby Isaac ierr = PetscMalloc5(dim+1,&pNewCount,dim+1,&pNewStart,dim+1,&pNewEnd,dim+1,&pOldStart,dim+1,&pOldEnd);CHKERRQ(ierr); 19056f5f1567SToby Isaac offset = 0; 19066f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19076f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 19086f5f1567SToby Isaac 19096f5f1567SToby Isaac pNewStart[d] = offset; 19106f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pOldStart[d],&pOldEnd[d]);CHKERRQ(ierr); 19116f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 19126f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 19136f5f1567SToby Isaac /* adding the new points */ 19146f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 19156f5f1567SToby Isaac if (!d) { 19166f5f1567SToby Isaac /* removing the cell */ 19176f5f1567SToby Isaac pNewCount[d]--; 19186f5f1567SToby Isaac } 19196f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19206f5f1567SToby Isaac PetscInt parent; 19216f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&parent,NULL);CHKERRQ(ierr); 19226f5f1567SToby Isaac if (parent == k) { 19236f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 19246f5f1567SToby Isaac pNewCount[d]--; 19256f5f1567SToby Isaac } 19266f5f1567SToby Isaac } 19276f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 19286f5f1567SToby Isaac offset = pNewEnd[d]; 19296f5f1567SToby Isaac 19306f5f1567SToby Isaac } 19316f5f1567SToby 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]); 19326f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 19336f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 19346f5f1567SToby Isaac 19356f5f1567SToby Isaac ierr = PetscMalloc1(pNewEnd[dim],&newConeSizes);CHKERRQ(ierr); 19366f5f1567SToby Isaac { 19376f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 19386f5f1567SToby Isaac 19396f5f1567SToby Isaac ierr = DMPlexGetChart(K,&kStart,&kEnd);CHKERRQ(ierr); 19406f5f1567SToby Isaac ierr = PetscMalloc4(kEnd-kStart,&Kembedding,kEnd-kStart,&perm,kEnd-kStart,&iperm,kEnd-kStart,&preOrient);CHKERRQ(ierr); 19416f5f1567SToby Isaac 19426f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19436f5f1567SToby Isaac perm[k - kStart] = k; 19446f5f1567SToby Isaac iperm [k - kStart] = k - kStart; 19456f5f1567SToby Isaac preOrient[k - kStart] = 0; 19466f5f1567SToby Isaac } 19476f5f1567SToby Isaac 19486f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 19496f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 19506f5f1567SToby Isaac PetscInt parentOrientA = closureK[2*j+1]; 19516f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2*j+1]; 19526f5f1567SToby Isaac PetscInt p, q; 19536f5f1567SToby Isaac 19546f5f1567SToby Isaac p = closureK[2*j]; 19556f5f1567SToby Isaac q = cellClosure[2*j]; 19566f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19576f5f1567SToby Isaac if (q >= pOldStart[d] && q < pOldEnd[d]) { 19586f5f1567SToby Isaac Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 19596f5f1567SToby Isaac } 19606f5f1567SToby Isaac } 19616f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 19626f5f1567SToby Isaac PetscInt numChildren, i; 19636f5f1567SToby Isaac const PetscInt *children; 19646f5f1567SToby Isaac 19656f5f1567SToby Isaac ierr = DMPlexGetTreeChildren(K,p,&numChildren,&children);CHKERRQ(ierr); 19666f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 19676f5f1567SToby Isaac PetscInt kPerm, oPerm; 19686f5f1567SToby Isaac 19696f5f1567SToby Isaac k = children[i]; 19706f5f1567SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry(K,p,parentOrientA,0,k,parentOrientB,&oPerm,&kPerm);CHKERRQ(ierr); 19716f5f1567SToby Isaac /* perm = what refTree position I'm in */ 19726f5f1567SToby Isaac perm[kPerm-kStart] = k; 19736f5f1567SToby Isaac /* iperm = who is at this position */ 19746f5f1567SToby Isaac iperm[k-kStart] = kPerm-kStart; 19756f5f1567SToby Isaac preOrient[kPerm-kStart] = oPerm; 19766f5f1567SToby Isaac } 19776f5f1567SToby Isaac } 19786f5f1567SToby Isaac } 19796f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 19806f5f1567SToby Isaac } 19816f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,0,pNewEnd[dim]);CHKERRQ(ierr); 19826f5f1567SToby Isaac offset = 0; 19836f5f1567SToby Isaac numNewCones = 0; 19846f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19856f5f1567SToby Isaac PetscInt kStart, kEnd, k; 19866f5f1567SToby Isaac PetscInt p; 19876f5f1567SToby Isaac PetscInt size; 19886f5f1567SToby Isaac 19896f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19906f5f1567SToby Isaac /* skip cell 0 */ 19916f5f1567SToby Isaac if (p == cell) continue; 19926f5f1567SToby Isaac /* old cones to new cones */ 19936f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 19946f5f1567SToby Isaac newConeSizes[offset++] = size; 19956f5f1567SToby Isaac numNewCones += size; 19966f5f1567SToby Isaac } 19976f5f1567SToby Isaac 19986f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 19996f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20006f5f1567SToby Isaac PetscInt kParent; 20016f5f1567SToby Isaac 20026f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 20036f5f1567SToby Isaac if (kParent != k) { 20046f5f1567SToby Isaac Kembedding[k] = offset; 20056f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 20066f5f1567SToby Isaac newConeSizes[offset++] = size; 20076f5f1567SToby Isaac numNewCones += size; 20086f5f1567SToby Isaac if (kParent != 0) { 20096f5f1567SToby Isaac ierr = PetscSectionSetDof(parentSection,Kembedding[k],1);CHKERRQ(ierr); 20106f5f1567SToby Isaac } 20116f5f1567SToby Isaac } 20126f5f1567SToby Isaac } 20136f5f1567SToby Isaac } 20146f5f1567SToby Isaac 20156f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 20166f5f1567SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&numPointsWithParents);CHKERRQ(ierr); 20176f5f1567SToby Isaac ierr = PetscMalloc2(numNewCones,&newCones,numNewCones,&newOrientations);CHKERRQ(ierr); 20186f5f1567SToby Isaac ierr = PetscMalloc2(numPointsWithParents,&parents,numPointsWithParents,&childIDs);CHKERRQ(ierr); 20196f5f1567SToby Isaac 20206f5f1567SToby Isaac /* fill new cones */ 20216f5f1567SToby Isaac offset = 0; 20226f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20236f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 20246f5f1567SToby Isaac PetscInt p; 20256f5f1567SToby Isaac PetscInt size; 20266f5f1567SToby Isaac const PetscInt *cone, *orientation; 20276f5f1567SToby Isaac 20286f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 20296f5f1567SToby Isaac /* skip cell 0 */ 20306f5f1567SToby Isaac if (p == cell) continue; 20316f5f1567SToby Isaac /* old cones to new cones */ 20326f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 20336f5f1567SToby Isaac ierr = DMPlexGetCone(dm,p,&cone);CHKERRQ(ierr); 20346f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(dm,p,&orientation);CHKERRQ(ierr); 20356f5f1567SToby Isaac for (l = 0; l < size; l++) { 20366f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 20376f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 20386f5f1567SToby Isaac } 20396f5f1567SToby Isaac } 20406f5f1567SToby Isaac 20416f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 20426f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20436f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 20446f5f1567SToby Isaac PetscInt preO = preOrient[k]; 20456f5f1567SToby Isaac 20466f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 20476f5f1567SToby Isaac if (kParent != k) { 20486f5f1567SToby Isaac /* embed new cones */ 20496f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 20506f5f1567SToby Isaac ierr = DMPlexGetCone(K,kPerm,&cone);CHKERRQ(ierr); 20516f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(K,kPerm,&orientation);CHKERRQ(ierr); 20526f5f1567SToby Isaac for (l = 0; l < size; l++) { 20536f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size -(preO + 1) - l) % size); 20546f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 20556f5f1567SToby Isaac 20566f5f1567SToby Isaac q = iperm[cone[m]]; 20576f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 20586f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,q,&lSize);CHKERRQ(ierr); 20596f5f1567SToby Isaac oTrue = orientation[m]; 20606f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 20616f5f1567SToby Isaac newO = DihedralCompose(lSize,oTrue,preOrient[q]); 20626f5f1567SToby Isaac newOrientations[offset++] = newO; 20636f5f1567SToby Isaac } 20646f5f1567SToby Isaac if (kParent != 0) { 20656f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 20666f5f1567SToby Isaac ierr = PetscSectionGetOffset(parentSection,Kembedding[k],&pOffset);CHKERRQ(ierr); 20676f5f1567SToby Isaac parents[pOffset] = newPoint; 20686f5f1567SToby Isaac childIDs[pOffset] = k; 20696f5f1567SToby Isaac } 20706f5f1567SToby Isaac } 20716f5f1567SToby Isaac } 20726f5f1567SToby Isaac } 20736f5f1567SToby Isaac 20746f5f1567SToby Isaac ierr = PetscMalloc1(dim*(pNewEnd[dim]-pNewStart[dim]),&newVertexCoords);CHKERRQ(ierr); 20756f5f1567SToby Isaac 20766f5f1567SToby Isaac /* fill coordinates */ 20776f5f1567SToby Isaac offset = 0; 20786f5f1567SToby Isaac { 2079d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 20806f5f1567SToby Isaac PetscSection vSection; 20816f5f1567SToby Isaac PetscInt v; 20826f5f1567SToby Isaac Vec coords; 20836f5f1567SToby Isaac PetscScalar *coordvals; 20846f5f1567SToby Isaac PetscInt dof, off; 2085c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 20866f5f1567SToby Isaac 208776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 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 } 209573a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 20966f5f1567SToby Isaac ierr = DMGetCoordinateSection(dm,&vSection);CHKERRQ(ierr); 20976f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coords);CHKERRQ(ierr); 20986f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 20996f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 21006f5f1567SToby Isaac 21016f5f1567SToby Isaac ierr = PetscSectionGetDof(vSection,v,&dof);CHKERRQ(ierr); 21026f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,v,&off);CHKERRQ(ierr); 21036f5f1567SToby Isaac for (l = 0; l < dof; l++) { 21046f5f1567SToby Isaac newVertexCoords[offset++] = coordvals[off + l]; 21056f5f1567SToby Isaac } 21066f5f1567SToby Isaac } 21076f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 21086f5f1567SToby Isaac 21096f5f1567SToby Isaac ierr = DMGetCoordinateSection(K,&vSection);CHKERRQ(ierr); 21106f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(K,&coords);CHKERRQ(ierr); 21116f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 21126f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 21136f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 21149bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 21156f5f1567SToby Isaac PetscInt vPerm = perm[v]; 21166f5f1567SToby Isaac PetscInt kParent; 2117c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 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]); 2124367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord); 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 PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 21886ecaa68aSToby Isaac { 21896ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 21906ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 21916ecaa68aSToby Isaac PetscSection localCoarse, localFine; 21926ecaa68aSToby Isaac PetscSection aSec, cSec; 21936ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 219446bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 219546bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 219646bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 21976ecaa68aSToby Isaac IS aIS; 21986ecaa68aSToby Isaac const PetscInt *anchors; 21996ecaa68aSToby Isaac Mat cMat; 22004acb8e1eSToby Isaac PetscInt numFields, maxFields; 22016ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 22026ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 22031c58ffc4SToby Isaac PetscInt *maxChildIds; 2204e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 22054acb8e1eSToby Isaac const PetscInt ***perms; 22064acb8e1eSToby Isaac const PetscScalar ***flips; 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); 2212e87a4003SBarry Smith ierr = DMGetGlobalSection(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 224692fd8e1eSJed Brown ierr = DMGetLocalSection(coarse,&localCoarse);CHKERRQ(ierr); 2247e87a4003SBarry Smith ierr = DMGetGlobalSection(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); 2262713c1c5dSToby Isaac maxFields = PetscMax(1,numFields); 2263713c1c5dSToby Isaac ierr = PetscMalloc7(maxFields+1,&offsets,maxFields+1,&offsetsCopy,maxFields+1,&newOffsets,maxFields+1,&newOffsetsCopy,maxFields+1,&rowOffsets,maxFields+1,&numD,maxFields+1,&numO);CHKERRQ(ierr); 2264f489ac74SBarry Smith ierr = PetscMalloc2(maxFields+1,(PetscInt****)&perms,maxFields+1,(PetscScalar****)&flips);CHKERRQ(ierr); 2265713c1c5dSToby Isaac ierr = PetscMemzero((void *) perms, (maxFields+1) * sizeof(const PetscInt **));CHKERRQ(ierr); 2266713c1c5dSToby Isaac ierr = PetscMemzero((void *) flips, (maxFields+1) * sizeof(const PetscScalar **));CHKERRQ(ierr); 226746bdb399SToby Isaac 226846bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 22698d2f55e7SToby Isaac PetscInt dof, matSize = 0; 22706ecaa68aSToby Isaac PetscInt aDof = 0; 22716ecaa68aSToby Isaac PetscInt cDof = 0; 22726ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22736ecaa68aSToby Isaac PetscInt numRowIndices = 0; 22746ecaa68aSToby Isaac PetscInt numColIndices = 0; 2275f13f9184SToby Isaac PetscInt f; 22766ecaa68aSToby Isaac 22776ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 22781cfc5b76SToby Isaac if (dof < 0) { 22791cfc5b76SToby Isaac dof = -(dof + 1); 22801cfc5b76SToby Isaac } 22816ecaa68aSToby Isaac if (p >= aStart && p < aEnd) { 22826ecaa68aSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 22836ecaa68aSToby Isaac } 22846ecaa68aSToby Isaac if (p >= cStart && p < cEnd) { 22856ecaa68aSToby Isaac ierr = PetscSectionGetDof(cSec,p,&cDof);CHKERRQ(ierr); 22866ecaa68aSToby Isaac } 2287f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2288f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 22896ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2290f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 22916ecaa68aSToby Isaac 22926ecaa68aSToby Isaac ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 229346bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 22946ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 22956ecaa68aSToby Isaac 22966ecaa68aSToby Isaac ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr); 22976ecaa68aSToby Isaac numRowIndices += clDof; 22986ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22996ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&clDof);CHKERRQ(ierr); 23006ecaa68aSToby Isaac offsets[f + 1] += clDof; 23016ecaa68aSToby Isaac } 23026ecaa68aSToby Isaac } 23036ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23046ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23056ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 23066ecaa68aSToby Isaac } 230746bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 23084acb8e1eSToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,NULL,NULL,NULL,&numColIndices,NULL,NULL,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 23096ecaa68aSToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 23106ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 23116ecaa68aSToby Isaac numColIndices = numRowIndices; 23126ecaa68aSToby Isaac matSize = 0; 23136ecaa68aSToby Isaac } 231446bdb399SToby Isaac else if (numFields) { /* we send one submat for each field: sum their sizes */ 23156ecaa68aSToby Isaac matSize = 0; 23166ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23176ecaa68aSToby Isaac PetscInt numRow, numCol; 23186ecaa68aSToby Isaac 23196ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2320f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 23216ecaa68aSToby Isaac matSize += numRow * numCol; 23226ecaa68aSToby Isaac } 23236ecaa68aSToby Isaac } 23246ecaa68aSToby Isaac else { 23256ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 23266ecaa68aSToby Isaac } 2327f13f9184SToby Isaac } else if (maxChildId == -1) { 23288d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2329f13f9184SToby Isaac PetscInt aOff, a; 23306ecaa68aSToby Isaac 23316ecaa68aSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 23326ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23336ecaa68aSToby Isaac PetscInt fDof; 23346ecaa68aSToby Isaac 23356ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 233621968bf8SToby Isaac offsets[f+1] = fDof; 23376ecaa68aSToby Isaac } 23386ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23396ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 23406ecaa68aSToby Isaac 23416ecaa68aSToby Isaac ierr = PetscSectionGetDof(localCoarse,anchor,&aLocalDof);CHKERRQ(ierr); 23426ecaa68aSToby Isaac numColIndices += aLocalDof; 23436ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23446ecaa68aSToby Isaac PetscInt fDof; 23456ecaa68aSToby Isaac 23466ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 234721968bf8SToby Isaac newOffsets[f+1] += fDof; 23486ecaa68aSToby Isaac } 23496ecaa68aSToby Isaac } 23506ecaa68aSToby Isaac if (numFields) { 23516ecaa68aSToby Isaac matSize = 0; 23526ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 235321968bf8SToby Isaac matSize += offsets[f+1] * newOffsets[f+1]; 23546ecaa68aSToby Isaac } 23556ecaa68aSToby Isaac } 23566ecaa68aSToby Isaac else { 23576ecaa68aSToby Isaac matSize = numColIndices * dof; 23586ecaa68aSToby Isaac } 23596ecaa68aSToby Isaac } 23606ecaa68aSToby Isaac else { /* no children, and no constraints on dofs: just get the global indices */ 23616ecaa68aSToby Isaac numColIndices = dof; 23626ecaa68aSToby Isaac matSize = 0; 23636ecaa68aSToby Isaac } 23648d2f55e7SToby Isaac } 236546bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 23666ecaa68aSToby Isaac ierr = PetscSectionSetDof(rootIndicesSec,p,numColIndices ? numColIndices+2*numFields : 0);CHKERRQ(ierr); 23676ecaa68aSToby Isaac ierr = PetscSectionSetDof(rootMatricesSec,p,matSize);CHKERRQ(ierr); 23686ecaa68aSToby Isaac } 23696ecaa68aSToby Isaac ierr = PetscSectionSetUp(rootIndicesSec);CHKERRQ(ierr); 23706ecaa68aSToby Isaac ierr = PetscSectionSetUp(rootMatricesSec);CHKERRQ(ierr); 23716ecaa68aSToby Isaac { 23726ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 23736ecaa68aSToby Isaac 23746ecaa68aSToby Isaac ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr); 23756ecaa68aSToby Isaac ierr = PetscSectionGetStorageSize(rootMatricesSec,&numRootMatrices);CHKERRQ(ierr); 23766ecaa68aSToby Isaac ierr = PetscMalloc2(numRootIndices,&rootIndices,numRootMatrices,&rootMatrices);CHKERRQ(ierr); 23776ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 23786ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2379f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 23806ecaa68aSToby Isaac PetscInt *pInd; 23816ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 23826ecaa68aSToby Isaac PetscScalar *pMat = NULL; 23836ecaa68aSToby Isaac 23846ecaa68aSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,p,&numColIndices);CHKERRQ(ierr); 23856ecaa68aSToby Isaac if (!numColIndices) { 23866ecaa68aSToby Isaac continue; 23876ecaa68aSToby Isaac } 2388f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2389f13f9184SToby Isaac offsets[f] = 0; 2390f13f9184SToby Isaac newOffsets[f] = 0; 2391f13f9184SToby Isaac offsetsCopy[f] = 0; 2392f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2393f13f9184SToby Isaac } 23946ecaa68aSToby Isaac numColIndices -= 2 * numFields; 23956ecaa68aSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,p,&pIndOff);CHKERRQ(ierr); 23966ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 23976ecaa68aSToby Isaac ierr = PetscSectionGetDof(rootMatricesSec,p,&matSize);CHKERRQ(ierr); 23986ecaa68aSToby Isaac if (matSize) { 23996ecaa68aSToby Isaac ierr = PetscSectionGetOffset(rootMatricesSec,p,&pMatOff);CHKERRQ(ierr); 24006ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 24016ecaa68aSToby Isaac } 24026ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 24031cfc5b76SToby Isaac if (dof < 0) { 24041cfc5b76SToby Isaac dof = -(dof + 1); 24051cfc5b76SToby Isaac } 24066ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 24076ecaa68aSToby Isaac PetscInt i, j; 24086ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 24096ecaa68aSToby Isaac 24106ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 24116ecaa68aSToby Isaac PetscInt numIndices, *indices; 241271f0bbf9SMatthew G. Knepley ierr = DMPlexGetClosureIndices(coarse,localCoarse,globalCoarse,p,PETSC_TRUE,&numIndices,&indices,offsets,NULL);CHKERRQ(ierr); 24136ecaa68aSToby Isaac if (numIndices != numColIndices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"mismatching constraint indices calculations"); 24146ecaa68aSToby Isaac for (i = 0; i < numColIndices; i++) { 24156ecaa68aSToby Isaac pInd[i] = indices[i]; 24166ecaa68aSToby Isaac } 24176ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 241846bdb399SToby Isaac pInd[numColIndices + i] = offsets[i+1]; 241946bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i+1]; 24206ecaa68aSToby Isaac } 242171f0bbf9SMatthew G. Knepley ierr = DMPlexRestoreClosureIndices(coarse,localCoarse,globalCoarse,p,PETSC_TRUE,&numIndices,&indices,offsets,NULL);CHKERRQ(ierr); 24226ecaa68aSToby Isaac } 24236ecaa68aSToby Isaac else { 24246ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 24256ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 24266ecaa68aSToby Isaac PetscInt numPoints,*points; 24276ecaa68aSToby Isaac 242869291d52SBarry Smith ierr = DMGetWorkArray(coarse,numRowIndices * numRowIndices,MPIU_SCALAR,&pMatIn);CHKERRQ(ierr); 24296ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 24306ecaa68aSToby Isaac for (j = 0; j < numRowIndices; j++) { 24316ecaa68aSToby Isaac pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 24326ecaa68aSToby Isaac } 24336ecaa68aSToby Isaac } 24346ecaa68aSToby Isaac ierr = DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 24354acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24364acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionGetFieldPointSyms(localCoarse,f,closureSize,closure,&perms[f],&flips[f]);CHKERRQ(ierr);} 24374acb8e1eSToby Isaac else {ierr = PetscSectionGetPointSyms(localCoarse,closureSize,closure,&perms[f],&flips[f]);CHKERRQ(ierr);} 24384acb8e1eSToby Isaac } 24396ecaa68aSToby Isaac if (numFields) { 24406ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 24416ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 24426ecaa68aSToby Isaac 24436ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24446ecaa68aSToby Isaac PetscInt fDof; 24456ecaa68aSToby Isaac 24466ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&fDof);CHKERRQ(ierr); 24476ecaa68aSToby Isaac offsets[f + 1] += fDof; 24486ecaa68aSToby Isaac } 24496ecaa68aSToby Isaac } 24506ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24516ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 24526ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 24536ecaa68aSToby Isaac } 24546ecaa68aSToby Isaac } 24554acb8e1eSToby Isaac /* TODO : flips here ? */ 24566ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 24574acb8e1eSToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,perms,pMatIn,&numPoints,NULL,&points,&pMatModified,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 24584acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24594acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(localCoarse,f,closureSize,closure,&perms[f],&flips[f]);CHKERRQ(ierr);} 24604acb8e1eSToby Isaac else {ierr = PetscSectionRestorePointSyms(localCoarse,closureSize,closure,&perms[f],&flips[f]);CHKERRQ(ierr);} 24614acb8e1eSToby Isaac } 24624acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24634acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionGetFieldPointSyms(localCoarse,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 24644acb8e1eSToby Isaac else {ierr = PetscSectionGetPointSyms(localCoarse,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 24654acb8e1eSToby Isaac } 24666ecaa68aSToby Isaac if (!numFields) { 24676ecaa68aSToby Isaac for (i = 0; i < numRowIndices * numColIndices; i++) { 24686ecaa68aSToby Isaac pMat[i] = pMatModified[i]; 24696ecaa68aSToby Isaac } 24706ecaa68aSToby Isaac } 24716ecaa68aSToby Isaac else { 2472f13f9184SToby Isaac PetscInt i, j, count; 24736ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24746ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f+1]; i++) { 24756ecaa68aSToby Isaac for (j = newOffsets[f]; j < newOffsets[f+1]; j++, count++) { 24766ecaa68aSToby Isaac pMat[count] = pMatModified[i * numColIndices + j]; 24776ecaa68aSToby Isaac } 24786ecaa68aSToby Isaac } 24796ecaa68aSToby Isaac } 24806ecaa68aSToby Isaac } 248169291d52SBarry Smith ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,MPIU_SCALAR,&pMatModified);CHKERRQ(ierr); 24826ecaa68aSToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 248369291d52SBarry Smith ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,MPIU_SCALAR,&pMatIn);CHKERRQ(ierr); 24846ecaa68aSToby Isaac if (numFields) { 248546bdb399SToby Isaac for (f = 0; f < numFields; f++) { 248646bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 248746bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 24886ecaa68aSToby Isaac } 24894acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 24904acb8e1eSToby Isaac PetscInt globalOff, c = points[2*cl]; 24916ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 249236fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd);CHKERRQ(ierr); 24936ecaa68aSToby Isaac } 24946ecaa68aSToby Isaac } else { 24954acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 24964acb8e1eSToby Isaac PetscInt c = points[2*cl], globalOff; 24974acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 24984acb8e1eSToby Isaac 24996ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 250036fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd);CHKERRQ(ierr); 25016ecaa68aSToby Isaac } 25026ecaa68aSToby Isaac } 25034acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 25044acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(localCoarse,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 25054acb8e1eSToby Isaac else {ierr = PetscSectionRestorePointSyms(localCoarse,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 25064acb8e1eSToby Isaac } 250769291d52SBarry Smith ierr = DMRestoreWorkArray(coarse,numPoints,MPIU_SCALAR,&points);CHKERRQ(ierr); 25086ecaa68aSToby Isaac } 25096ecaa68aSToby Isaac } 25106ecaa68aSToby Isaac else if (matSize) { 25116ecaa68aSToby Isaac PetscInt cOff; 25126ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 25136ecaa68aSToby Isaac 25146ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 2515628cbfb8SToby Isaac if (numRowIndices != dof) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Miscounted dofs"); 251669291d52SBarry Smith ierr = DMGetWorkArray(coarse,numRowIndices,MPIU_INT,&rowIndices);CHKERRQ(ierr); 251769291d52SBarry Smith ierr = DMGetWorkArray(coarse,numColIndices,MPIU_INT,&colIndices);CHKERRQ(ierr); 25186ecaa68aSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&cOff);CHKERRQ(ierr); 25196ecaa68aSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 25206ecaa68aSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 25216ecaa68aSToby Isaac if (numFields) { 25226ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25236ecaa68aSToby Isaac PetscInt fDof; 2524f13f9184SToby Isaac 25256ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&fDof);CHKERRQ(ierr); 25266ecaa68aSToby Isaac offsets[f + 1] = fDof; 25276ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25286ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25296ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 25306ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 25316ecaa68aSToby Isaac } 25326ecaa68aSToby Isaac } 25336ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25346ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 25356ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 25366ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 25376ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 25386ecaa68aSToby Isaac } 253936fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(cSec,PETSC_TRUE,p,cOff,offsetsCopy,PETSC_TRUE,NULL,-1, NULL,rowIndices);CHKERRQ(ierr); 25406ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25416ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25426ecaa68aSToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 254336fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_TRUE,anchor,lOff,newOffsetsCopy,PETSC_TRUE,NULL,-1, NULL,colIndices);CHKERRQ(ierr); 25446ecaa68aSToby Isaac } 25456ecaa68aSToby Isaac } 25466ecaa68aSToby Isaac else { 254736fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(cSec,PETSC_TRUE,p,cOff,offsetsCopy,PETSC_TRUE,NULL, NULL,rowIndices);CHKERRQ(ierr); 25486ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25496ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25506ecaa68aSToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 255136fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_TRUE,anchor,lOff,newOffsetsCopy,PETSC_TRUE,NULL, NULL,colIndices);CHKERRQ(ierr); 25526ecaa68aSToby Isaac } 25536ecaa68aSToby Isaac } 25546ecaa68aSToby Isaac if (numFields) { 2555f13f9184SToby Isaac PetscInt count, a; 2556f13f9184SToby Isaac 25576ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 25586ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 25596ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 25606ecaa68aSToby Isaac ierr = MatGetValues(cMat,iSize,&rowIndices[offsets[f]],jSize,&colIndices[newOffsets[f]],&pMat[count]);CHKERRQ(ierr); 25616ecaa68aSToby Isaac count += iSize * jSize; 256246bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 256346bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 25646ecaa68aSToby Isaac } 25656ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25666ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25676ecaa68aSToby Isaac PetscInt gOff; 25686ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 256936fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,NULL,-1, NULL,pInd);CHKERRQ(ierr); 25706ecaa68aSToby Isaac } 25716ecaa68aSToby Isaac } 25726ecaa68aSToby Isaac else { 25736ecaa68aSToby Isaac PetscInt a; 25746ecaa68aSToby Isaac ierr = MatGetValues(cMat,numRowIndices,rowIndices,numColIndices,colIndices,pMat);CHKERRQ(ierr); 25756ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25766ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25776ecaa68aSToby Isaac PetscInt gOff; 25786ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 257936fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,NULL, NULL,pInd);CHKERRQ(ierr); 25806ecaa68aSToby Isaac } 25816ecaa68aSToby Isaac } 258269291d52SBarry Smith ierr = DMRestoreWorkArray(coarse,numColIndices,MPIU_INT,&colIndices);CHKERRQ(ierr); 258369291d52SBarry Smith ierr = DMRestoreWorkArray(coarse,numRowIndices,MPIU_INT,&rowIndices);CHKERRQ(ierr); 25846ecaa68aSToby Isaac } 25856ecaa68aSToby Isaac else { 25866ecaa68aSToby Isaac PetscInt gOff; 25876ecaa68aSToby Isaac 25886ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 25896ecaa68aSToby Isaac if (numFields) { 25906ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25916ecaa68aSToby Isaac PetscInt fDof; 25926ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 25936ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 25946ecaa68aSToby Isaac } 25956ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 259646bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 259746bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f+1]; 25986ecaa68aSToby Isaac } 259936fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,-1, NULL,pInd);CHKERRQ(ierr); 2600367003a6SStefano Zampini } else { 260136fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL, NULL,pInd);CHKERRQ(ierr); 26026ecaa68aSToby Isaac } 26036ecaa68aSToby Isaac } 26046ecaa68aSToby Isaac } 2605e44e4e7fSToby Isaac ierr = PetscFree(maxChildIds);CHKERRQ(ierr); 26066ecaa68aSToby Isaac } 260746bdb399SToby Isaac { 260846bdb399SToby Isaac PetscSF indicesSF, matricesSF; 260946bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 261046bdb399SToby Isaac 261146bdb399SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr); 261246bdb399SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafMatricesSec);CHKERRQ(ierr); 261346bdb399SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootIndicesSec,&remoteOffsetsIndices,leafIndicesSec);CHKERRQ(ierr); 261446bdb399SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootMatricesSec,&remoteOffsetsMatrices,leafMatricesSec);CHKERRQ(ierr); 261546bdb399SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootIndicesSec,remoteOffsetsIndices,leafIndicesSec,&indicesSF);CHKERRQ(ierr); 261646bdb399SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootMatricesSec,remoteOffsetsMatrices,leafMatricesSec,&matricesSF);CHKERRQ(ierr); 2617e44e4e7fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 261846bdb399SToby Isaac ierr = PetscFree(remoteOffsetsIndices);CHKERRQ(ierr); 261946bdb399SToby Isaac ierr = PetscFree(remoteOffsetsMatrices);CHKERRQ(ierr); 262046bdb399SToby Isaac ierr = PetscSectionGetStorageSize(leafIndicesSec,&numLeafIndices);CHKERRQ(ierr); 262146bdb399SToby Isaac ierr = PetscSectionGetStorageSize(leafMatricesSec,&numLeafMatrices);CHKERRQ(ierr); 262246bdb399SToby Isaac ierr = PetscMalloc2(numLeafIndices,&leafIndices,numLeafMatrices,&leafMatrices);CHKERRQ(ierr); 2623ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,rootIndices,leafIndices,MPI_REPLACE);CHKERRQ(ierr); 2624ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices,MPI_REPLACE);CHKERRQ(ierr); 2625ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,rootIndices,leafIndices,MPI_REPLACE);CHKERRQ(ierr); 2626ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices,MPI_REPLACE);CHKERRQ(ierr); 262746bdb399SToby Isaac ierr = PetscSFDestroy(&matricesSF);CHKERRQ(ierr); 262846bdb399SToby Isaac ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr); 262946bdb399SToby Isaac ierr = PetscFree2(rootIndices,rootMatrices);CHKERRQ(ierr); 263046bdb399SToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 263146bdb399SToby Isaac ierr = PetscSectionDestroy(&rootMatricesSec);CHKERRQ(ierr); 263246bdb399SToby Isaac } 263346bdb399SToby Isaac /* count to preallocate */ 263492fd8e1eSJed Brown ierr = DMGetLocalSection(fine,&localFine);CHKERRQ(ierr); 263546bdb399SToby Isaac { 263646bdb399SToby Isaac PetscInt nGlobal; 263746bdb399SToby Isaac PetscInt *dnnz, *onnz; 2638b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2639b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 26401c58ffc4SToby Isaac PetscInt maxDof; 26411c58ffc4SToby Isaac PetscInt *rowIndices; 26421c58ffc4SToby Isaac DM refTree; 26431c58ffc4SToby Isaac PetscInt **refPointFieldN; 26441c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 26451c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 26460eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,maxConDof,maxColumns,leafStart,leafEnd; 26471c58ffc4SToby Isaac PetscScalar *pointWork; 264846bdb399SToby Isaac 264946bdb399SToby Isaac ierr = PetscSectionGetConstrainedStorageSize(globalFine,&nGlobal);CHKERRQ(ierr); 265046bdb399SToby Isaac ierr = PetscCalloc2(nGlobal,&dnnz,nGlobal,&onnz);CHKERRQ(ierr); 2651b9a5774bSToby Isaac ierr = MatGetLayouts(mat,&rowMap,&colMap);CHKERRQ(ierr); 2652b9a5774bSToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 26531c58ffc4SToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 2654b9a5774bSToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 265546bdb399SToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 26567f8983b1SJed Brown ierr = PetscSectionGetMaxDof(localFine,&maxDof);CHKERRQ(ierr); 26570eb7e1eaSToby Isaac ierr = PetscSectionGetChart(leafIndicesSec,&leafStart,&leafEnd);CHKERRQ(ierr); 265869291d52SBarry Smith ierr = DMGetWorkArray(fine,maxDof,MPIU_INT,&rowIndices);CHKERRQ(ierr); 26590eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 266046bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 266146bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 266246bdb399SToby Isaac PetscInt matSize; 266321968bf8SToby Isaac PetscInt i; 266446bdb399SToby Isaac 266546bdb399SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 266646bdb399SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 266746bdb399SToby Isaac if ((gDof - gcDof) <= 0) { 266846bdb399SToby Isaac continue; 266946bdb399SToby Isaac } 267046bdb399SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 267146bdb399SToby Isaac if (gOff < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"I though having global dofs meant a non-negative offset"); 2672b9a5774bSToby 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"); 267346bdb399SToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 267446bdb399SToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 267546bdb399SToby Isaac numColIndices -= 2 * numFields; 26761c58ffc4SToby Isaac if (numColIndices <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"global fine dof with no dofs to interpolate from"); 267746bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 267821968bf8SToby Isaac offsets[0] = 0; 267921968bf8SToby Isaac offsetsCopy[0] = 0; 268021968bf8SToby Isaac newOffsets[0] = 0; 268121968bf8SToby Isaac newOffsetsCopy[0] = 0; 268246bdb399SToby Isaac if (numFields) { 268321968bf8SToby Isaac PetscInt f; 268446bdb399SToby Isaac for (f = 0; f < numFields; f++) { 268546bdb399SToby Isaac PetscInt rowDof; 268646bdb399SToby Isaac 268746bdb399SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 268821968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 268921968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 269021968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 269121968bf8SToby Isaac numD[f] = 0; 269221968bf8SToby Isaac numO[f] = 0; 269346bdb399SToby Isaac } 269436fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,rowIndices);CHKERRQ(ierr); 269546bdb399SToby Isaac for (f = 0; f < numFields; f++) { 269621968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 269721968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 269846bdb399SToby Isaac 269946bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 270046bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 270146bdb399SToby Isaac 270246bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 270321968bf8SToby Isaac numD[f]++; 270446bdb399SToby Isaac } 270546bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 270621968bf8SToby Isaac numO[f]++; 270746bdb399SToby Isaac } 270846bdb399SToby Isaac } 270946bdb399SToby Isaac } 271046bdb399SToby Isaac } 271146bdb399SToby Isaac else { 271236fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,rowIndices);CHKERRQ(ierr); 271321968bf8SToby Isaac numD[0] = 0; 271421968bf8SToby Isaac numO[0] = 0; 271546bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 271646bdb399SToby Isaac PetscInt gInd = pInd[i]; 271746bdb399SToby Isaac 271846bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 271921968bf8SToby Isaac numD[0]++; 272046bdb399SToby Isaac } 272146bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 272221968bf8SToby Isaac numO[0]++; 272346bdb399SToby Isaac } 272446bdb399SToby Isaac } 272546bdb399SToby Isaac } 272646bdb399SToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 272746bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 272846bdb399SToby Isaac PetscInt childId; 272946bdb399SToby Isaac 273046bdb399SToby Isaac childId = childIds[p-pStartF]; 273121968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 273246bdb399SToby Isaac if (numFields) { 2733b9a5774bSToby Isaac PetscInt f; 2734b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 273521968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 273646bdb399SToby Isaac for (row = 0; row < numRows; row++) { 273721968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 273821968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 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 { 2754b9a5774bSToby Isaac PetscInt i; 2755b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 275646bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 275746bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 275846bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 2759b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2760b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 276146bdb399SToby Isaac } 276246bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 2763b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2764b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 276546bdb399SToby Isaac } 276646bdb399SToby Isaac else { /* constrained */ 276746bdb399SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 276846bdb399SToby Isaac } 276946bdb399SToby Isaac } 277046bdb399SToby Isaac } 277146bdb399SToby Isaac } 277246bdb399SToby Isaac else { /* interpolate from all */ 277346bdb399SToby Isaac if (numFields) { 2774b9a5774bSToby Isaac PetscInt f; 2775b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 277621968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 277746bdb399SToby Isaac for (row = 0; row < numRows; row++) { 277821968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 277946bdb399SToby Isaac if (gIndFine >= 0) { 2780b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2781b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2782b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 278346bdb399SToby Isaac } 278446bdb399SToby Isaac } 278546bdb399SToby Isaac } 278646bdb399SToby Isaac } 278746bdb399SToby Isaac else { 2788b9a5774bSToby Isaac PetscInt i; 2789b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 279046bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 279146bdb399SToby Isaac if (gIndFine >= 0) { 2792b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2793b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2794b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 279546bdb399SToby Isaac } 279646bdb399SToby Isaac } 279746bdb399SToby Isaac } 279846bdb399SToby Isaac } 279946bdb399SToby Isaac } 280046bdb399SToby Isaac else { /* interpolate from all */ 280146bdb399SToby Isaac if (numFields) { 2802b9a5774bSToby Isaac PetscInt f; 2803b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 280421968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 280546bdb399SToby Isaac for (row = 0; row < numRows; row++) { 280621968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 280746bdb399SToby Isaac if (gIndFine >= 0) { 2808b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2809b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2810b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 281146bdb399SToby Isaac } 281246bdb399SToby Isaac } 281346bdb399SToby Isaac } 281446bdb399SToby Isaac } 281546bdb399SToby Isaac else { /* every dof get a full row */ 2816b9a5774bSToby Isaac PetscInt i; 2817b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 281846bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 281946bdb399SToby Isaac if (gIndFine >= 0) { 2820b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2821b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2822b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 282346bdb399SToby Isaac } 282446bdb399SToby Isaac } 282546bdb399SToby Isaac } 282646bdb399SToby Isaac } 282746bdb399SToby Isaac } 282846bdb399SToby Isaac ierr = MatXAIJSetPreallocation(mat,1,dnnz,onnz,NULL,NULL);CHKERRQ(ierr); 282946bdb399SToby Isaac ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 283021968bf8SToby Isaac 283121968bf8SToby Isaac ierr = DMPlexGetReferenceTree(fine,&refTree);CHKERRQ(ierr); 283221968bf8SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 2833e44e4e7fSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 2834e44e4e7fSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,NULL);CHKERRQ(ierr); 2835e44e4e7fSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 28361c58ffc4SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxConDof);CHKERRQ(ierr); 28377c0540e0SToby Isaac ierr = PetscSectionGetMaxDof(leafIndicesSec,&maxColumns);CHKERRQ(ierr); 28387c0540e0SToby Isaac ierr = PetscMalloc1(maxConDof*maxColumns,&pointWork);CHKERRQ(ierr); 28390eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2840e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2841e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2842e44e4e7fSToby Isaac PetscInt matSize; 2843e44e4e7fSToby Isaac PetscInt childId; 2844e44e4e7fSToby Isaac 2845e44e4e7fSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 2846e44e4e7fSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 2847e44e4e7fSToby Isaac if ((gDof - gcDof) <= 0) { 2848e44e4e7fSToby Isaac continue; 2849e44e4e7fSToby Isaac } 2850e44e4e7fSToby Isaac childId = childIds[p-pStartF]; 2851e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 2852e44e4e7fSToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 2853e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 2854e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2855e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2856e44e4e7fSToby Isaac offsets[0] = 0; 2857e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2858e44e4e7fSToby Isaac newOffsets[0] = 0; 2859e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2860e44e4e7fSToby Isaac rowOffsets[0] = 0; 2861e44e4e7fSToby Isaac if (numFields) { 2862e44e4e7fSToby Isaac PetscInt f; 2863e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2864e44e4e7fSToby Isaac PetscInt rowDof; 2865e44e4e7fSToby Isaac 2866e44e4e7fSToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 2867e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2868e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2869e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2870e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2871e44e4e7fSToby Isaac } 287236fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,rowIndices);CHKERRQ(ierr); 2873e44e4e7fSToby Isaac } 28741c58ffc4SToby Isaac else { 287536fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,rowIndices);CHKERRQ(ierr); 28761c58ffc4SToby Isaac } 2877e44e4e7fSToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 2878e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2879e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2880e44e4e7fSToby Isaac if (numFields) { 2881e44e4e7fSToby Isaac PetscInt f; 2882e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2883e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 2884e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 2885e44e4e7fSToby Isaac ierr = MatSetValue(mat,rowIndices[offsets[f]+row],pInd[newOffsets[f]+row],1.,INSERT_VALUES);CHKERRQ(ierr); 288621968bf8SToby Isaac } 288721968bf8SToby Isaac } 2888e44e4e7fSToby Isaac } 2889e44e4e7fSToby Isaac else { 2890e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 2891e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 2892e44e4e7fSToby Isaac ierr = MatSetValue(mat,rowIndices[row],pInd[row],1.,INSERT_VALUES);CHKERRQ(ierr); 2893e44e4e7fSToby Isaac } 2894e44e4e7fSToby Isaac } 2895e44e4e7fSToby Isaac } 2896e44e4e7fSToby Isaac else { /* interpolate from all */ 2897e44e4e7fSToby Isaac if (numFields) { 2898e44e4e7fSToby Isaac PetscInt f; 2899e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2900e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 2901e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2902e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],refPointFieldMats[childId - pRefStart][f],INSERT_VALUES);CHKERRQ(ierr); 2903e44e4e7fSToby Isaac } 2904e44e4e7fSToby Isaac } 2905e44e4e7fSToby Isaac else { 2906e44e4e7fSToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,refPointFieldMats[childId - pRefStart][0],INSERT_VALUES);CHKERRQ(ierr); 2907e44e4e7fSToby Isaac } 2908e44e4e7fSToby Isaac } 2909e44e4e7fSToby Isaac } 2910e44e4e7fSToby Isaac else { /* interpolate from all */ 2911e44e4e7fSToby Isaac PetscInt pMatOff; 2912e44e4e7fSToby Isaac PetscScalar *pMat; 2913e44e4e7fSToby Isaac 2914e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(leafMatricesSec,p,&pMatOff);CHKERRQ(ierr); 2915e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2916e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2917e44e4e7fSToby Isaac if (numFields) { 2918e44e4e7fSToby Isaac PetscInt f, count; 2919e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2920e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2921e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2922e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2923e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2924e44e4e7fSToby Isaac 2925e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],inMat,INSERT_VALUES);CHKERRQ(ierr); 2926e44e4e7fSToby Isaac count += numCols * numInRows; 2927e44e4e7fSToby Isaac } 2928e44e4e7fSToby Isaac } 2929e44e4e7fSToby Isaac else { 2930e44e4e7fSToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,pMat,INSERT_VALUES);CHKERRQ(ierr); 2931e44e4e7fSToby Isaac } 2932e44e4e7fSToby Isaac } 2933e44e4e7fSToby Isaac else { /* multiply the incoming matrix by the child interpolation */ 2934e44e4e7fSToby Isaac if (numFields) { 2935e44e4e7fSToby Isaac PetscInt f, count; 2936e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2937e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2938e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2939e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2940e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2941e44e4e7fSToby Isaac PetscInt i, j, k; 2942e44e4e7fSToby Isaac if (refPointFieldN[childId - pRefStart][f] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2943e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2944e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2945e44e4e7fSToby Isaac PetscScalar val = 0.; 2946e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2947e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2948e44e4e7fSToby Isaac } 2949e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2950e44e4e7fSToby Isaac } 2951e44e4e7fSToby Isaac } 2952e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],pointWork,INSERT_VALUES);CHKERRQ(ierr); 2953e44e4e7fSToby Isaac count += numCols * numInRows; 2954e44e4e7fSToby Isaac } 2955e44e4e7fSToby Isaac } 2956267d4f3fSToby Isaac else { /* every dof gets a full row */ 2957e44e4e7fSToby Isaac PetscInt numRows = gDof; 2958e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2959e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2960e44e4e7fSToby Isaac PetscInt i, j, k; 2961e44e4e7fSToby Isaac if (refPointFieldN[childId - pRefStart][0] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2962e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2963e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2964e44e4e7fSToby Isaac PetscScalar val = 0.; 2965e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2966e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2967e44e4e7fSToby Isaac } 2968e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2969e44e4e7fSToby Isaac } 2970e44e4e7fSToby Isaac } 2971e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,rowIndices,numCols,pInd,pointWork,INSERT_VALUES);CHKERRQ(ierr); 2972e44e4e7fSToby Isaac } 2973e44e4e7fSToby Isaac } 2974e44e4e7fSToby Isaac } 2975e44e4e7fSToby Isaac } 29761c58ffc4SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 297769291d52SBarry Smith ierr = DMRestoreWorkArray(fine,maxDof,MPIU_INT,&rowIndices);CHKERRQ(ierr); 2978e44e4e7fSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 2979e44e4e7fSToby Isaac } 2980e44e4e7fSToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2981e44e4e7fSToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2982e44e4e7fSToby Isaac ierr = PetscSectionDestroy(&leafIndicesSec);CHKERRQ(ierr); 2983e44e4e7fSToby Isaac ierr = PetscSectionDestroy(&leafMatricesSec);CHKERRQ(ierr); 2984e44e4e7fSToby Isaac ierr = PetscFree2(leafIndices,leafMatrices);CHKERRQ(ierr); 29852cd485c2SBarry Smith ierr = PetscFree2(*(PetscInt****)&perms,*(PetscScalar****)&flips);CHKERRQ(ierr); 2986e44e4e7fSToby Isaac ierr = PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO);CHKERRQ(ierr); 29876ecaa68aSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 29886ecaa68aSToby Isaac PetscFunctionReturn(0); 29896ecaa68aSToby Isaac } 2990154bca37SToby Isaac 29918d2f55e7SToby Isaac /* 29928d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 29938d2f55e7SToby Isaac * 29948d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 29958d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 29968d2f55e7SToby Isaac * for each fine dof \phi^f_j; 29978d2f55e7SToby Isaac * a_{i,j} = 0; 29988d2f55e7SToby Isaac * for each fine dof \phi^f_k: 29998d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 30008d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 30018d2f55e7SToby Isaac */ 30028d2f55e7SToby Isaac PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 30038d2f55e7SToby Isaac { 30048d2f55e7SToby Isaac PetscDS ds; 30058d2f55e7SToby Isaac PetscSection section, cSection; 30068d2f55e7SToby Isaac DMLabel canonical, depth; 30078d2f55e7SToby Isaac Mat cMat, mat; 30088d2f55e7SToby Isaac PetscInt *nnz; 30098d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 30108d2f55e7SToby Isaac PetscInt m, n; 30118d2f55e7SToby Isaac PetscScalar *pointScalar; 30128d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 30138d2f55e7SToby Isaac PetscErrorCode ierr; 30148d2f55e7SToby Isaac 30158d2f55e7SToby Isaac PetscFunctionBegin; 301692fd8e1eSJed Brown ierr = DMGetLocalSection(refTree,§ion);CHKERRQ(ierr); 30178d2f55e7SToby Isaac ierr = DMGetDimension(refTree, &dim);CHKERRQ(ierr); 30188d2f55e7SToby Isaac ierr = PetscMalloc6(dim,&v0,dim,&v0parent,dim,&vtmp,dim*dim,&J,dim*dim,&Jparent,dim*dim,&invJ);CHKERRQ(ierr); 30198d2f55e7SToby Isaac ierr = PetscMalloc2(dim,&pointScalar,dim,&pointRef);CHKERRQ(ierr); 30208d2f55e7SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 30218d2f55e7SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 30228d2f55e7SToby Isaac ierr = PetscSectionGetNumFields(section,&numSecFields);CHKERRQ(ierr); 30238d2f55e7SToby Isaac ierr = DMGetLabel(refTree,"canonical",&canonical);CHKERRQ(ierr); 30248d2f55e7SToby Isaac ierr = DMGetLabel(refTree,"depth",&depth);CHKERRQ(ierr); 30258d2f55e7SToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSection,&cMat);CHKERRQ(ierr); 30268d2f55e7SToby Isaac ierr = DMPlexGetChart(refTree, &pStart, &pEnd);CHKERRQ(ierr); 30278d2f55e7SToby Isaac ierr = DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd);CHKERRQ(ierr); 30288d2f55e7SToby Isaac ierr = MatGetSize(cMat,&n,&m);CHKERRQ(ierr); /* the injector has transpose sizes from the constraint matrix */ 30298d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 30308d2f55e7SToby Isaac ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr); 30318d2f55e7SToby 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 */ 30328d2f55e7SToby Isaac const PetscInt *children; 30338d2f55e7SToby Isaac PetscInt numChildren; 30348d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30358d2f55e7SToby Isaac 30368d2f55e7SToby Isaac if (canonical) { 30378d2f55e7SToby Isaac PetscInt pCanonical; 30388d2f55e7SToby Isaac ierr = DMLabelGetValue(canonical,p,&pCanonical);CHKERRQ(ierr); 30398d2f55e7SToby Isaac if (p != pCanonical) continue; 30408d2f55e7SToby Isaac } 30418d2f55e7SToby Isaac ierr = DMPlexGetTreeChildren(refTree,p,&numChildren,&children);CHKERRQ(ierr); 30428d2f55e7SToby Isaac if (!numChildren) continue; 30438d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30448d2f55e7SToby Isaac PetscInt child = children[i]; 30458d2f55e7SToby Isaac PetscInt dof; 30468d2f55e7SToby Isaac 30478d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,child,&dof);CHKERRQ(ierr); 30488d2f55e7SToby Isaac numChildDof += dof; 30498d2f55e7SToby Isaac } 30508d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,p,&numSelfDof);CHKERRQ(ierr); 30518d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30528d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 30538d2f55e7SToby Isaac PetscInt selfOff; 30548d2f55e7SToby Isaac 30558d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 30568d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30578d2f55e7SToby Isaac PetscInt child = children[i]; 30588d2f55e7SToby Isaac PetscInt dof; 30598d2f55e7SToby Isaac 30608d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,child,f,&dof);CHKERRQ(ierr); 30618d2f55e7SToby Isaac numChildDof += dof; 30628d2f55e7SToby Isaac } 30638d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&numSelfDof);CHKERRQ(ierr); 30648d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(section,p,f,&selfOff);CHKERRQ(ierr); 30658d2f55e7SToby Isaac } 30668d2f55e7SToby Isaac else { 30678d2f55e7SToby Isaac ierr = PetscSectionGetOffset(section,p,&selfOff);CHKERRQ(ierr); 30688d2f55e7SToby Isaac } 30698d2f55e7SToby Isaac for (i = 0; i < numSelfDof; i++) { 30708d2f55e7SToby Isaac nnz[selfOff + i] = numChildDof; 30718d2f55e7SToby Isaac } 30728d2f55e7SToby Isaac } 30738d2f55e7SToby Isaac } 30748d2f55e7SToby Isaac ierr = MatCreateAIJ(PETSC_COMM_SELF,m,n,m,n,-1,nnz,-1,NULL,&mat);CHKERRQ(ierr); 30758d2f55e7SToby Isaac ierr = PetscFree(nnz);CHKERRQ(ierr); 30768d2f55e7SToby Isaac /* Setp 2: compute entries */ 30778d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 30788d2f55e7SToby Isaac const PetscInt *children; 30798d2f55e7SToby Isaac PetscInt numChildren; 30808d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30818d2f55e7SToby Isaac 30828d2f55e7SToby Isaac /* same conditions about when entries occur */ 30838d2f55e7SToby Isaac if (canonical) { 30848d2f55e7SToby Isaac PetscInt pCanonical; 30858d2f55e7SToby Isaac ierr = DMLabelGetValue(canonical,p,&pCanonical);CHKERRQ(ierr); 30868d2f55e7SToby Isaac if (p != pCanonical) continue; 30878d2f55e7SToby Isaac } 30888d2f55e7SToby Isaac ierr = DMPlexGetTreeChildren(refTree,p,&numChildren,&children);CHKERRQ(ierr); 30898d2f55e7SToby Isaac if (!numChildren) continue; 30908d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30918d2f55e7SToby Isaac PetscInt child = children[i]; 30928d2f55e7SToby Isaac PetscInt dof; 30938d2f55e7SToby Isaac 30948d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,child,&dof);CHKERRQ(ierr); 30958d2f55e7SToby Isaac numChildDof += dof; 30968d2f55e7SToby Isaac } 30978d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,p,&numSelfDof);CHKERRQ(ierr); 30988d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30998d2f55e7SToby Isaac 31008d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 310159fc6756SToby Isaac PetscInt pI = -1, cI = -1; 310252a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell; 31038d2f55e7SToby Isaac PetscInt cellShapeOff; 31048d2f55e7SToby Isaac PetscObject disc; 31058d2f55e7SToby Isaac PetscDualSpace dsp; 31068d2f55e7SToby Isaac PetscClassId classId; 31078d2f55e7SToby Isaac PetscScalar *pointMat; 31083b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 31098d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 31108d2f55e7SToby Isaac const PetscInt *depthNumDof; 31118d2f55e7SToby Isaac 31128d2f55e7SToby Isaac if (numSecFields) { 31138d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 31148d2f55e7SToby Isaac PetscInt child = children[i]; 31158d2f55e7SToby Isaac PetscInt dof; 31168d2f55e7SToby Isaac 31178d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,child,f,&dof);CHKERRQ(ierr); 31188d2f55e7SToby Isaac numChildDof += dof; 31198d2f55e7SToby Isaac } 31208d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&numSelfDof);CHKERRQ(ierr); 31218d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(section,p,f,&selfOff);CHKERRQ(ierr); 31228d2f55e7SToby Isaac } 31238d2f55e7SToby Isaac else { 31248d2f55e7SToby Isaac ierr = PetscSectionGetOffset(section,p,&selfOff);CHKERRQ(ierr); 31258d2f55e7SToby Isaac } 31268d2f55e7SToby Isaac 31273b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 31288d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 31298d2f55e7SToby Isaac parentCell = p; 31308d2f55e7SToby Isaac } 31318d2f55e7SToby Isaac else { 31328d2f55e7SToby Isaac PetscInt *star = NULL; 31338d2f55e7SToby Isaac PetscInt numStar; 31348d2f55e7SToby Isaac 31358d2f55e7SToby Isaac parentCell = -1; 31368d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 31378d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 31388d2f55e7SToby Isaac PetscInt c = star[2 * i]; 31398d2f55e7SToby Isaac 31408d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 31418d2f55e7SToby Isaac parentCell = c; 31428d2f55e7SToby Isaac break; 31438d2f55e7SToby Isaac } 31448d2f55e7SToby Isaac } 31458d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 31468d2f55e7SToby Isaac } 31478d2f55e7SToby Isaac /* determine the offset of p's shape functions withing parentCell's shape functions */ 3148c5356c36SToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 3149c5356c36SToby Isaac ierr = PetscObjectGetClassId(disc,&classId);CHKERRQ(ierr); 3150c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 3151c5356c36SToby Isaac ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 3152c5356c36SToby Isaac } 3153c5356c36SToby Isaac else if (classId == PETSCFV_CLASSID) { 3154c5356c36SToby Isaac ierr = PetscFVGetDualSpace((PetscFV)disc,&dsp);CHKERRQ(ierr); 3155c5356c36SToby Isaac } 3156c5356c36SToby Isaac else { 31579b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported discretization object"); 3158c5356c36SToby Isaac } 31598d2f55e7SToby Isaac ierr = PetscDualSpaceGetNumDof(dsp,&depthNumDof);CHKERRQ(ierr); 316052a3aeb4SToby Isaac ierr = PetscDualSpaceGetNumComponents(dsp,&Nc);CHKERRQ(ierr); 31618d2f55e7SToby Isaac { 31628d2f55e7SToby Isaac PetscInt *closure = NULL; 31638d2f55e7SToby Isaac PetscInt numClosure; 31648d2f55e7SToby Isaac 31658d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 316659fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) { 31678d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 31688d2f55e7SToby Isaac 31698d2f55e7SToby Isaac pO = closure[2 * i + 1]; 317059fc6756SToby Isaac if (point == p) { 317159fc6756SToby Isaac pI = i; 317259fc6756SToby Isaac break; 317359fc6756SToby Isaac } 31748d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,point,&pointDepth);CHKERRQ(ierr); 31758d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 31768d2f55e7SToby Isaac } 31778d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 31788d2f55e7SToby Isaac } 31798d2f55e7SToby Isaac 318069291d52SBarry Smith ierr = DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR,&pointMat);CHKERRQ(ierr); 318169291d52SBarry Smith ierr = DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT,&matRows);CHKERRQ(ierr); 318252a3aeb4SToby Isaac matCols = matRows + numSelfDof; 318352a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { 318452a3aeb4SToby Isaac matRows[i] = selfOff + i; 31853b1c2a6aSToby Isaac } 318652a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.; 31873b1c2a6aSToby Isaac { 31883b1c2a6aSToby Isaac PetscInt colOff = 0; 31893b1c2a6aSToby Isaac 31903b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 31913b1c2a6aSToby Isaac PetscInt child = children[i]; 31923b1c2a6aSToby Isaac PetscInt dof, off, j; 31933b1c2a6aSToby Isaac 31943b1c2a6aSToby Isaac if (numSecFields) { 3195c5356c36SToby Isaac ierr = PetscSectionGetFieldDof(cSection,child,f,&dof);CHKERRQ(ierr); 3196c5356c36SToby Isaac ierr = PetscSectionGetFieldOffset(cSection,child,f,&off);CHKERRQ(ierr); 31973b1c2a6aSToby Isaac } 31983b1c2a6aSToby Isaac else { 3199c5356c36SToby Isaac ierr = PetscSectionGetDof(cSection,child,&dof);CHKERRQ(ierr); 3200c5356c36SToby Isaac ierr = PetscSectionGetOffset(cSection,child,&off);CHKERRQ(ierr); 32013b1c2a6aSToby Isaac } 32023b1c2a6aSToby Isaac 320352a3aeb4SToby Isaac for (j = 0; j < dof; j++) { 320452a3aeb4SToby Isaac matCols[colOff++] = off + j; 32053b1c2a6aSToby Isaac } 32063b1c2a6aSToby Isaac } 32073b1c2a6aSToby Isaac } 32088d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 32098d2f55e7SToby Isaac PetscFE fe = (PetscFE) disc; 32108d2f55e7SToby Isaac PetscInt fSize; 321159fc6756SToby Isaac const PetscInt ***perms; 321259fc6756SToby Isaac const PetscScalar ***flips; 321359fc6756SToby Isaac const PetscInt *pperms; 321459fc6756SToby Isaac 32158d2f55e7SToby Isaac ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr); 32163b1c2a6aSToby Isaac ierr = PetscDualSpaceGetDimension(dsp,&fSize);CHKERRQ(ierr); 321759fc6756SToby Isaac ierr = PetscDualSpaceGetSymmetries(dsp, &perms, &flips);CHKERRQ(ierr); 321859fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL; 321952a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */ 32208d2f55e7SToby Isaac PetscQuadrature q; 322152a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k; 32228d2f55e7SToby Isaac const PetscReal *points; 32238d2f55e7SToby Isaac const PetscReal *weights; 32248d2f55e7SToby Isaac PetscInt *closure = NULL; 32258d2f55e7SToby Isaac PetscInt numClosure; 322659fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i; 322759fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell; 3228ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent; 32298d2f55e7SToby Isaac 32303b1c2a6aSToby Isaac ierr = PetscDualSpaceGetFunctional(dsp,parentCellShapeDof,&q);CHKERRQ(ierr); 323152a3aeb4SToby Isaac ierr = PetscQuadratureGetData(q,&dim,&thisNc,&numPoints,&points,&weights);CHKERRQ(ierr); 323252a3aeb4SToby Isaac if (thisNc != Nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Functional dim %D does not much basis dim %D\n",thisNc,Nc); 3233ef0bb6c7SMatthew G. Knepley ierr = PetscFECreateTabulation(fe,1,numPoints,points,0,&Tparent);CHKERRQ(ierr); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 32343b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 32358d2f55e7SToby Isaac PetscInt childCell = -1; 323652a3aeb4SToby Isaac PetscReal *parentValAtPoint; 3237c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 32388d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 32398d2f55e7SToby Isaac const PetscScalar *point; 3240ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild; 32418d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 32428d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 32438d2f55e7SToby Isaac PetscInt d; 32448d2f55e7SToby Isaac 32458d2f55e7SToby Isaac for (d = 0; d < dim; d++) { 32468d2f55e7SToby Isaac pointScalar[d] = points[dim * j + d]; 32478d2f55e7SToby Isaac } 32488d2f55e7SToby Isaac point = pointScalar; 32498d2f55e7SToby Isaac #else 32508d2f55e7SToby Isaac point = pointReal; 32518d2f55e7SToby Isaac #endif 32528d2f55e7SToby Isaac 3253ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc]; 32543b1c2a6aSToby Isaac 32553b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 32568d2f55e7SToby Isaac PetscInt child = children[k]; 32578d2f55e7SToby Isaac PetscInt *star = NULL; 32588d2f55e7SToby Isaac PetscInt numStar, s; 32598d2f55e7SToby Isaac 32608d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 32618d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 32628d2f55e7SToby Isaac PetscInt c = star[2 * s]; 32638d2f55e7SToby Isaac 32648d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 32658d2f55e7SToby Isaac ierr = DMPlexLocatePoint_Internal(refTree,dim,point,c,&childCell);CHKERRQ(ierr); 32668d2f55e7SToby Isaac if (childCell >= 0) break; 32678d2f55e7SToby Isaac } 32688d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 32698d2f55e7SToby Isaac if (childCell >= 0) break; 32708d2f55e7SToby Isaac } 327113903a91SSatish Balay if (childCell < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not locate quadrature point"); 32728d2f55e7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 32738d2f55e7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent);CHKERRQ(ierr); 3274c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp); 3275c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef); 32768d2f55e7SToby Isaac 3277ef0bb6c7SMatthew G. Knepley ierr = PetscFECreateTabulation(fe,1,1,pointRef,0,&Tchild);CHKERRQ(ierr); 32788d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 32793b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3280c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 32818d2f55e7SToby Isaac PetscInt l; 328259fc6756SToby Isaac const PetscInt *cperms; 32838d2f55e7SToby Isaac 32848d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,child,&childDepth);CHKERRQ(ierr); 32858d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 328659fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) { 32878d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 32888d2f55e7SToby Isaac PetscInt pointDepth; 32898d2f55e7SToby Isaac 32908d2f55e7SToby Isaac childO = closure[2 * l + 1]; 329159fc6756SToby Isaac if (point == child) { 329259fc6756SToby Isaac cI = l; 329359fc6756SToby Isaac break; 329459fc6756SToby Isaac } 32958d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,point,&pointDepth);CHKERRQ(ierr); 32968d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 32978d2f55e7SToby Isaac } 32988d2f55e7SToby Isaac if (l == numClosure) { 32998d2f55e7SToby Isaac pointMatOff += childDof; 33008d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 33018d2f55e7SToby Isaac } 330259fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL; 33038d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 330459fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l; 330559fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell; 330652a3aeb4SToby Isaac PetscReal *childValAtPoint; 330752a3aeb4SToby Isaac PetscReal val = 0.; 33088d2f55e7SToby Isaac 3309ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc]; 331052a3aeb4SToby Isaac for (m = 0; m < Nc; m++) { 331152a3aeb4SToby Isaac val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m]; 331252a3aeb4SToby Isaac } 331352a3aeb4SToby Isaac 331452a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val; 33158d2f55e7SToby Isaac } 33168d2f55e7SToby Isaac pointMatOff += childDof; 33178d2f55e7SToby Isaac } 33188d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 3319ef0bb6c7SMatthew G. Knepley ierr = PetscTabulationDestroy(&Tchild);CHKERRQ(ierr); 33208d2f55e7SToby Isaac } 3321ef0bb6c7SMatthew G. Knepley ierr = PetscTabulationDestroy(&Tparent);CHKERRQ(ierr); 33228d2f55e7SToby Isaac } 33238d2f55e7SToby Isaac } 3324c5356c36SToby Isaac else { /* just the volume-weighted averages of the children */ 33253b1c2a6aSToby Isaac PetscReal parentVol; 3326bfaa5bdcSToby Isaac PetscInt childCell; 33273b1c2a6aSToby Isaac 33283b1c2a6aSToby Isaac ierr = DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL);CHKERRQ(ierr); 3329bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) { 333052a3aeb4SToby Isaac PetscInt child = children[i], j; 33313b1c2a6aSToby Isaac PetscReal childVol; 33323b1c2a6aSToby Isaac 33333b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 33343b1c2a6aSToby Isaac ierr = DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL);CHKERRQ(ierr); 333552a3aeb4SToby Isaac for (j = 0; j < Nc; j++) { 3336bfaa5bdcSToby Isaac pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol; 333752a3aeb4SToby Isaac } 3338bfaa5bdcSToby Isaac childCell++; 33393b1c2a6aSToby Isaac } 33408d2f55e7SToby Isaac } 33413b1c2a6aSToby Isaac /* Insert pointMat into mat */ 334252a3aeb4SToby Isaac ierr = MatSetValues(mat,numSelfDof,matRows,numChildDof,matCols,pointMat,INSERT_VALUES);CHKERRQ(ierr); 334369291d52SBarry Smith ierr = DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT,&matRows);CHKERRQ(ierr); 334469291d52SBarry Smith ierr = DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR,&pointMat);CHKERRQ(ierr); 33458d2f55e7SToby Isaac } 33468d2f55e7SToby Isaac } 33473b1c2a6aSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJ);CHKERRQ(ierr); 33488d2f55e7SToby Isaac ierr = PetscFree2(pointScalar,pointRef);CHKERRQ(ierr); 33493b1c2a6aSToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 33503b1c2a6aSToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 33518d2f55e7SToby Isaac *inj = mat; 33528d2f55e7SToby Isaac PetscFunctionReturn(0); 33538d2f55e7SToby Isaac } 33548d2f55e7SToby Isaac 3355f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3356f30e825dSToby Isaac { 3357f30e825dSToby Isaac PetscDS ds; 3358f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3359f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3360f30e825dSToby Isaac PetscSection refConSec, refSection; 3361f30e825dSToby Isaac PetscErrorCode ierr; 3362f30e825dSToby Isaac 3363f30e825dSToby Isaac PetscFunctionBegin; 3364f30e825dSToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 3365f30e825dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 3366f30e825dSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 336792fd8e1eSJed Brown ierr = DMGetLocalSection(refTree,&refSection);CHKERRQ(ierr); 3368f30e825dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3369f30e825dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr); 3370f30e825dSToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 3371f30e825dSToby Isaac ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr); 3372f30e825dSToby Isaac ierr = PetscMalloc1(maxDof*maxDof,&cols);CHKERRQ(ierr); 3373f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3374f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3375f30e825dSToby Isaac 3376f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 3377f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 3378c6154584SToby Isaac ierr = PetscSectionGetDof(refSection,parent,&parentDof);CHKERRQ(ierr); 3379f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3380f30e825dSToby Isaac 3381f30e825dSToby Isaac ierr = PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr); 3382f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 338352a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r; 3384f30e825dSToby Isaac 3385f30e825dSToby Isaac if (numFields > 1) { 3386f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 3387f30e825dSToby Isaac ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr); 3388f30e825dSToby Isaac } 3389f30e825dSToby Isaac else { 3390f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 3391f30e825dSToby Isaac ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr); 3392f30e825dSToby Isaac } 3393f30e825dSToby Isaac 3394f30e825dSToby Isaac for (r = 0; r < cDof; r++) { 3395f30e825dSToby Isaac rows[r] = cOff + r; 3396f30e825dSToby Isaac } 3397f30e825dSToby Isaac numCols = 0; 3398f30e825dSToby Isaac { 3399f30e825dSToby Isaac PetscInt aDof, aOff, j; 3400f30e825dSToby Isaac 3401f30e825dSToby Isaac if (numFields > 1) { 3402f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refSection,parent,f,&aDof);CHKERRQ(ierr); 3403f30e825dSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,parent,f,&aOff);CHKERRQ(ierr); 3404f30e825dSToby Isaac } 3405f30e825dSToby Isaac else { 3406f30e825dSToby Isaac ierr = PetscSectionGetDof(refSection,parent,&aDof);CHKERRQ(ierr); 3407f30e825dSToby Isaac ierr = PetscSectionGetOffset(refSection,parent,&aOff);CHKERRQ(ierr); 3408f30e825dSToby Isaac } 3409f30e825dSToby Isaac 3410f30e825dSToby Isaac for (j = 0; j < aDof; j++) { 3411f30e825dSToby Isaac cols[numCols++] = aOff + j; 3412f30e825dSToby Isaac } 3413f30e825dSToby Isaac } 3414f30e825dSToby Isaac ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 3415f30e825dSToby Isaac /* transpose of constraint matrix */ 3416f30e825dSToby Isaac ierr = MatGetValues(inj,numCols,cols,cDof,rows,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 3417f30e825dSToby Isaac } 3418f30e825dSToby Isaac } 3419f30e825dSToby Isaac *childrenMats = refPointFieldMats; 3420f30e825dSToby Isaac ierr = PetscFree(rows);CHKERRQ(ierr); 3421f30e825dSToby Isaac ierr = PetscFree(cols);CHKERRQ(ierr); 3422f30e825dSToby Isaac PetscFunctionReturn(0); 3423f30e825dSToby Isaac } 3424f30e825dSToby Isaac 3425f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3426f30e825dSToby Isaac { 3427f30e825dSToby Isaac PetscDS ds; 3428f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3429f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3430c6154584SToby Isaac PetscSection refConSec, refSection; 3431f30e825dSToby Isaac PetscErrorCode ierr; 3432f30e825dSToby Isaac 3433f30e825dSToby Isaac PetscFunctionBegin; 3434f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3435f30e825dSToby Isaac *childrenMats = NULL; 3436f30e825dSToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 343792fd8e1eSJed Brown ierr = DMGetLocalSection(refTree,&refSection);CHKERRQ(ierr); 3438f30e825dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 3439f30e825dSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 3440f30e825dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3441f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3442f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3443f30e825dSToby Isaac 3444f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 3445f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 3446c6154584SToby Isaac ierr = PetscSectionGetDof(refSection,parent,&parentDof);CHKERRQ(ierr); 3447f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3448f30e825dSToby Isaac 3449f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3450f30e825dSToby Isaac PetscInt cDof; 3451f30e825dSToby Isaac 3452f30e825dSToby Isaac if (numFields > 1) { 3453f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 3454f30e825dSToby Isaac } 3455f30e825dSToby Isaac else { 3456f30e825dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 3457f30e825dSToby Isaac } 3458f30e825dSToby Isaac 3459f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr); 3460f30e825dSToby Isaac } 3461f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr); 3462f30e825dSToby Isaac } 3463f30e825dSToby Isaac ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr); 3464f30e825dSToby Isaac PetscFunctionReturn(0); 3465f30e825dSToby Isaac } 3466f30e825dSToby Isaac 3467ebf164c7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree,Mat *injRef) 3468154bca37SToby Isaac { 3469ebf164c7SToby Isaac Mat cMatRef; 34706148253fSToby Isaac PetscObject injRefObj; 34718d2f55e7SToby Isaac PetscErrorCode ierr; 34728d2f55e7SToby Isaac 3473154bca37SToby Isaac PetscFunctionBegin; 3474ebf164c7SToby Isaac ierr = DMGetDefaultConstraints(refTree,NULL,&cMatRef);CHKERRQ(ierr); 34756148253fSToby Isaac ierr = PetscObjectQuery((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",&injRefObj);CHKERRQ(ierr); 3476ebf164c7SToby Isaac *injRef = (Mat) injRefObj; 3477ebf164c7SToby Isaac if (!*injRef) { 3478ebf164c7SToby Isaac ierr = DMPlexComputeInjectorReferenceTree(refTree,injRef);CHKERRQ(ierr); 3479ebf164c7SToby Isaac ierr = PetscObjectCompose((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",(PetscObject)*injRef);CHKERRQ(ierr); 3480ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 3481ebf164c7SToby Isaac ierr = PetscObjectDereference((PetscObject)*injRef);CHKERRQ(ierr); 3482ebf164c7SToby Isaac } 3483ebf164c7SToby Isaac PetscFunctionReturn(0); 34846148253fSToby Isaac } 3485f30e825dSToby Isaac 3486c921d74cSToby 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) 3487ebf164c7SToby Isaac { 3488c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3489ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3490ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3491c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3492c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3493c921d74cSToby Isaac const PetscInt *rootDegrees; 3494c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3495ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3496ebf164c7SToby Isaac PetscErrorCode ierr; 3497ebf164c7SToby Isaac 3498ebf164c7SToby Isaac PetscFunctionBegin; 3499ebf164c7SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 35008d2f55e7SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 350192fd8e1eSJed Brown ierr = DMGetLocalSection(fine,&localFine);CHKERRQ(ierr); 3502e87a4003SBarry Smith ierr = DMGetGlobalSection(fine,&globalFine);CHKERRQ(ierr); 3503f30e825dSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr); 3504f30e825dSToby Isaac ierr = PetscSectionSetChart(leafIndicesSec,pStartF, pEndF);CHKERRQ(ierr); 3505c921d74cSToby Isaac ierr = PetscSectionGetMaxDof(localFine,&maxDof);CHKERRQ(ierr); 35068d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 35077e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 35087e96bdafSToby Isaac const PetscInt *leaves; 35098d2f55e7SToby Isaac 35107e96bdafSToby Isaac ierr = PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 35117e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 35127e96bdafSToby Isaac p = leaves ? leaves[l] : l; 35138d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 35148d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 35158d2f55e7SToby Isaac if ((dof - cdof) > 0) { 35168d2f55e7SToby Isaac numPointsWithDofs++; 3517f30e825dSToby Isaac 3518f30e825dSToby Isaac ierr = PetscSectionGetDof(localFine,p,&dof);CHKERRQ(ierr); 3519f30e825dSToby Isaac ierr = PetscSectionSetDof(leafIndicesSec,p,dof + 1);CHKERRQ(ierr); 35208d2f55e7SToby Isaac } 35218d2f55e7SToby Isaac } 35228d2f55e7SToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 3523f30e825dSToby Isaac ierr = PetscSectionSetUp(leafIndicesSec);CHKERRQ(ierr); 3524f30e825dSToby Isaac ierr = PetscSectionGetStorageSize(leafIndicesSec,&numIndices);CHKERRQ(ierr); 3525c921d74cSToby Isaac ierr = PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1),&leafInds);CHKERRQ(ierr); 3526c921d74cSToby Isaac if (gatheredValues) {ierr = PetscMalloc1(numIndices,&leafVals);CHKERRQ(ierr);} 35277e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 35287e96bdafSToby Isaac p = leaves ? leaves[l] : l; 35298d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 35308d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 35318d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3532f30e825dSToby Isaac PetscInt off, gOff; 3533f30e825dSToby Isaac PetscInt *pInd; 3534c921d74cSToby Isaac PetscScalar *pVal = NULL; 3535f30e825dSToby Isaac 35367e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3537f30e825dSToby Isaac 3538f30e825dSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&off);CHKERRQ(ierr); 3539f30e825dSToby Isaac 3540c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3541c921d74cSToby Isaac if (gatheredValues) { 3542c921d74cSToby Isaac PetscInt i; 3543c921d74cSToby Isaac 3544c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3545c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3546c921d74cSToby Isaac } 3547f30e825dSToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 3548f30e825dSToby Isaac 3549f30e825dSToby Isaac offsets[0] = 0; 3550f30e825dSToby Isaac if (numFields) { 3551f30e825dSToby Isaac PetscInt f; 3552f30e825dSToby Isaac 3553f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3554f30e825dSToby Isaac PetscInt fDof; 3555f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&fDof);CHKERRQ(ierr); 3556f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3557f30e825dSToby Isaac } 355836fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,-1, NULL,pInd);CHKERRQ(ierr); 3559367003a6SStefano Zampini } else { 356036fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL, NULL,pInd);CHKERRQ(ierr); 3561f30e825dSToby Isaac } 3562c921d74cSToby Isaac if (gatheredValues) {ierr = VecGetValues(fineVec,dof,pInd,pVal);CHKERRQ(ierr);} 35638d2f55e7SToby Isaac } 35648d2f55e7SToby Isaac } 35658d2f55e7SToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 3566f30e825dSToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 35678d2f55e7SToby Isaac } 3568f30e825dSToby Isaac 3569f30e825dSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 357092fd8e1eSJed Brown ierr = DMGetLocalSection(coarse,&localCoarse);CHKERRQ(ierr); 3571e87a4003SBarry Smith ierr = DMGetGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 3572f30e825dSToby Isaac 35736148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 35746148253fSToby Isaac MPI_Datatype threeInt; 35756148253fSToby Isaac PetscMPIInt rank; 35766148253fSToby Isaac PetscInt (*parentNodeAndIdCoarse)[3]; 35776148253fSToby Isaac PetscInt (*parentNodeAndIdFine)[3]; 35786148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 35796148253fSToby Isaac PetscSF pointSF, sfToParents; 35806148253fSToby Isaac const PetscInt *ilocal; 35816148253fSToby Isaac const PetscSFNode *iremote; 35826148253fSToby Isaac PetscSFNode *iremoteToParents; 35836148253fSToby Isaac PetscInt *ilocalToParents; 35846148253fSToby Isaac 3585ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)coarse),&rank);CHKERRMPI(ierr); 3586ffc4695bSBarry Smith ierr = MPI_Type_contiguous(3,MPIU_INT,&threeInt);CHKERRMPI(ierr); 3587ffc4695bSBarry Smith ierr = MPI_Type_commit(&threeInt);CHKERRMPI(ierr); 35886148253fSToby Isaac ierr = PetscMalloc2(pEndC-pStartC,&parentNodeAndIdCoarse,pEndF-pStartF,&parentNodeAndIdFine);CHKERRQ(ierr); 35896148253fSToby Isaac ierr = DMGetPointSF(coarse,&pointSF);CHKERRQ(ierr); 35906148253fSToby Isaac ierr = PetscSFGetGraph(pointSF,NULL,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 35916148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 35926148253fSToby Isaac PetscInt parent, childId; 35936148253fSToby Isaac ierr = DMPlexGetTreeParent(coarse,p,&parent,&childId);CHKERRQ(ierr); 35946148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 35956148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 35966148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 35976148253fSToby Isaac if (nleaves > 0) { 35986148253fSToby Isaac PetscInt leaf = -1; 35996148253fSToby Isaac 36006148253fSToby Isaac if (ilocal) { 36016148253fSToby Isaac ierr = PetscFindInt(parent,nleaves,ilocal,&leaf);CHKERRQ(ierr); 36026148253fSToby Isaac } 36036148253fSToby Isaac else { 36046148253fSToby Isaac leaf = p - pStartC; 36056148253fSToby Isaac } 36066148253fSToby Isaac if (leaf >= 0) { 36076148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 36086148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 36096148253fSToby Isaac } 36106148253fSToby Isaac } 36116148253fSToby Isaac } 36126148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 36136148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 36146148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 36156148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 36166148253fSToby Isaac } 3617ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine,MPI_REPLACE);CHKERRQ(ierr); 3618ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine,MPI_REPLACE);CHKERRQ(ierr); 36196148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3620f30e825dSToby Isaac PetscInt dof; 3621f30e825dSToby Isaac 3622f30e825dSToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&dof);CHKERRQ(ierr); 3623f30e825dSToby Isaac if (dof) { 3624f30e825dSToby Isaac PetscInt off; 3625f30e825dSToby Isaac 3626f30e825dSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&off);CHKERRQ(ierr); 3627c921d74cSToby Isaac if (gatheredIndices) { 3628c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3629c921d74cSToby Isaac } else if (gatheredValues) { 3630c921d74cSToby Isaac leafVals[off] = (PetscScalar) PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3631c921d74cSToby Isaac } 3632f30e825dSToby Isaac } 36336148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36346148253fSToby Isaac nleavesToParents++; 36356148253fSToby Isaac } 36366148253fSToby Isaac } 36376148253fSToby Isaac ierr = PetscMalloc1(nleavesToParents,&ilocalToParents);CHKERRQ(ierr); 36386148253fSToby Isaac ierr = PetscMalloc1(nleavesToParents,&iremoteToParents);CHKERRQ(ierr); 36396148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 36406148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36416148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 36426148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p-pStartF][0]; 36436148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p-pStartF][1]; 36446148253fSToby Isaac nleavesToParents++; 36456148253fSToby Isaac } 36466148253fSToby Isaac } 36476148253fSToby Isaac ierr = PetscSFCreate(PetscObjectComm((PetscObject)coarse),&sfToParents);CHKERRQ(ierr); 36486148253fSToby Isaac ierr = PetscSFSetGraph(sfToParents,pEndC-pStartC,nleavesToParents,ilocalToParents,PETSC_OWN_POINTER,iremoteToParents,PETSC_OWN_POINTER);CHKERRQ(ierr); 36496148253fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 36506148253fSToby Isaac 36516148253fSToby Isaac coarseToFineEmbedded = sfToParents; 36526148253fSToby Isaac 36536148253fSToby Isaac ierr = PetscFree2(parentNodeAndIdCoarse,parentNodeAndIdFine);CHKERRQ(ierr); 3654ffc4695bSBarry Smith ierr = MPI_Type_free(&threeInt);CHKERRMPI(ierr); 36556148253fSToby Isaac } 3656f30e825dSToby Isaac 36576148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 36586148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 36596148253fSToby Isaac PetscSF sfDofsOnly; 36606148253fSToby Isaac 36616148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 36626148253fSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 36636148253fSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 36646148253fSToby Isaac if ((dof - cdof) > 0) { 36656148253fSToby Isaac numPointsWithDofs++; 36666148253fSToby Isaac } 36676148253fSToby Isaac } 36686148253fSToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 36696148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 36706148253fSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 36716148253fSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 36726148253fSToby Isaac if ((dof - cdof) > 0) { 3673e03d9830SToby Isaac pointsWithDofs[offset++] = p - pStartC; 36746148253fSToby Isaac } 36756148253fSToby Isaac } 367672502a1fSJunchao Zhang ierr = PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly);CHKERRQ(ierr); 36776148253fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 3678f30e825dSToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 36796148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 36806148253fSToby Isaac } 3681f30e825dSToby Isaac 36826148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 3683f30e825dSToby Isaac ierr = PetscSFComputeDegreeBegin(coarseToFineEmbedded,&rootDegrees);CHKERRQ(ierr); 3684f30e825dSToby Isaac ierr = PetscSFComputeDegreeEnd(coarseToFineEmbedded,&rootDegrees);CHKERRQ(ierr); 3685f30e825dSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&multiRootSec);CHKERRQ(ierr); 3686f30e825dSToby Isaac ierr = PetscSectionSetChart(multiRootSec,pStartC,pEndC);CHKERRQ(ierr); 36878d2f55e7SToby Isaac for (p = pStartC; p < pEndC; p++) { 3688f30e825dSToby Isaac ierr = PetscSectionSetDof(multiRootSec,p,rootDegrees[p-pStartC]);CHKERRQ(ierr); 36898d2f55e7SToby Isaac } 3690f30e825dSToby Isaac ierr = PetscSectionSetUp(multiRootSec);CHKERRQ(ierr); 3691f30e825dSToby Isaac ierr = PetscSectionGetStorageSize(multiRootSec,&numMulti);CHKERRQ(ierr); 36928d2f55e7SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec);CHKERRQ(ierr); 3693f30e825dSToby Isaac { /* distribute the leaf section */ 3694f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3695f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 36968d2f55e7SToby Isaac 3697f30e825dSToby Isaac ierr = PetscSFGetMultiSF(coarseToFineEmbedded,&multi);CHKERRQ(ierr); 3698f30e825dSToby Isaac ierr = PetscSFCreateInverseSF(multi,&multiInv);CHKERRQ(ierr); 3699f30e825dSToby Isaac ierr = PetscSFDistributeSection(multiInv,leafIndicesSec,&remoteOffsets,rootIndicesSec);CHKERRQ(ierr); 3700f30e825dSToby Isaac ierr = PetscSFCreateSectionSF(multiInv,leafIndicesSec,remoteOffsets,rootIndicesSec,&indicesSF);CHKERRQ(ierr); 3701f30e825dSToby Isaac ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 3702f30e825dSToby Isaac ierr = PetscSFDestroy(&multiInv);CHKERRQ(ierr); 37038d2f55e7SToby Isaac ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr); 3704c921d74cSToby Isaac if (gatheredIndices) { 3705c921d74cSToby Isaac ierr = PetscMalloc1(numRootIndices,&rootInds);CHKERRQ(ierr); 3706ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,leafInds,rootInds,MPI_REPLACE);CHKERRQ(ierr); 3707ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,leafInds,rootInds,MPI_REPLACE);CHKERRQ(ierr); 3708c921d74cSToby Isaac } 3709c921d74cSToby Isaac if (gatheredValues) { 3710c921d74cSToby Isaac ierr = PetscMalloc1(numRootIndices,&rootVals);CHKERRQ(ierr); 3711ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(indicesSF,MPIU_SCALAR,leafVals,rootVals,MPI_REPLACE);CHKERRQ(ierr); 3712ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(indicesSF,MPIU_SCALAR,leafVals,rootVals,MPI_REPLACE);CHKERRQ(ierr); 3713c921d74cSToby Isaac } 37148d2f55e7SToby Isaac ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr); 37158d2f55e7SToby Isaac } 3716ec92bd66SToby Isaac ierr = PetscSectionDestroy(&leafIndicesSec);CHKERRQ(ierr); 3717c921d74cSToby Isaac ierr = PetscFree(leafInds);CHKERRQ(ierr); 3718c921d74cSToby Isaac ierr = PetscFree(leafVals);CHKERRQ(ierr); 3719f30e825dSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 3720c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3721c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3722c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3723c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 3724ebf164c7SToby Isaac PetscFunctionReturn(0); 3725ebf164c7SToby Isaac } 3726ebf164c7SToby Isaac 3727ebf164c7SToby Isaac PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3728ebf164c7SToby Isaac { 3729ebf164c7SToby Isaac DM refTree; 3730c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3731ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3732ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3733ebf164c7SToby Isaac PetscSection cSecRef; 3734277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd; 3735ebf164c7SToby Isaac Mat injRef; 3736c921d74cSToby Isaac PetscInt numFields, maxDof; 3737ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3738ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3739ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3740ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3741ebf164c7SToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3742ebf164c7SToby Isaac PetscErrorCode ierr; 3743ebf164c7SToby Isaac 3744ebf164c7SToby Isaac PetscFunctionBegin; 3745ebf164c7SToby Isaac 3746ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 3747ebf164c7SToby Isaac ierr = DMPlexGetReferenceTree(coarse,&refTree);CHKERRQ(ierr); 3748ebf164c7SToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSecRef,NULL);CHKERRQ(ierr); 3749ebf164c7SToby Isaac ierr = PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3750ebf164c7SToby Isaac ierr = DMPlexReferenceTreeGetInjector(refTree,&injRef);CHKERRQ(ierr); 3751ebf164c7SToby Isaac 3752ebf164c7SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 375392fd8e1eSJed Brown ierr = DMGetLocalSection(fine,&localFine);CHKERRQ(ierr); 3754e87a4003SBarry Smith ierr = DMGetGlobalSection(fine,&globalFine);CHKERRQ(ierr); 3755ebf164c7SToby Isaac ierr = PetscSectionGetNumFields(localFine,&numFields);CHKERRQ(ierr); 3756ebf164c7SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 375792fd8e1eSJed Brown ierr = DMGetLocalSection(coarse,&localCoarse);CHKERRQ(ierr); 3758e87a4003SBarry Smith ierr = DMGetGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 3759ebf164c7SToby Isaac ierr = PetscSectionGetMaxDof(localCoarse,&maxDof);CHKERRQ(ierr); 3760ebf164c7SToby Isaac { 3761ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 3762ebf164c7SToby Isaac ierr = PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets);CHKERRQ(ierr); 3763ebf164c7SToby Isaac } 3764ebf164c7SToby Isaac 3765c921d74cSToby Isaac ierr = DMPlexTransferInjectorTree(coarse,fine,coarseToFine,childIds,NULL,numFields,offsets,&multiRootSec,&rootIndicesSec,&rootIndices,NULL);CHKERRQ(ierr); 37668d2f55e7SToby Isaac 3767f30e825dSToby Isaac ierr = PetscMalloc1(maxDof,&parentIndices);CHKERRQ(ierr); 3768f30e825dSToby Isaac 3769f30e825dSToby Isaac /* count indices */ 37708d2f55e7SToby Isaac ierr = MatGetLayouts(mat,&rowMap,&colMap);CHKERRQ(ierr); 3771c6154584SToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 3772c6154584SToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 37738d2f55e7SToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 37748d2f55e7SToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 3775f30e825dSToby Isaac ierr = PetscCalloc2(rowEnd-rowStart,&nnzD,rowEnd-rowStart,&nnzO);CHKERRQ(ierr); 3776f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3777f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 37788d2f55e7SToby Isaac 3779f30e825dSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 3780f30e825dSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 3781f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 3782f30e825dSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 37838d2f55e7SToby Isaac 37848d2f55e7SToby Isaac rowOffsets[0] = 0; 3785f30e825dSToby Isaac offsetsCopy[0] = 0; 37868d2f55e7SToby Isaac if (numFields) { 37878d2f55e7SToby Isaac PetscInt f; 37888d2f55e7SToby Isaac 3789f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3790f30e825dSToby Isaac PetscInt fDof; 3791f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 3792f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 37938d2f55e7SToby Isaac } 379436fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,parentIndices);CHKERRQ(ierr); 3795367003a6SStefano Zampini } else { 379636fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,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 } 390236fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,parentIndices);CHKERRQ(ierr); 3903367003a6SStefano Zampini } else { 390436fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,parentIndices);CHKERRQ(ierr); 3905f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3906f30e825dSToby Isaac } 3907f30e825dSToby Isaac 3908f30e825dSToby Isaac ierr = PetscSectionGetDof(multiRootSec,p,&numLeaves);CHKERRQ(ierr); 3909f30e825dSToby Isaac ierr = PetscSectionGetOffset(multiRootSec,p,&leafStart);CHKERRQ(ierr); 3910f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3911f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3912f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3913f30e825dSToby Isaac const PetscInt *childIndices; 3914f30e825dSToby Isaac 3915f30e825dSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,l,&numIndices);CHKERRQ(ierr); 3916f30e825dSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,l,&offset);CHKERRQ(ierr); 3917f30e825dSToby Isaac childId = rootIndices[offset++]; 3918f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3919f30e825dSToby Isaac numIndices--; 3920f30e825dSToby Isaac 3921f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3922f30e825dSToby Isaac PetscInt i; 3923f30e825dSToby Isaac 3924f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3925f30e825dSToby Isaac ierr = MatSetValue(mat,parentIndices[i],childIndices[i],1.,INSERT_VALUES);CHKERRQ(ierr); 39268d2f55e7SToby Isaac } 39278d2f55e7SToby Isaac } 39288d2f55e7SToby Isaac else { 3929f30e825dSToby Isaac PetscInt parentId, f, lim; 39308d2f55e7SToby Isaac 3931f30e825dSToby Isaac ierr = DMPlexGetTreeParent(refTree,childId,&parentId,NULL);CHKERRQ(ierr); 3932f30e825dSToby Isaac 3933f30e825dSToby Isaac lim = PetscMax(1,numFields); 3934f30e825dSToby Isaac offsets[0] = 0; 39358d2f55e7SToby Isaac if (numFields) { 3936f30e825dSToby Isaac PetscInt f; 39378d2f55e7SToby Isaac 3938f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3939f30e825dSToby Isaac PetscInt fDof; 3940f30e825dSToby Isaac ierr = PetscSectionGetFieldDof(cSecRef,childId,f,&fDof);CHKERRQ(ierr); 3941f30e825dSToby Isaac 3942f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 39438d2f55e7SToby Isaac } 39448d2f55e7SToby Isaac } 39458d2f55e7SToby Isaac else { 3946f30e825dSToby Isaac PetscInt cDof; 3947f30e825dSToby Isaac 3948f30e825dSToby Isaac ierr = PetscSectionGetDof(cSecRef,childId,&cDof);CHKERRQ(ierr); 3949f30e825dSToby Isaac offsets[1] = cDof; 39508d2f55e7SToby Isaac } 3951f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3952f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3953f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3954f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3955f30e825dSToby Isaac 3956f30e825dSToby Isaac ierr = MatSetValues(mat,rowOffsets[f+1]-rowOffsets[f],rowIndices,offsets[f+1]-offsets[f],colIndices,childMat,INSERT_VALUES);CHKERRQ(ierr); 39578d2f55e7SToby Isaac } 39588d2f55e7SToby Isaac } 39598d2f55e7SToby Isaac } 39608d2f55e7SToby Isaac } 3961ec92bd66SToby Isaac ierr = PetscSectionDestroy(&multiRootSec);CHKERRQ(ierr); 3962ec92bd66SToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 3963ec92bd66SToby Isaac ierr = PetscFree(parentIndices);CHKERRQ(ierr); 3964f30e825dSToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 3965f30e825dSToby Isaac ierr = PetscFree(rootIndices);CHKERRQ(ierr); 3966f30e825dSToby Isaac ierr = PetscFree3(offsets,offsetsCopy,rowOffsets);CHKERRQ(ierr); 3967f30e825dSToby Isaac 39688d2f55e7SToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 39698d2f55e7SToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3970154bca37SToby Isaac PetscFunctionReturn(0); 3971154bca37SToby Isaac } 397238fc2455SToby Isaac 39730eb7e1eaSToby Isaac static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 3974ebf164c7SToby Isaac { 397562095d54SToby Isaac PetscSF coarseToFineEmbedded; 397662095d54SToby Isaac PetscSection globalCoarse, globalFine; 397762095d54SToby Isaac PetscSection localCoarse, localFine; 397862095d54SToby Isaac PetscSection aSec, cSec; 397962095d54SToby Isaac PetscSection rootValuesSec; 398062095d54SToby Isaac PetscSection leafValuesSec; 398162095d54SToby Isaac PetscScalar *rootValues, *leafValues; 398262095d54SToby Isaac IS aIS; 398362095d54SToby Isaac const PetscInt *anchors; 398462095d54SToby Isaac Mat cMat; 398562095d54SToby Isaac PetscInt numFields; 3986412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd; 398762095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 398862095d54SToby Isaac PetscInt *maxChildIds; 398962095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 39900eb7e1eaSToby Isaac PetscFV fv = NULL; 39910eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 39920eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 39930eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 39940eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 399562095d54SToby Isaac PetscErrorCode ierr; 399662095d54SToby Isaac 3997ebf164c7SToby Isaac PetscFunctionBegin; 3998708c7f19SToby Isaac ierr = VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 399962095d54SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 4000412e9a14SMatthew G. Knepley ierr = DMPlexGetSimplexOrBoxCells(coarse,0,&cellStart,&cellEnd);CHKERRQ(ierr); 400162095d54SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 4002e87a4003SBarry Smith ierr = DMGetGlobalSection(fine,&globalFine);CHKERRQ(ierr); 40030eb7e1eaSToby Isaac ierr = DMGetCoordinateDim(coarse,&dim);CHKERRQ(ierr); 400462095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 4005e4a60869SToby Isaac PetscInt nleaves, l; 4006e4a60869SToby Isaac const PetscInt *leaves; 400762095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 400862095d54SToby Isaac 4009e4a60869SToby Isaac ierr = PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 4010e4a60869SToby Isaac 4011e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 4012e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 4013e4a60869SToby Isaac 401462095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 401562095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 401662095d54SToby Isaac if ((dof - cdof) > 0) { 401762095d54SToby Isaac numPointsWithDofs++; 401862095d54SToby Isaac } 401962095d54SToby Isaac } 402062095d54SToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 40214833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 4022e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 4023e4a60869SToby Isaac 402462095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 402562095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 402662095d54SToby Isaac if ((dof - cdof) > 0) { 4027e4a60869SToby Isaac pointsWithDofs[offset++] = l; 402862095d54SToby Isaac } 402962095d54SToby Isaac } 403062095d54SToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 403162095d54SToby Isaac ierr = PetscFree(pointsWithDofs);CHKERRQ(ierr); 403262095d54SToby Isaac } 403362095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 403462095d54SToby Isaac ierr = PetscMalloc1(pEndC-pStartC,&maxChildIds);CHKERRQ(ierr); 403562095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 403662095d54SToby Isaac maxChildIds[p - pStartC] = -2; 403762095d54SToby Isaac } 403862095d54SToby Isaac ierr = PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 403962095d54SToby Isaac ierr = PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 404062095d54SToby Isaac 404192fd8e1eSJed Brown ierr = DMGetLocalSection(coarse,&localCoarse);CHKERRQ(ierr); 4042e87a4003SBarry Smith ierr = DMGetGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 404362095d54SToby Isaac 404462095d54SToby Isaac ierr = DMPlexGetAnchors(coarse,&aSec,&aIS);CHKERRQ(ierr); 404562095d54SToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 404662095d54SToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 404762095d54SToby Isaac 404862095d54SToby Isaac ierr = DMGetDefaultConstraints(coarse,&cSec,&cMat);CHKERRQ(ierr); 404962095d54SToby Isaac ierr = PetscSectionGetChart(cSec,&cStart,&cEnd);CHKERRQ(ierr); 405062095d54SToby Isaac 405162095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 405262095d54SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootValuesSec);CHKERRQ(ierr); 405362095d54SToby Isaac ierr = PetscSectionSetChart(rootValuesSec,pStartC,pEndC);CHKERRQ(ierr); 4054708c7f19SToby Isaac ierr = PetscSectionGetNumFields(localCoarse,&numFields);CHKERRQ(ierr); 405562095d54SToby Isaac { 405662095d54SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 405762095d54SToby Isaac ierr = PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO);CHKERRQ(ierr); 405862095d54SToby Isaac } 40590eb7e1eaSToby Isaac if (grad) { 40600eb7e1eaSToby Isaac PetscInt i; 40610eb7e1eaSToby Isaac 40620eb7e1eaSToby Isaac ierr = VecGetDM(cellGeom,&cellDM);CHKERRQ(ierr); 40630eb7e1eaSToby Isaac ierr = VecGetArrayRead(cellGeom,&cellGeomArray);CHKERRQ(ierr); 40640eb7e1eaSToby Isaac ierr = VecGetDM(grad,&gradDM);CHKERRQ(ierr); 40650eb7e1eaSToby Isaac ierr = VecGetArrayRead(grad,&gradArray);CHKERRQ(ierr); 40660eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1,numFields); i++) { 40670eb7e1eaSToby Isaac PetscObject obj; 40680eb7e1eaSToby Isaac PetscClassId id; 40690eb7e1eaSToby Isaac 407044a7f3ddSMatthew G. Knepley ierr = DMGetField(coarse, i, NULL, &obj);CHKERRQ(ierr); 40710eb7e1eaSToby Isaac ierr = PetscObjectGetClassId(obj,&id);CHKERRQ(ierr); 40720eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 40730eb7e1eaSToby Isaac fv = (PetscFV) obj; 40740eb7e1eaSToby Isaac ierr = PetscFVGetNumComponents(fv,&numFVcomps);CHKERRQ(ierr); 40750eb7e1eaSToby Isaac fvField = i; 40760eb7e1eaSToby Isaac break; 40770eb7e1eaSToby Isaac } 40780eb7e1eaSToby Isaac } 40790eb7e1eaSToby Isaac } 408062095d54SToby Isaac 408162095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 408262095d54SToby Isaac PetscInt dof; 408362095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 408462095d54SToby Isaac PetscInt numValues = 0; 408562095d54SToby Isaac 408662095d54SToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 408762095d54SToby Isaac if (dof < 0) { 408862095d54SToby Isaac dof = -(dof + 1); 408962095d54SToby Isaac } 409062095d54SToby Isaac offsets[0] = 0; 409162095d54SToby Isaac newOffsets[0] = 0; 409262095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 409362095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 409462095d54SToby Isaac 40954833aeb0SToby Isaac ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 409662095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 409762095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 409862095d54SToby Isaac 409962095d54SToby Isaac ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr); 410062095d54SToby Isaac numValues += clDof; 410162095d54SToby Isaac } 41024833aeb0SToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 410362095d54SToby Isaac } 410462095d54SToby Isaac else if (maxChildId == -1) { 410562095d54SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&numValues);CHKERRQ(ierr); 410662095d54SToby Isaac } 410762095d54SToby Isaac /* we will pack the column indices with the field offsets */ 410878b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 41090eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 41100eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 41110eb7e1eaSToby Isaac } 411262095d54SToby Isaac ierr = PetscSectionSetDof(rootValuesSec,p,numValues);CHKERRQ(ierr); 411362095d54SToby Isaac } 411462095d54SToby Isaac ierr = PetscSectionSetUp(rootValuesSec);CHKERRQ(ierr); 411562095d54SToby Isaac { 411662095d54SToby Isaac PetscInt numRootValues; 411762095d54SToby Isaac const PetscScalar *coarseArray; 411862095d54SToby Isaac 411962095d54SToby Isaac ierr = PetscSectionGetStorageSize(rootValuesSec,&numRootValues);CHKERRQ(ierr); 412062095d54SToby Isaac ierr = PetscMalloc1(numRootValues,&rootValues);CHKERRQ(ierr); 412162095d54SToby Isaac ierr = VecGetArrayRead(vecCoarseLocal,&coarseArray);CHKERRQ(ierr); 412262095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 412362095d54SToby Isaac PetscInt numValues; 412462095d54SToby Isaac PetscInt pValOff; 412562095d54SToby Isaac PetscScalar *pVal; 412662095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 412762095d54SToby Isaac 412862095d54SToby Isaac ierr = PetscSectionGetDof(rootValuesSec,p,&numValues);CHKERRQ(ierr); 412962095d54SToby Isaac if (!numValues) { 413062095d54SToby Isaac continue; 413162095d54SToby Isaac } 413262095d54SToby Isaac ierr = PetscSectionGetOffset(rootValuesSec,p,&pValOff);CHKERRQ(ierr); 413362095d54SToby Isaac pVal = &(rootValues[pValOff]); 413462095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 41350eb7e1eaSToby Isaac PetscInt closureSize = numValues; 41360eb7e1eaSToby Isaac ierr = DMPlexVecGetClosure(coarse,NULL,vecCoarseLocal,p,&closureSize,&pVal);CHKERRQ(ierr); 41370eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 4138193eb951SToby Isaac PetscFVCellGeom *cg; 41396dd00756SToby Isaac PetscScalar *gradVals = NULL; 41400eb7e1eaSToby Isaac PetscInt i; 41410eb7e1eaSToby Isaac 41420eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 41430eb7e1eaSToby Isaac 4144193eb951SToby Isaac ierr = DMPlexPointLocalRead(cellDM,p,cellGeomArray,(void *) &cg);CHKERRQ(ierr); 41450eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 41460eb7e1eaSToby Isaac pVal += dim; 4147193eb951SToby Isaac ierr = DMPlexPointGlobalRead(gradDM,p,gradArray,(void *) &gradVals);CHKERRQ(ierr); 41480eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 41490eb7e1eaSToby Isaac } 415062095d54SToby Isaac } 415178b7adb5SToby Isaac else if (maxChildId == -1) { 415278b7adb5SToby Isaac PetscInt lDof, lOff, i; 415378b7adb5SToby Isaac 415478b7adb5SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&lDof);CHKERRQ(ierr); 415578b7adb5SToby Isaac ierr = PetscSectionGetOffset(localCoarse,p,&lOff);CHKERRQ(ierr); 415678b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 415778b7adb5SToby Isaac } 415878b7adb5SToby Isaac } 415962095d54SToby Isaac ierr = VecRestoreArrayRead(vecCoarseLocal,&coarseArray);CHKERRQ(ierr); 416062095d54SToby Isaac ierr = PetscFree(maxChildIds);CHKERRQ(ierr); 416162095d54SToby Isaac } 416262095d54SToby Isaac { 416362095d54SToby Isaac PetscSF valuesSF; 416462095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 416562095d54SToby Isaac 416662095d54SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafValuesSec);CHKERRQ(ierr); 416762095d54SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootValuesSec,&remoteOffsetsValues,leafValuesSec);CHKERRQ(ierr); 416862095d54SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootValuesSec,remoteOffsetsValues,leafValuesSec,&valuesSF);CHKERRQ(ierr); 416962095d54SToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 417062095d54SToby Isaac ierr = PetscFree(remoteOffsetsValues);CHKERRQ(ierr); 417162095d54SToby Isaac ierr = PetscSectionGetStorageSize(leafValuesSec,&numLeafValues);CHKERRQ(ierr); 417262095d54SToby Isaac ierr = PetscMalloc1(numLeafValues,&leafValues);CHKERRQ(ierr); 4173ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(valuesSF,MPIU_SCALAR,rootValues,leafValues,MPI_REPLACE);CHKERRQ(ierr); 4174ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(valuesSF,MPIU_SCALAR,rootValues,leafValues,MPI_REPLACE);CHKERRQ(ierr); 417562095d54SToby Isaac ierr = PetscSFDestroy(&valuesSF);CHKERRQ(ierr); 417662095d54SToby Isaac ierr = PetscFree(rootValues);CHKERRQ(ierr); 417762095d54SToby Isaac ierr = PetscSectionDestroy(&rootValuesSec);CHKERRQ(ierr); 417862095d54SToby Isaac } 417992fd8e1eSJed Brown ierr = DMGetLocalSection(fine,&localFine);CHKERRQ(ierr); 418062095d54SToby Isaac { 418162095d54SToby Isaac PetscInt maxDof; 418262095d54SToby Isaac PetscInt *rowIndices; 418362095d54SToby Isaac DM refTree; 418462095d54SToby Isaac PetscInt **refPointFieldN; 418562095d54SToby Isaac PetscScalar ***refPointFieldMats; 418662095d54SToby Isaac PetscSection refConSec, refAnSec; 41870eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,leafStart,leafEnd; 418862095d54SToby Isaac PetscScalar *pointWork; 418962095d54SToby Isaac 4190cfc9abc1SToby Isaac ierr = PetscSectionGetMaxDof(localFine,&maxDof);CHKERRQ(ierr); 419169291d52SBarry Smith ierr = DMGetWorkArray(fine,maxDof,MPIU_INT,&rowIndices);CHKERRQ(ierr); 419269291d52SBarry Smith ierr = DMGetWorkArray(fine,maxDof,MPIU_SCALAR,&pointWork);CHKERRQ(ierr); 419362095d54SToby Isaac ierr = DMPlexGetReferenceTree(fine,&refTree);CHKERRQ(ierr); 4194e5e52638SMatthew G. Knepley ierr = DMCopyDisc(fine,refTree);CHKERRQ(ierr); 419562095d54SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 419662095d54SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 419762095d54SToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,NULL);CHKERRQ(ierr); 419862095d54SToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 41990eb7e1eaSToby Isaac ierr = PetscSectionGetChart(leafValuesSec,&leafStart,&leafEnd);CHKERRQ(ierr); 4200412e9a14SMatthew G. Knepley ierr = DMPlexGetSimplexOrBoxCells(fine,0,&cellStart,&cellEnd);CHKERRQ(ierr); 42010eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 420262095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 420362095d54SToby Isaac PetscInt numValues, pValOff; 420462095d54SToby Isaac PetscInt childId; 420562095d54SToby Isaac const PetscScalar *pVal; 42060eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 420762095d54SToby Isaac 420862095d54SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 420962095d54SToby Isaac ierr = PetscSectionGetDof(localFine,p,&lDof);CHKERRQ(ierr); 421062095d54SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 421162095d54SToby Isaac if ((gDof - gcDof) <= 0) { 421262095d54SToby Isaac continue; 421362095d54SToby Isaac } 421462095d54SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 421562095d54SToby Isaac ierr = PetscSectionGetDof(leafValuesSec,p,&numValues);CHKERRQ(ierr); 421662095d54SToby Isaac if (!numValues) continue; 421762095d54SToby Isaac ierr = PetscSectionGetOffset(leafValuesSec,p,&pValOff);CHKERRQ(ierr); 421862095d54SToby Isaac pVal = &leafValues[pValOff]; 421962095d54SToby Isaac offsets[0] = 0; 422062095d54SToby Isaac offsetsCopy[0] = 0; 422162095d54SToby Isaac newOffsets[0] = 0; 422262095d54SToby Isaac newOffsetsCopy[0] = 0; 42234833aeb0SToby Isaac childId = cids[p - pStartF]; 422462095d54SToby Isaac if (numFields) { 422562095d54SToby Isaac PetscInt f; 422662095d54SToby Isaac for (f = 0; f < numFields; f++) { 422762095d54SToby Isaac PetscInt rowDof; 422862095d54SToby Isaac 422962095d54SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 423062095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 423162095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 423262095d54SToby Isaac /* TODO: closure indices */ 42339f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 423462095d54SToby Isaac } 423536fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1,NULL,rowIndices);CHKERRQ(ierr); 423662095d54SToby Isaac } 423762095d54SToby Isaac else { 42384833aeb0SToby Isaac offsets[0] = 0; 42394833aeb0SToby Isaac offsets[1] = lDof; 42404833aeb0SToby Isaac newOffsets[0] = 0; 42414833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 424236fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,NULL,rowIndices);CHKERRQ(ierr); 424362095d54SToby Isaac } 424462095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 42452f65e181SToby Isaac ierr = VecSetValues(vecFine,numValues,rowIndices,pVal,INSERT_VALUES);CHKERRQ(ierr); 424662095d54SToby Isaac } else { 424762095d54SToby Isaac PetscInt f; 424862095d54SToby Isaac 424978b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 425078b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 425178b7adb5SToby Isaac fvGradData = &pVal[numValues]; 425278b7adb5SToby Isaac } 425362095d54SToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 425462095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 425562095d54SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 425662095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 425762095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 425862095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 425962095d54SToby Isaac PetscInt i, j; 426062095d54SToby Isaac 4261708c7f19SToby Isaac #if 0 4262cfc9abc1SToby Isaac ierr = PetscInfo5(coarse,"childId %D, numRows %D, numCols %D, refPointFieldN %D maxDof %D\n",childId,numRows,numCols,refPointFieldN[childId - pRefStart][f], maxDof);CHKERRQ(ierr); 4263708c7f19SToby Isaac #endif 426462095d54SToby Isaac for (i = 0; i < numRows; i++) { 426562095d54SToby Isaac PetscScalar val = 0.; 426662095d54SToby Isaac for (j = 0; j < numCols; j++) { 426762095d54SToby Isaac val += childMat[i * numCols + j] * cVal[j]; 426862095d54SToby Isaac } 426962095d54SToby Isaac rVal[i] = val; 427062095d54SToby Isaac } 42710eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 42720eb7e1eaSToby Isaac PetscReal centroid[3]; 42730eb7e1eaSToby Isaac PetscScalar diff[3]; 42740eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 42750eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 42760eb7e1eaSToby Isaac 42770eb7e1eaSToby Isaac ierr = DMPlexComputeCellGeometryFVM(fine,p,NULL,centroid,NULL);CHKERRQ(ierr); 42780eb7e1eaSToby Isaac for (i = 0; i < dim; i++) { 42790eb7e1eaSToby Isaac diff[i] = centroid[i] - parentCentroid[i]; 42800eb7e1eaSToby Isaac } 42810eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 42820eb7e1eaSToby Isaac PetscScalar val = 0.; 42830eb7e1eaSToby Isaac 428489698031SToby Isaac for (j = 0; j < dim; j++) { 42850eb7e1eaSToby Isaac val += gradient[dim * i + j] * diff[j]; 42860eb7e1eaSToby Isaac } 42870eb7e1eaSToby Isaac rVal[i] += val; 42880eb7e1eaSToby Isaac } 42890eb7e1eaSToby Isaac } 42902f65e181SToby Isaac ierr = VecSetValues(vecFine,numRows,&rowIndices[offsets[f]],rVal,INSERT_VALUES);CHKERRQ(ierr); 429162095d54SToby Isaac } 429262095d54SToby Isaac } 429362095d54SToby Isaac } 429462095d54SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 429569291d52SBarry Smith ierr = DMRestoreWorkArray(fine,maxDof,MPIU_SCALAR,&pointWork);CHKERRQ(ierr); 4296cfc9abc1SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,MPIU_INT,&rowIndices);CHKERRQ(ierr); 429762095d54SToby Isaac } 42984fe3dfefSToby Isaac ierr = PetscFree(leafValues);CHKERRQ(ierr); 429962095d54SToby Isaac ierr = PetscSectionDestroy(&leafValuesSec);CHKERRQ(ierr); 430062095d54SToby Isaac ierr = PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO);CHKERRQ(ierr); 430162095d54SToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4302ebf164c7SToby Isaac PetscFunctionReturn(0); 4303ebf164c7SToby Isaac } 4304ebf164c7SToby Isaac 4305ebf164c7SToby Isaac static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4306ebf164c7SToby Isaac { 4307c921d74cSToby Isaac DM refTree; 4308c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4309c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4310c921d74cSToby Isaac PetscSection localCoarse, localFine; 4311c921d74cSToby Isaac PetscSection cSecRef; 4312c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4313d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4314c921d74cSToby Isaac Mat injRef; 4315c921d74cSToby Isaac PetscInt numFields, maxDof; 4316c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4317c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4318c921d74cSToby Isaac PetscLayout rowMap, colMap; 4319c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4320c921d74cSToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4321c921d74cSToby Isaac PetscErrorCode ierr; 4322c921d74cSToby Isaac 4323ebf164c7SToby Isaac PetscFunctionBegin; 4324c921d74cSToby Isaac 4325c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 4326708c7f19SToby Isaac ierr = VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 4327708c7f19SToby Isaac ierr = VecSetOption(vecCoarse,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE);CHKERRQ(ierr); 4328c921d74cSToby Isaac ierr = DMPlexGetReferenceTree(coarse,&refTree);CHKERRQ(ierr); 4329e5e52638SMatthew G. Knepley ierr = DMCopyDisc(coarse,refTree);CHKERRQ(ierr); 4330c921d74cSToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSecRef,NULL);CHKERRQ(ierr); 4331c921d74cSToby Isaac ierr = PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd);CHKERRQ(ierr); 4332c921d74cSToby Isaac ierr = DMPlexReferenceTreeGetInjector(refTree,&injRef);CHKERRQ(ierr); 4333c921d74cSToby Isaac 4334c921d74cSToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 433592fd8e1eSJed Brown ierr = DMGetLocalSection(fine,&localFine);CHKERRQ(ierr); 4336e87a4003SBarry Smith ierr = DMGetGlobalSection(fine,&globalFine);CHKERRQ(ierr); 4337c921d74cSToby Isaac ierr = PetscSectionGetNumFields(localFine,&numFields);CHKERRQ(ierr); 4338c921d74cSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 433992fd8e1eSJed Brown ierr = DMGetLocalSection(coarse,&localCoarse);CHKERRQ(ierr); 4340e87a4003SBarry Smith ierr = DMGetGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 4341c921d74cSToby Isaac ierr = PetscSectionGetMaxDof(localCoarse,&maxDof);CHKERRQ(ierr); 4342c921d74cSToby Isaac { 4343c921d74cSToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 4344c921d74cSToby Isaac ierr = PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets);CHKERRQ(ierr); 4345c921d74cSToby Isaac } 4346c921d74cSToby Isaac 4347c921d74cSToby Isaac ierr = DMPlexTransferInjectorTree(coarse,fine,coarseToFine,cids,vecFine,numFields,offsets,&multiRootSec,&rootIndicesSec,NULL,&rootValues);CHKERRQ(ierr); 4348c921d74cSToby Isaac 4349d3bc4906SToby Isaac ierr = PetscMalloc2(maxDof,&parentIndices,maxDof,&parentValues);CHKERRQ(ierr); 4350c921d74cSToby Isaac 4351c921d74cSToby Isaac /* count indices */ 435262095d54SToby Isaac ierr = VecGetLayout(vecFine,&colMap);CHKERRQ(ierr); 435362095d54SToby Isaac ierr = VecGetLayout(vecCoarse,&rowMap);CHKERRQ(ierr); 4354c921d74cSToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 4355c921d74cSToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 4356c921d74cSToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 4357c921d74cSToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 4358c921d74cSToby Isaac /* insert values */ 4359c921d74cSToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 4360c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4361c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 436278b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4363c921d74cSToby Isaac 4364c921d74cSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 4365c921d74cSToby Isaac ierr = PetscSectionGetConstraintDof(globalCoarse,p,&cdof);CHKERRQ(ierr); 4366c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 43672f65e181SToby Isaac ierr = PetscSectionGetDof(localCoarse,p,&dof);CHKERRQ(ierr); 4368c921d74cSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 4369c921d74cSToby Isaac 4370c921d74cSToby Isaac rowOffsets[0] = 0; 4371c921d74cSToby Isaac offsetsCopy[0] = 0; 4372c921d74cSToby Isaac if (numFields) { 4373c921d74cSToby Isaac PetscInt f; 4374c921d74cSToby Isaac 4375c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4376c921d74cSToby Isaac PetscInt fDof; 4377c921d74cSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 4378c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4379c921d74cSToby Isaac } 438036fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1,NULL,parentIndices);CHKERRQ(ierr); 4381367003a6SStefano Zampini } else { 438236fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,NULL,parentIndices);CHKERRQ(ierr); 4383c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4384c921d74cSToby Isaac } 4385c921d74cSToby Isaac 4386c921d74cSToby Isaac ierr = PetscSectionGetDof(multiRootSec,p,&numLeaves);CHKERRQ(ierr); 4387c921d74cSToby Isaac ierr = PetscSectionGetOffset(multiRootSec,p,&leafStart);CHKERRQ(ierr); 4388c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 43892f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4390c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4391c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4392c921d74cSToby Isaac const PetscScalar *childValues; 4393c921d74cSToby Isaac 4394c921d74cSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,l,&numIndices);CHKERRQ(ierr); 4395c921d74cSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,l,&offset);CHKERRQ(ierr); 4396c921d74cSToby Isaac childId = (PetscInt) PetscRealPart(rootValues[offset++]); 4397c921d74cSToby Isaac childValues = &rootValues[offset]; 4398c921d74cSToby Isaac numIndices--; 4399c921d74cSToby Isaac 4400c921d74cSToby Isaac if (childId == -2) { /* skip */ 4401c921d74cSToby Isaac continue; 4402c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 44032f65e181SToby Isaac PetscInt m; 44042f65e181SToby Isaac 440578b7adb5SToby Isaac contribute = PETSC_TRUE; 44062f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4407beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4408d3bc4906SToby Isaac PetscInt parentId, f, lim; 4409d3bc4906SToby Isaac 441078b7adb5SToby Isaac contribute = PETSC_TRUE; 4411d3bc4906SToby Isaac ierr = DMPlexGetTreeParent(refTree,childId,&parentId,NULL);CHKERRQ(ierr); 4412d3bc4906SToby Isaac 4413d3bc4906SToby Isaac lim = PetscMax(1,numFields); 4414d3bc4906SToby Isaac offsets[0] = 0; 4415d3bc4906SToby Isaac if (numFields) { 4416d3bc4906SToby Isaac PetscInt f; 4417d3bc4906SToby Isaac 4418d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4419d3bc4906SToby Isaac PetscInt fDof; 4420d3bc4906SToby Isaac ierr = PetscSectionGetFieldDof(cSecRef,childId,f,&fDof);CHKERRQ(ierr); 4421d3bc4906SToby Isaac 4422d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4423d3bc4906SToby Isaac } 4424d3bc4906SToby Isaac } 4425d3bc4906SToby Isaac else { 4426d3bc4906SToby Isaac PetscInt cDof; 4427d3bc4906SToby Isaac 4428d3bc4906SToby Isaac ierr = PetscSectionGetDof(cSecRef,childId,&cDof);CHKERRQ(ierr); 4429d3bc4906SToby Isaac offsets[1] = cDof; 4430d3bc4906SToby Isaac } 4431d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4432d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4433d3bc4906SToby Isaac PetscInt n = offsets[f+1]-offsets[f]; 4434e328ff09SToby Isaac PetscInt m = rowOffsets[f+1]-rowOffsets[f]; 4435d3bc4906SToby Isaac PetscInt i, j; 4436d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4437d3bc4906SToby Isaac 4438e328ff09SToby Isaac for (i = 0; i < m; i++) { 4439d3bc4906SToby Isaac PetscScalar val = 0.; 4440d3bc4906SToby Isaac for (j = 0; j < n; j++) { 4441d3bc4906SToby Isaac val += childMat[n * i + j] * colValues[j]; 4442d3bc4906SToby Isaac } 4443e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val; 4444d3bc4906SToby Isaac } 4445d3bc4906SToby Isaac } 4446c921d74cSToby Isaac } 4447c921d74cSToby Isaac } 444878b7adb5SToby Isaac if (contribute) {ierr = VecSetValues(vecCoarse,dof,parentIndices,parentValues,INSERT_VALUES);CHKERRQ(ierr);} 4449c921d74cSToby Isaac } 4450c921d74cSToby Isaac ierr = PetscSectionDestroy(&multiRootSec);CHKERRQ(ierr); 4451c921d74cSToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 4452d3bc4906SToby Isaac ierr = PetscFree2(parentIndices,parentValues);CHKERRQ(ierr); 4453c921d74cSToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats);CHKERRQ(ierr); 4454c921d74cSToby Isaac ierr = PetscFree(rootValues);CHKERRQ(ierr); 4455c921d74cSToby Isaac ierr = PetscFree3(offsets,offsetsCopy,rowOffsets);CHKERRQ(ierr); 4456ebf164c7SToby Isaac PetscFunctionReturn(0); 4457ebf164c7SToby Isaac } 4458ebf164c7SToby Isaac 4459ff1f73f7SToby Isaac /*@ 4460ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4461ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4462ff1f73f7SToby Isaac coarsening and refinement at the same time. 4463ff1f73f7SToby Isaac 4464ff1f73f7SToby Isaac collective 4465ff1f73f7SToby Isaac 4466ff1f73f7SToby Isaac Input Parameters: 4467ff1f73f7SToby Isaac + dmIn - The DMPlex mesh for the input vector 4468ff1f73f7SToby Isaac . vecIn - The input vector 4469ff1f73f7SToby Isaac . sfRefine - A star forest indicating points in the mesh dmIn (roots in the star forest) that are parents to points in 4470ff1f73f7SToby Isaac the mesh dmOut (leaves in the star forest), i.e. where dmOut is more refined than dmIn 4471ff1f73f7SToby Isaac . sfCoarsen - A star forest indicating points in the mesh dmOut (roots in the star forest) that are parents to points in 4472ff1f73f7SToby Isaac the mesh dmIn (leaves in the star forest), i.e. where dmOut is more coarsened than dmIn 4473ff1f73f7SToby Isaac . cidsRefine - The childIds of the points in dmOut. These childIds relate back to the reference tree: childid[j] = k implies 4474ff1f73f7SToby Isaac that mesh point j of dmOut was refined from a point in dmIn just as the mesh point k in the reference 4475ff1f73f7SToby Isaac tree was refined from its parent. childid[j] = -1 indicates that the point j in dmOut is exactly 4476ff1f73f7SToby Isaac equivalent to its root in dmIn, so no interpolation is necessary. childid[j] = -2 indicates that this 4477ff1f73f7SToby Isaac point j in dmOut is not a leaf of sfRefine. 4478ff1f73f7SToby Isaac . cidsCoarsen - The childIds of the points in dmIn. These childIds relate back to the reference tree: childid[j] = k implies 4479ff1f73f7SToby Isaac that mesh point j of dmIn coarsens to a point in dmOut just as the mesh point k in the reference 4480ff1f73f7SToby Isaac tree coarsens to its parent. childid[j] = -2 indicates that point j in dmOut is not a leaf in sfCoarsen. 4481ff1f73f7SToby Isaac . useBCs - PETSC_TRUE indicates that boundary values should be inserted into vecIn before transfer. 4482ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4483ff1f73f7SToby Isaac 4484ff1f73f7SToby Isaac Output Parameters: 44858966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred 4486ff1f73f7SToby Isaac projection of vecIn from dmIn to dmOut. Note that any field discretized with a PetscFV finite volume 4487ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4488ff1f73f7SToby Isaac coarse points to fine points. 4489ff1f73f7SToby Isaac 4490ff1f73f7SToby Isaac Level: developer 4491ff1f73f7SToby Isaac 4492fd292e60Sprj- .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree(), PetscFVGetComputeGradients() 4493ff1f73f7SToby Isaac @*/ 4494ff1f73f7SToby Isaac PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) 449538fc2455SToby Isaac { 4496ebf164c7SToby Isaac PetscErrorCode ierr; 4497ebf164c7SToby Isaac 449838fc2455SToby Isaac PetscFunctionBegin; 449978b7adb5SToby Isaac ierr = VecSet(vecOut,0.0);CHKERRQ(ierr); 4500ff1f73f7SToby Isaac if (sfRefine) { 4501fbfa57b9SToby Isaac Vec vecInLocal; 45020eb7e1eaSToby Isaac DM dmGrad = NULL; 45030eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4504fbfa57b9SToby Isaac 4505fbfa57b9SToby Isaac ierr = DMGetLocalVector(dmIn,&vecInLocal);CHKERRQ(ierr); 4506fbfa57b9SToby Isaac ierr = VecSet(vecInLocal,0.0);CHKERRQ(ierr); 45070eb7e1eaSToby Isaac { 45080eb7e1eaSToby Isaac PetscInt numFields, i; 45090eb7e1eaSToby Isaac 45100eb7e1eaSToby Isaac ierr = DMGetNumFields(dmIn, &numFields);CHKERRQ(ierr); 45110eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 45120eb7e1eaSToby Isaac PetscObject obj; 45130eb7e1eaSToby Isaac PetscClassId classid; 45140eb7e1eaSToby Isaac 451544a7f3ddSMatthew G. Knepley ierr = DMGetField(dmIn, i, NULL, &obj);CHKERRQ(ierr); 45160eb7e1eaSToby Isaac ierr = PetscObjectGetClassId(obj, &classid);CHKERRQ(ierr); 45170eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 45180eb7e1eaSToby Isaac ierr = DMPlexGetDataFVM(dmIn,(PetscFV)obj,&cellGeom,&faceGeom,&dmGrad);CHKERRQ(ierr); 45190eb7e1eaSToby Isaac break; 45200eb7e1eaSToby Isaac } 45210eb7e1eaSToby Isaac } 45220eb7e1eaSToby Isaac } 45230eb7e1eaSToby Isaac if (useBCs) { 45240eb7e1eaSToby Isaac ierr = DMPlexInsertBoundaryValues(dmIn,PETSC_TRUE,vecInLocal,time,faceGeom,cellGeom,NULL);CHKERRQ(ierr); 45250eb7e1eaSToby Isaac } 4526fbfa57b9SToby Isaac ierr = DMGlobalToLocalBegin(dmIn,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 4527fbfa57b9SToby Isaac ierr = DMGlobalToLocalEnd(dmIn,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 45280eb7e1eaSToby Isaac if (dmGrad) { 45290eb7e1eaSToby Isaac ierr = DMGetGlobalVector(dmGrad,&grad);CHKERRQ(ierr); 45300eb7e1eaSToby Isaac ierr = DMPlexReconstructGradientsFVM(dmIn,vecInLocal,grad);CHKERRQ(ierr); 45310eb7e1eaSToby Isaac } 4532ff1f73f7SToby Isaac ierr = DMPlexTransferVecTree_Interpolate(dmIn,vecInLocal,dmOut,vecOut,sfRefine,cidsRefine,grad,cellGeom);CHKERRQ(ierr); 4533fbfa57b9SToby Isaac ierr = DMRestoreLocalVector(dmIn,&vecInLocal);CHKERRQ(ierr); 45340eb7e1eaSToby Isaac if (dmGrad) { 45350eb7e1eaSToby Isaac ierr = DMRestoreGlobalVector(dmGrad,&grad);CHKERRQ(ierr); 45360eb7e1eaSToby Isaac } 4537ebf164c7SToby Isaac } 4538ff1f73f7SToby Isaac if (sfCoarsen) { 4539ff1f73f7SToby Isaac ierr = DMPlexTransferVecTree_Inject(dmIn,vecIn,dmOut,vecOut,sfCoarsen,cidsCoarsen);CHKERRQ(ierr); 4540ebf164c7SToby Isaac } 45412f65e181SToby Isaac ierr = VecAssemblyBegin(vecOut);CHKERRQ(ierr); 45422f65e181SToby Isaac ierr = VecAssemblyEnd(vecOut);CHKERRQ(ierr); 454338fc2455SToby Isaac PetscFunctionReturn(0); 454438fc2455SToby Isaac } 4545