1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/isimpl.h> 3af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 4d6a7ad0dSToby Isaac #include <petscsf.h> 50c37af3bSToby Isaac #include <petscds.h> 6d6a7ad0dSToby Isaac 70e3d61c9SBarry Smith /* hierarchy routines */ 8d6a7ad0dSToby Isaac 9d6a7ad0dSToby Isaac /*@ 10d6a7ad0dSToby Isaac DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes. 11d6a7ad0dSToby Isaac 12d6a7ad0dSToby Isaac Not collective 13d6a7ad0dSToby Isaac 14d6a7ad0dSToby Isaac Input Parameters: 15d6a7ad0dSToby Isaac + dm - The DMPlex object 16d6a7ad0dSToby Isaac - ref - The reference tree DMPlex object 17d6a7ad0dSToby Isaac 180b7167a0SToby Isaac Level: intermediate 19d6a7ad0dSToby Isaac 20da43764aSToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexCreateDefaultReferenceTree() 21d6a7ad0dSToby Isaac @*/ 22d6a7ad0dSToby Isaac PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 23d6a7ad0dSToby Isaac { 24d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 25d6a7ad0dSToby Isaac 26d6a7ad0dSToby Isaac PetscFunctionBegin; 27d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2847a1df27SMatthew G. Knepley if (ref) {PetscValidHeaderSpecific(ref, DM_CLASSID, 2);} 295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)ref)); 305f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&mesh->referenceTree)); 31d6a7ad0dSToby Isaac mesh->referenceTree = ref; 32d6a7ad0dSToby Isaac PetscFunctionReturn(0); 33d6a7ad0dSToby Isaac } 34d6a7ad0dSToby Isaac 35d6a7ad0dSToby Isaac /*@ 36d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 37d6a7ad0dSToby Isaac 38d6a7ad0dSToby Isaac Not collective 39d6a7ad0dSToby Isaac 40d6a7ad0dSToby Isaac Input Parameters: 41d6a7ad0dSToby Isaac . dm - The DMPlex object 42d6a7ad0dSToby Isaac 437a7aea1fSJed Brown Output Parameters: 44d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 45d6a7ad0dSToby Isaac 460b7167a0SToby Isaac Level: intermediate 47d6a7ad0dSToby Isaac 48da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexCreateDefaultReferenceTree() 49d6a7ad0dSToby Isaac @*/ 50d6a7ad0dSToby Isaac PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 51d6a7ad0dSToby Isaac { 52d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 53d6a7ad0dSToby Isaac 54d6a7ad0dSToby Isaac PetscFunctionBegin; 55d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56d6a7ad0dSToby Isaac PetscValidPointer(ref,2); 57d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 58d6a7ad0dSToby Isaac PetscFunctionReturn(0); 59d6a7ad0dSToby Isaac } 60d6a7ad0dSToby Isaac 61dcbd3bf7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 62dcbd3bf7SToby Isaac { 63dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 64dcbd3bf7SToby Isaac 65dcbd3bf7SToby Isaac PetscFunctionBegin; 66dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) { 67dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA; 68dcbd3bf7SToby Isaac if (childB) *childB = childA; 69dcbd3bf7SToby Isaac PetscFunctionReturn(0); 70dcbd3bf7SToby Isaac } 71dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) { 725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd)); 73dcbd3bf7SToby Isaac if (parent >= dStart && parent <= dEnd) { 74dcbd3bf7SToby Isaac break; 75dcbd3bf7SToby Isaac } 76dcbd3bf7SToby Isaac } 772c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim > 2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %d-cells",dim); 78*28b400f6SJacob Faibussowitsch PetscCheck(dim,PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 79dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) { 80dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */ 81dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 82dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB; 83dcbd3bf7SToby Isaac 845f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm,childA,&size)); 855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm,childA,&supp)); 86dcbd3bf7SToby Isaac 87dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */ 88dcbd3bf7SToby Isaac for (i = 0; i < size; i++) { 89dcbd3bf7SToby Isaac PetscInt sParent; 90dcbd3bf7SToby Isaac 91dcbd3bf7SToby Isaac sA = supp[i]; 92dcbd3bf7SToby Isaac if (sA == parent) continue; 935f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,sA,&sParent,NULL)); 94dcbd3bf7SToby Isaac if (sParent == parent) { 95dcbd3bf7SToby Isaac break; 96dcbd3bf7SToby Isaac } 97dcbd3bf7SToby Isaac } 982c71b3e2SJacob Faibussowitsch PetscCheckFalse(i == size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 99dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under 100dcbd3bf7SToby Isaac * parentOrientB */ 1015f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetChildSymmetry_Default(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB)); 1025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,sA,&sConeSize)); 1035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm,sA,&coneA)); 1045f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm,sB,&coneB)); 1055f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm,sA,&oA)); 1065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm,sB,&oB)); 107dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */ 108dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) { 109dcbd3bf7SToby Isaac if (coneA[i] == childA) { 110dcbd3bf7SToby Isaac /* if childA is at position i in coneA, 111dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */ 112dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 113dcbd3bf7SToby Isaac if (childB) *childB = coneB[j]; 114dcbd3bf7SToby Isaac if (childOrientB) { 115b5a892a1SMatthew G. Knepley DMPolytopeType ct; 116dcbd3bf7SToby Isaac PetscInt oBtrue; 117dcbd3bf7SToby Isaac 1185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,childA,&coneSize)); 119dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */ 1202c71b3e2SJacob Faibussowitsch PetscCheckFalse(coneSize != 0 && coneSize != 2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 121b5a892a1SMatthew G. Knepley ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 122dcbd3bf7SToby Isaac /* we may have to flip an edge */ 123b5a892a1SMatthew G. Knepley oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientation(ct, -1, oB[j]); 124b5a892a1SMatthew G. Knepley oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 125b5a892a1SMatthew G. Knepley ABswap = DihedralSwap(coneSize,DMPolytopeConvertNewOrientation_Internal(ct, oA[i]),oBtrue); 126dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 127dcbd3bf7SToby Isaac } 128dcbd3bf7SToby Isaac break; 129dcbd3bf7SToby Isaac } 130dcbd3bf7SToby Isaac } 1312c71b3e2SJacob Faibussowitsch PetscCheckFalse(i == sConeSize,PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 132dcbd3bf7SToby Isaac PetscFunctionReturn(0); 133dcbd3bf7SToby Isaac } 134dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */ 1355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,parent,&coneSize)); 136dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 137dcbd3bf7SToby Isaac if (dim == 2) { 138dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices: 139dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a 140dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */ 141dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 142dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 143dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 144947b95d8SBarry Smith } else { 145dcbd3bf7SToby Isaac ABswapVert = ABswap; 146dcbd3bf7SToby Isaac } 147dcbd3bf7SToby Isaac if (childB) { 148dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */ 149dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i; 150dcbd3bf7SToby Isaac const PetscInt *children; 151dcbd3bf7SToby Isaac 152dcbd3bf7SToby Isaac /* count which position the child is in */ 1535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm,parent,&numChildren,&children)); 154dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) { 155dcbd3bf7SToby Isaac p = children[i]; 156dcbd3bf7SToby Isaac if (p == childA) { 157dcbd3bf7SToby Isaac posA = i; 158dcbd3bf7SToby Isaac break; 159dcbd3bf7SToby Isaac } 160dcbd3bf7SToby Isaac } 161dcbd3bf7SToby Isaac if (posA >= coneSize) { 162dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it 163dcbd3bf7SToby Isaac * is invariant */ 1642c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim != 2 || posA != 3,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Expected a middle triangle, got something else"); 165dcbd3bf7SToby Isaac *childB = childA; 166dcbd3bf7SToby Isaac } 167dcbd3bf7SToby Isaac else { 168dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */ 169dcbd3bf7SToby Isaac PetscInt posB; 170dcbd3bf7SToby Isaac 171dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 172dcbd3bf7SToby Isaac if (childB) *childB = children[posB]; 173dcbd3bf7SToby Isaac } 174dcbd3bf7SToby Isaac } 175dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 176dcbd3bf7SToby Isaac PetscFunctionReturn(0); 177dcbd3bf7SToby Isaac } 178dcbd3bf7SToby Isaac 179dcbd3bf7SToby Isaac /*@ 180dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another 181dcbd3bf7SToby Isaac 182dcbd3bf7SToby Isaac Input Parameters: 183dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object 184dcbd3bf7SToby Isaac . parent - the parent point 185dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent 186dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child 187dcbd3bf7SToby Isaac . childA - the reference childID for describing the child 188dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent 189dcbd3bf7SToby Isaac 190dcbd3bf7SToby Isaac Output Parameters: 191dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child 192ff1f73f7SToby Isaac - childB - if not NULL, the new childID for describing the child 193dcbd3bf7SToby Isaac 194dcbd3bf7SToby Isaac Level: developer 195dcbd3bf7SToby Isaac 196dcbd3bf7SToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexSetReferenceTree(), DMPlexSetTree() 197dcbd3bf7SToby Isaac @*/ 198dcbd3bf7SToby Isaac PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 199dcbd3bf7SToby Isaac { 200dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 201dcbd3bf7SToby Isaac 202dcbd3bf7SToby Isaac PetscFunctionBegin; 203dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 204*28b400f6SJacob Faibussowitsch PetscCheck(mesh->getchildsymmetry,PETSC_COMM_SELF,PETSC_ERR_SUP,"DMPlexReferenceTreeGetChildSymmetry not implemented"); 2055f80ce2aSJacob Faibussowitsch CHKERRQ(mesh->getchildsymmetry(dm,parent,parentOrientA,childOrientA,childA,parentOrientB,childOrientB,childB)); 206dcbd3bf7SToby Isaac PetscFunctionReturn(0); 207dcbd3bf7SToby Isaac } 208dcbd3bf7SToby Isaac 209776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM,PetscSection,PetscInt*,PetscInt*,PetscBool,PetscBool); 210f9f063d4SToby Isaac 211f2c1aa1dSLisandro Dalcin PetscErrorCode DMPlexCreateReferenceTree_SetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 212f2c1aa1dSLisandro Dalcin { 213f2c1aa1dSLisandro Dalcin PetscFunctionBegin; 2145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_TRUE,PETSC_FALSE)); 215f2c1aa1dSLisandro Dalcin PetscFunctionReturn(0); 216f2c1aa1dSLisandro Dalcin } 217f2c1aa1dSLisandro Dalcin 2180e2cc29aSToby Isaac PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref) 219da43764aSToby Isaac { 2200e2cc29aSToby Isaac MPI_Comm comm; 2210e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 222da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 223da43764aSToby Isaac DMLabel identity, identityRef; 22410f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 225da43764aSToby Isaac PetscScalar *unionCoords; 226da43764aSToby Isaac IS perm; 227da43764aSToby Isaac 228da43764aSToby Isaac PetscFunctionBegin; 2290e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K); 2305f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(K, &dim)); 2315f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(K, &pStart, &pEnd)); 2325f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(K, labelName, &identity)); 2335f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(Kref, labelName, &identityRef)); 2345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(Kref, &pRefStart, &pRefEnd)); 2355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &unionSection)); 2365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart))); 237da43764aSToby Isaac /* count points that will go in the union */ 238da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 2395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(unionSection, p - pStart, 1)); 240da43764aSToby Isaac } 241da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 242da43764aSToby Isaac PetscInt q, qSize; 2435f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(identityRef, p, &q)); 2445f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumSize(identityRef, q, &qSize)); 245da43764aSToby Isaac if (qSize > 1) { 2465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1)); 247da43764aSToby Isaac } 248da43764aSToby Isaac } 2495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart,&permvals)); 250da43764aSToby Isaac offset = 0; 251da43764aSToby Isaac /* stratify points in the union by topological dimension */ 252da43764aSToby Isaac for (d = 0; d <= dim; d++) { 253da43764aSToby Isaac PetscInt cStart, cEnd, c; 254da43764aSToby Isaac 2555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(K, d, &cStart, &cEnd)); 256da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 257da43764aSToby Isaac permvals[offset++] = c; 258da43764aSToby Isaac } 259da43764aSToby Isaac 2605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd)); 261da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 262da43764aSToby Isaac permvals[offset++] = c + (pEnd - pStart); 263da43764aSToby Isaac } 264da43764aSToby Isaac } 2655f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm)); 2665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetPermutation(unionSection,perm)); 2675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(unionSection)); 2685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(unionSection,&numUnionPoints)); 2695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints)); 270da43764aSToby Isaac /* count dimension points */ 271da43764aSToby Isaac for (d = 0; d <= dim; d++) { 272da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 2735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(K,d,&cStart,NULL)); 2745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection,cStart-pStart,&cOff)); 275da43764aSToby Isaac if (d < dim) { 2765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(K,d+1,&cStart,NULL)); 2775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2)); 278da43764aSToby Isaac } 279da43764aSToby Isaac else { 280da43764aSToby Isaac cOff2 = numUnionPoints; 281da43764aSToby Isaac } 282da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 283da43764aSToby Isaac } 2845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &unionConeSection)); 2855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(unionConeSection, 0, numUnionPoints)); 286da43764aSToby Isaac /* count the cones in the union */ 287da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 288da43764aSToby Isaac PetscInt dof, uOff; 289da43764aSToby Isaac 2905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(K, p, &dof)); 2915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, p - pStart,&uOff)); 2925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(unionConeSection, uOff, dof)); 293da43764aSToby Isaac coneSizes[uOff] = dof; 294da43764aSToby Isaac } 295da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 296da43764aSToby Isaac PetscInt dof, uDof, uOff; 297da43764aSToby Isaac 2985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(Kref, p, &dof)); 2995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof)); 3005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff)); 301da43764aSToby Isaac if (uDof) { 3025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(unionConeSection, uOff, dof)); 303da43764aSToby Isaac coneSizes[uOff] = dof; 304da43764aSToby Isaac } 305da43764aSToby Isaac } 3065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(unionConeSection)); 3075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(unionConeSection,&numCones)); 3085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations)); 309da43764aSToby Isaac /* write the cones in the union */ 310da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 311da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 312da43764aSToby Isaac const PetscInt *cone, *orientation; 313da43764aSToby Isaac 3145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(K, p, &dof)); 3155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(K, p, &cone)); 3165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(K, p, &orientation)); 3175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, p - pStart,&uOff)); 3185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionConeSection,uOff,&cOff)); 319da43764aSToby Isaac for (c = 0; c < dof; c++) { 320da43764aSToby Isaac PetscInt e, eOff; 321da43764aSToby Isaac e = cone[c]; 3225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 323da43764aSToby Isaac unionCones[cOff + c] = eOff; 324da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 325da43764aSToby Isaac } 326da43764aSToby Isaac } 327da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 328da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 329da43764aSToby Isaac const PetscInt *cone, *orientation; 330da43764aSToby Isaac 3315f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(Kref, p, &dof)); 3325f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(Kref, p, &cone)); 3335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(Kref, p, &orientation)); 3345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof)); 3355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff)); 336da43764aSToby Isaac if (uDof) { 3375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionConeSection,uOff,&cOff)); 338da43764aSToby Isaac for (c = 0; c < dof; c++) { 339da43764aSToby Isaac PetscInt e, eOff, eDof; 340da43764aSToby Isaac 341da43764aSToby Isaac e = cone[c]; 3425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof)); 343da43764aSToby Isaac if (eDof) { 3445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff)); 345da43764aSToby Isaac } 346da43764aSToby Isaac else { 3475f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(identityRef, e, &e)); 3485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, e - pStart, &eOff)); 349da43764aSToby Isaac } 350da43764aSToby Isaac unionCones[cOff + c] = eOff; 351da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 352da43764aSToby Isaac } 353da43764aSToby Isaac } 354da43764aSToby Isaac } 355da43764aSToby Isaac /* get the coordinates */ 356da43764aSToby Isaac { 357da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 358da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 359da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 360da43764aSToby Isaac PetscScalar *Kcoords; 361da43764aSToby Isaac 3625f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(K, &KcoordsSec)); 3635f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(K, &KcoordsVec)); 3645f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(Kref, &KrefCoordsSec)); 3655f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(Kref, &KrefCoordsVec)); 366da43764aSToby Isaac 367da43764aSToby Isaac numVerts = numDimPoints[0]; 3685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numVerts * dim,&unionCoords)); 3695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(K,0,&vStart,&vEnd)); 370da43764aSToby Isaac 371da43764aSToby Isaac offset = 0; 372da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 3735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection,v - pStart,&vOff)); 3745f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords)); 375da43764aSToby Isaac for (d = 0; d < dim; d++) { 376da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 377da43764aSToby Isaac } 378da43764aSToby Isaac offset++; 379da43764aSToby Isaac } 3805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd)); 381da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 3825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof)); 3835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff)); 3845f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords)); 385da43764aSToby Isaac if (vDof) { 386da43764aSToby Isaac for (d = 0; d < dim; d++) { 387da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 388da43764aSToby Isaac } 389da43764aSToby Isaac offset++; 390da43764aSToby Isaac } 391da43764aSToby Isaac } 392da43764aSToby Isaac } 3935f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm,ref)); 3945f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*ref,DMPLEX)); 3955f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*ref,dim)); 3965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords)); 39710f7e118SToby Isaac /* set the tree */ 3985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm,&parentSection)); 3995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(parentSection,0,numUnionPoints)); 40010f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 40110f7e118SToby Isaac PetscInt uDof, uOff; 40210f7e118SToby Isaac 4035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof)); 4045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff)); 40510f7e118SToby Isaac if (uDof) { 4065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(parentSection,uOff,1)); 40710f7e118SToby Isaac } 40810f7e118SToby Isaac } 4095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(parentSection)); 4105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(parentSection,&parentSize)); 4115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(parentSize,&parents,parentSize,&childIDs)); 41210f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 41310f7e118SToby Isaac PetscInt uDof, uOff; 41410f7e118SToby Isaac 4155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof)); 4165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff)); 41710f7e118SToby Isaac if (uDof) { 41810f7e118SToby Isaac PetscInt pOff, parent, parentU; 4195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(parentSection,uOff,&pOff)); 4205f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(identityRef,p,&parent)); 4215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(unionSection, parent - pStart,&parentU)); 42210f7e118SToby Isaac parents[pOff] = parentU; 42310f7e118SToby Isaac childIDs[pOff] = uOff; 42410f7e118SToby Isaac } 42510f7e118SToby Isaac } 4265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateReferenceTree_SetTree(*ref,parentSection,parents,childIDs)); 4275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&parentSection)); 4285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(parents,childIDs)); 42910f7e118SToby Isaac 430da43764aSToby Isaac /* clean up */ 4315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&unionSection)); 4325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&unionConeSection)); 4335f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&perm)); 4345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(unionCoords)); 4355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(unionCones,unionOrientations)); 4365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(coneSizes,numDimPoints)); 4370e2cc29aSToby Isaac PetscFunctionReturn(0); 4380e2cc29aSToby Isaac } 4390e2cc29aSToby Isaac 4400e2cc29aSToby Isaac /*@ 4410e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 4420e2cc29aSToby Isaac 443d083f849SBarry Smith Collective 4440e2cc29aSToby Isaac 4450e2cc29aSToby Isaac Input Parameters: 4460e2cc29aSToby Isaac + comm - the MPI communicator 4470e2cc29aSToby Isaac . dim - the spatial dimension 4480e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 4490e2cc29aSToby Isaac 4500e2cc29aSToby Isaac Output Parameters: 4510e2cc29aSToby Isaac . ref - the reference tree DMPlex object 4520e2cc29aSToby Isaac 4530e2cc29aSToby Isaac Level: intermediate 4540e2cc29aSToby Isaac 4550e2cc29aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree() 4560e2cc29aSToby Isaac @*/ 4570e2cc29aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 4580e2cc29aSToby Isaac { 4590e2cc29aSToby Isaac DM_Plex *mesh; 4600e2cc29aSToby Isaac DM K, Kref; 4610e2cc29aSToby Isaac PetscInt p, pStart, pEnd; 4620e2cc29aSToby Isaac DMLabel identity; 4630e2cc29aSToby Isaac 4640e2cc29aSToby Isaac PetscFunctionBegin; 4650e2cc29aSToby Isaac #if 1 4660e2cc29aSToby Isaac comm = PETSC_COMM_SELF; 4670e2cc29aSToby Isaac #endif 4680e2cc29aSToby Isaac /* create a reference element */ 4695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateReferenceCell(comm, DMPolytopeTypeSimpleShape(dim, simplex), &K)); 4705f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(K, "identity")); 4715f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(K, "identity", &identity)); 4725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(K, &pStart, &pEnd)); 4730e2cc29aSToby Isaac for (p = pStart; p < pEnd; p++) { 4745f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(identity, p, p)); 4750e2cc29aSToby Isaac } 4760e2cc29aSToby Isaac /* refine it */ 4775f80ce2aSJacob Faibussowitsch CHKERRQ(DMRefine(K,comm,&Kref)); 4780e2cc29aSToby Isaac 4790e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating 4800e2cc29aSToby Isaac * points that appear in both */ 4815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref)); 4820e2cc29aSToby Isaac mesh = (DM_Plex *) (*ref)->data; 4830e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default; 4845f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&K)); 4855f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&Kref)); 486da43764aSToby Isaac PetscFunctionReturn(0); 487da43764aSToby Isaac } 488da43764aSToby Isaac 489878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 490878b19aaSToby Isaac { 491878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 492878b19aaSToby Isaac PetscSection childSec, pSec; 493878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 494878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 495878b19aaSToby Isaac 496878b19aaSToby Isaac PetscFunctionBegin; 497878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->childSection)); 4995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->children)); 500878b19aaSToby Isaac pSec = mesh->parentSection; 501878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 5025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(pSec,&pSize)); 503878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 504878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 505878b19aaSToby Isaac 506878b19aaSToby Isaac parMax = PetscMax(parMax,par+1); 507878b19aaSToby Isaac parMin = PetscMin(parMin,par); 508878b19aaSToby Isaac } 509878b19aaSToby Isaac if (parMin > parMax) { 510878b19aaSToby Isaac parMin = -1; 511878b19aaSToby Isaac parMax = -1; 512878b19aaSToby Isaac } 5135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec)); 5145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(childSec,parMin,parMax)); 515878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 516878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 517878b19aaSToby Isaac 5185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(childSec,par,1)); 519878b19aaSToby Isaac } 5205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(childSec)); 5215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(childSec,&cSize)); 5225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(cSize,&children)); 5235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(parMax-parMin,&offsets)); 5245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(pSec,&pStart,&pEnd)); 525878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 526878b19aaSToby Isaac PetscInt dof, off, i; 527878b19aaSToby Isaac 5285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(pSec,p,&dof)); 5295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(pSec,p,&off)); 530878b19aaSToby Isaac for (i = 0; i < dof; i++) { 531878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 532878b19aaSToby Isaac 5335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(childSec,par,&cOff)); 534878b19aaSToby Isaac children[cOff + offsets[par-parMin]++] = p; 535878b19aaSToby Isaac } 536878b19aaSToby Isaac } 537878b19aaSToby Isaac mesh->childSection = childSec; 538878b19aaSToby Isaac mesh->children = children; 5395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(offsets)); 540878b19aaSToby Isaac PetscFunctionReturn(0); 541878b19aaSToby Isaac } 542878b19aaSToby Isaac 5436dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 5446dd5a8c8SToby Isaac { 5456dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 5466dd5a8c8SToby Isaac const PetscInt *vals; 5476dd5a8c8SToby Isaac PetscSection secNew; 5486dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 5496dd5a8c8SToby Isaac PetscBool compress; 5506dd5a8c8SToby Isaac 5516dd5a8c8SToby Isaac PetscFunctionBegin; 5525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section,&pStart,&pEnd)); 5535f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(is,&size)); 5545f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(is,&vals)); 5555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew)); 5565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(secNew,pStart,pEnd)); 5576dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 5586dd5a8c8SToby Isaac PetscInt dof; 5596dd5a8c8SToby Isaac 5606dd5a8c8SToby Isaac p = vals[i]; 5616dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 5625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, p, &dof)); 5636dd5a8c8SToby Isaac if (dof) break; 5646dd5a8c8SToby Isaac } 5656dd5a8c8SToby Isaac if (i == size) { 5665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(secNew)); 5676dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 5686dd5a8c8SToby Isaac compress = PETSC_FALSE; 5696dd5a8c8SToby Isaac sizeNew = 0; 5706dd5a8c8SToby Isaac } 5716dd5a8c8SToby Isaac else { 5726dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 5736dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5746dd5a8c8SToby Isaac PetscInt dof, off; 5756dd5a8c8SToby Isaac 5765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, p, &dof)); 5775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, p, &off)); 5786dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 5796dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 5806dd5a8c8SToby Isaac 5816dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 5825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, q, &qDof)); 5836dd5a8c8SToby Isaac } 5846dd5a8c8SToby Isaac if (qDof) { 5855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(secNew, p, qDof)); 5866dd5a8c8SToby Isaac } 5876dd5a8c8SToby Isaac else { 5885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(secNew, p, 1)); 5896dd5a8c8SToby Isaac } 5906dd5a8c8SToby Isaac } 5916dd5a8c8SToby Isaac } 5925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(secNew)); 5935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(secNew,&sizeNew)); 5945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(sizeNew,&valsNew)); 5956dd5a8c8SToby Isaac compress = PETSC_FALSE; 5966dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5976dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 5986dd5a8c8SToby Isaac 5995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, p, &dof)); 6005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, p, &off)); 6015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(secNew, p, &dofNew)); 6025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(secNew, p, &offNew)); 6036dd5a8c8SToby Isaac count = 0; 6046dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 6056dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 6066dd5a8c8SToby Isaac 6076dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 6085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, q, &qDof)); 6095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, q, &qOff)); 6106dd5a8c8SToby Isaac } 6116dd5a8c8SToby Isaac if (qDof) { 6126dd5a8c8SToby Isaac PetscInt oldCount = count; 6136dd5a8c8SToby Isaac 6146dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 6156dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 6166dd5a8c8SToby Isaac 6176dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6186dd5a8c8SToby Isaac if (valsNew[offNew + k] == r) { 6196dd5a8c8SToby Isaac break; 6206dd5a8c8SToby Isaac } 6216dd5a8c8SToby Isaac } 6226dd5a8c8SToby Isaac if (k == oldCount) { 6236dd5a8c8SToby Isaac valsNew[offNew + count++] = r; 6246dd5a8c8SToby Isaac } 6256dd5a8c8SToby Isaac } 6266dd5a8c8SToby Isaac } 6276dd5a8c8SToby Isaac else { 6286dd5a8c8SToby Isaac PetscInt k, oldCount = count; 6296dd5a8c8SToby Isaac 6306dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 6316dd5a8c8SToby Isaac if (valsNew[offNew + k] == q) { 6326dd5a8c8SToby Isaac break; 6336dd5a8c8SToby Isaac } 6346dd5a8c8SToby Isaac } 6356dd5a8c8SToby Isaac if (k == oldCount) { 6366dd5a8c8SToby Isaac valsNew[offNew + count++] = q; 6376dd5a8c8SToby Isaac } 6386dd5a8c8SToby Isaac } 6396dd5a8c8SToby Isaac } 6406dd5a8c8SToby Isaac if (count < dofNew) { 6415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(secNew, p, count)); 6426dd5a8c8SToby Isaac compress = PETSC_TRUE; 6436dd5a8c8SToby Isaac } 6446dd5a8c8SToby Isaac } 6456dd5a8c8SToby Isaac } 6465f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(is,&vals)); 6475f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew))); 6486dd5a8c8SToby Isaac if (!globalAnyNew) { 6495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&secNew)); 6506dd5a8c8SToby Isaac *sectionNew = NULL; 6516dd5a8c8SToby Isaac *isNew = NULL; 6526dd5a8c8SToby Isaac } 6536dd5a8c8SToby Isaac else { 6546dd5a8c8SToby Isaac PetscBool globalCompress; 6556dd5a8c8SToby Isaac 6565f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew))); 6576dd5a8c8SToby Isaac if (compress) { 6586dd5a8c8SToby Isaac PetscSection secComp; 6596dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 6606dd5a8c8SToby Isaac 6615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp)); 6625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(secComp,pStart,pEnd)); 6636dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6646dd5a8c8SToby Isaac PetscInt dof; 6656dd5a8c8SToby Isaac 6665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(secNew, p, &dof)); 6675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(secComp, p, dof)); 6686dd5a8c8SToby Isaac } 6695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(secComp)); 6705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(secComp,&sizeNew)); 6715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(sizeNew,&valsComp)); 6726dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 6736dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 6746dd5a8c8SToby Isaac 6755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(secNew, p, &dof)); 6765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(secNew, p, &off)); 6775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(secComp, p, &offNew)); 6786dd5a8c8SToby Isaac for (j = 0; j < dof; j++) { 6796dd5a8c8SToby Isaac valsComp[offNew + j] = valsNew[off + j]; 6806dd5a8c8SToby Isaac } 6816dd5a8c8SToby Isaac } 6825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&secNew)); 6836dd5a8c8SToby Isaac secNew = secComp; 6845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(valsNew)); 6856dd5a8c8SToby Isaac valsNew = valsComp; 6866dd5a8c8SToby Isaac } 6875f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew)); 6886dd5a8c8SToby Isaac } 6896dd5a8c8SToby Isaac PetscFunctionReturn(0); 6906dd5a8c8SToby Isaac } 6916dd5a8c8SToby Isaac 692f7c74593SToby Isaac static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm) 69366af876cSToby Isaac { 69466af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 69566af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 69666af876cSToby Isaac PetscSection aSec; 697f9f063d4SToby Isaac DMLabel canonLabel; 69866af876cSToby Isaac IS aIS; 69966af876cSToby Isaac 70066af876cSToby Isaac PetscFunctionBegin; 70166af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm,&pStart,&pEnd)); 7035f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm,"canonical",&canonLabel)); 70466af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 70566af876cSToby Isaac PetscInt parent; 70666af876cSToby Isaac 707f9f063d4SToby Isaac if (canonLabel) { 708f9f063d4SToby Isaac PetscInt canon; 709f9f063d4SToby Isaac 7105f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(canonLabel,p,&canon)); 711f9f063d4SToby Isaac if (p != canon) continue; 712f9f063d4SToby Isaac } 7135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,p,&parent,NULL)); 71466af876cSToby Isaac if (parent != p) { 71566af876cSToby Isaac aMin = PetscMin(aMin,p); 71666af876cSToby Isaac aMax = PetscMax(aMax,p+1); 71766af876cSToby Isaac } 71866af876cSToby Isaac } 71966af876cSToby Isaac if (aMin > aMax) { 72066af876cSToby Isaac aMin = -1; 72166af876cSToby Isaac aMax = -1; 72266af876cSToby Isaac } 7235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF,&aSec)); 7245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(aSec,aMin,aMax)); 72566af876cSToby Isaac for (p = aMin; p < aMax; p++) { 72666af876cSToby Isaac PetscInt parent, ancestor = p; 72766af876cSToby Isaac 728f9f063d4SToby Isaac if (canonLabel) { 729f9f063d4SToby Isaac PetscInt canon; 730f9f063d4SToby Isaac 7315f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(canonLabel,p,&canon)); 732f9f063d4SToby Isaac if (p != canon) continue; 733f9f063d4SToby Isaac } 7345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,p,&parent,NULL)); 73566af876cSToby Isaac while (parent != ancestor) { 73666af876cSToby Isaac ancestor = parent; 7375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,ancestor,&parent,NULL)); 73866af876cSToby Isaac } 73966af876cSToby Isaac if (ancestor != p) { 74066af876cSToby Isaac PetscInt closureSize, *closure = NULL; 74166af876cSToby Isaac 7425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure)); 7435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(aSec,p,closureSize)); 7445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure)); 74566af876cSToby Isaac } 74666af876cSToby Isaac } 7475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(aSec)); 7485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(aSec,&size)); 7495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size,&anchors)); 75066af876cSToby Isaac for (p = aMin; p < aMax; p++) { 75166af876cSToby Isaac PetscInt parent, ancestor = p; 75266af876cSToby Isaac 753f9f063d4SToby Isaac if (canonLabel) { 754f9f063d4SToby Isaac PetscInt canon; 755f9f063d4SToby Isaac 7565f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(canonLabel,p,&canon)); 757f9f063d4SToby Isaac if (p != canon) continue; 758f9f063d4SToby Isaac } 7595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,p,&parent,NULL)); 76066af876cSToby Isaac while (parent != ancestor) { 76166af876cSToby Isaac ancestor = parent; 7625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,ancestor,&parent,NULL)); 76366af876cSToby Isaac } 76466af876cSToby Isaac if (ancestor != p) { 76566af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 76666af876cSToby Isaac 7675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,p,&aOff)); 76866af876cSToby Isaac 7695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure)); 77066af876cSToby Isaac for (j = 0; j < closureSize; j++) { 77166af876cSToby Isaac anchors[aOff + j] = closure[2*j]; 77266af876cSToby Isaac } 7735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure)); 77466af876cSToby Isaac } 77566af876cSToby Isaac } 7765f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,size,anchors,PETSC_OWN_POINTER,&aIS)); 7776dd5a8c8SToby Isaac { 7786dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 7796dd5a8c8SToby Isaac IS aISNew = aIS; 7806dd5a8c8SToby Isaac 7815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)aSec)); 7825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)aIS)); 7836dd5a8c8SToby Isaac while (aSecNew) { 7845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&aSec)); 7855f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&aIS)); 7866dd5a8c8SToby Isaac aSec = aSecNew; 7876dd5a8c8SToby Isaac aIS = aISNew; 7886dd5a8c8SToby Isaac aSecNew = NULL; 7896dd5a8c8SToby Isaac aISNew = NULL; 7905f80ce2aSJacob Faibussowitsch CHKERRQ(AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew)); 7916dd5a8c8SToby Isaac } 7926dd5a8c8SToby Isaac } 7935f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetAnchors(dm,aSec,aIS)); 7945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&aSec)); 7955f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&aIS)); 79666af876cSToby Isaac PetscFunctionReturn(0); 79766af876cSToby Isaac } 79866af876cSToby Isaac 7996461c1adSToby Isaac static PetscErrorCode DMPlexGetTrueSupportSize(DM dm,PetscInt p,PetscInt *dof,PetscInt *numTrueSupp) 8006461c1adSToby Isaac { 8016461c1adSToby Isaac PetscFunctionBegin; 8026461c1adSToby Isaac if (numTrueSupp[p] == -1) { 8036461c1adSToby Isaac PetscInt i, alldof; 8046461c1adSToby Isaac const PetscInt *supp; 8056461c1adSToby Isaac PetscInt count = 0; 8066461c1adSToby Isaac 8075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm,p,&alldof)); 8085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm,p,&supp)); 8096461c1adSToby Isaac for (i = 0; i < alldof; i++) { 8106461c1adSToby Isaac PetscInt q = supp[i], numCones, j; 8116461c1adSToby Isaac const PetscInt *cone; 8126461c1adSToby Isaac 8135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,q,&numCones)); 8145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm,q,&cone)); 8156461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8166461c1adSToby Isaac if (cone[j] == p) break; 8176461c1adSToby Isaac } 8186461c1adSToby Isaac if (j < numCones) count++; 8196461c1adSToby Isaac } 8206461c1adSToby Isaac numTrueSupp[p] = count; 8216461c1adSToby Isaac } 8226461c1adSToby Isaac *dof = numTrueSupp[p]; 8236461c1adSToby Isaac PetscFunctionReturn(0); 8246461c1adSToby Isaac } 8256461c1adSToby Isaac 826776742edSToby Isaac static PetscErrorCode DMPlexTreeExchangeSupports(DM dm) 827776742edSToby Isaac { 828776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 829776742edSToby Isaac PetscSection newSupportSection; 830776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth; 8316461c1adSToby Isaac PetscInt *numTrueSupp; 832776742edSToby Isaac PetscInt *offsets; 833776742edSToby Isaac 834776742edSToby Isaac PetscFunctionBegin; 835776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 836776742edSToby Isaac /* symmetrize the hierarchy */ 8375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm,&depth)); 8385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)),&newSupportSection)); 8395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm,&pStart,&pEnd)); 8405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(newSupportSection,pStart,pEnd)); 8415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(pEnd,&offsets)); 8425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd,&numTrueSupp)); 8436461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1; 8446461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of 845776742edSToby Isaac * parent(q) */ 846776742edSToby Isaac for (d = 0; d <= depth; d++) { 8475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,d,&pStart,&pEnd)); 848776742edSToby Isaac for (p = pStart; p < pEnd; ++p) { 849776742edSToby Isaac PetscInt dof, q, qdof, parent; 850776742edSToby Isaac 8515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTrueSupportSize(dm,p,&dof,numTrueSupp)); 8525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(newSupportSection, p, dof)); 853776742edSToby Isaac q = p; 8545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,q,&parent,NULL)); 855776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 856776742edSToby Isaac q = parent; 857776742edSToby Isaac 8585f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTrueSupportSize(dm,q,&qdof,numTrueSupp)); 8595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(newSupportSection,p,qdof)); 8605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(newSupportSection,q,dof)); 8615f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,q,&parent,NULL)); 862776742edSToby Isaac } 863776742edSToby Isaac } 864776742edSToby Isaac } 8655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(newSupportSection)); 8665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(newSupportSection,&newSize)); 8675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(newSize,&newSupports)); 868776742edSToby Isaac for (d = 0; d <= depth; d++) { 8695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,d,&pStart,&pEnd)); 870776742edSToby Isaac for (p = pStart; p < pEnd; p++) { 871776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent; 872776742edSToby Isaac 8735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof)); 8745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off)); 8755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(newSupportSection, p, &newDof)); 8765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(newSupportSection, p, &newOff)); 877776742edSToby Isaac for (i = 0; i < dof; i++) { 8786461c1adSToby Isaac PetscInt numCones, j; 8796461c1adSToby Isaac const PetscInt *cone; 8806461c1adSToby Isaac PetscInt q = mesh->supports[off + i]; 8816461c1adSToby Isaac 8825f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,q,&numCones)); 8835f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm,q,&cone)); 8846461c1adSToby Isaac for (j = 0; j < numCones; j++) { 8856461c1adSToby Isaac if (cone[j] == p) break; 8866461c1adSToby Isaac } 8876461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = q; 888776742edSToby Isaac } 889776742edSToby Isaac mesh->maxSupportSize = PetscMax(mesh->maxSupportSize,newDof); 890776742edSToby Isaac 891776742edSToby Isaac q = p; 8925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,q,&parent,NULL)); 893776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) { 894776742edSToby Isaac q = parent; 8955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(mesh->supportSection, q, &qdof)); 8965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(mesh->supportSection, q, &qoff)); 8975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(newSupportSection, q, &newqOff)); 898776742edSToby Isaac for (i = 0; i < qdof; i++) { 8996461c1adSToby Isaac PetscInt numCones, j; 9006461c1adSToby Isaac const PetscInt *cone; 9016461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i]; 9026461c1adSToby Isaac 9035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,r,&numCones)); 9045f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm,r,&cone)); 9056461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9066461c1adSToby Isaac if (cone[j] == q) break; 9076461c1adSToby Isaac } 9086461c1adSToby Isaac if (j < numCones) newSupports[newOff+offsets[p]++] = r; 909776742edSToby Isaac } 910776742edSToby Isaac for (i = 0; i < dof; i++) { 9116461c1adSToby Isaac PetscInt numCones, j; 9126461c1adSToby Isaac const PetscInt *cone; 9136461c1adSToby Isaac PetscInt r = mesh->supports[off + i]; 9146461c1adSToby Isaac 9155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,r,&numCones)); 9165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm,r,&cone)); 9176461c1adSToby Isaac for (j = 0; j < numCones; j++) { 9186461c1adSToby Isaac if (cone[j] == p) break; 9196461c1adSToby Isaac } 9206461c1adSToby Isaac if (j < numCones) newSupports[newqOff+offsets[q]++] = r; 921776742edSToby Isaac } 9225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,q,&parent,NULL)); 923776742edSToby Isaac } 924776742edSToby Isaac } 925776742edSToby Isaac } 9265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->supportSection)); 927776742edSToby Isaac mesh->supportSection = newSupportSection; 9285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->supports)); 929776742edSToby Isaac mesh->supports = newSupports; 9305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(offsets)); 9315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(numTrueSupp)); 932776742edSToby Isaac 933776742edSToby Isaac PetscFunctionReturn(0); 934776742edSToby Isaac } 935776742edSToby Isaac 936f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM,PetscSection,PetscSection,Mat); 937f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM,PetscSection,PetscSection,Mat); 938f7c74593SToby Isaac 939776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports) 940f9f063d4SToby Isaac { 941f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 942f9f063d4SToby Isaac DM refTree; 943f9f063d4SToby Isaac PetscInt size; 944f9f063d4SToby Isaac 945f9f063d4SToby Isaac PetscFunctionBegin; 946f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 947f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 9485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)parentSection)); 9495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&mesh->parentSection)); 950f9f063d4SToby Isaac mesh->parentSection = parentSection; 9515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(parentSection,&size)); 952f9f063d4SToby Isaac if (parents != mesh->parents) { 9535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->parents)); 9545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size,&mesh->parents)); 9555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(mesh->parents, parents, size)); 956f9f063d4SToby Isaac } 957f9f063d4SToby Isaac if (childIDs != mesh->childIDs) { 9585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mesh->childIDs)); 9595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size,&mesh->childIDs)); 9605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(mesh->childIDs, childIDs, size)); 961f9f063d4SToby Isaac } 9625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetReferenceTree(dm,&refTree)); 963f9f063d4SToby Isaac if (refTree) { 964f9f063d4SToby Isaac DMLabel canonLabel; 965f9f063d4SToby Isaac 9665f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(refTree,"canonical",&canonLabel)); 967f9f063d4SToby Isaac if (canonLabel) { 968f9f063d4SToby Isaac PetscInt i; 969f9f063d4SToby Isaac 970f9f063d4SToby Isaac for (i = 0; i < size; i++) { 971f9f063d4SToby Isaac PetscInt canon; 9725f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon)); 973f9f063d4SToby Isaac if (canon >= 0) { 974f9f063d4SToby Isaac mesh->childIDs[i] = canon; 975f9f063d4SToby Isaac } 976f9f063d4SToby Isaac } 977f9f063d4SToby Isaac } 978f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference; 9796e0288c8SStefano Zampini } else { 980f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct; 981f9f063d4SToby Isaac } 9825f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTreeSymmetrize(dm)); 983f9f063d4SToby Isaac if (computeCanonical) { 984f9f063d4SToby Isaac PetscInt d, dim; 985f9f063d4SToby Isaac 986f9f063d4SToby Isaac /* add the canonical label */ 9875f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm,&dim)); 9885f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(dm,"canonical")); 989f9f063d4SToby Isaac for (d = 0; d <= dim; d++) { 990f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren; 991f9f063d4SToby Isaac const PetscInt *cChildren; 992f9f063d4SToby Isaac 9935f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm,d,&dStart,&dEnd)); 994f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 9955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm,p,&cNumChildren,&cChildren)); 996f9f063d4SToby Isaac if (cNumChildren) { 997f9f063d4SToby Isaac canon = p; 998f9f063d4SToby Isaac break; 999f9f063d4SToby Isaac } 1000f9f063d4SToby Isaac } 1001f9f063d4SToby Isaac if (canon == -1) continue; 1002f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) { 1003f9f063d4SToby Isaac PetscInt numChildren, i; 1004f9f063d4SToby Isaac const PetscInt *children; 1005f9f063d4SToby Isaac 10065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm,p,&numChildren,&children)); 1007f9f063d4SToby Isaac if (numChildren) { 10082c71b3e2SJacob Faibussowitsch PetscCheckFalse(numChildren != cNumChildren,PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"All parent points in a stratum should have the same number of children: %d != %d", numChildren, cNumChildren); 10095f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"canonical",p,canon)); 1010f9f063d4SToby Isaac for (i = 0; i < numChildren; i++) { 10115f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue(dm,"canonical",children[i],cChildren[i])); 1012f9f063d4SToby Isaac } 1013f9f063d4SToby Isaac } 1014f9f063d4SToby Isaac } 1015f9f063d4SToby Isaac } 1016f9f063d4SToby Isaac } 1017776742edSToby Isaac if (exchangeSupports) { 10185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTreeExchangeSupports(dm)); 1019776742edSToby Isaac } 1020f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree; 1021f7c74593SToby Isaac /* reset anchors */ 10225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetAnchors(dm,NULL,NULL)); 1023f9f063d4SToby Isaac PetscFunctionReturn(0); 1024f9f063d4SToby Isaac } 1025f9f063d4SToby Isaac 10260b7167a0SToby Isaac /*@ 10270b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 10280b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 10290b7167a0SToby Isaac tree root. 10300b7167a0SToby Isaac 10310b7167a0SToby Isaac Collective on dm 10320b7167a0SToby Isaac 10330b7167a0SToby Isaac Input Parameters: 10340b7167a0SToby Isaac + dm - the DMPlex object 10350b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 10360b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 10370b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 10380b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 10390b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 10400b7167a0SToby Isaac 10410b7167a0SToby Isaac Level: intermediate 10420b7167a0SToby Isaac 1043a17985deSToby Isaac .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 10440b7167a0SToby Isaac @*/ 1045b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 10460b7167a0SToby Isaac { 10470b7167a0SToby Isaac PetscFunctionBegin; 10485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_FALSE,PETSC_TRUE)); 10490b7167a0SToby Isaac PetscFunctionReturn(0); 10500b7167a0SToby Isaac } 10510b7167a0SToby Isaac 1052b2f41788SToby Isaac /*@ 1053b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 1054b2f41788SToby Isaac Collective on dm 1055b2f41788SToby Isaac 1056f899ff85SJose E. Roman Input Parameter: 1057b2f41788SToby Isaac . dm - the DMPlex object 1058b2f41788SToby Isaac 1059b2f41788SToby Isaac Output Parameters: 1060b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 1061b2f41788SToby Isaac offset indexes the parent and childID list 1062b2f41788SToby Isaac . parents - a list of the point parents 1063b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 1064b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 1065b2f41788SToby Isaac . childSection - the inverse of the parent section 1066b2f41788SToby Isaac - children - a list of the point children 1067b2f41788SToby Isaac 1068b2f41788SToby Isaac Level: intermediate 1069b2f41788SToby Isaac 1070a17985deSToby Isaac .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 1071b2f41788SToby Isaac @*/ 1072b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 1073b2f41788SToby Isaac { 1074b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1075b2f41788SToby Isaac 1076b2f41788SToby Isaac PetscFunctionBegin; 1077b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1078b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 1079b2f41788SToby Isaac if (parents) *parents = mesh->parents; 1080b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 1081b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 1082b2f41788SToby Isaac if (children) *children = mesh->children; 1083b2f41788SToby Isaac PetscFunctionReturn(0); 1084b2f41788SToby Isaac } 1085b2f41788SToby Isaac 1086d961a43aSToby Isaac /*@ 1087eaf898f9SPatrick Sanan DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the DAG) 1088d961a43aSToby Isaac 1089d961a43aSToby Isaac Input Parameters: 1090d961a43aSToby Isaac + dm - the DMPlex object 1091d961a43aSToby Isaac - point - the query point 1092d961a43aSToby Isaac 1093d961a43aSToby Isaac Output Parameters: 1094d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 1095d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 1096d961a43aSToby Isaac does not have a parent 1097d961a43aSToby Isaac 1098d961a43aSToby Isaac Level: intermediate 1099d961a43aSToby Isaac 1100d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren() 1101d961a43aSToby Isaac @*/ 1102d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 1103d961a43aSToby Isaac { 1104d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1105d961a43aSToby Isaac PetscSection pSec; 1106d961a43aSToby Isaac 1107d961a43aSToby Isaac PetscFunctionBegin; 1108d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1109d961a43aSToby Isaac pSec = mesh->parentSection; 1110d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 1111d961a43aSToby Isaac PetscInt dof; 1112d961a43aSToby Isaac 11135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof (pSec, point, &dof)); 1114d961a43aSToby Isaac if (dof) { 1115d961a43aSToby Isaac PetscInt off; 1116d961a43aSToby Isaac 11175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset (pSec, point, &off)); 1118d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 1119d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 1120d961a43aSToby Isaac PetscFunctionReturn(0); 1121d961a43aSToby Isaac } 1122d961a43aSToby Isaac } 1123d961a43aSToby Isaac if (parent) { 1124d961a43aSToby Isaac *parent = point; 1125d961a43aSToby Isaac } 1126d961a43aSToby Isaac if (childID) { 1127d961a43aSToby Isaac *childID = 0; 1128d961a43aSToby Isaac } 1129d961a43aSToby Isaac PetscFunctionReturn(0); 1130d961a43aSToby Isaac } 1131d961a43aSToby Isaac 1132d961a43aSToby Isaac /*@C 1133eaf898f9SPatrick Sanan DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the DAG) 1134d961a43aSToby Isaac 1135d961a43aSToby Isaac Input Parameters: 1136d961a43aSToby Isaac + dm - the DMPlex object 1137d961a43aSToby Isaac - point - the query point 1138d961a43aSToby Isaac 1139d961a43aSToby Isaac Output Parameters: 1140d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 1141d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 1142d961a43aSToby Isaac 1143d961a43aSToby Isaac Level: intermediate 1144d961a43aSToby Isaac 1145d961a43aSToby Isaac Fortran Notes: 1146d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 1147d961a43aSToby Isaac include petsc.h90 in your code. 1148d961a43aSToby Isaac 1149d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent() 1150d961a43aSToby Isaac @*/ 1151d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 1152d961a43aSToby Isaac { 1153d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 1154d961a43aSToby Isaac PetscSection childSec; 1155d961a43aSToby Isaac PetscInt dof = 0; 1156d961a43aSToby Isaac 1157d961a43aSToby Isaac PetscFunctionBegin; 1158d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1159d961a43aSToby Isaac childSec = mesh->childSection; 1160d961a43aSToby Isaac if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 11615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof (childSec, point, &dof)); 1162d961a43aSToby Isaac } 1163d961a43aSToby Isaac if (numChildren) *numChildren = dof; 1164d961a43aSToby Isaac if (children) { 1165d961a43aSToby Isaac if (dof) { 1166d961a43aSToby Isaac PetscInt off; 1167d961a43aSToby Isaac 11685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset (childSec, point, &off)); 1169d961a43aSToby Isaac *children = &mesh->children[off]; 1170d961a43aSToby Isaac } 1171d961a43aSToby Isaac else { 1172d961a43aSToby Isaac *children = NULL; 1173d961a43aSToby Isaac } 1174d961a43aSToby Isaac } 1175d961a43aSToby Isaac PetscFunctionReturn(0); 1176d961a43aSToby Isaac } 11770c37af3bSToby Isaac 117852a3aeb4SToby Isaac static PetscErrorCode EvaluateBasis(PetscSpace space, PetscInt nBasis, PetscInt nFunctionals, PetscInt nComps, PetscInt nPoints, const PetscInt *pointsPerFn, const PetscReal *points, const PetscReal *weights, PetscReal *work, Mat basisAtPoints) 1179b3a4bf2aSToby Isaac { 118052a3aeb4SToby Isaac PetscInt f, b, p, c, offset, qPoints; 1181b3a4bf2aSToby Isaac 1182b3a4bf2aSToby Isaac PetscFunctionBegin; 11835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceEvaluate(space,nPoints,points,work,NULL,NULL)); 118452a3aeb4SToby Isaac for (f = 0, offset = 0; f < nFunctionals; f++) { 118552a3aeb4SToby Isaac qPoints = pointsPerFn[f]; 118652a3aeb4SToby Isaac for (b = 0; b < nBasis; b++) { 1187b3a4bf2aSToby Isaac PetscScalar val = 0.; 1188b3a4bf2aSToby Isaac 118952a3aeb4SToby Isaac for (p = 0; p < qPoints; p++) { 119052a3aeb4SToby Isaac for (c = 0; c < nComps; c++) { 119152a3aeb4SToby Isaac val += work[((offset + p) * nBasis + b) * nComps + c] * weights[(offset + p) * nComps + c]; 1192b3a4bf2aSToby Isaac } 119352a3aeb4SToby Isaac } 11945f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(basisAtPoints,b,f,val,INSERT_VALUES)); 1195b3a4bf2aSToby Isaac } 1196b3a4bf2aSToby Isaac offset += qPoints; 1197b3a4bf2aSToby Isaac } 11985f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(basisAtPoints,MAT_FINAL_ASSEMBLY)); 11995f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(basisAtPoints,MAT_FINAL_ASSEMBLY)); 1200b3a4bf2aSToby Isaac PetscFunctionReturn(0); 1201b3a4bf2aSToby Isaac } 1202b3a4bf2aSToby Isaac 1203f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat) 12040c37af3bSToby Isaac { 12050c37af3bSToby Isaac PetscDS ds; 12060c37af3bSToby Isaac PetscInt spdim; 12070c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 12080c37af3bSToby Isaac const PetscInt *anchors; 1209f7c74593SToby Isaac PetscSection aSec; 12100c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 12110c37af3bSToby Isaac IS aIS; 12120c37af3bSToby Isaac 12130c37af3bSToby Isaac PetscFunctionBegin; 12145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm,&pStart,&pEnd)); 12155f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm,&ds)); 12165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds,&numFields)); 12175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,0,&cStart,&cEnd)); 12185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(dm,&aSec,&aIS)); 12195f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(aIS,&anchors)); 12205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(cSec,&conStart,&conEnd)); 12215f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm,&spdim)); 12225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent)); 12230c37af3bSToby Isaac 12240c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 12250dd1b1feSToby Isaac PetscObject disc; 12260dd1b1feSToby Isaac PetscClassId id; 1227b3a4bf2aSToby Isaac PetscSpace bspace; 1228b3a4bf2aSToby Isaac PetscDualSpace dspace; 12299c3cf19fSMatthew G. Knepley PetscInt i, j, k, nPoints, Nc, offset; 123052a3aeb4SToby Isaac PetscInt fSize, maxDof; 1231b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work; 12321683a169SBarry Smith PetscScalar *scwork; 12331683a169SBarry Smith const PetscScalar *X; 12342c44ad04SToby Isaac PetscInt *sizes, *workIndRow, *workIndCol; 12350c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 12362c44ad04SToby Isaac const PetscInt *numDof = NULL; 1237085f0adfSToby Isaac const PetscInt ***perms = NULL; 1238085f0adfSToby Isaac const PetscScalar ***flips = NULL; 12390c37af3bSToby Isaac 12405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(ds,f,&disc)); 12415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(disc,&id)); 12420dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) { 1243b3a4bf2aSToby Isaac PetscFE fe = (PetscFE) disc; 1244b3a4bf2aSToby Isaac 12455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetBasisSpace(fe,&bspace)); 12465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetDualSpace(fe,&dspace)); 12475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(dspace,&fSize)); 12485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetNumComponents(fe,&Nc)); 12490dd1b1feSToby Isaac } 12500dd1b1feSToby Isaac else if (id == PETSCFV_CLASSID) { 1251b3a4bf2aSToby Isaac PetscFV fv = (PetscFV) disc; 1252b3a4bf2aSToby Isaac 12535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFVGetNumComponents(fv,&Nc)); 12545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceCreate(PetscObjectComm((PetscObject)fv),&bspace)); 12555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetType(bspace,PETSCSPACEPOLYNOMIAL)); 12565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetDegree(bspace,0,PETSC_DETERMINE)); 12575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetNumComponents(bspace,Nc)); 12585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetNumVariables(bspace,spdim)); 12595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetUp(bspace)); 12605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFVGetDualSpace(fv,&dspace)); 12615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(dspace,&fSize)); 12620dd1b1feSToby Isaac } 126398921bdaSJacob Faibussowitsch else SETERRQ(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id); 12645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetNumDof(dspace,&numDof)); 12652c44ad04SToby Isaac for (i = 0, maxDof = 0; i <= spdim; i++) {maxDof = PetscMax(maxDof,numDof[i]);} 12665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetSymmetries(dspace,&perms,&flips)); 12670dd1b1feSToby Isaac 12685f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF,&Amat)); 12695f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(Amat,fSize,fSize,fSize,fSize)); 12705f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(Amat,MATSEQDENSE)); 12715f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(Amat)); 12725f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat)); 12735f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat)); 12740c37af3bSToby Isaac nPoints = 0; 12750c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 127652a3aeb4SToby Isaac PetscInt qPoints, thisNc; 12770c37af3bSToby Isaac PetscQuadrature quad; 12780c37af3bSToby Isaac 12795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(dspace,i,&quad)); 12805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(quad,NULL,&thisNc,&qPoints,NULL,NULL)); 12812c71b3e2SJacob Faibussowitsch PetscCheckFalse(thisNc != Nc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Functional dim %D does not much basis dim %D",thisNc,Nc); 12820c37af3bSToby Isaac nPoints += qPoints; 12830c37af3bSToby Isaac } 12845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc7(fSize,&sizes,nPoints*Nc,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal,nPoints*fSize*Nc,&work,maxDof,&workIndRow,maxDof,&workIndCol)); 12855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxDof * maxDof,&scwork)); 12860c37af3bSToby Isaac offset = 0; 12870c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 12880c37af3bSToby Isaac PetscInt qPoints; 12890c37af3bSToby Isaac const PetscReal *p, *w; 12900c37af3bSToby Isaac PetscQuadrature quad; 12910c37af3bSToby Isaac 12925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(dspace,i,&quad)); 12935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(quad,NULL,NULL,&qPoints,&p,&w)); 12945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(weights+Nc*offset,w,Nc*qPoints)); 12955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(pointsRef+spdim*offset,p,spdim*qPoints)); 1296b3a4bf2aSToby Isaac sizes[i] = qPoints; 12970c37af3bSToby Isaac offset += qPoints; 12980c37af3bSToby Isaac } 12995f80ce2aSJacob Faibussowitsch CHKERRQ(EvaluateBasis(bspace,fSize,fSize,Nc,nPoints,sizes,pointsRef,weights,work,Amat)); 13005f80ce2aSJacob Faibussowitsch CHKERRQ(MatLUFactor(Amat,NULL,NULL,NULL)); 13010c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 13020c37af3bSToby Isaac PetscInt parent; 13030c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 13040c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 13050c37af3bSToby Isaac 13065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,c,&parent,NULL)); 13070c37af3bSToby Isaac if (parent == c) continue; 13085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure)); 13090c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13100c37af3bSToby Isaac PetscInt p = closure[2*i]; 13110c37af3bSToby Isaac PetscInt conDof; 13120c37af3bSToby Isaac 13130c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1314085f0adfSToby Isaac if (numFields) { 13155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSec,p,f,&conDof)); 13160c37af3bSToby Isaac } 13170c37af3bSToby Isaac else { 13185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSec,p,&conDof)); 13190c37af3bSToby Isaac } 13200c37af3bSToby Isaac if (conDof) break; 13210c37af3bSToby Isaac } 13220c37af3bSToby Isaac if (i == closureSize) { 13235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure)); 13240c37af3bSToby Isaac continue; 13250c37af3bSToby Isaac } 13260c37af3bSToby Isaac 13275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ)); 13285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent)); 13290c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 1330c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 1331c330f8ffSToby Isaac 1332c330f8ffSToby Isaac CoordinatesRefToReal(spdim, spdim, xi0, v0, J, &pointsRef[i*spdim],vtmp); 1333c330f8ffSToby Isaac CoordinatesRealToRef(spdim, spdim, xi0, v0parent, invJparent, vtmp, &pointsReal[i*spdim]); 13340c37af3bSToby Isaac } 13355f80ce2aSJacob Faibussowitsch CHKERRQ(EvaluateBasis(bspace,fSize,fSize,Nc,nPoints,sizes,pointsReal,weights,work,Bmat)); 13365f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatSolve(Amat,Bmat,Xmat)); 13375f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(Xmat,&X)); 13385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP)); 13395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets)); 13400c37af3bSToby Isaac childOffsets[0] = 0; 13410c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13420c37af3bSToby Isaac PetscInt p = closure[2*i]; 13430c37af3bSToby Isaac PetscInt dof; 13440c37af3bSToby Isaac 1345085f0adfSToby Isaac if (numFields) { 13465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,p,f,&dof)); 13470c37af3bSToby Isaac } 13480c37af3bSToby Isaac else { 13495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,p,&dof)); 13500c37af3bSToby Isaac } 135152a3aeb4SToby Isaac childOffsets[i+1]=childOffsets[i]+dof; 13520c37af3bSToby Isaac } 13530c37af3bSToby Isaac parentOffsets[0] = 0; 13540c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 13550c37af3bSToby Isaac PetscInt p = closureP[2*i]; 13560c37af3bSToby Isaac PetscInt dof; 13570c37af3bSToby Isaac 1358085f0adfSToby Isaac if (numFields) { 13595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,p,f,&dof)); 13600c37af3bSToby Isaac } 13610c37af3bSToby Isaac else { 13625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,p,&dof)); 13630c37af3bSToby Isaac } 136452a3aeb4SToby Isaac parentOffsets[i+1]=parentOffsets[i]+dof; 13650c37af3bSToby Isaac } 13660c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 13672c44ad04SToby Isaac PetscInt conDof, conOff, aDof, aOff, nWork; 13680c37af3bSToby Isaac PetscInt p = closure[2*i]; 13690c37af3bSToby Isaac PetscInt o = closure[2*i+1]; 1370085f0adfSToby Isaac const PetscInt *perm; 1371085f0adfSToby Isaac const PetscScalar *flip; 13720c37af3bSToby Isaac 13730c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 1374085f0adfSToby Isaac if (numFields) { 13755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSec,p,f,&conDof)); 13765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(cSec,p,f,&conOff)); 13770c37af3bSToby Isaac } 13780c37af3bSToby Isaac else { 13795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSec,p,&conDof)); 13805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(cSec,p,&conOff)); 13810c37af3bSToby Isaac } 13820c37af3bSToby Isaac if (!conDof) continue; 1383085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL; 1384085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL; 13855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec,p,&aDof)); 13865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,p,&aOff)); 13872c44ad04SToby Isaac nWork = childOffsets[i+1]-childOffsets[i]; 13880c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 13890c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 13900c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 13910c37af3bSToby Isaac 1392085f0adfSToby Isaac if (numFields) { 13935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,a,f,&aSecDof)); 13945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(section,a,f,&aSecOff)); 13950c37af3bSToby Isaac } 13960c37af3bSToby Isaac else { 13975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,a,&aSecDof)); 13985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section,a,&aSecOff)); 13990c37af3bSToby Isaac } 14000c37af3bSToby Isaac if (!aSecDof) continue; 14010c37af3bSToby Isaac 14020c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 14030c37af3bSToby Isaac PetscInt q = closureP[2*j]; 14040c37af3bSToby Isaac PetscInt oq = closureP[2*j+1]; 14052c44ad04SToby Isaac 14062c44ad04SToby Isaac if (q == a) { 140752a3aeb4SToby Isaac PetscInt r, s, nWorkP; 1408085f0adfSToby Isaac const PetscInt *permP; 1409085f0adfSToby Isaac const PetscScalar *flipP; 1410085f0adfSToby Isaac 1411085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL; 1412085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL; 14132c44ad04SToby Isaac nWorkP = parentOffsets[j+1]-parentOffsets[j]; 14142c44ad04SToby Isaac /* get a copy of the child-to-anchor portion of the matrix, and transpose so that rows correspond to the 14151683a169SBarry Smith * child and columns correspond to the anchor: BUT the maxrix returned by MatDenseGetArrayRead() is 14162c44ad04SToby Isaac * column-major, so transpose-transpose = do nothing */ 14172c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14182c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14192c44ad04SToby Isaac scwork[r * nWorkP + s] = X[fSize * (r + childOffsets[i]) + (s + parentOffsets[j])]; 14202c44ad04SToby Isaac } 14212c44ad04SToby Isaac } 142252a3aeb4SToby Isaac for (r = 0; r < nWork; r++) {workIndRow[perm ? perm[r] : r] = conOff + r;} 142352a3aeb4SToby Isaac for (s = 0; s < nWorkP; s++) {workIndCol[permP ? permP[s] : s] = aSecOff + s;} 14242c44ad04SToby Isaac if (flip) { 14252c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14262c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14272c44ad04SToby Isaac scwork[r * nWorkP + s] *= flip[r]; 14282c44ad04SToby Isaac } 14292c44ad04SToby Isaac } 14302c44ad04SToby Isaac } 14312c44ad04SToby Isaac if (flipP) { 14322c44ad04SToby Isaac for (r = 0; r < nWork; r++) { 14332c44ad04SToby Isaac for (s = 0; s < nWorkP; s++) { 14342c44ad04SToby Isaac scwork[r * nWorkP + s] *= flipP[s]; 14352c44ad04SToby Isaac } 14362c44ad04SToby Isaac } 14372c44ad04SToby Isaac } 14385f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(cMat,nWork,workIndRow,nWorkP,workIndCol,scwork,INSERT_VALUES)); 14392c44ad04SToby Isaac break; 14400c37af3bSToby Isaac } 14410c37af3bSToby Isaac } 14420c37af3bSToby Isaac } 14430c37af3bSToby Isaac } 14445f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(Xmat,&X)); 14455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(childOffsets,parentOffsets)); 14465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure)); 14475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP)); 14480c37af3bSToby Isaac } 14495f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Amat)); 14505f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Bmat)); 14515f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Xmat)); 14525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(scwork)); 14535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree7(sizes,weights,pointsRef,pointsReal,work,workIndRow,workIndCol)); 1454b3a4bf2aSToby Isaac if (id == PETSCFV_CLASSID) { 14555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceDestroy(&bspace)); 1456b3a4bf2aSToby Isaac } 14570c37af3bSToby Isaac } 14585f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY)); 14595f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY)); 14605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent)); 14615f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(aIS,&anchors)); 14620c37af3bSToby Isaac 14630c37af3bSToby Isaac PetscFunctionReturn(0); 14640c37af3bSToby Isaac } 146595a0b26dSToby Isaac 146621968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 146795a0b26dSToby Isaac { 1468f7c74593SToby Isaac Mat refCmat; 146921968bf8SToby Isaac PetscDS ds; 1470085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN; 147121968bf8SToby Isaac PetscScalar ***refPointFieldMats; 147221968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection; 147321968bf8SToby Isaac IS refAnIS; 147421968bf8SToby Isaac const PetscInt *refAnchors; 1475085f0adfSToby Isaac const PetscInt **perms; 1476085f0adfSToby Isaac const PetscScalar **flips; 147795a0b26dSToby Isaac 147895a0b26dSToby Isaac PetscFunctionBegin; 14795f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(refTree,&ds)); 14805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds,&numFields)); 1481085f0adfSToby Isaac maxFields = PetscMax(1,numFields); 14825f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&refConSec,&refCmat,NULL)); 14835f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(refTree,&refAnSec,&refAnIS)); 14845f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(refAnIS,&refAnchors)); 14855f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(refTree,&refSection)); 14865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 14875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats)); 14885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pRefEnd-pRefStart,&refPointFieldN)); 14895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(refConSec,&maxDof)); 14905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(refAnSec,&maxAnDof)); 14915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxDof,&rows)); 14925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxDof*maxAnDof,&cols)); 149395a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 149495a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof; 149595a0b26dSToby Isaac 14965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(refTree,p,&parent,NULL)); 14975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refConSec,p,&pDof)); 149895a0b26dSToby Isaac if (!pDof || parent == p) continue; 149995a0b26dSToby Isaac 15005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxFields,&refPointFieldMats[p-pRefStart])); 15015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(maxFields,&refPointFieldN[p-pRefStart])); 15025f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure)); 1503085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1504085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i; 150595a0b26dSToby Isaac 1506085f0adfSToby Isaac if (f < numFields) { 15075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(refConSec,p,f,&cDof)); 15085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(refConSec,p,f,&cOff)); 15095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldPointSyms(refSection,f,closureSize,closure,&perms,&flips)); 1510085f0adfSToby Isaac } else { 15115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refConSec,p,&cDof)); 15125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(refConSec,p,&cOff)); 15135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetPointSyms(refSection,closureSize,closure,&perms,&flips)); 151495a0b26dSToby Isaac } 151595a0b26dSToby Isaac 151695a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 151795a0b26dSToby Isaac rows[r] = cOff + r; 151895a0b26dSToby Isaac } 151995a0b26dSToby Isaac numCols = 0; 152095a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 152195a0b26dSToby Isaac PetscInt q = closure[2*i]; 152295a0b26dSToby Isaac PetscInt aDof, aOff, j; 1523085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 152495a0b26dSToby Isaac 1525085f0adfSToby Isaac if (numFields) { 15265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(refSection,q,f,&aDof)); 15275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(refSection,q,f,&aOff)); 152895a0b26dSToby Isaac } 152995a0b26dSToby Isaac else { 15305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refSection,q,&aDof)); 15315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(refSection,q,&aOff)); 153295a0b26dSToby Isaac } 153395a0b26dSToby Isaac 153495a0b26dSToby Isaac for (j = 0; j < aDof; j++) { 1535085f0adfSToby Isaac cols[numCols++] = aOff + (perm ? perm[j] : j); 153695a0b26dSToby Isaac } 153795a0b26dSToby Isaac } 153895a0b26dSToby Isaac refPointFieldN[p-pRefStart][f] = numCols; 15395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f])); 15405f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetValues(refCmat,cDof,rows,numCols,cols,refPointFieldMats[p-pRefStart][f])); 1541085f0adfSToby Isaac if (flips) { 1542085f0adfSToby Isaac PetscInt colOff = 0; 1543085f0adfSToby Isaac 1544085f0adfSToby Isaac for (i = 0; i < closureSize; i++) { 1545085f0adfSToby Isaac PetscInt q = closure[2*i]; 1546085f0adfSToby Isaac PetscInt aDof, aOff, j; 1547085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 1548085f0adfSToby Isaac 1549085f0adfSToby Isaac if (numFields) { 15505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(refSection,q,f,&aDof)); 15515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(refSection,q,f,&aOff)); 1552085f0adfSToby Isaac } 1553085f0adfSToby Isaac else { 15545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refSection,q,&aDof)); 15555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(refSection,q,&aOff)); 1556085f0adfSToby Isaac } 1557085f0adfSToby Isaac if (flip) { 1558085f0adfSToby Isaac PetscInt k; 1559085f0adfSToby Isaac for (k = 0; k < cDof; k++) { 1560085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1561085f0adfSToby Isaac refPointFieldMats[p-pRefStart][f][k * numCols + colOff + j] *= flip[j]; 1562085f0adfSToby Isaac } 1563085f0adfSToby Isaac } 1564085f0adfSToby Isaac } 1565085f0adfSToby Isaac colOff += aDof; 1566085f0adfSToby Isaac } 1567085f0adfSToby Isaac } 1568085f0adfSToby Isaac if (numFields) { 15695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(refSection,f,closureSize,closure,&perms,&flips)); 1570085f0adfSToby Isaac } else { 15715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestorePointSyms(refSection,closureSize,closure,&perms,&flips)); 1572085f0adfSToby Isaac } 157395a0b26dSToby Isaac } 15745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure)); 157595a0b26dSToby Isaac } 157621968bf8SToby Isaac *childrenMats = refPointFieldMats; 157721968bf8SToby Isaac *childrenN = refPointFieldN; 15785f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(refAnIS,&refAnchors)); 15795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rows)); 15805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cols)); 158121968bf8SToby Isaac PetscFunctionReturn(0); 158221968bf8SToby Isaac } 158321968bf8SToby Isaac 158421968bf8SToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN) 158521968bf8SToby Isaac { 158621968bf8SToby Isaac PetscDS ds; 158721968bf8SToby Isaac PetscInt **refPointFieldN; 158821968bf8SToby Isaac PetscScalar ***refPointFieldMats; 1589085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f; 159021968bf8SToby Isaac PetscSection refConSec; 159121968bf8SToby Isaac 159221968bf8SToby Isaac PetscFunctionBegin; 159321968bf8SToby Isaac refPointFieldN = *childrenN; 159421968bf8SToby Isaac *childrenN = NULL; 159521968bf8SToby Isaac refPointFieldMats = *childrenMats; 159621968bf8SToby Isaac *childrenMats = NULL; 15975f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(refTree,&ds)); 15985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds,&numFields)); 1599367003a6SStefano Zampini maxFields = PetscMax(1,numFields); 16005f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 16015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 160221968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 160321968bf8SToby Isaac PetscInt parent, pDof; 160421968bf8SToby Isaac 16055f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(refTree,p,&parent,NULL)); 16065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refConSec,p,&pDof)); 160721968bf8SToby Isaac if (!pDof || parent == p) continue; 160821968bf8SToby Isaac 1609085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 161021968bf8SToby Isaac PetscInt cDof; 161121968bf8SToby Isaac 1612085f0adfSToby Isaac if (numFields) { 16135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(refConSec,p,f,&cDof)); 161421968bf8SToby Isaac } 161521968bf8SToby Isaac else { 16165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refConSec,p,&cDof)); 161721968bf8SToby Isaac } 161821968bf8SToby Isaac 16195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(refPointFieldMats[p - pRefStart][f])); 162021968bf8SToby Isaac } 16215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(refPointFieldMats[p - pRefStart])); 16225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(refPointFieldN[p - pRefStart])); 162321968bf8SToby Isaac } 16245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(refPointFieldMats)); 16255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(refPointFieldN)); 162621968bf8SToby Isaac PetscFunctionReturn(0); 162721968bf8SToby Isaac } 162821968bf8SToby Isaac 162921968bf8SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat) 163021968bf8SToby Isaac { 163121968bf8SToby Isaac DM refTree; 163221968bf8SToby Isaac PetscDS ds; 163321968bf8SToby Isaac Mat refCmat; 1634085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN; 163521968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork; 163621968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec; 163721968bf8SToby Isaac IS refAnIS, anIS; 163821968bf8SToby Isaac const PetscInt *anchors; 163921968bf8SToby Isaac 164021968bf8SToby Isaac PetscFunctionBegin; 164121968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 16425f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm,&ds)); 16435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds,&numFields)); 1644085f0adfSToby Isaac maxFields = PetscMax(1,numFields); 16455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetReferenceTree(dm,&refTree)); 16465f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(dm,refTree)); 16475f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&refConSec,&refCmat,NULL)); 16485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(refTree,&refAnSec,&refAnIS)); 16495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(dm,&anSec,&anIS)); 16505f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(anIS,&anchors)); 16515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 16525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(conSec,&conStart,&conEnd)); 16535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(refConSec,&maxDof)); 16545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(refAnSec,&maxAnDof)); 16555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxDof*maxDof*maxAnDof,&pointWork)); 165621968bf8SToby Isaac 165721968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */ 16585f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 165995a0b26dSToby Isaac 166095a0b26dSToby Isaac /* step 2: compute the preorder */ 16615f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm,&pStart,&pEnd)); 16625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(pEnd-pStart,&perm,pEnd-pStart,&iperm)); 166395a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) { 166495a0b26dSToby Isaac perm[p - pStart] = p; 166595a0b26dSToby Isaac iperm[p - pStart] = p-pStart; 166695a0b26dSToby Isaac } 166795a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) { 166895a0b26dSToby Isaac PetscInt point = perm[p]; 166995a0b26dSToby Isaac PetscInt parent; 167095a0b26dSToby Isaac 16715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,point,&parent,NULL)); 167295a0b26dSToby Isaac if (parent == point) { 167395a0b26dSToby Isaac p++; 167495a0b26dSToby Isaac } 167595a0b26dSToby Isaac else { 167695a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i; 167795a0b26dSToby Isaac 16785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 167995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 168095a0b26dSToby Isaac PetscInt q = closure[2*i]; 168195a0b26dSToby Isaac if (iperm[q-pStart] > iperm[point-pStart]) { 168295a0b26dSToby Isaac /* swap */ 168395a0b26dSToby Isaac perm[p] = q; 168495a0b26dSToby Isaac perm[iperm[q-pStart]] = point; 168595a0b26dSToby Isaac iperm[point-pStart] = iperm[q-pStart]; 168695a0b26dSToby Isaac iperm[q-pStart] = p; 168795a0b26dSToby Isaac break; 168895a0b26dSToby Isaac } 168995a0b26dSToby Isaac } 169095a0b26dSToby Isaac size = closureSize; 16915f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 169295a0b26dSToby Isaac if (i == size) { 169395a0b26dSToby Isaac p++; 169495a0b26dSToby Isaac } 169595a0b26dSToby Isaac } 169695a0b26dSToby Isaac } 169795a0b26dSToby Isaac 169895a0b26dSToby Isaac /* step 3: fill the constraint matrix */ 169995a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't 170095a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the 170195a0b26dSToby Isaac * values outside of the Mat first. 170295a0b26dSToby Isaac */ 170395a0b26dSToby Isaac { 170495a0b26dSToby Isaac PetscInt nRows, row, nnz; 170595a0b26dSToby Isaac PetscBool done; 170695a0b26dSToby Isaac const PetscInt *ia, *ja; 170795a0b26dSToby Isaac PetscScalar *vals; 170895a0b26dSToby Isaac 17095f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done)); 1710*28b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not get RowIJ of constraint matrix"); 171195a0b26dSToby Isaac nnz = ia[nRows]; 171295a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind 171395a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */ 17145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nnz,&vals)); 171595a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) { 171695a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL; 171795a0b26dSToby Isaac PetscInt point = perm[p], pointDof; 171895a0b26dSToby Isaac 17195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,point,&parent,&childid)); 172095a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue; 17215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(conSec,point,&pointDof)); 172295a0b26dSToby Isaac if (!pointDof) continue; 17235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 1724085f0adfSToby Isaac for (f = 0; f < maxFields; f++) { 1725085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset; 172695a0b26dSToby Isaac PetscScalar *pointMat; 1727085f0adfSToby Isaac const PetscInt **perms; 1728085f0adfSToby Isaac const PetscScalar **flips; 172995a0b26dSToby Isaac 1730085f0adfSToby Isaac if (numFields) { 17315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(conSec,point,f,&cDof)); 17325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(conSec,point,f,&cOff)); 173395a0b26dSToby Isaac } 173495a0b26dSToby Isaac else { 17355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(conSec,point,&cDof)); 17365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(conSec,point,&cOff)); 173795a0b26dSToby Isaac } 173895a0b26dSToby Isaac if (!cDof) continue; 17395f80ce2aSJacob Faibussowitsch if (numFields) CHKERRQ(PetscSectionGetFieldPointSyms(section,f,closureSize,closure,&perms,&flips)); 17405f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetPointSyms(section,closureSize,closure,&perms,&flips)); 174195a0b26dSToby Isaac 174295a0b26dSToby Isaac /* make sure that every row for this point is the same size */ 174376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 174495a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 174595a0b26dSToby Isaac if (cDof > 1 && r) { 17462c71b3e2SJacob Faibussowitsch PetscCheckFalse((ia[cOff+r+1]-ia[cOff+r]) != (ia[cOff+r]-ia[cOff+r-1]),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])); 174795a0b26dSToby Isaac } 174895a0b26dSToby Isaac } 174976bd3646SJed Brown } 175095a0b26dSToby Isaac /* zero rows */ 175195a0b26dSToby Isaac for (i = ia[cOff] ; i< ia[cOff+cDof];i++) { 175295a0b26dSToby Isaac vals[i] = 0.; 175395a0b26dSToby Isaac } 175495a0b26dSToby Isaac matOffset = ia[cOff]; 175595a0b26dSToby Isaac numFillCols = ia[cOff+1] - matOffset; 175695a0b26dSToby Isaac pointMat = refPointFieldMats[childid-pRefStart][f]; 175795a0b26dSToby Isaac numCols = refPointFieldN[childid-pRefStart][f]; 175895a0b26dSToby Isaac offset = 0; 175995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) { 176095a0b26dSToby Isaac PetscInt q = closure[2*i]; 176195a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff; 1762085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL; 1763085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL; 176495a0b26dSToby Isaac 176595a0b26dSToby Isaac qConDof = qConOff = 0; 1766085f0adfSToby Isaac if (numFields) { 17675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,q,f,&aDof)); 17685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(section,q,f,&aOff)); 176995a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 17705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(conSec,q,f,&qConDof)); 17715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(conSec,q,f,&qConOff)); 177295a0b26dSToby Isaac } 177395a0b26dSToby Isaac } 177495a0b26dSToby Isaac else { 17755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,q,&aDof)); 17765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section,q,&aOff)); 177795a0b26dSToby Isaac if (q >= conStart && q < conEnd) { 17785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(conSec,q,&qConDof)); 17795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(conSec,q,&qConOff)); 178095a0b26dSToby Isaac } 178195a0b26dSToby Isaac } 178295a0b26dSToby Isaac if (!aDof) continue; 178395a0b26dSToby Isaac if (qConDof) { 178495a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already 178595a0b26dSToby Isaac * be filled, thanks to preordering */ 178695a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */ 178795a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff]; 178895a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset; 178995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 179095a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) { 179195a0b26dSToby Isaac PetscScalar inVal = 0; 179295a0b26dSToby Isaac for (k = 0; k < aDof; k++) { 1793085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k; 179495a0b26dSToby Isaac 1795085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.); 179695a0b26dSToby Isaac } 179795a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal; 179895a0b26dSToby Isaac } 179995a0b26dSToby Isaac } 180095a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */ 180195a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) { 180295a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j]; 180395a0b26dSToby Isaac for (;k < numFillCols; k++) { 180495a0b26dSToby Isaac if (ja[matOffset + k] == col) { 180595a0b26dSToby Isaac break; 180695a0b26dSToby Isaac } 180795a0b26dSToby Isaac } 18082c71b3e2SJacob Faibussowitsch PetscCheckFalse(k == numFillCols,PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, col); 180995a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 181095a0b26dSToby Isaac vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j]; 181195a0b26dSToby Isaac } 181295a0b26dSToby Isaac } 181395a0b26dSToby Isaac } 181495a0b26dSToby Isaac else { 181595a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */ 181695a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) { 181795a0b26dSToby Isaac if (ja[matOffset + k] == aOff) { 181895a0b26dSToby Isaac break; 181995a0b26dSToby Isaac } 182095a0b26dSToby Isaac } 18212c71b3e2SJacob Faibussowitsch PetscCheckFalse(k == numFillCols,PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, aOff); 182295a0b26dSToby Isaac for (r = 0; r < cDof; r++) { 1823085f0adfSToby Isaac for (j = 0; j < aDof; j++) { 1824085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j; 1825085f0adfSToby Isaac 1826085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.); 182795a0b26dSToby Isaac } 182895a0b26dSToby Isaac } 182995a0b26dSToby Isaac } 183095a0b26dSToby Isaac offset += aDof; 183195a0b26dSToby Isaac } 1832085f0adfSToby Isaac if (numFields) { 18335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestoreFieldPointSyms(section,f,closureSize,closure,&perms,&flips)); 1834085f0adfSToby Isaac } else { 18355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionRestorePointSyms(section,closureSize,closure,&perms,&flips)); 1836085f0adfSToby Isaac } 183795a0b26dSToby Isaac } 18385f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 183995a0b26dSToby Isaac } 184095a0b26dSToby Isaac for (row = 0; row < nRows; row++) { 18415f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(cMat,1,&row,ia[row+1]-ia[row],&ja[ia[row]],&vals[ia[row]],INSERT_VALUES)); 184295a0b26dSToby Isaac } 18435f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done)); 1844*28b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not restore RowIJ of constraint matrix"); 18455f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY)); 18465f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY)); 18475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vals)); 184895a0b26dSToby Isaac } 184995a0b26dSToby Isaac 185095a0b26dSToby Isaac /* clean up */ 18515f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(anIS,&anchors)); 18525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(perm,iperm)); 18535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pointWork)); 18545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 185595a0b26dSToby Isaac PetscFunctionReturn(0); 185695a0b26dSToby Isaac } 185795a0b26dSToby Isaac 18586f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of 18596f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */ 18606f5f1567SToby Isaac PetscErrorCode DMPlexTreeRefineCell (DM dm, PetscInt cell, DM *ncdm) 18616f5f1567SToby Isaac { 18626f5f1567SToby Isaac DM K; 1863420f55faSMatthew G. Knepley PetscMPIInt rank; 18646f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd; 18656f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations; 18666f5f1567SToby Isaac PetscInt *Kembedding; 18676f5f1567SToby Isaac PetscInt *cellClosure=NULL, nc; 18686f5f1567SToby Isaac PetscScalar *newVertexCoords; 18696f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset; 18706f5f1567SToby Isaac PetscSection parentSection; 18716f5f1567SToby Isaac 18726f5f1567SToby Isaac PetscFunctionBegin; 18735f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank)); 18745f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm,&dim)); 18755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm)); 18765f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*ncdm,dim)); 18776f5f1567SToby Isaac 18785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 18795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm),&parentSection)); 18805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetReferenceTree(dm,&K)); 1881dd400576SPatrick Sanan if (rank == 0) { 18826f5f1567SToby Isaac /* compute the new charts */ 18835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc5(dim+1,&pNewCount,dim+1,&pNewStart,dim+1,&pNewEnd,dim+1,&pOldStart,dim+1,&pOldEnd)); 18846f5f1567SToby Isaac offset = 0; 18856f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 18866f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k; 18876f5f1567SToby Isaac 18886f5f1567SToby Isaac pNewStart[d] = offset; 18895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,d,&pOldStart[d],&pOldEnd[d])); 18905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(K,d,&kStart,&kEnd)); 18916f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d]; 18926f5f1567SToby Isaac /* adding the new points */ 18936f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart; 18946f5f1567SToby Isaac if (!d) { 18956f5f1567SToby Isaac /* removing the cell */ 18966f5f1567SToby Isaac pNewCount[d]--; 18976f5f1567SToby Isaac } 18986f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 18996f5f1567SToby Isaac PetscInt parent; 19005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(K,k,&parent,NULL)); 19016f5f1567SToby Isaac if (parent == k) { 19026f5f1567SToby Isaac /* avoid double counting points that won't actually be new */ 19036f5f1567SToby Isaac pNewCount[d]--; 19046f5f1567SToby Isaac } 19056f5f1567SToby Isaac } 19066f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d]; 19076f5f1567SToby Isaac offset = pNewEnd[d]; 19086f5f1567SToby Isaac 19096f5f1567SToby Isaac } 19102c71b3e2SJacob Faibussowitsch PetscCheckFalse(cell < pOldStart[0] || cell >= pOldEnd[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"%d not in cell range [%d, %d)", cell, pOldStart[0], pOldEnd[0]); 19116f5f1567SToby Isaac /* get the current closure of the cell that we are removing */ 19125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure)); 19136f5f1567SToby Isaac 19145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pNewEnd[dim],&newConeSizes)); 19156f5f1567SToby Isaac { 1916b5a892a1SMatthew G. Knepley DMPolytopeType pct, qct; 19176f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j; 19186f5f1567SToby Isaac 19195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(K,&kStart,&kEnd)); 19205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc4(kEnd-kStart,&Kembedding,kEnd-kStart,&perm,kEnd-kStart,&iperm,kEnd-kStart,&preOrient)); 19216f5f1567SToby Isaac 19226f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19236f5f1567SToby Isaac perm[k - kStart] = k; 19246f5f1567SToby Isaac iperm [k - kStart] = k - kStart; 19256f5f1567SToby Isaac preOrient[k - kStart] = 0; 19266f5f1567SToby Isaac } 19276f5f1567SToby Isaac 19285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK)); 19296f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) { 19306f5f1567SToby Isaac PetscInt parentOrientA = closureK[2*j+1]; 19316f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2*j+1]; 19326f5f1567SToby Isaac PetscInt p, q; 19336f5f1567SToby Isaac 19346f5f1567SToby Isaac p = closureK[2*j]; 19356f5f1567SToby Isaac q = cellClosure[2*j]; 19365f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(K, p, &pct)); 19375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, q, &qct)); 19386f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19396f5f1567SToby Isaac if (q >= pOldStart[d] && q < pOldEnd[d]) { 19406f5f1567SToby Isaac Kembedding[p] = (q - pOldStart[d]) + pNewStart[d]; 19416f5f1567SToby Isaac } 19426f5f1567SToby Isaac } 1943b5a892a1SMatthew G. Knepley parentOrientA = DMPolytopeConvertNewOrientation_Internal(pct, parentOrientA); 1944b5a892a1SMatthew G. Knepley parentOrientB = DMPolytopeConvertNewOrientation_Internal(qct, parentOrientB); 19456f5f1567SToby Isaac if (parentOrientA != parentOrientB) { 19466f5f1567SToby Isaac PetscInt numChildren, i; 19476f5f1567SToby Isaac const PetscInt *children; 19486f5f1567SToby Isaac 19495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(K,p,&numChildren,&children)); 19506f5f1567SToby Isaac for (i = 0; i < numChildren; i++) { 19516f5f1567SToby Isaac PetscInt kPerm, oPerm; 19526f5f1567SToby Isaac 19536f5f1567SToby Isaac k = children[i]; 19545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetChildSymmetry(K,p,parentOrientA,0,k,parentOrientB,&oPerm,&kPerm)); 19556f5f1567SToby Isaac /* perm = what refTree position I'm in */ 19566f5f1567SToby Isaac perm[kPerm-kStart] = k; 19576f5f1567SToby Isaac /* iperm = who is at this position */ 19586f5f1567SToby Isaac iperm[k-kStart] = kPerm-kStart; 19596f5f1567SToby Isaac preOrient[kPerm-kStart] = oPerm; 19606f5f1567SToby Isaac } 19616f5f1567SToby Isaac } 19626f5f1567SToby Isaac } 19635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK)); 19646f5f1567SToby Isaac } 19655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(parentSection,0,pNewEnd[dim])); 19666f5f1567SToby Isaac offset = 0; 19676f5f1567SToby Isaac numNewCones = 0; 19686f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 19696f5f1567SToby Isaac PetscInt kStart, kEnd, k; 19706f5f1567SToby Isaac PetscInt p; 19716f5f1567SToby Isaac PetscInt size; 19726f5f1567SToby Isaac 19736f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 19746f5f1567SToby Isaac /* skip cell 0 */ 19756f5f1567SToby Isaac if (p == cell) continue; 19766f5f1567SToby Isaac /* old cones to new cones */ 19775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,p,&size)); 19786f5f1567SToby Isaac newConeSizes[offset++] = size; 19796f5f1567SToby Isaac numNewCones += size; 19806f5f1567SToby Isaac } 19816f5f1567SToby Isaac 19825f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(K,d,&kStart,&kEnd)); 19836f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 19846f5f1567SToby Isaac PetscInt kParent; 19856f5f1567SToby Isaac 19865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(K,k,&kParent,NULL)); 19876f5f1567SToby Isaac if (kParent != k) { 19886f5f1567SToby Isaac Kembedding[k] = offset; 19895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(K,k,&size)); 19906f5f1567SToby Isaac newConeSizes[offset++] = size; 19916f5f1567SToby Isaac numNewCones += size; 19926f5f1567SToby Isaac if (kParent != 0) { 19935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(parentSection,Kembedding[k],1)); 19946f5f1567SToby Isaac } 19956f5f1567SToby Isaac } 19966f5f1567SToby Isaac } 19976f5f1567SToby Isaac } 19986f5f1567SToby Isaac 19995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(parentSection)); 20005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(parentSection,&numPointsWithParents)); 20015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(numNewCones,&newCones,numNewCones,&newOrientations)); 20025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(numPointsWithParents,&parents,numPointsWithParents,&childIDs)); 20036f5f1567SToby Isaac 20046f5f1567SToby Isaac /* fill new cones */ 20056f5f1567SToby Isaac offset = 0; 20066f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 20076f5f1567SToby Isaac PetscInt kStart, kEnd, k, l; 20086f5f1567SToby Isaac PetscInt p; 20096f5f1567SToby Isaac PetscInt size; 20106f5f1567SToby Isaac const PetscInt *cone, *orientation; 20116f5f1567SToby Isaac 20126f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) { 20136f5f1567SToby Isaac /* skip cell 0 */ 20146f5f1567SToby Isaac if (p == cell) continue; 20156f5f1567SToby Isaac /* old cones to new cones */ 20165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,p,&size)); 20175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm,p,&cone)); 20185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(dm,p,&orientation)); 20196f5f1567SToby Isaac for (l = 0; l < size; l++) { 20206f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1]; 20216f5f1567SToby Isaac newOrientations[offset++] = orientation[l]; 20226f5f1567SToby Isaac } 20236f5f1567SToby Isaac } 20246f5f1567SToby Isaac 20255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(K,d,&kStart,&kEnd)); 20266f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20276f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent; 20286f5f1567SToby Isaac PetscInt preO = preOrient[k]; 20296f5f1567SToby Isaac 20305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(K,k,&kParent,NULL)); 20316f5f1567SToby Isaac if (kParent != k) { 20326f5f1567SToby Isaac /* embed new cones */ 20335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(K,k,&size)); 20345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(K,kPerm,&cone)); 20355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientation(K,kPerm,&orientation)); 20366f5f1567SToby Isaac for (l = 0; l < size; l++) { 20376f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size -(preO + 1) - l) % size); 20386f5f1567SToby Isaac PetscInt newO, lSize, oTrue; 2039b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_NUM_POLYTOPES; 20406f5f1567SToby Isaac 20416f5f1567SToby Isaac q = iperm[cone[m]]; 20426f5f1567SToby Isaac newCones[offset] = Kembedding[q]; 20435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(K,q,&lSize)); 2044b5a892a1SMatthew G. Knepley if (lSize == 2) ct = DM_POLYTOPE_SEGMENT; 2045b5a892a1SMatthew G. Knepley else if (lSize == 4) ct = DM_POLYTOPE_QUADRILATERAL; 2046b5a892a1SMatthew G. Knepley oTrue = DMPolytopeConvertNewOrientation_Internal(ct, orientation[m]); 20476f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2); 20486f5f1567SToby Isaac newO = DihedralCompose(lSize,oTrue,preOrient[q]); 2049b5a892a1SMatthew G. Knepley newOrientations[offset++] = DMPolytopeConvertOldOrientation_Internal(ct, newO); 20506f5f1567SToby Isaac } 20516f5f1567SToby Isaac if (kParent != 0) { 20526f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent]; 20535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(parentSection,Kembedding[k],&pOffset)); 20546f5f1567SToby Isaac parents[pOffset] = newPoint; 20556f5f1567SToby Isaac childIDs[pOffset] = k; 20566f5f1567SToby Isaac } 20576f5f1567SToby Isaac } 20586f5f1567SToby Isaac } 20596f5f1567SToby Isaac } 20606f5f1567SToby Isaac 20615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(dim*(pNewEnd[dim]-pNewStart[dim]),&newVertexCoords)); 20626f5f1567SToby Isaac 20636f5f1567SToby Isaac /* fill coordinates */ 20646f5f1567SToby Isaac offset = 0; 20656f5f1567SToby Isaac { 2066d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l; 20676f5f1567SToby Isaac PetscSection vSection; 20686f5f1567SToby Isaac PetscInt v; 20696f5f1567SToby Isaac Vec coords; 20706f5f1567SToby Isaac PetscScalar *coordvals; 20716f5f1567SToby Isaac PetscInt dof, off; 2072c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ; 20736f5f1567SToby Isaac 207476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 2075d90620a3SMatthew G. Knepley PetscInt k; 20765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(K,0,&kStart,&kEnd)); 20776f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) { 20785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ)); 20792c71b3e2SJacob Faibussowitsch PetscCheckFalse(detJ <= 0.,PETSC_COMM_SELF,PETSC_ERR_PLIB,"reference tree cell %d has bad determinant",k); 20806f5f1567SToby Isaac } 2081d90620a3SMatthew G. Knepley } 20825f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ)); 20835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm,&vSection)); 20845f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm,&coords)); 20855f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coords,&coordvals)); 20866f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) { 20876f5f1567SToby Isaac 20885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(vSection,v,&dof)); 20895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(vSection,v,&off)); 20906f5f1567SToby Isaac for (l = 0; l < dof; l++) { 20916f5f1567SToby Isaac newVertexCoords[offset++] = coordvals[off + l]; 20926f5f1567SToby Isaac } 20936f5f1567SToby Isaac } 20945f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coords,&coordvals)); 20956f5f1567SToby Isaac 20965f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(K,&vSection)); 20975f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(K,&coords)); 20985f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coords,&coordvals)); 20995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(K,0,&kStart,&kEnd)); 21006f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) { 21019bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3]; 21026f5f1567SToby Isaac PetscInt vPerm = perm[v]; 21036f5f1567SToby Isaac PetscInt kParent; 2104c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 21056f5f1567SToby Isaac 21065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(K,v,&kParent,NULL)); 21076f5f1567SToby Isaac if (kParent != v) { 21086f5f1567SToby Isaac /* this is a new vertex */ 21095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(vSection,vPerm,&off)); 21109bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off+l]); 2111367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord); 21129bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset+l] = newCoord[l]; 21136f5f1567SToby Isaac offset += dim; 21146f5f1567SToby Isaac } 21156f5f1567SToby Isaac } 21165f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coords,&coordvals)); 21176f5f1567SToby Isaac } 21186f5f1567SToby Isaac 21196f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */ 21206f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) { 21216f5f1567SToby Isaac PetscInt tmp; 21226f5f1567SToby Isaac 21236f5f1567SToby Isaac tmp = pNewCount[d]; 21246f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d]; 21256f5f1567SToby Isaac pNewCount[dim - d] = tmp; 21266f5f1567SToby Isaac } 21276f5f1567SToby Isaac 21285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(*ncdm,dim,pNewCount,newConeSizes,newCones,newOrientations,newVertexCoords)); 21295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetReferenceTree(*ncdm,K)); 21305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetTree(*ncdm,parentSection,parents,childIDs)); 21316f5f1567SToby Isaac 21326f5f1567SToby Isaac /* clean up */ 21335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure)); 21345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree5(pNewCount,pNewStart,pNewEnd,pOldStart,pOldEnd)); 21355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(newConeSizes)); 21365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(newCones,newOrientations)); 21375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(newVertexCoords)); 21385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(parents,childIDs)); 21395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(Kembedding,perm,iperm,preOrient)); 21406f5f1567SToby Isaac } 21416f5f1567SToby Isaac else { 21426f5f1567SToby Isaac PetscInt p, counts[4]; 21436f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations; 21446f5f1567SToby Isaac Vec coordVec; 21456f5f1567SToby Isaac PetscScalar *coords; 21466f5f1567SToby Isaac 21476f5f1567SToby Isaac for (d = 0; d <= dim; d++) { 21486f5f1567SToby Isaac PetscInt dStart, dEnd; 21496f5f1567SToby Isaac 21505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm,d,&dStart,&dEnd)); 21516f5f1567SToby Isaac counts[d] = dEnd - dStart; 21526f5f1567SToby Isaac } 21535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart,&coneSizes)); 21546f5f1567SToby Isaac for (p = pStart; p < pEnd; p++) { 21555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm,p,&coneSizes[p-pStart])); 21566f5f1567SToby Isaac } 21575f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCones(dm, &cones)); 21585f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientations(dm, &orientations)); 21595f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm,&coordVec)); 21605f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordVec,&coords)); 21616f5f1567SToby Isaac 21625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(parentSection,pStart,pEnd)); 21635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(parentSection)); 21645f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromDAG(*ncdm,dim,counts,coneSizes,cones,orientations,NULL)); 21655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetReferenceTree(*ncdm,K)); 21665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetTree(*ncdm,parentSection,NULL,NULL)); 21675f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordVec,&coords)); 21686f5f1567SToby Isaac } 21695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&parentSection)); 21706f5f1567SToby Isaac 21716f5f1567SToby Isaac PetscFunctionReturn(0); 21726f5f1567SToby Isaac } 21736ecaa68aSToby Isaac 21746ecaa68aSToby Isaac PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 21756ecaa68aSToby Isaac { 21766ecaa68aSToby Isaac PetscSF coarseToFineEmbedded; 21776ecaa68aSToby Isaac PetscSection globalCoarse, globalFine; 21786ecaa68aSToby Isaac PetscSection localCoarse, localFine; 21796ecaa68aSToby Isaac PetscSection aSec, cSec; 21806ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec; 218146bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec; 218246bdb399SToby Isaac PetscInt *rootIndices, *leafIndices; 218346bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices; 21846ecaa68aSToby Isaac IS aIS; 21856ecaa68aSToby Isaac const PetscInt *anchors; 21866ecaa68aSToby Isaac Mat cMat; 21874acb8e1eSToby Isaac PetscInt numFields, maxFields; 21886ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 21896ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 21901c58ffc4SToby Isaac PetscInt *maxChildIds; 2191e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 21924acb8e1eSToby Isaac const PetscInt ***perms; 21934acb8e1eSToby Isaac const PetscScalar ***flips; 21946ecaa68aSToby Isaac 21956ecaa68aSToby Isaac PetscFunctionBegin; 21965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(coarse,&pStartC,&pEndC)); 21975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(fine,&pStartF,&pEndF)); 21985f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(fine,&globalFine)); 21996ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 220089698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l; 220189698031SToby Isaac const PetscInt *leaves; 22026ecaa68aSToby Isaac 22035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL)); 220489698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 220589698031SToby Isaac p = leaves ? leaves[l] : l; 22065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&dof)); 22075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 22086ecaa68aSToby Isaac if ((dof - cdof) > 0) { 22096ecaa68aSToby Isaac numPointsWithDofs++; 22106ecaa68aSToby Isaac } 22116ecaa68aSToby Isaac } 22125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numPointsWithDofs,&pointsWithDofs)); 22137cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 221489698031SToby Isaac p = leaves ? leaves[l] : l; 22155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&dof)); 22165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 22176ecaa68aSToby Isaac if ((dof - cdof) > 0) { 221889698031SToby Isaac pointsWithDofs[offset++] = l; 22196ecaa68aSToby Isaac } 22206ecaa68aSToby Isaac } 22215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 22225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pointsWithDofs)); 22236ecaa68aSToby Isaac } 22246ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 22255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEndC-pStartC,&maxChildIds)); 22266ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 22278d2f55e7SToby Isaac maxChildIds[p - pStartC] = -2; 22286ecaa68aSToby Isaac } 22295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX)); 22305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX)); 223146bdb399SToby Isaac 22325f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(coarse,&localCoarse)); 22335f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(coarse,&globalCoarse)); 223446bdb399SToby Isaac 22355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(coarse,&aSec,&aIS)); 22365f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(aIS,&anchors)); 22375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(aSec,&aStart,&aEnd)); 223846bdb399SToby Isaac 22395f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(coarse,&cSec,&cMat,NULL)); 22405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(cSec,&cStart,&cEnd)); 224146bdb399SToby Isaac 224246bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 22435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec)); 22445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootMatricesSec)); 22455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(rootIndicesSec,pStartC,pEndC)); 22465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(rootMatricesSec,pStartC,pEndC)); 22475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(localCoarse,&numFields)); 2248713c1c5dSToby Isaac maxFields = PetscMax(1,numFields); 22495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc7(maxFields+1,&offsets,maxFields+1,&offsetsCopy,maxFields+1,&newOffsets,maxFields+1,&newOffsetsCopy,maxFields+1,&rowOffsets,maxFields+1,&numD,maxFields+1,&numO)); 22505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(maxFields+1,(PetscInt****)&perms,maxFields+1,(PetscScalar****)&flips)); 22515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMemzero((void *) perms, (maxFields+1) * sizeof(const PetscInt **))); 22525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMemzero((void *) flips, (maxFields+1) * sizeof(const PetscScalar **))); 225346bdb399SToby Isaac 225446bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 22558d2f55e7SToby Isaac PetscInt dof, matSize = 0; 22566ecaa68aSToby Isaac PetscInt aDof = 0; 22576ecaa68aSToby Isaac PetscInt cDof = 0; 22586ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 22596ecaa68aSToby Isaac PetscInt numRowIndices = 0; 22606ecaa68aSToby Isaac PetscInt numColIndices = 0; 2261f13f9184SToby Isaac PetscInt f; 22626ecaa68aSToby Isaac 22635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalCoarse,p,&dof)); 22641cfc5b76SToby Isaac if (dof < 0) { 22651cfc5b76SToby Isaac dof = -(dof + 1); 22661cfc5b76SToby Isaac } 22676ecaa68aSToby Isaac if (p >= aStart && p < aEnd) { 22685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec,p,&aDof)); 22696ecaa68aSToby Isaac } 22706ecaa68aSToby Isaac if (p >= cStart && p < cEnd) { 22715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSec,p,&cDof)); 22726ecaa68aSToby Isaac } 2273f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0; 2274f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0; 22756ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 2276f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl; 22776ecaa68aSToby Isaac 22785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure)); 227946bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 22806ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof; 22816ecaa68aSToby Isaac 22825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(localCoarse,c,&clDof)); 22836ecaa68aSToby Isaac numRowIndices += clDof; 22846ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,c,f,&clDof)); 22866ecaa68aSToby Isaac offsets[f + 1] += clDof; 22876ecaa68aSToby Isaac } 22886ecaa68aSToby Isaac } 22896ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 22906ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 22916ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 22926ecaa68aSToby Isaac } 229346bdb399SToby Isaac /* get the number of indices needed and their field offsets */ 22945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,NULL,NULL,NULL,&numColIndices,NULL,NULL,newOffsets,PETSC_FALSE)); 22955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure)); 22966ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */ 22976ecaa68aSToby Isaac numColIndices = numRowIndices; 22986ecaa68aSToby Isaac matSize = 0; 22996ecaa68aSToby Isaac } 230046bdb399SToby Isaac else if (numFields) { /* we send one submat for each field: sum their sizes */ 23016ecaa68aSToby Isaac matSize = 0; 23026ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23036ecaa68aSToby Isaac PetscInt numRow, numCol; 23046ecaa68aSToby Isaac 23056ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f]; 2306f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f]; 23076ecaa68aSToby Isaac matSize += numRow * numCol; 23086ecaa68aSToby Isaac } 23096ecaa68aSToby Isaac } 23106ecaa68aSToby Isaac else { 23116ecaa68aSToby Isaac matSize = numRowIndices * numColIndices; 23126ecaa68aSToby Isaac } 2313f13f9184SToby Isaac } else if (maxChildId == -1) { 23148d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */ 2315f13f9184SToby Isaac PetscInt aOff, a; 23166ecaa68aSToby Isaac 23175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,p,&aOff)); 23186ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23196ecaa68aSToby Isaac PetscInt fDof; 23206ecaa68aSToby Isaac 23215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 232221968bf8SToby Isaac offsets[f+1] = fDof; 23236ecaa68aSToby Isaac } 23246ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 23256ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof; 23266ecaa68aSToby Isaac 23275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(localCoarse,anchor,&aLocalDof)); 23286ecaa68aSToby Isaac numColIndices += aLocalDof; 23296ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 23306ecaa68aSToby Isaac PetscInt fDof; 23316ecaa68aSToby Isaac 23325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof)); 233321968bf8SToby Isaac newOffsets[f+1] += fDof; 23346ecaa68aSToby Isaac } 23356ecaa68aSToby Isaac } 23366ecaa68aSToby Isaac if (numFields) { 23376ecaa68aSToby Isaac matSize = 0; 23386ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 233921968bf8SToby Isaac matSize += offsets[f+1] * newOffsets[f+1]; 23406ecaa68aSToby Isaac } 23416ecaa68aSToby Isaac } 23426ecaa68aSToby Isaac else { 23436ecaa68aSToby Isaac matSize = numColIndices * dof; 23446ecaa68aSToby Isaac } 23456ecaa68aSToby Isaac } 23466ecaa68aSToby Isaac else { /* no children, and no constraints on dofs: just get the global indices */ 23476ecaa68aSToby Isaac numColIndices = dof; 23486ecaa68aSToby Isaac matSize = 0; 23496ecaa68aSToby Isaac } 23508d2f55e7SToby Isaac } 235146bdb399SToby Isaac /* we will pack the column indices with the field offsets */ 23525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(rootIndicesSec,p,numColIndices ? numColIndices+2*numFields : 0)); 23535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(rootMatricesSec,p,matSize)); 23546ecaa68aSToby Isaac } 23555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(rootIndicesSec)); 23565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(rootMatricesSec)); 23576ecaa68aSToby Isaac { 23586ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices; 23596ecaa68aSToby Isaac 23605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices)); 23615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(rootMatricesSec,&numRootMatrices)); 23625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(numRootIndices,&rootIndices,numRootMatrices,&rootMatrices)); 23636ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) { 23646ecaa68aSToby Isaac PetscInt numRowIndices, numColIndices, matSize, dof; 2365f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f; 23666ecaa68aSToby Isaac PetscInt *pInd; 23676ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 23686ecaa68aSToby Isaac PetscScalar *pMat = NULL; 23696ecaa68aSToby Isaac 23705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootIndicesSec,p,&numColIndices)); 23716ecaa68aSToby Isaac if (!numColIndices) { 23726ecaa68aSToby Isaac continue; 23736ecaa68aSToby Isaac } 2374f13f9184SToby Isaac for (f = 0; f <= numFields; f++) { 2375f13f9184SToby Isaac offsets[f] = 0; 2376f13f9184SToby Isaac newOffsets[f] = 0; 2377f13f9184SToby Isaac offsetsCopy[f] = 0; 2378f13f9184SToby Isaac newOffsetsCopy[f] = 0; 2379f13f9184SToby Isaac } 23806ecaa68aSToby Isaac numColIndices -= 2 * numFields; 23815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootIndicesSec,p,&pIndOff)); 23826ecaa68aSToby Isaac pInd = &(rootIndices[pIndOff]); 23835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootMatricesSec,p,&matSize)); 23846ecaa68aSToby Isaac if (matSize) { 23855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootMatricesSec,p,&pMatOff)); 23866ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff]; 23876ecaa68aSToby Isaac } 23885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalCoarse,p,&dof)); 23891cfc5b76SToby Isaac if (dof < 0) { 23901cfc5b76SToby Isaac dof = -(dof + 1); 23911cfc5b76SToby Isaac } 23926ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 23936ecaa68aSToby Isaac PetscInt i, j; 23946ecaa68aSToby Isaac PetscInt numRowIndices = matSize / numColIndices; 23956ecaa68aSToby Isaac 23966ecaa68aSToby Isaac if (!numRowIndices) { /* don't need to calculate the mat, just the indices */ 23976ecaa68aSToby Isaac PetscInt numIndices, *indices; 23985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetClosureIndices(coarse,localCoarse,globalCoarse,p,PETSC_TRUE,&numIndices,&indices,offsets,NULL)); 23992c71b3e2SJacob Faibussowitsch PetscCheckFalse(numIndices != numColIndices,PETSC_COMM_SELF,PETSC_ERR_PLIB,"mismatching constraint indices calculations"); 24006ecaa68aSToby Isaac for (i = 0; i < numColIndices; i++) { 24016ecaa68aSToby Isaac pInd[i] = indices[i]; 24026ecaa68aSToby Isaac } 24036ecaa68aSToby Isaac for (i = 0; i < numFields; i++) { 240446bdb399SToby Isaac pInd[numColIndices + i] = offsets[i+1]; 240546bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i+1]; 24066ecaa68aSToby Isaac } 24075f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreClosureIndices(coarse,localCoarse,globalCoarse,p,PETSC_TRUE,&numIndices,&indices,offsets,NULL)); 24086ecaa68aSToby Isaac } 24096ecaa68aSToby Isaac else { 24106ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl; 24116ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified; 24126ecaa68aSToby Isaac PetscInt numPoints,*points; 24136ecaa68aSToby Isaac 24145f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(coarse,numRowIndices * numRowIndices,MPIU_SCALAR,&pMatIn)); 24156ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */ 24166ecaa68aSToby Isaac for (j = 0; j < numRowIndices; j++) { 24176ecaa68aSToby Isaac pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.; 24186ecaa68aSToby Isaac } 24196ecaa68aSToby Isaac } 24205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 24214acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24225f80ce2aSJacob Faibussowitsch if (numFields) CHKERRQ(PetscSectionGetFieldPointSyms(localCoarse,f,closureSize,closure,&perms[f],&flips[f])); 24235f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetPointSyms(localCoarse,closureSize,closure,&perms[f],&flips[f])); 24244acb8e1eSToby Isaac } 24256ecaa68aSToby Isaac if (numFields) { 24266ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) { 24276ecaa68aSToby Isaac PetscInt c = closure[2 * cl]; 24286ecaa68aSToby Isaac 24296ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24306ecaa68aSToby Isaac PetscInt fDof; 24316ecaa68aSToby Isaac 24325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,c,f,&fDof)); 24336ecaa68aSToby Isaac offsets[f + 1] += fDof; 24346ecaa68aSToby Isaac } 24356ecaa68aSToby Isaac } 24366ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 24376ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 24386ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1]; 24396ecaa68aSToby Isaac } 24406ecaa68aSToby Isaac } 24414acb8e1eSToby Isaac /* TODO : flips here ? */ 24426ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */ 24435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,perms,pMatIn,&numPoints,NULL,&points,&pMatModified,newOffsets,PETSC_FALSE)); 24444acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24455f80ce2aSJacob Faibussowitsch if (numFields) CHKERRQ(PetscSectionRestoreFieldPointSyms(localCoarse,f,closureSize,closure,&perms[f],&flips[f])); 24465f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionRestorePointSyms(localCoarse,closureSize,closure,&perms[f],&flips[f])); 24474acb8e1eSToby Isaac } 24484acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24495f80ce2aSJacob Faibussowitsch if (numFields) CHKERRQ(PetscSectionGetFieldPointSyms(localCoarse,f,numPoints,points,&perms[f],&flips[f])); 24505f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionGetPointSyms(localCoarse,numPoints,points,&perms[f],&flips[f])); 24514acb8e1eSToby Isaac } 24526ecaa68aSToby Isaac if (!numFields) { 24536ecaa68aSToby Isaac for (i = 0; i < numRowIndices * numColIndices; i++) { 24546ecaa68aSToby Isaac pMat[i] = pMatModified[i]; 24556ecaa68aSToby Isaac } 24566ecaa68aSToby Isaac } 24576ecaa68aSToby Isaac else { 2458f13f9184SToby Isaac PetscInt i, j, count; 24596ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 24606ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f+1]; i++) { 24616ecaa68aSToby Isaac for (j = newOffsets[f]; j < newOffsets[f+1]; j++, count++) { 24626ecaa68aSToby Isaac pMat[count] = pMatModified[i * numColIndices + j]; 24636ecaa68aSToby Isaac } 24646ecaa68aSToby Isaac } 24656ecaa68aSToby Isaac } 24666ecaa68aSToby Isaac } 24675f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(coarse,numRowIndices * numColIndices,MPIU_SCALAR,&pMatModified)); 24685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure)); 24695f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(coarse,numRowIndices * numColIndices,MPIU_SCALAR,&pMatIn)); 24706ecaa68aSToby Isaac if (numFields) { 247146bdb399SToby Isaac for (f = 0; f < numFields; f++) { 247246bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 247346bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 24746ecaa68aSToby Isaac } 24754acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 24764acb8e1eSToby Isaac PetscInt globalOff, c = points[2*cl]; 24775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 24785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd)); 24796ecaa68aSToby Isaac } 24806ecaa68aSToby Isaac } else { 24814acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) { 24824acb8e1eSToby Isaac PetscInt c = points[2*cl], globalOff; 24834acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL; 24844acb8e1eSToby Isaac 24855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCoarse, c, &globalOff)); 24865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd)); 24876ecaa68aSToby Isaac } 24886ecaa68aSToby Isaac } 24894acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) { 24905f80ce2aSJacob Faibussowitsch if (numFields) CHKERRQ(PetscSectionRestoreFieldPointSyms(localCoarse,f,numPoints,points,&perms[f],&flips[f])); 24915f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSectionRestorePointSyms(localCoarse,numPoints,points,&perms[f],&flips[f])); 24924acb8e1eSToby Isaac } 24935f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(coarse,numPoints,MPIU_SCALAR,&points)); 24946ecaa68aSToby Isaac } 24956ecaa68aSToby Isaac } 24966ecaa68aSToby Isaac else if (matSize) { 24976ecaa68aSToby Isaac PetscInt cOff; 24986ecaa68aSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof, aOff; 24996ecaa68aSToby Isaac 25006ecaa68aSToby Isaac numRowIndices = matSize / numColIndices; 25012c71b3e2SJacob Faibussowitsch PetscCheckFalse(numRowIndices != dof,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Miscounted dofs"); 25025f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(coarse,numRowIndices,MPIU_INT,&rowIndices)); 25035f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(coarse,numColIndices,MPIU_INT,&colIndices)); 25045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(cSec,p,&cOff)); 25055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec,p,&aDof)); 25065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,p,&aOff)); 25076ecaa68aSToby Isaac if (numFields) { 25086ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25096ecaa68aSToby Isaac PetscInt fDof; 2510f13f9184SToby Isaac 25115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSec,p,f,&fDof)); 25126ecaa68aSToby Isaac offsets[f + 1] = fDof; 25136ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25146ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof)); 25166ecaa68aSToby Isaac newOffsets[f + 1] += fDof; 25176ecaa68aSToby Isaac } 25186ecaa68aSToby Isaac } 25196ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25206ecaa68aSToby Isaac offsets[f + 1] += offsets[f]; 25216ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 25226ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f]; 25236ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1]; 25246ecaa68aSToby Isaac } 25255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(cSec,PETSC_TRUE,p,cOff,offsetsCopy,PETSC_TRUE,NULL,-1, NULL,rowIndices)); 25266ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25276ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(localCoarse,anchor,&lOff)); 25295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_TRUE,anchor,lOff,newOffsetsCopy,PETSC_TRUE,NULL,-1, NULL,colIndices)); 25306ecaa68aSToby Isaac } 25316ecaa68aSToby Isaac } 25326ecaa68aSToby Isaac else { 25335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(cSec,PETSC_TRUE,p,cOff,offsetsCopy,PETSC_TRUE,NULL, NULL,rowIndices)); 25346ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25356ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff; 25365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(localCoarse,anchor,&lOff)); 25375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_TRUE,anchor,lOff,newOffsetsCopy,PETSC_TRUE,NULL, NULL,colIndices)); 25386ecaa68aSToby Isaac } 25396ecaa68aSToby Isaac } 25406ecaa68aSToby Isaac if (numFields) { 2541f13f9184SToby Isaac PetscInt count, a; 2542f13f9184SToby Isaac 25436ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 25446ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f]; 25456ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f]; 25465f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetValues(cMat,iSize,&rowIndices[offsets[f]],jSize,&colIndices[newOffsets[f]],&pMat[count])); 25476ecaa68aSToby Isaac count += iSize * jSize; 254846bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 254946bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f+1]; 25506ecaa68aSToby Isaac } 25516ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25526ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25536ecaa68aSToby Isaac PetscInt gOff; 25545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCoarse,anchor,&gOff)); 25555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,NULL,-1, NULL,pInd)); 25566ecaa68aSToby Isaac } 25576ecaa68aSToby Isaac } 25586ecaa68aSToby Isaac else { 25596ecaa68aSToby Isaac PetscInt a; 25605f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetValues(cMat,numRowIndices,rowIndices,numColIndices,colIndices,pMat)); 25616ecaa68aSToby Isaac for (a = 0; a < aDof; a++) { 25626ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff]; 25636ecaa68aSToby Isaac PetscInt gOff; 25645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCoarse,anchor,&gOff)); 25655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,NULL, NULL,pInd)); 25666ecaa68aSToby Isaac } 25676ecaa68aSToby Isaac } 25685f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(coarse,numColIndices,MPIU_INT,&colIndices)); 25695f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(coarse,numRowIndices,MPIU_INT,&rowIndices)); 25706ecaa68aSToby Isaac } 25716ecaa68aSToby Isaac else { 25726ecaa68aSToby Isaac PetscInt gOff; 25736ecaa68aSToby Isaac 25745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCoarse,p,&gOff)); 25756ecaa68aSToby Isaac if (numFields) { 25766ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 25776ecaa68aSToby Isaac PetscInt fDof; 25785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 25796ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f]; 25806ecaa68aSToby Isaac } 25816ecaa68aSToby Isaac for (f = 0; f < numFields; f++) { 258246bdb399SToby Isaac pInd[numColIndices + f] = offsets[f+1]; 258346bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f+1]; 25846ecaa68aSToby Isaac } 25855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,-1, NULL,pInd)); 2586367003a6SStefano Zampini } else { 25875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL, NULL,pInd)); 25886ecaa68aSToby Isaac } 25896ecaa68aSToby Isaac } 25906ecaa68aSToby Isaac } 25915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(maxChildIds)); 25926ecaa68aSToby Isaac } 259346bdb399SToby Isaac { 259446bdb399SToby Isaac PetscSF indicesSF, matricesSF; 259546bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices; 259646bdb399SToby Isaac 25975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec)); 25985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafMatricesSec)); 25995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(coarseToFineEmbedded,rootIndicesSec,&remoteOffsetsIndices,leafIndicesSec)); 26005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(coarseToFineEmbedded,rootMatricesSec,&remoteOffsetsMatrices,leafMatricesSec)); 26015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(coarseToFineEmbedded,rootIndicesSec,remoteOffsetsIndices,leafIndicesSec,&indicesSF)); 26025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(coarseToFineEmbedded,rootMatricesSec,remoteOffsetsMatrices,leafMatricesSec,&matricesSF)); 26035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&coarseToFineEmbedded)); 26045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsetsIndices)); 26055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsetsMatrices)); 26065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(leafIndicesSec,&numLeafIndices)); 26075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(leafMatricesSec,&numLeafMatrices)); 26085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(numLeafIndices,&leafIndices,numLeafMatrices,&leafMatrices)); 26095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(indicesSF,MPIU_INT,rootIndices,leafIndices,MPI_REPLACE)); 26105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices,MPI_REPLACE)); 26115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(indicesSF,MPIU_INT,rootIndices,leafIndices,MPI_REPLACE)); 26125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(matricesSF,MPIU_SCALAR,rootMatrices,leafMatrices,MPI_REPLACE)); 26135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&matricesSF)); 26145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&indicesSF)); 26155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(rootIndices,rootMatrices)); 26165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&rootIndicesSec)); 26175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&rootMatricesSec)); 261846bdb399SToby Isaac } 261946bdb399SToby Isaac /* count to preallocate */ 26205f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(fine,&localFine)); 262146bdb399SToby Isaac { 262246bdb399SToby Isaac PetscInt nGlobal; 262346bdb399SToby Isaac PetscInt *dnnz, *onnz; 2624b9a5774bSToby Isaac PetscLayout rowMap, colMap; 2625b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 26261c58ffc4SToby Isaac PetscInt maxDof; 26271c58ffc4SToby Isaac PetscInt *rowIndices; 26281c58ffc4SToby Isaac DM refTree; 26291c58ffc4SToby Isaac PetscInt **refPointFieldN; 26301c58ffc4SToby Isaac PetscScalar ***refPointFieldMats; 26311c58ffc4SToby Isaac PetscSection refConSec, refAnSec; 26320eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,maxConDof,maxColumns,leafStart,leafEnd; 26331c58ffc4SToby Isaac PetscScalar *pointWork; 263446bdb399SToby Isaac 26355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstrainedStorageSize(globalFine,&nGlobal)); 26365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc2(nGlobal,&dnnz,nGlobal,&onnz)); 26375f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLayouts(mat,&rowMap,&colMap)); 26385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(rowMap)); 26395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(colMap)); 26405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRange(rowMap,&rowStart,&rowEnd)); 26415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRange(colMap,&colStart,&colEnd)); 26425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(localFine,&maxDof)); 26435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(leafIndicesSec,&leafStart,&leafEnd)); 26445f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(fine,maxDof,MPIU_INT,&rowIndices)); 26450eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 264646bdb399SToby Isaac PetscInt gDof, gcDof, gOff; 264746bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd; 264846bdb399SToby Isaac PetscInt matSize; 264921968bf8SToby Isaac PetscInt i; 265046bdb399SToby Isaac 26515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&gDof)); 26525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&gcDof)); 265346bdb399SToby Isaac if ((gDof - gcDof) <= 0) { 265446bdb399SToby Isaac continue; 265546bdb399SToby Isaac } 26565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalFine,p,&gOff)); 26572c71b3e2SJacob Faibussowitsch PetscCheckFalse(gOff < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"I though having global dofs meant a non-negative offset"); 26582c71b3e2SJacob Faibussowitsch PetscCheckFalse((gOff < rowStart) || ((gOff + gDof - gcDof) > rowEnd),PETSC_COMM_SELF,PETSC_ERR_PLIB,"I thought the row map would constrain the global dofs"); 26595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(leafIndicesSec,p,&numColIndices)); 26605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(leafIndicesSec,p,&pIndOff)); 266146bdb399SToby Isaac numColIndices -= 2 * numFields; 26622c71b3e2SJacob Faibussowitsch PetscCheckFalse(numColIndices <= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"global fine dof with no dofs to interpolate from"); 266346bdb399SToby Isaac pInd = &leafIndices[pIndOff]; 266421968bf8SToby Isaac offsets[0] = 0; 266521968bf8SToby Isaac offsetsCopy[0] = 0; 266621968bf8SToby Isaac newOffsets[0] = 0; 266721968bf8SToby Isaac newOffsetsCopy[0] = 0; 266846bdb399SToby Isaac if (numFields) { 266921968bf8SToby Isaac PetscInt f; 267046bdb399SToby Isaac for (f = 0; f < numFields; f++) { 267146bdb399SToby Isaac PetscInt rowDof; 267246bdb399SToby Isaac 26735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localFine,p,f,&rowDof)); 267421968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 267521968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 267621968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 267721968bf8SToby Isaac numD[f] = 0; 267821968bf8SToby Isaac numO[f] = 0; 267946bdb399SToby Isaac } 26805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,rowIndices)); 268146bdb399SToby Isaac for (f = 0; f < numFields; f++) { 268221968bf8SToby Isaac PetscInt colOffset = newOffsets[f]; 268321968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f]; 268446bdb399SToby Isaac 268546bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) { 268646bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset]; 268746bdb399SToby Isaac 268846bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 268921968bf8SToby Isaac numD[f]++; 269046bdb399SToby Isaac } 269146bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 269221968bf8SToby Isaac numO[f]++; 269346bdb399SToby Isaac } 269446bdb399SToby Isaac } 269546bdb399SToby Isaac } 269646bdb399SToby Isaac } 269746bdb399SToby Isaac else { 26985f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,rowIndices)); 269921968bf8SToby Isaac numD[0] = 0; 270021968bf8SToby Isaac numO[0] = 0; 270146bdb399SToby Isaac for (i = 0; i < numColIndices; i++) { 270246bdb399SToby Isaac PetscInt gInd = pInd[i]; 270346bdb399SToby Isaac 270446bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) { 270521968bf8SToby Isaac numD[0]++; 270646bdb399SToby Isaac } 270746bdb399SToby Isaac else if (gInd >= 0) { /* negative means non-entry */ 270821968bf8SToby Isaac numO[0]++; 270946bdb399SToby Isaac } 271046bdb399SToby Isaac } 271146bdb399SToby Isaac } 27125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(leafMatricesSec,p,&matSize)); 271346bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */ 271446bdb399SToby Isaac PetscInt childId; 271546bdb399SToby Isaac 271646bdb399SToby Isaac childId = childIds[p-pStartF]; 271721968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */ 271846bdb399SToby Isaac if (numFields) { 2719b9a5774bSToby Isaac PetscInt f; 2720b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 272121968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 272246bdb399SToby Isaac for (row = 0; row < numRows; row++) { 272321968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row]; 272421968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 272546bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 27262c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine < rowStart || gIndFine >= rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2727b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1; 272846bdb399SToby Isaac } 272946bdb399SToby Isaac else if (gIndCoarse >= 0) { /* remote */ 27302c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine < rowStart || gIndFine >= rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2731b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 273246bdb399SToby Isaac } 273346bdb399SToby Isaac else { /* constrained */ 27342c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine >= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 273546bdb399SToby Isaac } 273646bdb399SToby Isaac } 273746bdb399SToby Isaac } 273846bdb399SToby Isaac } 273946bdb399SToby Isaac else { 2740b9a5774bSToby Isaac PetscInt i; 2741b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 274246bdb399SToby Isaac PetscInt gIndCoarse = pInd[i]; 274346bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 274446bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */ 27452c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine < rowStart || gIndFine >= rowEnd,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 */ 27492c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine < rowStart || gIndFine >= rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2750b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1; 275146bdb399SToby Isaac } 275246bdb399SToby Isaac else { /* constrained */ 27532c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine >= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 275446bdb399SToby Isaac } 275546bdb399SToby Isaac } 275646bdb399SToby Isaac } 275746bdb399SToby Isaac } 275846bdb399SToby Isaac else { /* interpolate from all */ 275946bdb399SToby Isaac if (numFields) { 2760b9a5774bSToby Isaac PetscInt f; 2761b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 276221968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 276346bdb399SToby Isaac for (row = 0; row < numRows; row++) { 276421968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 276546bdb399SToby Isaac if (gIndFine >= 0) { 27662c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine < rowStart || gIndFine >= rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2767b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2768b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 276946bdb399SToby Isaac } 277046bdb399SToby Isaac } 277146bdb399SToby Isaac } 277246bdb399SToby Isaac } 277346bdb399SToby Isaac else { 2774b9a5774bSToby Isaac PetscInt i; 2775b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 277646bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 277746bdb399SToby Isaac if (gIndFine >= 0) { 27782c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine < rowStart || gIndFine >= rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2779b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2780b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 278146bdb399SToby Isaac } 278246bdb399SToby Isaac } 278346bdb399SToby Isaac } 278446bdb399SToby Isaac } 278546bdb399SToby Isaac } 278646bdb399SToby Isaac else { /* interpolate from all */ 278746bdb399SToby Isaac if (numFields) { 2788b9a5774bSToby Isaac PetscInt f; 2789b9a5774bSToby Isaac for (f = 0; f < numFields; f++) { 279021968bf8SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 279146bdb399SToby Isaac for (row = 0; row < numRows; row++) { 279221968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row]; 279346bdb399SToby Isaac if (gIndFine >= 0) { 27942c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine < rowStart || gIndFine >= rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2795b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f]; 2796b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f]; 279746bdb399SToby Isaac } 279846bdb399SToby Isaac } 279946bdb399SToby Isaac } 280046bdb399SToby Isaac } 280146bdb399SToby Isaac else { /* every dof get a full row */ 2802b9a5774bSToby Isaac PetscInt i; 2803b9a5774bSToby Isaac for (i = 0; i < gDof; i++) { 280446bdb399SToby Isaac PetscInt gIndFine = rowIndices[i]; 280546bdb399SToby Isaac if (gIndFine >= 0) { 28062c71b3e2SJacob Faibussowitsch PetscCheckFalse(gIndFine < rowStart || gIndFine >= rowEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs"); 2807b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0]; 2808b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0]; 280946bdb399SToby Isaac } 281046bdb399SToby Isaac } 281146bdb399SToby Isaac } 281246bdb399SToby Isaac } 281346bdb399SToby Isaac } 28145f80ce2aSJacob Faibussowitsch CHKERRQ(MatXAIJSetPreallocation(mat,1,dnnz,onnz,NULL,NULL)); 28155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(dnnz,onnz)); 281621968bf8SToby Isaac 28175f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetReferenceTree(fine,&refTree)); 28185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 28195f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 28205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(refTree,&refAnSec,NULL)); 28215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 28225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(refConSec,&maxConDof)); 28235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(leafIndicesSec,&maxColumns)); 28245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxConDof*maxColumns,&pointWork)); 28250eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 2826e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff; 2827e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd; 2828e44e4e7fSToby Isaac PetscInt matSize; 2829e44e4e7fSToby Isaac PetscInt childId; 2830e44e4e7fSToby Isaac 28315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&gDof)); 28325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&gcDof)); 2833e44e4e7fSToby Isaac if ((gDof - gcDof) <= 0) { 2834e44e4e7fSToby Isaac continue; 2835e44e4e7fSToby Isaac } 2836e44e4e7fSToby Isaac childId = childIds[p-pStartF]; 28375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalFine,p,&gOff)); 28385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(leafIndicesSec,p,&numColIndices)); 28395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(leafIndicesSec,p,&pIndOff)); 2840e44e4e7fSToby Isaac numColIndices -= 2 * numFields; 2841e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff]; 2842e44e4e7fSToby Isaac offsets[0] = 0; 2843e44e4e7fSToby Isaac offsetsCopy[0] = 0; 2844e44e4e7fSToby Isaac newOffsets[0] = 0; 2845e44e4e7fSToby Isaac newOffsetsCopy[0] = 0; 2846e44e4e7fSToby Isaac rowOffsets[0] = 0; 2847e44e4e7fSToby Isaac if (numFields) { 2848e44e4e7fSToby Isaac PetscInt f; 2849e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2850e44e4e7fSToby Isaac PetscInt rowDof; 2851e44e4e7fSToby Isaac 28525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localFine,p,f,&rowDof)); 2853e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof; 2854e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 2855e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f]; 2856e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f]; 2857e44e4e7fSToby Isaac } 28585f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,rowIndices)); 2859e44e4e7fSToby Isaac } 28601c58ffc4SToby Isaac else { 28615f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,rowIndices)); 28621c58ffc4SToby Isaac } 28635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(leafMatricesSec,p,&matSize)); 2864e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */ 2865e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */ 2866e44e4e7fSToby Isaac if (numFields) { 2867e44e4e7fSToby Isaac PetscInt f; 2868e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2869e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f], row; 2870e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 28715f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(mat,rowIndices[offsets[f]+row],pInd[newOffsets[f]+row],1.,INSERT_VALUES)); 287221968bf8SToby Isaac } 287321968bf8SToby Isaac } 2874e44e4e7fSToby Isaac } 2875e44e4e7fSToby Isaac else { 2876e44e4e7fSToby Isaac PetscInt numRows = gDof, row; 2877e44e4e7fSToby Isaac for (row = 0; row < numRows; row++) { 28785f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(mat,rowIndices[row],pInd[row],1.,INSERT_VALUES)); 2879e44e4e7fSToby Isaac } 2880e44e4e7fSToby Isaac } 2881e44e4e7fSToby Isaac } 2882e44e4e7fSToby Isaac else { /* interpolate from all */ 2883e44e4e7fSToby Isaac if (numFields) { 2884e44e4e7fSToby Isaac PetscInt f; 2885e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) { 2886e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 2887e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 28885f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],refPointFieldMats[childId - pRefStart][f],INSERT_VALUES)); 2889e44e4e7fSToby Isaac } 2890e44e4e7fSToby Isaac } 2891e44e4e7fSToby Isaac else { 28925f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,refPointFieldMats[childId - pRefStart][0],INSERT_VALUES)); 2893e44e4e7fSToby Isaac } 2894e44e4e7fSToby Isaac } 2895e44e4e7fSToby Isaac } 2896e44e4e7fSToby Isaac else { /* interpolate from all */ 2897e44e4e7fSToby Isaac PetscInt pMatOff; 2898e44e4e7fSToby Isaac PetscScalar *pMat; 2899e44e4e7fSToby Isaac 29005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(leafMatricesSec,p,&pMatOff)); 2901e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff]; 2902e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */ 2903e44e4e7fSToby Isaac if (numFields) { 2904e44e4e7fSToby Isaac PetscInt f, count; 2905e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2906e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2907e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2908e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2909e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2910e44e4e7fSToby Isaac 29115f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],inMat,INSERT_VALUES)); 2912e44e4e7fSToby Isaac count += numCols * numInRows; 2913e44e4e7fSToby Isaac } 2914e44e4e7fSToby Isaac } 2915e44e4e7fSToby Isaac else { 29165f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,gDof,rowIndices,numColIndices,pInd,pMat,INSERT_VALUES)); 2917e44e4e7fSToby Isaac } 2918e44e4e7fSToby Isaac } 2919e44e4e7fSToby Isaac else { /* multiply the incoming matrix by the child interpolation */ 2920e44e4e7fSToby Isaac if (numFields) { 2921e44e4e7fSToby Isaac PetscInt f, count; 2922e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) { 2923e44e4e7fSToby Isaac PetscInt numRows = offsets[f+1]-offsets[f]; 2924e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f+1]-newOffsets[f]; 2925e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f+1]-rowOffsets[f]; 2926e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count]; 2927e44e4e7fSToby Isaac PetscInt i, j, k; 29282c71b3e2SJacob Faibussowitsch PetscCheckFalse(refPointFieldN[childId - pRefStart][f] != numInRows,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2929e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2930e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2931e44e4e7fSToby Isaac PetscScalar val = 0.; 2932e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2933e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j]; 2934e44e4e7fSToby Isaac } 2935e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2936e44e4e7fSToby Isaac } 2937e44e4e7fSToby Isaac } 29385f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,numRows,&rowIndices[offsets[f]],numCols,&pInd[newOffsets[f]],pointWork,INSERT_VALUES)); 2939e44e4e7fSToby Isaac count += numCols * numInRows; 2940e44e4e7fSToby Isaac } 2941e44e4e7fSToby Isaac } 2942267d4f3fSToby Isaac else { /* every dof gets a full row */ 2943e44e4e7fSToby Isaac PetscInt numRows = gDof; 2944e44e4e7fSToby Isaac PetscInt numCols = numColIndices; 2945e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices; 2946e44e4e7fSToby Isaac PetscInt i, j, k; 29472c71b3e2SJacob Faibussowitsch PetscCheckFalse(refPointFieldN[childId - pRefStart][0] != numInRows,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Point constraint matrix multiply dimension mismatch"); 2948e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) { 2949e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) { 2950e44e4e7fSToby Isaac PetscScalar val = 0.; 2951e44e4e7fSToby Isaac for (k = 0; k < numInRows; k++) { 2952e44e4e7fSToby Isaac val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j]; 2953e44e4e7fSToby Isaac } 2954e44e4e7fSToby Isaac pointWork[i * numCols + j] = val; 2955e44e4e7fSToby Isaac } 2956e44e4e7fSToby Isaac } 29575f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,numRows,rowIndices,numCols,pInd,pointWork,INSERT_VALUES)); 2958e44e4e7fSToby Isaac } 2959e44e4e7fSToby Isaac } 2960e44e4e7fSToby Isaac } 2961e44e4e7fSToby Isaac } 29625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 29635f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(fine,maxDof,MPIU_INT,&rowIndices)); 29645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pointWork)); 2965e44e4e7fSToby Isaac } 29665f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 29675f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 29685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&leafIndicesSec)); 29695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&leafMatricesSec)); 29705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(leafIndices,leafMatrices)); 29715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(*(PetscInt****)&perms,*(PetscScalar****)&flips)); 29725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO)); 29735f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(aIS,&anchors)); 29746ecaa68aSToby Isaac PetscFunctionReturn(0); 29756ecaa68aSToby Isaac } 2976154bca37SToby Isaac 29778d2f55e7SToby Isaac /* 29788d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis: 29798d2f55e7SToby Isaac * 29808d2f55e7SToby Isaac * for each coarse dof \phi^c_i: 29818d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i: 29828d2f55e7SToby Isaac * for each fine dof \phi^f_j; 29838d2f55e7SToby Isaac * a_{i,j} = 0; 29848d2f55e7SToby Isaac * for each fine dof \phi^f_k: 29858d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l 29868d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^] 29878d2f55e7SToby Isaac */ 29888d2f55e7SToby Isaac PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj) 29898d2f55e7SToby Isaac { 29908d2f55e7SToby Isaac PetscDS ds; 29918d2f55e7SToby Isaac PetscSection section, cSection; 29928d2f55e7SToby Isaac DMLabel canonical, depth; 29938d2f55e7SToby Isaac Mat cMat, mat; 29948d2f55e7SToby Isaac PetscInt *nnz; 29958d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd; 29968d2f55e7SToby Isaac PetscInt m, n; 29978d2f55e7SToby Isaac PetscScalar *pointScalar; 29988d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent; 29998d2f55e7SToby Isaac 30008d2f55e7SToby Isaac PetscFunctionBegin; 30015f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(refTree,§ion)); 30025f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(refTree, &dim)); 30035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc6(dim,&v0,dim,&v0parent,dim,&vtmp,dim*dim,&J,dim*dim,&Jparent,dim*dim,&invJ)); 30045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(dim,&pointScalar,dim,&pointRef)); 30055f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(refTree,&ds)); 30065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds,&numFields)); 30075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(section,&numSecFields)); 30085f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(refTree,"canonical",&canonical)); 30095f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(refTree,"depth",&depth)); 30105f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&cSection,&cMat,NULL)); 30115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(refTree, &pStart, &pEnd)); 30125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd)); 30135f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(cMat,&n,&m)); /* the injector has transpose sizes from the constraint matrix */ 30148d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */ 30155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(m,&nnz)); 30168d2f55e7SToby 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 */ 30178d2f55e7SToby Isaac const PetscInt *children; 30188d2f55e7SToby Isaac PetscInt numChildren; 30198d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30208d2f55e7SToby Isaac 30218d2f55e7SToby Isaac if (canonical) { 30228d2f55e7SToby Isaac PetscInt pCanonical; 30235f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(canonical,p,&pCanonical)); 30248d2f55e7SToby Isaac if (p != pCanonical) continue; 30258d2f55e7SToby Isaac } 30265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(refTree,p,&numChildren,&children)); 30278d2f55e7SToby Isaac if (!numChildren) continue; 30288d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30298d2f55e7SToby Isaac PetscInt child = children[i]; 30308d2f55e7SToby Isaac PetscInt dof; 30318d2f55e7SToby Isaac 30325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,child,&dof)); 30338d2f55e7SToby Isaac numChildDof += dof; 30348d2f55e7SToby Isaac } 30355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,p,&numSelfDof)); 30368d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30378d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 30388d2f55e7SToby Isaac PetscInt selfOff; 30398d2f55e7SToby Isaac 30408d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */ 30418d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30428d2f55e7SToby Isaac PetscInt child = children[i]; 30438d2f55e7SToby Isaac PetscInt dof; 30448d2f55e7SToby Isaac 30455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,child,f,&dof)); 30468d2f55e7SToby Isaac numChildDof += dof; 30478d2f55e7SToby Isaac } 30485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,p,f,&numSelfDof)); 30495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(section,p,f,&selfOff)); 30508d2f55e7SToby Isaac } 30518d2f55e7SToby Isaac else { 30525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section,p,&selfOff)); 30538d2f55e7SToby Isaac } 30548d2f55e7SToby Isaac for (i = 0; i < numSelfDof; i++) { 30558d2f55e7SToby Isaac nnz[selfOff + i] = numChildDof; 30568d2f55e7SToby Isaac } 30578d2f55e7SToby Isaac } 30588d2f55e7SToby Isaac } 30595f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateAIJ(PETSC_COMM_SELF,m,n,m,n,-1,nnz,-1,NULL,&mat)); 30605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(nnz)); 30618d2f55e7SToby Isaac /* Setp 2: compute entries */ 30628d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { 30638d2f55e7SToby Isaac const PetscInt *children; 30648d2f55e7SToby Isaac PetscInt numChildren; 30658d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof; 30668d2f55e7SToby Isaac 30678d2f55e7SToby Isaac /* same conditions about when entries occur */ 30688d2f55e7SToby Isaac if (canonical) { 30698d2f55e7SToby Isaac PetscInt pCanonical; 30705f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(canonical,p,&pCanonical)); 30718d2f55e7SToby Isaac if (p != pCanonical) continue; 30728d2f55e7SToby Isaac } 30735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(refTree,p,&numChildren,&children)); 30748d2f55e7SToby Isaac if (!numChildren) continue; 30758d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30768d2f55e7SToby Isaac PetscInt child = children[i]; 30778d2f55e7SToby Isaac PetscInt dof; 30788d2f55e7SToby Isaac 30795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,child,&dof)); 30808d2f55e7SToby Isaac numChildDof += dof; 30818d2f55e7SToby Isaac } 30825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section,p,&numSelfDof)); 30838d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue; 30848d2f55e7SToby Isaac 30858d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 308659fc6756SToby Isaac PetscInt pI = -1, cI = -1; 308752a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell; 30888d2f55e7SToby Isaac PetscInt cellShapeOff; 30898d2f55e7SToby Isaac PetscObject disc; 30908d2f55e7SToby Isaac PetscDualSpace dsp; 30918d2f55e7SToby Isaac PetscClassId classId; 30928d2f55e7SToby Isaac PetscScalar *pointMat; 30933b1c2a6aSToby Isaac PetscInt *matRows, *matCols; 30948d2f55e7SToby Isaac PetscInt pO = PETSC_MIN_INT; 30958d2f55e7SToby Isaac const PetscInt *depthNumDof; 30968d2f55e7SToby Isaac 30978d2f55e7SToby Isaac if (numSecFields) { 30988d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) { 30998d2f55e7SToby Isaac PetscInt child = children[i]; 31008d2f55e7SToby Isaac PetscInt dof; 31018d2f55e7SToby Isaac 31025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,child,f,&dof)); 31038d2f55e7SToby Isaac numChildDof += dof; 31048d2f55e7SToby Isaac } 31055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(section,p,f,&numSelfDof)); 31065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(section,p,f,&selfOff)); 31078d2f55e7SToby Isaac } 31088d2f55e7SToby Isaac else { 31095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section,p,&selfOff)); 31108d2f55e7SToby Isaac } 31118d2f55e7SToby Isaac 31123b1c2a6aSToby Isaac /* find a cell whose closure contains p */ 31138d2f55e7SToby Isaac if (p >= cStart && p < cEnd) { 31148d2f55e7SToby Isaac parentCell = p; 31158d2f55e7SToby Isaac } 31168d2f55e7SToby Isaac else { 31178d2f55e7SToby Isaac PetscInt *star = NULL; 31188d2f55e7SToby Isaac PetscInt numStar; 31198d2f55e7SToby Isaac 31208d2f55e7SToby Isaac parentCell = -1; 31215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star)); 31228d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) { 31238d2f55e7SToby Isaac PetscInt c = star[2 * i]; 31248d2f55e7SToby Isaac 31258d2f55e7SToby Isaac if (c >= cStart && c < cEnd) { 31268d2f55e7SToby Isaac parentCell = c; 31278d2f55e7SToby Isaac break; 31288d2f55e7SToby Isaac } 31298d2f55e7SToby Isaac } 31305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(refTree,p,PETSC_FALSE,&numStar,&star)); 31318d2f55e7SToby Isaac } 3132a5b23f4aSJose E. Roman /* determine the offset of p's shape functions within parentCell's shape functions */ 31335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(ds,f,&disc)); 31345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(disc,&classId)); 3135c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) { 31365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetDualSpace((PetscFE)disc,&dsp)); 3137c5356c36SToby Isaac } 3138c5356c36SToby Isaac else if (classId == PETSCFV_CLASSID) { 31395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFVGetDualSpace((PetscFV)disc,&dsp)); 3140c5356c36SToby Isaac } 3141c5356c36SToby Isaac else { 31429b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported discretization object"); 3143c5356c36SToby Isaac } 31445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetNumDof(dsp,&depthNumDof)); 31455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetNumComponents(dsp,&Nc)); 31468d2f55e7SToby Isaac { 31478d2f55e7SToby Isaac PetscInt *closure = NULL; 31488d2f55e7SToby Isaac PetscInt numClosure; 31498d2f55e7SToby Isaac 31505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure)); 315159fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) { 31528d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth; 31538d2f55e7SToby Isaac 31548d2f55e7SToby Isaac pO = closure[2 * i + 1]; 315559fc6756SToby Isaac if (point == p) { 315659fc6756SToby Isaac pI = i; 315759fc6756SToby Isaac break; 315859fc6756SToby Isaac } 31595f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(depth,point,&pointDepth)); 31608d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth]; 31618d2f55e7SToby Isaac } 31625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(refTree,parentCell,PETSC_TRUE,&numClosure,&closure)); 31638d2f55e7SToby Isaac } 31648d2f55e7SToby Isaac 31655f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR,&pointMat)); 31665f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT,&matRows)); 316752a3aeb4SToby Isaac matCols = matRows + numSelfDof; 316852a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { 316952a3aeb4SToby Isaac matRows[i] = selfOff + i; 31703b1c2a6aSToby Isaac } 317152a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.; 31723b1c2a6aSToby Isaac { 31733b1c2a6aSToby Isaac PetscInt colOff = 0; 31743b1c2a6aSToby Isaac 31753b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) { 31763b1c2a6aSToby Isaac PetscInt child = children[i]; 31773b1c2a6aSToby Isaac PetscInt dof, off, j; 31783b1c2a6aSToby Isaac 31793b1c2a6aSToby Isaac if (numSecFields) { 31805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSection,child,f,&dof)); 31815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(cSection,child,f,&off)); 31823b1c2a6aSToby Isaac } 31833b1c2a6aSToby Isaac else { 31845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSection,child,&dof)); 31855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(cSection,child,&off)); 31863b1c2a6aSToby Isaac } 31873b1c2a6aSToby Isaac 318852a3aeb4SToby Isaac for (j = 0; j < dof; j++) { 318952a3aeb4SToby Isaac matCols[colOff++] = off + j; 31903b1c2a6aSToby Isaac } 31913b1c2a6aSToby Isaac } 31923b1c2a6aSToby Isaac } 31938d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) { 31948d2f55e7SToby Isaac PetscFE fe = (PetscFE) disc; 31958d2f55e7SToby Isaac PetscInt fSize; 319659fc6756SToby Isaac const PetscInt ***perms; 319759fc6756SToby Isaac const PetscScalar ***flips; 319859fc6756SToby Isaac const PetscInt *pperms; 319959fc6756SToby Isaac 32005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEGetDualSpace(fe,&dsp)); 32015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(dsp,&fSize)); 32025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetSymmetries(dsp, &perms, &flips)); 320359fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL; 320452a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */ 32058d2f55e7SToby Isaac PetscQuadrature q; 320652a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k; 32078d2f55e7SToby Isaac const PetscReal *points; 32088d2f55e7SToby Isaac const PetscReal *weights; 32098d2f55e7SToby Isaac PetscInt *closure = NULL; 32108d2f55e7SToby Isaac PetscInt numClosure; 321159fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i; 321259fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell; 3213ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent; 32148d2f55e7SToby Isaac 32155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(dsp,parentCellShapeDof,&q)); 32165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(q,&dim,&thisNc,&numPoints,&points,&weights)); 32172c71b3e2SJacob Faibussowitsch PetscCheckFalse(thisNc != Nc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Functional dim %D does not much basis dim %D",thisNc,Nc); 32185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateTabulation(fe,1,numPoints,points,0,&Tparent)); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */ 32193b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) { 32208d2f55e7SToby Isaac PetscInt childCell = -1; 322152a3aeb4SToby Isaac PetscReal *parentValAtPoint; 3222c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 32238d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j]; 32248d2f55e7SToby Isaac const PetscScalar *point; 3225ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild; 32268d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff; 32278d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX) 32288d2f55e7SToby Isaac PetscInt d; 32298d2f55e7SToby Isaac 32308d2f55e7SToby Isaac for (d = 0; d < dim; d++) { 32318d2f55e7SToby Isaac pointScalar[d] = points[dim * j + d]; 32328d2f55e7SToby Isaac } 32338d2f55e7SToby Isaac point = pointScalar; 32348d2f55e7SToby Isaac #else 32358d2f55e7SToby Isaac point = pointReal; 32368d2f55e7SToby Isaac #endif 32378d2f55e7SToby Isaac 3238ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc]; 32393b1c2a6aSToby Isaac 32403b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/ 32418d2f55e7SToby Isaac PetscInt child = children[k]; 32428d2f55e7SToby Isaac PetscInt *star = NULL; 32438d2f55e7SToby Isaac PetscInt numStar, s; 32448d2f55e7SToby Isaac 32455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star)); 32468d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) { 32478d2f55e7SToby Isaac PetscInt c = star[2 * s]; 32488d2f55e7SToby Isaac 32498d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue; 32505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLocatePoint_Internal(refTree,dim,point,c,&childCell)); 32518d2f55e7SToby Isaac if (childCell >= 0) break; 32528d2f55e7SToby Isaac } 32535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(refTree,child,PETSC_FALSE,&numStar,&star)); 32548d2f55e7SToby Isaac if (childCell >= 0) break; 32558d2f55e7SToby Isaac } 32562c71b3e2SJacob Faibussowitsch PetscCheckFalse(childCell < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not locate quadrature point"); 32575f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ)); 32585f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent)); 3259c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp); 3260c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef); 32618d2f55e7SToby Isaac 32625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateTabulation(fe,1,1,pointRef,0,&Tchild)); 32635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure)); 32643b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */ 3265c5356c36SToby Isaac PetscInt child = children[k], childDepth, childDof, childO = PETSC_MIN_INT; 32668d2f55e7SToby Isaac PetscInt l; 326759fc6756SToby Isaac const PetscInt *cperms; 32688d2f55e7SToby Isaac 32695f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(depth,child,&childDepth)); 32708d2f55e7SToby Isaac childDof = depthNumDof[childDepth]; 327159fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) { 32728d2f55e7SToby Isaac PetscInt point = closure[2 * l]; 32738d2f55e7SToby Isaac PetscInt pointDepth; 32748d2f55e7SToby Isaac 32758d2f55e7SToby Isaac childO = closure[2 * l + 1]; 327659fc6756SToby Isaac if (point == child) { 327759fc6756SToby Isaac cI = l; 327859fc6756SToby Isaac break; 327959fc6756SToby Isaac } 32805f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(depth,point,&pointDepth)); 32818d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth]; 32828d2f55e7SToby Isaac } 32838d2f55e7SToby Isaac if (l == numClosure) { 32848d2f55e7SToby Isaac pointMatOff += childDof; 32858d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */ 32868d2f55e7SToby Isaac } 328759fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL; 32888d2f55e7SToby Isaac for (l = 0; l < childDof; l++) { 328959fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l; 329059fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell; 329152a3aeb4SToby Isaac PetscReal *childValAtPoint; 329252a3aeb4SToby Isaac PetscReal val = 0.; 32938d2f55e7SToby Isaac 3294ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc]; 329552a3aeb4SToby Isaac for (m = 0; m < Nc; m++) { 329652a3aeb4SToby Isaac val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m]; 329752a3aeb4SToby Isaac } 329852a3aeb4SToby Isaac 329952a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val; 33008d2f55e7SToby Isaac } 33018d2f55e7SToby Isaac pointMatOff += childDof; 33028d2f55e7SToby Isaac } 33035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(refTree,childCell,PETSC_TRUE,&numClosure,&closure)); 33045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTabulationDestroy(&Tchild)); 33058d2f55e7SToby Isaac } 33065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTabulationDestroy(&Tparent)); 33078d2f55e7SToby Isaac } 33088d2f55e7SToby Isaac } 3309c5356c36SToby Isaac else { /* just the volume-weighted averages of the children */ 33103b1c2a6aSToby Isaac PetscReal parentVol; 3311bfaa5bdcSToby Isaac PetscInt childCell; 33123b1c2a6aSToby Isaac 33135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL)); 3314bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) { 331552a3aeb4SToby Isaac PetscInt child = children[i], j; 33163b1c2a6aSToby Isaac PetscReal childVol; 33173b1c2a6aSToby Isaac 33183b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue; 33195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL)); 332052a3aeb4SToby Isaac for (j = 0; j < Nc; j++) { 3321bfaa5bdcSToby Isaac pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol; 332252a3aeb4SToby Isaac } 3323bfaa5bdcSToby Isaac childCell++; 33243b1c2a6aSToby Isaac } 33258d2f55e7SToby Isaac } 33263b1c2a6aSToby Isaac /* Insert pointMat into mat */ 33275f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,numSelfDof,matRows,numChildDof,matCols,pointMat,INSERT_VALUES)); 33285f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT,&matRows)); 33295f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR,&pointMat)); 33308d2f55e7SToby Isaac } 33318d2f55e7SToby Isaac } 33325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree6(v0,v0parent,vtmp,J,Jparent,invJ)); 33335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(pointScalar,pointRef)); 33345f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 33355f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 33368d2f55e7SToby Isaac *inj = mat; 33378d2f55e7SToby Isaac PetscFunctionReturn(0); 33388d2f55e7SToby Isaac } 33398d2f55e7SToby Isaac 3340f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3341f30e825dSToby Isaac { 3342f30e825dSToby Isaac PetscDS ds; 3343f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof; 3344f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3345f30e825dSToby Isaac PetscSection refConSec, refSection; 3346f30e825dSToby Isaac 3347f30e825dSToby Isaac PetscFunctionBegin; 33485f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(refTree,&ds)); 33495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds,&numFields)); 33505f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 33515f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(refTree,&refSection)); 33525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 33535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats)); 33545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(refConSec,&maxDof)); 33555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxDof,&rows)); 33565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxDof*maxDof,&cols)); 3357f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3358f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3359f30e825dSToby Isaac 33605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(refTree,p,&parent,NULL)); 33615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refConSec,p,&pDof)); 33625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refSection,parent,&parentDof)); 3363f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3364f30e825dSToby Isaac 33655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart])); 3366f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 336752a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r; 3368f30e825dSToby Isaac 3369f30e825dSToby Isaac if (numFields > 1) { 33705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(refConSec,p,f,&cDof)); 33715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(refConSec,p,f,&cOff)); 3372f30e825dSToby Isaac } 3373f30e825dSToby Isaac else { 33745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refConSec,p,&cDof)); 33755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(refConSec,p,&cOff)); 3376f30e825dSToby Isaac } 3377f30e825dSToby Isaac 3378f30e825dSToby Isaac for (r = 0; r < cDof; r++) { 3379f30e825dSToby Isaac rows[r] = cOff + r; 3380f30e825dSToby Isaac } 3381f30e825dSToby Isaac numCols = 0; 3382f30e825dSToby Isaac { 3383f30e825dSToby Isaac PetscInt aDof, aOff, j; 3384f30e825dSToby Isaac 3385f30e825dSToby Isaac if (numFields > 1) { 33865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(refSection,parent,f,&aDof)); 33875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(refSection,parent,f,&aOff)); 3388f30e825dSToby Isaac } 3389f30e825dSToby Isaac else { 33905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refSection,parent,&aDof)); 33915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(refSection,parent,&aOff)); 3392f30e825dSToby Isaac } 3393f30e825dSToby Isaac 3394f30e825dSToby Isaac for (j = 0; j < aDof; j++) { 3395f30e825dSToby Isaac cols[numCols++] = aOff + j; 3396f30e825dSToby Isaac } 3397f30e825dSToby Isaac } 33985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f])); 3399f30e825dSToby Isaac /* transpose of constraint matrix */ 34005f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetValues(inj,numCols,cols,cDof,rows,refPointFieldMats[p-pRefStart][f])); 3401f30e825dSToby Isaac } 3402f30e825dSToby Isaac } 3403f30e825dSToby Isaac *childrenMats = refPointFieldMats; 34045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rows)); 34055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cols)); 3406f30e825dSToby Isaac PetscFunctionReturn(0); 3407f30e825dSToby Isaac } 3408f30e825dSToby Isaac 3409f30e825dSToby Isaac static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats) 3410f30e825dSToby Isaac { 3411f30e825dSToby Isaac PetscDS ds; 3412f30e825dSToby Isaac PetscScalar ***refPointFieldMats; 3413f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f; 3414c6154584SToby Isaac PetscSection refConSec, refSection; 3415f30e825dSToby Isaac 3416f30e825dSToby Isaac PetscFunctionBegin; 3417f30e825dSToby Isaac refPointFieldMats = *childrenMats; 3418f30e825dSToby Isaac *childrenMats = NULL; 34195f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(refTree,&ds)); 34205f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(refTree,&refSection)); 34215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds,&numFields)); 34225f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 34235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 3424f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 3425f30e825dSToby Isaac PetscInt parent, pDof, parentDof; 3426f30e825dSToby Isaac 34275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(refTree,p,&parent,NULL)); 34285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refConSec,p,&pDof)); 34295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refSection,parent,&parentDof)); 3430f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue; 3431f30e825dSToby Isaac 3432f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3433f30e825dSToby Isaac PetscInt cDof; 3434f30e825dSToby Isaac 3435f30e825dSToby Isaac if (numFields > 1) { 34365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(refConSec,p,f,&cDof)); 3437f30e825dSToby Isaac } 3438f30e825dSToby Isaac else { 34395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(refConSec,p,&cDof)); 3440f30e825dSToby Isaac } 3441f30e825dSToby Isaac 34425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(refPointFieldMats[p - pRefStart][f])); 3443f30e825dSToby Isaac } 34445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(refPointFieldMats[p - pRefStart])); 3445f30e825dSToby Isaac } 34465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(refPointFieldMats)); 3447f30e825dSToby Isaac PetscFunctionReturn(0); 3448f30e825dSToby Isaac } 3449f30e825dSToby Isaac 3450ebf164c7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree,Mat *injRef) 3451154bca37SToby Isaac { 3452ebf164c7SToby Isaac Mat cMatRef; 34536148253fSToby Isaac PetscObject injRefObj; 34548d2f55e7SToby Isaac 3455154bca37SToby Isaac PetscFunctionBegin; 34565f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,NULL,&cMatRef,NULL)); 34575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",&injRefObj)); 3458ebf164c7SToby Isaac *injRef = (Mat) injRefObj; 3459ebf164c7SToby Isaac if (!*injRef) { 34605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeInjectorReferenceTree(refTree,injRef)); 34615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject)cMatRef,"DMPlexComputeInjectorTree_refTree",(PetscObject)*injRef)); 3462ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */ 34635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject)*injRef)); 3464ebf164c7SToby Isaac } 3465ebf164c7SToby Isaac PetscFunctionReturn(0); 34666148253fSToby Isaac } 3467f30e825dSToby Isaac 3468c921d74cSToby Isaac static PetscErrorCode DMPlexTransferInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, const PetscInt *childIds, Vec fineVec, PetscInt numFields, PetscInt *offsets, PetscSection *rootMultiSec, PetscSection *multiLeafSec, PetscInt **gatheredIndices, PetscScalar **gatheredValues) 3469ebf164c7SToby Isaac { 3470c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti; 3471ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3472ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec; 3473c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3474c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL; 3475c921d74cSToby Isaac const PetscInt *rootDegrees; 3476c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL; 3477ebf164c7SToby Isaac PetscSF coarseToFineEmbedded; 3478ebf164c7SToby Isaac 3479ebf164c7SToby Isaac PetscFunctionBegin; 34805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(coarse,&pStartC,&pEndC)); 34815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(fine,&pStartF,&pEndF)); 34825f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(fine,&localFine)); 34835f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(fine,&globalFine)); 34845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec)); 34855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(leafIndicesSec,pStartF, pEndF)); 34865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(localFine,&maxDof)); 34878d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 34887e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices; 34897e96bdafSToby Isaac const PetscInt *leaves; 34908d2f55e7SToby Isaac 34915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL)); 34927e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 34937e96bdafSToby Isaac p = leaves ? leaves[l] : l; 34945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&dof)); 34955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 34968d2f55e7SToby Isaac if ((dof - cdof) > 0) { 34978d2f55e7SToby Isaac numPointsWithDofs++; 3498f30e825dSToby Isaac 34995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(localFine,p,&dof)); 35005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(leafIndicesSec,p,dof + 1)); 35018d2f55e7SToby Isaac } 35028d2f55e7SToby Isaac } 35035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numPointsWithDofs,&pointsWithDofs)); 35045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(leafIndicesSec)); 35055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(leafIndicesSec,&numIndices)); 35065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(gatheredIndices ? numIndices : (maxDof + 1),&leafInds)); 35075f80ce2aSJacob Faibussowitsch if (gatheredValues) CHKERRQ(PetscMalloc1(numIndices,&leafVals)); 35087e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 35097e96bdafSToby Isaac p = leaves ? leaves[l] : l; 35105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&dof)); 35115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 35128d2f55e7SToby Isaac if ((dof - cdof) > 0) { 3513f30e825dSToby Isaac PetscInt off, gOff; 3514f30e825dSToby Isaac PetscInt *pInd; 3515c921d74cSToby Isaac PetscScalar *pVal = NULL; 3516f30e825dSToby Isaac 35177e96bdafSToby Isaac pointsWithDofs[offset++] = l; 3518f30e825dSToby Isaac 35195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(leafIndicesSec,p,&off)); 3520f30e825dSToby Isaac 3521c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds; 3522c921d74cSToby Isaac if (gatheredValues) { 3523c921d74cSToby Isaac PetscInt i; 3524c921d74cSToby Isaac 3525c921d74cSToby Isaac pVal = &leafVals[off + 1]; 3526c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.; 3527c921d74cSToby Isaac } 35285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalFine,p,&gOff)); 3529f30e825dSToby Isaac 3530f30e825dSToby Isaac offsets[0] = 0; 3531f30e825dSToby Isaac if (numFields) { 3532f30e825dSToby Isaac PetscInt f; 3533f30e825dSToby Isaac 3534f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3535f30e825dSToby Isaac PetscInt fDof; 35365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localFine,p,f,&fDof)); 3537f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 3538f30e825dSToby Isaac } 35395f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL,-1, NULL,pInd)); 3540367003a6SStefano Zampini } else { 35415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,NULL, NULL,pInd)); 3542f30e825dSToby Isaac } 35435f80ce2aSJacob Faibussowitsch if (gatheredValues) CHKERRQ(VecGetValues(fineVec,dof,pInd,pVal)); 35448d2f55e7SToby Isaac } 35458d2f55e7SToby Isaac } 35465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 35475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pointsWithDofs)); 35488d2f55e7SToby Isaac } 3549f30e825dSToby Isaac 35505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(coarse,&pStartC,&pEndC)); 35515f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(coarse,&localCoarse)); 35525f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(coarse,&globalCoarse)); 3553f30e825dSToby Isaac 35546148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */ 35556148253fSToby Isaac MPI_Datatype threeInt; 35566148253fSToby Isaac PetscMPIInt rank; 35576148253fSToby Isaac PetscInt (*parentNodeAndIdCoarse)[3]; 35586148253fSToby Isaac PetscInt (*parentNodeAndIdFine)[3]; 35596148253fSToby Isaac PetscInt p, nleaves, nleavesToParents; 35606148253fSToby Isaac PetscSF pointSF, sfToParents; 35616148253fSToby Isaac const PetscInt *ilocal; 35626148253fSToby Isaac const PetscSFNode *iremote; 35636148253fSToby Isaac PetscSFNode *iremoteToParents; 35646148253fSToby Isaac PetscInt *ilocalToParents; 35656148253fSToby Isaac 35665f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)coarse),&rank)); 35675f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_contiguous(3,MPIU_INT,&threeInt)); 35685f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_commit(&threeInt)); 35695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(pEndC-pStartC,&parentNodeAndIdCoarse,pEndF-pStartF,&parentNodeAndIdFine)); 35705f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(coarse,&pointSF)); 35715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(pointSF,NULL,&nleaves,&ilocal,&iremote)); 35726148253fSToby Isaac for (p = pStartC; p < pEndC; p++) { 35736148253fSToby Isaac PetscInt parent, childId; 35745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(coarse,p,&parent,&childId)); 35756148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank; 35766148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC; 35776148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId; 35786148253fSToby Isaac if (nleaves > 0) { 35796148253fSToby Isaac PetscInt leaf = -1; 35806148253fSToby Isaac 35816148253fSToby Isaac if (ilocal) { 35825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(parent,nleaves,ilocal,&leaf)); 35836148253fSToby Isaac } 35846148253fSToby Isaac else { 35856148253fSToby Isaac leaf = p - pStartC; 35866148253fSToby Isaac } 35876148253fSToby Isaac if (leaf >= 0) { 35886148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank; 35896148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index; 35906148253fSToby Isaac } 35916148253fSToby Isaac } 35926148253fSToby Isaac } 35936148253fSToby Isaac for (p = pStartF; p < pEndF; p++) { 35946148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1; 35956148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1; 35966148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1; 35976148253fSToby Isaac } 35985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine,MPI_REPLACE)); 35995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(coarseToFineEmbedded,threeInt,parentNodeAndIdCoarse,parentNodeAndIdFine,MPI_REPLACE)); 36006148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 3601f30e825dSToby Isaac PetscInt dof; 3602f30e825dSToby Isaac 36035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(leafIndicesSec,p,&dof)); 3604f30e825dSToby Isaac if (dof) { 3605f30e825dSToby Isaac PetscInt off; 3606f30e825dSToby Isaac 36075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(leafIndicesSec,p,&off)); 3608c921d74cSToby Isaac if (gatheredIndices) { 3609c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3610c921d74cSToby Isaac } else if (gatheredValues) { 3611c921d74cSToby Isaac leafVals[off] = (PetscScalar) PetscMax(childIds[p-pStartF],parentNodeAndIdFine[p-pStartF][2]); 3612c921d74cSToby Isaac } 3613f30e825dSToby Isaac } 36146148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36156148253fSToby Isaac nleavesToParents++; 36166148253fSToby Isaac } 36176148253fSToby Isaac } 36185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nleavesToParents,&ilocalToParents)); 36195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nleavesToParents,&iremoteToParents)); 36206148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) { 36216148253fSToby Isaac if (parentNodeAndIdFine[p-pStartF][0] >= 0) { 36226148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF; 36236148253fSToby Isaac iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p-pStartF][0]; 36246148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p-pStartF][1]; 36256148253fSToby Isaac nleavesToParents++; 36266148253fSToby Isaac } 36276148253fSToby Isaac } 36285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject)coarse),&sfToParents)); 36295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(sfToParents,pEndC-pStartC,nleavesToParents,ilocalToParents,PETSC_OWN_POINTER,iremoteToParents,PETSC_OWN_POINTER)); 36305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&coarseToFineEmbedded)); 36316148253fSToby Isaac 36326148253fSToby Isaac coarseToFineEmbedded = sfToParents; 36336148253fSToby Isaac 36345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(parentNodeAndIdCoarse,parentNodeAndIdFine)); 36355f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_free(&threeInt)); 36366148253fSToby Isaac } 3637f30e825dSToby Isaac 36386148253fSToby Isaac { /* winnow out coarse points that don't have dofs */ 36396148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 36406148253fSToby Isaac PetscSF sfDofsOnly; 36416148253fSToby Isaac 36426148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) { 36435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalCoarse,p,&dof)); 36445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 36456148253fSToby Isaac if ((dof - cdof) > 0) { 36466148253fSToby Isaac numPointsWithDofs++; 36476148253fSToby Isaac } 36486148253fSToby Isaac } 36495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numPointsWithDofs,&pointsWithDofs)); 36506148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) { 36515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalCoarse,p,&dof)); 36525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 36536148253fSToby Isaac if ((dof - cdof) > 0) { 3654e03d9830SToby Isaac pointsWithDofs[offset++] = p - pStartC; 36556148253fSToby Isaac } 36566148253fSToby Isaac } 36575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly)); 36585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&coarseToFineEmbedded)); 36595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pointsWithDofs)); 36606148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly; 36616148253fSToby Isaac } 3662f30e825dSToby Isaac 36636148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */ 36645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeBegin(coarseToFineEmbedded,&rootDegrees)); 36655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeEnd(coarseToFineEmbedded,&rootDegrees)); 36665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&multiRootSec)); 36675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(multiRootSec,pStartC,pEndC)); 36688d2f55e7SToby Isaac for (p = pStartC; p < pEndC; p++) { 36695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(multiRootSec,p,rootDegrees[p-pStartC])); 36708d2f55e7SToby Isaac } 36715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(multiRootSec)); 36725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(multiRootSec,&numMulti)); 36735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec)); 3674f30e825dSToby Isaac { /* distribute the leaf section */ 3675f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF; 3676f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices; 36778d2f55e7SToby Isaac 36785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetMultiSF(coarseToFineEmbedded,&multi)); 36795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateInverseSF(multi,&multiInv)); 36805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(multiInv,leafIndicesSec,&remoteOffsets,rootIndicesSec)); 36815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(multiInv,leafIndicesSec,remoteOffsets,rootIndicesSec,&indicesSF)); 36825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsets)); 36835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&multiInv)); 36845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices)); 3685c921d74cSToby Isaac if (gatheredIndices) { 36865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numRootIndices,&rootInds)); 36875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(indicesSF,MPIU_INT,leafInds,rootInds,MPI_REPLACE)); 36885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(indicesSF,MPIU_INT,leafInds,rootInds,MPI_REPLACE)); 3689c921d74cSToby Isaac } 3690c921d74cSToby Isaac if (gatheredValues) { 36915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numRootIndices,&rootVals)); 36925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(indicesSF,MPIU_SCALAR,leafVals,rootVals,MPI_REPLACE)); 36935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(indicesSF,MPIU_SCALAR,leafVals,rootVals,MPI_REPLACE)); 3694c921d74cSToby Isaac } 36955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&indicesSF)); 36968d2f55e7SToby Isaac } 36975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&leafIndicesSec)); 36985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(leafInds)); 36995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(leafVals)); 37005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&coarseToFineEmbedded)); 3701c921d74cSToby Isaac *rootMultiSec = multiRootSec; 3702c921d74cSToby Isaac *multiLeafSec = rootIndicesSec; 3703c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds; 3704c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals; 3705ebf164c7SToby Isaac PetscFunctionReturn(0); 3706ebf164c7SToby Isaac } 3707ebf164c7SToby Isaac 3708ebf164c7SToby Isaac PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat) 3709ebf164c7SToby Isaac { 3710ebf164c7SToby Isaac DM refTree; 3711c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 3712ebf164c7SToby Isaac PetscSection globalCoarse, globalFine; 3713ebf164c7SToby Isaac PetscSection localCoarse, localFine; 3714ebf164c7SToby Isaac PetscSection cSecRef; 3715277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd; 3716ebf164c7SToby Isaac Mat injRef; 3717c921d74cSToby Isaac PetscInt numFields, maxDof; 3718ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 3719ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 3720ebf164c7SToby Isaac PetscLayout rowMap, colMap; 3721ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO; 3722ebf164c7SToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 3723ebf164c7SToby Isaac 3724ebf164c7SToby Isaac PetscFunctionBegin; 3725ebf164c7SToby Isaac 3726ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 37275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetReferenceTree(coarse,&refTree)); 37285f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&cSecRef,NULL,NULL)); 37295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd)); 37305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetInjector(refTree,&injRef)); 3731ebf164c7SToby Isaac 37325f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(fine,&pStartF,&pEndF)); 37335f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(fine,&localFine)); 37345f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(fine,&globalFine)); 37355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(localFine,&numFields)); 37365f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(coarse,&pStartC,&pEndC)); 37375f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(coarse,&localCoarse)); 37385f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(coarse,&globalCoarse)); 37395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(localCoarse,&maxDof)); 3740ebf164c7SToby Isaac { 3741ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 37425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets)); 3743ebf164c7SToby Isaac } 3744ebf164c7SToby Isaac 37455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransferInjectorTree(coarse,fine,coarseToFine,childIds,NULL,numFields,offsets,&multiRootSec,&rootIndicesSec,&rootIndices,NULL)); 37468d2f55e7SToby Isaac 37475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxDof,&parentIndices)); 3748f30e825dSToby Isaac 3749f30e825dSToby Isaac /* count indices */ 37505f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLayouts(mat,&rowMap,&colMap)); 37515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(rowMap)); 37525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(colMap)); 37535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRange(rowMap,&rowStart,&rowEnd)); 37545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRange(colMap,&colStart,&colEnd)); 37555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc2(rowEnd-rowStart,&nnzD,rowEnd-rowStart,&nnzO)); 3756f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3757f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 37588d2f55e7SToby Isaac 37595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalCoarse,p,&dof)); 37605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 3761f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 37625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCoarse,p,&gOff)); 37638d2f55e7SToby Isaac 37648d2f55e7SToby Isaac rowOffsets[0] = 0; 3765f30e825dSToby Isaac offsetsCopy[0] = 0; 37668d2f55e7SToby Isaac if (numFields) { 37678d2f55e7SToby Isaac PetscInt f; 37688d2f55e7SToby Isaac 3769f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3770f30e825dSToby Isaac PetscInt fDof; 37715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 3772f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 37738d2f55e7SToby Isaac } 37745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,parentIndices)); 3775367003a6SStefano Zampini } else { 37765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,parentIndices)); 3777f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 37788d2f55e7SToby Isaac } 3779f30e825dSToby Isaac 37805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(multiRootSec,p,&numLeaves)); 37815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(multiRootSec,p,&leafStart)); 3782f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3783f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3784f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3785f30e825dSToby Isaac const PetscInt *childIndices; 3786f30e825dSToby Isaac 37875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootIndicesSec,l,&numIndices)); 37885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootIndicesSec,l,&offset)); 3789f30e825dSToby Isaac childId = rootIndices[offset++]; 3790f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3791f30e825dSToby Isaac numIndices--; 3792f30e825dSToby Isaac 3793f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3794f30e825dSToby Isaac PetscInt i; 3795f30e825dSToby Isaac 3796f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 3797f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3798f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3799f30e825dSToby Isaac if (rowIndex < 0) continue; 38002c71b3e2SJacob Faibussowitsch PetscCheckFalse(colIndex < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unconstrained fine and constrained coarse"); 3801a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3802f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1; 3803f30e825dSToby Isaac } 3804f30e825dSToby Isaac else { 3805f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1; 3806f30e825dSToby Isaac } 3807f30e825dSToby Isaac } 3808f30e825dSToby Isaac } 3809f30e825dSToby Isaac else { 3810f30e825dSToby Isaac PetscInt parentId, f, lim; 3811f30e825dSToby Isaac 38125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(refTree,childId,&parentId,NULL)); 3813f30e825dSToby Isaac 3814f30e825dSToby Isaac lim = PetscMax(1,numFields); 3815f30e825dSToby Isaac offsets[0] = 0; 38168d2f55e7SToby Isaac if (numFields) { 38178d2f55e7SToby Isaac PetscInt f; 3818f30e825dSToby Isaac 38198d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3820f30e825dSToby Isaac PetscInt fDof; 38215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSecRef,childId,f,&fDof)); 3822f30e825dSToby Isaac 3823f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 38248d2f55e7SToby Isaac } 38258d2f55e7SToby Isaac } 38268d2f55e7SToby Isaac else { 3827f30e825dSToby Isaac PetscInt cDof; 3828f30e825dSToby Isaac 38295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSecRef,childId,&cDof)); 3830f30e825dSToby Isaac offsets[1] = cDof; 3831f30e825dSToby Isaac } 3832f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3833f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1]; 3834f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1]; 3835f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0; 3836f30e825dSToby Isaac 3837f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) { 3838f30e825dSToby Isaac PetscInt colIndex = childIndices[i]; 3839f30e825dSToby Isaac 3840f30e825dSToby Isaac if (colIndex < 0) continue; 3841f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) { 3842f30e825dSToby Isaac numD++; 3843f30e825dSToby Isaac } 3844f30e825dSToby Isaac else { 3845f30e825dSToby Isaac numO++; 3846f30e825dSToby Isaac } 3847f30e825dSToby Isaac } 3848f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) { 3849f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i]; 3850f30e825dSToby Isaac 3851f30e825dSToby Isaac if (rowIndex < 0) continue; 3852f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD; 3853f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO; 38548d2f55e7SToby Isaac } 38558d2f55e7SToby Isaac } 38568d2f55e7SToby Isaac } 3857f30e825dSToby Isaac } 3858f30e825dSToby Isaac } 3859f30e825dSToby Isaac /* preallocate */ 38605f80ce2aSJacob Faibussowitsch CHKERRQ(MatXAIJSetPreallocation(mat,1,nnzD,nnzO,NULL,NULL)); 38615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(nnzD,nnzO)); 3862f30e825dSToby Isaac /* insert values */ 38635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats)); 3864f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) { 3865f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 3866f30e825dSToby Isaac 38675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalCoarse,p,&dof)); 38685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 3869f30e825dSToby Isaac if ((dof - cdof) <= 0) continue; 38705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCoarse,p,&gOff)); 3871f30e825dSToby Isaac 3872f30e825dSToby Isaac rowOffsets[0] = 0; 3873f30e825dSToby Isaac offsetsCopy[0] = 0; 38748d2f55e7SToby Isaac if (numFields) { 38758d2f55e7SToby Isaac PetscInt f; 3876f30e825dSToby Isaac 38778d2f55e7SToby Isaac for (f = 0; f < numFields; f++) { 3878f30e825dSToby Isaac PetscInt fDof; 38795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 3880f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 3881f30e825dSToby Isaac } 38825f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1, NULL,parentIndices)); 3883367003a6SStefano Zampini } else { 38845f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL, NULL,parentIndices)); 3885f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0]; 3886f30e825dSToby Isaac } 3887f30e825dSToby Isaac 38885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(multiRootSec,p,&numLeaves)); 38895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(multiRootSec,p,&leafStart)); 3890f30e825dSToby Isaac leafEnd = leafStart + numLeaves; 3891f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) { 3892f30e825dSToby Isaac PetscInt numIndices, childId, offset; 3893f30e825dSToby Isaac const PetscInt *childIndices; 3894f30e825dSToby Isaac 38955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootIndicesSec,l,&numIndices)); 38965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootIndicesSec,l,&offset)); 3897f30e825dSToby Isaac childId = rootIndices[offset++]; 3898f30e825dSToby Isaac childIndices = &rootIndices[offset]; 3899f30e825dSToby Isaac numIndices--; 3900f30e825dSToby Isaac 3901f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */ 3902f30e825dSToby Isaac PetscInt i; 3903f30e825dSToby Isaac 3904f30e825dSToby Isaac for (i = 0; i < numIndices; i++) { 39055f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(mat,parentIndices[i],childIndices[i],1.,INSERT_VALUES)); 39068d2f55e7SToby Isaac } 39078d2f55e7SToby Isaac } 39088d2f55e7SToby Isaac else { 3909f30e825dSToby Isaac PetscInt parentId, f, lim; 39108d2f55e7SToby Isaac 39115f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(refTree,childId,&parentId,NULL)); 3912f30e825dSToby Isaac 3913f30e825dSToby Isaac lim = PetscMax(1,numFields); 3914f30e825dSToby Isaac offsets[0] = 0; 39158d2f55e7SToby Isaac if (numFields) { 3916f30e825dSToby Isaac PetscInt f; 39178d2f55e7SToby Isaac 3918f30e825dSToby Isaac for (f = 0; f < numFields; f++) { 3919f30e825dSToby Isaac PetscInt fDof; 39205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSecRef,childId,f,&fDof)); 3921f30e825dSToby Isaac 3922f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f]; 39238d2f55e7SToby Isaac } 39248d2f55e7SToby Isaac } 39258d2f55e7SToby Isaac else { 3926f30e825dSToby Isaac PetscInt cDof; 3927f30e825dSToby Isaac 39285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSecRef,childId,&cDof)); 3929f30e825dSToby Isaac offsets[1] = cDof; 39308d2f55e7SToby Isaac } 3931f30e825dSToby Isaac for (f = 0; f < lim; f++) { 3932f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 3933f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]]; 3934f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]]; 3935f30e825dSToby Isaac 39365f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(mat,rowOffsets[f+1]-rowOffsets[f],rowIndices,offsets[f+1]-offsets[f],colIndices,childMat,INSERT_VALUES)); 39378d2f55e7SToby Isaac } 39388d2f55e7SToby Isaac } 39398d2f55e7SToby Isaac } 39408d2f55e7SToby Isaac } 39415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&multiRootSec)); 39425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&rootIndicesSec)); 39435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(parentIndices)); 39445f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats)); 39455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rootIndices)); 39465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(offsets,offsetsCopy,rowOffsets)); 3947f30e825dSToby Isaac 39485f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 39495f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 3950154bca37SToby Isaac PetscFunctionReturn(0); 3951154bca37SToby Isaac } 395238fc2455SToby Isaac 39530eb7e1eaSToby Isaac static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom) 3954ebf164c7SToby Isaac { 395562095d54SToby Isaac PetscSF coarseToFineEmbedded; 395662095d54SToby Isaac PetscSection globalCoarse, globalFine; 395762095d54SToby Isaac PetscSection localCoarse, localFine; 395862095d54SToby Isaac PetscSection aSec, cSec; 395962095d54SToby Isaac PetscSection rootValuesSec; 396062095d54SToby Isaac PetscSection leafValuesSec; 396162095d54SToby Isaac PetscScalar *rootValues, *leafValues; 396262095d54SToby Isaac IS aIS; 396362095d54SToby Isaac const PetscInt *anchors; 396462095d54SToby Isaac Mat cMat; 396562095d54SToby Isaac PetscInt numFields; 3966412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd; 396762095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd; 396862095d54SToby Isaac PetscInt *maxChildIds; 396962095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO; 39700eb7e1eaSToby Isaac PetscFV fv = NULL; 39710eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1; 39720eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL; 39730eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL; 39740eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL; 397562095d54SToby Isaac 3976ebf164c7SToby Isaac PetscFunctionBegin; 39775f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE)); 39785f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(coarse,&pStartC,&pEndC)); 39795f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSimplexOrBoxCells(coarse,0,&cellStart,&cellEnd)); 39805f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(fine,&pStartF,&pEndF)); 39815f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(fine,&globalFine)); 39825f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(coarse,&dim)); 398362095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */ 3984e4a60869SToby Isaac PetscInt nleaves, l; 3985e4a60869SToby Isaac const PetscInt *leaves; 398662095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs; 398762095d54SToby Isaac 39885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(coarseToFine,NULL,&nleaves,&leaves,NULL)); 3989e4a60869SToby Isaac 3990e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) { 3991e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 3992e4a60869SToby Isaac 39935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&dof)); 39945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 399562095d54SToby Isaac if ((dof - cdof) > 0) { 399662095d54SToby Isaac numPointsWithDofs++; 399762095d54SToby Isaac } 399862095d54SToby Isaac } 39995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numPointsWithDofs,&pointsWithDofs)); 40004833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) { 4001e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l; 4002e4a60869SToby Isaac 40035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&dof)); 40045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&cdof)); 400562095d54SToby Isaac if ((dof - cdof) > 0) { 4006e4a60869SToby Isaac pointsWithDofs[offset++] = l; 400762095d54SToby Isaac } 400862095d54SToby Isaac } 40095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded)); 40105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pointsWithDofs)); 401162095d54SToby Isaac } 401262095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */ 40135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEndC-pStartC,&maxChildIds)); 401462095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 401562095d54SToby Isaac maxChildIds[p - pStartC] = -2; 401662095d54SToby Isaac } 40175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX)); 40185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,cids,maxChildIds,MPIU_MAX)); 401962095d54SToby Isaac 40205f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(coarse,&localCoarse)); 40215f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(coarse,&globalCoarse)); 402262095d54SToby Isaac 40235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(coarse,&aSec,&aIS)); 40245f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(aIS,&anchors)); 40255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(aSec,&aStart,&aEnd)); 402662095d54SToby Isaac 40275f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(coarse,&cSec,&cMat,NULL)); 40285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(cSec,&cStart,&cEnd)); 402962095d54SToby Isaac 403062095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */ 40315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootValuesSec)); 40325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(rootValuesSec,pStartC,pEndC)); 40335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(localCoarse,&numFields)); 403462095d54SToby Isaac { 403562095d54SToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 40365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc7(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&newOffsets,maxFields,&newOffsetsCopy,maxFields,&rowOffsets,maxFields,&numD,maxFields,&numO)); 403762095d54SToby Isaac } 40380eb7e1eaSToby Isaac if (grad) { 40390eb7e1eaSToby Isaac PetscInt i; 40400eb7e1eaSToby Isaac 40415f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(cellGeom,&cellDM)); 40425f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(cellGeom,&cellGeomArray)); 40435f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetDM(grad,&gradDM)); 40445f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(grad,&gradArray)); 40450eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1,numFields); i++) { 40460eb7e1eaSToby Isaac PetscObject obj; 40470eb7e1eaSToby Isaac PetscClassId id; 40480eb7e1eaSToby Isaac 40495f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetField(coarse, i, NULL, &obj)); 40505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(obj,&id)); 40510eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) { 40520eb7e1eaSToby Isaac fv = (PetscFV) obj; 40535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFVGetNumComponents(fv,&numFVcomps)); 40540eb7e1eaSToby Isaac fvField = i; 40550eb7e1eaSToby Isaac break; 40560eb7e1eaSToby Isaac } 40570eb7e1eaSToby Isaac } 40580eb7e1eaSToby Isaac } 405962095d54SToby Isaac 406062095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */ 406162095d54SToby Isaac PetscInt dof; 406262095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 406362095d54SToby Isaac PetscInt numValues = 0; 406462095d54SToby Isaac 40655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalCoarse,p,&dof)); 406662095d54SToby Isaac if (dof < 0) { 406762095d54SToby Isaac dof = -(dof + 1); 406862095d54SToby Isaac } 406962095d54SToby Isaac offsets[0] = 0; 407062095d54SToby Isaac newOffsets[0] = 0; 407162095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */ 407262095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl; 407362095d54SToby Isaac 40745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure)); 407562095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */ 407662095d54SToby Isaac PetscInt c = closure[2 * cl], clDof; 407762095d54SToby Isaac 40785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(localCoarse,c,&clDof)); 407962095d54SToby Isaac numValues += clDof; 408062095d54SToby Isaac } 40815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure)); 408262095d54SToby Isaac } 408362095d54SToby Isaac else if (maxChildId == -1) { 40845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(localCoarse,p,&numValues)); 408562095d54SToby Isaac } 408662095d54SToby Isaac /* we will pack the column indices with the field offsets */ 408778b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) { 40880eb7e1eaSToby Isaac /* also send the centroid, and the gradient */ 40890eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps); 40900eb7e1eaSToby Isaac } 40915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(rootValuesSec,p,numValues)); 409262095d54SToby Isaac } 40935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(rootValuesSec)); 409462095d54SToby Isaac { 409562095d54SToby Isaac PetscInt numRootValues; 409662095d54SToby Isaac const PetscScalar *coarseArray; 409762095d54SToby Isaac 40985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(rootValuesSec,&numRootValues)); 40995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numRootValues,&rootValues)); 41005f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(vecCoarseLocal,&coarseArray)); 410162095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { 410262095d54SToby Isaac PetscInt numValues; 410362095d54SToby Isaac PetscInt pValOff; 410462095d54SToby Isaac PetscScalar *pVal; 410562095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC]; 410662095d54SToby Isaac 41075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootValuesSec,p,&numValues)); 410862095d54SToby Isaac if (!numValues) { 410962095d54SToby Isaac continue; 411062095d54SToby Isaac } 41115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootValuesSec,p,&pValOff)); 411262095d54SToby Isaac pVal = &(rootValues[pValOff]); 411362095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */ 41140eb7e1eaSToby Isaac PetscInt closureSize = numValues; 41155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(coarse,NULL,vecCoarseLocal,p,&closureSize,&pVal)); 41160eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) { 4117193eb951SToby Isaac PetscFVCellGeom *cg; 41186dd00756SToby Isaac PetscScalar *gradVals = NULL; 41190eb7e1eaSToby Isaac PetscInt i; 41200eb7e1eaSToby Isaac 41210eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps)); 41220eb7e1eaSToby Isaac 41235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointLocalRead(cellDM,p,cellGeomArray,(void *) &cg)); 41240eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i]; 41250eb7e1eaSToby Isaac pVal += dim; 41265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPointGlobalRead(gradDM,p,gradArray,(void *) &gradVals)); 41270eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i]; 41280eb7e1eaSToby Isaac } 412962095d54SToby Isaac } 413078b7adb5SToby Isaac else if (maxChildId == -1) { 413178b7adb5SToby Isaac PetscInt lDof, lOff, i; 413278b7adb5SToby Isaac 41335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(localCoarse,p,&lDof)); 41345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(localCoarse,p,&lOff)); 413578b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i]; 413678b7adb5SToby Isaac } 413778b7adb5SToby Isaac } 41385f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(vecCoarseLocal,&coarseArray)); 41395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(maxChildIds)); 414062095d54SToby Isaac } 414162095d54SToby Isaac { 414262095d54SToby Isaac PetscSF valuesSF; 414362095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues; 414462095d54SToby Isaac 41455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafValuesSec)); 41465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(coarseToFineEmbedded,rootValuesSec,&remoteOffsetsValues,leafValuesSec)); 41475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(coarseToFineEmbedded,rootValuesSec,remoteOffsetsValues,leafValuesSec,&valuesSF)); 41485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&coarseToFineEmbedded)); 41495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsetsValues)); 41505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(leafValuesSec,&numLeafValues)); 41515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numLeafValues,&leafValues)); 41525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(valuesSF,MPIU_SCALAR,rootValues,leafValues,MPI_REPLACE)); 41535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(valuesSF,MPIU_SCALAR,rootValues,leafValues,MPI_REPLACE)); 41545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&valuesSF)); 41555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rootValues)); 41565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&rootValuesSec)); 415762095d54SToby Isaac } 41585f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(fine,&localFine)); 415962095d54SToby Isaac { 416062095d54SToby Isaac PetscInt maxDof; 416162095d54SToby Isaac PetscInt *rowIndices; 416262095d54SToby Isaac DM refTree; 416362095d54SToby Isaac PetscInt **refPointFieldN; 416462095d54SToby Isaac PetscScalar ***refPointFieldMats; 416562095d54SToby Isaac PetscSection refConSec, refAnSec; 41660eb7e1eaSToby Isaac PetscInt pRefStart,pRefEnd,leafStart,leafEnd; 416762095d54SToby Isaac PetscScalar *pointWork; 416862095d54SToby Isaac 41695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(localFine,&maxDof)); 41705f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(fine,maxDof,MPIU_INT,&rowIndices)); 41715f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(fine,maxDof,MPIU_SCALAR,&pointWork)); 41725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetReferenceTree(fine,&refTree)); 41735f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(fine,refTree)); 41745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 41755f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&refConSec,NULL,NULL)); 41765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(refTree,&refAnSec,NULL)); 41775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd)); 41785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(leafValuesSec,&leafStart,&leafEnd)); 41795f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSimplexOrBoxCells(fine,0,&cellStart,&cellEnd)); 41800eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) { 418162095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof; 418262095d54SToby Isaac PetscInt numValues, pValOff; 418362095d54SToby Isaac PetscInt childId; 418462095d54SToby Isaac const PetscScalar *pVal; 41850eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL; 418662095d54SToby Isaac 41875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalFine,p,&gDof)); 41885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(localFine,p,&lDof)); 41895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalFine,p,&gcDof)); 419062095d54SToby Isaac if ((gDof - gcDof) <= 0) { 419162095d54SToby Isaac continue; 419262095d54SToby Isaac } 41935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalFine,p,&gOff)); 41945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(leafValuesSec,p,&numValues)); 419562095d54SToby Isaac if (!numValues) continue; 41965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(leafValuesSec,p,&pValOff)); 419762095d54SToby Isaac pVal = &leafValues[pValOff]; 419862095d54SToby Isaac offsets[0] = 0; 419962095d54SToby Isaac offsetsCopy[0] = 0; 420062095d54SToby Isaac newOffsets[0] = 0; 420162095d54SToby Isaac newOffsetsCopy[0] = 0; 42024833aeb0SToby Isaac childId = cids[p - pStartF]; 420362095d54SToby Isaac if (numFields) { 420462095d54SToby Isaac PetscInt f; 420562095d54SToby Isaac for (f = 0; f < numFields; f++) { 420662095d54SToby Isaac PetscInt rowDof; 420762095d54SToby Isaac 42085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localFine,p,f,&rowDof)); 420962095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof; 421062095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1]; 421162095d54SToby Isaac /* TODO: closure indices */ 42129f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]); 421362095d54SToby Isaac } 42145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,-1,NULL,rowIndices)); 421562095d54SToby Isaac } 421662095d54SToby Isaac else { 42174833aeb0SToby Isaac offsets[0] = 0; 42184833aeb0SToby Isaac offsets[1] = lDof; 42194833aeb0SToby Isaac newOffsets[0] = 0; 42204833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0]; 42215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localFine,PETSC_FALSE,p,gOff,offsetsCopy,PETSC_FALSE,NULL,NULL,rowIndices)); 422262095d54SToby Isaac } 422362095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */ 42245f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(vecFine,numValues,rowIndices,pVal,INSERT_VALUES)); 422562095d54SToby Isaac } else { 422662095d54SToby Isaac PetscInt f; 422762095d54SToby Isaac 422878b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) { 422978b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps)); 423078b7adb5SToby Isaac fvGradData = &pVal[numValues]; 423178b7adb5SToby Isaac } 423262095d54SToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 423362095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f]; 423462095d54SToby Isaac PetscInt numRows = offsets[f+1] - offsets[f]; 423562095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f]; 423662095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]]; 423762095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]]; 423862095d54SToby Isaac PetscInt i, j; 423962095d54SToby Isaac 4240708c7f19SToby Isaac #if 0 42415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(coarse,"childId %D, numRows %D, numCols %D, refPointFieldN %D maxDof %D\n",childId,numRows,numCols,refPointFieldN[childId - pRefStart][f], maxDof)); 4242708c7f19SToby Isaac #endif 424362095d54SToby Isaac for (i = 0; i < numRows; i++) { 424462095d54SToby Isaac PetscScalar val = 0.; 424562095d54SToby Isaac for (j = 0; j < numCols; j++) { 424662095d54SToby Isaac val += childMat[i * numCols + j] * cVal[j]; 424762095d54SToby Isaac } 424862095d54SToby Isaac rVal[i] = val; 424962095d54SToby Isaac } 42500eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) { 42510eb7e1eaSToby Isaac PetscReal centroid[3]; 42520eb7e1eaSToby Isaac PetscScalar diff[3]; 42530eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0]; 42540eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim]; 42550eb7e1eaSToby Isaac 42565f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFVM(fine,p,NULL,centroid,NULL)); 42570eb7e1eaSToby Isaac for (i = 0; i < dim; i++) { 42580eb7e1eaSToby Isaac diff[i] = centroid[i] - parentCentroid[i]; 42590eb7e1eaSToby Isaac } 42600eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) { 42610eb7e1eaSToby Isaac PetscScalar val = 0.; 42620eb7e1eaSToby Isaac 426389698031SToby Isaac for (j = 0; j < dim; j++) { 42640eb7e1eaSToby Isaac val += gradient[dim * i + j] * diff[j]; 42650eb7e1eaSToby Isaac } 42660eb7e1eaSToby Isaac rVal[i] += val; 42670eb7e1eaSToby Isaac } 42680eb7e1eaSToby Isaac } 42695f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(vecFine,numRows,&rowIndices[offsets[f]],rVal,INSERT_VALUES)); 427062095d54SToby Isaac } 427162095d54SToby Isaac } 427262095d54SToby Isaac } 42735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeRestoreChildrenMatrices(refTree,&refPointFieldMats,&refPointFieldN)); 42745f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(fine,maxDof,MPIU_SCALAR,&pointWork)); 42755f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(fine,maxDof,MPIU_INT,&rowIndices)); 427662095d54SToby Isaac } 42775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(leafValues)); 42785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&leafValuesSec)); 42795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree7(offsets,offsetsCopy,newOffsets,newOffsetsCopy,rowOffsets,numD,numO)); 42805f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(aIS,&anchors)); 4281ebf164c7SToby Isaac PetscFunctionReturn(0); 4282ebf164c7SToby Isaac } 4283ebf164c7SToby Isaac 4284ebf164c7SToby Isaac static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids) 4285ebf164c7SToby Isaac { 4286c921d74cSToby Isaac DM refTree; 4287c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec; 4288c921d74cSToby Isaac PetscSection globalCoarse, globalFine; 4289c921d74cSToby Isaac PetscSection localCoarse, localFine; 4290c921d74cSToby Isaac PetscSection cSecRef; 4291c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd; 4292d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues; 4293c921d74cSToby Isaac Mat injRef; 4294c921d74cSToby Isaac PetscInt numFields, maxDof; 4295c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p; 4296c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets; 4297c921d74cSToby Isaac PetscLayout rowMap, colMap; 4298c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd; 4299c921d74cSToby Isaac PetscScalar ***childrenMats=NULL ; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */ 4300c921d74cSToby Isaac 4301ebf164c7SToby Isaac PetscFunctionBegin; 4302c921d74cSToby Isaac 4303c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */ 43045f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOption(vecFine,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE)); 43055f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetOption(vecCoarse,VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE)); 43065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetReferenceTree(coarse,&refTree)); 43075f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(coarse,refTree)); 43085f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDefaultConstraints(refTree,&cSecRef,NULL,NULL)); 43095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(cSecRef,&pRefStart,&pRefEnd)); 43105f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetInjector(refTree,&injRef)); 4311c921d74cSToby Isaac 43125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(fine,&pStartF,&pEndF)); 43135f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(fine,&localFine)); 43145f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(fine,&globalFine)); 43155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(localFine,&numFields)); 43165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(coarse,&pStartC,&pEndC)); 43175f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(coarse,&localCoarse)); 43185f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalSection(coarse,&globalCoarse)); 43195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(localCoarse,&maxDof)); 4320c921d74cSToby Isaac { 4321c921d74cSToby Isaac PetscInt maxFields = PetscMax(1,numFields) + 1; 43225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(maxFields,&offsets,maxFields,&offsetsCopy,maxFields,&rowOffsets)); 4323c921d74cSToby Isaac } 4324c921d74cSToby Isaac 43255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransferInjectorTree(coarse,fine,coarseToFine,cids,vecFine,numFields,offsets,&multiRootSec,&rootIndicesSec,NULL,&rootValues)); 4326c921d74cSToby Isaac 43275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(maxDof,&parentIndices,maxDof,&parentValues)); 4328c921d74cSToby Isaac 4329c921d74cSToby Isaac /* count indices */ 43305f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLayout(vecFine,&colMap)); 43315f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLayout(vecCoarse,&rowMap)); 43325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(rowMap)); 43335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(colMap)); 43345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRange(rowMap,&rowStart,&rowEnd)); 43355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRange(colMap,&colStart,&colEnd)); 4336c921d74cSToby Isaac /* insert values */ 43375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree,injRef,&childrenMats)); 4338c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) { 4339c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff; 434078b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE; 4341c921d74cSToby Isaac 43425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(globalCoarse,p,&dof)); 43435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(globalCoarse,p,&cdof)); 4344c921d74cSToby Isaac if ((dof - cdof) <= 0) continue; 43455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(localCoarse,p,&dof)); 43465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(globalCoarse,p,&gOff)); 4347c921d74cSToby Isaac 4348c921d74cSToby Isaac rowOffsets[0] = 0; 4349c921d74cSToby Isaac offsetsCopy[0] = 0; 4350c921d74cSToby Isaac if (numFields) { 4351c921d74cSToby Isaac PetscInt f; 4352c921d74cSToby Isaac 4353c921d74cSToby Isaac for (f = 0; f < numFields; f++) { 4354c921d74cSToby Isaac PetscInt fDof; 43555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(localCoarse,p,f,&fDof)); 4356c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f]; 4357c921d74cSToby Isaac } 43585f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPointFields_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,-1,NULL,parentIndices)); 4359367003a6SStefano Zampini } else { 43605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetIndicesPoint_Internal(localCoarse,PETSC_FALSE,p,gOff < 0 ? -(gOff + 1) : gOff,offsetsCopy,PETSC_FALSE,NULL,NULL,parentIndices)); 4361c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0]; 4362c921d74cSToby Isaac } 4363c921d74cSToby Isaac 43645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(multiRootSec,p,&numLeaves)); 43655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(multiRootSec,p,&leafStart)); 4366c921d74cSToby Isaac leafEnd = leafStart + numLeaves; 43672f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.; 4368c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) { 4369c921d74cSToby Isaac PetscInt numIndices, childId, offset; 4370c921d74cSToby Isaac const PetscScalar *childValues; 4371c921d74cSToby Isaac 43725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootIndicesSec,l,&numIndices)); 43735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootIndicesSec,l,&offset)); 4374c921d74cSToby Isaac childId = (PetscInt) PetscRealPart(rootValues[offset++]); 4375c921d74cSToby Isaac childValues = &rootValues[offset]; 4376c921d74cSToby Isaac numIndices--; 4377c921d74cSToby Isaac 4378c921d74cSToby Isaac if (childId == -2) { /* skip */ 4379c921d74cSToby Isaac continue; 4380c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */ 43812f65e181SToby Isaac PetscInt m; 43822f65e181SToby Isaac 438378b7adb5SToby Isaac contribute = PETSC_TRUE; 43842f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m]; 4385beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */ 4386d3bc4906SToby Isaac PetscInt parentId, f, lim; 4387d3bc4906SToby Isaac 438878b7adb5SToby Isaac contribute = PETSC_TRUE; 43895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(refTree,childId,&parentId,NULL)); 4390d3bc4906SToby Isaac 4391d3bc4906SToby Isaac lim = PetscMax(1,numFields); 4392d3bc4906SToby Isaac offsets[0] = 0; 4393d3bc4906SToby Isaac if (numFields) { 4394d3bc4906SToby Isaac PetscInt f; 4395d3bc4906SToby Isaac 4396d3bc4906SToby Isaac for (f = 0; f < numFields; f++) { 4397d3bc4906SToby Isaac PetscInt fDof; 43985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(cSecRef,childId,f,&fDof)); 4399d3bc4906SToby Isaac 4400d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f]; 4401d3bc4906SToby Isaac } 4402d3bc4906SToby Isaac } 4403d3bc4906SToby Isaac else { 4404d3bc4906SToby Isaac PetscInt cDof; 4405d3bc4906SToby Isaac 44065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cSecRef,childId,&cDof)); 4407d3bc4906SToby Isaac offsets[1] = cDof; 4408d3bc4906SToby Isaac } 4409d3bc4906SToby Isaac for (f = 0; f < lim; f++) { 4410d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0]; 4411d3bc4906SToby Isaac PetscInt n = offsets[f+1]-offsets[f]; 4412e328ff09SToby Isaac PetscInt m = rowOffsets[f+1]-rowOffsets[f]; 4413d3bc4906SToby Isaac PetscInt i, j; 4414d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]]; 4415d3bc4906SToby Isaac 4416e328ff09SToby Isaac for (i = 0; i < m; i++) { 4417d3bc4906SToby Isaac PetscScalar val = 0.; 4418d3bc4906SToby Isaac for (j = 0; j < n; j++) { 4419d3bc4906SToby Isaac val += childMat[n * i + j] * colValues[j]; 4420d3bc4906SToby Isaac } 4421e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val; 4422d3bc4906SToby Isaac } 4423d3bc4906SToby Isaac } 4424c921d74cSToby Isaac } 4425c921d74cSToby Isaac } 44265f80ce2aSJacob Faibussowitsch if (contribute) CHKERRQ(VecSetValues(vecCoarse,dof,parentIndices,parentValues,INSERT_VALUES)); 4427c921d74cSToby Isaac } 44285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&multiRootSec)); 44295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&rootIndicesSec)); 44305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(parentIndices,parentValues)); 44315f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree,injRef,&childrenMats)); 44325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rootValues)); 44335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(offsets,offsetsCopy,rowOffsets)); 4434ebf164c7SToby Isaac PetscFunctionReturn(0); 4435ebf164c7SToby Isaac } 4436ebf164c7SToby Isaac 4437ff1f73f7SToby Isaac /*@ 4438ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening 4439ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of 4440ff1f73f7SToby Isaac coarsening and refinement at the same time. 4441ff1f73f7SToby Isaac 4442ff1f73f7SToby Isaac collective 4443ff1f73f7SToby Isaac 4444ff1f73f7SToby Isaac Input Parameters: 4445ff1f73f7SToby Isaac + dmIn - The DMPlex mesh for the input vector 4446ff1f73f7SToby Isaac . vecIn - The input vector 4447ff1f73f7SToby Isaac . sfRefine - A star forest indicating points in the mesh dmIn (roots in the star forest) that are parents to points in 4448ff1f73f7SToby Isaac the mesh dmOut (leaves in the star forest), i.e. where dmOut is more refined than dmIn 4449ff1f73f7SToby Isaac . sfCoarsen - A star forest indicating points in the mesh dmOut (roots in the star forest) that are parents to points in 4450ff1f73f7SToby Isaac the mesh dmIn (leaves in the star forest), i.e. where dmOut is more coarsened than dmIn 4451ff1f73f7SToby Isaac . cidsRefine - The childIds of the points in dmOut. These childIds relate back to the reference tree: childid[j] = k implies 4452ff1f73f7SToby Isaac that mesh point j of dmOut was refined from a point in dmIn just as the mesh point k in the reference 4453ff1f73f7SToby Isaac tree was refined from its parent. childid[j] = -1 indicates that the point j in dmOut is exactly 4454ff1f73f7SToby Isaac equivalent to its root in dmIn, so no interpolation is necessary. childid[j] = -2 indicates that this 4455ff1f73f7SToby Isaac point j in dmOut is not a leaf of sfRefine. 4456ff1f73f7SToby Isaac . cidsCoarsen - The childIds of the points in dmIn. These childIds relate back to the reference tree: childid[j] = k implies 4457ff1f73f7SToby Isaac that mesh point j of dmIn coarsens to a point in dmOut just as the mesh point k in the reference 4458ff1f73f7SToby Isaac tree coarsens to its parent. childid[j] = -2 indicates that point j in dmOut is not a leaf in sfCoarsen. 4459ff1f73f7SToby Isaac . useBCs - PETSC_TRUE indicates that boundary values should be inserted into vecIn before transfer. 4460ff1f73f7SToby Isaac - time - Used if boundary values are time dependent. 4461ff1f73f7SToby Isaac 4462ff1f73f7SToby Isaac Output Parameters: 44638966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred 4464ff1f73f7SToby Isaac projection of vecIn from dmIn to dmOut. Note that any field discretized with a PetscFV finite volume 4465ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from 4466ff1f73f7SToby Isaac coarse points to fine points. 4467ff1f73f7SToby Isaac 4468ff1f73f7SToby Isaac Level: developer 4469ff1f73f7SToby Isaac 4470fd292e60Sprj- .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree(), PetscFVGetComputeGradients() 4471ff1f73f7SToby Isaac @*/ 4472ff1f73f7SToby Isaac PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time) 447338fc2455SToby Isaac { 447438fc2455SToby Isaac PetscFunctionBegin; 44755f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(vecOut,0.0)); 4476ff1f73f7SToby Isaac if (sfRefine) { 4477fbfa57b9SToby Isaac Vec vecInLocal; 44780eb7e1eaSToby Isaac DM dmGrad = NULL; 44790eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL; 4480fbfa57b9SToby Isaac 44815f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(dmIn,&vecInLocal)); 44825f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(vecInLocal,0.0)); 44830eb7e1eaSToby Isaac { 44840eb7e1eaSToby Isaac PetscInt numFields, i; 44850eb7e1eaSToby Isaac 44865f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumFields(dmIn, &numFields)); 44870eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) { 44880eb7e1eaSToby Isaac PetscObject obj; 44890eb7e1eaSToby Isaac PetscClassId classid; 44900eb7e1eaSToby Isaac 44915f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetField(dmIn, i, NULL, &obj)); 44925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(obj, &classid)); 44930eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) { 44945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDataFVM(dmIn,(PetscFV)obj,&cellGeom,&faceGeom,&dmGrad)); 44950eb7e1eaSToby Isaac break; 44960eb7e1eaSToby Isaac } 44970eb7e1eaSToby Isaac } 44980eb7e1eaSToby Isaac } 44990eb7e1eaSToby Isaac if (useBCs) { 45005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInsertBoundaryValues(dmIn,PETSC_TRUE,vecInLocal,time,faceGeom,cellGeom,NULL)); 45010eb7e1eaSToby Isaac } 45025f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(dmIn,vecIn,INSERT_VALUES,vecInLocal)); 45035f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(dmIn,vecIn,INSERT_VALUES,vecInLocal)); 45040eb7e1eaSToby Isaac if (dmGrad) { 45055f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetGlobalVector(dmGrad,&grad)); 45065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReconstructGradientsFVM(dmIn,vecInLocal,grad)); 45070eb7e1eaSToby Isaac } 45085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransferVecTree_Interpolate(dmIn,vecInLocal,dmOut,vecOut,sfRefine,cidsRefine,grad,cellGeom)); 45095f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(dmIn,&vecInLocal)); 45100eb7e1eaSToby Isaac if (dmGrad) { 45115f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreGlobalVector(dmGrad,&grad)); 45120eb7e1eaSToby Isaac } 4513ebf164c7SToby Isaac } 4514ff1f73f7SToby Isaac if (sfCoarsen) { 45155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexTransferVecTree_Inject(dmIn,vecIn,dmOut,vecOut,sfCoarsen,cidsCoarsen)); 4516ebf164c7SToby Isaac } 45175f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(vecOut)); 45185f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(vecOut)); 451938fc2455SToby Isaac PetscFunctionReturn(0); 452038fc2455SToby Isaac } 4521