1d6a7ad0dSToby Isaac #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2d6a7ad0dSToby Isaac #include <../src/sys/utils/hash.h> 3d6a7ad0dSToby Isaac #include <petsc-private/isimpl.h> 4*0c37af3bSToby Isaac #include <petsc-private/petscfeimpl.h> 5d6a7ad0dSToby Isaac #include <petscsf.h> 6*0c37af3bSToby Isaac #include <petscds.h> 7d6a7ad0dSToby Isaac 8d6a7ad0dSToby Isaac /** hierarchy routines */ 9d6a7ad0dSToby Isaac 10d6a7ad0dSToby Isaac #undef __FUNCT__ 11d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexSetReferenceTree" 12d6a7ad0dSToby Isaac /*@ 13d6a7ad0dSToby Isaac DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes. 14d6a7ad0dSToby Isaac 15d6a7ad0dSToby Isaac Not collective 16d6a7ad0dSToby Isaac 17d6a7ad0dSToby Isaac Input Parameters: 18d6a7ad0dSToby Isaac + dm - The DMPlex object 19d6a7ad0dSToby Isaac - ref - The reference tree DMPlex object 20d6a7ad0dSToby Isaac 210b7167a0SToby Isaac Level: intermediate 22d6a7ad0dSToby Isaac 23da43764aSToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexCreateDefaultReferenceTree() 24d6a7ad0dSToby Isaac @*/ 25d6a7ad0dSToby Isaac PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 26d6a7ad0dSToby Isaac { 27d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 28d6a7ad0dSToby Isaac PetscErrorCode ierr; 29d6a7ad0dSToby Isaac 30d6a7ad0dSToby Isaac PetscFunctionBegin; 31d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32d6a7ad0dSToby Isaac PetscValidHeaderSpecific(ref, DM_CLASSID, 2); 33d6a7ad0dSToby Isaac ierr = PetscObjectReference((PetscObject)ref);CHKERRQ(ierr); 34d6a7ad0dSToby Isaac ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 35d6a7ad0dSToby Isaac mesh->referenceTree = ref; 36d6a7ad0dSToby Isaac PetscFunctionReturn(0); 37d6a7ad0dSToby Isaac } 38d6a7ad0dSToby Isaac 39d6a7ad0dSToby Isaac #undef __FUNCT__ 40d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexGetReferenceTree" 41d6a7ad0dSToby Isaac /*@ 42d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 43d6a7ad0dSToby Isaac 44d6a7ad0dSToby Isaac Not collective 45d6a7ad0dSToby Isaac 46d6a7ad0dSToby Isaac Input Parameters: 47d6a7ad0dSToby Isaac . dm - The DMPlex object 48d6a7ad0dSToby Isaac 49d6a7ad0dSToby Isaac Output Parameters 50d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object 51d6a7ad0dSToby Isaac 520b7167a0SToby Isaac Level: intermediate 53d6a7ad0dSToby Isaac 54da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexCreateDefaultReferenceTree() 55d6a7ad0dSToby Isaac @*/ 56d6a7ad0dSToby Isaac PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 57d6a7ad0dSToby Isaac { 58d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 59d6a7ad0dSToby Isaac 60d6a7ad0dSToby Isaac PetscFunctionBegin; 61d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62d6a7ad0dSToby Isaac PetscValidPointer(ref,2); 63d6a7ad0dSToby Isaac *ref = mesh->referenceTree; 64d6a7ad0dSToby Isaac PetscFunctionReturn(0); 65d6a7ad0dSToby Isaac } 66d6a7ad0dSToby Isaac 67da43764aSToby Isaac #undef __FUNCT__ 68da43764aSToby Isaac #define __FUNCT__ "DMPlexCreateDefaultReferenceTree" 69da43764aSToby Isaac /*@ 70da43764aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 71da43764aSToby Isaac 72da43764aSToby Isaac Collective on comm 73da43764aSToby Isaac 74da43764aSToby Isaac Input Parameters: 75da43764aSToby Isaac + comm - the MPI communicator 76da43764aSToby Isaac . dim - the spatial dimension 77da43764aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell 78da43764aSToby Isaac 79da43764aSToby Isaac Output Parameters: 80da43764aSToby Isaac . ref - the reference tree DMPlex object 81da43764aSToby Isaac 820b7167a0SToby Isaac Level: intermediate 83da43764aSToby Isaac 84da43764aSToby Isaac .keywords: reference cell 85da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree() 86da43764aSToby Isaac @*/ 87da43764aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 88da43764aSToby Isaac { 89da43764aSToby Isaac DM K, Kref; 9010f7e118SToby Isaac PetscInt p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 91da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 92da43764aSToby Isaac DMLabel identity, identityRef; 9310f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection; 94da43764aSToby Isaac PetscScalar *unionCoords; 95da43764aSToby Isaac IS perm; 96da43764aSToby Isaac PetscErrorCode ierr; 97da43764aSToby Isaac 98da43764aSToby Isaac PetscFunctionBegin; 99da43764aSToby Isaac /* create a reference element */ 100da43764aSToby Isaac ierr = DMPlexCreateReferenceCell(comm, dim, simplex, &K);CHKERRQ(ierr); 101da43764aSToby Isaac ierr = DMPlexCreateLabel(K, "identity");CHKERRQ(ierr); 102da43764aSToby Isaac ierr = DMPlexGetLabel(K, "identity", &identity);CHKERRQ(ierr); 103da43764aSToby Isaac ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 104da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 105da43764aSToby Isaac ierr = DMLabelSetValue(identity, p, p);CHKERRQ(ierr); 106da43764aSToby Isaac } 107da43764aSToby Isaac /* refine it */ 108da43764aSToby Isaac ierr = DMRefine(K,comm,&Kref);CHKERRQ(ierr); 109da43764aSToby Isaac 110da43764aSToby Isaac /* the reference tree is the union of these two, without duplicating 111da43764aSToby Isaac * points that appear in both */ 112da43764aSToby Isaac ierr = DMPlexGetLabel(Kref, "identity", &identityRef);CHKERRQ(ierr); 113da43764aSToby Isaac ierr = DMPlexGetChart(Kref, &pRefStart, &pRefEnd);CHKERRQ(ierr); 114da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionSection);CHKERRQ(ierr); 115da43764aSToby Isaac ierr = PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart));CHKERRQ(ierr); 116da43764aSToby Isaac /* count points that will go in the union */ 117da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 118da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pStart, 1);CHKERRQ(ierr); 119da43764aSToby Isaac } 120da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 121da43764aSToby Isaac PetscInt q, qSize; 122da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, p, &q);CHKERRQ(ierr); 123da43764aSToby Isaac ierr = DMLabelGetStratumSize(identityRef, q, &qSize);CHKERRQ(ierr); 124da43764aSToby Isaac if (qSize > 1) { 125da43764aSToby Isaac ierr = PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1);CHKERRQ(ierr); 126da43764aSToby Isaac } 127da43764aSToby Isaac } 128da43764aSToby Isaac ierr = PetscMalloc1((pEnd - pStart) + (pRefEnd - pRefStart),&permvals);CHKERRQ(ierr); 129da43764aSToby Isaac offset = 0; 130da43764aSToby Isaac /* stratify points in the union by topological dimension */ 131da43764aSToby Isaac for (d = 0; d <= dim; d++) { 132da43764aSToby Isaac PetscInt cStart, cEnd, c; 133da43764aSToby Isaac 134da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K, d, &cStart, &cEnd);CHKERRQ(ierr); 135da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 136da43764aSToby Isaac permvals[offset++] = c; 137da43764aSToby Isaac } 138da43764aSToby Isaac 139da43764aSToby Isaac ierr = DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd);CHKERRQ(ierr); 140da43764aSToby Isaac for (c = cStart; c < cEnd; c++) { 141da43764aSToby Isaac permvals[offset++] = c + (pEnd - pStart); 142da43764aSToby Isaac } 143da43764aSToby Isaac } 144da43764aSToby Isaac ierr = ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr); 145da43764aSToby Isaac ierr = PetscSectionSetPermutation(unionSection,perm);CHKERRQ(ierr); 146da43764aSToby Isaac ierr = PetscSectionSetUp(unionSection);CHKERRQ(ierr); 147da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionSection,&numUnionPoints);CHKERRQ(ierr); 148da43764aSToby Isaac ierr = PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints);CHKERRQ(ierr); 149da43764aSToby Isaac /* count dimension points */ 150da43764aSToby Isaac for (d = 0; d <= dim; d++) { 151da43764aSToby Isaac PetscInt cStart, cOff, cOff2; 152da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d,&cStart,NULL);CHKERRQ(ierr); 153da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff);CHKERRQ(ierr); 154da43764aSToby Isaac if (d < dim) { 155da43764aSToby Isaac ierr = DMPlexGetHeightStratum(K,d+1,&cStart,NULL);CHKERRQ(ierr); 156da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2);CHKERRQ(ierr); 157da43764aSToby Isaac } 158da43764aSToby Isaac else { 159da43764aSToby Isaac cOff2 = numUnionPoints; 160da43764aSToby Isaac } 161da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff; 162da43764aSToby Isaac } 163da43764aSToby Isaac ierr = PetscSectionCreate(comm, &unionConeSection);CHKERRQ(ierr); 164da43764aSToby Isaac ierr = PetscSectionSetChart(unionConeSection, 0, numUnionPoints);CHKERRQ(ierr); 165da43764aSToby Isaac /* count the cones in the union */ 166da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 167da43764aSToby Isaac PetscInt dof, uOff; 168da43764aSToby Isaac 169da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 170da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 171da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 172da43764aSToby Isaac coneSizes[uOff] = dof; 173da43764aSToby Isaac } 174da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 175da43764aSToby Isaac PetscInt dof, uDof, uOff; 176da43764aSToby Isaac 177da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 178da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 179da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 180da43764aSToby Isaac if (uDof) { 181da43764aSToby Isaac ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 182da43764aSToby Isaac coneSizes[uOff] = dof; 183da43764aSToby Isaac } 184da43764aSToby Isaac } 185da43764aSToby Isaac ierr = PetscSectionSetUp(unionConeSection);CHKERRQ(ierr); 186da43764aSToby Isaac ierr = PetscSectionGetStorageSize(unionConeSection,&numCones);CHKERRQ(ierr); 187da43764aSToby Isaac ierr = PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations);CHKERRQ(ierr); 188da43764aSToby Isaac /* write the cones in the union */ 189da43764aSToby Isaac for (p = pStart; p < pEnd; p++) { 190da43764aSToby Isaac PetscInt dof, uOff, c, cOff; 191da43764aSToby Isaac const PetscInt *cone, *orientation; 192da43764aSToby Isaac 193da43764aSToby Isaac ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 194da43764aSToby Isaac ierr = DMPlexGetCone(K, p, &cone);CHKERRQ(ierr); 195da43764aSToby Isaac ierr = DMPlexGetConeOrientation(K, p, &orientation);CHKERRQ(ierr); 196da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 197da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 198da43764aSToby Isaac for (c = 0; c < dof; c++) { 199da43764aSToby Isaac PetscInt e, eOff; 200da43764aSToby Isaac e = cone[c]; 201da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 202da43764aSToby Isaac unionCones[cOff + c] = eOff; 203da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 204da43764aSToby Isaac } 205da43764aSToby Isaac } 206da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 207da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff; 208da43764aSToby Isaac const PetscInt *cone, *orientation; 209da43764aSToby Isaac 210da43764aSToby Isaac ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 211da43764aSToby Isaac ierr = DMPlexGetCone(Kref, p, &cone);CHKERRQ(ierr); 212da43764aSToby Isaac ierr = DMPlexGetConeOrientation(Kref, p, &orientation);CHKERRQ(ierr); 213da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 214da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 215da43764aSToby Isaac if (uDof) { 216da43764aSToby Isaac ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 217da43764aSToby Isaac for (c = 0; c < dof; c++) { 218da43764aSToby Isaac PetscInt e, eOff, eDof; 219da43764aSToby Isaac 220da43764aSToby Isaac e = cone[c]; 221da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof);CHKERRQ(ierr); 222da43764aSToby Isaac if (eDof) { 223da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff);CHKERRQ(ierr); 224da43764aSToby Isaac } 225da43764aSToby Isaac else { 226da43764aSToby Isaac ierr = DMLabelGetValue(identityRef, e, &e);CHKERRQ(ierr); 227da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 228da43764aSToby Isaac } 229da43764aSToby Isaac unionCones[cOff + c] = eOff; 230da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c]; 231da43764aSToby Isaac } 232da43764aSToby Isaac } 233da43764aSToby Isaac } 234da43764aSToby Isaac /* get the coordinates */ 235da43764aSToby Isaac { 236da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 237da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec; 238da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec; 239da43764aSToby Isaac PetscScalar *Kcoords; 240da43764aSToby Isaac 241da43764aSToby Isaac DMGetCoordinateSection(K, &KcoordsSec);CHKERRQ(ierr); 242da43764aSToby Isaac DMGetCoordinatesLocal(K, &KcoordsVec);CHKERRQ(ierr); 243da43764aSToby Isaac DMGetCoordinateSection(Kref, &KrefCoordsSec);CHKERRQ(ierr); 244da43764aSToby Isaac DMGetCoordinatesLocal(Kref, &KrefCoordsVec);CHKERRQ(ierr); 245da43764aSToby Isaac 246da43764aSToby Isaac numVerts = numDimPoints[0]; 247da43764aSToby Isaac ierr = PetscMalloc1(numVerts * dim,&unionCoords);CHKERRQ(ierr); 248da43764aSToby Isaac ierr = DMPlexGetDepthStratum(K,0,&vStart,&vEnd);CHKERRQ(ierr); 249da43764aSToby Isaac 250da43764aSToby Isaac offset = 0; 251da43764aSToby Isaac for (v = vStart; v < vEnd; v++) { 252da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pStart,&vOff);CHKERRQ(ierr); 253da43764aSToby Isaac ierr = VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords);CHKERRQ(ierr); 254da43764aSToby Isaac for (d = 0; d < dim; d++) { 255da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 256da43764aSToby Isaac } 257da43764aSToby Isaac offset++; 258da43764aSToby Isaac } 259da43764aSToby Isaac ierr = DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd);CHKERRQ(ierr); 260da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) { 261da43764aSToby Isaac ierr = PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof);CHKERRQ(ierr); 262da43764aSToby Isaac ierr = PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff);CHKERRQ(ierr); 263da43764aSToby Isaac ierr = VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords);CHKERRQ(ierr); 264da43764aSToby Isaac if (vDof) { 265da43764aSToby Isaac for (d = 0; d < dim; d++) { 266da43764aSToby Isaac unionCoords[offset * dim + d] = Kcoords[d]; 267da43764aSToby Isaac } 268da43764aSToby Isaac offset++; 269da43764aSToby Isaac } 270da43764aSToby Isaac } 271da43764aSToby Isaac } 272da43764aSToby Isaac ierr = DMCreate(comm,ref);CHKERRQ(ierr); 273da43764aSToby Isaac ierr = DMSetType(*ref,DMPLEX);CHKERRQ(ierr); 274da43764aSToby Isaac ierr = DMPlexSetDimension(*ref,dim);CHKERRQ(ierr); 275da43764aSToby Isaac ierr = DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords);CHKERRQ(ierr); 27610f7e118SToby Isaac /* set the tree */ 27710f7e118SToby Isaac ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr); 27810f7e118SToby Isaac ierr = PetscSectionSetChart(parentSection,0,numUnionPoints);CHKERRQ(ierr); 27910f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 28010f7e118SToby Isaac PetscInt uDof, uOff; 28110f7e118SToby Isaac 28210f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 28310f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 28410f7e118SToby Isaac if (uDof) { 28510f7e118SToby Isaac PetscSectionSetDof(parentSection,uOff,1);CHKERRQ(ierr); 28610f7e118SToby Isaac } 28710f7e118SToby Isaac } 28810f7e118SToby Isaac ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 28910f7e118SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&parentSize);CHKERRQ(ierr); 29010f7e118SToby Isaac ierr = PetscMalloc2(parentSize,&parents,parentSize,&childIDs);CHKERRQ(ierr); 29110f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) { 29210f7e118SToby Isaac PetscInt uDof, uOff; 29310f7e118SToby Isaac 29410f7e118SToby Isaac ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 29510f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 29610f7e118SToby Isaac if (uDof) { 29710f7e118SToby Isaac PetscInt pOff, parent, parentU; 29810f7e118SToby Isaac PetscSectionGetOffset(parentSection,uOff,&pOff);CHKERRQ(ierr); 29910f7e118SToby Isaac DMLabelGetValue(identityRef,p,&parent);CHKERRQ(ierr); 30010f7e118SToby Isaac ierr = PetscSectionGetOffset(unionSection, parent - pStart,&parentU);CHKERRQ(ierr); 30110f7e118SToby Isaac parents[pOff] = parentU; 30210f7e118SToby Isaac childIDs[pOff] = uOff; 30310f7e118SToby Isaac } 30410f7e118SToby Isaac } 30510f7e118SToby Isaac ierr = DMPlexSetTree(*ref,parentSection,parents,childIDs);CHKERRQ(ierr); 30610f7e118SToby Isaac ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 30710f7e118SToby Isaac ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 30810f7e118SToby Isaac 309da43764aSToby Isaac /* clean up */ 310da43764aSToby Isaac ierr = PetscSectionDestroy(&unionSection);CHKERRQ(ierr); 311da43764aSToby Isaac ierr = PetscSectionDestroy(&unionConeSection);CHKERRQ(ierr); 312da43764aSToby Isaac ierr = ISDestroy(&perm);CHKERRQ(ierr); 313da43764aSToby Isaac ierr = PetscFree(unionCoords);CHKERRQ(ierr); 314da43764aSToby Isaac ierr = PetscFree2(unionCones,unionOrientations);CHKERRQ(ierr); 315da43764aSToby Isaac ierr = PetscFree2(coneSizes,numDimPoints);CHKERRQ(ierr); 316da43764aSToby Isaac ierr = DMDestroy(&K);CHKERRQ(ierr); 317da43764aSToby Isaac ierr = DMDestroy(&Kref);CHKERRQ(ierr); 318da43764aSToby Isaac PetscFunctionReturn(0); 319da43764aSToby Isaac } 320da43764aSToby Isaac 321d961a43aSToby Isaac #undef __FUNCT__ 322878b19aaSToby Isaac #define __FUNCT__ "DMPlexTreeSymmetrize" 323878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 324878b19aaSToby Isaac { 325878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 326878b19aaSToby Isaac PetscSection childSec, pSec; 327878b19aaSToby Isaac PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 328878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd; 329878b19aaSToby Isaac PetscErrorCode ierr; 330878b19aaSToby Isaac 331878b19aaSToby Isaac PetscFunctionBegin; 332878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 333878b19aaSToby Isaac ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 334878b19aaSToby Isaac ierr = PetscFree(mesh->children);CHKERRQ(ierr); 335878b19aaSToby Isaac pSec = mesh->parentSection; 336878b19aaSToby Isaac if (!pSec) PetscFunctionReturn(0); 337878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(pSec,&pSize);CHKERRQ(ierr); 338878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 339878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 340878b19aaSToby Isaac 341878b19aaSToby Isaac parMax = PetscMax(parMax,par+1); 342878b19aaSToby Isaac parMin = PetscMin(parMin,par); 343878b19aaSToby Isaac } 344878b19aaSToby Isaac if (parMin > parMax) { 345878b19aaSToby Isaac parMin = -1; 346878b19aaSToby Isaac parMax = -1; 347878b19aaSToby Isaac } 348878b19aaSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec);CHKERRQ(ierr); 349878b19aaSToby Isaac ierr = PetscSectionSetChart(childSec,parMin,parMax);CHKERRQ(ierr); 350878b19aaSToby Isaac for (p = 0; p < pSize; p++) { 351878b19aaSToby Isaac PetscInt par = mesh->parents[p]; 352878b19aaSToby Isaac 353878b19aaSToby Isaac ierr = PetscSectionAddDof(childSec,par,1);CHKERRQ(ierr); 354878b19aaSToby Isaac } 355878b19aaSToby Isaac ierr = PetscSectionSetUp(childSec);CHKERRQ(ierr); 356878b19aaSToby Isaac ierr = PetscSectionGetStorageSize(childSec,&cSize);CHKERRQ(ierr); 357878b19aaSToby Isaac ierr = PetscMalloc1(cSize,&children);CHKERRQ(ierr); 358878b19aaSToby Isaac ierr = PetscCalloc1(parMax-parMin,&offsets);CHKERRQ(ierr); 359878b19aaSToby Isaac ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr); 360878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) { 361878b19aaSToby Isaac PetscInt dof, off, i; 362878b19aaSToby Isaac 363878b19aaSToby Isaac ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 364878b19aaSToby Isaac ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr); 365878b19aaSToby Isaac for (i = 0; i < dof; i++) { 366878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff; 367878b19aaSToby Isaac 368878b19aaSToby Isaac ierr = PetscSectionGetOffset(childSec,par,&cOff);CHKERRQ(ierr); 369878b19aaSToby Isaac children[cOff + offsets[par-parMin]++] = p; 370878b19aaSToby Isaac } 371878b19aaSToby Isaac } 372878b19aaSToby Isaac mesh->childSection = childSec; 373878b19aaSToby Isaac mesh->children = children; 374878b19aaSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 375878b19aaSToby Isaac PetscFunctionReturn(0); 376878b19aaSToby Isaac } 377878b19aaSToby Isaac 378878b19aaSToby Isaac #undef __FUNCT__ 3796dd5a8c8SToby Isaac #define __FUNCT__ "AnchorsFlatten" 3806dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew) 3816dd5a8c8SToby Isaac { 3826dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL; 3836dd5a8c8SToby Isaac const PetscInt *vals; 3846dd5a8c8SToby Isaac PetscSection secNew; 3856dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew; 3866dd5a8c8SToby Isaac PetscBool compress; 3876dd5a8c8SToby Isaac PetscErrorCode ierr; 3886dd5a8c8SToby Isaac 3896dd5a8c8SToby Isaac PetscFunctionBegin; 3906dd5a8c8SToby Isaac ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr); 3916dd5a8c8SToby Isaac ierr = ISGetLocalSize(is,&size);CHKERRQ(ierr); 3926dd5a8c8SToby Isaac ierr = ISGetIndices(is,&vals);CHKERRQ(ierr); 3936dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew);CHKERRQ(ierr); 3946dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secNew,pStart,pEnd);CHKERRQ(ierr); 3956dd5a8c8SToby Isaac for (i = 0; i < size; i++) { 3966dd5a8c8SToby Isaac PetscInt dof; 3976dd5a8c8SToby Isaac 3986dd5a8c8SToby Isaac p = vals[i]; 3996dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue; 4006dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 4016dd5a8c8SToby Isaac if (dof) break; 4026dd5a8c8SToby Isaac } 4036dd5a8c8SToby Isaac if (i == size) { 4046dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 4056dd5a8c8SToby Isaac anyNew = PETSC_FALSE; 4066dd5a8c8SToby Isaac compress = PETSC_FALSE; 4076dd5a8c8SToby Isaac sizeNew = 0; 4086dd5a8c8SToby Isaac } 4096dd5a8c8SToby Isaac else { 4106dd5a8c8SToby Isaac anyNew = PETSC_TRUE; 4116dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 4126dd5a8c8SToby Isaac PetscInt dof, off; 4136dd5a8c8SToby Isaac 4146dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 4156dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 4166dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 4176dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0; 4186dd5a8c8SToby Isaac 4196dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 4206dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 4216dd5a8c8SToby Isaac } 4226dd5a8c8SToby Isaac if (qDof) { 4236dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, qDof);CHKERRQ(ierr); 4246dd5a8c8SToby Isaac } 4256dd5a8c8SToby Isaac else { 4266dd5a8c8SToby Isaac ierr = PetscSectionAddDof(secNew, p, 1);CHKERRQ(ierr); 4276dd5a8c8SToby Isaac } 4286dd5a8c8SToby Isaac } 4296dd5a8c8SToby Isaac } 4306dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr); 4316dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secNew,&sizeNew);CHKERRQ(ierr); 4326dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsNew);CHKERRQ(ierr); 4336dd5a8c8SToby Isaac compress = PETSC_FALSE; 4346dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 4356dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew; 4366dd5a8c8SToby Isaac 4376dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 4386dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 4396dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dofNew);CHKERRQ(ierr); 4406dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &offNew);CHKERRQ(ierr); 4416dd5a8c8SToby Isaac count = 0; 4426dd5a8c8SToby Isaac for (i = 0; i < dof; i++) { 4436dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j; 4446dd5a8c8SToby Isaac 4456dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) { 4466dd5a8c8SToby Isaac ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr); 4476dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(section, q, &qOff);CHKERRQ(ierr); 4486dd5a8c8SToby Isaac } 4496dd5a8c8SToby Isaac if (qDof) { 4506dd5a8c8SToby Isaac PetscInt oldCount = count; 4516dd5a8c8SToby Isaac 4526dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) { 4536dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j]; 4546dd5a8c8SToby Isaac 4556dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 4566dd5a8c8SToby Isaac if (valsNew[offNew + k] == r) { 4576dd5a8c8SToby Isaac break; 4586dd5a8c8SToby Isaac } 4596dd5a8c8SToby Isaac } 4606dd5a8c8SToby Isaac if (k == oldCount) { 4616dd5a8c8SToby Isaac valsNew[offNew + count++] = r; 4626dd5a8c8SToby Isaac } 4636dd5a8c8SToby Isaac } 4646dd5a8c8SToby Isaac } 4656dd5a8c8SToby Isaac else { 4666dd5a8c8SToby Isaac PetscInt k, oldCount = count; 4676dd5a8c8SToby Isaac 4686dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) { 4696dd5a8c8SToby Isaac if (valsNew[offNew + k] == q) { 4706dd5a8c8SToby Isaac break; 4716dd5a8c8SToby Isaac } 4726dd5a8c8SToby Isaac } 4736dd5a8c8SToby Isaac if (k == oldCount) { 4746dd5a8c8SToby Isaac valsNew[offNew + count++] = q; 4756dd5a8c8SToby Isaac } 4766dd5a8c8SToby Isaac } 4776dd5a8c8SToby Isaac } 4786dd5a8c8SToby Isaac if (count < dofNew) { 4796dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secNew, p, count);CHKERRQ(ierr); 4806dd5a8c8SToby Isaac compress = PETSC_TRUE; 4816dd5a8c8SToby Isaac } 4826dd5a8c8SToby Isaac } 4836dd5a8c8SToby Isaac } 4846dd5a8c8SToby Isaac ierr = ISRestoreIndices(is,&vals);CHKERRQ(ierr); 4856dd5a8c8SToby Isaac ierr = MPI_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 4866dd5a8c8SToby Isaac if (!globalAnyNew) { 4876dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 4886dd5a8c8SToby Isaac *sectionNew = NULL; 4896dd5a8c8SToby Isaac *isNew = NULL; 4906dd5a8c8SToby Isaac } 4916dd5a8c8SToby Isaac else { 4926dd5a8c8SToby Isaac PetscBool globalCompress; 4936dd5a8c8SToby Isaac 4946dd5a8c8SToby Isaac ierr = MPI_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr); 4956dd5a8c8SToby Isaac if (compress) { 4966dd5a8c8SToby Isaac PetscSection secComp; 4976dd5a8c8SToby Isaac PetscInt *valsComp = NULL; 4986dd5a8c8SToby Isaac 4996dd5a8c8SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp);CHKERRQ(ierr); 5006dd5a8c8SToby Isaac ierr = PetscSectionSetChart(secComp,pStart,pEnd);CHKERRQ(ierr); 5016dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5026dd5a8c8SToby Isaac PetscInt dof; 5036dd5a8c8SToby Isaac 5046dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 5056dd5a8c8SToby Isaac ierr = PetscSectionSetDof(secComp, p, dof);CHKERRQ(ierr); 5066dd5a8c8SToby Isaac } 5076dd5a8c8SToby Isaac ierr = PetscSectionSetUp(secComp);CHKERRQ(ierr); 5086dd5a8c8SToby Isaac ierr = PetscSectionGetStorageSize(secComp,&sizeNew);CHKERRQ(ierr); 5096dd5a8c8SToby Isaac ierr = PetscMalloc1(sizeNew,&valsComp);CHKERRQ(ierr); 5106dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) { 5116dd5a8c8SToby Isaac PetscInt dof, off, offNew, j; 5126dd5a8c8SToby Isaac 5136dd5a8c8SToby Isaac ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr); 5146dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secNew, p, &off);CHKERRQ(ierr); 5156dd5a8c8SToby Isaac ierr = PetscSectionGetOffset(secComp, p, &offNew);CHKERRQ(ierr); 5166dd5a8c8SToby Isaac for (j = 0; j < dof; j++) { 5176dd5a8c8SToby Isaac valsComp[offNew + j] = valsNew[off + j]; 5186dd5a8c8SToby Isaac } 5196dd5a8c8SToby Isaac } 5206dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr); 5216dd5a8c8SToby Isaac secNew = secComp; 5226dd5a8c8SToby Isaac ierr = PetscFree(valsNew);CHKERRQ(ierr); 5236dd5a8c8SToby Isaac valsNew = valsComp; 5246dd5a8c8SToby Isaac } 5256dd5a8c8SToby Isaac ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew);CHKERRQ(ierr); 5266dd5a8c8SToby Isaac } 5276dd5a8c8SToby Isaac PetscFunctionReturn(0); 5286dd5a8c8SToby Isaac } 5296dd5a8c8SToby Isaac 5306dd5a8c8SToby Isaac #undef __FUNCT__ 53166af876cSToby Isaac #define __FUNCT__ "DMPlexComputeConstraints_Tree" 53266af876cSToby Isaac static PetscErrorCode DMPlexComputeConstraints_Tree(DM dm) 53366af876cSToby Isaac { 53466af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size; 53566af876cSToby Isaac PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 53666af876cSToby Isaac PetscSection aSec; 53766af876cSToby Isaac IS aIS; 53866af876cSToby Isaac PetscErrorCode ierr; 53966af876cSToby Isaac 54066af876cSToby Isaac PetscFunctionBegin; 54166af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54266af876cSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 54366af876cSToby Isaac for (p = pStart; p < pEnd; p++) { 54466af876cSToby Isaac PetscInt parent; 54566af876cSToby Isaac 54666af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 54766af876cSToby Isaac if (parent != p) { 54866af876cSToby Isaac aMin = PetscMin(aMin,p); 54966af876cSToby Isaac aMax = PetscMax(aMax,p+1); 55066af876cSToby Isaac } 55166af876cSToby Isaac } 55266af876cSToby Isaac if (aMin > aMax) { 55366af876cSToby Isaac aMin = -1; 55466af876cSToby Isaac aMax = -1; 55566af876cSToby Isaac } 55666af876cSToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&aSec);CHKERRQ(ierr); 55766af876cSToby Isaac ierr = PetscSectionSetChart(aSec,aMin,aMax);CHKERRQ(ierr); 55866af876cSToby Isaac for (p = aMin; p < aMax; p++) { 55966af876cSToby Isaac PetscInt parent, ancestor = p; 56066af876cSToby Isaac 56166af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 56266af876cSToby Isaac while (parent != ancestor) { 56366af876cSToby Isaac ancestor = parent; 56466af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 56566af876cSToby Isaac } 56666af876cSToby Isaac if (ancestor != p) { 56766af876cSToby Isaac PetscInt closureSize, *closure = NULL; 56866af876cSToby Isaac 56966af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 57066af876cSToby Isaac ierr = PetscSectionSetDof(aSec,p,closureSize);CHKERRQ(ierr); 57166af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 57266af876cSToby Isaac } 57366af876cSToby Isaac } 57466af876cSToby Isaac ierr = PetscSectionSetUp(aSec);CHKERRQ(ierr); 57566af876cSToby Isaac ierr = PetscSectionGetStorageSize(aSec,&size);CHKERRQ(ierr); 57666af876cSToby Isaac ierr = PetscMalloc1(size,&anchors);CHKERRQ(ierr); 57766af876cSToby Isaac for (p = aMin; p < aMax; p++) { 57866af876cSToby Isaac PetscInt parent, ancestor = p; 57966af876cSToby Isaac 58066af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 58166af876cSToby Isaac while (parent != ancestor) { 58266af876cSToby Isaac ancestor = parent; 58366af876cSToby Isaac ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 58466af876cSToby Isaac } 58566af876cSToby Isaac if (ancestor != p) { 58666af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff; 58766af876cSToby Isaac 58866af876cSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 58966af876cSToby Isaac 59066af876cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 59166af876cSToby Isaac for (j = 0; j < closureSize; j++) { 59266af876cSToby Isaac anchors[aOff + j] = closure[2*j]; 59366af876cSToby Isaac } 59466af876cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 59566af876cSToby Isaac } 59666af876cSToby Isaac } 59766af876cSToby Isaac ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm),size,anchors,PETSC_OWN_POINTER,&aIS);CHKERRQ(ierr); 5986dd5a8c8SToby Isaac { 5996dd5a8c8SToby Isaac PetscSection aSecNew = aSec; 6006dd5a8c8SToby Isaac IS aISNew = aIS; 6016dd5a8c8SToby Isaac 6026dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aSec);CHKERRQ(ierr); 6036dd5a8c8SToby Isaac ierr = PetscObjectReference((PetscObject)aIS);CHKERRQ(ierr); 6046dd5a8c8SToby Isaac while (aSecNew) { 6056dd5a8c8SToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 6066dd5a8c8SToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 6076dd5a8c8SToby Isaac aSec = aSecNew; 6086dd5a8c8SToby Isaac aIS = aISNew; 6096dd5a8c8SToby Isaac aSecNew = NULL; 6106dd5a8c8SToby Isaac aISNew = NULL; 6116dd5a8c8SToby Isaac ierr = AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew);CHKERRQ(ierr); 6126dd5a8c8SToby Isaac } 6136dd5a8c8SToby Isaac } 61466af876cSToby Isaac ierr = DMPlexSetConstraints(dm,aSec,aIS);CHKERRQ(ierr); 61566af876cSToby Isaac ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 61666af876cSToby Isaac ierr = ISDestroy(&aIS);CHKERRQ(ierr); 61766af876cSToby Isaac PetscFunctionReturn(0); 61866af876cSToby Isaac } 61966af876cSToby Isaac 62066af876cSToby Isaac #undef __FUNCT__ 6210b7167a0SToby Isaac #define __FUNCT__ "DMPlexSetTree" 6220b7167a0SToby Isaac /*@ 6230b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 6240b7167a0SToby Isaac the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 6250b7167a0SToby Isaac tree root. 6260b7167a0SToby Isaac 6270b7167a0SToby Isaac Collective on dm 6280b7167a0SToby Isaac 6290b7167a0SToby Isaac Input Parameters: 6300b7167a0SToby Isaac + dm - the DMPlex object 6310b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 6320b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented 6330b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed 6340b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 6350b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 6360b7167a0SToby Isaac 6370b7167a0SToby Isaac Level: intermediate 6380b7167a0SToby Isaac 639b2f41788SToby Isaac .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetConstraints(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 6400b7167a0SToby Isaac @*/ 641b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 6420b7167a0SToby Isaac { 6430b7167a0SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 6440b7167a0SToby Isaac PetscInt size; 6450b7167a0SToby Isaac PetscErrorCode ierr; 6460b7167a0SToby Isaac 6470b7167a0SToby Isaac PetscFunctionBegin; 6480b7167a0SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6490b7167a0SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 6500b7167a0SToby Isaac ierr = PetscObjectReference((PetscObject)parentSection);CHKERRQ(ierr); 6510b7167a0SToby Isaac ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 6520b7167a0SToby Isaac mesh->parentSection = parentSection; 6530b7167a0SToby Isaac ierr = PetscSectionGetStorageSize(parentSection,&size);CHKERRQ(ierr); 6540b7167a0SToby Isaac if (parents != mesh->parents) { 6550b7167a0SToby Isaac ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 6560b7167a0SToby Isaac ierr = PetscMalloc1(size,&mesh->parents);CHKERRQ(ierr); 6570b7167a0SToby Isaac ierr = PetscMemcpy(mesh->parents, parents, size * sizeof(*parents));CHKERRQ(ierr); 6580b7167a0SToby Isaac } 6590b7167a0SToby Isaac if (childIDs != mesh->childIDs) { 6600b7167a0SToby Isaac ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 6610b7167a0SToby Isaac ierr = PetscMalloc1(size,&mesh->childIDs);CHKERRQ(ierr); 6620b7167a0SToby Isaac ierr = PetscMemcpy(mesh->childIDs, childIDs, size * sizeof(*childIDs));CHKERRQ(ierr); 6630b7167a0SToby Isaac } 664878b19aaSToby Isaac ierr = DMPlexTreeSymmetrize(dm);CHKERRQ(ierr); 66566af876cSToby Isaac ierr = DMPlexComputeConstraints_Tree(dm);CHKERRQ(ierr); 6660b7167a0SToby Isaac PetscFunctionReturn(0); 6670b7167a0SToby Isaac } 6680b7167a0SToby Isaac 6690b7167a0SToby Isaac #undef __FUNCT__ 670b2f41788SToby Isaac #define __FUNCT__ "DMPlexGetTree" 671b2f41788SToby Isaac /*@ 672b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 673b2f41788SToby Isaac Collective on dm 674b2f41788SToby Isaac 675b2f41788SToby Isaac Input Parameters: 676b2f41788SToby Isaac . dm - the DMPlex object 677b2f41788SToby Isaac 678b2f41788SToby Isaac Output Parameters: 679b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 680b2f41788SToby Isaac offset indexes the parent and childID list 681b2f41788SToby Isaac . parents - a list of the point parents 682b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 683b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID 684b2f41788SToby Isaac . childSection - the inverse of the parent section 685b2f41788SToby Isaac - children - a list of the point children 686b2f41788SToby Isaac 687b2f41788SToby Isaac Level: intermediate 688b2f41788SToby Isaac 689b2f41788SToby Isaac .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetConstraints(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 690b2f41788SToby Isaac @*/ 691b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 692b2f41788SToby Isaac { 693b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 694b2f41788SToby Isaac 695b2f41788SToby Isaac PetscFunctionBegin; 696b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 697b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection; 698b2f41788SToby Isaac if (parents) *parents = mesh->parents; 699b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs; 700b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection; 701b2f41788SToby Isaac if (children) *children = mesh->children; 702b2f41788SToby Isaac PetscFunctionReturn(0); 703b2f41788SToby Isaac } 704b2f41788SToby Isaac 705b2f41788SToby Isaac #undef __FUNCT__ 706d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeParent" 707d961a43aSToby Isaac /*@ 708d961a43aSToby Isaac DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the Sieve DAG) 709d961a43aSToby Isaac 710d961a43aSToby Isaac Input Parameters: 711d961a43aSToby Isaac + dm - the DMPlex object 712d961a43aSToby Isaac - point - the query point 713d961a43aSToby Isaac 714d961a43aSToby Isaac Output Parameters: 715d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 716d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 717d961a43aSToby Isaac does not have a parent 718d961a43aSToby Isaac 719d961a43aSToby Isaac Level: intermediate 720d961a43aSToby Isaac 721d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren() 722d961a43aSToby Isaac @*/ 723d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 724d961a43aSToby Isaac { 725d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 726d961a43aSToby Isaac PetscSection pSec; 727d961a43aSToby Isaac PetscErrorCode ierr; 728d961a43aSToby Isaac 729d961a43aSToby Isaac PetscFunctionBegin; 730d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 731d961a43aSToby Isaac pSec = mesh->parentSection; 732d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 733d961a43aSToby Isaac PetscInt dof; 734d961a43aSToby Isaac 735d961a43aSToby Isaac ierr = PetscSectionGetDof (pSec, point, &dof);CHKERRQ(ierr); 736d961a43aSToby Isaac if (dof) { 737d961a43aSToby Isaac PetscInt off; 738d961a43aSToby Isaac 739d961a43aSToby Isaac ierr = PetscSectionGetOffset (pSec, point, &off);CHKERRQ(ierr); 740d961a43aSToby Isaac if (parent) *parent = mesh->parents[off]; 741d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off]; 742d961a43aSToby Isaac PetscFunctionReturn(0); 743d961a43aSToby Isaac } 744d961a43aSToby Isaac } 745d961a43aSToby Isaac if (parent) { 746d961a43aSToby Isaac *parent = point; 747d961a43aSToby Isaac } 748d961a43aSToby Isaac if (childID) { 749d961a43aSToby Isaac *childID = 0; 750d961a43aSToby Isaac } 751d961a43aSToby Isaac PetscFunctionReturn(0); 752d961a43aSToby Isaac } 753d961a43aSToby Isaac 754d961a43aSToby Isaac #undef __FUNCT__ 755d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeChildren" 756d961a43aSToby Isaac /*@C 757d961a43aSToby Isaac DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the Sieve DAG) 758d961a43aSToby Isaac 759d961a43aSToby Isaac Input Parameters: 760d961a43aSToby Isaac + dm - the DMPlex object 761d961a43aSToby Isaac - point - the query point 762d961a43aSToby Isaac 763d961a43aSToby Isaac Output Parameters: 764d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children 765d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children 766d961a43aSToby Isaac 767d961a43aSToby Isaac Level: intermediate 768d961a43aSToby Isaac 769d961a43aSToby Isaac Fortran Notes: 770d961a43aSToby Isaac Since it returns an array, this routine is only available in Fortran 90, and you must 771d961a43aSToby Isaac include petsc.h90 in your code. 772d961a43aSToby Isaac 773d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent() 774d961a43aSToby Isaac @*/ 775d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 776d961a43aSToby Isaac { 777d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 778d961a43aSToby Isaac PetscSection childSec; 779d961a43aSToby Isaac PetscInt dof = 0; 780d961a43aSToby Isaac PetscErrorCode ierr; 781d961a43aSToby Isaac 782d961a43aSToby Isaac PetscFunctionBegin; 783d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 784d961a43aSToby Isaac childSec = mesh->childSection; 785d961a43aSToby Isaac if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 786d961a43aSToby Isaac ierr = PetscSectionGetDof (childSec, point, &dof);CHKERRQ(ierr); 787d961a43aSToby Isaac } 788d961a43aSToby Isaac if (numChildren) *numChildren = dof; 789d961a43aSToby Isaac if (children) { 790d961a43aSToby Isaac if (dof) { 791d961a43aSToby Isaac PetscInt off; 792d961a43aSToby Isaac 793d961a43aSToby Isaac ierr = PetscSectionGetOffset (childSec, point, &off);CHKERRQ(ierr); 794d961a43aSToby Isaac *children = &mesh->children[off]; 795d961a43aSToby Isaac } 796d961a43aSToby Isaac else { 797d961a43aSToby Isaac *children = NULL; 798d961a43aSToby Isaac } 799d961a43aSToby Isaac } 800d961a43aSToby Isaac PetscFunctionReturn(0); 801d961a43aSToby Isaac } 802*0c37af3bSToby Isaac 803*0c37af3bSToby Isaac #undef __FUNCT__ 804*0c37af3bSToby Isaac #define __FUNCT__ "DMPlexComputeConstraintMatrix_ReferenceTree" 805*0c37af3bSToby Isaac PetscErrorCode DMPlexComputeConstraintMatrix_ReferenceTree(DM dm) 806*0c37af3bSToby Isaac { 807*0c37af3bSToby Isaac PetscDS ds; 808*0c37af3bSToby Isaac PetscInt spdim; 809*0c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd; 810*0c37af3bSToby Isaac const PetscInt *anchors; 811*0c37af3bSToby Isaac PetscSection section, cSec, aSec; 812*0c37af3bSToby Isaac Mat cMat; 813*0c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent; 814*0c37af3bSToby Isaac IS aIS; 815*0c37af3bSToby Isaac PetscErrorCode ierr; 816*0c37af3bSToby Isaac 817*0c37af3bSToby Isaac PetscFunctionBegin; 818*0c37af3bSToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 819*0c37af3bSToby Isaac ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 820*0c37af3bSToby Isaac ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr); 821*0c37af3bSToby Isaac ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 822*0c37af3bSToby Isaac ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 823*0c37af3bSToby Isaac ierr = DMPlexGetConstraintSection(dm,&cSec);CHKERRQ(ierr); 824*0c37af3bSToby Isaac ierr = DMPlexGetConstraints(dm,&aSec,&aIS);CHKERRQ(ierr); 825*0c37af3bSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 826*0c37af3bSToby Isaac ierr = PetscSectionGetChart(cSec,&conStart,&conEnd);CHKERRQ(ierr); 827*0c37af3bSToby Isaac ierr = DMPlexGetConstraintMatrix(dm,&cMat);CHKERRQ(ierr); 828*0c37af3bSToby Isaac ierr = DMPlexGetDimension(dm,&spdim);CHKERRQ(ierr); 829*0c37af3bSToby Isaac ierr = PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent);CHKERRQ(ierr); 830*0c37af3bSToby Isaac 831*0c37af3bSToby Isaac for (f = 0; f < numFields; f++) { 832*0c37af3bSToby Isaac PetscFE fe; 833*0c37af3bSToby Isaac PetscDualSpace space; 834*0c37af3bSToby Isaac PetscInt i, j, k, nPoints, offset; 835*0c37af3bSToby Isaac PetscInt fSize, fComp; 836*0c37af3bSToby Isaac PetscScalar *B = NULL; 837*0c37af3bSToby Isaac PetscReal *weights, *pointsRef, *pointsReal; 838*0c37af3bSToby Isaac Mat Amat, Bmat, Xmat; 839*0c37af3bSToby Isaac 840*0c37af3bSToby Isaac ierr = PetscDSGetDiscretization(ds,f,(PetscObject *)(&fe));CHKERRQ(ierr); 841*0c37af3bSToby Isaac ierr = PetscFEGetDualSpace(fe,&space);CHKERRQ(ierr); 842*0c37af3bSToby Isaac ierr = PetscDualSpaceGetDimension(space,&fSize);CHKERRQ(ierr); 843*0c37af3bSToby Isaac ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr); 844*0c37af3bSToby Isaac ierr = MatCreate(PETSC_COMM_SELF,&Amat);CHKERRQ(ierr); 845*0c37af3bSToby Isaac ierr = MatSetSizes(Amat,fSize,fSize,fSize,fSize);CHKERRQ(ierr); 846*0c37af3bSToby Isaac ierr = MatSetType(Amat,MATSEQDENSE);CHKERRQ(ierr); 847*0c37af3bSToby Isaac ierr = MatSetUp(Amat);CHKERRQ(ierr); 848*0c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat);CHKERRQ(ierr); 849*0c37af3bSToby Isaac ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat);CHKERRQ(ierr); 850*0c37af3bSToby Isaac nPoints = 0; 851*0c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 852*0c37af3bSToby Isaac PetscInt qPoints; 853*0c37af3bSToby Isaac PetscQuadrature quad; 854*0c37af3bSToby Isaac 855*0c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 856*0c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 857*0c37af3bSToby Isaac nPoints += qPoints; 858*0c37af3bSToby Isaac } 859*0c37af3bSToby Isaac ierr = PetscMalloc3(nPoints,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal);CHKERRQ(ierr); 860*0c37af3bSToby Isaac offset = 0; 861*0c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 862*0c37af3bSToby Isaac PetscInt qPoints; 863*0c37af3bSToby Isaac const PetscReal *p, *w; 864*0c37af3bSToby Isaac PetscQuadrature quad; 865*0c37af3bSToby Isaac 866*0c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 867*0c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,&p,&w);CHKERRQ(ierr); 868*0c37af3bSToby Isaac ierr = PetscMemcpy(weights+offset,w,qPoints*sizeof(*w));CHKERRQ(ierr); 869*0c37af3bSToby Isaac ierr = PetscMemcpy(pointsRef+spdim*offset,p,spdim*qPoints*sizeof(*p));CHKERRQ(ierr); 870*0c37af3bSToby Isaac offset += qPoints; 871*0c37af3bSToby Isaac } 872*0c37af3bSToby Isaac ierr = PetscFEGetTabulation(fe,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 873*0c37af3bSToby Isaac offset = 0; 874*0c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 875*0c37af3bSToby Isaac PetscInt qPoints; 876*0c37af3bSToby Isaac PetscQuadrature quad; 877*0c37af3bSToby Isaac 878*0c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 879*0c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 880*0c37af3bSToby Isaac for (j = 0; j < fSize; j++) { 881*0c37af3bSToby Isaac PetscScalar val = 0.; 882*0c37af3bSToby Isaac 883*0c37af3bSToby Isaac for (k = 0; k < qPoints; k++) { 884*0c37af3bSToby Isaac val += B[((offset + k) * fSize + j) * fComp] * weights[k]; 885*0c37af3bSToby Isaac } 886*0c37af3bSToby Isaac ierr = MatSetValue(Amat,i,j,val,INSERT_VALUES);CHKERRQ(ierr); 887*0c37af3bSToby Isaac } 888*0c37af3bSToby Isaac offset += qPoints; 889*0c37af3bSToby Isaac } 890*0c37af3bSToby Isaac ierr = PetscFERestoreTabulation(fe,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr); 891*0c37af3bSToby Isaac ierr = MatAssemblyBegin(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 892*0c37af3bSToby Isaac ierr = MatAssemblyEnd(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 893*0c37af3bSToby Isaac ierr = MatLUFactor(Amat,NULL,NULL,NULL);CHKERRQ(ierr); 894*0c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) { 895*0c37af3bSToby Isaac PetscInt parent; 896*0c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL; 897*0c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets; 898*0c37af3bSToby Isaac 899*0c37af3bSToby Isaac ierr = DMPlexGetTreeParent(dm,c,&parent,NULL);CHKERRQ(ierr); 900*0c37af3bSToby Isaac if (parent == c) continue; 901*0c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 902*0c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 903*0c37af3bSToby Isaac PetscInt p = closure[2*i]; 904*0c37af3bSToby Isaac PetscInt conDof; 905*0c37af3bSToby Isaac 906*0c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 907*0c37af3bSToby Isaac if (numFields > 1) { 908*0c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 909*0c37af3bSToby Isaac } 910*0c37af3bSToby Isaac else { 911*0c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 912*0c37af3bSToby Isaac } 913*0c37af3bSToby Isaac if (conDof) break; 914*0c37af3bSToby Isaac } 915*0c37af3bSToby Isaac if (i == closureSize) { 916*0c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 917*0c37af3bSToby Isaac continue; 918*0c37af3bSToby Isaac } 919*0c37af3bSToby Isaac 920*0c37af3bSToby Isaac ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 921*0c37af3bSToby Isaac ierr = DMPlexComputeCellGeometry(dm, parent, v0parent, Jparent, invJparent, &detJparent);CHKERRQ(ierr); 922*0c37af3bSToby Isaac for (i = 0; i < nPoints; i++) { 923*0c37af3bSToby Isaac CoordinatesRefToReal(spdim, spdim, v0, J, &pointsRef[i*spdim],vtmp);CHKERRQ(ierr); 924*0c37af3bSToby Isaac CoordinatesRealToRef(spdim, spdim, v0parent, invJparent, vtmp, &pointsReal[i*spdim]);CHKERRQ(ierr); 925*0c37af3bSToby Isaac } 926*0c37af3bSToby Isaac ierr = PetscFEGetTabulation(fe,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 927*0c37af3bSToby Isaac offset = 0; 928*0c37af3bSToby Isaac for (i = 0; i < fSize; i++) { 929*0c37af3bSToby Isaac PetscInt qPoints; 930*0c37af3bSToby Isaac PetscQuadrature quad; 931*0c37af3bSToby Isaac 932*0c37af3bSToby Isaac ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr); 933*0c37af3bSToby Isaac ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr); 934*0c37af3bSToby Isaac for (j = 0; j < fSize; j++) { 935*0c37af3bSToby Isaac PetscScalar val = 0.; 936*0c37af3bSToby Isaac 937*0c37af3bSToby Isaac for (k = 0; k < qPoints; k++) { 938*0c37af3bSToby Isaac val += B[((offset + k) * fSize + j) * fComp] * weights[k]; 939*0c37af3bSToby Isaac } 940*0c37af3bSToby Isaac MatSetValue(Bmat,i,j,val,INSERT_VALUES);CHKERRQ(ierr); 941*0c37af3bSToby Isaac } 942*0c37af3bSToby Isaac offset += qPoints; 943*0c37af3bSToby Isaac } 944*0c37af3bSToby Isaac ierr = PetscFERestoreTabulation(fe,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr); 945*0c37af3bSToby Isaac ierr = MatAssemblyBegin(Bmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 946*0c37af3bSToby Isaac ierr = MatAssemblyEnd(Bmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 947*0c37af3bSToby Isaac ierr = MatMatSolve(Amat,Bmat,Xmat);CHKERRQ(ierr); 948*0c37af3bSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 949*0c37af3bSToby Isaac ierr = PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets);CHKERRQ(ierr); 950*0c37af3bSToby Isaac childOffsets[0] = 0; 951*0c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 952*0c37af3bSToby Isaac PetscInt p = closure[2*i]; 953*0c37af3bSToby Isaac PetscInt dof; 954*0c37af3bSToby Isaac 955*0c37af3bSToby Isaac if (numFields > 1) { 956*0c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 957*0c37af3bSToby Isaac } 958*0c37af3bSToby Isaac else { 959*0c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 960*0c37af3bSToby Isaac } 961*0c37af3bSToby Isaac childOffsets[i+1]=childOffsets[i]+dof / fComp; 962*0c37af3bSToby Isaac } 963*0c37af3bSToby Isaac parentOffsets[0] = 0; 964*0c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) { 965*0c37af3bSToby Isaac PetscInt p = closureP[2*i]; 966*0c37af3bSToby Isaac PetscInt dof; 967*0c37af3bSToby Isaac 968*0c37af3bSToby Isaac if (numFields > 1) { 969*0c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 970*0c37af3bSToby Isaac } 971*0c37af3bSToby Isaac else { 972*0c37af3bSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 973*0c37af3bSToby Isaac } 974*0c37af3bSToby Isaac parentOffsets[i+1]=parentOffsets[i]+dof / fComp; 975*0c37af3bSToby Isaac } 976*0c37af3bSToby Isaac for (i = 0; i < closureSize; i++) { 977*0c37af3bSToby Isaac PetscInt conDof, conOff, aDof, aOff; 978*0c37af3bSToby Isaac PetscInt p = closure[2*i]; 979*0c37af3bSToby Isaac PetscInt o = closure[2*i+1]; 980*0c37af3bSToby Isaac 981*0c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue; 982*0c37af3bSToby Isaac if (numFields > 1) { 983*0c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr); 984*0c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(cSec,p,f,&conOff);CHKERRQ(ierr); 985*0c37af3bSToby Isaac } 986*0c37af3bSToby Isaac else { 987*0c37af3bSToby Isaac ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr); 988*0c37af3bSToby Isaac ierr = PetscSectionGetOffset(cSec,p,&conOff);CHKERRQ(ierr); 989*0c37af3bSToby Isaac } 990*0c37af3bSToby Isaac if (!conDof) continue; 991*0c37af3bSToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 992*0c37af3bSToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 993*0c37af3bSToby Isaac for (k = 0; k < aDof; k++) { 994*0c37af3bSToby Isaac PetscInt a = anchors[aOff + k]; 995*0c37af3bSToby Isaac PetscInt aSecDof, aSecOff; 996*0c37af3bSToby Isaac 997*0c37af3bSToby Isaac if (numFields > 1) { 998*0c37af3bSToby Isaac ierr = PetscSectionGetFieldDof(section,a,f,&aSecDof);CHKERRQ(ierr); 999*0c37af3bSToby Isaac ierr = PetscSectionGetFieldOffset(section,a,f,&aSecOff);CHKERRQ(ierr); 1000*0c37af3bSToby Isaac } 1001*0c37af3bSToby Isaac else { 1002*0c37af3bSToby Isaac ierr = PetscSectionGetDof(section,a,&aSecDof);CHKERRQ(ierr); 1003*0c37af3bSToby Isaac ierr = PetscSectionGetOffset(section,a,&aSecOff);CHKERRQ(ierr); 1004*0c37af3bSToby Isaac } 1005*0c37af3bSToby Isaac if (!aSecDof) continue; 1006*0c37af3bSToby Isaac 1007*0c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) { 1008*0c37af3bSToby Isaac PetscInt q = closureP[2*j]; 1009*0c37af3bSToby Isaac PetscInt oq = closureP[2*j+1]; 1010*0c37af3bSToby Isaac 1011*0c37af3bSToby Isaac if (q == a) { 1012*0c37af3bSToby Isaac PetscInt r, s, t; 1013*0c37af3bSToby Isaac 1014*0c37af3bSToby Isaac for (r = childOffsets[i]; r < childOffsets[i+1]; r++) { 1015*0c37af3bSToby Isaac for (s = parentOffsets[j]; s < parentOffsets[j+1]; s++) { 1016*0c37af3bSToby Isaac PetscScalar val; 1017*0c37af3bSToby Isaac PetscInt insertCol, insertRow; 1018*0c37af3bSToby Isaac 1019*0c37af3bSToby Isaac ierr = MatGetValue(Xmat,r,s,&val);CHKERRQ(ierr); 1020*0c37af3bSToby Isaac if (o >= 0) { 1021*0c37af3bSToby Isaac insertRow = conOff + fComp * (r - childOffsets[i]); 1022*0c37af3bSToby Isaac } 1023*0c37af3bSToby Isaac else { 1024*0c37af3bSToby Isaac insertRow = conOff + fComp * (childOffsets[i + 1] - 1 - r); 1025*0c37af3bSToby Isaac } 1026*0c37af3bSToby Isaac if (oq >= 0) { 1027*0c37af3bSToby Isaac insertCol = aSecOff + fComp * (s - parentOffsets[j]); 1028*0c37af3bSToby Isaac } 1029*0c37af3bSToby Isaac else { 1030*0c37af3bSToby Isaac insertCol = aSecOff + fComp * (parentOffsets[j + 1] - 1 - s); 1031*0c37af3bSToby Isaac } 1032*0c37af3bSToby Isaac for (t = 0; t < fComp; t++) { 1033*0c37af3bSToby Isaac ierr = MatSetValue(cMat,insertRow + t,insertCol + t,val,INSERT_VALUES);CHKERRQ(ierr); 1034*0c37af3bSToby Isaac } 1035*0c37af3bSToby Isaac } 1036*0c37af3bSToby Isaac } 1037*0c37af3bSToby Isaac } 1038*0c37af3bSToby Isaac } 1039*0c37af3bSToby Isaac } 1040*0c37af3bSToby Isaac } 1041*0c37af3bSToby Isaac ierr = PetscFree2(childOffsets,parentOffsets);CHKERRQ(ierr); 1042*0c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1043*0c37af3bSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr); 1044*0c37af3bSToby Isaac } 1045*0c37af3bSToby Isaac ierr = MatDestroy(&Amat);CHKERRQ(ierr); 1046*0c37af3bSToby Isaac ierr = MatDestroy(&Bmat);CHKERRQ(ierr); 1047*0c37af3bSToby Isaac ierr = MatDestroy(&Xmat);CHKERRQ(ierr); 1048*0c37af3bSToby Isaac ierr = PetscFree3(weights,pointsRef,pointsReal);CHKERRQ(ierr); 1049*0c37af3bSToby Isaac } 1050*0c37af3bSToby Isaac ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1051*0c37af3bSToby Isaac ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1052*0c37af3bSToby Isaac ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent);CHKERRQ(ierr); 1053*0c37af3bSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 1054*0c37af3bSToby Isaac 1055*0c37af3bSToby Isaac PetscFunctionReturn(0); 1056*0c37af3bSToby Isaac } 1057