/*@ DMPlexCopyCoordinates - Copy coordinates from one mesh to another with the same vertices Collective on DM Input Parameter: . dmA - The DMPlex object with initial coordinates Output Parameter: . dmB - The DMPlex object with copied coordinates Level: intermediate Note: This is typically used when adding pieces other than vertices to a mesh .keywords: mesh .seealso: DMCopyLabels(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() @*/ PetscErrorCode DMPlexCopyCoordinates(DM dmA, DM dmB) { Vec coordinatesA, coordinatesB; PetscSection coordSectionA, coordSectionB; PetscScalar *coordsA, *coordsB; PetscInt spaceDim, vStartA, vStartB, vEndA, vEndB, coordSizeB, v, d; PetscErrorCode ierr; PetscFunctionBegin; if (dmA == dmB) PetscFunctionReturn(0); ierr = DMPlexGetDepthStratum(dmA, 0, &vStartA, &vEndA);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(dmB, 0, &vStartB, &vEndB);CHKERRQ(ierr); if ((vEndA-vStartA) != (vEndB-vStartB)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of vertices in first DM %d != %d in the second DM", vEndA-vStartA, vEndB-vStartB); ierr = DMGetCoordinateSection(dmA, &coordSectionA);CHKERRQ(ierr); ierr = DMGetCoordinateSection(dmB, &coordSectionB);CHKERRQ(ierr); if (!coordSectionB) { PetscInt dim; ierr = PetscSectionCreate(PetscObjectComm((PetscObject) coordSectionA), &coordSectionB);CHKERRQ(ierr); ierr = DMGetCoordinateDim(dmA, &dim);CHKERRQ(ierr); ierr = DMSetCoordinateSection(dmB, dim, coordSectionB);CHKERRQ(ierr); ierr = PetscObjectDereference((PetscObject) coordSectionB);CHKERRQ(ierr); } ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); ierr = PetscSectionGetFieldComponents(coordSectionA, 0, &spaceDim);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(coordSectionB, 0, spaceDim);CHKERRQ(ierr); ierr = PetscSectionSetChart(coordSectionB, vStartB, vEndB);CHKERRQ(ierr); for (v = vStartB; v < vEndB; ++v) { ierr = PetscSectionSetDof(coordSectionB, v, spaceDim);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, spaceDim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(coordSectionB, &coordSizeB);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dmA, &coordinatesA);CHKERRQ(ierr); ierr = VecCreate(PetscObjectComm((PetscObject) dmB), &coordinatesB);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); ierr = VecSetSizes(coordinatesB, coordSizeB, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetType(coordinatesB,VECSTANDARD);CHKERRQ(ierr); ierr = VecGetArray(coordinatesA, &coordsA);CHKERRQ(ierr); ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); for (v = 0; v < vEndB-vStartB; ++v) { for (d = 0; d < spaceDim; ++d) { coordsB[v*spaceDim+d] = coordsA[v*spaceDim+d]; } } ierr = VecRestoreArray(coordinatesA, &coordsA);CHKERRQ(ierr); ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(dmB, coordinatesB);CHKERRQ(ierr); ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode DMPlexTSSetupGeometry(DM dm, PetscFV fvm, DMTS_Plex *dmplexts) { DM dmFace, dmCell; DMLabel ghostLabel; PetscSection sectionFace, sectionCell; PetscSection coordSection; Vec coordinates; PetscReal minradius; PetscScalar *fgeom, *cgeom; PetscInt dim, cStart, cEnd, cEndInterior, c, fStart, fEnd, f; PetscErrorCode ierr; PetscFunctionBegin; if (dmplexts->setupGeom) PetscFunctionReturn(0); ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); /* Make cell centroids and volumes */ ierr = DMClone(dm, &dmCell);CHKERRQ(ierr); ierr = DMSetCoordinateSection(dmCell, coordSection);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(dmCell, coordinates);CHKERRQ(ierr); ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ionCell);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); ierr = PetscSectionSetChart(sectionCell, cStart, cEnd);CHKERRQ(ierr); for (c = cStart; c < cEnd; ++c) {ierr = PetscSectionSetDof(sectionCell, c, sizeof(CellGeom)/sizeof(PetscScalar));CHKERRQ(ierr);} ierr = PetscSectionSetUp(sectionCell);CHKERRQ(ierr); ierr = DMSetDefaultSection(dmCell, sectionCell);CHKERRQ(ierr); ierr = PetscSectionDestroy(§ionCell);CHKERRQ(ierr); ierr = DMCreateLocalVector(dmCell, &dmplexts->cellgeom);CHKERRQ(ierr); ierr = VecGetArray(dmplexts->cellgeom, &cgeom);CHKERRQ(ierr); for (c = cStart; c < cEndInterior; ++c) { CellGeom *cg; ierr = DMPlexPointLocalRef(dmCell, c, cgeom, &cg);CHKERRQ(ierr); ierr = PetscMemzero(cg, sizeof(*cg));CHKERRQ(ierr); ierr = DMPlexComputeCellGeometryFVM(dmCell, c, &cg->volume, cg->centroid, NULL);CHKERRQ(ierr); } /* Compute face normals and minimum cell radius */ ierr = DMClone(dm, &dmFace);CHKERRQ(ierr); ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ionFace);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); ierr = PetscSectionSetChart(sectionFace, fStart, fEnd);CHKERRQ(ierr); for (f = fStart; f < fEnd; ++f) {ierr = PetscSectionSetDof(sectionFace, f, sizeof(FaceGeom)/sizeof(PetscScalar));CHKERRQ(ierr);} ierr = PetscSectionSetUp(sectionFace);CHKERRQ(ierr); ierr = DMSetDefaultSection(dmFace, sectionFace);CHKERRQ(ierr); ierr = PetscSectionDestroy(§ionFace);CHKERRQ(ierr); ierr = DMCreateLocalVector(dmFace, &dmplexts->facegeom);CHKERRQ(ierr); ierr = VecGetArray(dmplexts->facegeom, &fgeom);CHKERRQ(ierr); ierr = DMPlexGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); minradius = PETSC_MAX_REAL; for (f = fStart; f < fEnd; ++f) { FaceGeom *fg; PetscReal area; PetscInt ghost, d; ierr = DMLabelGetValue(ghostLabel, f, &ghost);CHKERRQ(ierr); if (ghost >= 0) continue; ierr = DMPlexPointLocalRef(dmFace, f, fgeom, &fg);CHKERRQ(ierr); ierr = DMPlexComputeCellGeometryFVM(dm, f, &area, fg->centroid, fg->normal);CHKERRQ(ierr); for (d = 0; d < dim; ++d) fg->normal[d] *= area; /* Flip face orientation if necessary to match ordering in support, and Update minimum radius */ { CellGeom *cL, *cR; const PetscInt *cells; PetscReal *lcentroid, *rcentroid; PetscReal v[3]; ierr = DMPlexGetSupport(dm, f, &cells);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmCell, cells[0], cgeom, &cL);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmCell, cells[1], cgeom, &cR);CHKERRQ(ierr); lcentroid = cells[0] >= cEndInterior ? fg->centroid : cL->centroid; rcentroid = cells[1] >= cEndInterior ? fg->centroid : cR->centroid; WaxpyD(dim, -1, lcentroid, rcentroid, v); if (DotRealD(dim, fg->normal, v) < 0) { for (d = 0; d < dim; ++d) fg->normal[d] = -fg->normal[d]; } if (DotRealD(dim, fg->normal, v) <= 0) { if (dim == 2) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Direction for face %d could not be fixed, normal (%g,%g) v (%g,%g)", f, (double) fg->normal[0], (double) fg->normal[1], (double) v[0], (double) v[1]); if (dim == 3) SETERRQ7(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Direction for face %d could not be fixed, normal (%g,%g,%g) v (%g,%g,%g)", f, (double) fg->normal[0], (double) fg->normal[1], (double) fg->normal[2], (double) v[0], (double) v[1], (double) v[2]); SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Direction for face %d could not be fixed", f); } if (cells[0] < cEndInterior) { WaxpyD(dim, -1, fg->centroid, cL->centroid, v); minradius = PetscMin(minradius, NormD(dim, v)); } if (cells[1] < cEndInterior) { WaxpyD(dim, -1, fg->centroid, cR->centroid, v); minradius = PetscMin(minradius, NormD(dim, v)); } } } ierr = MPI_Allreduce(&minradius, &dmplexts->minradius, 1, MPIU_REAL, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); /* Compute centroids of ghost cells */ for (c = cEndInterior; c < cEnd; ++c) { FaceGeom *fg; const PetscInt *cone, *support; PetscInt coneSize, supportSize, s; ierr = DMPlexGetConeSize(dmCell, c, &coneSize);CHKERRQ(ierr); if (coneSize != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Ghost cell %d has cone size %d != 1", c, coneSize); ierr = DMPlexGetCone(dmCell, c, &cone);CHKERRQ(ierr); ierr = DMPlexGetSupportSize(dmCell, cone[0], &supportSize);CHKERRQ(ierr); if (supportSize != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d has support size %d != 1", cone[0], supportSize); ierr = DMPlexGetSupport(dmCell, cone[0], &support);CHKERRQ(ierr); ierr = DMPlexPointLocalRef(dmFace, cone[0], fgeom, &fg);CHKERRQ(ierr); for (s = 0; s < 2; ++s) { /* Reflect ghost centroid across plane of face */ if (support[s] == c) { const CellGeom *ci; CellGeom *cg; PetscReal c2f[3], a; ierr = DMPlexPointLocalRead(dmCell, support[(s+1)%2], cgeom, &ci);CHKERRQ(ierr); WaxpyD(dim, -1, ci->centroid, fg->centroid, c2f); /* cell to face centroid */ a = DotRealD(dim, c2f, fg->normal)/DotRealD(dim, fg->normal, fg->normal); ierr = DMPlexPointLocalRef(dmCell, support[s], cgeom, &cg);CHKERRQ(ierr); WaxpyD(dim, 2*a, fg->normal, ci->centroid, cg->centroid); cg->volume = ci->volume; } } } ierr = VecRestoreArray(dmplexts->facegeom, &fgeom);CHKERRQ(ierr); ierr = VecRestoreArray(dmplexts->cellgeom, &cgeom);CHKERRQ(ierr); ierr = DMDestroy(&dmCell);CHKERRQ(ierr); ierr = DMDestroy(&dmFace);CHKERRQ(ierr); dmplexts->setupGeom = PETSC_TRUE; PetscFunctionReturn(0); }