/*@C DMPlexAddBoundary - Add a boundary condition to the model Input Parameters: + dm - The mesh object . isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition . name - The BC name . labelname - The label defining constrained points . field - The field to constrain . numcomps - The number of constrained field components . comps - An array of constrained component numbers . bcFunc - A pointwise function giving boundary values . numids - The number of DMLabel ids for constrained points . ids - An array of ids for constrained points - ctx - An optional user context for bcFunc Options Database Keys: + -bc_<boundary name> <num> - Overrides the boundary ids - -bc_<boundary name>_comp <num> - Overrides the boundary components Level: developer .seealso: DMPlexGetBoundary() @*/ PetscErrorCode DMPlexAddBoundary(DM dm, PetscBool isEssential, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(), PetscInt numids, const PetscInt *ids, void *ctx) { DM_Plex *mesh = (DM_Plex *) dm->data; DMBoundary b; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); ierr = PetscNew(&b);CHKERRQ(ierr); ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr); if (numcomps) {ierr = PetscMemcpy(b->comps, comps, numcomps*sizeof(PetscInt));CHKERRQ(ierr);} ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); if (numids) {ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr);} if (b->labelname) { ierr = DMPlexGetLabel(dm, b->labelname, &b->label);CHKERRQ(ierr); if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); } b->essential = isEssential; b->field = field; b->numcomps = numcomps; b->func = bcFunc; b->numids = numids; b->ctx = ctx; b->next = mesh->boundary; mesh->boundary = b; PetscFunctionReturn(0); }
/*@C DMPlexSetLabelValue - Add a point to a Sieve Label with given value Not Collective Input Parameters: + dm - The DMPlex object . name - The label name . point - The mesh point - value - The label value for this point Output Parameter: Level: beginner .keywords: mesh .seealso: DMLabelSetValue(), DMPlexGetStratumIS(), DMPlexClearLabelValue() @*/ PetscErrorCode DMPlexSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) { DMLabel label; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidCharPointer(name, 2); ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); if (!label) { ierr = DMPlexCreateLabel(dm, name);CHKERRQ(ierr); ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); } ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode BuildGradientReconstruction(DM dm, PetscFV fvm, DM dmFace, PetscScalar *fgeom, DM dmCell, PetscScalar *cgeom) { DMLabel ghostLabel; PetscScalar *dx, *grad, **gref; PetscInt dim, cStart, cEnd, c, cEndInterior, maxNumFaces; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexGetMaxSizes(dm, &maxNumFaces, NULL);CHKERRQ(ierr); ierr = PetscFVLeastSquaresSetMaxFaces(fvm, maxNumFaces);CHKERRQ(ierr); ierr = DMPlexGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); ierr = PetscMalloc3(maxNumFaces*dim, &dx, maxNumFaces*dim, &grad, maxNumFaces, &gref);CHKERRQ(ierr); for (c = cStart; c < cEndInterior; c++) { const PetscInt *faces; PetscInt numFaces, usedFaces, f, d; const CellGeom *cg; PetscBool boundary; PetscInt ghost; ierr = DMPlexPointLocalRead(dmCell, c, cgeom, &cg);CHKERRQ(ierr); ierr = DMPlexGetConeSize(dm, c, &numFaces);CHKERRQ(ierr); ierr = DMPlexGetCone(dm, c, &faces);CHKERRQ(ierr); if (numFaces < dim) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cell %D has only %D faces, not enough for gradient reconstruction", c, numFaces); for (f = 0, usedFaces = 0; f < numFaces; ++f) { const CellGeom *cg1; FaceGeom *fg; const PetscInt *fcells; PetscInt ncell, side; ierr = DMLabelGetValue(ghostLabel, faces[f], &ghost);CHKERRQ(ierr); ierr = DMPlexIsBoundaryPoint(dm, faces[f], &boundary);CHKERRQ(ierr); if ((ghost >= 0) || boundary) continue; ierr = DMPlexGetSupport(dm, faces[f], &fcells);CHKERRQ(ierr); side = (c != fcells[0]); /* c is on left=0 or right=1 of face */ ncell = fcells[!side]; /* the neighbor */ ierr = DMPlexPointLocalRef(dmFace, faces[f], fgeom, &fg);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmCell, ncell, cgeom, &cg1);CHKERRQ(ierr); for (d = 0; d < dim; ++d) dx[usedFaces*dim+d] = cg1->centroid[d] - cg->centroid[d]; gref[usedFaces++] = fg->grad[side]; /* Gradient reconstruction term will go here */ } if (!usedFaces) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Mesh contains isolated cell (no neighbors). Is it intentional?"); ierr = PetscFVComputeGradient(fvm, usedFaces, dx, grad);CHKERRQ(ierr); for (f = 0, usedFaces = 0; f < numFaces; ++f) { ierr = DMLabelGetValue(ghostLabel, faces[f], &ghost);CHKERRQ(ierr); ierr = DMPlexIsBoundaryPoint(dm, faces[f], &boundary);CHKERRQ(ierr); if ((ghost >= 0) || boundary) continue; for (d = 0; d < dim; ++d) gref[usedFaces][d] = grad[usedFaces*dim+d]; ++usedFaces; } } ierr = PetscFree3(dx, grad, gref);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMPlexClearLabelStratum - Remove all points from a stratum from a Sieve Label Not Collective Input Parameters: + dm - The DMPlex object . name - The label name - value - The label value for this point Output Parameter: Level: beginner .keywords: mesh .seealso: DMLabelClearStratum(), DMPlexSetLabelValue(), DMPlexGetStratumIS(), DMPlexClearLabelValue() @*/ PetscErrorCode DMPlexClearLabelStratum(DM dm, const char name[], PetscInt value) { DMLabel label; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidCharPointer(name, 2); ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); if (!label) PetscFunctionReturn(0); ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMPlexGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default Not Collective Input Parameters: + dm - The DMPlex object . name - The label name - point - The mesh point Output Parameter: . value - The label value for this point, or -1 if the point is not in the label Level: beginner .keywords: mesh .seealso: DMLabelGetValue(), DMPlexSetLabelValue(), DMPlexGetStratumIS() @*/ PetscErrorCode DMPlexGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) { DMLabel label; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidCharPointer(name, 2); ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr); ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMPlexGetStratumIS - Get the points in a label stratum Not Collective Input Parameters: + dm - The DMPlex object . name - The label name - value - The stratum value Output Parameter: . points - The stratum points, or PETSC_NULL if the label does not exist or does not have that value Level: beginner .keywords: mesh .seealso: DMLabelGetStratumIS(), DMPlexGetStratumSize() @*/ PetscErrorCode DMPlexGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) { DMLabel label; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidCharPointer(name, 2); PetscValidPointer(points, 4); ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); *points = PETSC_NULL; if (!label) PetscFunctionReturn(0); ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMPlexGetStratumSize - Get the number of points in a label stratum Not Collective Input Parameters: + dm - The DMPlex object . name - The label name - value - The stratum value Output Parameter: . size - The stratum size Level: beginner .keywords: mesh .seealso: DMLabelGetStratumSize(), DMPlexGetLabelSize(), DMPlexGetLabelIds() @*/ PetscErrorCode DMPlexGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) { DMLabel label; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidCharPointer(name, 2); PetscValidPointer(size, 4); ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); *size = 0; if (!label) PetscFunctionReturn(0); ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMPlexGetLabelIdIS - Get the integer ids in a label Not Collective Input Parameters: + mesh - The DMPlex object - name - The label name Output Parameter: . ids - The integer ids, or NULL if the label does not exist Level: beginner .keywords: mesh .seealso: DMLabelGetValueIS(), DMPlexGetLabelSize() @*/ PetscErrorCode DMPlexGetLabelIdIS(DM dm, const char name[], IS *ids) { DMLabel label; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidCharPointer(name, 2); PetscValidPointer(ids, 3); ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); *ids = NULL; if (!label) PetscFunctionReturn(0); ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMPlexCopyBoundary(DM dm, DM dmNew) { DM_Plex *mesh = (DM_Plex *) dm->data; DM_Plex *meshNew = (DM_Plex *) dmNew->data; DMBoundary b; PetscErrorCode ierr; PetscFunctionBegin; ierr = BoundaryDuplicate(mesh->boundary, &meshNew->boundary);CHKERRQ(ierr); for (b = meshNew->boundary; b; b = b->next) { if (b->labelname) { ierr = DMPlexGetLabel(dmNew, b->labelname, &b->label);CHKERRQ(ierr); if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); } } PetscFunctionReturn(0); }
/*@ DMPlexCopyLabels - Copy labels from one mesh to another with a superset of the points Collective on DM Input Parameter: . dmA - The DMPlex object with initial labels Output Parameter: . dmB - The DMPlex object with copied labels Level: intermediate Note: This is typically used when interpolating or otherwise adding to a mesh .keywords: mesh .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() @*/ PetscErrorCode DMPlexCopyLabels(DM dmA, DM dmB) { PetscInt numLabels, l; PetscErrorCode ierr; PetscFunctionBegin; if (dmA == dmB) PetscFunctionReturn(0); ierr = DMPlexGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); for (l = 0; l < numLabels; ++l) { DMLabel label, labelNew; const char *name; PetscBool flg; ierr = DMPlexGetLabelName(dmA, l, &name);CHKERRQ(ierr); ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); if (flg) continue; ierr = DMPlexGetLabel(dmA, name, &label);CHKERRQ(ierr); ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); ierr = DMPlexAddLabel(dmB, labelNew);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) { DMLabel label; PetscInt dim = user->dim; PetscBool interpolate = user->interpolate; PetscReal refinementLimit = user->refinementLimit; const char *partitioner = user->partitioner; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = PetscLogEventBegin(user->createMeshEvent,0,0,0,0);CHKERRQ(ierr); ierr = DMPlexCreateBoxMesh(comm, dim, interpolate, dm);CHKERRQ(ierr); ierr = DMPlexGetLabel(*dm, "marker", &label);CHKERRQ(ierr); if (label) {ierr = DMPlexLabelComplete(*dm, label);CHKERRQ(ierr);} { DM refinedMesh = NULL; DM distributedMesh = NULL; /* Refine mesh using a volume constraint */ ierr = DMPlexSetRefinementLimit(*dm, refinementLimit);CHKERRQ(ierr); ierr = DMRefine(*dm, comm, &refinedMesh);CHKERRQ(ierr); if (refinedMesh) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = refinedMesh; } /* Distribute mesh over processes */ ierr = DMPlexDistribute(*dm, partitioner, 0, NULL, &distributedMesh);CHKERRQ(ierr); if (distributedMesh) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = distributedMesh; } } ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); ierr = PetscLogEventEnd(user->createMeshEvent,0,0,0,0);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); }
static PetscErrorCode TSComputeRHSFunction_DMPlex(TS ts, PetscReal time, Vec X, Vec F, void *ctx) { DM dm; DMTS_Plex *dmplexts = (DMTS_Plex *) ctx; void (*riemann)(const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscScalar[], void *) = dmplexts->riemann; PetscFV fvm; PetscLimiter lim; Vec faceGeometry = dmplexts->facegeom; Vec cellGeometry = dmplexts->cellgeom; Vec Grad = NULL, locGrad, locX; DM dmFace, dmCell; DMLabel ghostLabel; PetscCellGeometry fgeom, cgeom; const PetscScalar *facegeom, *cellgeom, *x, *lgrad; PetscScalar *grad, *f, *uL, *uR, *fluxL, *fluxR; PetscReal *centroid, *normal, *vol, *cellPhi; PetscBool computeGradients; PetscInt Nf, dim, pdim, fStart, fEnd, numFaces = 0, face, iface, cell, cStart, cEnd, cEndInterior; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(ts,TS_CLASSID,1); PetscValidHeaderSpecific(X,VEC_CLASSID,3); PetscValidHeaderSpecific(F,VEC_CLASSID,5); ierr = TSGetDM(ts, &dm);CHKERRQ(ierr); ierr = DMGetLocalVector(dm, &locX);CHKERRQ(ierr); ierr = VecZeroEntries(locX);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, locX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, locX);CHKERRQ(ierr); ierr = VecZeroEntries(F);CHKERRQ(ierr); ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); ierr = DMGetField(dm, 0, (PetscObject *) &fvm);CHKERRQ(ierr); ierr = PetscFVGetLimiter(fvm, &lim);CHKERRQ(ierr); ierr = PetscFVGetNumComponents(fvm, &pdim);CHKERRQ(ierr); ierr = PetscFVGetComputeGradients(fvm, &computeGradients);CHKERRQ(ierr); if (computeGradients) { ierr = DMGetGlobalVector(dmplexts->dmGrad, &Grad);CHKERRQ(ierr); ierr = VecZeroEntries(Grad);CHKERRQ(ierr); ierr = VecGetArray(Grad, &grad);CHKERRQ(ierr); } ierr = DMPlexGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); ierr = VecGetArrayRead(locX, &x);CHKERRQ(ierr); /* Count faces and reconstruct gradients */ for (face = fStart; face < fEnd; ++face) { const PetscInt *cells; const FaceGeom *fg; const PetscScalar *cx[2]; PetscScalar *cgrad[2]; PetscBool boundary; PetscInt ghost, c, pd, d; ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr); if (ghost >= 0) continue; ++numFaces; if (!computeGradients) continue; ierr = DMPlexIsBoundaryPoint(dm, face, &boundary);CHKERRQ(ierr); if (boundary) continue; ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); for (c = 0; c < 2; ++c) { ierr = DMPlexPointLocalRead(dm, cells[c], x, &cx[c]);CHKERRQ(ierr); ierr = DMPlexPointGlobalRef(dmplexts->dmGrad, cells[c], grad, &cgrad[c]);CHKERRQ(ierr); } for (pd = 0; pd < pdim; ++pd) { PetscScalar delta = cx[1][pd] - cx[0][pd]; for (d = 0; d < dim; ++d) { if (cgrad[0]) cgrad[0][pd*dim+d] += fg->grad[0][d] * delta; if (cgrad[1]) cgrad[1][pd*dim+d] -= fg->grad[1][d] * delta; } } } /* Limit interior gradients (using cell-based loop because it generalizes better to vector limiters) */ ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMGetWorkArray(dm, pdim, PETSC_REAL, &cellPhi);CHKERRQ(ierr); for (cell = computeGradients && lim ? cStart : cEnd; cell < cEndInterior; ++cell) { const PetscInt *faces; const PetscScalar *cx; const CellGeom *cg; PetscScalar *cgrad; PetscInt coneSize, f, pd, d; ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); ierr = DMPlexGetCone(dm, cell, &faces);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dm, cell, x, &cx);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmCell, cell, cellgeom, &cg);CHKERRQ(ierr); ierr = DMPlexPointGlobalRef(dmplexts->dmGrad, cell, grad, &cgrad);CHKERRQ(ierr); if (!cgrad) continue; /* Unowned overlap cell, we do not compute */ /* Limiter will be minimum value over all neighbors */ for (d = 0; d < pdim; ++d) cellPhi[d] = PETSC_MAX_REAL; for (f = 0; f < coneSize; ++f) { const PetscScalar *ncx; const CellGeom *ncg; const PetscInt *fcells; PetscInt face = faces[f], ncell, ghost; PetscReal v[3]; PetscBool boundary; ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr); ierr = DMPlexIsBoundaryPoint(dm, face, &boundary);CHKERRQ(ierr); if ((ghost >= 0) || boundary) continue; ierr = DMPlexGetSupport(dm, face, &fcells);CHKERRQ(ierr); ncell = cell == fcells[0] ? fcells[1] : fcells[0]; ierr = DMPlexPointLocalRead(dm, ncell, x, &ncx);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmCell, ncell, cellgeom, &ncg);CHKERRQ(ierr); WaxpyD(dim, -1, cg->centroid, ncg->centroid, v); for (d = 0; d < pdim; ++d) { /* We use the symmetric slope limited form of Berger, Aftosmis, and Murman 2005 */ PetscReal phi, flim = 0.5 * PetscRealPart(ncx[d] - cx[d]) / DotD(dim, &cgrad[d*dim], v); ierr = PetscLimiterLimit(lim, flim, &phi);CHKERRQ(ierr); cellPhi[d] = PetscMin(cellPhi[d], phi); } } /* Apply limiter to gradient */ for (pd = 0; pd < pdim; ++pd) /* Scalar limiter applied to each component separately */ for (d = 0; d < dim; ++d) cgrad[pd*dim+d] *= cellPhi[pd]; } ierr = DMRestoreWorkArray(dm, pdim, PETSC_REAL, &cellPhi);CHKERRQ(ierr); ierr = DMPlexInsertBoundaryValuesFVM_Static(dm, fvm, time, locX, Grad, dmplexts);CHKERRQ(ierr); if (computeGradients) { ierr = VecRestoreArray(Grad, &grad);CHKERRQ(ierr); ierr = DMGetLocalVector(dmplexts->dmGrad, &locGrad);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(dmplexts->dmGrad, Grad, INSERT_VALUES, locGrad);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(dmplexts->dmGrad, Grad, INSERT_VALUES, locGrad);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dmplexts->dmGrad, &Grad);CHKERRQ(ierr); ierr = VecGetArrayRead(locGrad, &lgrad);CHKERRQ(ierr); } ierr = PetscMalloc7(numFaces*dim,¢roid,numFaces*dim,&normal,numFaces*2,&vol,numFaces*pdim,&uL,numFaces*pdim,&uR,numFaces*pdim,&fluxL,numFaces*pdim,&fluxR);CHKERRQ(ierr); /* Read out values */ for (face = fStart, iface = 0; face < fEnd; ++face) { const PetscInt *cells; const FaceGeom *fg; const CellGeom *cgL, *cgR; const PetscScalar *xL, *xR, *gL, *gR; PetscInt ghost, d; ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr); if (ghost >= 0) continue; ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cgL);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmCell, cells[1], cellgeom, &cgR);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dm, cells[0], x, &xL);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dm, cells[1], x, &xR);CHKERRQ(ierr); if (computeGradients) { PetscReal dxL[3], dxR[3]; ierr = DMPlexPointLocalRead(dmplexts->dmGrad, cells[0], lgrad, &gL);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmplexts->dmGrad, cells[1], lgrad, &gR);CHKERRQ(ierr); WaxpyD(dim, -1, cgL->centroid, fg->centroid, dxL); WaxpyD(dim, -1, cgR->centroid, fg->centroid, dxR); for (d = 0; d < pdim; ++d) { uL[iface*pdim+d] = xL[d] + DotD(dim, &gL[d*dim], dxL); uR[iface*pdim+d] = xR[d] + DotD(dim, &gR[d*dim], dxR); } } else { for (d = 0; d < pdim; ++d) { uL[iface*pdim+d] = xL[d]; uR[iface*pdim+d] = xR[d]; } } for (d = 0; d < dim; ++d) { centroid[iface*dim+d] = fg->centroid[d]; normal[iface*dim+d] = fg->normal[d]; } vol[iface*2+0] = cgL->volume; vol[iface*2+1] = cgR->volume; ++iface; } if (computeGradients) { ierr = VecRestoreArrayRead(locGrad,&lgrad);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dmplexts->dmGrad, &locGrad);CHKERRQ(ierr); } ierr = VecRestoreArrayRead(locX, &x);CHKERRQ(ierr); ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); fgeom.v0 = centroid; fgeom.n = normal; cgeom.vol = vol; /* Riemann solve */ ierr = PetscFVIntegrateRHSFunction(fvm, numFaces, Nf, &fvm, 0, fgeom, cgeom, uL, uR, riemann, fluxL, fluxR, dmplexts->rhsfunctionlocalctx);CHKERRQ(ierr); /* Insert fluxes */ ierr = VecGetArray(F, &f);CHKERRQ(ierr); for (face = fStart, iface = 0; face < fEnd; ++face) { const PetscInt *cells; PetscScalar *fL, *fR; PetscInt ghost, d; ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr); if (ghost >= 0) continue; ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); ierr = DMPlexPointGlobalRef(dm, cells[0], f, &fL);CHKERRQ(ierr); ierr = DMPlexPointGlobalRef(dm, cells[1], f, &fR);CHKERRQ(ierr); for (d = 0; d < pdim; ++d) { if (fL) fL[d] -= fluxL[iface*pdim+d]; if (fR) fR[d] += fluxR[iface*pdim+d]; } ++iface; } ierr = VecRestoreArray(F, &f);CHKERRQ(ierr); ierr = PetscFree7(centroid,normal,vol,uL,uR,fluxL,fluxR);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dm, &locX);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode DMPlexInsertBoundaryValuesFVM_Static(DM dm, PetscFV fvm, PetscReal time, Vec locX, Vec Grad, DMTS_Plex *dmplexts) { Vec faceGeometry = dmplexts->facegeom; Vec cellGeometry = dmplexts->cellgeom; DM dmFace, dmCell; const PetscScalar *facegeom, *cellgeom, *grad; PetscScalar *x, *fx; PetscInt numBd, b, dim, pdim, fStart, fEnd; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); ierr = PetscFVGetNumComponents(fvm, &pdim);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); if (Grad) { ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); ierr = DMGetWorkArray(dm, pdim, PETSC_SCALAR, &fx);CHKERRQ(ierr); ierr = VecGetArrayRead(Grad, &grad);CHKERRQ(ierr); } ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); ierr = VecGetArray(locX, &x);CHKERRQ(ierr); for (b = 0; b < numBd; ++b) { PetscErrorCode (*func)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*); DMLabel label; const char *labelname; const PetscInt *ids; PetscInt numids, i; void *ctx; ierr = DMPlexGetBoundary(dm, b, NULL, NULL, &labelname, NULL, (void (**)()) &func, &numids, &ids, &ctx);CHKERRQ(ierr); ierr = DMPlexGetLabel(dm, labelname, &label);CHKERRQ(ierr); for (i = 0; i < numids; ++i) { IS faceIS; const PetscInt *faces; PetscInt numFaces, f; ierr = DMLabelGetStratumIS(label, ids[i], &faceIS);CHKERRQ(ierr); if (!faceIS) continue; /* No points with that id on this process */ ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); for (f = 0; f < numFaces; ++f) { const PetscInt face = faces[f], *cells; const FaceGeom *fg; if ((face < fStart) || (face >= fEnd)) continue; /* Refinement adds non-faces to labels */ ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); if (Grad) { const CellGeom *cg; const PetscScalar *cx, *cgrad; PetscScalar *xG; PetscReal dx[3]; PetscInt d; ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cg);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dm, cells[0], x, &cx);CHKERRQ(ierr); ierr = DMPlexPointLocalRead(dmplexts->dmGrad, cells[0], grad, &cgrad);CHKERRQ(ierr); ierr = DMPlexPointLocalRef(dm, cells[1], x, &xG);CHKERRQ(ierr); WaxpyD(dim, -1, cg->centroid, fg->centroid, dx); for (d = 0; d < pdim; ++d) fx[d] = cx[d] + DotD(dim, &cgrad[d*dim], dx); ierr = (*func)(time, fg->centroid, fg->normal, fx, xG, ctx);CHKERRQ(ierr); } else { const PetscScalar *xI; PetscScalar *xG; ierr = DMPlexPointLocalRead(dm, cells[0], x, &xI);CHKERRQ(ierr); ierr = DMPlexPointLocalRef(dm, cells[1], x, &xG);CHKERRQ(ierr); ierr = (*func)(time, fg->centroid, fg->normal, xI, xG, ctx);CHKERRQ(ierr); } } ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); ierr = ISDestroy(&faceIS);CHKERRQ(ierr); } } ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); ierr = VecRestoreArray(locX, &x);CHKERRQ(ierr); if (Grad) { ierr = DMRestoreWorkArray(dm, pdim, PETSC_SCALAR, &fx);CHKERRQ(ierr); ierr = VecRestoreArrayRead(Grad, &grad);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ DMPlexCreateCGNS - Create a DMPlex mesh from a CGNS file ID. Collective on comm Input Parameters: + comm - The MPI communicator . cgid - The CG id associated with a file and obtained using cg_open - interpolate - Create faces and edges in the mesh Output Parameter: . dm - The DM object representing the mesh Note: http://www.grc.nasa.gov/WWW/cgns/CGNS_docs_current/index.html Level: beginner .keywords: mesh,CGNS .seealso: DMPlexCreate(), DMPlexCreateExodus() @*/ PetscErrorCode DMPlexCreateCGNS(MPI_Comm comm, PetscInt cgid, PetscBool interpolate, DM *dm) { #if defined(PETSC_HAVE_CGNS) PetscMPIInt num_proc, rank; PetscSection coordSection; Vec coordinates; PetscScalar *coords; PetscInt *cellStart, *vertStart; PetscInt coordSize, v; PetscErrorCode ierr; /* Read from file */ char basename[CGIO_MAX_NAME_LENGTH+1]; char buffer[CGIO_MAX_NAME_LENGTH+1]; int dim = 0, physDim = 0, numVertices = 0, numCells = 0; int nzones = 0; #endif PetscFunctionBegin; #if defined(PETSC_HAVE_CGNS) ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); /* Open CGNS II file and read basic informations on rank 0, then broadcast to all processors */ if (!rank) { int nbases, z; ierr = cg_nbases(cgid, &nbases);CHKERRQ(ierr); if (nbases > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CGNS file must have a single base, not %d\n",nbases); ierr = cg_base_read(cgid, 1, basename, &dim, &physDim);CHKERRQ(ierr); ierr = cg_nzones(cgid, 1, &nzones);CHKERRQ(ierr); ierr = PetscCalloc2(nzones+1, &cellStart, nzones+1, &vertStart);CHKERRQ(ierr); for (z = 1; z <= nzones; ++z) { cgsize_t sizes[3]; /* Number of vertices, number of cells, number of boundary vertices */ ierr = cg_zone_read(cgid, 1, z, buffer, sizes);CHKERRQ(ierr); numVertices += sizes[0]; numCells += sizes[1]; cellStart[z] += sizes[1] + cellStart[z-1]; vertStart[z] += sizes[0] + vertStart[z-1]; } for (z = 1; z <= nzones; ++z) { vertStart[z] += numCells; } } ierr = MPI_Bcast(basename, CGIO_MAX_NAME_LENGTH+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); ierr = MPI_Bcast(&dim, 1, MPI_INT, 0, comm);CHKERRQ(ierr); ierr = MPI_Bcast(&nzones, 1, MPI_INT, 0, comm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) *dm, basename);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); /* Read zone information */ if (!rank) { int z, c, c_loc, v, v_loc; /* Read the cell set connectivity table and build mesh topology CGNS standard requires that cells in a zone be numbered sequentially and be pairwise disjoint. */ /* First set sizes */ for (z = 1, c = 0; z <= nzones; ++z) { ZoneType_t zonetype; int nsections; ElementType_t cellType; cgsize_t start, end; int nbndry, parentFlag; PetscInt numCorners; ierr = cg_zone_type(cgid, 1, z, &zonetype);CHKERRQ(ierr); if (zonetype == Structured) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Can only handle Unstructured zones for CGNS"); ierr = cg_nsections(cgid, 1, z, &nsections);CHKERRQ(ierr); if (nsections > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CGNS file must have a single section, not %d\n",nsections); ierr = cg_section_read(cgid, 1, z, 1, buffer, &cellType, &start, &end, &nbndry, &parentFlag);CHKERRQ(ierr); /* This alone is reason enough to bludgeon every single CGNDS developer, this must be what they describe as the "idiocy of crowds" */ if (cellType == MIXED) { cgsize_t elementDataSize, *elements; PetscInt off; ierr = cg_ElementDataSize(cgid, 1, z, 1, &elementDataSize);CHKERRQ(ierr); ierr = PetscMalloc1(elementDataSize, &elements);CHKERRQ(ierr); ierr = cg_elements_read(cgid, 1, z, 1, elements, NULL);CHKERRQ(ierr); for (c_loc = start, off = 0; c_loc <= end; ++c_loc, ++c) { switch (elements[off]) { case TRI_3: numCorners = 3;break; case QUAD_4: numCorners = 4;break; case TETRA_4: numCorners = 4;break; case HEXA_8: numCorners = 8;break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell type %d", (int) elements[off]); } ierr = DMPlexSetConeSize(*dm, c, numCorners);CHKERRQ(ierr); off += numCorners+1; } ierr = PetscFree(elements);CHKERRQ(ierr); } else { switch (cellType) { case TRI_3: numCorners = 3;break; case QUAD_4: numCorners = 4;break; case TETRA_4: numCorners = 4;break; case HEXA_8: numCorners = 8;break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell type %d", (int) cellType); } for (c_loc = start; c_loc <= end; ++c_loc, ++c) { ierr = DMPlexSetConeSize(*dm, c, numCorners);CHKERRQ(ierr); } } } ierr = DMSetUp(*dm);CHKERRQ(ierr); for (z = 1, c = 0; z <= nzones; ++z) { ElementType_t cellType; cgsize_t *elements, elementDataSize, start, end; int nbndry, parentFlag; PetscInt *cone, numc, numCorners, maxCorners = 27; ierr = cg_section_read(cgid, 1, z, 1, buffer, &cellType, &start, &end, &nbndry, &parentFlag);CHKERRQ(ierr); numc = end - start; /* This alone is reason enough to bludgeon every single CGNDS developer, this must be what they describe as the "idiocy of crowds" */ ierr = cg_ElementDataSize(cgid, 1, z, 1, &elementDataSize);CHKERRQ(ierr); ierr = PetscMalloc2(elementDataSize,&elements,maxCorners,&cone);CHKERRQ(ierr); ierr = cg_elements_read(cgid, 1, z, 1, elements, NULL);CHKERRQ(ierr); if (cellType == MIXED) { /* CGNS uses Fortran-based indexing, sieve uses C-style and numbers cell first then vertices. */ for (c_loc = 0, v = 0; c_loc <= numc; ++c_loc, ++c) { switch (elements[v]) { case TRI_3: numCorners = 3;break; case QUAD_4: numCorners = 4;break; case TETRA_4: numCorners = 4;break; case HEXA_8: numCorners = 8;break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell type %d", (int) elements[v]); } ++v; for (v_loc = 0; v_loc < numCorners; ++v_loc, ++v) { cone[v_loc] = elements[v]+numCells-1; } /* Tetrahedra are inverted */ if (elements[v] == TETRA_4) { PetscInt tmp = cone[0]; cone[0] = cone[1]; cone[1] = tmp; } /* Hexahedra are inverted */ if (elements[v] == HEXA_8) { PetscInt tmp = cone[5]; cone[5] = cone[7]; cone[7] = tmp; } ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); ierr = DMPlexSetLabelValue(*dm, "zone", c, z);CHKERRQ(ierr); } } else { switch (cellType) { case TRI_3: numCorners = 3;break; case QUAD_4: numCorners = 4;break; case TETRA_4: numCorners = 4;break; case HEXA_8: numCorners = 8;break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell type %d", (int) cellType); } /* CGNS uses Fortran-based indexing, sieve uses C-style and numbers cell first then vertices. */ for (c_loc = 0, v = 0; c_loc <= numc; ++c_loc, ++c) { for (v_loc = 0; v_loc < numCorners; ++v_loc, ++v) { cone[v_loc] = elements[v]+numCells-1; } /* Tetrahedra are inverted */ if (cellType == TETRA_4) { PetscInt tmp = cone[0]; cone[0] = cone[1]; cone[1] = tmp; } /* Hexahedra are inverted, and they give the top first */ if (cellType == HEXA_8) { PetscInt tmp = cone[5]; cone[5] = cone[7]; cone[7] = tmp; } ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); ierr = DMPlexSetLabelValue(*dm, "zone", c, z);CHKERRQ(ierr); } } ierr = PetscFree2(elements,cone);CHKERRQ(ierr); } } ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); ierr = DMPlexStratify(*dm);CHKERRQ(ierr); if (interpolate) { DM idm = NULL; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); /* Maintain zone label */ { DMLabel label; ierr = DMPlexRemoveLabel(*dm, "zone", &label);CHKERRQ(ierr); if (label) {ierr = DMPlexAddLabel(idm, label);CHKERRQ(ierr);} } ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } /* Read coordinates */ ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); for (v = numCells; v < numCells+numVertices; ++v) { ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); ierr = VecCreate(comm, &coordinates);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); if (!rank) { PetscInt off = 0; float *x[3]; int z, d; ierr = PetscMalloc3(numVertices,&x[0],numVertices,&x[1],numVertices,&x[2]);CHKERRQ(ierr); for (z = 1; z <= nzones; ++z) { DataType_t datatype; cgsize_t sizes[3]; /* Number of vertices, number of cells, number of boundary vertices */ cgsize_t range_min[3] = {1, 1, 1}; cgsize_t range_max[3] = {1, 1, 1}; int ngrids, ncoords; ierr = cg_zone_read(cgid, 1, z, buffer, sizes);CHKERRQ(ierr); range_max[0] = sizes[0]; ierr = cg_ngrids(cgid, 1, z, &ngrids);CHKERRQ(ierr); if (ngrids > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CGNS file must have a single grid, not %d\n",ngrids); ierr = cg_ncoords(cgid, 1, z, &ncoords);CHKERRQ(ierr); if (ncoords != dim) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CGNS file must have a coordinate array for each dimension, not %d\n",ncoords); for (d = 0; d < dim; ++d) { ierr = cg_coord_info(cgid, 1, z, 1+d, &datatype, buffer);CHKERRQ(ierr); ierr = cg_coord_read(cgid, 1, z, buffer, RealSingle, range_min, range_max, x[d]);CHKERRQ(ierr); } if (dim > 0) { for (v = 0; v < sizes[0]; ++v) coords[(v+off)*dim+0] = x[0][v]; } if (dim > 1) { for (v = 0; v < sizes[0]; ++v) coords[(v+off)*dim+1] = x[1][v]; } if (dim > 2) { for (v = 0; v < sizes[0]; ++v) coords[(v+off)*dim+2] = x[2][v]; } off += sizes[0]; } ierr = PetscFree3(x[0],x[1],x[2]);CHKERRQ(ierr); } ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); ierr = VecDestroy(&coordinates);CHKERRQ(ierr); /* Read boundary conditions */ if (!rank) { DMLabel label; BCType_t bctype; DataType_t datatype; PointSetType_t pointtype; cgsize_t *points; PetscReal *normals; int normal[3]; char *bcname = buffer; cgsize_t npoints, nnormals; int z, nbc, bc, c, ndatasets; for (z = 1; z <= nzones; ++z) { ierr = cg_nbocos(cgid, 1, z, &nbc);CHKERRQ(ierr); for (bc = 1; bc <= nbc; ++bc) { ierr = cg_boco_info(cgid, 1, z, bc, bcname, &bctype, &pointtype, &npoints, normal, &nnormals, &datatype, &ndatasets);CHKERRQ(ierr); ierr = DMPlexCreateLabel(*dm, bcname);CHKERRQ(ierr); ierr = DMPlexGetLabel(*dm, bcname, &label);CHKERRQ(ierr); ierr = PetscMalloc2(npoints, &points, nnormals, &normals);CHKERRQ(ierr); ierr = cg_boco_read(cgid, 1, z, bc, points, (void *) normals);CHKERRQ(ierr); if (pointtype == ElementRange) { /* Range of cells: assuming half-open interval since the documentation sucks */ for (c = points[0]; c < points[1]; ++c) { ierr = DMLabelSetValue(label, c - cellStart[z-1], 1);CHKERRQ(ierr); } } else if (pointtype == ElementList) { /* List of cells */ for (c = 0; c < npoints; ++c) { ierr = DMLabelSetValue(label, points[c] - cellStart[z-1], 1);CHKERRQ(ierr); } } else if (pointtype == PointRange) { GridLocation_t gridloc; /* List of points: Oh please, someone get the CGNS developers away from a computer. This is unconscionable. */ ierr = cg_goto(cgid, 1, "Zone_t", z, "BC_t", bc, "end");CHKERRQ(ierr); ierr = cg_gridlocation_read(&gridloc);CHKERRQ(ierr); /* Range of points: assuming half-open interval since the documentation sucks */ for (c = points[0]; c < points[1]; ++c) { if (gridloc == Vertex) {ierr = DMLabelSetValue(label, c - vertStart[z-1], 1);CHKERRQ(ierr);} else {ierr = DMLabelSetValue(label, c - cellStart[z-1], 1);CHKERRQ(ierr);} } } else if (pointtype == PointList) { GridLocation_t gridloc; /* List of points: Oh please, someone get the CGNS developers away from a computer. This is unconscionable. */ ierr = cg_goto(cgid, 1, "Zone_t", z, "BC_t", bc, "end"); ierr = cg_gridlocation_read(&gridloc); for (c = 0; c < npoints; ++c) { if (gridloc == Vertex) {ierr = DMLabelSetValue(label, points[c] - vertStart[z-1], 1);CHKERRQ(ierr);} else {ierr = DMLabelSetValue(label, points[c] - cellStart[z-1], 1);CHKERRQ(ierr);} } } else SETERRQ1(comm, PETSC_ERR_SUP, "Unsupported point set type %d", (int) pointtype); ierr = PetscFree2(points, normals);CHKERRQ(ierr); } } ierr = PetscFree2(cellStart, vertStart);CHKERRQ(ierr); } #else SETERRQ(comm, PETSC_ERR_SUP, "This method requires CGNS support. Reconfigure using --with-cgns-dir"); #endif PetscFunctionReturn(0); }
PetscErrorCode DMPlexVTKWriteCells_ASCII(DM dm, FILE *fp, PetscInt *totalCells) { MPI_Comm comm; DMLabel label; IS globalVertexNumbers = NULL; const PetscInt *gvertex; PetscInt dim; PetscInt numCorners = 0, totCorners = 0, maxCorners, *corners; PetscInt numCells = 0, totCells = 0, maxCells, cellHeight; PetscInt numLabelCells, maxLabelCells, cMax, cStart, cEnd, c, vStart, vEnd, v; PetscMPIInt numProcs, rank, proc, tag; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); ierr = PetscCommGetNewTag(comm, &tag);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); ierr = DMPlexGetLabel(dm, "vtk", &label);CHKERRQ(ierr); ierr = DMPlexGetStratumSize(dm, "vtk", 1, &numLabelCells);CHKERRQ(ierr); ierr = MPI_Allreduce(&numLabelCells, &maxLabelCells, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); if (!maxLabelCells) label = NULL; for (c = cStart; c < cEnd; ++c) { PetscInt *closure = NULL; PetscInt closureSize, value; if (label) { ierr = DMLabelGetValue(label, c, &value);CHKERRQ(ierr); if (value != 1) continue; } ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); for (v = 0; v < closureSize*2; v += 2) { if ((closure[v] >= vStart) && (closure[v] < vEnd)) ++numCorners; } ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); ++numCells; } maxCells = numCells; ierr = MPI_Reduce(&numCells, &totCells, 1, MPIU_INT, MPI_SUM, 0, comm);CHKERRQ(ierr); ierr = MPI_Reduce(&numCells, &maxCells, 1, MPIU_INT, MPI_MAX, 0, comm);CHKERRQ(ierr); ierr = MPI_Reduce(&numCorners, &totCorners, 1, MPIU_INT, MPI_SUM, 0, comm);CHKERRQ(ierr); ierr = MPI_Reduce(&numCorners, &maxCorners, 1, MPIU_INT, MPI_MAX, 0, comm);CHKERRQ(ierr); ierr = DMPlexGetVertexNumbering(dm, &globalVertexNumbers);CHKERRQ(ierr); ierr = ISGetIndices(globalVertexNumbers, &gvertex);CHKERRQ(ierr); ierr = PetscMalloc1(maxCells, &corners);CHKERRQ(ierr); ierr = PetscFPrintf(comm, fp, "CELLS %d %d\n", totCells, totCorners+totCells);CHKERRQ(ierr); if (!rank) { PetscInt *remoteVertices; int *vertices; ierr = PetscMalloc1(maxCorners, &vertices);CHKERRQ(ierr); for (c = cStart, numCells = 0; c < cEnd; ++c) { PetscInt *closure = NULL; PetscInt closureSize, value, nC = 0; if (label) { ierr = DMLabelGetValue(label, c, &value);CHKERRQ(ierr); if (value != 1) continue; } ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); for (v = 0; v < closureSize*2; v += 2) { if ((closure[v] >= vStart) && (closure[v] < vEnd)) { const PetscInt gv = gvertex[closure[v] - vStart]; vertices[nC++] = gv < 0 ? -(gv+1) : gv; } } ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); corners[numCells++] = nC; ierr = PetscFPrintf(comm, fp, "%d ", nC);CHKERRQ(ierr); ierr = DMPlexInvertCell(dim, nC, vertices);CHKERRQ(ierr); for (v = 0; v < nC; ++v) { ierr = PetscFPrintf(comm, fp, " %d", vertices[v]);CHKERRQ(ierr); } ierr = PetscFPrintf(comm, fp, "\n");CHKERRQ(ierr); } if (numProcs > 1) {ierr = PetscMalloc1(maxCorners+maxCells, &remoteVertices);CHKERRQ(ierr);} for (proc = 1; proc < numProcs; ++proc) { MPI_Status status; ierr = MPI_Recv(&numCorners, 1, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); ierr = MPI_Recv(remoteVertices, numCorners, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); for (c = 0; c < numCorners;) { PetscInt nC = remoteVertices[c++]; for (v = 0; v < nC; ++v, ++c) { vertices[v] = remoteVertices[c]; } ierr = DMPlexInvertCell(dim, nC, vertices);CHKERRQ(ierr); ierr = PetscFPrintf(comm, fp, "%d ", nC);CHKERRQ(ierr); for (v = 0; v < nC; ++v) { ierr = PetscFPrintf(comm, fp, " %d", vertices[v]);CHKERRQ(ierr); } ierr = PetscFPrintf(comm, fp, "\n");CHKERRQ(ierr); } } if (numProcs > 1) {ierr = PetscFree(remoteVertices);CHKERRQ(ierr);} ierr = PetscFree(vertices);CHKERRQ(ierr); } else { PetscInt *localVertices, numSend = numCells+numCorners, k = 0; ierr = PetscMalloc1(numSend, &localVertices);CHKERRQ(ierr); for (c = cStart, numCells = 0; c < cEnd; ++c) { PetscInt *closure = NULL; PetscInt closureSize, value, nC = 0; if (label) { ierr = DMLabelGetValue(label, c, &value);CHKERRQ(ierr); if (value != 1) continue; } ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); for (v = 0; v < closureSize*2; v += 2) { if ((closure[v] >= vStart) && (closure[v] < vEnd)) { const PetscInt gv = gvertex[closure[v] - vStart]; closure[nC++] = gv < 0 ? -(gv+1) : gv; } } corners[numCells++] = nC; localVertices[k++] = nC; for (v = 0; v < nC; ++v, ++k) { localVertices[k] = closure[v]; } ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); } if (k != numSend) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Invalid number of vertices to send %d should be %d", k, numSend); ierr = MPI_Send(&numSend, 1, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); ierr = MPI_Send(localVertices, numSend, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); ierr = PetscFree(localVertices);CHKERRQ(ierr); } ierr = ISRestoreIndices(globalVertexNumbers, &gvertex);CHKERRQ(ierr); ierr = PetscFPrintf(comm, fp, "CELL_TYPES %d\n", totCells);CHKERRQ(ierr); if (!rank) { PetscInt cellType; for (c = 0; c < numCells; ++c) { ierr = DMPlexVTKGetCellType(dm, dim, corners[c], &cellType);CHKERRQ(ierr); ierr = PetscFPrintf(comm, fp, "%d\n", cellType);CHKERRQ(ierr); } for (proc = 1; proc < numProcs; ++proc) { MPI_Status status; ierr = MPI_Recv(&numCells, 1, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); ierr = MPI_Recv(corners, numCells, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); for (c = 0; c < numCells; ++c) { ierr = DMPlexVTKGetCellType(dm, dim, corners[c], &cellType);CHKERRQ(ierr); ierr = PetscFPrintf(comm, fp, "%d\n", cellType);CHKERRQ(ierr); } } } else { ierr = MPI_Send(&numCells, 1, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); ierr = MPI_Send(corners, numCells, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); } ierr = PetscFree(corners);CHKERRQ(ierr); *totalCells = totCells; PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) { PetscInt dim = user->dim; const char *filename = user->filename; PetscBool interpolate = user->interpolate; PetscReal refinementLimit = user->refinementLimit; PetscBool refinementUniform = user->refinementUniform; PetscInt refinementRounds = user->refinementRounds; const char *partitioner = user->partitioner; size_t len; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = PetscLogEventBegin(user->createMeshEvent,0,0,0,0);CHKERRQ(ierr); ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); if (!len) { ierr = DMPlexCreateBoxMesh(comm, dim, interpolate, dm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) *dm, "Mesh");CHKERRQ(ierr); } else if (user->checkpoint) { ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMLoad(*dm, user->checkpoint);CHKERRQ(ierr); ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); } else { PetscMPIInt rank; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = DMPlexCreateExodusFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); /* Must have boundary marker for Dirichlet conditions */ } { DM refinedMesh = NULL; DM distributedMesh = NULL; /* Refine mesh using a volume constraint */ ierr = DMPlexSetRefinementLimit(*dm, refinementLimit);CHKERRQ(ierr); ierr = DMRefine(*dm, comm, &refinedMesh);CHKERRQ(ierr); if (refinedMesh) { const char *name; ierr = PetscObjectGetName((PetscObject) *dm, &name);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) refinedMesh, name);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = refinedMesh; } /* Distribute mesh over processes */ ierr = DMPlexDistribute(*dm, partitioner, 0, NULL, &distributedMesh);CHKERRQ(ierr); if (distributedMesh) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = distributedMesh; } /* Use regular refinement in parallel */ if (refinementUniform) { PetscInt r; ierr = DMPlexSetRefinementUniform(*dm, refinementUniform);CHKERRQ(ierr); for (r = 0; r < refinementRounds; ++r) { ierr = DMRefine(*dm, comm, &refinedMesh);CHKERRQ(ierr); if (refinedMesh) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = refinedMesh; } } } } ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); if (user->bcType == NEUMANN) { DMLabel label; ierr = DMPlexCreateLabel(*dm, "boundary");CHKERRQ(ierr); ierr = DMPlexGetLabel(*dm, "boundary", &label);CHKERRQ(ierr); ierr = DMPlexMarkBoundaryFaces(*dm, label);CHKERRQ(ierr); } ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); ierr = PetscLogEventEnd(user->createMeshEvent,0,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }