1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2d6a7ad0dSToby Isaac #include <../src/sys/utils/hash.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 5d6a7ad0dSToby Isaac #include <petscsf.h> 60c37af3bSToby Isaac #include <petscds.h> 7d6a7ad0dSToby Isaac 8d6a7ad0dSToby Isaac /** hierarchy routines */ 9d6a7ad0dSToby Isaac 10d6a7ad0dSToby Isaac #undef __FUNCT__ 11d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexSetReferenceTree" 12d6a7ad0dSToby Isaac /*@ 13d6a7ad0dSToby Isaac DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes. 14d6a7ad0dSToby Isaac 15d6a7ad0dSToby Isaac Not collective 16d6a7ad0dSToby Isaac 17d6a7ad0dSToby Isaac Input Parameters: 18d6a7ad0dSToby Isaac + dm - The DMPlex object 19d6a7ad0dSToby Isaac - ref - The reference tree DMPlex object 20d6a7ad0dSToby Isaac 210b7167a0SToby Isaac Level: intermediate 22d6a7ad0dSToby Isaac 23da43764aSToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexCreateDefaultReferenceTree() 24d6a7ad0dSToby Isaac @*/ 25d6a7ad0dSToby Isaac PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 26d6a7ad0dSToby Isaac { 27d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 28d6a7ad0dSToby Isaac PetscErrorCode ierr; 29d6a7ad0dSToby Isaac 30d6a7ad0dSToby Isaac PetscFunctionBegin; 31d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3247a1df27SMatthew G. Knepley if (ref) {PetscValidHeaderSpecific(ref, DM_CLASSID, 2);} 33d6a7ad0dSToby Isaac ierr = PetscObjectReference((PetscObject)ref);CHKERRQ(ierr); 34d6a7ad0dSToby Isaac ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 35d6a7ad0dSToby Isaac mesh->referenceTree = ref; 36d6a7ad0dSToby Isaac PetscFunctionReturn(0); 37d6a7ad0dSToby Isaac } 38d6a7ad0dSToby Isaac 39d6a7ad0dSToby Isaac #undef __FUNCT__ 40d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexGetReferenceTree" 41d6a7ad0dSToby Isaac /*@ 42d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 43d6a7ad0dSToby Isaac 44d6a7ad0dSToby Isaac Not collective 45d6a7ad0dSToby Isaac 46d6a7ad0dSToby Isaac Input Parameters: 47d6a7ad0dSToby Isaac . dm - The DMPlex object 48d6a7ad0dSToby Isaac 49d6a7ad0dSToby Isaac Output Parameters 50d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 51d6a7ad0dSToby Isaac 520b7167a0SToby Isaac Level: intermediate 53d6a7ad0dSToby Isaac 54da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexCreateDefaultReferenceTree() 55d6a7ad0dSToby Isaac @*/ 56d6a7ad0dSToby Isaac PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 57d6a7ad0dSToby Isaac { 58d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 59d6a7ad0dSToby Isaac 60d6a7ad0dSToby Isaac PetscFunctionBegin; 61d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62d6a7ad0dSToby Isaac PetscValidPointer(ref,2); 63d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 64d6a7ad0dSToby Isaac PetscFunctionReturn(0); 65d6a7ad0dSToby Isaac } 66d6a7ad0dSToby Isaac 67dcbd3bf7SToby Isaac #undef __FUNCT__ 68dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry_Default" 69dcbd3bf7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 70dcbd3bf7SToby Isaac { 71dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 72dcbd3bf7SToby Isaac PetscErrorCode ierr; 73dcbd3bf7SToby Isaac 74dcbd3bf7SToby Isaac PetscFunctionBegin; 75dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 76dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 77dcbd3bf7SToby Isaac if (childB) *childB = childA; 78dcbd3bf7SToby Isaac PetscFunctionReturn(0); 79dcbd3bf7SToby Isaac } 80dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 81dcbd3bf7SToby Isaac ierr = DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd);CHKERRQ(ierr); 82dcbd3bf7SToby Isaac if (parent >= dStart && parent <= dEnd) { 83dcbd3bf7SToby Isaac break; 84dcbd3bf7SToby Isaac } 85dcbd3bf7SToby Isaac } 86dcbd3bf7SToby Isaac if (dim > 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %d-cells",dim); 87dcbd3bf7SToby Isaac if (!dim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 88dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 89dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 90dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 91dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 92dcbd3bf7SToby Isaac 93dcbd3bf7SToby Isaac ierr = DMPlexGetSupportSize(dm,childA,&size);CHKERRQ(ierr); 94dcbd3bf7SToby Isaac ierr = DMPlexGetSupport(dm,childA,&supp);CHKERRQ(ierr); 95dcbd3bf7SToby Isaac 96dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 97dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 98dcbd3bf7SToby Isaac PetscInt sParent; 99dcbd3bf7SToby Isaac 100dcbd3bf7SToby Isaac sA = supp[i]; 101dcbd3bf7SToby Isaac if (sA == parent) continue; 102dcbd3bf7SToby Isaac ierr = DMPlexGetTreeParent(dm,sA,&sParent,NULL);CHKERRQ(ierr); 103dcbd3bf7SToby Isaac if (sParent == parent) { 104dcbd3bf7SToby Isaac break; 105dcbd3bf7SToby Isaac } 106dcbd3bf7SToby Isaac } 107dcbd3bf7SToby Isaac if (i == size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 108dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 109dcbd3bf7SToby Isaac * parentOrientB */ 110dcbd3bf7SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry_Default(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB);CHKERRQ(ierr); 111dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,sA,&sConeSize);CHKERRQ(ierr); 112dcbd3bf7SToby Isaac ierr = DMPlexGetCone(dm,sA,&coneA);CHKERRQ(ierr); 113dcbd3bf7SToby Isaac ierr = DMPlexGetCone(dm,sB,&coneB);CHKERRQ(ierr); 114dcbd3bf7SToby Isaac ierr = DMPlexGetConeOrientation(dm,sA,&oA);CHKERRQ(ierr); 115dcbd3bf7SToby Isaac ierr = DMPlexGetConeOrientation(dm,sB,&oB);CHKERRQ(ierr); 116dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 117dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 118dcbd3bf7SToby Isaac if (coneA[i] == childA) { 119dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 120dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 121dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 122dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 123dcbd3bf7SToby Isaac if (childOrientB) { 124dcbd3bf7SToby Isaac PetscInt oBtrue; 125dcbd3bf7SToby Isaac 126dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,childA,&coneSize);CHKERRQ(ierr); 127dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 128dcbd3bf7SToby Isaac if (coneSize != 0 && coneSize != 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 129dcbd3bf7SToby Isaac /* we may have to flip an edge */ 130dcbd3bf7SToby Isaac oBtrue = coneSize ? ((sOrientB >= 0) ? oB[j] : -(oB[j] + 2)) : 0; 131dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize,oA[i],oBtrue);CHKERRQ(ierr); 132dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 133dcbd3bf7SToby Isaac } 134dcbd3bf7SToby Isaac break; 135dcbd3bf7SToby Isaac } 136dcbd3bf7SToby Isaac } 137dcbd3bf7SToby Isaac if (i == sConeSize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 138dcbd3bf7SToby Isaac PetscFunctionReturn(0); 139dcbd3bf7SToby Isaac } 140dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 141dcbd3bf7SToby Isaac ierr = DMPlexGetConeSize(dm,parent,&coneSize);CHKERRQ(ierr); 142dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 143dcbd3bf7SToby Isaac if (dim == 2) { 144dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 145dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 146dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 147dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 148dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 149dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 150dcbd3bf7SToby Isaac } 151dcbd3bf7SToby Isaac else { 152dcbd3bf7SToby Isaac oAvert = parentOrientA; 153dcbd3bf7SToby Isaac oBvert = parentOrientB; 154dcbd3bf7SToby Isaac ABswapVert = ABswap; 155dcbd3bf7SToby Isaac } 156dcbd3bf7SToby Isaac if (childB) { 157dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 158dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 159dcbd3bf7SToby Isaac const PetscInt *children; 160dcbd3bf7SToby Isaac 161dcbd3bf7SToby Isaac /* count which position the child is in */ 162dcbd3bf7SToby Isaac ierr = DMPlexGetTreeChildren(dm,parent,&numChildren,&children);CHKERRQ(ierr); 163dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 164dcbd3bf7SToby Isaac p = children[i]; 165dcbd3bf7SToby Isaac if (p == childA) { 166dcbd3bf7SToby Isaac posA = i; 167dcbd3bf7SToby Isaac break; 168dcbd3bf7SToby Isaac } 169dcbd3bf7SToby Isaac } 170dcbd3bf7SToby Isaac if (posA >= coneSize) { 171dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 172dcbd3bf7SToby Isaac * is invariant */ 173dcbd3bf7SToby Isaac if (dim != 2 || posA != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Expected a middle triangle, got something else"); 174dcbd3bf7SToby Isaac *childB = childA; 175dcbd3bf7SToby Isaac } 176dcbd3bf7SToby Isaac else { 177dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 178dcbd3bf7SToby Isaac PetscInt posB; 179dcbd3bf7SToby Isaac 180dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 181dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 182dcbd3bf7SToby Isaac } 183dcbd3bf7SToby Isaac } 184dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 185dcbd3bf7SToby Isaac PetscFunctionReturn(0); 186dcbd3bf7SToby Isaac } 187dcbd3bf7SToby Isaac 188dcbd3bf7SToby Isaac #undef __FUNCT__ 189dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry" 190dcbd3bf7SToby Isaac /*@ 191dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 192dcbd3bf7SToby Isaac 193dcbd3bf7SToby Isaac Input Parameters: 194dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object 195dcbd3bf7SToby Isaac . parent - the parent point 196dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 197dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 198dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 199dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 200dcbd3bf7SToby Isaac 201dcbd3bf7SToby Isaac Output Parameters: 202dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child 203dcbd3bf7SToby Isaac . childB - if not NULL, the new childID for describing the child 204dcbd3bf7SToby Isaac 205dcbd3bf7SToby Isaac Level: developer 206dcbd3bf7SToby Isaac 207dcbd3bf7SToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexSetReferenceTree(), DMPlexSetTree() 208dcbd3bf7SToby Isaac @*/ 209dcbd3bf7SToby Isaac PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 210dcbd3bf7SToby Isaac { 211dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 212dcbd3bf7SToby Isaac PetscErrorCode ierr; 213dcbd3bf7SToby Isaac 214dcbd3bf7SToby Isaac PetscFunctionBegin; 215dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 216dcbd3bf7SToby Isaac if (!mesh->getchildsymmetry) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"DMPlexReferenceTreeGetChildSymmetry not implemented"); 217dcbd3bf7SToby Isaac ierr = mesh->getchildsymmetry(dm,parent,parentOrientA,childOrientA,childA,parentOrientB,childOrientB,childB);CHKERRQ(ierr); 218dcbd3bf7SToby Isaac PetscFunctionReturn(0); 219dcbd3bf7SToby Isaac } 220dcbd3bf7SToby Isaac 221776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM,PetscSection,PetscInt*,PetscInt*,PetscBool,PetscBool); 222f9f063d4SToby Isaac 223da43764aSToby Isaac #undef __FUNCT__ 2240e2cc29aSToby Isaac #define __FUNCT__ "DMPlexCreateReferenceTree_Union" 2250e2cc29aSToby Isaac PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 226da43764aSToby Isaac { 2270e2cc29aSToby Isaac MPI_Comm comm; 2280e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 229da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 230da43764aSToby Isaac DMLabel identity, identityRef; 23110f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 232da43764aSToby Isaac PetscScalar *unionCoords; 233da43764aSToby Isaac IS perm; 234da43764aSToby Isaac PetscErrorCode ierr; 235da43764aSToby Isaac 236da43764aSToby Isaac PetscFunctionBegin; 2370e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2380e2cc29aSToby Isaac ierr = DMGetDimension(K, &dim);CHKERRQ(ierr); 239da43764aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 2400e2cc29aSToby Isaac ierr = DMGetLabel(K, labelName, &identity);CHKERRQ(ierr); 2410e2cc29aSToby Isaac ierr = DMGetLabel(Kref, labelName, &identityRef);CHKERRQ(ierr); 242da43764aSToby Isaac ierr = DMPlexGetChart(Kref, &pRefStart, &pRefEnd);CHKERRQ(ierr); 243da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionSection);CHKERRQ(ierr); 244da43764aSToby Isaac ierr = PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart));CHKERRQ(ierr); 245da43764aSToby Isaac /* count points that will go in the union */ 246da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 247da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pStart, 1);CHKERRQ(ierr); 248da43764aSToby Isaac } 249da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 250da43764aSToby Isaac PetscInt q, qSize; 251da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, p, &q);CHKERRQ(ierr); 252da43764aSToby Isaac ierr = DMLabelGetStratumSize(identityRef, q, &qSize);CHKERRQ(ierr); 253da43764aSToby Isaac if (qSize > 1) { 254da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1);CHKERRQ(ierr); 255da43764aSToby Isaac } 256da43764aSToby Isaac } 257854ce69bSBarry Smith ierr = PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart,&permvals);CHKERRQ(ierr); 258da43764aSToby Isaac offset = 0; 259da43764aSToby Isaac /* stratify points in the union by topological dimension */ 260da43764aSToby Isaac for (d = 0; d <= dim; d++) { 261da43764aSToby Isaac PetscInt cStart, cEnd, c; 262da43764aSToby Isaac 263da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K, d, &cStart, &cEnd);CHKERRQ(ierr); 264da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 265da43764aSToby Isaac permvals[offset++] = c; 266da43764aSToby Isaac } 267da43764aSToby Isaac 268da43764aSToby Isaac ierr = DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd);CHKERRQ(ierr); 269da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 270da43764aSToby Isaac permvals[offset++] = c + (pEnd - pStart); 271da43764aSToby Isaac } 272da43764aSToby Isaac } 273da43764aSToby Isaac ierr = ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr); 274da43764aSToby Isaac ierr = PetscSectionSetPermutation(unionSection,perm);CHKERRQ(ierr); 275da43764aSToby Isaac ierr = PetscSectionSetUp(unionSection);CHKERRQ(ierr); 276da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionSection,&numUnionPoints);CHKERRQ(ierr); 277da43764aSToby Isaac ierr = PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints);CHKERRQ(ierr); 278da43764aSToby Isaac /* count dimension points */ 279da43764aSToby Isaac for (d = 0; d <= dim; d++) { 280da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 281da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d,&cStart,NULL);CHKERRQ(ierr); 282da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff);CHKERRQ(ierr); 283da43764aSToby Isaac if (d < dim) { 284da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d+1,&cStart,NULL);CHKERRQ(ierr); 285da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2);CHKERRQ(ierr); 286da43764aSToby Isaac } 287da43764aSToby Isaac else { 288da43764aSToby Isaac cOff2 = numUnionPoints; 289da43764aSToby Isaac } 290da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 291da43764aSToby Isaac } 292da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionConeSection);CHKERRQ(ierr); 293da43764aSToby Isaac ierr = PetscSectionSetChart(unionConeSection, 0, numUnionPoints);CHKERRQ(ierr); 294da43764aSToby Isaac /* count the cones in the union */ 295da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 296da43764aSToby Isaac PetscInt dof, uOff; 297da43764aSToby Isaac 298da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 299da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 300da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 301da43764aSToby Isaac coneSizes[uOff] = dof; 302da43764aSToby Isaac } 303da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 304da43764aSToby Isaac PetscInt dof, uDof, uOff; 305da43764aSToby Isaac 306da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 307da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 308da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 309da43764aSToby Isaac if (uDof) { 310da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 311da43764aSToby Isaac coneSizes[uOff] = dof; 312da43764aSToby Isaac } 313da43764aSToby Isaac } 314da43764aSToby Isaac ierr = PetscSectionSetUp(unionConeSection);CHKERRQ(ierr); 315da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionConeSection,&numCones);CHKERRQ(ierr); 316da43764aSToby Isaac ierr = PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations);CHKERRQ(ierr); 317da43764aSToby Isaac /* write the cones in the union */ 318da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 319da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 320da43764aSToby Isaac const PetscInt *cone, *orientation; 321da43764aSToby Isaac 322da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 323da43764aSToby Isaac ierr = DMPlexGetCone(K, p, &cone);CHKERRQ(ierr); 324da43764aSToby Isaac ierr = DMPlexGetConeOrientation(K, p, &orientation);CHKERRQ(ierr); 325da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 326da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 327da43764aSToby Isaac for (c = 0; c < dof; c++) { 328da43764aSToby Isaac PetscInt e, eOff; 329da43764aSToby Isaac e = cone[c]; 330da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 331da43764aSToby Isaac unionCones[cOff + c] = eOff; 332da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 333da43764aSToby Isaac } 334da43764aSToby Isaac } 335da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 336da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 337da43764aSToby Isaac const PetscInt *cone, *orientation; 338da43764aSToby Isaac 339da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 340da43764aSToby Isaac ierr = DMPlexGetCone(Kref, p, &cone);CHKERRQ(ierr); 341da43764aSToby Isaac ierr = DMPlexGetConeOrientation(Kref, p, &orientation);CHKERRQ(ierr); 342da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 343da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 344da43764aSToby Isaac if (uDof) { 345da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 346da43764aSToby Isaac for (c = 0; c < dof; c++) { 347da43764aSToby Isaac PetscInt e, eOff, eDof; 348da43764aSToby Isaac 349da43764aSToby Isaac e = cone[c]; 350da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof);CHKERRQ(ierr); 351da43764aSToby Isaac if (eDof) { 352da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff);CHKERRQ(ierr); 353da43764aSToby Isaac } 354da43764aSToby Isaac else { 355da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, e, &e);CHKERRQ(ierr); 356da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 357da43764aSToby Isaac } 358da43764aSToby Isaac unionCones[cOff + c] = eOff; 359da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 360da43764aSToby Isaac } 361da43764aSToby Isaac } 362da43764aSToby Isaac } 363da43764aSToby Isaac /* get the coordinates */ 364da43764aSToby Isaac { 365da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 366da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 367da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 368da43764aSToby Isaac PetscScalar *Kcoords; 369da43764aSToby Isaac 370da43764aSToby Isaac DMGetCoordinateSection(K, &KcoordsSec);CHKERRQ(ierr); 371da43764aSToby Isaac DMGetCoordinatesLocal(K, &KcoordsVec);CHKERRQ(ierr); 372da43764aSToby Isaac DMGetCoordinateSection(Kref, &KrefCoordsSec);CHKERRQ(ierr); 373da43764aSToby Isaac DMGetCoordinatesLocal(Kref, &KrefCoordsVec);CHKERRQ(ierr); 374da43764aSToby Isaac 375da43764aSToby Isaac numVerts = numDimPoints[0]; 376da43764aSToby Isaac ierr = PetscMalloc1(numVerts * dim,&unionCoords);CHKERRQ(ierr); 377da43764aSToby Isaac ierr = DMPlexGetDepthStratum(K,0,&vStart,&vEnd);CHKERRQ(ierr); 378da43764aSToby Isaac 379da43764aSToby Isaac offset = 0; 380da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 381da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pStart,&vOff);CHKERRQ(ierr); 382da43764aSToby Isaac ierr = VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords);CHKERRQ(ierr); 383da43764aSToby Isaac for (d = 0; d < dim; d++) { 384da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 385da43764aSToby Isaac } 386da43764aSToby Isaac offset++; 387da43764aSToby Isaac } 388da43764aSToby Isaac ierr = DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd);CHKERRQ(ierr); 389da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 390da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof);CHKERRQ(ierr); 391da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff);CHKERRQ(ierr); 392da43764aSToby Isaac ierr = VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords);CHKERRQ(ierr); 393da43764aSToby Isaac if (vDof) { 394da43764aSToby Isaac for (d = 0; d < dim; d++) { 395da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 396da43764aSToby Isaac } 397da43764aSToby Isaac offset++; 398da43764aSToby Isaac } 399da43764aSToby Isaac } 400da43764aSToby Isaac } 401da43764aSToby Isaac ierr = DMCreate(comm,ref);CHKERRQ(ierr); 402da43764aSToby Isaac ierr = DMSetType(*ref,DMPLEX);CHKERRQ(ierr); 40328f4b327SMatthew G. Knepley ierr = DMSetDimension(*ref,dim);CHKERRQ(ierr); 404da43764aSToby Isaac ierr = DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords);CHKERRQ(ierr); 40510f7e118SToby Isaac /* set the tree */ 40610f7e118SToby Isaac ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr); 40710f7e118SToby Isaac ierr = PetscSectionSetChart(parentSection,0,numUnionPoints);CHKERRQ(ierr); 40810f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 40910f7e118SToby Isaac PetscInt uDof, uOff; 41010f7e118SToby Isaac 41110f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 41210f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 41310f7e118SToby Isaac if (uDof) { 41410f7e118SToby Isaac PetscSectionSetDof(parentSection,uOff,1);CHKERRQ(ierr); 41510f7e118SToby Isaac } 41610f7e118SToby Isaac } 41710f7e118SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 41810f7e118SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&parentSize);CHKERRQ(ierr); 41910f7e118SToby Isaac ierr = PetscMalloc2(parentSize,&parents,parentSize,&childIDs);CHKERRQ(ierr); 42010f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 42110f7e118SToby Isaac PetscInt uDof, uOff; 42210f7e118SToby Isaac 42310f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 42410f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 42510f7e118SToby Isaac if (uDof) { 42610f7e118SToby Isaac PetscInt pOff, parent, parentU; 42710f7e118SToby Isaac PetscSectionGetOffset(parentSection,uOff,&pOff);CHKERRQ(ierr); 42810f7e118SToby Isaac DMLabelGetValue(identityRef,p,&parent);CHKERRQ(ierr); 42910f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, parent - pStart,&parentU);CHKERRQ(ierr); 43010f7e118SToby Isaac parents[pOff] = parentU; 43110f7e118SToby Isaac childIDs[pOff] = uOff; 43210f7e118SToby Isaac } 43310f7e118SToby Isaac } 434776742edSToby Isaac ierr = DMPlexSetTree_Internal(*ref,parentSection,parents,childIDs,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 43510f7e118SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 43610f7e118SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 43710f7e118SToby Isaac 438da43764aSToby Isaac /* clean up */ 439da43764aSToby Isaac ierr = PetscSectionDestroy(&unionSection);CHKERRQ(ierr); 440da43764aSToby Isaac ierr = PetscSectionDestroy(&unionConeSection);CHKERRQ(ierr); 441da43764aSToby Isaac ierr = ISDestroy(&perm);CHKERRQ(ierr); 442da43764aSToby Isaac ierr = PetscFree(unionCoords);CHKERRQ(ierr); 443da43764aSToby Isaac ierr = PetscFree2(unionCones,unionOrientations);CHKERRQ(ierr); 444da43764aSToby Isaac ierr = PetscFree2(coneSizes,numDimPoints);CHKERRQ(ierr); 4450e2cc29aSToby Isaac PetscFunctionReturn(0); 4460e2cc29aSToby Isaac } 4470e2cc29aSToby Isaac 4480e2cc29aSToby Isaac #undef __FUNCT__ 4490e2cc29aSToby Isaac #define __FUNCT__ "DMPlexCreateDefaultReferenceTree" 4500e2cc29aSToby Isaac /*@ 4510e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4520e2cc29aSToby Isaac 4530e2cc29aSToby Isaac Collective on comm 4540e2cc29aSToby Isaac 4550e2cc29aSToby Isaac Input Parameters: 4560e2cc29aSToby Isaac + comm - the MPI communicator 4570e2cc29aSToby Isaac . dim - the spatial dimension 4580e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4590e2cc29aSToby Isaac 4600e2cc29aSToby Isaac Output Parameters: 4610e2cc29aSToby Isaac . ref - the reference tree DMPlex object 4620e2cc29aSToby Isaac 4630e2cc29aSToby Isaac Level: intermediate 4640e2cc29aSToby Isaac 4650e2cc29aSToby Isaac .keywords: reference cell 4660e2cc29aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree() 4670e2cc29aSToby Isaac @*/ 4680e2cc29aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 4690e2cc29aSToby Isaac { 4700e2cc29aSToby Isaac DM_Plex *mesh; 4710e2cc29aSToby Isaac DM K, Kref; 4720e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4730e2cc29aSToby Isaac DMLabel identity; 4740e2cc29aSToby Isaac PetscErrorCode ierr; 4750e2cc29aSToby Isaac 4760e2cc29aSToby Isaac PetscFunctionBegin; 4770e2cc29aSToby Isaac #if 1 4780e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4790e2cc29aSToby Isaac #endif 4800e2cc29aSToby Isaac /* create a reference element */ 4810e2cc29aSToby Isaac ierr = DMPlexCreateReferenceCell(comm, dim, simplex, &K);CHKERRQ(ierr); 4820e2cc29aSToby Isaac ierr = DMCreateLabel(K, "identity");CHKERRQ(ierr); 4830e2cc29aSToby Isaac ierr = DMGetLabel(K, "identity", &identity);CHKERRQ(ierr); 4840e2cc29aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 4850e2cc29aSToby Isaac for (p = pStart; p < pEnd; p++) { 4860e2cc29aSToby Isaac ierr = DMLabelSetValue(identity, p, p);CHKERRQ(ierr); 4870e2cc29aSToby Isaac } 4880e2cc29aSToby Isaac /* refine it */ 4890e2cc29aSToby Isaac ierr = DMRefine(K,comm,&Kref);CHKERRQ(ierr); 4900e2cc29aSToby Isaac 4910e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4920e2cc29aSToby Isaac * points that appear in both */ 4930e2cc29aSToby Isaac ierr = DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref);CHKERRQ(ierr); 4940e2cc29aSToby Isaac mesh = (DM_Plex *) (*ref)->data; 4950e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 496da43764aSToby Isaac ierr = DMDestroy(&K);CHKERRQ(ierr); 497da43764aSToby Isaac ierr = DMDestroy(&Kref);CHKERRQ(ierr); 498da43764aSToby Isaac PetscFunctionReturn(0); 499da43764aSToby Isaac } 500da43764aSToby Isaac 501d961a43aSToby Isaac #undef __FUNCT__ 502878b19aaSToby Isaac #define __FUNCT__ "DMPlexTreeSymmetrize" 503878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 504878b19aaSToby Isaac { 505878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 506878b19aaSToby Isaac PetscSection childSec, pSec; 507878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 508878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 509878b19aaSToby Isaac PetscErrorCode ierr; 510878b19aaSToby Isaac 511878b19aaSToby Isaac PetscFunctionBegin; 512878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 513878b19aaSToby Isaac ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 514878b19aaSToby Isaac ierr = PetscFree(mesh->children);CHKERRQ(ierr); 515878b19aaSToby Isaac pSec = mesh->parentSection; 516878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 517878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(pSec,&pSize);CHKERRQ(ierr); 518878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 519878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 520878b19aaSToby Isaac 521878b19aaSToby Isaac parMax = PetscMax(parMax,par+1); 522878b19aaSToby Isaac parMin = PetscMin(parMin,par); 523878b19aaSToby Isaac } 524878b19aaSToby Isaac if (parMin > parMax) { 525878b19aaSToby Isaac parMin = -1; 526878b19aaSToby Isaac parMax = -1; 527878b19aaSToby Isaac } 528878b19aaSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec);CHKERRQ(ierr); 529878b19aaSToby Isaac ierr = PetscSectionSetChart(childSec,parMin,parMax);CHKERRQ(ierr); 530878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 531878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 532878b19aaSToby Isaac 533878b19aaSToby Isaac ierr = PetscSectionAddDof(childSec,par,1);CHKERRQ(ierr); 534878b19aaSToby Isaac } 535878b19aaSToby Isaac ierr = PetscSectionSetUp(childSec);CHKERRQ(ierr); 536878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(childSec,&cSize);CHKERRQ(ierr); 537878b19aaSToby Isaac ierr = PetscMalloc1(cSize,&children);CHKERRQ(ierr); 538878b19aaSToby Isaac ierr = PetscCalloc1(parMax-parMin,&offsets);CHKERRQ(ierr); 539878b19aaSToby Isaac ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr); 540878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 541878b19aaSToby Isaac PetscInt dof, off, i; 542878b19aaSToby Isaac 543878b19aaSToby Isaac ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 544878b19aaSToby Isaac ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr); 545878b19aaSToby Isaac for (i = 0; i < dof; i++) { 546878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 547878b19aaSToby Isaac 548878b19aaSToby Isaac ierr = PetscSectionGetOffset(childSec,par,&cOff);CHKERRQ(ierr); 549878b19aaSToby Isaac children[cOff + offsets[par-parMin]++] = p; 550878b19aaSToby Isaac } 551878b19aaSToby Isaac } 552878b19aaSToby Isaac mesh->childSection = childSec; 553878b19aaSToby Isaac mesh->children = children; 554878b19aaSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 555878b19aaSToby Isaac PetscFunctionReturn(0); 556878b19aaSToby Isaac } 557878b19aaSToby Isaac 558878b19aaSToby Isaac #undef __FUNCT__ 5596dd5a8c8SToby Isaac #define __FUNCT__ "AnchorsFlatten" 5606dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 5616dd5a8c8SToby Isaac { 5626dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5636dd5a8c8SToby Isaac const PetscInt *vals; 5646dd5a8c8SToby Isaac PetscSection secNew; 5656dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5666dd5a8c8SToby Isaac PetscBool compress; 5676dd5a8c8SToby Isaac PetscErrorCode ierr; 5686dd5a8c8SToby Isaac 5696dd5a8c8SToby Isaac PetscFunctionBegin; 5706dd5a8c8SToby Isaac ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr); 5716dd5a8c8SToby Isaac ierr = ISGetLocalSize(is,&size);CHKERRQ(ierr); 5726dd5a8c8SToby Isaac ierr = ISGetIndices(is,&vals);CHKERRQ(ierr); 5736dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew);CHKERRQ(ierr); 5746dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secNew,pStart,pEnd);CHKERRQ(ierr); 5756dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5766dd5a8c8SToby Isaac PetscInt dof; 5776dd5a8c8SToby Isaac 5786dd5a8c8SToby Isaac p = vals[i]; 5796dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5806dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5816dd5a8c8SToby Isaac if (dof) break; 5826dd5a8c8SToby Isaac } 5836dd5a8c8SToby Isaac if (i == size) { 5846dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 5856dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5866dd5a8c8SToby Isaac compress = PETSC_FALSE; 5876dd5a8c8SToby Isaac sizeNew = 0; 5886dd5a8c8SToby Isaac } 5896dd5a8c8SToby Isaac else { 5906dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5916dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5926dd5a8c8SToby Isaac PetscInt dof, off; 5936dd5a8c8SToby Isaac 5946dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 5956dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 5966dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5976dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5986dd5a8c8SToby Isaac 5996dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 6006dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 6016dd5a8c8SToby Isaac } 6026dd5a8c8SToby Isaac if (qDof) { 6036dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, qDof);CHKERRQ(ierr); 6046dd5a8c8SToby Isaac } 6056dd5a8c8SToby Isaac else { 6066dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, 1);CHKERRQ(ierr); 6076dd5a8c8SToby Isaac } 6086dd5a8c8SToby Isaac } 6096dd5a8c8SToby Isaac } 6106dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 6116dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secNew,&sizeNew);CHKERRQ(ierr); 6126dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsNew);CHKERRQ(ierr); 6136dd5a8c8SToby Isaac compress = PETSC_FALSE; 6146dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6156dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 6166dd5a8c8SToby Isaac 6176dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 6186dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 6196dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dofNew);CHKERRQ(ierr); 6206dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &offNew);CHKERRQ(ierr); 6216dd5a8c8SToby Isaac count = 0; 6226dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 6236dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 6246dd5a8c8SToby Isaac 6256dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 6266dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 6276dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, q, &qOff);CHKERRQ(ierr); 6286dd5a8c8SToby Isaac } 6296dd5a8c8SToby Isaac if (qDof) { 6306dd5a8c8SToby Isaac PetscInt oldCount = count; 6316dd5a8c8SToby Isaac 6326dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 6336dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 6346dd5a8c8SToby Isaac 6356dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6366dd5a8c8SToby Isaac if (valsNew[offNew + k] == r) { 6376dd5a8c8SToby Isaac break; 6386dd5a8c8SToby Isaac } 6396dd5a8c8SToby Isaac } 6406dd5a8c8SToby Isaac if (k == oldCount) { 6416dd5a8c8SToby Isaac valsNew[offNew + count++] = r; 6426dd5a8c8SToby Isaac } 6436dd5a8c8SToby Isaac } 6446dd5a8c8SToby Isaac } 6456dd5a8c8SToby Isaac else { 6466dd5a8c8SToby Isaac PetscInt k, oldCount = count; 6476dd5a8c8SToby Isaac 6486dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6496dd5a8c8SToby Isaac if (valsNew[offNew + k] == q) { 6506dd5a8c8SToby Isaac break; 6516dd5a8c8SToby Isaac } 6526dd5a8c8SToby Isaac } 6536dd5a8c8SToby Isaac if (k == oldCount) { 6546dd5a8c8SToby Isaac valsNew[offNew + count++] = q; 6556dd5a8c8SToby Isaac } 6566dd5a8c8SToby Isaac } 6576dd5a8c8SToby Isaac } 6586dd5a8c8SToby Isaac if (count < dofNew) { 6596dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secNew, p, count);CHKERRQ(ierr); 6606dd5a8c8SToby Isaac compress = PETSC_TRUE; 6616dd5a8c8SToby Isaac } 6626dd5a8c8SToby Isaac } 6636dd5a8c8SToby Isaac } 6646dd5a8c8SToby Isaac ierr = ISRestoreIndices(is,&vals);CHKERRQ(ierr); 665b2566f29SBarry Smith ierr = MPIU_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 6666dd5a8c8SToby Isaac if (!globalAnyNew) { 6676dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 6686dd5a8c8SToby Isaac *sectionNew = NULL; 6696dd5a8c8SToby Isaac *isNew = NULL; 6706dd5a8c8SToby Isaac } 6716dd5a8c8SToby Isaac else { 6726dd5a8c8SToby Isaac PetscBool globalCompress; 6736dd5a8c8SToby Isaac 674b2566f29SBarry Smith ierr = MPIU_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 6756dd5a8c8SToby Isaac if (compress) { 6766dd5a8c8SToby Isaac PetscSection secComp; 6776dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6786dd5a8c8SToby Isaac 6796dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp);CHKERRQ(ierr); 6806dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secComp,pStart,pEnd);CHKERRQ(ierr); 6816dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6826dd5a8c8SToby Isaac PetscInt dof; 6836dd5a8c8SToby Isaac 6846dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6856dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secComp, p, dof);CHKERRQ(ierr); 6866dd5a8c8SToby Isaac } 6876dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secComp);CHKERRQ(ierr); 6886dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secComp,&sizeNew);CHKERRQ(ierr); 6896dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsComp);CHKERRQ(ierr); 6906dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6916dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6926dd5a8c8SToby Isaac 6936dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 6946dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &off);CHKERRQ(ierr); 6956dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secComp, p, &offNew);CHKERRQ(ierr); 6966dd5a8c8SToby Isaac for (j = 0; j < dof; j++) { 6976dd5a8c8SToby Isaac valsComp[offNew + j] = valsNew[off + j]; 6986dd5a8c8SToby Isaac } 6996dd5a8c8SToby Isaac } 7006dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 7016dd5a8c8SToby Isaac secNew = secComp; 7026dd5a8c8SToby Isaac ierr = PetscFree(valsNew);CHKERRQ(ierr); 7036dd5a8c8SToby Isaac valsNew = valsComp; 7046dd5a8c8SToby Isaac } 7056dd5a8c8SToby Isaac ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew);CHKERRQ(ierr); 7066dd5a8c8SToby Isaac } 7076dd5a8c8SToby Isaac PetscFunctionReturn(0); 7086dd5a8c8SToby Isaac } 7096dd5a8c8SToby Isaac 7106dd5a8c8SToby Isaac #undef __FUNCT__ 711f7c74593SToby Isaac #define __FUNCT__ "DMPlexCreateAnchors_Tree" 712f7c74593SToby Isaac static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 71366af876cSToby Isaac { 71466af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 71566af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 71666af876cSToby Isaac PetscSection aSec; 717f9f063d4SToby Isaac DMLabel canonLabel; 71866af876cSToby Isaac IS aIS; 71966af876cSToby Isaac PetscErrorCode ierr; 72066af876cSToby Isaac 72166af876cSToby Isaac PetscFunctionBegin; 72266af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 72366af876cSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 724c58f1c22SToby Isaac ierr = DMGetLabel(dm,"canonical",&canonLabel);CHKERRQ(ierr); 72566af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 72666af876cSToby Isaac PetscInt parent; 72766af876cSToby Isaac 728f9f063d4SToby Isaac if (canonLabel) { 729f9f063d4SToby Isaac PetscInt canon; 730f9f063d4SToby Isaac 731f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 732f9f063d4SToby Isaac if (p != canon) continue; 733f9f063d4SToby Isaac } 73466af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 73566af876cSToby Isaac if (parent != p) { 73666af876cSToby Isaac aMin = PetscMin(aMin,p); 73766af876cSToby Isaac aMax = PetscMax(aMax,p+1); 73866af876cSToby Isaac } 73966af876cSToby Isaac } 74066af876cSToby Isaac if (aMin > aMax) { 74166af876cSToby Isaac aMin = -1; 74266af876cSToby Isaac aMax = -1; 74366af876cSToby Isaac } 744e228b242SToby Isaac ierr = PetscSectionCreate(PETSC_COMM_SELF,&aSec);CHKERRQ(ierr); 74566af876cSToby Isaac ierr = PetscSectionSetChart(aSec,aMin,aMax);CHKERRQ(ierr); 74666af876cSToby Isaac for (p = aMin; p < aMax; p++) { 74766af876cSToby Isaac PetscInt parent, ancestor = p; 74866af876cSToby Isaac 749f9f063d4SToby Isaac if (canonLabel) { 750f9f063d4SToby Isaac PetscInt canon; 751f9f063d4SToby Isaac 752f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 753f9f063d4SToby Isaac if (p != canon) continue; 754f9f063d4SToby Isaac } 75566af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 75666af876cSToby Isaac while (parent != ancestor) { 75766af876cSToby Isaac ancestor = parent; 75866af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 75966af876cSToby Isaac } 76066af876cSToby Isaac if (ancestor != p) { 76166af876cSToby Isaac PetscInt closureSize, *closure = NULL; 76266af876cSToby Isaac 76366af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 76466af876cSToby Isaac ierr = PetscSectionSetDof(aSec,p,closureSize);CHKERRQ(ierr); 76566af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 76666af876cSToby Isaac } 76766af876cSToby Isaac } 76866af876cSToby Isaac ierr = PetscSectionSetUp(aSec);CHKERRQ(ierr); 76966af876cSToby Isaac ierr = PetscSectionGetStorageSize(aSec,&size);CHKERRQ(ierr); 77066af876cSToby Isaac ierr = PetscMalloc1(size,&anchors);CHKERRQ(ierr); 77166af876cSToby Isaac for (p = aMin; p < aMax; p++) { 77266af876cSToby Isaac PetscInt parent, ancestor = p; 77366af876cSToby Isaac 774f9f063d4SToby Isaac if (canonLabel) { 775f9f063d4SToby Isaac PetscInt canon; 776f9f063d4SToby Isaac 777f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr); 778f9f063d4SToby Isaac if (p != canon) continue; 779f9f063d4SToby Isaac } 78066af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 78166af876cSToby Isaac while (parent != ancestor) { 78266af876cSToby Isaac ancestor = parent; 78366af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 78466af876cSToby Isaac } 78566af876cSToby Isaac if (ancestor != p) { 78666af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 78766af876cSToby Isaac 78866af876cSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 78966af876cSToby Isaac 79066af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 79166af876cSToby Isaac for (j = 0; j < closureSize; j++) { 79266af876cSToby Isaac anchors[aOff + j] = closure[2*j]; 79366af876cSToby Isaac } 79466af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 79566af876cSToby Isaac } 79666af876cSToby Isaac } 797e228b242SToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,size,anchors,PETSC_OWN_POINTER,&aIS);CHKERRQ(ierr); 7986dd5a8c8SToby Isaac { 7996dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 8006dd5a8c8SToby Isaac IS aISNew = aIS; 8016dd5a8c8SToby Isaac 8026dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aSec);CHKERRQ(ierr); 8036dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aIS);CHKERRQ(ierr); 8046dd5a8c8SToby Isaac while (aSecNew) { 8056dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 8066dd5a8c8SToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 8076dd5a8c8SToby Isaac aSec = aSecNew; 8086dd5a8c8SToby Isaac aIS = aISNew; 8096dd5a8c8SToby Isaac aSecNew = NULL; 8106dd5a8c8SToby Isaac aISNew = NULL; 8116dd5a8c8SToby Isaac ierr = AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew);CHKERRQ(ierr); 8126dd5a8c8SToby Isaac } 8136dd5a8c8SToby Isaac } 814a17985deSToby Isaac ierr = DMPlexSetAnchors(dm,aSec,aIS);CHKERRQ(ierr); 81566af876cSToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 81666af876cSToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 81766af876cSToby Isaac PetscFunctionReturn(0); 81866af876cSToby Isaac } 81966af876cSToby Isaac 82066af876cSToby Isaac #undef __FUNCT__ 8216461c1adSToby Isaac #define __FUNCT__ "DMPlexGetTrueSupportSize" 8226461c1adSToby Isaac static PetscErrorCode DMPlexGetTrueSupportSize(DM dm,PetscInt p,PetscInt *dof,PetscInt *numTrueSupp) 8236461c1adSToby Isaac { 8246461c1adSToby Isaac PetscErrorCode ierr; 8256461c1adSToby Isaac 8266461c1adSToby Isaac PetscFunctionBegin; 8276461c1adSToby Isaac if (numTrueSupp[p] == -1) { 8286461c1adSToby Isaac PetscInt i, alldof; 8296461c1adSToby Isaac const PetscInt *supp; 8306461c1adSToby Isaac PetscInt count = 0; 8316461c1adSToby Isaac 8326461c1adSToby Isaac ierr = DMPlexGetSupportSize(dm,p,&alldof);CHKERRQ(ierr); 8336461c1adSToby Isaac ierr = DMPlexGetSupport(dm,p,&supp);CHKERRQ(ierr); 8346461c1adSToby Isaac for (i = 0; i < alldof; i++) { 8356461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 8366461c1adSToby Isaac const PetscInt *cone; 8376461c1adSToby Isaac 8386461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr); 8396461c1adSToby Isaac ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr); 8406461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8416461c1adSToby Isaac if (cone[j] == p) break; 8426461c1adSToby Isaac } 8436461c1adSToby Isaac if (j < numCones) count++; 8446461c1adSToby Isaac } 8456461c1adSToby Isaac numTrueSupp[p] = count; 8466461c1adSToby Isaac } 8476461c1adSToby Isaac *dof = numTrueSupp[p]; 8486461c1adSToby Isaac PetscFunctionReturn(0); 8496461c1adSToby Isaac } 8506461c1adSToby Isaac 8516461c1adSToby Isaac #undef __FUNCT__ 852776742edSToby Isaac #define __FUNCT__ "DMPlexTreeExchangeSupports" 853776742edSToby Isaac static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 854776742edSToby Isaac { 855776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 856776742edSToby Isaac PetscSection newSupportSection; 857776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 8586461c1adSToby Isaac PetscInt *numTrueSupp; 859776742edSToby Isaac PetscInt *offsets; 860776742edSToby Isaac PetscErrorCode ierr; 861776742edSToby Isaac 862776742edSToby Isaac PetscFunctionBegin; 863776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 864776742edSToby Isaac /* symmetrize the hierarchy */ 865776742edSToby Isaac ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 866e228b242SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)),&newSupportSection);CHKERRQ(ierr); 867776742edSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 868776742edSToby Isaac ierr = PetscSectionSetChart(newSupportSection,pStart,pEnd);CHKERRQ(ierr); 869776742edSToby Isaac ierr = PetscCalloc1(pEnd,&offsets);CHKERRQ(ierr); 8706461c1adSToby Isaac ierr = PetscMalloc1(pEnd,&numTrueSupp);CHKERRQ(ierr); 8716461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 8726461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 873776742edSToby Isaac * parent(q) */ 874776742edSToby Isaac for (d = 0; d <= depth; d++) { 875776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 876776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 877776742edSToby Isaac PetscInt dof, q, qdof, parent; 878776742edSToby Isaac 8796461c1adSToby Isaac ierr = DMPlexGetTrueSupportSize(dm,p,&dof,numTrueSupp);CHKERRQ(ierr); 880776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection, p, dof);CHKERRQ(ierr); 881776742edSToby Isaac q = p; 882776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 883776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 884776742edSToby Isaac q = parent; 885776742edSToby Isaac 8866461c1adSToby Isaac ierr = DMPlexGetTrueSupportSize(dm,q,&qdof,numTrueSupp);CHKERRQ(ierr); 887776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,p,qdof);CHKERRQ(ierr); 888776742edSToby Isaac ierr = PetscSectionAddDof(newSupportSection,q,dof);CHKERRQ(ierr); 889776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 890776742edSToby Isaac } 891776742edSToby Isaac } 892776742edSToby Isaac } 893776742edSToby Isaac ierr = PetscSectionSetUp(newSupportSection);CHKERRQ(ierr); 894776742edSToby Isaac ierr = PetscSectionGetStorageSize(newSupportSection,&newSize);CHKERRQ(ierr); 895776742edSToby Isaac ierr = PetscMalloc1(newSize,&newSupports);CHKERRQ(ierr); 896776742edSToby Isaac for (d = 0; d <= depth; d++) { 897776742edSToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr); 898776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 899776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 900776742edSToby Isaac 901776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 902776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 903776742edSToby Isaac ierr = PetscSectionGetDof(newSupportSection, p, &newDof);CHKERRQ(ierr); 904776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, p, &newOff);CHKERRQ(ierr); 905776742edSToby Isaac for (i = 0; i < dof; i++) { 9066461c1adSToby Isaac PetscInt numCones, j; 9076461c1adSToby Isaac const PetscInt *cone; 9086461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 9096461c1adSToby Isaac 9106461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr); 9116461c1adSToby Isaac ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr); 9126461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9136461c1adSToby Isaac if (cone[j] == p) break; 9146461c1adSToby Isaac } 9156461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = q; 916776742edSToby Isaac } 917776742edSToby Isaac mesh->maxSupportSize = PetscMax(mesh->maxSupportSize,newDof); 918776742edSToby Isaac 919776742edSToby Isaac q = p; 920776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 921776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 922776742edSToby Isaac q = parent; 923776742edSToby Isaac ierr = PetscSectionGetDof(mesh->supportSection, q, &qdof);CHKERRQ(ierr); 924776742edSToby Isaac ierr = PetscSectionGetOffset(mesh->supportSection, q, &qoff);CHKERRQ(ierr); 925776742edSToby Isaac ierr = PetscSectionGetOffset(newSupportSection, q, &newqOff);CHKERRQ(ierr); 926776742edSToby Isaac for (i = 0; i < qdof; i++) { 9276461c1adSToby Isaac PetscInt numCones, j; 9286461c1adSToby Isaac const PetscInt *cone; 9296461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 9306461c1adSToby Isaac 9316461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr); 9326461c1adSToby Isaac ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr); 9336461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9346461c1adSToby Isaac if (cone[j] == q) break; 9356461c1adSToby Isaac } 9366461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = r; 937776742edSToby Isaac } 938776742edSToby Isaac for (i = 0; i < dof; i++) { 9396461c1adSToby Isaac PetscInt numCones, j; 9406461c1adSToby Isaac const PetscInt *cone; 9416461c1adSToby Isaac PetscInt r = mesh->supports[off + i]; 9426461c1adSToby Isaac 9436461c1adSToby Isaac ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr); 9446461c1adSToby Isaac ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr); 9456461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9466461c1adSToby Isaac if (cone[j] == p) break; 9476461c1adSToby Isaac } 9486461c1adSToby Isaac if (j < numCones) newSupports[newqOff+offsets[q]++] = r; 949776742edSToby Isaac } 950776742edSToby Isaac ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr); 951776742edSToby Isaac } 952776742edSToby Isaac } 953776742edSToby Isaac } 954776742edSToby Isaac ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 955776742edSToby Isaac mesh->supportSection = newSupportSection; 956776742edSToby Isaac ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 957776742edSToby Isaac mesh->supports = newSupports; 958776742edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 9596461c1adSToby Isaac ierr = PetscFree(numTrueSupp);CHKERRQ(ierr); 960776742edSToby Isaac 961776742edSToby Isaac PetscFunctionReturn(0); 962776742edSToby Isaac } 963776742edSToby Isaac 964f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM,PetscSection,PetscSection,Mat); 965f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM,PetscSection,PetscSection,Mat); 966f7c74593SToby Isaac 967776742edSToby Isaac #undef __FUNCT__ 968f9f063d4SToby Isaac #define __FUNCT__ "DMPlexSetTree_Internal" 969776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 970f9f063d4SToby Isaac { 971f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 972f9f063d4SToby Isaac DM refTree; 973f9f063d4SToby Isaac PetscInt size; 974f9f063d4SToby Isaac PetscErrorCode ierr; 975f9f063d4SToby Isaac 976f9f063d4SToby Isaac PetscFunctionBegin; 977f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 978f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 979f9f063d4SToby Isaac ierr = PetscObjectReference((PetscObject)parentSection);CHKERRQ(ierr); 980f9f063d4SToby Isaac ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 981f9f063d4SToby Isaac mesh->parentSection = parentSection; 982f9f063d4SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&size);CHKERRQ(ierr); 983f9f063d4SToby Isaac if (parents != mesh->parents) { 984f9f063d4SToby Isaac ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 985f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->parents);CHKERRQ(ierr); 986f9f063d4SToby Isaac ierr = PetscMemcpy(mesh->parents, parents, size * sizeof(*parents));CHKERRQ(ierr); 987f9f063d4SToby Isaac } 988f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 989f9f063d4SToby Isaac ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 990f9f063d4SToby Isaac ierr = PetscMalloc1(size,&mesh->childIDs);CHKERRQ(ierr); 991f9f063d4SToby Isaac ierr = PetscMemcpy(mesh->childIDs, childIDs, size * sizeof(*childIDs));CHKERRQ(ierr); 992f9f063d4SToby Isaac } 993f9f063d4SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 994f9f063d4SToby Isaac if (refTree) { 995f9f063d4SToby Isaac DMLabel canonLabel; 996f9f063d4SToby Isaac 997c58f1c22SToby Isaac ierr = DMGetLabel(refTree,"canonical",&canonLabel);CHKERRQ(ierr); 998f9f063d4SToby Isaac if (canonLabel) { 999f9f063d4SToby Isaac PetscInt i; 1000f9f063d4SToby Isaac 1001f9f063d4SToby Isaac for (i = 0; i < size; i++) { 1002f9f063d4SToby Isaac PetscInt canon; 1003f9f063d4SToby Isaac ierr = DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon);CHKERRQ(ierr); 1004f9f063d4SToby Isaac if (canon >= 0) { 1005f9f063d4SToby Isaac mesh->childIDs[i] = canon; 1006f9f063d4SToby Isaac } 1007f9f063d4SToby Isaac } 1008f9f063d4SToby Isaac } 1009f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 1010f7c74593SToby Isaac } 1011f7c74593SToby Isaac else { 1012f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 1013f9f063d4SToby Isaac } 1014f9f063d4SToby Isaac ierr = DMPlexTreeSymmetrize(dm);CHKERRQ(ierr); 1015f9f063d4SToby Isaac if (computeCanonical) { 1016f9f063d4SToby Isaac PetscInt d, dim; 1017f9f063d4SToby Isaac 1018f9f063d4SToby Isaac /* add the canonical label */ 101928f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 1020c58f1c22SToby Isaac ierr = DMCreateLabel(dm,"canonical");CHKERRQ(ierr); 1021f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 1022f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 1023f9f063d4SToby Isaac const PetscInt *cChildren; 1024f9f063d4SToby Isaac 1025f9f063d4SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 1026f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1027f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&cNumChildren,&cChildren);CHKERRQ(ierr); 1028f9f063d4SToby Isaac if (cNumChildren) { 1029f9f063d4SToby Isaac canon = p; 1030f9f063d4SToby Isaac break; 1031f9f063d4SToby Isaac } 1032f9f063d4SToby Isaac } 1033f9f063d4SToby Isaac if (canon == -1) continue; 1034f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1035f9f063d4SToby Isaac PetscInt numChildren, i; 1036f9f063d4SToby Isaac const PetscInt *children; 1037f9f063d4SToby Isaac 1038f9f063d4SToby Isaac ierr = DMPlexGetTreeChildren(dm,p,&numChildren,&children);CHKERRQ(ierr); 1039f9f063d4SToby Isaac if (numChildren) { 1040f9f063d4SToby 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); 1041c58f1c22SToby Isaac ierr = DMSetLabelValue(dm,"canonical",p,canon);CHKERRQ(ierr); 1042f9f063d4SToby Isaac for (i = 0; i < numChildren; i++) { 1043c58f1c22SToby Isaac ierr = DMSetLabelValue(dm,"canonical",children[i],cChildren[i]);CHKERRQ(ierr); 1044f9f063d4SToby Isaac } 1045f9f063d4SToby Isaac } 1046f9f063d4SToby Isaac } 1047f9f063d4SToby Isaac } 1048f9f063d4SToby Isaac } 1049776742edSToby Isaac if (exchangeSupports) { 1050776742edSToby Isaac ierr = DMPlexTreeExchangeSupports(dm);CHKERRQ(ierr); 1051776742edSToby Isaac } 1052f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 1053f7c74593SToby Isaac /* reset anchors */ 1054f7c74593SToby Isaac ierr = DMPlexSetAnchors(dm,NULL,NULL);CHKERRQ(ierr); 1055f9f063d4SToby Isaac PetscFunctionReturn(0); 1056f9f063d4SToby Isaac } 1057f9f063d4SToby Isaac 1058f9f063d4SToby Isaac #undef __FUNCT__ 10590b7167a0SToby Isaac #define __FUNCT__ "DMPlexSetTree" 10600b7167a0SToby Isaac /*@ 10610b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 10620b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 10630b7167a0SToby Isaac tree root. 10640b7167a0SToby Isaac 10650b7167a0SToby Isaac Collective on dm 10660b7167a0SToby Isaac 10670b7167a0SToby Isaac Input Parameters: 10680b7167a0SToby Isaac + dm - the DMPlex object 10690b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 10700b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 10710b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 10720b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 10730b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 10740b7167a0SToby Isaac 10750b7167a0SToby Isaac Level: intermediate 10760b7167a0SToby Isaac 1077a17985deSToby Isaac .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 10780b7167a0SToby Isaac @*/ 1079b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 10800b7167a0SToby Isaac { 10810b7167a0SToby Isaac PetscErrorCode ierr; 10820b7167a0SToby Isaac 10830b7167a0SToby Isaac PetscFunctionBegin; 1084776742edSToby Isaac ierr = DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 10850b7167a0SToby Isaac PetscFunctionReturn(0); 10860b7167a0SToby Isaac } 10870b7167a0SToby Isaac 10880b7167a0SToby Isaac #undef __FUNCT__ 1089b2f41788SToby Isaac #define __FUNCT__ "DMPlexGetTree" 1090b2f41788SToby Isaac /*@ 1091b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 1092b2f41788SToby Isaac Collective on dm 1093b2f41788SToby Isaac 1094b2f41788SToby Isaac Input Parameters: 1095b2f41788SToby Isaac . dm - the DMPlex object 1096b2f41788SToby Isaac 1097b2f41788SToby Isaac Output Parameters: 1098b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1099b2f41788SToby Isaac offset indexes the parent and childID list 1100b2f41788SToby Isaac . parents - a list of the point parents 1101b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1102b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1103b2f41788SToby Isaac . childSection - the inverse of the parent section 1104b2f41788SToby Isaac - children - a list of the point children 1105b2f41788SToby Isaac 1106b2f41788SToby Isaac Level: intermediate 1107b2f41788SToby Isaac 1108a17985deSToby Isaac .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 1109b2f41788SToby Isaac @*/ 1110b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1111b2f41788SToby Isaac { 1112b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1113b2f41788SToby Isaac 1114b2f41788SToby Isaac PetscFunctionBegin; 1115b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1116b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1117b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1118b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1119b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1120b2f41788SToby Isaac if (children) *children = mesh->children; 1121b2f41788SToby Isaac PetscFunctionReturn(0); 1122b2f41788SToby Isaac } 1123b2f41788SToby Isaac 1124b2f41788SToby Isaac #undef __FUNCT__ 1125d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeParent" 1126d961a43aSToby Isaac /*@ 1127d961a43aSToby Isaac DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the Sieve DAG) 1128d961a43aSToby Isaac 1129d961a43aSToby Isaac Input Parameters: 1130d961a43aSToby Isaac + dm - the DMPlex object 1131d961a43aSToby Isaac - point - the query point 1132d961a43aSToby Isaac 1133d961a43aSToby Isaac Output Parameters: 1134d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 1135d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 1136d961a43aSToby Isaac does not have a parent 1137d961a43aSToby Isaac 1138d961a43aSToby Isaac Level: intermediate 1139d961a43aSToby Isaac 1140d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren() 1141d961a43aSToby Isaac @*/ 1142d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1143d961a43aSToby Isaac { 1144d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1145d961a43aSToby Isaac PetscSection pSec; 1146d961a43aSToby Isaac PetscErrorCode ierr; 1147d961a43aSToby Isaac 1148d961a43aSToby Isaac PetscFunctionBegin; 1149d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1150d961a43aSToby Isaac pSec = mesh->parentSection; 1151d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1152d961a43aSToby Isaac PetscInt dof; 1153d961a43aSToby Isaac 1154d961a43aSToby Isaac ierr = PetscSectionGetDof (pSec, point, &dof);CHKERRQ(ierr); 1155d961a43aSToby Isaac if (dof) { 1156d961a43aSToby Isaac PetscInt off; 1157d961a43aSToby Isaac 1158d961a43aSToby Isaac ierr = PetscSectionGetOffset (pSec, point, &off);CHKERRQ(ierr); 1159d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1160d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 1161d961a43aSToby Isaac PetscFunctionReturn(0); 1162d961a43aSToby Isaac } 1163d961a43aSToby Isaac } 1164d961a43aSToby Isaac if (parent) { 1165d961a43aSToby Isaac *parent = point; 1166d961a43aSToby Isaac } 1167d961a43aSToby Isaac if (childID) { 1168d961a43aSToby Isaac *childID = 0; 1169d961a43aSToby Isaac } 1170d961a43aSToby Isaac PetscFunctionReturn(0); 1171d961a43aSToby Isaac } 1172d961a43aSToby Isaac 1173d961a43aSToby Isaac #undef __FUNCT__ 1174d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeChildren" 1175d961a43aSToby Isaac /*@C 1176d961a43aSToby Isaac DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the Sieve DAG) 1177d961a43aSToby Isaac 1178d961a43aSToby Isaac Input Parameters: 1179d961a43aSToby Isaac + dm - the DMPlex object 1180d961a43aSToby Isaac - point - the query point 1181d961a43aSToby Isaac 1182d961a43aSToby Isaac Output Parameters: 1183d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 1184d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 1185d961a43aSToby Isaac 1186d961a43aSToby Isaac Level: intermediate 1187d961a43aSToby Isaac 1188d961a43aSToby Isaac Fortran Notes: 1189d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1190d961a43aSToby Isaac include petsc.h90 in your code. 1191d961a43aSToby Isaac 1192d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent() 1193d961a43aSToby Isaac @*/ 1194d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1195d961a43aSToby Isaac { 1196d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1197d961a43aSToby Isaac PetscSection childSec; 1198d961a43aSToby Isaac PetscInt dof = 0; 1199d961a43aSToby Isaac PetscErrorCode ierr; 1200d961a43aSToby Isaac 1201d961a43aSToby Isaac PetscFunctionBegin; 1202d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1203d961a43aSToby Isaac childSec = mesh->childSection; 1204d961a43aSToby Isaac if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 1205d961a43aSToby Isaac ierr = PetscSectionGetDof (childSec, point, &dof);CHKERRQ(ierr); 1206d961a43aSToby Isaac } 1207d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1208d961a43aSToby Isaac if (children) { 1209d961a43aSToby Isaac if (dof) { 1210d961a43aSToby Isaac PetscInt off; 1211d961a43aSToby Isaac 1212d961a43aSToby Isaac ierr = PetscSectionGetOffset (childSec, point, &off);CHKERRQ(ierr); 1213d961a43aSToby Isaac *children = &mesh->children[off]; 1214d961a43aSToby Isaac } 1215d961a43aSToby Isaac else { 1216d961a43aSToby Isaac *children = NULL; 1217d961a43aSToby Isaac } 1218d961a43aSToby Isaac } 1219d961a43aSToby Isaac PetscFunctionReturn(0); 1220d961a43aSToby Isaac } 12210c37af3bSToby Isaac 12220c37af3bSToby Isaac #undef __FUNCT__ 1223f7c74593SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_Direct" 1224f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 12250c37af3bSToby Isaac { 12260c37af3bSToby Isaac PetscDS ds; 12270c37af3bSToby Isaac PetscInt spdim; 12280c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 12290c37af3bSToby Isaac const PetscInt *anchors; 1230f7c74593SToby Isaac PetscSection aSec; 12310c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 12320c37af3bSToby Isaac IS aIS; 12330c37af3bSToby Isaac PetscErrorCode ierr; 12340c37af3bSToby Isaac 12350c37af3bSToby Isaac PetscFunctionBegin; 12360c37af3bSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 12370c37af3bSToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 12380c37af3bSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 12390c37af3bSToby Isaac ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 1240a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 12410c37af3bSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 12420c37af3bSToby Isaac ierr = PetscSectionGetChart(cSec,&conStart,&conEnd);CHKERRQ(ierr); 124328f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&spdim);CHKERRQ(ierr); 12440c37af3bSToby Isaac ierr = PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent);CHKERRQ(ierr); 12450c37af3bSToby Isaac 12460c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 12470dd1b1feSToby Isaac PetscObject disc; 12480dd1b1feSToby Isaac PetscFE fe = NULL; 12490dd1b1feSToby Isaac PetscFV fv = NULL; 12500dd1b1feSToby Isaac PetscClassId id; 12510c37af3bSToby Isaac PetscDualSpace space; 12520c37af3bSToby Isaac PetscInt i, j, k, nPoints, offset; 12530c37af3bSToby Isaac PetscInt fSize, fComp; 1254c111c6b7SMatthew G. Knepley PetscReal *B = NULL; 12550c37af3bSToby Isaac PetscReal *weights, *pointsRef, *pointsReal; 12560c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 12570c37af3bSToby Isaac 12580dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 12590dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 12600dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 12610dd1b1feSToby Isaac fe = (PetscFE) disc; 12620c37af3bSToby Isaac ierr = PetscFEGetDualSpace(fe,&space);CHKERRQ(ierr); 12630c37af3bSToby Isaac ierr = PetscDualSpaceGetDimension(space,&fSize);CHKERRQ(ierr); 12640c37af3bSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 12650dd1b1feSToby Isaac } 12660dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 12670dd1b1feSToby Isaac fv = (PetscFV) disc; 12680dd1b1feSToby Isaac ierr = PetscFVGetDualSpace(fv,&space);CHKERRQ(ierr); 12690dd1b1feSToby Isaac ierr = PetscDualSpaceGetDimension(space,&fSize);CHKERRQ(ierr); 12700dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 12710dd1b1feSToby Isaac } 12720dd1b1feSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 12730dd1b1feSToby Isaac 12740c37af3bSToby Isaac ierr = MatCreate(PETSC_COMM_SELF,&Amat);CHKERRQ(ierr); 12750c37af3bSToby Isaac ierr = MatSetSizes(Amat,fSize,fSize,fSize,fSize);CHKERRQ(ierr); 12760c37af3bSToby Isaac ierr = MatSetType(Amat,MATSEQDENSE);CHKERRQ(ierr); 12770c37af3bSToby Isaac ierr = MatSetUp(Amat);CHKERRQ(ierr); 12780c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat);CHKERRQ(ierr); 12790c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat);CHKERRQ(ierr); 12800c37af3bSToby Isaac nPoints = 0; 12810c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12820c37af3bSToby Isaac PetscInt qPoints; 12830c37af3bSToby Isaac PetscQuadrature quad; 12840c37af3bSToby Isaac 12850c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 12860c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 12870c37af3bSToby Isaac nPoints += qPoints; 12880c37af3bSToby Isaac } 12890c37af3bSToby Isaac ierr = PetscMalloc3(nPoints,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal);CHKERRQ(ierr); 12900c37af3bSToby Isaac offset = 0; 12910c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12920c37af3bSToby Isaac PetscInt qPoints; 12930c37af3bSToby Isaac const PetscReal *p, *w; 12940c37af3bSToby Isaac PetscQuadrature quad; 12950c37af3bSToby Isaac 12960c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 12970c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,&p,&w);CHKERRQ(ierr); 12980c37af3bSToby Isaac ierr = PetscMemcpy(weights+offset,w,qPoints*sizeof(*w));CHKERRQ(ierr); 12990c37af3bSToby Isaac ierr = PetscMemcpy(pointsRef+spdim*offset,p,spdim*qPoints*sizeof(*p));CHKERRQ(ierr); 13000c37af3bSToby Isaac offset += qPoints; 13010c37af3bSToby Isaac } 13020dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 13030c37af3bSToby Isaac ierr = PetscFEGetTabulation(fe,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 13040dd1b1feSToby Isaac } 13050dd1b1feSToby Isaac else { 13060dd1b1feSToby Isaac ierr = PetscFVGetTabulation(fv,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 13070dd1b1feSToby Isaac } 13080c37af3bSToby Isaac offset = 0; 13090c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 13100c37af3bSToby Isaac PetscInt qPoints; 13110c37af3bSToby Isaac PetscQuadrature quad; 13120c37af3bSToby Isaac 13130c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 13140c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 13150c37af3bSToby Isaac for (j = 0; j < fSize; j++) { 13160c37af3bSToby Isaac PetscScalar val = 0.; 13170c37af3bSToby Isaac 13180c37af3bSToby Isaac for (k = 0; k < qPoints; k++) { 13190c37af3bSToby Isaac val += B[((offset + k) * fSize + j) * fComp] * weights[k]; 13200c37af3bSToby Isaac } 13210c37af3bSToby Isaac ierr = MatSetValue(Amat,i,j,val,INSERT_VALUES);CHKERRQ(ierr); 13220c37af3bSToby Isaac } 13230c37af3bSToby Isaac offset += qPoints; 13240c37af3bSToby Isaac } 13250dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 13260c37af3bSToby Isaac ierr = PetscFERestoreTabulation(fe,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 13270dd1b1feSToby Isaac } 13280dd1b1feSToby Isaac else { 13290dd1b1feSToby Isaac ierr = PetscFVRestoreTabulation(fv,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 13300dd1b1feSToby Isaac } 13310c37af3bSToby Isaac ierr = MatAssemblyBegin(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 13320c37af3bSToby Isaac ierr = MatAssemblyEnd(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 13330c37af3bSToby Isaac ierr = MatLUFactor(Amat,NULL,NULL,NULL);CHKERRQ(ierr); 13340c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 13350c37af3bSToby Isaac PetscInt parent; 13360c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 13370c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 13380c37af3bSToby Isaac 13390c37af3bSToby Isaac ierr = DMPlexGetTreeParent(dm,c,&parent,NULL);CHKERRQ(ierr); 13400c37af3bSToby Isaac if (parent == c) continue; 13410c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13420c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13430c37af3bSToby Isaac PetscInt p = closure[2*i]; 13440c37af3bSToby Isaac PetscInt conDof; 13450c37af3bSToby Isaac 13460c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 13470c37af3bSToby Isaac if (numFields > 1) { 13480c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 13490c37af3bSToby Isaac } 13500c37af3bSToby Isaac else { 13510c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 13520c37af3bSToby Isaac } 13530c37af3bSToby Isaac if (conDof) break; 13540c37af3bSToby Isaac } 13550c37af3bSToby Isaac if (i == closureSize) { 13560c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13570c37af3bSToby Isaac continue; 13580c37af3bSToby Isaac } 13590c37af3bSToby Isaac 136073a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 136173a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent);CHKERRQ(ierr); 13620c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 13630c37af3bSToby Isaac CoordinatesRefToReal(spdim, spdim, v0, J, &pointsRef[i*spdim],vtmp);CHKERRQ(ierr); 13640c37af3bSToby Isaac CoordinatesRealToRef(spdim, spdim, v0parent, invJparent, vtmp, &pointsReal[i*spdim]);CHKERRQ(ierr); 13650c37af3bSToby Isaac } 13660dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 13670c37af3bSToby Isaac ierr = PetscFEGetTabulation(fe,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 13680dd1b1feSToby Isaac } 13690dd1b1feSToby Isaac else { 13700dd1b1feSToby Isaac ierr = PetscFVGetTabulation(fv,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 13710dd1b1feSToby Isaac } 13720c37af3bSToby Isaac offset = 0; 13730c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 13740c37af3bSToby Isaac PetscInt qPoints; 13750c37af3bSToby Isaac PetscQuadrature quad; 13760c37af3bSToby Isaac 13770c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 13780c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 13790c37af3bSToby Isaac for (j = 0; j < fSize; j++) { 13800c37af3bSToby Isaac PetscScalar val = 0.; 13810c37af3bSToby Isaac 13820c37af3bSToby Isaac for (k = 0; k < qPoints; k++) { 13830c37af3bSToby Isaac val += B[((offset + k) * fSize + j) * fComp] * weights[k]; 13840c37af3bSToby Isaac } 13850c37af3bSToby Isaac MatSetValue(Bmat,i,j,val,INSERT_VALUES);CHKERRQ(ierr); 13860c37af3bSToby Isaac } 13870c37af3bSToby Isaac offset += qPoints; 13880c37af3bSToby Isaac } 13890dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 13900c37af3bSToby Isaac ierr = PetscFERestoreTabulation(fe,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 13910dd1b1feSToby Isaac } 13920dd1b1feSToby Isaac else { 13930dd1b1feSToby Isaac ierr = PetscFVRestoreTabulation(fv,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 13940dd1b1feSToby Isaac } 13950c37af3bSToby Isaac ierr = MatAssemblyBegin(Bmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 13960c37af3bSToby Isaac ierr = MatAssemblyEnd(Bmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 13970c37af3bSToby Isaac ierr = MatMatSolve(Amat,Bmat,Xmat);CHKERRQ(ierr); 13980c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 13990c37af3bSToby Isaac ierr = PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets);CHKERRQ(ierr); 14000c37af3bSToby Isaac childOffsets[0] = 0; 14010c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 14020c37af3bSToby Isaac PetscInt p = closure[2*i]; 14030c37af3bSToby Isaac PetscInt dof; 14040c37af3bSToby Isaac 14050c37af3bSToby Isaac if (numFields > 1) { 14060c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 14070c37af3bSToby Isaac } 14080c37af3bSToby Isaac else { 14090c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 14100c37af3bSToby Isaac } 14110c37af3bSToby Isaac childOffsets[i+1]=childOffsets[i]+dof / fComp; 14120c37af3bSToby Isaac } 14130c37af3bSToby Isaac parentOffsets[0] = 0; 14140c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 14150c37af3bSToby Isaac PetscInt p = closureP[2*i]; 14160c37af3bSToby Isaac PetscInt dof; 14170c37af3bSToby Isaac 14180c37af3bSToby Isaac if (numFields > 1) { 14190c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 14200c37af3bSToby Isaac } 14210c37af3bSToby Isaac else { 14220c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 14230c37af3bSToby Isaac } 14240c37af3bSToby Isaac parentOffsets[i+1]=parentOffsets[i]+dof / fComp; 14250c37af3bSToby Isaac } 14260c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 14270c37af3bSToby Isaac PetscInt conDof, conOff, aDof, aOff; 14280c37af3bSToby Isaac PetscInt p = closure[2*i]; 14290c37af3bSToby Isaac PetscInt o = closure[2*i+1]; 14300c37af3bSToby Isaac 14310c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 14320c37af3bSToby Isaac if (numFields > 1) { 14330c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 14340c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(cSec,p,f,&conOff);CHKERRQ(ierr); 14350c37af3bSToby Isaac } 14360c37af3bSToby Isaac else { 14370c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 14380c37af3bSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&conOff);CHKERRQ(ierr); 14390c37af3bSToby Isaac } 14400c37af3bSToby Isaac if (!conDof) continue; 14410c37af3bSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 14420c37af3bSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 14430c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 14440c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 14450c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 14460c37af3bSToby Isaac 14470c37af3bSToby Isaac if (numFields > 1) { 14480c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,a,f,&aSecDof);CHKERRQ(ierr); 14490c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(section,a,f,&aSecOff);CHKERRQ(ierr); 14500c37af3bSToby Isaac } 14510c37af3bSToby Isaac else { 14520c37af3bSToby Isaac ierr = PetscSectionGetDof(section,a,&aSecDof);CHKERRQ(ierr); 14530c37af3bSToby Isaac ierr = PetscSectionGetOffset(section,a,&aSecOff);CHKERRQ(ierr); 14540c37af3bSToby Isaac } 14550c37af3bSToby Isaac if (!aSecDof) continue; 14560c37af3bSToby Isaac 14570c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 14580c37af3bSToby Isaac PetscInt q = closureP[2*j]; 14590c37af3bSToby Isaac PetscInt oq = closureP[2*j+1]; 14600c37af3bSToby Isaac 14610c37af3bSToby Isaac if (q == a) { 14620c37af3bSToby Isaac PetscInt r, s, t; 14630c37af3bSToby Isaac 14640c37af3bSToby Isaac for (r = childOffsets[i]; r < childOffsets[i+1]; r++) { 14650c37af3bSToby Isaac for (s = parentOffsets[j]; s < parentOffsets[j+1]; s++) { 14660c37af3bSToby Isaac PetscScalar val; 14670c37af3bSToby Isaac PetscInt insertCol, insertRow; 14680c37af3bSToby Isaac 14690c37af3bSToby Isaac ierr = MatGetValue(Xmat,r,s,&val);CHKERRQ(ierr); 14700c37af3bSToby Isaac if (o >= 0) { 14710c37af3bSToby Isaac insertRow = conOff + fComp * (r - childOffsets[i]); 14720c37af3bSToby Isaac } 14730c37af3bSToby Isaac else { 14740c37af3bSToby Isaac insertRow = conOff + fComp * (childOffsets[i + 1] - 1 - r); 14750c37af3bSToby Isaac } 14760c37af3bSToby Isaac if (oq >= 0) { 14770c37af3bSToby Isaac insertCol = aSecOff + fComp * (s - parentOffsets[j]); 14780c37af3bSToby Isaac } 14790c37af3bSToby Isaac else { 14800c37af3bSToby Isaac insertCol = aSecOff + fComp * (parentOffsets[j + 1] - 1 - s); 14810c37af3bSToby Isaac } 14820c37af3bSToby Isaac for (t = 0; t < fComp; t++) { 14830c37af3bSToby Isaac ierr = MatSetValue(cMat,insertRow + t,insertCol + t,val,INSERT_VALUES);CHKERRQ(ierr); 14840c37af3bSToby Isaac } 14850c37af3bSToby Isaac } 14860c37af3bSToby Isaac } 14870c37af3bSToby Isaac } 14880c37af3bSToby Isaac } 14890c37af3bSToby Isaac } 14900c37af3bSToby Isaac } 14910c37af3bSToby Isaac ierr = PetscFree2(childOffsets,parentOffsets);CHKERRQ(ierr); 14920c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 14930c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 14940c37af3bSToby Isaac } 14950c37af3bSToby Isaac ierr = MatDestroy(&Amat);CHKERRQ(ierr); 14960c37af3bSToby Isaac ierr = MatDestroy(&Bmat);CHKERRQ(ierr); 14970c37af3bSToby Isaac ierr = MatDestroy(&Xmat);CHKERRQ(ierr); 14980c37af3bSToby Isaac ierr = PetscFree3(weights,pointsRef,pointsReal);CHKERRQ(ierr); 14990c37af3bSToby Isaac } 15000c37af3bSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 15010c37af3bSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 15020c37af3bSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent);CHKERRQ(ierr); 15030c37af3bSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 15040c37af3bSToby Isaac 15050c37af3bSToby Isaac PetscFunctionReturn(0); 15060c37af3bSToby Isaac } 150795a0b26dSToby Isaac 150895a0b26dSToby Isaac #undef __FUNCT__ 150921968bf8SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildrenMatrices" 151021968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 151195a0b26dSToby Isaac { 1512f7c74593SToby Isaac Mat refCmat; 151321968bf8SToby Isaac PetscDS ds; 151421968bf8SToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 151521968bf8SToby Isaac PetscScalar ***refPointFieldMats; 151621968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 151721968bf8SToby Isaac IS refAnIS; 151821968bf8SToby Isaac const PetscInt *refAnchors; 151995a0b26dSToby Isaac PetscErrorCode ierr; 152095a0b26dSToby Isaac 152195a0b26dSToby Isaac PetscFunctionBegin; 152221968bf8SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 152395a0b26dSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 1524f7c74593SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 1525a17985deSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 152695a0b26dSToby Isaac ierr = ISGetIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 152795a0b26dSToby Isaac ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr); 152895a0b26dSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 152995a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr); 153095a0b26dSToby Isaac ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldN);CHKERRQ(ierr); 153195a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 153295a0b26dSToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 153395a0b26dSToby Isaac ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr); 153495a0b26dSToby Isaac ierr = PetscMalloc1(maxDof*maxAnDof,&cols);CHKERRQ(ierr); 153595a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 153695a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 153795a0b26dSToby Isaac 153895a0b26dSToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 153995a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 154095a0b26dSToby Isaac if (!pDof || parent == p) continue; 154195a0b26dSToby Isaac 154295a0b26dSToby Isaac ierr = PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr); 154395a0b26dSToby Isaac ierr = PetscCalloc1(numFields,&refPointFieldN[p-pRefStart]);CHKERRQ(ierr); 154495a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 154595a0b26dSToby Isaac for (f = 0; f < numFields; f++) { 154695a0b26dSToby Isaac PetscInt cDof, cOff, numCols, r, i, fComp; 15470dd1b1feSToby Isaac PetscObject disc; 15480dd1b1feSToby Isaac PetscClassId id; 15490dd1b1feSToby Isaac PetscFE fe = NULL; 15500dd1b1feSToby Isaac PetscFV fv = NULL; 155195a0b26dSToby Isaac 15520dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 15530dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 15540dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 15550dd1b1feSToby Isaac fe = (PetscFE) disc; 155695a0b26dSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 15570dd1b1feSToby Isaac } 15580dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 15590dd1b1feSToby Isaac fv = (PetscFV) disc; 15600dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 15610dd1b1feSToby Isaac } 15620dd1b1feSToby Isaac else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 156395a0b26dSToby Isaac 156495a0b26dSToby Isaac if (numFields > 1) { 156595a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 156695a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr); 156795a0b26dSToby Isaac } 156895a0b26dSToby Isaac else { 156995a0b26dSToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 157095a0b26dSToby Isaac ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr); 157195a0b26dSToby Isaac } 157295a0b26dSToby Isaac 157395a0b26dSToby Isaac if (!cDof) continue; 157495a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 157595a0b26dSToby Isaac rows[r] = cOff + r; 157695a0b26dSToby Isaac } 157795a0b26dSToby Isaac numCols = 0; 157895a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 157995a0b26dSToby Isaac PetscInt q = closure[2*i]; 158095a0b26dSToby Isaac PetscInt o = closure[2*i+1]; 158195a0b26dSToby Isaac PetscInt aDof, aOff, j; 158295a0b26dSToby Isaac 158395a0b26dSToby Isaac if (numFields > 1) { 158495a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(refSection,q,f,&aDof);CHKERRQ(ierr); 158595a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(refSection,q,f,&aOff);CHKERRQ(ierr); 158695a0b26dSToby Isaac } 158795a0b26dSToby Isaac else { 158895a0b26dSToby Isaac ierr = PetscSectionGetDof(refSection,q,&aDof);CHKERRQ(ierr); 158995a0b26dSToby Isaac ierr = PetscSectionGetOffset(refSection,q,&aOff);CHKERRQ(ierr); 159095a0b26dSToby Isaac } 159195a0b26dSToby Isaac 159295a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 159395a0b26dSToby Isaac PetscInt node = (o >= 0) ? (j / fComp) : ((aDof - 1 - j) / fComp); 159495a0b26dSToby Isaac PetscInt comp = (j % fComp); 159595a0b26dSToby Isaac 159695a0b26dSToby Isaac cols[numCols++] = aOff + node * fComp + comp; 159795a0b26dSToby Isaac } 159895a0b26dSToby Isaac } 159995a0b26dSToby Isaac refPointFieldN[p-pRefStart][f] = numCols; 160095a0b26dSToby Isaac ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 160195a0b26dSToby Isaac ierr = MatGetValues(refCmat,cDof,rows,numCols,cols,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr); 160295a0b26dSToby Isaac } 160395a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 160495a0b26dSToby Isaac } 160521968bf8SToby Isaac *childrenMats = refPointFieldMats; 160621968bf8SToby Isaac *childrenN = refPointFieldN; 160721968bf8SToby Isaac ierr = ISRestoreIndices(refAnIS,&refAnchors);CHKERRQ(ierr); 160821968bf8SToby Isaac ierr = PetscFree(rows);CHKERRQ(ierr); 160921968bf8SToby Isaac ierr = PetscFree(cols);CHKERRQ(ierr); 161021968bf8SToby Isaac PetscFunctionReturn(0); 161121968bf8SToby Isaac } 161221968bf8SToby Isaac 161321968bf8SToby Isaac #undef __FUNCT__ 161421968bf8SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeRestoreChildrenMatrices" 161521968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 161621968bf8SToby Isaac { 161721968bf8SToby Isaac PetscDS ds; 161821968bf8SToby Isaac PetscInt **refPointFieldN; 161921968bf8SToby Isaac PetscScalar ***refPointFieldMats; 162021968bf8SToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 162121968bf8SToby Isaac PetscSection refConSec; 162221968bf8SToby Isaac PetscErrorCode ierr; 162321968bf8SToby Isaac 162421968bf8SToby Isaac PetscFunctionBegin; 162521968bf8SToby Isaac refPointFieldN = *childrenN; 162621968bf8SToby Isaac *childrenN = NULL; 162721968bf8SToby Isaac refPointFieldMats = *childrenMats; 162821968bf8SToby Isaac *childrenMats = NULL; 162921968bf8SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 163021968bf8SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 163121968bf8SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 1632e44e4e7fSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 163321968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 163421968bf8SToby Isaac PetscInt parent, pDof; 163521968bf8SToby Isaac 163621968bf8SToby Isaac ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr); 163721968bf8SToby Isaac ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr); 163821968bf8SToby Isaac if (!pDof || parent == p) continue; 163921968bf8SToby Isaac 164021968bf8SToby Isaac for (f = 0; f < numFields; f++) { 164121968bf8SToby Isaac PetscInt cDof; 164221968bf8SToby Isaac 164321968bf8SToby Isaac if (numFields > 1) { 164421968bf8SToby Isaac ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr); 164521968bf8SToby Isaac } 164621968bf8SToby Isaac else { 164721968bf8SToby Isaac ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr); 164821968bf8SToby Isaac } 164921968bf8SToby Isaac 165021968bf8SToby Isaac if (!cDof) continue; 165121968bf8SToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr); 165221968bf8SToby Isaac } 165321968bf8SToby Isaac ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr); 165421968bf8SToby Isaac ierr = PetscFree(refPointFieldN[p - pRefStart]);CHKERRQ(ierr); 165521968bf8SToby Isaac } 165621968bf8SToby Isaac ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr); 165721968bf8SToby Isaac ierr = PetscFree(refPointFieldN);CHKERRQ(ierr); 165821968bf8SToby Isaac PetscFunctionReturn(0); 165921968bf8SToby Isaac } 166021968bf8SToby Isaac 166121968bf8SToby Isaac #undef __FUNCT__ 166221968bf8SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_FromReference" 166321968bf8SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 166421968bf8SToby Isaac { 166521968bf8SToby Isaac DM refTree; 166621968bf8SToby Isaac PetscDS ds; 166721968bf8SToby Isaac Mat refCmat; 166821968bf8SToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 166921968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 167021968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 167121968bf8SToby Isaac IS refAnIS, anIS; 167221968bf8SToby Isaac const PetscInt *anchors; 167321968bf8SToby Isaac PetscErrorCode ierr; 167421968bf8SToby Isaac 167521968bf8SToby Isaac PetscFunctionBegin; 167621968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 167721968bf8SToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 167821968bf8SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 167921968bf8SToby Isaac ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 168021968bf8SToby Isaac ierr = DMSetDS(refTree,ds);CHKERRQ(ierr); 168121968bf8SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr); 168221968bf8SToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr); 168321968bf8SToby Isaac ierr = DMPlexGetAnchors(dm,&anSec,&anIS);CHKERRQ(ierr); 168421968bf8SToby Isaac ierr = ISGetIndices(anIS,&anchors);CHKERRQ(ierr); 168521968bf8SToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 168621968bf8SToby Isaac ierr = PetscSectionGetChart(conSec,&conStart,&conEnd);CHKERRQ(ierr); 168721968bf8SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr); 168821968bf8SToby Isaac ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr); 168921968bf8SToby Isaac ierr = PetscMalloc1(maxDof*maxDof*maxAnDof,&pointWork);CHKERRQ(ierr); 169021968bf8SToby Isaac 169121968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 169221968bf8SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 169395a0b26dSToby Isaac 169495a0b26dSToby Isaac /* step 2: compute the preorder */ 169595a0b26dSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 169695a0b26dSToby Isaac ierr = PetscMalloc2(pEnd-pStart,&perm,pEnd-pStart,&iperm);CHKERRQ(ierr); 169795a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 169895a0b26dSToby Isaac perm[p - pStart] = p; 169995a0b26dSToby Isaac iperm[p - pStart] = p-pStart; 170095a0b26dSToby Isaac } 170195a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 170295a0b26dSToby Isaac PetscInt point = perm[p]; 170395a0b26dSToby Isaac PetscInt parent; 170495a0b26dSToby Isaac 170595a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 170695a0b26dSToby Isaac if (parent == point) { 170795a0b26dSToby Isaac p++; 170895a0b26dSToby Isaac } 170995a0b26dSToby Isaac else { 171095a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 171195a0b26dSToby Isaac 171295a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 171395a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 171495a0b26dSToby Isaac PetscInt q = closure[2*i]; 171595a0b26dSToby Isaac if (iperm[q-pStart] > iperm[point-pStart]) { 171695a0b26dSToby Isaac /* swap */ 171795a0b26dSToby Isaac perm[p] = q; 171895a0b26dSToby Isaac perm[iperm[q-pStart]] = point; 171995a0b26dSToby Isaac iperm[point-pStart] = iperm[q-pStart]; 172095a0b26dSToby Isaac iperm[q-pStart] = p; 172195a0b26dSToby Isaac break; 172295a0b26dSToby Isaac } 172395a0b26dSToby Isaac } 172495a0b26dSToby Isaac size = closureSize; 172595a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 172695a0b26dSToby Isaac if (i == size) { 172795a0b26dSToby Isaac p++; 172895a0b26dSToby Isaac } 172995a0b26dSToby Isaac } 173095a0b26dSToby Isaac } 173195a0b26dSToby Isaac 173295a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 173395a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 173495a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 173595a0b26dSToby Isaac * values outside of the Mat first. 173695a0b26dSToby Isaac */ 173795a0b26dSToby Isaac { 173895a0b26dSToby Isaac PetscInt nRows, row, nnz; 173995a0b26dSToby Isaac PetscBool done; 174095a0b26dSToby Isaac const PetscInt *ia, *ja; 174195a0b26dSToby Isaac PetscScalar *vals; 174295a0b26dSToby Isaac 174395a0b26dSToby Isaac ierr = MatGetRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 174495a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not get RowIJ of constraint matrix"); 174595a0b26dSToby Isaac nnz = ia[nRows]; 174695a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 174795a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 174895a0b26dSToby Isaac ierr = PetscMalloc1(nnz,&vals);CHKERRQ(ierr); 174995a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 175095a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 175195a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 175295a0b26dSToby Isaac 175395a0b26dSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,&childid);CHKERRQ(ierr); 175495a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 175595a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&pointDof);CHKERRQ(ierr); 175695a0b26dSToby Isaac if (!pointDof) continue; 175795a0b26dSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 175895a0b26dSToby Isaac for (f = 0; f < numFields; f++) { 175995a0b26dSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, fComp, matOffset, offset; 176095a0b26dSToby Isaac PetscScalar *pointMat; 17610dd1b1feSToby Isaac PetscObject disc; 17620dd1b1feSToby Isaac PetscClassId id; 17630dd1b1feSToby Isaac PetscFE fe = NULL; 17640dd1b1feSToby Isaac PetscFV fv = NULL; 176595a0b26dSToby Isaac 17660dd1b1feSToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 17670dd1b1feSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 17680dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 17690dd1b1feSToby Isaac fe = (PetscFE) disc; 177095a0b26dSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 17710dd1b1feSToby Isaac } 17720dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 17730dd1b1feSToby Isaac fv = (PetscFV) disc; 17740dd1b1feSToby Isaac ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr); 17750dd1b1feSToby Isaac } 177695a0b26dSToby Isaac 177795a0b26dSToby Isaac if (numFields > 1) { 177895a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,point,f,&cDof);CHKERRQ(ierr); 177995a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,point,f,&cOff);CHKERRQ(ierr); 178095a0b26dSToby Isaac } 178195a0b26dSToby Isaac else { 178295a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,point,&cDof);CHKERRQ(ierr); 178395a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,point,&cOff);CHKERRQ(ierr); 178495a0b26dSToby Isaac } 178595a0b26dSToby Isaac if (!cDof) continue; 178695a0b26dSToby Isaac 178795a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 178895a0b26dSToby Isaac #if defined(PETSC_USE_DEBUG) 178995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 179095a0b26dSToby Isaac if (cDof > 1 && r) { 179121968bf8SToby 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])); 179295a0b26dSToby Isaac } 179395a0b26dSToby Isaac } 179495a0b26dSToby Isaac #endif 179595a0b26dSToby Isaac /* zero rows */ 179695a0b26dSToby Isaac for (i = ia[cOff] ; i< ia[cOff+cDof];i++) { 179795a0b26dSToby Isaac vals[i] = 0.; 179895a0b26dSToby Isaac } 179995a0b26dSToby Isaac matOffset = ia[cOff]; 180095a0b26dSToby Isaac numFillCols = ia[cOff+1] - matOffset; 180195a0b26dSToby Isaac pointMat = refPointFieldMats[childid-pRefStart][f]; 180295a0b26dSToby Isaac numCols = refPointFieldN[childid-pRefStart][f]; 180395a0b26dSToby Isaac offset = 0; 180495a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 180595a0b26dSToby Isaac PetscInt q = closure[2*i]; 180695a0b26dSToby Isaac PetscInt o = closure[2*i+1]; 180795a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 180895a0b26dSToby Isaac 180995a0b26dSToby Isaac qConDof = qConOff = 0; 181095a0b26dSToby Isaac if (numFields > 1) { 181195a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(section,q,f,&aDof);CHKERRQ(ierr); 181295a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(section,q,f,&aOff);CHKERRQ(ierr); 181395a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 181495a0b26dSToby Isaac ierr = PetscSectionGetFieldDof(conSec,q,f,&qConDof);CHKERRQ(ierr); 181595a0b26dSToby Isaac ierr = PetscSectionGetFieldOffset(conSec,q,f,&qConOff);CHKERRQ(ierr); 181695a0b26dSToby Isaac } 181795a0b26dSToby Isaac } 181895a0b26dSToby Isaac else { 181995a0b26dSToby Isaac ierr = PetscSectionGetDof(section,q,&aDof);CHKERRQ(ierr); 182095a0b26dSToby Isaac ierr = PetscSectionGetOffset(section,q,&aOff);CHKERRQ(ierr); 182195a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 182295a0b26dSToby Isaac ierr = PetscSectionGetDof(conSec,q,&qConDof);CHKERRQ(ierr); 182395a0b26dSToby Isaac ierr = PetscSectionGetOffset(conSec,q,&qConOff);CHKERRQ(ierr); 182495a0b26dSToby Isaac } 182595a0b26dSToby Isaac } 182695a0b26dSToby Isaac if (!aDof) continue; 182795a0b26dSToby Isaac if (qConDof) { 182895a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 182995a0b26dSToby Isaac * be filled, thanks to preordering */ 183095a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 183195a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 183295a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 183395a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 183495a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 183595a0b26dSToby Isaac PetscScalar inVal = 0; 183695a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 183795a0b26dSToby Isaac PetscInt node = (o >= 0) ? (k / fComp) : ((aDof - 1 - k) / fComp); 183895a0b26dSToby Isaac PetscInt comp = (k % fComp); 183995a0b26dSToby Isaac PetscInt col = node * fComp + comp; 184095a0b26dSToby Isaac 184195a0b26dSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j]; 184295a0b26dSToby Isaac } 184395a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 184495a0b26dSToby Isaac } 184595a0b26dSToby Isaac } 184695a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 184795a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 184895a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 184995a0b26dSToby Isaac for (;k < numFillCols; k++) { 185095a0b26dSToby Isaac if (ja[matOffset + k] == col) { 185195a0b26dSToby Isaac break; 185295a0b26dSToby Isaac } 185395a0b26dSToby Isaac } 185495a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, col); 185595a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 185695a0b26dSToby Isaac vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 185795a0b26dSToby Isaac } 185895a0b26dSToby Isaac } 185995a0b26dSToby Isaac } 186095a0b26dSToby Isaac else { 186195a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 186295a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 186395a0b26dSToby Isaac if (ja[matOffset + k] == aOff) { 186495a0b26dSToby Isaac break; 186595a0b26dSToby Isaac } 186695a0b26dSToby Isaac } 186795a0b26dSToby Isaac if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, aOff); 186895a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 186995a0b26dSToby Isaac PetscInt node = (o >= 0) ? (j / fComp) : ((aDof - 1 - j) / fComp); 187095a0b26dSToby Isaac PetscInt comp = (j % fComp); 187195a0b26dSToby Isaac PetscInt col = node * fComp + comp; 187295a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 187395a0b26dSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + col]; 187495a0b26dSToby Isaac } 187595a0b26dSToby Isaac } 187695a0b26dSToby Isaac } 187795a0b26dSToby Isaac offset += aDof; 187895a0b26dSToby Isaac } 187995a0b26dSToby Isaac } 188095a0b26dSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 188195a0b26dSToby Isaac } 188295a0b26dSToby Isaac for (row = 0; row < nRows; row++) { 188395a0b26dSToby Isaac ierr = MatSetValues(cMat,1,&row,ia[row+1]-ia[row],&ja[ia[row]],&vals[ia[row]],INSERT_VALUES);CHKERRQ(ierr); 188495a0b26dSToby Isaac } 188595a0b26dSToby Isaac ierr = MatRestoreRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr); 188695a0b26dSToby Isaac if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not restore RowIJ of constraint matrix"); 188795a0b26dSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 188895a0b26dSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 188995a0b26dSToby Isaac ierr = PetscFree(vals);CHKERRQ(ierr); 189095a0b26dSToby Isaac } 189195a0b26dSToby Isaac 189295a0b26dSToby Isaac /* clean up */ 189395a0b26dSToby Isaac ierr = ISRestoreIndices(anIS,&anchors);CHKERRQ(ierr); 189495a0b26dSToby Isaac ierr = PetscFree2(perm,iperm);CHKERRQ(ierr); 189595a0b26dSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 189621968bf8SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 189795a0b26dSToby Isaac PetscFunctionReturn(0); 189895a0b26dSToby Isaac } 189995a0b26dSToby Isaac 19006f5f1567SToby Isaac #undef __FUNCT__ 19016f5f1567SToby Isaac #define __FUNCT__ "DMPlexTreeRefineCell" 19026f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 19036f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 19046f5f1567SToby Isaac PetscErrorCode DMPlexTreeRefineCell (DM dm, PetscInt cell, DM *ncdm) 19056f5f1567SToby Isaac { 19066f5f1567SToby Isaac DM K; 1907420f55faSMatthew G. Knepley PetscMPIInt rank; 19086f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 19096f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 19106f5f1567SToby Isaac PetscInt *Kembedding; 19116f5f1567SToby Isaac PetscInt *cellClosure=NULL, nc; 19126f5f1567SToby Isaac PetscScalar *newVertexCoords; 19136f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 19146f5f1567SToby Isaac PetscSection parentSection; 19156f5f1567SToby Isaac PetscErrorCode ierr; 19166f5f1567SToby Isaac 19176f5f1567SToby Isaac PetscFunctionBegin; 19186f5f1567SToby Isaac ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr); 191928f4b327SMatthew G. Knepley ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 19206f5f1567SToby Isaac ierr = DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm);CHKERRQ(ierr); 192128f4b327SMatthew G. Knepley ierr = DMSetDimension(*ncdm,dim);CHKERRQ(ierr); 19226f5f1567SToby Isaac 19236f5f1567SToby Isaac ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 19246f5f1567SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&parentSection);CHKERRQ(ierr); 19256f5f1567SToby Isaac ierr = DMPlexGetReferenceTree(dm,&K);CHKERRQ(ierr); 19266f5f1567SToby Isaac if (!rank) { 19276f5f1567SToby Isaac /* compute the new charts */ 19286f5f1567SToby Isaac ierr = PetscMalloc5(dim+1,&pNewCount,dim+1,&pNewStart,dim+1,&pNewEnd,dim+1,&pOldStart,dim+1,&pOldEnd);CHKERRQ(ierr); 19296f5f1567SToby Isaac offset = 0; 19306f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19316f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 19326f5f1567SToby Isaac 19336f5f1567SToby Isaac pNewStart[d] = offset; 19346f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(dm,d,&pOldStart[d],&pOldEnd[d]);CHKERRQ(ierr); 19356f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 19366f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 19376f5f1567SToby Isaac /* adding the new points */ 19386f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 19396f5f1567SToby Isaac if (!d) { 19406f5f1567SToby Isaac /* removing the cell */ 19416f5f1567SToby Isaac pNewCount[d]--; 19426f5f1567SToby Isaac } 19436f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19446f5f1567SToby Isaac PetscInt parent; 19456f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&parent,NULL);CHKERRQ(ierr); 19466f5f1567SToby Isaac if (parent == k) { 19476f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 19486f5f1567SToby Isaac pNewCount[d]--; 19496f5f1567SToby Isaac } 19506f5f1567SToby Isaac } 19516f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 19526f5f1567SToby Isaac offset = pNewEnd[d]; 19536f5f1567SToby Isaac 19546f5f1567SToby Isaac } 19556f5f1567SToby 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]); 19566f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 19576f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 19586f5f1567SToby Isaac 19596f5f1567SToby Isaac ierr = PetscMalloc1(pNewEnd[dim],&newConeSizes);CHKERRQ(ierr); 19606f5f1567SToby Isaac { 19616f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 19626f5f1567SToby Isaac 19636f5f1567SToby Isaac ierr = DMPlexGetChart(K,&kStart,&kEnd);CHKERRQ(ierr); 19646f5f1567SToby Isaac ierr = PetscMalloc4(kEnd-kStart,&Kembedding,kEnd-kStart,&perm,kEnd-kStart,&iperm,kEnd-kStart,&preOrient);CHKERRQ(ierr); 19656f5f1567SToby Isaac 19666f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19676f5f1567SToby Isaac perm[k - kStart] = k; 19686f5f1567SToby Isaac iperm [k - kStart] = k - kStart; 19696f5f1567SToby Isaac preOrient[k - kStart] = 0; 19706f5f1567SToby Isaac } 19716f5f1567SToby Isaac 19726f5f1567SToby Isaac ierr = DMPlexGetTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 19736f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 19746f5f1567SToby Isaac PetscInt parentOrientA = closureK[2*j+1]; 19756f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2*j+1]; 19766f5f1567SToby Isaac PetscInt p, q; 19776f5f1567SToby Isaac 19786f5f1567SToby Isaac p = closureK[2*j]; 19796f5f1567SToby Isaac q = cellClosure[2*j]; 19806f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19816f5f1567SToby Isaac if (q >= pOldStart[d] && q < pOldEnd[d]) { 19826f5f1567SToby Isaac Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 19836f5f1567SToby Isaac } 19846f5f1567SToby Isaac } 19856f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 19866f5f1567SToby Isaac PetscInt numChildren, i; 19876f5f1567SToby Isaac const PetscInt *children; 19886f5f1567SToby Isaac 19896f5f1567SToby Isaac ierr = DMPlexGetTreeChildren(K,p,&numChildren,&children);CHKERRQ(ierr); 19906f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 19916f5f1567SToby Isaac PetscInt kPerm, oPerm; 19926f5f1567SToby Isaac 19936f5f1567SToby Isaac k = children[i]; 19946f5f1567SToby Isaac ierr = DMPlexReferenceTreeGetChildSymmetry(K,p,parentOrientA,0,k,parentOrientB,&oPerm,&kPerm);CHKERRQ(ierr); 19956f5f1567SToby Isaac /* perm = what refTree position I'm in */ 19966f5f1567SToby Isaac perm[kPerm-kStart] = k; 19976f5f1567SToby Isaac /* iperm = who is at this position */ 19986f5f1567SToby Isaac iperm[k-kStart] = kPerm-kStart; 19996f5f1567SToby Isaac preOrient[kPerm-kStart] = oPerm; 20006f5f1567SToby Isaac } 20016f5f1567SToby Isaac } 20026f5f1567SToby Isaac } 20036f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr); 20046f5f1567SToby Isaac } 20056f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,0,pNewEnd[dim]);CHKERRQ(ierr); 20066f5f1567SToby Isaac offset = 0; 20076f5f1567SToby Isaac numNewCones = 0; 20086f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20096f5f1567SToby Isaac PetscInt kStart, kEnd, k; 20106f5f1567SToby Isaac PetscInt p; 20116f5f1567SToby Isaac PetscInt size; 20126f5f1567SToby Isaac 20136f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 20146f5f1567SToby Isaac /* skip cell 0 */ 20156f5f1567SToby Isaac if (p == cell) continue; 20166f5f1567SToby Isaac /* old cones to new cones */ 20176f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 20186f5f1567SToby Isaac newConeSizes[offset++] = size; 20196f5f1567SToby Isaac numNewCones += size; 20206f5f1567SToby Isaac } 20216f5f1567SToby Isaac 20226f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 20236f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20246f5f1567SToby Isaac PetscInt kParent; 20256f5f1567SToby Isaac 20266f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 20276f5f1567SToby Isaac if (kParent != k) { 20286f5f1567SToby Isaac Kembedding[k] = offset; 20296f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 20306f5f1567SToby Isaac newConeSizes[offset++] = size; 20316f5f1567SToby Isaac numNewCones += size; 20326f5f1567SToby Isaac if (kParent != 0) { 20336f5f1567SToby Isaac ierr = PetscSectionSetDof(parentSection,Kembedding[k],1);CHKERRQ(ierr); 20346f5f1567SToby Isaac } 20356f5f1567SToby Isaac } 20366f5f1567SToby Isaac } 20376f5f1567SToby Isaac } 20386f5f1567SToby Isaac 20396f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 20406f5f1567SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&numPointsWithParents);CHKERRQ(ierr); 20416f5f1567SToby Isaac ierr = PetscMalloc2(numNewCones,&newCones,numNewCones,&newOrientations);CHKERRQ(ierr); 20426f5f1567SToby Isaac ierr = PetscMalloc2(numPointsWithParents,&parents,numPointsWithParents,&childIDs);CHKERRQ(ierr); 20436f5f1567SToby Isaac 20446f5f1567SToby Isaac /* fill new cones */ 20456f5f1567SToby Isaac offset = 0; 20466f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20476f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 20486f5f1567SToby Isaac PetscInt p; 20496f5f1567SToby Isaac PetscInt size; 20506f5f1567SToby Isaac const PetscInt *cone, *orientation; 20516f5f1567SToby Isaac 20526f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 20536f5f1567SToby Isaac /* skip cell 0 */ 20546f5f1567SToby Isaac if (p == cell) continue; 20556f5f1567SToby Isaac /* old cones to new cones */ 20566f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr); 20576f5f1567SToby Isaac ierr = DMPlexGetCone(dm,p,&cone);CHKERRQ(ierr); 20586f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(dm,p,&orientation);CHKERRQ(ierr); 20596f5f1567SToby Isaac for (l = 0; l < size; l++) { 20606f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 20616f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 20626f5f1567SToby Isaac } 20636f5f1567SToby Isaac } 20646f5f1567SToby Isaac 20656f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr); 20666f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20676f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 20686f5f1567SToby Isaac PetscInt preO = preOrient[k]; 20696f5f1567SToby Isaac 20706f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr); 20716f5f1567SToby Isaac if (kParent != k) { 20726f5f1567SToby Isaac /* embed new cones */ 20736f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr); 20746f5f1567SToby Isaac ierr = DMPlexGetCone(K,kPerm,&cone);CHKERRQ(ierr); 20756f5f1567SToby Isaac ierr = DMPlexGetConeOrientation(K,kPerm,&orientation);CHKERRQ(ierr); 20766f5f1567SToby Isaac for (l = 0; l < size; l++) { 20776f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size -(preO + 1) - l) % size); 20786f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 20796f5f1567SToby Isaac 20806f5f1567SToby Isaac q = iperm[cone[m]]; 20816f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 20826f5f1567SToby Isaac ierr = DMPlexGetConeSize(K,q,&lSize);CHKERRQ(ierr); 20836f5f1567SToby Isaac oTrue = orientation[m]; 20846f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 20856f5f1567SToby Isaac newO = DihedralCompose(lSize,oTrue,preOrient[q]); 20866f5f1567SToby Isaac newOrientations[offset++] = newO; 20876f5f1567SToby Isaac } 20886f5f1567SToby Isaac if (kParent != 0) { 20896f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 20906f5f1567SToby Isaac ierr = PetscSectionGetOffset(parentSection,Kembedding[k],&pOffset);CHKERRQ(ierr); 20916f5f1567SToby Isaac parents[pOffset] = newPoint; 20926f5f1567SToby Isaac childIDs[pOffset] = k; 20936f5f1567SToby Isaac } 20946f5f1567SToby Isaac } 20956f5f1567SToby Isaac } 20966f5f1567SToby Isaac } 20976f5f1567SToby Isaac 20986f5f1567SToby Isaac ierr = PetscMalloc1(dim*(pNewEnd[dim]-pNewStart[dim]),&newVertexCoords);CHKERRQ(ierr); 20996f5f1567SToby Isaac 21006f5f1567SToby Isaac /* fill coordinates */ 21016f5f1567SToby Isaac offset = 0; 21026f5f1567SToby Isaac { 2103d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 21046f5f1567SToby Isaac PetscSection vSection; 21056f5f1567SToby Isaac PetscInt v; 21066f5f1567SToby Isaac Vec coords; 21076f5f1567SToby Isaac PetscScalar *coordvals; 21086f5f1567SToby Isaac PetscInt dof, off; 2109c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 21106f5f1567SToby Isaac 21116f5f1567SToby Isaac #if defined(PETSC_USE_DEBUG) 2112d90620a3SMatthew G. Knepley { 2113d90620a3SMatthew G. Knepley PetscInt k; 21146f5f1567SToby Isaac ierr = DMPlexGetHeightStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 21156f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 211673a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 21176f5f1567SToby Isaac if (detJ <= 0.) SETERRQ1 (PETSC_COMM_SELF,PETSC_ERR_PLIB,"reference tree cell %d has bad determinant",k); 21186f5f1567SToby Isaac } 2119d90620a3SMatthew G. Knepley } 21206f5f1567SToby Isaac #endif 212173a7f2aaSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 21226f5f1567SToby Isaac ierr = DMGetCoordinateSection(dm,&vSection);CHKERRQ(ierr); 21236f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coords);CHKERRQ(ierr); 21246f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 21256f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 21266f5f1567SToby Isaac 21276f5f1567SToby Isaac ierr = PetscSectionGetDof(vSection,v,&dof);CHKERRQ(ierr); 21286f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,v,&off);CHKERRQ(ierr); 21296f5f1567SToby Isaac for (l = 0; l < dof; l++) { 21306f5f1567SToby Isaac newVertexCoords[offset++] = coordvals[off + l]; 21316f5f1567SToby Isaac } 21326f5f1567SToby Isaac } 21336f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 21346f5f1567SToby Isaac 21356f5f1567SToby Isaac ierr = DMGetCoordinateSection(K,&vSection);CHKERRQ(ierr); 21366f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(K,&coords);CHKERRQ(ierr); 21376f5f1567SToby Isaac ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr); 21386f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr); 21396f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 21409bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 21416f5f1567SToby Isaac PetscInt vPerm = perm[v]; 21426f5f1567SToby Isaac PetscInt kParent; 21436f5f1567SToby Isaac 21446f5f1567SToby Isaac ierr = DMPlexGetTreeParent(K,v,&kParent,NULL);CHKERRQ(ierr); 21456f5f1567SToby Isaac if (kParent != v) { 21466f5f1567SToby Isaac /* this is a new vertex */ 21476f5f1567SToby Isaac ierr = PetscSectionGetOffset(vSection,vPerm,&off);CHKERRQ(ierr); 21489bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off+l]); 21499bc368c7SMatthew G. Knepley CoordinatesRefToReal(dim, dim, v0, J, coord, newCoord);CHKERRQ(ierr); 21509bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset+l] = newCoord[l]; 21516f5f1567SToby Isaac offset += dim; 21526f5f1567SToby Isaac } 21536f5f1567SToby Isaac } 21546f5f1567SToby Isaac ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr); 21556f5f1567SToby Isaac } 21566f5f1567SToby Isaac 21576f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 21586f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 21596f5f1567SToby Isaac PetscInt tmp; 21606f5f1567SToby Isaac 21616f5f1567SToby Isaac tmp = pNewCount[d]; 21626f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 21636f5f1567SToby Isaac pNewCount[dim - d] = tmp; 21646f5f1567SToby Isaac } 21656f5f1567SToby Isaac 21666f5f1567SToby Isaac ierr = DMPlexCreateFromDAG(*ncdm,dim,pNewCount,newConeSizes,newCones,newOrientations,newVertexCoords);CHKERRQ(ierr); 21676f5f1567SToby Isaac ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr); 21686f5f1567SToby Isaac ierr = DMPlexSetTree(*ncdm,parentSection,parents,childIDs);CHKERRQ(ierr); 21696f5f1567SToby Isaac 21706f5f1567SToby Isaac /* clean up */ 21716f5f1567SToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr); 21726f5f1567SToby Isaac ierr = PetscFree5(pNewCount,pNewStart,pNewEnd,pOldStart,pOldEnd);CHKERRQ(ierr); 21736f5f1567SToby Isaac ierr = PetscFree(newConeSizes);CHKERRQ(ierr); 21746f5f1567SToby Isaac ierr = PetscFree2(newCones,newOrientations);CHKERRQ(ierr); 21756f5f1567SToby Isaac ierr = PetscFree(newVertexCoords);CHKERRQ(ierr); 21766f5f1567SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 21776f5f1567SToby Isaac ierr = PetscFree4(Kembedding,perm,iperm,preOrient);CHKERRQ(ierr); 21786f5f1567SToby Isaac } 21796f5f1567SToby Isaac else { 21806f5f1567SToby Isaac PetscInt p, counts[4]; 21816f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 21826f5f1567SToby Isaac Vec coordVec; 21836f5f1567SToby Isaac PetscScalar *coords; 21846f5f1567SToby Isaac 21856f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 21866f5f1567SToby Isaac PetscInt dStart, dEnd; 21876f5f1567SToby Isaac 21886f5f1567SToby Isaac ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr); 21896f5f1567SToby Isaac counts[d] = dEnd - dStart; 21906f5f1567SToby Isaac } 21916f5f1567SToby Isaac ierr = PetscMalloc1(pEnd-pStart,&coneSizes);CHKERRQ(ierr); 21926f5f1567SToby Isaac for (p = pStart; p < pEnd; p++) { 21936f5f1567SToby Isaac ierr = DMPlexGetConeSize(dm,p,&coneSizes[p-pStart]);CHKERRQ(ierr); 21946f5f1567SToby Isaac } 21956f5f1567SToby Isaac ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 21966f5f1567SToby Isaac ierr = DMPlexGetConeOrientations(dm, &orientations);CHKERRQ(ierr); 21976f5f1567SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coordVec);CHKERRQ(ierr); 21986f5f1567SToby Isaac ierr = VecGetArray(coordVec,&coords);CHKERRQ(ierr); 21996f5f1567SToby Isaac 22006f5f1567SToby Isaac ierr = PetscSectionSetChart(parentSection,pStart,pEnd);CHKERRQ(ierr); 22016f5f1567SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 22026f5f1567SToby Isaac ierr = DMPlexCreateFromDAG(*ncdm,dim,counts,coneSizes,cones,orientations,NULL);CHKERRQ(ierr); 22036f5f1567SToby Isaac ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr); 22046f5f1567SToby Isaac ierr = DMPlexSetTree(*ncdm,parentSection,NULL,NULL);CHKERRQ(ierr); 22056f5f1567SToby Isaac ierr = VecRestoreArray(coordVec,&coords);CHKERRQ(ierr); 22066f5f1567SToby Isaac } 22076f5f1567SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 22086f5f1567SToby Isaac 22096f5f1567SToby Isaac PetscFunctionReturn(0); 22106f5f1567SToby Isaac } 22116ecaa68aSToby Isaac 22126ecaa68aSToby Isaac PETSC_EXTERN PetscErrorCode indicesPointFields_private(PetscSection,PetscInt,PetscInt,PetscInt[],PetscBool,PetscInt,PetscInt[]); 22136ecaa68aSToby Isaac PETSC_EXTERN PetscErrorCode indicesPoint_private(PetscSection,PetscInt,PetscInt,PetscInt *,PetscBool,PetscInt,PetscInt[]); 221421968bf8SToby Isaac 22156ecaa68aSToby Isaac #undef __FUNCT__ 22166ecaa68aSToby Isaac #define __FUNCT__ "DMPlexComputeInterpolatorTree" 22176ecaa68aSToby Isaac PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 22186ecaa68aSToby Isaac { 22196ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 22206ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 22216ecaa68aSToby Isaac PetscSection localCoarse, localFine; 22226ecaa68aSToby Isaac PetscSection aSec, cSec; 22236ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 222446bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 222546bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 222646bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 22276ecaa68aSToby Isaac IS aIS; 22286ecaa68aSToby Isaac const PetscInt *anchors; 22296ecaa68aSToby Isaac Mat cMat; 22306ecaa68aSToby Isaac PetscInt numFields; 22316ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 22326ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 22331c58ffc4SToby Isaac PetscInt *maxChildIds; 2234e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 22356ecaa68aSToby Isaac PetscErrorCode ierr; 22366ecaa68aSToby Isaac 22376ecaa68aSToby Isaac PetscFunctionBegin; 22386ecaa68aSToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 22396ecaa68aSToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 22406ecaa68aSToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 22416ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 22426ecaa68aSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 22436ecaa68aSToby Isaac 22446ecaa68aSToby Isaac for (p = pStartF, numPointsWithDofs = 0; p < pEndF; p++) { 22456ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 22466ecaa68aSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 22476ecaa68aSToby Isaac if ((dof - cdof) > 0) { 22486ecaa68aSToby Isaac numPointsWithDofs++; 22496ecaa68aSToby Isaac } 22506ecaa68aSToby Isaac } 22516ecaa68aSToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 22526ecaa68aSToby Isaac for (p = pStartF, offset = 0; p < pEndF; p++) { 22536ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 22546ecaa68aSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 22556ecaa68aSToby Isaac if ((dof - cdof) > 0) { 22566ecaa68aSToby Isaac pointsWithDofs[offset++] = p - pStartF; 22576ecaa68aSToby Isaac } 22586ecaa68aSToby Isaac } 22596ecaa68aSToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 22606ecaa68aSToby Isaac } 22616ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 22626ecaa68aSToby Isaac ierr = PetscMalloc1(pEndC-pStartC,&maxChildIds);CHKERRQ(ierr); 22636ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 2264*8d2f55e7SToby Isaac maxChildIds[p - pStartC] = -2; 22656ecaa68aSToby Isaac } 22666ecaa68aSToby Isaac ierr = PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 22676ecaa68aSToby Isaac ierr = PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 226846bdb399SToby Isaac 22696ecaa68aSToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 22706ecaa68aSToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 227146bdb399SToby Isaac 22726ecaa68aSToby Isaac ierr = DMPlexGetAnchors(coarse,&aSec,&aIS);CHKERRQ(ierr); 22736ecaa68aSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 22746ecaa68aSToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 227546bdb399SToby Isaac 22766ecaa68aSToby Isaac ierr = DMGetDefaultConstraints(coarse,&cSec,&cMat);CHKERRQ(ierr); 22776ecaa68aSToby Isaac ierr = PetscSectionGetChart(cSec,&cStart,&cEnd);CHKERRQ(ierr); 227846bdb399SToby Isaac 227946bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 22806ecaa68aSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec);CHKERRQ(ierr); 22816ecaa68aSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootMatricesSec);CHKERRQ(ierr); 22826ecaa68aSToby Isaac ierr = PetscSectionSetChart(rootIndicesSec,pStartC,pEndC);CHKERRQ(ierr); 22836ecaa68aSToby Isaac ierr = PetscSectionSetChart(rootMatricesSec,pStartC,pEndC);CHKERRQ(ierr); 22846ecaa68aSToby Isaac ierr = PetscSectionGetNumFields(globalCoarse,&numFields);CHKERRQ(ierr); 228521968bf8SToby Isaac { 2286267d4f3fSToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 2287e44e4e7fSToby Isaac ierr = PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO);CHKERRQ(ierr); 228821968bf8SToby Isaac } 228946bdb399SToby Isaac 229046bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 2291*8d2f55e7SToby Isaac PetscInt dof, matSize = 0; 22926ecaa68aSToby Isaac PetscInt aDof = 0; 22936ecaa68aSToby Isaac PetscInt cDof = 0; 22946ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22956ecaa68aSToby Isaac PetscInt numRowIndices = 0; 22966ecaa68aSToby Isaac PetscInt numColIndices = 0; 22976ecaa68aSToby Isaac 22986ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 22991cfc5b76SToby Isaac if (dof < 0) { 23001cfc5b76SToby Isaac dof = -(dof + 1); 23011cfc5b76SToby Isaac } 23026ecaa68aSToby Isaac if (p >= aStart && p < aEnd) { 23036ecaa68aSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 23046ecaa68aSToby Isaac } 23056ecaa68aSToby Isaac if (p >= cStart && p < cEnd) { 23066ecaa68aSToby Isaac ierr = PetscSectionGetDof(cSec,p,&cDof);CHKERRQ(ierr); 23076ecaa68aSToby Isaac } 230821968bf8SToby Isaac offsets[0] = 0; 230921968bf8SToby Isaac newOffsets[0] = 0; 23106ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 23116ecaa68aSToby Isaac PetscInt *closure = NULL, closureSize, cl, f; 23126ecaa68aSToby Isaac 23136ecaa68aSToby Isaac ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 231446bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 23156ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 23166ecaa68aSToby Isaac 23176ecaa68aSToby Isaac ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr); 23186ecaa68aSToby Isaac numRowIndices += clDof; 23196ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23206ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&clDof);CHKERRQ(ierr); 23216ecaa68aSToby Isaac offsets[f + 1] += clDof; 23226ecaa68aSToby Isaac } 23236ecaa68aSToby Isaac } 23246ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23256ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 23266ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 23276ecaa68aSToby Isaac } 232846bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 23296ecaa68aSToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,NULL,NULL,&numColIndices,NULL,NULL,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 23306ecaa68aSToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 23316ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 23326ecaa68aSToby Isaac numColIndices = numRowIndices; 23336ecaa68aSToby Isaac matSize = 0; 23346ecaa68aSToby Isaac } 233546bdb399SToby Isaac else if (numFields) { /* we send one submat for each field: sum their sizes */ 23366ecaa68aSToby Isaac matSize = 0; 23376ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23386ecaa68aSToby Isaac PetscInt numRow, numCol; 23396ecaa68aSToby Isaac 23406ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 23416ecaa68aSToby Isaac numCol = newOffsets[f + 1] - newOffsets[f + 1]; 23426ecaa68aSToby Isaac matSize += numRow * numCol; 23436ecaa68aSToby Isaac } 23446ecaa68aSToby Isaac } 23456ecaa68aSToby Isaac else { 23466ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 23476ecaa68aSToby Isaac } 23486ecaa68aSToby Isaac } 2349*8d2f55e7SToby Isaac else if (maxChildId == -1) { 2350*8d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 23516ecaa68aSToby Isaac PetscInt aOff, a, f; 23526ecaa68aSToby Isaac 23536ecaa68aSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 23546ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23556ecaa68aSToby Isaac PetscInt fDof; 23566ecaa68aSToby Isaac 23576ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 235821968bf8SToby Isaac offsets[f+1] = fDof; 23596ecaa68aSToby Isaac } 23606ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23616ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 23626ecaa68aSToby Isaac 23636ecaa68aSToby Isaac ierr = PetscSectionGetDof(localCoarse,anchor,&aLocalDof);CHKERRQ(ierr); 23646ecaa68aSToby Isaac numColIndices += aLocalDof; 23656ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23666ecaa68aSToby Isaac PetscInt fDof; 23676ecaa68aSToby Isaac 23686ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 236921968bf8SToby Isaac newOffsets[f+1] += fDof; 23706ecaa68aSToby Isaac } 23716ecaa68aSToby Isaac } 23726ecaa68aSToby Isaac if (numFields) { 23736ecaa68aSToby Isaac matSize = 0; 23746ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 237521968bf8SToby Isaac matSize += offsets[f+1] * newOffsets[f+1]; 23766ecaa68aSToby Isaac } 23776ecaa68aSToby Isaac } 23786ecaa68aSToby Isaac else { 23796ecaa68aSToby Isaac matSize = numColIndices * dof; 23806ecaa68aSToby Isaac } 23816ecaa68aSToby Isaac } 23826ecaa68aSToby Isaac else { /* no children, and no constraints on dofs: just get the global indices */ 23836ecaa68aSToby Isaac numColIndices = dof; 23846ecaa68aSToby Isaac matSize = 0; 23856ecaa68aSToby Isaac } 2386*8d2f55e7SToby Isaac } 238746bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 23886ecaa68aSToby Isaac ierr = PetscSectionSetDof(rootIndicesSec,p,numColIndices ? numColIndices+2*numFields : 0);CHKERRQ(ierr); 23896ecaa68aSToby Isaac ierr = PetscSectionSetDof(rootMatricesSec,p,matSize);CHKERRQ(ierr); 23906ecaa68aSToby Isaac } 23916ecaa68aSToby Isaac ierr = PetscSectionSetUp(rootIndicesSec);CHKERRQ(ierr); 23926ecaa68aSToby Isaac ierr = PetscSectionSetUp(rootMatricesSec);CHKERRQ(ierr); 23936ecaa68aSToby Isaac { 23946ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 23956ecaa68aSToby Isaac 23966ecaa68aSToby Isaac ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr); 23976ecaa68aSToby Isaac ierr = PetscSectionGetStorageSize(rootMatricesSec,&numRootMatrices);CHKERRQ(ierr); 23986ecaa68aSToby Isaac ierr = PetscMalloc2(numRootIndices,&rootIndices,numRootMatrices,&rootMatrices);CHKERRQ(ierr); 23996ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 24006ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 24016ecaa68aSToby Isaac PetscInt pIndOff, pMatOff; 24026ecaa68aSToby Isaac PetscInt *pInd; 24036ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 24046ecaa68aSToby Isaac PetscScalar *pMat = NULL; 24056ecaa68aSToby Isaac 24066ecaa68aSToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,p,&numColIndices);CHKERRQ(ierr); 24076ecaa68aSToby Isaac if (!numColIndices) { 24086ecaa68aSToby Isaac continue; 24096ecaa68aSToby Isaac } 241021968bf8SToby Isaac offsets[0] = 0; 241121968bf8SToby Isaac newOffsets[0] = 0; 241221968bf8SToby Isaac offsetsCopy[0] = 0; 241321968bf8SToby Isaac newOffsetsCopy[0] = 0; 24146ecaa68aSToby Isaac numColIndices -= 2 * numFields; 24156ecaa68aSToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,p,&pIndOff);CHKERRQ(ierr); 24166ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 24176ecaa68aSToby Isaac ierr = PetscSectionGetDof(rootMatricesSec,p,&matSize);CHKERRQ(ierr); 24186ecaa68aSToby Isaac if (matSize) { 24196ecaa68aSToby Isaac ierr = PetscSectionGetOffset(rootMatricesSec,p,&pMatOff);CHKERRQ(ierr); 24206ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 24216ecaa68aSToby Isaac } 24226ecaa68aSToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 24231cfc5b76SToby Isaac if (dof < 0) { 24241cfc5b76SToby Isaac dof = -(dof + 1); 24251cfc5b76SToby Isaac } 24266ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 24276ecaa68aSToby Isaac PetscInt i, j; 24286ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 24296ecaa68aSToby Isaac 24306ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 24316ecaa68aSToby Isaac PetscInt numIndices, *indices; 24326ecaa68aSToby Isaac ierr = DMPlexGetClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr); 24336ecaa68aSToby Isaac if (numIndices != numColIndices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"mismatching constraint indices calculations"); 24346ecaa68aSToby Isaac for (i = 0; i < numColIndices; i++) { 24356ecaa68aSToby Isaac pInd[i] = indices[i]; 24366ecaa68aSToby Isaac } 24376ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 243846bdb399SToby Isaac pInd[numColIndices + i] = offsets[i+1]; 243946bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i+1]; 24406ecaa68aSToby Isaac } 244146bdb399SToby Isaac ierr = DMPlexRestoreClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr); 24426ecaa68aSToby Isaac } 24436ecaa68aSToby Isaac else { 24446ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 24456ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 24466ecaa68aSToby Isaac PetscInt numPoints,*points; 24476ecaa68aSToby Isaac 24486ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numRowIndices * numRowIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr); 24496ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 24506ecaa68aSToby Isaac for (j = 0; j < numRowIndices; j++) { 24516ecaa68aSToby Isaac pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 24526ecaa68aSToby Isaac } 24536ecaa68aSToby Isaac } 24546ecaa68aSToby Isaac ierr = DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 24556ecaa68aSToby Isaac if (numFields) { 24566ecaa68aSToby Isaac PetscInt f; 24576ecaa68aSToby Isaac 24586ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 24596ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 24606ecaa68aSToby Isaac 24616ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24626ecaa68aSToby Isaac PetscInt fDof; 24636ecaa68aSToby Isaac 24646ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&fDof);CHKERRQ(ierr); 24656ecaa68aSToby Isaac offsets[f + 1] += fDof; 24666ecaa68aSToby Isaac } 24676ecaa68aSToby Isaac } 24686ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24696ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 24706ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 24716ecaa68aSToby Isaac } 24726ecaa68aSToby Isaac } 24736ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 2474267d4f3fSToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,pMatIn,&numPoints,NULL,&points,&pMatModified,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 24756ecaa68aSToby Isaac if (!numFields) { 24766ecaa68aSToby Isaac for (i = 0; i < numRowIndices * numColIndices; i++) { 24776ecaa68aSToby Isaac pMat[i] = pMatModified[i]; 24786ecaa68aSToby Isaac } 24796ecaa68aSToby Isaac } 24806ecaa68aSToby Isaac else { 24816ecaa68aSToby Isaac PetscInt f, i, j, count; 24826ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24836ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f+1]; i++) { 24846ecaa68aSToby Isaac for (j = newOffsets[f]; j < newOffsets[f+1]; j++, count++) { 24856ecaa68aSToby Isaac pMat[count] = pMatModified[i * numColIndices + j]; 24866ecaa68aSToby Isaac } 24876ecaa68aSToby Isaac } 24886ecaa68aSToby Isaac } 24896ecaa68aSToby Isaac } 24906ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatModified);CHKERRQ(ierr); 24916ecaa68aSToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 24926ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr); 24936ecaa68aSToby Isaac if (numFields) { 249446bdb399SToby Isaac PetscInt f; 249546bdb399SToby Isaac for (f = 0; f < numFields; f++) { 249646bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 249746bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 24986ecaa68aSToby Isaac } 24996ecaa68aSToby Isaac for (cl = 0; cl < numPoints*2; cl += 2) { 25006ecaa68aSToby Isaac PetscInt o = points[cl+1], globalOff, c = points[cl]; 25016ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 250246bdb399SToby Isaac indicesPointFields_private(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, o, pInd); 25036ecaa68aSToby Isaac } 25046ecaa68aSToby Isaac } else { 25056ecaa68aSToby Isaac for (cl = 0; cl < numPoints*2; cl += 2) { 25066ecaa68aSToby Isaac PetscInt o = points[cl+1], c = points[cl], globalOff; 25076ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 25086ecaa68aSToby Isaac indicesPoint_private(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, o, pInd); 25096ecaa68aSToby Isaac } 25106ecaa68aSToby Isaac } 25116ecaa68aSToby Isaac } 25126ecaa68aSToby Isaac } 25136ecaa68aSToby Isaac else if (matSize) { 25146ecaa68aSToby Isaac PetscInt cOff; 25156ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 25166ecaa68aSToby Isaac 25176ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 2518628cbfb8SToby Isaac if (numRowIndices != dof) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Miscounted dofs"); 25196ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr); 25206ecaa68aSToby Isaac ierr = DMGetWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr); 25216ecaa68aSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&cOff);CHKERRQ(ierr); 25226ecaa68aSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 25236ecaa68aSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 25246ecaa68aSToby Isaac if (numFields) { 25256ecaa68aSToby Isaac PetscInt f; 25266ecaa68aSToby Isaac 25276ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25286ecaa68aSToby Isaac PetscInt fDof; 25296ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&fDof);CHKERRQ(ierr); 25306ecaa68aSToby Isaac offsets[f + 1] = fDof; 25316ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25326ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25336ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 25346ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 25356ecaa68aSToby Isaac } 25366ecaa68aSToby Isaac } 25376ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25386ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 25396ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 25406ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 25416ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 25426ecaa68aSToby Isaac } 25436ecaa68aSToby Isaac indicesPointFields_private(cSec,p,cOff,offsetsCopy,PETSC_TRUE,0,rowIndices);CHKERRQ(ierr); 25446ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25456ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25466ecaa68aSToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 254721968bf8SToby Isaac indicesPointFields_private(localCoarse,anchor,lOff,newOffsetsCopy,PETSC_TRUE,0,colIndices);CHKERRQ(ierr); 25486ecaa68aSToby Isaac } 25496ecaa68aSToby Isaac } 25506ecaa68aSToby Isaac else { 2551267d4f3fSToby Isaac indicesPoint_private(cSec,p,cOff,offsetsCopy,PETSC_TRUE,0,rowIndices);CHKERRQ(ierr); 25526ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25536ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25546ecaa68aSToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 2555267d4f3fSToby Isaac indicesPoint_private(localCoarse,anchor,lOff,newOffsetsCopy,PETSC_TRUE,0,colIndices);CHKERRQ(ierr); 25566ecaa68aSToby Isaac } 25576ecaa68aSToby Isaac } 25586ecaa68aSToby Isaac if (numFields) { 25596ecaa68aSToby Isaac PetscInt count, f, a; 25606ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 25616ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 25626ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 25636ecaa68aSToby Isaac ierr = MatGetValues(cMat,iSize,&rowIndices[offsets[f]],jSize,&colIndices[newOffsets[f]],&pMat[count]);CHKERRQ(ierr); 25646ecaa68aSToby Isaac count += iSize * jSize; 256546bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 256646bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 25676ecaa68aSToby Isaac } 25686ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25696ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25706ecaa68aSToby Isaac PetscInt gOff; 25716ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 25726ecaa68aSToby Isaac indicesPointFields_private(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 25736ecaa68aSToby Isaac } 25746ecaa68aSToby Isaac } 25756ecaa68aSToby Isaac else { 25766ecaa68aSToby Isaac PetscInt a; 25776ecaa68aSToby Isaac ierr = MatGetValues(cMat,numRowIndices,rowIndices,numColIndices,colIndices,pMat);CHKERRQ(ierr); 25786ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25796ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25806ecaa68aSToby Isaac PetscInt gOff; 25816ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 25826ecaa68aSToby Isaac indicesPoint_private(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 25836ecaa68aSToby Isaac } 25846ecaa68aSToby Isaac } 25856ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr); 25866ecaa68aSToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr); 25876ecaa68aSToby Isaac } 25886ecaa68aSToby Isaac else { 25896ecaa68aSToby Isaac PetscInt gOff; 25906ecaa68aSToby Isaac 25916ecaa68aSToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 25926ecaa68aSToby Isaac if (numFields) { 25936ecaa68aSToby Isaac PetscInt f; 25946ecaa68aSToby Isaac 25956ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25966ecaa68aSToby Isaac PetscInt fDof; 25976ecaa68aSToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 25986ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 25996ecaa68aSToby Isaac } 26006ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 260146bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 260246bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f+1]; 26036ecaa68aSToby Isaac } 26046ecaa68aSToby Isaac indicesPointFields_private(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 26056ecaa68aSToby Isaac } 26066ecaa68aSToby Isaac else { 26076ecaa68aSToby Isaac indicesPoint_private(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 26086ecaa68aSToby Isaac } 26096ecaa68aSToby Isaac } 26106ecaa68aSToby Isaac } 2611e44e4e7fSToby Isaac ierr = PetscFree(maxChildIds);CHKERRQ(ierr); 26126ecaa68aSToby Isaac } 261346bdb399SToby Isaac { 261446bdb399SToby Isaac PetscSF indicesSF, matricesSF; 261546bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 261646bdb399SToby Isaac 261746bdb399SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr); 261846bdb399SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafMatricesSec);CHKERRQ(ierr); 261946bdb399SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootIndicesSec,&remoteOffsetsIndices,leafIndicesSec);CHKERRQ(ierr); 262046bdb399SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootMatricesSec,&remoteOffsetsMatrices,leafMatricesSec);CHKERRQ(ierr); 262146bdb399SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootIndicesSec,remoteOffsetsIndices,leafIndicesSec,&indicesSF);CHKERRQ(ierr); 262246bdb399SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootMatricesSec,remoteOffsetsMatrices,leafMatricesSec,&matricesSF);CHKERRQ(ierr); 2623e44e4e7fSToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 262446bdb399SToby Isaac ierr = PetscFree(remoteOffsetsIndices);CHKERRQ(ierr); 262546bdb399SToby Isaac ierr = PetscFree(remoteOffsetsMatrices);CHKERRQ(ierr); 262646bdb399SToby Isaac ierr = PetscSectionGetStorageSize(leafIndicesSec,&numLeafIndices);CHKERRQ(ierr); 262746bdb399SToby Isaac ierr = PetscSectionGetStorageSize(leafMatricesSec,&numLeafMatrices);CHKERRQ(ierr); 262846bdb399SToby Isaac ierr = PetscMalloc2(numLeafIndices,&leafIndices,numLeafMatrices,&leafMatrices);CHKERRQ(ierr); 262946bdb399SToby Isaac ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr); 2630267d4f3fSToby Isaac ierr = PetscSFBcastBegin(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices);CHKERRQ(ierr); 263146bdb399SToby Isaac ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr); 2632267d4f3fSToby Isaac ierr = PetscSFBcastEnd(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices);CHKERRQ(ierr); 263346bdb399SToby Isaac ierr = PetscSFDestroy(&matricesSF);CHKERRQ(ierr); 263446bdb399SToby Isaac ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr); 263546bdb399SToby Isaac ierr = PetscFree2(rootIndices,rootMatrices);CHKERRQ(ierr); 263646bdb399SToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 263746bdb399SToby Isaac ierr = PetscSectionDestroy(&rootMatricesSec);CHKERRQ(ierr); 263846bdb399SToby Isaac } 263946bdb399SToby Isaac /* count to preallocate */ 264046bdb399SToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 264146bdb399SToby Isaac { 264246bdb399SToby Isaac PetscInt nGlobal; 264346bdb399SToby Isaac PetscInt *dnnz, *onnz; 2644b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2645b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 26461c58ffc4SToby Isaac PetscInt maxDof; 26471c58ffc4SToby Isaac PetscInt *rowIndices; 26481c58ffc4SToby Isaac DM refTree; 26491c58ffc4SToby Isaac PetscInt **refPointFieldN; 26501c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 26511c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 26527c0540e0SToby Isaac PetscInt pRefStart,pRefEnd,maxConDof,maxColumns; 26531c58ffc4SToby Isaac PetscScalar *pointWork; 265446bdb399SToby Isaac 265546bdb399SToby Isaac ierr = PetscSectionGetConstrainedStorageSize(globalFine,&nGlobal);CHKERRQ(ierr); 265646bdb399SToby Isaac ierr = PetscCalloc2(nGlobal,&dnnz,nGlobal,&onnz);CHKERRQ(ierr); 2657b9a5774bSToby Isaac ierr = MatGetLayouts(mat,&rowMap,&colMap);CHKERRQ(ierr); 2658b9a5774bSToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 26591c58ffc4SToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 2660b9a5774bSToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 266146bdb399SToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 26621c58ffc4SToby Isaac ierr = PetscSectionGetMaxDof(globalFine,&maxDof);CHKERRQ(ierr); 26631c58ffc4SToby Isaac ierr = DMGetWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 266446bdb399SToby Isaac for (p = pStartF; p < pEndF; p++) { 266546bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 266646bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 266746bdb399SToby Isaac PetscInt matSize; 266821968bf8SToby Isaac PetscInt i; 266946bdb399SToby Isaac 267046bdb399SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 267146bdb399SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 267246bdb399SToby Isaac if ((gDof - gcDof) <= 0) { 267346bdb399SToby Isaac continue; 267446bdb399SToby Isaac } 267546bdb399SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 267646bdb399SToby Isaac if (gOff < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"I though having global dofs meant a non-negative offset"); 2677b9a5774bSToby 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"); 267846bdb399SToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 267946bdb399SToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 268046bdb399SToby Isaac numColIndices -= 2 * numFields; 26811c58ffc4SToby Isaac if (numColIndices <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"global fine dof with no dofs to interpolate from"); 268246bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 268321968bf8SToby Isaac offsets[0] = 0; 268421968bf8SToby Isaac offsetsCopy[0] = 0; 268521968bf8SToby Isaac newOffsets[0] = 0; 268621968bf8SToby Isaac newOffsetsCopy[0] = 0; 268746bdb399SToby Isaac if (numFields) { 268821968bf8SToby Isaac PetscInt f; 268946bdb399SToby Isaac for (f = 0; f < numFields; f++) { 269046bdb399SToby Isaac PetscInt rowDof; 269146bdb399SToby Isaac 269246bdb399SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 269321968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 269421968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 269521968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 269621968bf8SToby Isaac numD[f] = 0; 269721968bf8SToby Isaac numO[f] = 0; 269846bdb399SToby Isaac } 269921968bf8SToby Isaac ierr = indicesPointFields_private(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 270046bdb399SToby Isaac for (f = 0; f < numFields; f++) { 270121968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 270221968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 270346bdb399SToby Isaac 270446bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 270546bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 270646bdb399SToby Isaac 270746bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 270821968bf8SToby Isaac numD[f]++; 270946bdb399SToby Isaac } 271046bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 271121968bf8SToby Isaac numO[f]++; 271246bdb399SToby Isaac } 271346bdb399SToby Isaac } 271446bdb399SToby Isaac } 271546bdb399SToby Isaac } 271646bdb399SToby Isaac else { 271721968bf8SToby Isaac ierr = indicesPoint_private(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 271821968bf8SToby Isaac numD[0] = 0; 271921968bf8SToby Isaac numO[0] = 0; 272046bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 272146bdb399SToby Isaac PetscInt gInd = pInd[i]; 272246bdb399SToby Isaac 272346bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 272421968bf8SToby Isaac numD[0]++; 272546bdb399SToby Isaac } 272646bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 272721968bf8SToby Isaac numO[0]++; 272846bdb399SToby Isaac } 272946bdb399SToby Isaac } 273046bdb399SToby Isaac } 273146bdb399SToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 273246bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 273346bdb399SToby Isaac PetscInt childId; 273446bdb399SToby Isaac 273546bdb399SToby Isaac childId = childIds[p-pStartF]; 273621968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 273746bdb399SToby Isaac if (numFields) { 2738b9a5774bSToby Isaac PetscInt f; 2739b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 274021968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 274146bdb399SToby Isaac for (row = 0; row < numRows; row++) { 274221968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 274321968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 274446bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 2745b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2746b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 274746bdb399SToby Isaac } 274846bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 2749b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2750b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 275146bdb399SToby Isaac } 275246bdb399SToby Isaac else { /* constrained */ 275346bdb399SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 275446bdb399SToby Isaac } 275546bdb399SToby Isaac } 275646bdb399SToby Isaac } 275746bdb399SToby Isaac } 275846bdb399SToby Isaac else { 2759b9a5774bSToby Isaac PetscInt i; 2760b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 276146bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 276246bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 276346bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 2764b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2765b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 276646bdb399SToby Isaac } 276746bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 2768b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2769b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 277046bdb399SToby Isaac } 277146bdb399SToby Isaac else { /* constrained */ 277246bdb399SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 277346bdb399SToby Isaac } 277446bdb399SToby Isaac } 277546bdb399SToby Isaac } 277646bdb399SToby Isaac } 277746bdb399SToby Isaac else { /* interpolate from all */ 277846bdb399SToby Isaac if (numFields) { 2779b9a5774bSToby Isaac PetscInt f; 2780b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 278121968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 278246bdb399SToby Isaac for (row = 0; row < numRows; row++) { 278321968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 278446bdb399SToby Isaac if (gIndFine >= 0) { 2785b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2786b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2787b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 278846bdb399SToby Isaac } 278946bdb399SToby Isaac } 279046bdb399SToby Isaac } 279146bdb399SToby Isaac } 279246bdb399SToby Isaac else { 2793b9a5774bSToby Isaac PetscInt i; 2794b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 279546bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 279646bdb399SToby Isaac if (gIndFine >= 0) { 2797b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2798b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2799b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 280046bdb399SToby Isaac } 280146bdb399SToby Isaac } 280246bdb399SToby Isaac } 280346bdb399SToby Isaac } 280446bdb399SToby Isaac } 280546bdb399SToby Isaac else { /* interpolate from all */ 280646bdb399SToby Isaac if (numFields) { 2807b9a5774bSToby Isaac PetscInt f; 2808b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 280921968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 281046bdb399SToby Isaac for (row = 0; row < numRows; row++) { 281121968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 281246bdb399SToby Isaac if (gIndFine >= 0) { 2813b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2814b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2815b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 281646bdb399SToby Isaac } 281746bdb399SToby Isaac } 281846bdb399SToby Isaac } 281946bdb399SToby Isaac } 282046bdb399SToby Isaac else { /* every dof get a full row */ 2821b9a5774bSToby Isaac PetscInt i; 2822b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 282346bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 282446bdb399SToby Isaac if (gIndFine >= 0) { 2825b9a5774bSToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2826b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2827b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 282846bdb399SToby Isaac } 282946bdb399SToby Isaac } 283046bdb399SToby Isaac } 283146bdb399SToby Isaac } 283246bdb399SToby Isaac } 283346bdb399SToby Isaac ierr = MatXAIJSetPreallocation(mat,1,dnnz,onnz,NULL,NULL);CHKERRQ(ierr); 283446bdb399SToby Isaac ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 283521968bf8SToby Isaac 283621968bf8SToby Isaac ierr = DMPlexGetReferenceTree(fine,&refTree);CHKERRQ(ierr); 283721968bf8SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 2838e44e4e7fSToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 2839e44e4e7fSToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,NULL);CHKERRQ(ierr); 2840e44e4e7fSToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 28411c58ffc4SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxConDof);CHKERRQ(ierr); 28427c0540e0SToby Isaac ierr = PetscSectionGetMaxDof(leafIndicesSec,&maxColumns);CHKERRQ(ierr); 28437c0540e0SToby Isaac ierr = PetscMalloc1(maxConDof*maxColumns,&pointWork);CHKERRQ(ierr); 284421968bf8SToby Isaac for (p = pStartF; p < pEndF; p++) { 2845e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2846e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2847e44e4e7fSToby Isaac PetscInt matSize; 2848e44e4e7fSToby Isaac PetscInt childId; 2849e44e4e7fSToby Isaac 2850e44e4e7fSToby Isaac 2851e44e4e7fSToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 2852e44e4e7fSToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 2853e44e4e7fSToby Isaac if ((gDof - gcDof) <= 0) { 2854e44e4e7fSToby Isaac continue; 2855e44e4e7fSToby Isaac } 2856e44e4e7fSToby Isaac childId = childIds[p-pStartF]; 2857e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 2858e44e4e7fSToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 2859e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 2860e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2861e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2862e44e4e7fSToby Isaac offsets[0] = 0; 2863e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2864e44e4e7fSToby Isaac newOffsets[0] = 0; 2865e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2866e44e4e7fSToby Isaac rowOffsets[0] = 0; 2867e44e4e7fSToby Isaac if (numFields) { 2868e44e4e7fSToby Isaac PetscInt f; 2869e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2870e44e4e7fSToby Isaac PetscInt rowDof; 2871e44e4e7fSToby Isaac 2872e44e4e7fSToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 2873e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2874e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2875e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2876e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2877e44e4e7fSToby Isaac } 2878e44e4e7fSToby Isaac ierr = indicesPointFields_private(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 2879e44e4e7fSToby Isaac } 28801c58ffc4SToby Isaac else { 28811c58ffc4SToby Isaac ierr = indicesPoint_private(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 28821c58ffc4SToby Isaac } 2883e44e4e7fSToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 2884e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2885e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2886e44e4e7fSToby Isaac if (numFields) { 2887e44e4e7fSToby Isaac PetscInt f; 2888e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2889e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 2890e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 2891e44e4e7fSToby Isaac ierr = MatSetValue(mat,rowIndices[offsets[f]+row],pInd[newOffsets[f]+row],1.,INSERT_VALUES);CHKERRQ(ierr); 289221968bf8SToby Isaac } 289321968bf8SToby Isaac } 2894e44e4e7fSToby Isaac } 2895e44e4e7fSToby Isaac else { 2896e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 2897e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 2898e44e4e7fSToby Isaac ierr = MatSetValue(mat,rowIndices[row],pInd[row],1.,INSERT_VALUES);CHKERRQ(ierr); 2899e44e4e7fSToby Isaac } 2900e44e4e7fSToby Isaac } 2901e44e4e7fSToby Isaac } 2902e44e4e7fSToby Isaac else { /* interpolate from all */ 2903e44e4e7fSToby Isaac if (numFields) { 2904e44e4e7fSToby Isaac PetscInt f; 2905e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2906e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 2907e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 2908e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],refPointFieldMats[childId - pRefStart][f],INSERT_VALUES);CHKERRQ(ierr); 2909e44e4e7fSToby Isaac } 2910e44e4e7fSToby Isaac } 2911e44e4e7fSToby Isaac else { 2912e44e4e7fSToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,refPointFieldMats[childId - pRefStart][0],INSERT_VALUES);CHKERRQ(ierr); 2913e44e4e7fSToby Isaac } 2914e44e4e7fSToby Isaac } 2915e44e4e7fSToby Isaac } 2916e44e4e7fSToby Isaac else { /* interpolate from all */ 2917e44e4e7fSToby Isaac PetscInt pMatOff; 2918e44e4e7fSToby Isaac PetscScalar *pMat; 2919e44e4e7fSToby Isaac 2920e44e4e7fSToby Isaac ierr = PetscSectionGetOffset(leafMatricesSec,p,&pMatOff);CHKERRQ(ierr); 2921e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2922e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2923e44e4e7fSToby Isaac if (numFields) { 2924e44e4e7fSToby Isaac PetscInt f, count; 2925e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2926e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2927e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2928e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2929e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2930e44e4e7fSToby Isaac 2931e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],inMat,INSERT_VALUES);CHKERRQ(ierr); 2932e44e4e7fSToby Isaac count += numCols * numInRows; 2933e44e4e7fSToby Isaac } 2934e44e4e7fSToby Isaac } 2935e44e4e7fSToby Isaac else { 2936e44e4e7fSToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,pMat,INSERT_VALUES);CHKERRQ(ierr); 2937e44e4e7fSToby Isaac } 2938e44e4e7fSToby Isaac } 2939e44e4e7fSToby Isaac else { /* multiply the incoming matrix by the child interpolation */ 2940e44e4e7fSToby Isaac if (numFields) { 2941e44e4e7fSToby Isaac PetscInt f, count; 2942e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2943e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2944e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2945e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2946e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2947e44e4e7fSToby Isaac PetscInt i, j, k; 2948e44e4e7fSToby Isaac if (refPointFieldN[childId - pRefStart][f] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2949e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2950e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2951e44e4e7fSToby Isaac PetscScalar val = 0.; 2952e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2953e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2954e44e4e7fSToby Isaac } 2955e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2956e44e4e7fSToby Isaac } 2957e44e4e7fSToby Isaac } 2958e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],pointWork,INSERT_VALUES);CHKERRQ(ierr); 2959e44e4e7fSToby Isaac count += numCols * numInRows; 2960e44e4e7fSToby Isaac } 2961e44e4e7fSToby Isaac } 2962267d4f3fSToby Isaac else { /* every dof gets a full row */ 2963e44e4e7fSToby Isaac PetscInt numRows = gDof; 2964e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2965e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2966e44e4e7fSToby Isaac PetscInt i, j, k; 2967e44e4e7fSToby Isaac if (refPointFieldN[childId - pRefStart][0] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2968e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2969e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2970e44e4e7fSToby Isaac PetscScalar val = 0.; 2971e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2972e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2973e44e4e7fSToby Isaac } 2974e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2975e44e4e7fSToby Isaac } 2976e44e4e7fSToby Isaac } 2977e44e4e7fSToby Isaac ierr = MatSetValues(mat,numRows,rowIndices,numCols,pInd,pointWork,INSERT_VALUES);CHKERRQ(ierr); 2978e44e4e7fSToby Isaac } 2979e44e4e7fSToby Isaac } 2980e44e4e7fSToby Isaac } 2981e44e4e7fSToby Isaac } 29821c58ffc4SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 29831c58ffc4SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 2984e44e4e7fSToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 2985e44e4e7fSToby Isaac } 2986e44e4e7fSToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2987e44e4e7fSToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2988e44e4e7fSToby Isaac ierr = PetscSectionDestroy(&leafIndicesSec);CHKERRQ(ierr); 2989e44e4e7fSToby Isaac ierr = PetscSectionDestroy(&leafMatricesSec);CHKERRQ(ierr); 2990e44e4e7fSToby Isaac ierr = PetscFree2(leafIndices,leafMatrices);CHKERRQ(ierr); 2991e44e4e7fSToby Isaac ierr = PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO);CHKERRQ(ierr); 29926ecaa68aSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 29936ecaa68aSToby Isaac PetscFunctionReturn(0); 29946ecaa68aSToby Isaac } 2995154bca37SToby Isaac 2996154bca37SToby Isaac #undef __FUNCT__ 2997*8d2f55e7SToby Isaac #define __FUNCT__ "DMPlexComputeInjectorReferenceTree" 2998*8d2f55e7SToby Isaac /* 2999*8d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 3000*8d2f55e7SToby Isaac * 3001*8d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 3002*8d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 3003*8d2f55e7SToby Isaac * for each fine dof \phi^f_j; 3004*8d2f55e7SToby Isaac * a_{i,j} = 0; 3005*8d2f55e7SToby Isaac * for each fine dof \phi^f_k: 3006*8d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 3007*8d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 3008*8d2f55e7SToby Isaac */ 3009*8d2f55e7SToby Isaac PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 3010*8d2f55e7SToby Isaac { 3011*8d2f55e7SToby Isaac PetscDS ds; 3012*8d2f55e7SToby Isaac PetscSection section, cSection; 3013*8d2f55e7SToby Isaac DMLabel canonical, depth; 3014*8d2f55e7SToby Isaac Mat cMat, mat; 3015*8d2f55e7SToby Isaac PetscInt *nnz; 3016*8d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 3017*8d2f55e7SToby Isaac PetscInt m, n; 3018*8d2f55e7SToby Isaac PetscScalar *pointScalar; 3019*8d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 3020*8d2f55e7SToby Isaac PetscErrorCode ierr; 3021*8d2f55e7SToby Isaac 3022*8d2f55e7SToby Isaac PetscFunctionBegin; 3023*8d2f55e7SToby Isaac ierr = DMGetDefaultSection(refTree,§ion);CHKERRQ(ierr); 3024*8d2f55e7SToby Isaac ierr = DMGetDimension(refTree, &dim);CHKERRQ(ierr); 3025*8d2f55e7SToby Isaac ierr = PetscMalloc6(dim,&v0,dim,&v0parent,dim,&vtmp,dim*dim,&J,dim*dim,&Jparent,dim*dim,&invJ);CHKERRQ(ierr); 3026*8d2f55e7SToby Isaac ierr = PetscMalloc2(dim,&pointScalar,dim,&pointRef);CHKERRQ(ierr); 3027*8d2f55e7SToby Isaac ierr = DMGetDS(refTree,&ds);CHKERRQ(ierr); 3028*8d2f55e7SToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 3029*8d2f55e7SToby Isaac ierr = PetscSectionGetNumFields(section,&numSecFields);CHKERRQ(ierr); 3030*8d2f55e7SToby Isaac ierr = DMGetLabel(refTree,"canonical",&canonical);CHKERRQ(ierr); 3031*8d2f55e7SToby Isaac ierr = DMGetLabel(refTree,"depth",&depth);CHKERRQ(ierr); 3032*8d2f55e7SToby Isaac ierr = DMGetDefaultConstraints(refTree,&cSection,&cMat);CHKERRQ(ierr); 3033*8d2f55e7SToby Isaac ierr = DMPlexGetChart(refTree, &pStart, &pEnd);CHKERRQ(ierr); 3034*8d2f55e7SToby Isaac ierr = DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd);CHKERRQ(ierr); 3035*8d2f55e7SToby Isaac ierr = MatGetSize(cMat,&n,&m);CHKERRQ(ierr); /* the injector has transpose sizes from the constraint matrix */ 3036*8d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 3037*8d2f55e7SToby Isaac ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr); 3038*8d2f55e7SToby 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 */ 3039*8d2f55e7SToby Isaac const PetscInt *children; 3040*8d2f55e7SToby Isaac PetscInt numChildren; 3041*8d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 3042*8d2f55e7SToby Isaac 3043*8d2f55e7SToby Isaac if (canonical) { 3044*8d2f55e7SToby Isaac PetscInt pCanonical; 3045*8d2f55e7SToby Isaac ierr = DMLabelGetValue(canonical,p,&pCanonical);CHKERRQ(ierr); 3046*8d2f55e7SToby Isaac if (p != pCanonical) continue; 3047*8d2f55e7SToby Isaac } 3048*8d2f55e7SToby Isaac ierr = DMPlexGetTreeChildren(refTree,p,&numChildren,&children);CHKERRQ(ierr); 3049*8d2f55e7SToby Isaac if (!numChildren) continue; 3050*8d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 3051*8d2f55e7SToby Isaac PetscInt child = children[i]; 3052*8d2f55e7SToby Isaac PetscInt dof; 3053*8d2f55e7SToby Isaac 3054*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,child,&dof);CHKERRQ(ierr); 3055*8d2f55e7SToby Isaac numChildDof += dof; 3056*8d2f55e7SToby Isaac } 3057*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,p,&numSelfDof);CHKERRQ(ierr); 3058*8d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 3059*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3060*8d2f55e7SToby Isaac PetscInt selfOff; 3061*8d2f55e7SToby Isaac 3062*8d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 3063*8d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 3064*8d2f55e7SToby Isaac PetscInt child = children[i]; 3065*8d2f55e7SToby Isaac PetscInt dof; 3066*8d2f55e7SToby Isaac 3067*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,child,f,&dof);CHKERRQ(ierr); 3068*8d2f55e7SToby Isaac numChildDof += dof; 3069*8d2f55e7SToby Isaac } 3070*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&numSelfDof);CHKERRQ(ierr); 3071*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(section,p,f,&selfOff);CHKERRQ(ierr); 3072*8d2f55e7SToby Isaac } 3073*8d2f55e7SToby Isaac else { 3074*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(section,p,&selfOff);CHKERRQ(ierr); 3075*8d2f55e7SToby Isaac } 3076*8d2f55e7SToby Isaac for (i = 0; i < numSelfDof; i++) { 3077*8d2f55e7SToby Isaac nnz[selfOff + i] = numChildDof; 3078*8d2f55e7SToby Isaac } 3079*8d2f55e7SToby Isaac } 3080*8d2f55e7SToby Isaac } 3081*8d2f55e7SToby Isaac ierr = MatCreateAIJ(PETSC_COMM_SELF,m,n,m,n,-1,nnz,-1,NULL,&mat);CHKERRQ(ierr); 3082*8d2f55e7SToby Isaac ierr = PetscFree(nnz);CHKERRQ(ierr); 3083*8d2f55e7SToby Isaac /* Setp 2: compute entries */ 3084*8d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 3085*8d2f55e7SToby Isaac const PetscInt *children; 3086*8d2f55e7SToby Isaac PetscInt numChildren; 3087*8d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 3088*8d2f55e7SToby Isaac 3089*8d2f55e7SToby Isaac /* same conditions about when entries occur */ 3090*8d2f55e7SToby Isaac if (canonical) { 3091*8d2f55e7SToby Isaac PetscInt pCanonical; 3092*8d2f55e7SToby Isaac ierr = DMLabelGetValue(canonical,p,&pCanonical);CHKERRQ(ierr); 3093*8d2f55e7SToby Isaac if (p != pCanonical) continue; 3094*8d2f55e7SToby Isaac } 3095*8d2f55e7SToby Isaac ierr = DMPlexGetTreeChildren(refTree,p,&numChildren,&children);CHKERRQ(ierr); 3096*8d2f55e7SToby Isaac if (!numChildren) continue; 3097*8d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 3098*8d2f55e7SToby Isaac PetscInt child = children[i]; 3099*8d2f55e7SToby Isaac PetscInt dof; 3100*8d2f55e7SToby Isaac 3101*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,child,&dof);CHKERRQ(ierr); 3102*8d2f55e7SToby Isaac numChildDof += dof; 3103*8d2f55e7SToby Isaac } 3104*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(section,p,&numSelfDof);CHKERRQ(ierr); 3105*8d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 3106*8d2f55e7SToby Isaac 3107*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3108*8d2f55e7SToby Isaac PetscInt selfOff, fComp, numSelfShapes, numChildShapes, parentCell; 3109*8d2f55e7SToby Isaac PetscInt cellShapeOff; 3110*8d2f55e7SToby Isaac PetscObject disc; 3111*8d2f55e7SToby Isaac PetscDualSpace dsp; 3112*8d2f55e7SToby Isaac PetscClassId classId; 3113*8d2f55e7SToby Isaac PetscScalar *pointMat; 3114*8d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 3115*8d2f55e7SToby Isaac const PetscInt *depthNumDof; 3116*8d2f55e7SToby Isaac 3117*8d2f55e7SToby Isaac if (numSecFields) { 3118*8d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 3119*8d2f55e7SToby Isaac PetscInt child = children[i]; 3120*8d2f55e7SToby Isaac PetscInt dof; 3121*8d2f55e7SToby Isaac 3122*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,child,f,&dof);CHKERRQ(ierr); 3123*8d2f55e7SToby Isaac numChildDof += dof; 3124*8d2f55e7SToby Isaac } 3125*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&numSelfDof);CHKERRQ(ierr); 3126*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(section,p,f,&selfOff);CHKERRQ(ierr); 3127*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldComponents(section,f,&fComp);CHKERRQ(ierr); 3128*8d2f55e7SToby Isaac } 3129*8d2f55e7SToby Isaac else { 3130*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(section,p,&selfOff);CHKERRQ(ierr); 3131*8d2f55e7SToby Isaac fComp = 1; 3132*8d2f55e7SToby Isaac } 3133*8d2f55e7SToby Isaac numSelfShapes = numSelfDof / fComp; 3134*8d2f55e7SToby Isaac numChildShapes = numChildDof / fComp; 3135*8d2f55e7SToby Isaac 3136*8d2f55e7SToby Isaac /* find a cell whose star contains p */ 3137*8d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 3138*8d2f55e7SToby Isaac parentCell = p; 3139*8d2f55e7SToby Isaac } 3140*8d2f55e7SToby Isaac else { 3141*8d2f55e7SToby Isaac PetscInt *star = NULL; 3142*8d2f55e7SToby Isaac PetscInt numStar; 3143*8d2f55e7SToby Isaac 3144*8d2f55e7SToby Isaac parentCell = -1; 3145*8d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 3146*8d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 3147*8d2f55e7SToby Isaac PetscInt c = star[2 * i]; 3148*8d2f55e7SToby Isaac 3149*8d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 3150*8d2f55e7SToby Isaac parentCell = c; 3151*8d2f55e7SToby Isaac break; 3152*8d2f55e7SToby Isaac } 3153*8d2f55e7SToby Isaac } 3154*8d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 3155*8d2f55e7SToby Isaac } 3156*8d2f55e7SToby Isaac /* determine the offset of p's shape functions withing parentCell's shape functions */ 3157*8d2f55e7SToby Isaac ierr = PetscDualSpaceGetNumDof(dsp,&depthNumDof);CHKERRQ(ierr); 3158*8d2f55e7SToby Isaac { 3159*8d2f55e7SToby Isaac PetscInt *closure = NULL; 3160*8d2f55e7SToby Isaac PetscInt numClosure; 3161*8d2f55e7SToby Isaac 3162*8d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 3163*8d2f55e7SToby Isaac for (i = 0, cellShapeOff = 0; i < numClosure; i++) { 3164*8d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 3165*8d2f55e7SToby Isaac 3166*8d2f55e7SToby Isaac pO = closure[2 * i + 1]; 3167*8d2f55e7SToby Isaac if (point == p) break; 3168*8d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,point,&pointDepth);CHKERRQ(ierr); 3169*8d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 3170*8d2f55e7SToby Isaac } 3171*8d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 3172*8d2f55e7SToby Isaac } 3173*8d2f55e7SToby Isaac 3174*8d2f55e7SToby Isaac ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr); 3175*8d2f55e7SToby Isaac ierr = PetscObjectGetClassId(disc,&classId);CHKERRQ(ierr); 3176*8d2f55e7SToby Isaac ierr = DMGetWorkArray(refTree, numSelfShapes * numChildShapes, PETSC_SCALAR,&pointMat);CHKERRQ(ierr); 3177*8d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 3178*8d2f55e7SToby Isaac PetscFE fe = (PetscFE) disc; 3179*8d2f55e7SToby Isaac PetscInt fSize; 3180*8d2f55e7SToby Isaac 3181*8d2f55e7SToby Isaac ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr); 3182*8d2f55e7SToby Isaac ierr = PetscDualSpaceGetDimension(dsp,&fSize); 3183*8d2f55e7SToby Isaac for (i = 0; i < numSelfShapes; i++) { /* for every shape function */ 3184*8d2f55e7SToby Isaac PetscQuadrature q; 3185*8d2f55e7SToby Isaac PetscInt dim, numPoints, j, k; 3186*8d2f55e7SToby Isaac const PetscReal *points; 3187*8d2f55e7SToby Isaac const PetscReal *weights; 3188*8d2f55e7SToby Isaac PetscInt *closure = NULL; 3189*8d2f55e7SToby Isaac PetscInt numClosure; 3190*8d2f55e7SToby Isaac PetscInt iOff = selfOff + fComp * i; 3191*8d2f55e7SToby Isaac PetscReal *Bparent; 3192*8d2f55e7SToby Isaac 3193*8d2f55e7SToby Isaac PetscDualSpaceGetFunctional(dsp,cellShapeOff + (p0 < 0 ? (numSelfShapes - 1 - i) : i),&q);CHKERRQ(ierr); 3194*8d2f55e7SToby Isaac PetscQuadratureGetData(q,&dim,&numPoints,&points,&weights);CHKERRQ(ierr); 3195*8d2f55e7SToby Isaac ierr = PetscFEGetTabulation(fe,numPoints,points,&Bparent,NULL,NULL);CHKERRQ(ierr); 3196*8d2f55e7SToby Isaac for (k = 0; k < numChildShapes; k++) { 3197*8d2f55e7SToby Isaac pointMat[numChildShapes * i + k] = 0.; 3198*8d2f55e7SToby Isaac } 3199*8d2f55e7SToby Isaac for (j = 0; j < numPoints; j++) { /* locate the point in a cell*/ 3200*8d2f55e7SToby Isaac PetscInt childCell = -1; 3201*8d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 3202*8d2f55e7SToby Isaac const PetscScalar *point; 3203*8d2f55e7SToby Isaac PetscReal *Bchild; 3204*8d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 3205*8d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 3206*8d2f55e7SToby Isaac PetscInt d; 3207*8d2f55e7SToby Isaac 3208*8d2f55e7SToby Isaac for (d = 0; d < dim; d++) { 3209*8d2f55e7SToby Isaac pointScalar[d] = points[dim * j + d]; 3210*8d2f55e7SToby Isaac } 3211*8d2f55e7SToby Isaac point = pointScalar; 3212*8d2f55e7SToby Isaac #else 3213*8d2f55e7SToby Isaac point = pointReal; 3214*8d2f55e7SToby Isaac #endif 3215*8d2f55e7SToby Isaac 3216*8d2f55e7SToby Isaac for (k = 0; k < numChildren; k++) { 3217*8d2f55e7SToby Isaac PetscInt child = children[k]; 3218*8d2f55e7SToby Isaac PetscInt *star = NULL; 3219*8d2f55e7SToby Isaac PetscInt numStar, s; 3220*8d2f55e7SToby Isaac 3221*8d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 3222*8d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 3223*8d2f55e7SToby Isaac PetscInt c = star[2 * s]; 3224*8d2f55e7SToby Isaac 3225*8d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 3226*8d2f55e7SToby Isaac ierr = DMPlexLocatePoint_Internal(refTree,dim,point,c,&childCell);CHKERRQ(ierr); 3227*8d2f55e7SToby Isaac if (childCell >= 0) break; 3228*8d2f55e7SToby Isaac } 3229*8d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star);CHKERRQ(ierr); 3230*8d2f55e7SToby Isaac if (childCell >= 0) break; 3231*8d2f55e7SToby Isaac } 3232*8d2f55e7SToby Isaac if (childCell < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not locate quadrature point");CHKERRQ(ierr); 3233*8d2f55e7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 3234*8d2f55e7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent);CHKERRQ(ierr); 3235*8d2f55e7SToby Isaac CoordinatesRefToReal(dim, dim, v0parent, Jparent, pointReal, vtmp); 3236*8d2f55e7SToby Isaac CoordinatesRealToRef(dim, dim, v0, invJ, vtmp, pointRef); 3237*8d2f55e7SToby Isaac 3238*8d2f55e7SToby Isaac ierr = PetscFEGetTabulation(fe,1,pointRef,&Bchild,NULL,NULL);CHKERRQ(ierr); 3239*8d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 3240*8d2f55e7SToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { 3241*8d2f55e7SToby Isaac PetscInt child = children[k], childDepth, childDof, childOff, childO = PETSC_MIN_INT; 3242*8d2f55e7SToby Isaac PetscInt l; 3243*8d2f55e7SToby Isaac 3244*8d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,child,&childDepth);CHKERRQ(ierr); 3245*8d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 3246*8d2f55e7SToby Isaac for (l = 0, childCellShapeOff = 0; l < numClosure; l++) { 3247*8d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 3248*8d2f55e7SToby Isaac PetscInt pointDepth; 3249*8d2f55e7SToby Isaac 3250*8d2f55e7SToby Isaac childO = closure[2 * l + 1]; 3251*8d2f55e7SToby Isaac if (point == child) break; 3252*8d2f55e7SToby Isaac ierr = DMLabelGetValue(depth,point,&pointDepth);CHKERRQ(ierr); 3253*8d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 3254*8d2f55e7SToby Isaac } 3255*8d2f55e7SToby Isaac if (l == numClosure) { 3256*8d2f55e7SToby Isaac pointMatOff += childDof; 3257*8d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 3258*8d2f55e7SToby Isaac } 3259*8d2f55e7SToby Isaac if (numSecFields) { 3260*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldOffset(cSection,child,f,&childOff);CHKERRQ(ierr); 3261*8d2f55e7SToby Isaac } 3262*8d2f55e7SToby Isaac else { 3263*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(cSection,child,&childOff);CHKERRQ(ierr); 3264*8d2f55e7SToby Isaac } 3265*8d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 3266*8d2f55e7SToby Isaac PetscInt lOff = childOff + fComp * l; 3267*8d2f55e7SToby Isaac PetscInt cellDof = childCellShapeOff + (childO ? (childDof - 1 - l) : l); 3268*8d2f55e7SToby Isaac PetscReal valAtPoint = Bchild[cellDof]; 3269*8d2f55e7SToby Isaac PetscScalar interpItoL; 3270*8d2f55e7SToby Isaac 3271*8d2f55e7SToby Isaac ierr = MatGetValue(cMat,lOff,iOff,&interpItoL);CHKERRQ(ierr); 3272*8d2f55e7SToby Isaac pointMat[i * numChildShapes + pointMatOff + l] += weight[j] * Bparent[ 3273*8d2f55e7SToby Isaac } 3274*8d2f55e7SToby Isaac pointMatOff += childDof; 3275*8d2f55e7SToby Isaac } 3276*8d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure);CHKERRQ(ierr); 3277*8d2f55e7SToby Isaac ierr = PetscFERestoreTabulation(fe,1,pointRef,&Bchild,NULL,NULL);CHKERRQ(ierr); 3278*8d2f55e7SToby Isaac } 3279*8d2f55e7SToby Isaac ierr = PetscFERestoreTabulation(fe,numPoints,points,&Bparent,NULL,NULL);CHKERRQ(ierr); 3280*8d2f55e7SToby Isaac } 3281*8d2f55e7SToby Isaac } 3282*8d2f55e7SToby Isaac else if (classId == PETSCFV_CLASSID) { 3283*8d2f55e7SToby Isaac PetscFV fv = (PetscFV) disc; 3284*8d2f55e7SToby Isaac } 3285*8d2f55e7SToby Isaac else { 3286*8d2f55e7SToby Isaac SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported discretization object");CHKERRQ(ierr); 3287*8d2f55e7SToby Isaac } 3288*8d2f55e7SToby Isaac ierr = DMRestoreWorkArray(refTree, numSelfShapes * numChildShapes, PETSC_SCALAR,&pointMat);CHKERRQ(ierr); 3289*8d2f55e7SToby Isaac } 3290*8d2f55e7SToby Isaac } 3291*8d2f55e7SToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent);CHKERRQ(ierr); 3292*8d2f55e7SToby Isaac ierr = PetscFree2(pointScalar,pointRef);CHKERRQ(ierr); 3293*8d2f55e7SToby Isaac *inj = mat; 3294*8d2f55e7SToby Isaac PetscFunctionReturn(0); 3295*8d2f55e7SToby Isaac } 3296*8d2f55e7SToby Isaac 3297*8d2f55e7SToby Isaac #undef __FUNCT__ 3298154bca37SToby Isaac #define __FUNCT__ "DMPlexComputeInjectorTree" 3299154bca37SToby Isaac PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3300154bca37SToby Isaac { 3301*8d2f55e7SToby Isaac PetscSF coarseToFineEmbedded; 3302*8d2f55e7SToby Isaac PetscSection globalCoarse, globalFine; 3303*8d2f55e7SToby Isaac PetscSection localCoarse, localFine; 3304*8d2f55e7SToby Isaac PetscSection aSec, cSec; 3305*8d2f55e7SToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 3306*8d2f55e7SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 3307*8d2f55e7SToby Isaac PetscInt *rootIndices, *leafIndices; 3308*8d2f55e7SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 3309*8d2f55e7SToby Isaac IS aIS; 3310*8d2f55e7SToby Isaac const PetscInt *anchors; 3311*8d2f55e7SToby Isaac Mat cMat; 3312*8d2f55e7SToby Isaac PetscInt numFields; 3313*8d2f55e7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3314*8d2f55e7SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 3315*8d2f55e7SToby Isaac PetscInt *maxChildIds; 3316*8d2f55e7SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 3317*8d2f55e7SToby Isaac PetscErrorCode ierr; 3318*8d2f55e7SToby Isaac 3319154bca37SToby Isaac PetscFunctionBegin; 3320*8d2f55e7SToby Isaac ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr); 3321*8d2f55e7SToby Isaac ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr); 3322*8d2f55e7SToby Isaac ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr); 3323*8d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 3324*8d2f55e7SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 3325*8d2f55e7SToby Isaac 3326*8d2f55e7SToby Isaac for (p = pStartF, numPointsWithDofs = 0; p < pEndF; p++) { 3327*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 3328*8d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 3329*8d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3330*8d2f55e7SToby Isaac numPointsWithDofs++; 3331*8d2f55e7SToby Isaac } 3332*8d2f55e7SToby Isaac } 3333*8d2f55e7SToby Isaac ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr); 3334*8d2f55e7SToby Isaac for (p = pStartF, offset = 0; p < pEndF; p++) { 3335*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr); 3336*8d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr); 3337*8d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3338*8d2f55e7SToby Isaac pointsWithDofs[offset++] = p - pStartF; 3339*8d2f55e7SToby Isaac } 3340*8d2f55e7SToby Isaac } 3341*8d2f55e7SToby Isaac ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr); 3342*8d2f55e7SToby Isaac } 3343*8d2f55e7SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 3344*8d2f55e7SToby Isaac ierr = PetscMalloc1(pEndC-pStartC,&maxChildIds);CHKERRQ(ierr); 3345*8d2f55e7SToby Isaac for (p = pStartC; p < pEndC; p++) { 3346*8d2f55e7SToby Isaac maxChildIds[p - pStartC] = -2; 3347*8d2f55e7SToby Isaac } 3348*8d2f55e7SToby Isaac ierr = PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 3349*8d2f55e7SToby Isaac ierr = PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr); 3350*8d2f55e7SToby Isaac 3351*8d2f55e7SToby Isaac ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr); 3352*8d2f55e7SToby Isaac ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr); 3353*8d2f55e7SToby Isaac 3354*8d2f55e7SToby Isaac ierr = DMPlexGetAnchors(coarse,&aSec,&aIS);CHKERRQ(ierr); 3355*8d2f55e7SToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 3356*8d2f55e7SToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 3357*8d2f55e7SToby Isaac 3358*8d2f55e7SToby Isaac ierr = DMGetDefaultConstraints(coarse,&cSec,&cMat);CHKERRQ(ierr); 3359*8d2f55e7SToby Isaac ierr = PetscSectionGetChart(cSec,&cStart,&cEnd);CHKERRQ(ierr); 3360*8d2f55e7SToby Isaac 3361*8d2f55e7SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 3362*8d2f55e7SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec);CHKERRQ(ierr); 3363*8d2f55e7SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootMatricesSec);CHKERRQ(ierr); 3364*8d2f55e7SToby Isaac ierr = PetscSectionSetChart(rootIndicesSec,pStartC,pEndC);CHKERRQ(ierr); 3365*8d2f55e7SToby Isaac ierr = PetscSectionSetChart(rootMatricesSec,pStartC,pEndC);CHKERRQ(ierr); 3366*8d2f55e7SToby Isaac ierr = PetscSectionGetNumFields(globalCoarse,&numFields);CHKERRQ(ierr); 3367*8d2f55e7SToby Isaac { 3368*8d2f55e7SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 3369*8d2f55e7SToby Isaac ierr = PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO);CHKERRQ(ierr); 3370*8d2f55e7SToby Isaac } 3371*8d2f55e7SToby Isaac 3372*8d2f55e7SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 3373*8d2f55e7SToby Isaac PetscInt dof, matSize = 0; 3374*8d2f55e7SToby Isaac PetscInt aDof = 0; 3375*8d2f55e7SToby Isaac PetscInt cDof = 0; 3376*8d2f55e7SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 3377*8d2f55e7SToby Isaac PetscInt numRowIndices = 0; 3378*8d2f55e7SToby Isaac PetscInt numColIndices = 0; 3379*8d2f55e7SToby Isaac 3380*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 3381*8d2f55e7SToby Isaac if (dof < 0) { 3382*8d2f55e7SToby Isaac dof = -(dof + 1); 3383*8d2f55e7SToby Isaac } 3384*8d2f55e7SToby Isaac if (p >= aStart && p < aEnd) { 3385*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 3386*8d2f55e7SToby Isaac } 3387*8d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 3388*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(cSec,p,&cDof);CHKERRQ(ierr); 3389*8d2f55e7SToby Isaac } 3390*8d2f55e7SToby Isaac offsets[0] = 0; 3391*8d2f55e7SToby Isaac newOffsets[0] = 0; 3392*8d2f55e7SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 3393*8d2f55e7SToby Isaac PetscInt *closure = NULL, closureSize, cl, f; 3394*8d2f55e7SToby Isaac 3395*8d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 3396*8d2f55e7SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 3397*8d2f55e7SToby Isaac PetscInt c = closure[2 * cl], clDof; 3398*8d2f55e7SToby Isaac 3399*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr); 3400*8d2f55e7SToby Isaac numRowIndices += clDof; 3401*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3402*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&clDof);CHKERRQ(ierr); 3403*8d2f55e7SToby Isaac offsets[f + 1] += clDof; 3404*8d2f55e7SToby Isaac } 3405*8d2f55e7SToby Isaac } 3406*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3407*8d2f55e7SToby Isaac offsets[f + 1] += offsets[f]; 3408*8d2f55e7SToby Isaac newOffsets[f + 1] = offsets[f + 1]; 3409*8d2f55e7SToby Isaac } 3410*8d2f55e7SToby Isaac /* get the number of indices needed and their field offsets */ 3411*8d2f55e7SToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,NULL,NULL,&numColIndices,NULL,NULL,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 3412*8d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 3413*8d2f55e7SToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 3414*8d2f55e7SToby Isaac numColIndices = numRowIndices; 3415*8d2f55e7SToby Isaac matSize = 0; 3416*8d2f55e7SToby Isaac } 3417*8d2f55e7SToby Isaac else if (numFields) { /* we send one submat for each field: sum their sizes */ 3418*8d2f55e7SToby Isaac matSize = 0; 3419*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3420*8d2f55e7SToby Isaac PetscInt numRow, numCol; 3421*8d2f55e7SToby Isaac 3422*8d2f55e7SToby Isaac numRow = offsets[f + 1] - offsets[f]; 3423*8d2f55e7SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f + 1]; 3424*8d2f55e7SToby Isaac matSize += numRow * numCol; 3425*8d2f55e7SToby Isaac } 3426*8d2f55e7SToby Isaac } 3427*8d2f55e7SToby Isaac else { 3428*8d2f55e7SToby Isaac matSize = numRowIndices * numColIndices; 3429*8d2f55e7SToby Isaac } 3430*8d2f55e7SToby Isaac } 3431*8d2f55e7SToby Isaac else if (maxChildId == -1) { 3432*8d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 3433*8d2f55e7SToby Isaac PetscInt aOff, a, f; 3434*8d2f55e7SToby Isaac 3435*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 3436*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3437*8d2f55e7SToby Isaac PetscInt fDof; 3438*8d2f55e7SToby Isaac 3439*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 3440*8d2f55e7SToby Isaac offsets[f+1] = fDof; 3441*8d2f55e7SToby Isaac } 3442*8d2f55e7SToby Isaac for (a = 0; a < aDof; a++) { 3443*8d2f55e7SToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 3444*8d2f55e7SToby Isaac 3445*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(localCoarse,anchor,&aLocalDof);CHKERRQ(ierr); 3446*8d2f55e7SToby Isaac numColIndices += aLocalDof; 3447*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3448*8d2f55e7SToby Isaac PetscInt fDof; 3449*8d2f55e7SToby Isaac 3450*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 3451*8d2f55e7SToby Isaac newOffsets[f+1] += fDof; 3452*8d2f55e7SToby Isaac } 3453*8d2f55e7SToby Isaac } 3454*8d2f55e7SToby Isaac if (numFields) { 3455*8d2f55e7SToby Isaac matSize = 0; 3456*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3457*8d2f55e7SToby Isaac matSize += offsets[f+1] * newOffsets[f+1]; 3458*8d2f55e7SToby Isaac } 3459*8d2f55e7SToby Isaac } 3460*8d2f55e7SToby Isaac else { 3461*8d2f55e7SToby Isaac matSize = numColIndices * dof; 3462*8d2f55e7SToby Isaac } 3463*8d2f55e7SToby Isaac } 3464*8d2f55e7SToby Isaac else { /* no children, and no constraints on dofs: just get the global indices */ 3465*8d2f55e7SToby Isaac numColIndices = dof; 3466*8d2f55e7SToby Isaac matSize = 0; 3467*8d2f55e7SToby Isaac } 3468*8d2f55e7SToby Isaac } 3469*8d2f55e7SToby Isaac /* we will pack the column indices with the field offsets */ 3470*8d2f55e7SToby Isaac ierr = PetscSectionSetDof(rootIndicesSec,p,numColIndices ? numColIndices+2*numFields : 0);CHKERRQ(ierr); 3471*8d2f55e7SToby Isaac ierr = PetscSectionSetDof(rootMatricesSec,p,matSize);CHKERRQ(ierr); 3472*8d2f55e7SToby Isaac } 3473*8d2f55e7SToby Isaac ierr = PetscSectionSetUp(rootIndicesSec);CHKERRQ(ierr); 3474*8d2f55e7SToby Isaac ierr = PetscSectionSetUp(rootMatricesSec);CHKERRQ(ierr); 3475*8d2f55e7SToby Isaac { 3476*8d2f55e7SToby Isaac PetscInt numRootIndices, numRootMatrices; 3477*8d2f55e7SToby Isaac 3478*8d2f55e7SToby Isaac ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr); 3479*8d2f55e7SToby Isaac ierr = PetscSectionGetStorageSize(rootMatricesSec,&numRootMatrices);CHKERRQ(ierr); 3480*8d2f55e7SToby Isaac ierr = PetscMalloc2(numRootIndices,&rootIndices,numRootMatrices,&rootMatrices);CHKERRQ(ierr); 3481*8d2f55e7SToby Isaac for (p = pStartC; p < pEndC; p++) { 3482*8d2f55e7SToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 3483*8d2f55e7SToby Isaac PetscInt pIndOff, pMatOff; 3484*8d2f55e7SToby Isaac PetscInt *pInd; 3485*8d2f55e7SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 3486*8d2f55e7SToby Isaac PetscScalar *pMat = NULL; 3487*8d2f55e7SToby Isaac 3488*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(rootIndicesSec,p,&numColIndices);CHKERRQ(ierr); 3489*8d2f55e7SToby Isaac if (!numColIndices) { 3490*8d2f55e7SToby Isaac continue; 3491*8d2f55e7SToby Isaac } 3492*8d2f55e7SToby Isaac offsets[0] = 0; 3493*8d2f55e7SToby Isaac newOffsets[0] = 0; 3494*8d2f55e7SToby Isaac offsetsCopy[0] = 0; 3495*8d2f55e7SToby Isaac newOffsetsCopy[0] = 0; 3496*8d2f55e7SToby Isaac numColIndices -= 2 * numFields; 3497*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(rootIndicesSec,p,&pIndOff);CHKERRQ(ierr); 3498*8d2f55e7SToby Isaac pInd = &(rootIndices[pIndOff]); 3499*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(rootMatricesSec,p,&matSize);CHKERRQ(ierr); 3500*8d2f55e7SToby Isaac if (matSize) { 3501*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(rootMatricesSec,p,&pMatOff);CHKERRQ(ierr); 3502*8d2f55e7SToby Isaac pMat = &rootMatrices[pMatOff]; 3503*8d2f55e7SToby Isaac } 3504*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr); 3505*8d2f55e7SToby Isaac if (dof < 0) { 3506*8d2f55e7SToby Isaac dof = -(dof + 1); 3507*8d2f55e7SToby Isaac } 3508*8d2f55e7SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 3509*8d2f55e7SToby Isaac PetscInt i, j; 3510*8d2f55e7SToby Isaac PetscInt numRowIndices = matSize / numColIndices; 3511*8d2f55e7SToby Isaac 3512*8d2f55e7SToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 3513*8d2f55e7SToby Isaac PetscInt numIndices, *indices; 3514*8d2f55e7SToby Isaac ierr = DMPlexGetClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr); 3515*8d2f55e7SToby Isaac if (numIndices != numColIndices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"mismatching constraint indices calculations"); 3516*8d2f55e7SToby Isaac for (i = 0; i < numColIndices; i++) { 3517*8d2f55e7SToby Isaac pInd[i] = indices[i]; 3518*8d2f55e7SToby Isaac } 3519*8d2f55e7SToby Isaac for (i = 0; i < numFields; i++) { 3520*8d2f55e7SToby Isaac pInd[numColIndices + i] = offsets[i+1]; 3521*8d2f55e7SToby Isaac pInd[numColIndices + numFields + i] = offsets[i+1]; 3522*8d2f55e7SToby Isaac } 3523*8d2f55e7SToby Isaac ierr = DMPlexRestoreClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr); 3524*8d2f55e7SToby Isaac } 3525*8d2f55e7SToby Isaac else { 3526*8d2f55e7SToby Isaac PetscInt closureSize, *closure = NULL, cl; 3527*8d2f55e7SToby Isaac PetscScalar *pMatIn, *pMatModified; 3528*8d2f55e7SToby Isaac PetscInt numPoints,*points; 3529*8d2f55e7SToby Isaac 3530*8d2f55e7SToby Isaac ierr = DMGetWorkArray(coarse,numRowIndices * numRowIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr); 3531*8d2f55e7SToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 3532*8d2f55e7SToby Isaac for (j = 0; j < numRowIndices; j++) { 3533*8d2f55e7SToby Isaac pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 3534*8d2f55e7SToby Isaac } 3535*8d2f55e7SToby Isaac } 3536*8d2f55e7SToby Isaac ierr = DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3537*8d2f55e7SToby Isaac if (numFields) { 3538*8d2f55e7SToby Isaac PetscInt f; 3539*8d2f55e7SToby Isaac 3540*8d2f55e7SToby Isaac for (cl = 0; cl < closureSize; cl++) { 3541*8d2f55e7SToby Isaac PetscInt c = closure[2 * cl]; 3542*8d2f55e7SToby Isaac 3543*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3544*8d2f55e7SToby Isaac PetscInt fDof; 3545*8d2f55e7SToby Isaac 3546*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,c,f,&fDof);CHKERRQ(ierr); 3547*8d2f55e7SToby Isaac offsets[f + 1] += fDof; 3548*8d2f55e7SToby Isaac } 3549*8d2f55e7SToby Isaac } 3550*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3551*8d2f55e7SToby Isaac offsets[f + 1] += offsets[f]; 3552*8d2f55e7SToby Isaac newOffsets[f + 1] = offsets[f + 1]; 3553*8d2f55e7SToby Isaac } 3554*8d2f55e7SToby Isaac } 3555*8d2f55e7SToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 3556*8d2f55e7SToby Isaac ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,pMatIn,&numPoints,NULL,&points,&pMatModified,newOffsets,PETSC_FALSE);CHKERRQ(ierr); 3557*8d2f55e7SToby Isaac if (!numFields) { 3558*8d2f55e7SToby Isaac for (i = 0; i < numRowIndices * numColIndices; i++) { 3559*8d2f55e7SToby Isaac pMat[i] = pMatModified[i]; 3560*8d2f55e7SToby Isaac } 3561*8d2f55e7SToby Isaac } 3562*8d2f55e7SToby Isaac else { 3563*8d2f55e7SToby Isaac PetscInt f, i, j, count; 3564*8d2f55e7SToby Isaac for (f = 0, count = 0; f < numFields; f++) { 3565*8d2f55e7SToby Isaac for (i = offsets[f]; i < offsets[f+1]; i++) { 3566*8d2f55e7SToby Isaac for (j = newOffsets[f]; j < newOffsets[f+1]; j++, count++) { 3567*8d2f55e7SToby Isaac pMat[count] = pMatModified[i * numColIndices + j]; 3568*8d2f55e7SToby Isaac } 3569*8d2f55e7SToby Isaac } 3570*8d2f55e7SToby Isaac } 3571*8d2f55e7SToby Isaac } 3572*8d2f55e7SToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatModified);CHKERRQ(ierr); 3573*8d2f55e7SToby Isaac ierr = DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3574*8d2f55e7SToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr); 3575*8d2f55e7SToby Isaac if (numFields) { 3576*8d2f55e7SToby Isaac PetscInt f; 3577*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3578*8d2f55e7SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 3579*8d2f55e7SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 3580*8d2f55e7SToby Isaac } 3581*8d2f55e7SToby Isaac for (cl = 0; cl < numPoints*2; cl += 2) { 3582*8d2f55e7SToby Isaac PetscInt o = points[cl+1], globalOff, c = points[cl]; 3583*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 3584*8d2f55e7SToby Isaac indicesPointFields_private(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, o, pInd); 3585*8d2f55e7SToby Isaac } 3586*8d2f55e7SToby Isaac } else { 3587*8d2f55e7SToby Isaac for (cl = 0; cl < numPoints*2; cl += 2) { 3588*8d2f55e7SToby Isaac PetscInt o = points[cl+1], c = points[cl], globalOff; 3589*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr); 3590*8d2f55e7SToby Isaac indicesPoint_private(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, o, pInd); 3591*8d2f55e7SToby Isaac } 3592*8d2f55e7SToby Isaac } 3593*8d2f55e7SToby Isaac } 3594*8d2f55e7SToby Isaac } 3595*8d2f55e7SToby Isaac else if (matSize) { 3596*8d2f55e7SToby Isaac PetscInt cOff; 3597*8d2f55e7SToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 3598*8d2f55e7SToby Isaac 3599*8d2f55e7SToby Isaac numRowIndices = matSize / numColIndices; 3600*8d2f55e7SToby Isaac if (numRowIndices != dof) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Miscounted dofs"); 3601*8d2f55e7SToby Isaac ierr = DMGetWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr); 3602*8d2f55e7SToby Isaac ierr = DMGetWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr); 3603*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(cSec,p,&cOff);CHKERRQ(ierr); 3604*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 3605*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 3606*8d2f55e7SToby Isaac if (numFields) { 3607*8d2f55e7SToby Isaac PetscInt f; 3608*8d2f55e7SToby Isaac 3609*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3610*8d2f55e7SToby Isaac PetscInt fDof; 3611*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&fDof);CHKERRQ(ierr); 3612*8d2f55e7SToby Isaac offsets[f + 1] = fDof; 3613*8d2f55e7SToby Isaac for (a = 0; a < aDof; a++) { 3614*8d2f55e7SToby Isaac PetscInt anchor = anchors[a + aOff]; 3615*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr); 3616*8d2f55e7SToby Isaac newOffsets[f + 1] += fDof; 3617*8d2f55e7SToby Isaac } 3618*8d2f55e7SToby Isaac } 3619*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3620*8d2f55e7SToby Isaac offsets[f + 1] += offsets[f]; 3621*8d2f55e7SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 3622*8d2f55e7SToby Isaac newOffsets[f + 1] += newOffsets[f]; 3623*8d2f55e7SToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 3624*8d2f55e7SToby Isaac } 3625*8d2f55e7SToby Isaac indicesPointFields_private(cSec,p,cOff,offsetsCopy,PETSC_TRUE,0,rowIndices);CHKERRQ(ierr); 3626*8d2f55e7SToby Isaac for (a = 0; a < aDof; a++) { 3627*8d2f55e7SToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 3628*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 3629*8d2f55e7SToby Isaac indicesPointFields_private(localCoarse,anchor,lOff,newOffsetsCopy,PETSC_TRUE,0,colIndices);CHKERRQ(ierr); 3630*8d2f55e7SToby Isaac } 3631*8d2f55e7SToby Isaac } 3632*8d2f55e7SToby Isaac else { 3633*8d2f55e7SToby Isaac indicesPoint_private(cSec,p,cOff,offsetsCopy,PETSC_TRUE,0,rowIndices);CHKERRQ(ierr); 3634*8d2f55e7SToby Isaac for (a = 0; a < aDof; a++) { 3635*8d2f55e7SToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 3636*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr); 3637*8d2f55e7SToby Isaac indicesPoint_private(localCoarse,anchor,lOff,newOffsetsCopy,PETSC_TRUE,0,colIndices);CHKERRQ(ierr); 3638*8d2f55e7SToby Isaac } 3639*8d2f55e7SToby Isaac } 3640*8d2f55e7SToby Isaac if (numFields) { 3641*8d2f55e7SToby Isaac PetscInt count, f, a; 3642*8d2f55e7SToby Isaac for (f = 0, count = 0; f < numFields; f++) { 3643*8d2f55e7SToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 3644*8d2f55e7SToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 3645*8d2f55e7SToby Isaac ierr = MatGetValues(cMat,iSize,&rowIndices[offsets[f]],jSize,&colIndices[newOffsets[f]],&pMat[count]);CHKERRQ(ierr); 3646*8d2f55e7SToby Isaac count += iSize * jSize; 3647*8d2f55e7SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 3648*8d2f55e7SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 3649*8d2f55e7SToby Isaac } 3650*8d2f55e7SToby Isaac for (a = 0; a < aDof; a++) { 3651*8d2f55e7SToby Isaac PetscInt anchor = anchors[a + aOff]; 3652*8d2f55e7SToby Isaac PetscInt gOff; 3653*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 3654*8d2f55e7SToby Isaac indicesPointFields_private(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 3655*8d2f55e7SToby Isaac } 3656*8d2f55e7SToby Isaac } 3657*8d2f55e7SToby Isaac else { 3658*8d2f55e7SToby Isaac PetscInt a; 3659*8d2f55e7SToby Isaac ierr = MatGetValues(cMat,numRowIndices,rowIndices,numColIndices,colIndices,pMat);CHKERRQ(ierr); 3660*8d2f55e7SToby Isaac for (a = 0; a < aDof; a++) { 3661*8d2f55e7SToby Isaac PetscInt anchor = anchors[a + aOff]; 3662*8d2f55e7SToby Isaac PetscInt gOff; 3663*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr); 3664*8d2f55e7SToby Isaac indicesPoint_private(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 3665*8d2f55e7SToby Isaac } 3666*8d2f55e7SToby Isaac } 3667*8d2f55e7SToby Isaac ierr = DMRestoreWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr); 3668*8d2f55e7SToby Isaac ierr = DMRestoreWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr); 3669*8d2f55e7SToby Isaac } 3670*8d2f55e7SToby Isaac else { 3671*8d2f55e7SToby Isaac PetscInt gOff; 3672*8d2f55e7SToby Isaac 3673*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr); 3674*8d2f55e7SToby Isaac if (numFields) { 3675*8d2f55e7SToby Isaac PetscInt f; 3676*8d2f55e7SToby Isaac 3677*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3678*8d2f55e7SToby Isaac PetscInt fDof; 3679*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr); 3680*8d2f55e7SToby Isaac offsets[f + 1] = fDof + offsets[f]; 3681*8d2f55e7SToby Isaac } 3682*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3683*8d2f55e7SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 3684*8d2f55e7SToby Isaac pInd[numColIndices + numFields + f] = offsets[f+1]; 3685*8d2f55e7SToby Isaac } 3686*8d2f55e7SToby Isaac indicesPointFields_private(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 3687*8d2f55e7SToby Isaac } 3688*8d2f55e7SToby Isaac else { 3689*8d2f55e7SToby Isaac indicesPoint_private(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr); 3690*8d2f55e7SToby Isaac } 3691*8d2f55e7SToby Isaac } 3692*8d2f55e7SToby Isaac } 3693*8d2f55e7SToby Isaac ierr = PetscFree(maxChildIds);CHKERRQ(ierr); 3694*8d2f55e7SToby Isaac } 3695*8d2f55e7SToby Isaac { 3696*8d2f55e7SToby Isaac PetscSF indicesSF, matricesSF; 3697*8d2f55e7SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 3698*8d2f55e7SToby Isaac 3699*8d2f55e7SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr); 3700*8d2f55e7SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafMatricesSec);CHKERRQ(ierr); 3701*8d2f55e7SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootIndicesSec,&remoteOffsetsIndices,leafIndicesSec);CHKERRQ(ierr); 3702*8d2f55e7SToby Isaac ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootMatricesSec,&remoteOffsetsMatrices,leafMatricesSec);CHKERRQ(ierr); 3703*8d2f55e7SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootIndicesSec,remoteOffsetsIndices,leafIndicesSec,&indicesSF);CHKERRQ(ierr); 3704*8d2f55e7SToby Isaac ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootMatricesSec,remoteOffsetsMatrices,leafMatricesSec,&matricesSF);CHKERRQ(ierr); 3705*8d2f55e7SToby Isaac ierr = PetscSFDestroy(&coarseToFineEmbedded);CHKERRQ(ierr); 3706*8d2f55e7SToby Isaac ierr = PetscFree(remoteOffsetsIndices);CHKERRQ(ierr); 3707*8d2f55e7SToby Isaac ierr = PetscFree(remoteOffsetsMatrices);CHKERRQ(ierr); 3708*8d2f55e7SToby Isaac ierr = PetscSectionGetStorageSize(leafIndicesSec,&numLeafIndices);CHKERRQ(ierr); 3709*8d2f55e7SToby Isaac ierr = PetscSectionGetStorageSize(leafMatricesSec,&numLeafMatrices);CHKERRQ(ierr); 3710*8d2f55e7SToby Isaac ierr = PetscMalloc2(numLeafIndices,&leafIndices,numLeafMatrices,&leafMatrices);CHKERRQ(ierr); 3711*8d2f55e7SToby Isaac ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr); 3712*8d2f55e7SToby Isaac ierr = PetscSFBcastBegin(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices);CHKERRQ(ierr); 3713*8d2f55e7SToby Isaac ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr); 3714*8d2f55e7SToby Isaac ierr = PetscSFBcastEnd(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices);CHKERRQ(ierr); 3715*8d2f55e7SToby Isaac ierr = PetscSFDestroy(&matricesSF);CHKERRQ(ierr); 3716*8d2f55e7SToby Isaac ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr); 3717*8d2f55e7SToby Isaac ierr = PetscFree2(rootIndices,rootMatrices);CHKERRQ(ierr); 3718*8d2f55e7SToby Isaac ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr); 3719*8d2f55e7SToby Isaac ierr = PetscSectionDestroy(&rootMatricesSec);CHKERRQ(ierr); 3720*8d2f55e7SToby Isaac } 3721*8d2f55e7SToby Isaac /* count to preallocate */ 3722*8d2f55e7SToby Isaac ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr); 3723*8d2f55e7SToby Isaac { 3724*8d2f55e7SToby Isaac PetscInt nGlobal; 3725*8d2f55e7SToby Isaac PetscInt *dnnz, *onnz; 3726*8d2f55e7SToby Isaac PetscLayout rowMap, colMap; 3727*8d2f55e7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 3728*8d2f55e7SToby Isaac PetscInt maxDof; 3729*8d2f55e7SToby Isaac PetscInt *rowIndices; 3730*8d2f55e7SToby Isaac DM refTree; 3731*8d2f55e7SToby Isaac PetscInt **refPointFieldN; 3732*8d2f55e7SToby Isaac PetscScalar ***refPointFieldMats; 3733*8d2f55e7SToby Isaac PetscSection refConSec, refAnSec; 3734*8d2f55e7SToby Isaac PetscInt pRefStart,pRefEnd,maxConDof,maxColumns; 3735*8d2f55e7SToby Isaac PetscScalar *pointWork; 3736*8d2f55e7SToby Isaac 3737*8d2f55e7SToby Isaac ierr = PetscSectionGetConstrainedStorageSize(globalFine,&nGlobal);CHKERRQ(ierr); 3738*8d2f55e7SToby Isaac ierr = PetscCalloc2(nGlobal,&dnnz,nGlobal,&onnz);CHKERRQ(ierr); 3739*8d2f55e7SToby Isaac ierr = MatGetLayouts(mat,&rowMap,&colMap);CHKERRQ(ierr); 3740*8d2f55e7SToby Isaac ierr = PetscLayoutSetUp(rowMap);CHKERRQ(ierr); 3741*8d2f55e7SToby Isaac ierr = PetscLayoutSetUp(colMap);CHKERRQ(ierr); 3742*8d2f55e7SToby Isaac ierr = PetscLayoutGetRange(rowMap,&rowStart,&rowEnd);CHKERRQ(ierr); 3743*8d2f55e7SToby Isaac ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr); 3744*8d2f55e7SToby Isaac ierr = PetscSectionGetMaxDof(globalFine,&maxDof);CHKERRQ(ierr); 3745*8d2f55e7SToby Isaac ierr = DMGetWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 3746*8d2f55e7SToby Isaac for (p = pStartF; p < pEndF; p++) { 3747*8d2f55e7SToby Isaac PetscInt gDof, gcDof, gOff; 3748*8d2f55e7SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 3749*8d2f55e7SToby Isaac PetscInt matSize; 3750*8d2f55e7SToby Isaac PetscInt i; 3751*8d2f55e7SToby Isaac 3752*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 3753*8d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 3754*8d2f55e7SToby Isaac if ((gDof - gcDof) <= 0) { 3755*8d2f55e7SToby Isaac continue; 3756*8d2f55e7SToby Isaac } 3757*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 3758*8d2f55e7SToby Isaac if (gOff < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"I though having global dofs meant a non-negative offset"); 3759*8d2f55e7SToby 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"); 3760*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 3761*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 3762*8d2f55e7SToby Isaac numColIndices -= 2 * numFields; 3763*8d2f55e7SToby Isaac if (numColIndices <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"global fine dof with no dofs to interpolate from"); 3764*8d2f55e7SToby Isaac pInd = &leafIndices[pIndOff]; 3765*8d2f55e7SToby Isaac offsets[0] = 0; 3766*8d2f55e7SToby Isaac offsetsCopy[0] = 0; 3767*8d2f55e7SToby Isaac newOffsets[0] = 0; 3768*8d2f55e7SToby Isaac newOffsetsCopy[0] = 0; 3769*8d2f55e7SToby Isaac if (numFields) { 3770*8d2f55e7SToby Isaac PetscInt f; 3771*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3772*8d2f55e7SToby Isaac PetscInt rowDof; 3773*8d2f55e7SToby Isaac 3774*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 3775*8d2f55e7SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 3776*8d2f55e7SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 3777*8d2f55e7SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 3778*8d2f55e7SToby Isaac numD[f] = 0; 3779*8d2f55e7SToby Isaac numO[f] = 0; 3780*8d2f55e7SToby Isaac } 3781*8d2f55e7SToby Isaac ierr = indicesPointFields_private(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 3782*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3783*8d2f55e7SToby Isaac PetscInt colOffset = newOffsets[f]; 3784*8d2f55e7SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 3785*8d2f55e7SToby Isaac 3786*8d2f55e7SToby Isaac for (i = 0; i < numFieldCols; i++) { 3787*8d2f55e7SToby Isaac PetscInt gInd = pInd[i + colOffset]; 3788*8d2f55e7SToby Isaac 3789*8d2f55e7SToby Isaac if (gInd >= colStart && gInd < colEnd) { 3790*8d2f55e7SToby Isaac numD[f]++; 3791*8d2f55e7SToby Isaac } 3792*8d2f55e7SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 3793*8d2f55e7SToby Isaac numO[f]++; 3794*8d2f55e7SToby Isaac } 3795*8d2f55e7SToby Isaac } 3796*8d2f55e7SToby Isaac } 3797*8d2f55e7SToby Isaac } 3798*8d2f55e7SToby Isaac else { 3799*8d2f55e7SToby Isaac ierr = indicesPoint_private(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 3800*8d2f55e7SToby Isaac numD[0] = 0; 3801*8d2f55e7SToby Isaac numO[0] = 0; 3802*8d2f55e7SToby Isaac for (i = 0; i < numColIndices; i++) { 3803*8d2f55e7SToby Isaac PetscInt gInd = pInd[i]; 3804*8d2f55e7SToby Isaac 3805*8d2f55e7SToby Isaac if (gInd >= colStart && gInd < colEnd) { 3806*8d2f55e7SToby Isaac numD[0]++; 3807*8d2f55e7SToby Isaac } 3808*8d2f55e7SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 3809*8d2f55e7SToby Isaac numO[0]++; 3810*8d2f55e7SToby Isaac } 3811*8d2f55e7SToby Isaac } 3812*8d2f55e7SToby Isaac } 3813*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 3814*8d2f55e7SToby Isaac if (!matSize) { /* incoming matrix is identity */ 3815*8d2f55e7SToby Isaac PetscInt childId; 3816*8d2f55e7SToby Isaac 3817*8d2f55e7SToby Isaac childId = childIds[p-pStartF]; 3818*8d2f55e7SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 3819*8d2f55e7SToby Isaac if (numFields) { 3820*8d2f55e7SToby Isaac PetscInt f; 3821*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3822*8d2f55e7SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 3823*8d2f55e7SToby Isaac for (row = 0; row < numRows; row++) { 3824*8d2f55e7SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 3825*8d2f55e7SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 3826*8d2f55e7SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 3827*8d2f55e7SToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3828*8d2f55e7SToby Isaac dnnz[gIndFine - rowStart] = 1; 3829*8d2f55e7SToby Isaac } 3830*8d2f55e7SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 3831*8d2f55e7SToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3832*8d2f55e7SToby Isaac onnz[gIndFine - rowStart] = 1; 3833*8d2f55e7SToby Isaac } 3834*8d2f55e7SToby Isaac else { /* constrained */ 3835*8d2f55e7SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3836*8d2f55e7SToby Isaac } 3837*8d2f55e7SToby Isaac } 3838*8d2f55e7SToby Isaac } 3839*8d2f55e7SToby Isaac } 3840*8d2f55e7SToby Isaac else { 3841*8d2f55e7SToby Isaac PetscInt i; 3842*8d2f55e7SToby Isaac for (i = 0; i < gDof; i++) { 3843*8d2f55e7SToby Isaac PetscInt gIndCoarse = pInd[i]; 3844*8d2f55e7SToby Isaac PetscInt gIndFine = rowIndices[i]; 3845*8d2f55e7SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 3846*8d2f55e7SToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3847*8d2f55e7SToby Isaac dnnz[gIndFine - rowStart] = 1; 3848*8d2f55e7SToby Isaac } 3849*8d2f55e7SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 3850*8d2f55e7SToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3851*8d2f55e7SToby Isaac onnz[gIndFine - rowStart] = 1; 3852*8d2f55e7SToby Isaac } 3853*8d2f55e7SToby Isaac else { /* constrained */ 3854*8d2f55e7SToby Isaac if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3855*8d2f55e7SToby Isaac } 3856*8d2f55e7SToby Isaac } 3857*8d2f55e7SToby Isaac } 3858*8d2f55e7SToby Isaac } 3859*8d2f55e7SToby Isaac else { /* interpolate from all */ 3860*8d2f55e7SToby Isaac if (numFields) { 3861*8d2f55e7SToby Isaac PetscInt f; 3862*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3863*8d2f55e7SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 3864*8d2f55e7SToby Isaac for (row = 0; row < numRows; row++) { 3865*8d2f55e7SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 3866*8d2f55e7SToby Isaac if (gIndFine >= 0) { 3867*8d2f55e7SToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3868*8d2f55e7SToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 3869*8d2f55e7SToby Isaac onnz[gIndFine - rowStart] = numO[f]; 3870*8d2f55e7SToby Isaac } 3871*8d2f55e7SToby Isaac } 3872*8d2f55e7SToby Isaac } 3873*8d2f55e7SToby Isaac } 3874*8d2f55e7SToby Isaac else { 3875*8d2f55e7SToby Isaac PetscInt i; 3876*8d2f55e7SToby Isaac for (i = 0; i < gDof; i++) { 3877*8d2f55e7SToby Isaac PetscInt gIndFine = rowIndices[i]; 3878*8d2f55e7SToby Isaac if (gIndFine >= 0) { 3879*8d2f55e7SToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3880*8d2f55e7SToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 3881*8d2f55e7SToby Isaac onnz[gIndFine - rowStart] = numO[0]; 3882*8d2f55e7SToby Isaac } 3883*8d2f55e7SToby Isaac } 3884*8d2f55e7SToby Isaac } 3885*8d2f55e7SToby Isaac } 3886*8d2f55e7SToby Isaac } 3887*8d2f55e7SToby Isaac else { /* interpolate from all */ 3888*8d2f55e7SToby Isaac if (numFields) { 3889*8d2f55e7SToby Isaac PetscInt f; 3890*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3891*8d2f55e7SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 3892*8d2f55e7SToby Isaac for (row = 0; row < numRows; row++) { 3893*8d2f55e7SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 3894*8d2f55e7SToby Isaac if (gIndFine >= 0) { 3895*8d2f55e7SToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3896*8d2f55e7SToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 3897*8d2f55e7SToby Isaac onnz[gIndFine - rowStart] = numO[f]; 3898*8d2f55e7SToby Isaac } 3899*8d2f55e7SToby Isaac } 3900*8d2f55e7SToby Isaac } 3901*8d2f55e7SToby Isaac } 3902*8d2f55e7SToby Isaac else { /* every dof get a full row */ 3903*8d2f55e7SToby Isaac PetscInt i; 3904*8d2f55e7SToby Isaac for (i = 0; i < gDof; i++) { 3905*8d2f55e7SToby Isaac PetscInt gIndFine = rowIndices[i]; 3906*8d2f55e7SToby Isaac if (gIndFine >= 0) { 3907*8d2f55e7SToby Isaac if (gIndFine < rowStart || gIndFine >= rowEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 3908*8d2f55e7SToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 3909*8d2f55e7SToby Isaac onnz[gIndFine - rowStart] = numO[0]; 3910*8d2f55e7SToby Isaac } 3911*8d2f55e7SToby Isaac } 3912*8d2f55e7SToby Isaac } 3913*8d2f55e7SToby Isaac } 3914*8d2f55e7SToby Isaac } 3915*8d2f55e7SToby Isaac ierr = MatXAIJSetPreallocation(mat,1,dnnz,onnz,NULL,NULL);CHKERRQ(ierr); 3916*8d2f55e7SToby Isaac ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 3917*8d2f55e7SToby Isaac 3918*8d2f55e7SToby Isaac ierr = DMPlexGetReferenceTree(fine,&refTree);CHKERRQ(ierr); 3919*8d2f55e7SToby Isaac ierr = DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 3920*8d2f55e7SToby Isaac ierr = DMGetDefaultConstraints(refTree,&refConSec,NULL);CHKERRQ(ierr); 3921*8d2f55e7SToby Isaac ierr = DMPlexGetAnchors(refTree,&refAnSec,NULL);CHKERRQ(ierr); 3922*8d2f55e7SToby Isaac ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr); 3923*8d2f55e7SToby Isaac ierr = PetscSectionGetMaxDof(refConSec,&maxConDof);CHKERRQ(ierr); 3924*8d2f55e7SToby Isaac ierr = PetscSectionGetMaxDof(leafIndicesSec,&maxColumns);CHKERRQ(ierr); 3925*8d2f55e7SToby Isaac ierr = PetscMalloc1(maxConDof*maxColumns,&pointWork);CHKERRQ(ierr); 3926*8d2f55e7SToby Isaac for (p = pStartF; p < pEndF; p++) { 3927*8d2f55e7SToby Isaac PetscInt gDof, gcDof, gOff; 3928*8d2f55e7SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 3929*8d2f55e7SToby Isaac PetscInt matSize; 3930*8d2f55e7SToby Isaac PetscInt childId; 3931*8d2f55e7SToby Isaac 3932*8d2f55e7SToby Isaac 3933*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr); 3934*8d2f55e7SToby Isaac ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr); 3935*8d2f55e7SToby Isaac if ((gDof - gcDof) <= 0) { 3936*8d2f55e7SToby Isaac continue; 3937*8d2f55e7SToby Isaac } 3938*8d2f55e7SToby Isaac childId = childIds[p-pStartF]; 3939*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr); 3940*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr); 3941*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr); 3942*8d2f55e7SToby Isaac numColIndices -= 2 * numFields; 3943*8d2f55e7SToby Isaac pInd = &leafIndices[pIndOff]; 3944*8d2f55e7SToby Isaac offsets[0] = 0; 3945*8d2f55e7SToby Isaac offsetsCopy[0] = 0; 3946*8d2f55e7SToby Isaac newOffsets[0] = 0; 3947*8d2f55e7SToby Isaac newOffsetsCopy[0] = 0; 3948*8d2f55e7SToby Isaac rowOffsets[0] = 0; 3949*8d2f55e7SToby Isaac if (numFields) { 3950*8d2f55e7SToby Isaac PetscInt f; 3951*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3952*8d2f55e7SToby Isaac PetscInt rowDof; 3953*8d2f55e7SToby Isaac 3954*8d2f55e7SToby Isaac ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr); 3955*8d2f55e7SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 3956*8d2f55e7SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 3957*8d2f55e7SToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 3958*8d2f55e7SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 3959*8d2f55e7SToby Isaac } 3960*8d2f55e7SToby Isaac ierr = indicesPointFields_private(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 3961*8d2f55e7SToby Isaac } 3962*8d2f55e7SToby Isaac else { 3963*8d2f55e7SToby Isaac ierr = indicesPoint_private(localFine,p,gOff,offsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr); 3964*8d2f55e7SToby Isaac } 3965*8d2f55e7SToby Isaac ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr); 3966*8d2f55e7SToby Isaac if (!matSize) { /* incoming matrix is identity */ 3967*8d2f55e7SToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 3968*8d2f55e7SToby Isaac if (numFields) { 3969*8d2f55e7SToby Isaac PetscInt f; 3970*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3971*8d2f55e7SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 3972*8d2f55e7SToby Isaac for (row = 0; row < numRows; row++) { 3973*8d2f55e7SToby Isaac ierr = MatSetValue(mat,rowIndices[offsets[f]+row],pInd[newOffsets[f]+row],1.,INSERT_VALUES);CHKERRQ(ierr); 3974*8d2f55e7SToby Isaac } 3975*8d2f55e7SToby Isaac } 3976*8d2f55e7SToby Isaac } 3977*8d2f55e7SToby Isaac else { 3978*8d2f55e7SToby Isaac PetscInt numRows = gDof, row; 3979*8d2f55e7SToby Isaac for (row = 0; row < numRows; row++) { 3980*8d2f55e7SToby Isaac ierr = MatSetValue(mat,rowIndices[row],pInd[row],1.,INSERT_VALUES);CHKERRQ(ierr); 3981*8d2f55e7SToby Isaac } 3982*8d2f55e7SToby Isaac } 3983*8d2f55e7SToby Isaac } 3984*8d2f55e7SToby Isaac else { /* interpolate from all */ 3985*8d2f55e7SToby Isaac if (numFields) { 3986*8d2f55e7SToby Isaac PetscInt f; 3987*8d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3988*8d2f55e7SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 3989*8d2f55e7SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 3990*8d2f55e7SToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],refPointFieldMats[childId - pRefStart][f],INSERT_VALUES);CHKERRQ(ierr); 3991*8d2f55e7SToby Isaac } 3992*8d2f55e7SToby Isaac } 3993*8d2f55e7SToby Isaac else { 3994*8d2f55e7SToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,refPointFieldMats[childId - pRefStart][0],INSERT_VALUES);CHKERRQ(ierr); 3995*8d2f55e7SToby Isaac } 3996*8d2f55e7SToby Isaac } 3997*8d2f55e7SToby Isaac } 3998*8d2f55e7SToby Isaac else { /* interpolate from all */ 3999*8d2f55e7SToby Isaac PetscInt pMatOff; 4000*8d2f55e7SToby Isaac PetscScalar *pMat; 4001*8d2f55e7SToby Isaac 4002*8d2f55e7SToby Isaac ierr = PetscSectionGetOffset(leafMatricesSec,p,&pMatOff);CHKERRQ(ierr); 4003*8d2f55e7SToby Isaac pMat = &leafMatrices[pMatOff]; 4004*8d2f55e7SToby Isaac if (childId < 0) { /* copy the incoming matrix */ 4005*8d2f55e7SToby Isaac if (numFields) { 4006*8d2f55e7SToby Isaac PetscInt f, count; 4007*8d2f55e7SToby Isaac for (f = 0, count = 0; f < numFields; f++) { 4008*8d2f55e7SToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 4009*8d2f55e7SToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 4010*8d2f55e7SToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 4011*8d2f55e7SToby Isaac PetscScalar *inMat = &pMat[count]; 4012*8d2f55e7SToby Isaac 4013*8d2f55e7SToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],inMat,INSERT_VALUES);CHKERRQ(ierr); 4014*8d2f55e7SToby Isaac count += numCols * numInRows; 4015*8d2f55e7SToby Isaac } 4016*8d2f55e7SToby Isaac } 4017*8d2f55e7SToby Isaac else { 4018*8d2f55e7SToby Isaac ierr = MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,pMat,INSERT_VALUES);CHKERRQ(ierr); 4019*8d2f55e7SToby Isaac } 4020*8d2f55e7SToby Isaac } 4021*8d2f55e7SToby Isaac else { /* multiply the incoming matrix by the child interpolation */ 4022*8d2f55e7SToby Isaac if (numFields) { 4023*8d2f55e7SToby Isaac PetscInt f, count; 4024*8d2f55e7SToby Isaac for (f = 0, count = 0; f < numFields; f++) { 4025*8d2f55e7SToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 4026*8d2f55e7SToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 4027*8d2f55e7SToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 4028*8d2f55e7SToby Isaac PetscScalar *inMat = &pMat[count]; 4029*8d2f55e7SToby Isaac PetscInt i, j, k; 4030*8d2f55e7SToby Isaac if (refPointFieldN[childId - pRefStart][f] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 4031*8d2f55e7SToby Isaac for (i = 0; i < numRows; i++) { 4032*8d2f55e7SToby Isaac for (j = 0; j < numCols; j++) { 4033*8d2f55e7SToby Isaac PetscScalar val = 0.; 4034*8d2f55e7SToby Isaac for (k = 0; k < numInRows; k++) { 4035*8d2f55e7SToby Isaac val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 4036*8d2f55e7SToby Isaac } 4037*8d2f55e7SToby Isaac pointWork[i * numCols + j] = val; 4038*8d2f55e7SToby Isaac } 4039*8d2f55e7SToby Isaac } 4040*8d2f55e7SToby Isaac ierr = MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],pointWork,INSERT_VALUES);CHKERRQ(ierr); 4041*8d2f55e7SToby Isaac count += numCols * numInRows; 4042*8d2f55e7SToby Isaac } 4043*8d2f55e7SToby Isaac } 4044*8d2f55e7SToby Isaac else { /* every dof gets a full row */ 4045*8d2f55e7SToby Isaac PetscInt numRows = gDof; 4046*8d2f55e7SToby Isaac PetscInt numCols = numColIndices; 4047*8d2f55e7SToby Isaac PetscInt numInRows = matSize / numColIndices; 4048*8d2f55e7SToby Isaac PetscInt i, j, k; 4049*8d2f55e7SToby Isaac if (refPointFieldN[childId - pRefStart][0] != numInRows) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 4050*8d2f55e7SToby Isaac for (i = 0; i < numRows; i++) { 4051*8d2f55e7SToby Isaac for (j = 0; j < numCols; j++) { 4052*8d2f55e7SToby Isaac PetscScalar val = 0.; 4053*8d2f55e7SToby Isaac for (k = 0; k < numInRows; k++) { 4054*8d2f55e7SToby Isaac val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 4055*8d2f55e7SToby Isaac } 4056*8d2f55e7SToby Isaac pointWork[i * numCols + j] = val; 4057*8d2f55e7SToby Isaac } 4058*8d2f55e7SToby Isaac } 4059*8d2f55e7SToby Isaac ierr = MatSetValues(mat,numRows,rowIndices,numCols,pInd,pointWork,INSERT_VALUES);CHKERRQ(ierr); 4060*8d2f55e7SToby Isaac } 4061*8d2f55e7SToby Isaac } 4062*8d2f55e7SToby Isaac } 4063*8d2f55e7SToby Isaac } 4064*8d2f55e7SToby Isaac ierr = DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN);CHKERRQ(ierr); 4065*8d2f55e7SToby Isaac ierr = DMRestoreWorkArray(fine,maxDof,PETSC_INT,&rowIndices);CHKERRQ(ierr); 4066*8d2f55e7SToby Isaac ierr = PetscFree(pointWork);CHKERRQ(ierr); 4067*8d2f55e7SToby Isaac } 4068*8d2f55e7SToby Isaac ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4069*8d2f55e7SToby Isaac ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4070*8d2f55e7SToby Isaac ierr = PetscSectionDestroy(&leafIndicesSec);CHKERRQ(ierr); 4071*8d2f55e7SToby Isaac ierr = PetscSectionDestroy(&leafMatricesSec);CHKERRQ(ierr); 4072*8d2f55e7SToby Isaac ierr = PetscFree2(leafIndices,leafMatrices);CHKERRQ(ierr); 4073*8d2f55e7SToby Isaac ierr = PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO);CHKERRQ(ierr); 4074*8d2f55e7SToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4075154bca37SToby Isaac PetscFunctionReturn(0); 4076154bca37SToby Isaac } 4077