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); }
PetscErrorCode TestSetup(DMLabel label, AppCtx *user) { PetscRandom r; PetscInt n = (PetscInt) (user->fill*(user->pEnd - user->pStart)), i; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr);/* -random_type <> */ ierr = PetscRandomSetInterval(r, user->pStart, user->pEnd);CHKERRQ(ierr); ierr = PetscRandomSetSeed(r, 123456789L);CHKERRQ(ierr); ierr = PetscRandomSeed(r);CHKERRQ(ierr); user->size = 0; for(i = 0; i < n; ++i) { PetscReal p; PetscInt val; ierr = PetscRandomGetValueReal(r, &p);CHKERRQ(ierr); ierr = DMLabelGetValue(label, (PetscInt) p, &val);CHKERRQ(ierr); if (val < 0) { ++user->size; ierr = DMLabelSetValue(label, (PetscInt) p, i % user->numStrata);CHKERRQ(ierr); } } ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); ierr = DMLabelCreateIndex(label, user->pStart, user->pEnd);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_SELF, "Created label with chart [%D, %D) and set %D values\n", user->pStart, user->pEnd, user->size);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); }
PetscErrorCode TestClear(DMLabel label, AppCtx *user) { PetscInt pStart = user->pStart, pEnd = user->pEnd, p; PetscInt defaultValue; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMLabelGetDefaultValue(label,&defaultValue);CHKERRQ(ierr); for (p = pStart; p < pEnd; p++) { PetscInt val; PetscBool hasPoint; ierr = DMLabelGetValue(label,p,&val);CHKERRQ(ierr); if (val != defaultValue) { ierr = DMLabelClearValue(label,p,val);CHKERRQ(ierr); } ierr = DMLabelGetValue(label,p,&val);CHKERRQ(ierr); ierr = DMLabelHasPoint(label,p,&hasPoint);CHKERRQ(ierr); if (val != defaultValue) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected default value %D after clearing point %D, got %D",defaultValue,p,val); if (hasPoint) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Label contains %D after clearing",p); } PetscFunctionReturn(0); }
static PetscErrorCode CreateAdaptivityLabel(DM forest,DMLabel *adaptLabel) { DMLabel identLabel; PetscInt cStart, cEnd, c; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMLabelCreate("adapt",adaptLabel);CHKERRQ(ierr); ierr = DMLabelSetDefaultValue(*adaptLabel,DM_ADAPT_COARSEN);CHKERRQ(ierr); ierr = DMGetLabel(forest,"identity",&identLabel);CHKERRQ(ierr); ierr = DMForestGetCellChart(forest,&cStart,&cEnd);CHKERRQ(ierr); for (c = cStart; c < cEnd; c++) { PetscInt basePoint; ierr = DMLabelGetValue(identLabel,c,&basePoint);CHKERRQ(ierr); if (!basePoint) {ierr = DMLabelSetValue(*adaptLabel,c,DM_ADAPT_REFINE);CHKERRQ(ierr);} } PetscFunctionReturn(0); }
PetscErrorCode TestLookup(DMLabel label, AppCtx *user) { const PetscInt pStart = user->pStart; const PetscInt pEnd = user->pEnd; PetscInt p, n = 0; PetscErrorCode ierr; PetscFunctionBegin; for(p = pStart; p < pEnd; ++p) { PetscInt val; PetscBool has; ierr = DMLabelGetValue(label, p, &val);CHKERRQ(ierr); ierr = DMLabelHasPoint(label, p, &has);CHKERRQ(ierr); if (((val >= 0) && !has) || ((val < 0) && has)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %D does not match contains check %D for point %D", val, (PetscInt) has, p); if (has) ++n; } if (n != user->size) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of label points detected %D does not match number set %D", n, user->size); /* Also put in timing code */ PetscFunctionReturn(0); }
/*@ DMPlexGetOrdering - Calculate a reordering of the mesh Collective on DM Input Parameter: + dm - The DMPlex object . otype - type of reordering, one of the following: $ MATORDERINGNATURAL - Natural $ MATORDERINGND - Nested Dissection $ MATORDERING1WD - One-way Dissection $ MATORDERINGRCM - Reverse Cuthill-McKee $ MATORDERINGQMD - Quotient Minimum Degree - label - [Optional] Label used to segregate ordering into sets, or NULL Output Parameter: . perm - The point permutation as an IS, perm[old point number] = new point number Note: The label is used to group sets of points together by label value. This makes it easy to reorder a mesh which has different types of cells, and then loop over each set of reordered cells for assembly. Level: intermediate .keywords: mesh .seealso: MatGetOrdering() @*/ PetscErrorCode DMPlexGetOrdering(DM dm, MatOrderingType otype, DMLabel label, IS *perm) { PetscInt numCells = 0; PetscInt *start = NULL, *adjacency = NULL, *cperm, *clperm, *invclperm, *mask, *xls, pStart, pEnd, c, i; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidPointer(perm, 3); ierr = DMPlexCreateNeighborCSR(dm, 0, &numCells, &start, &adjacency);CHKERRQ(ierr); ierr = PetscMalloc3(numCells,&cperm,numCells,&mask,numCells*2,&xls);CHKERRQ(ierr); if (numCells) { /* Shift for Fortran numbering */ for (i = 0; i < start[numCells]; ++i) ++adjacency[i]; for (i = 0; i <= numCells; ++i) ++start[i]; ierr = SPARSEPACKgenrcm(&numCells, start, adjacency, cperm, mask, xls);CHKERRQ(ierr); } ierr = PetscFree(start);CHKERRQ(ierr); ierr = PetscFree(adjacency);CHKERRQ(ierr); /* Shift for Fortran numbering */ for (c = 0; c < numCells; ++c) --cperm[c]; /* Segregate */ if (label) { IS valueIS; const PetscInt *values; PetscInt numValues, numPoints = 0; PetscInt *sperm, *vsize, *voff, v; ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); ierr = ISSort(valueIS);CHKERRQ(ierr); ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); ierr = PetscCalloc3(numCells,&sperm,numValues,&vsize,numValues+1,&voff);CHKERRQ(ierr); for (v = 0; v < numValues; ++v) { ierr = DMLabelGetStratumSize(label, values[v], &vsize[v]);CHKERRQ(ierr); if (v < numValues-1) voff[v+2] += vsize[v] + voff[v+1]; numPoints += vsize[v]; } if (numPoints != numCells) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label only covers %D cells < %D total", numPoints, numCells); for (c = 0; c < numCells; ++c) { const PetscInt oldc = cperm[c]; PetscInt val, vloc; ierr = DMLabelGetValue(label, oldc, &val);CHKERRQ(ierr); if (val == -1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D not present in label", oldc); ierr = PetscFindInt(val, numValues, values, &vloc);CHKERRQ(ierr); if (vloc < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Value %D not present label", val); sperm[voff[vloc+1]++] = oldc; } for (v = 0; v < numValues; ++v) { if (voff[v+1] - voff[v] != vsize[v]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of %D values found is %D != %D", values[v], voff[v+1] - voff[v], vsize[v]); } ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); ierr = ISDestroy(&valueIS);CHKERRQ(ierr); ierr = PetscMemcpy(cperm, sperm, numCells * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscFree3(sperm, vsize, voff);CHKERRQ(ierr); } /* Construct closure */ ierr = DMPlexCreateOrderingClosure_Static(dm, numCells, cperm, &clperm, &invclperm);CHKERRQ(ierr); ierr = PetscFree3(cperm,mask,xls);CHKERRQ(ierr); ierr = PetscFree(clperm);CHKERRQ(ierr); /* Invert permutation */ ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd-pStart, invclperm, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 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); }
/*@C PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using the local section and an SF describing the section point overlap. Input Parameters: + s - The PetscSection for the local field layout . sf - The SF describing parallel layout of the section points . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs . label - The label specifying the points - labelValue - The label stratum specifying the points Output Parameter: . gsection - The PetscSection for the global field layout Note: This gives negative sizes and offsets to points not owned by this process Level: developer .seealso: PetscSectionCreate() @*/ PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) { PetscInt *neg = NULL, *tmpOff = NULL; PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr); ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); if (nroots >= 0) { if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr); if (nroots > pEnd-pStart) { ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr); } else { tmpOff = &(*gsection)->atlasDof[-pStart]; } } /* Mark ghost points with negative dof */ for (p = pStart; p < pEnd; ++p) { PetscInt value; ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); if (value != labelValue) continue; ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} if (neg) neg[p] = -(dof+1); } ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); if (nroots >= 0) { ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); if (nroots > pEnd-pStart) { for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} } } /* Calculate new sizes, get proccess offset, and calculate point offsets */ for (p = 0, off = 0; p < pEnd-pStart; ++p) { cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; (*gsection)->atlasOff[p] = off; off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; } ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr); globalOff -= off; for (p = 0, off = 0; p < pEnd-pStart; ++p) { (*gsection)->atlasOff[p] += globalOff; if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); } /* Put in negative offsets for ghost points */ if (nroots >= 0) { ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); if (nroots > pEnd-pStart) { for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} } } if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} ierr = PetscFree(neg);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); }
PETSC_EXTERN PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) { MPI_Comm comm; const PetscInt dim = 3; const char *labelName = "marker"; PLC *in, *out; DMLabel label; PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); ierr = MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMGetLabel(dm, labelName, &label);CHKERRQ(ierr); ierr = PLCCreate(&in);CHKERRQ(ierr); ierr = PLCCreate(&out);CHKERRQ(ierr); in->numberofpoints = vEnd - vStart; if (in->numberofpoints > 0) { PetscSection coordSection; Vec coordinates; PetscScalar *array; ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); for (v = vStart; v < vEnd; ++v) { const PetscInt idx = v - vStart; PetscInt off, d, m = -1; ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); for (d = 0; d < dim; ++d) { in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); } if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);} in->pointmarkerlist[idx] = (int) m; } ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); } ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); in->numberofcorners = 4; in->numberoftetrahedra = cEnd - cStart; in->tetrahedronvolumelist = maxVolumes; if (in->numberoftetrahedra > 0) { ierr = PetscMalloc1(in->numberoftetrahedra*in->numberofcorners, &in->tetrahedronlist);CHKERRQ(ierr); for (c = cStart; c < cEnd; ++c) { const PetscInt idx = c - cStart; PetscInt *closure = NULL; PetscInt closureSize; ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); for (v = 0; v < 4; ++v) { in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; } ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); } } if (!rank) { TetGenOpts t; ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); t.in = dm; /* Should go away */ t.refine = 1; t.varvolume = 1; t.quality = 1; t.edgesout = 1; t.zeroindex = 1; t.quiet = 1; t.verbose = verbose; /* Change this */ ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); } in->tetrahedronvolumelist = NULL; { DMLabel rlabel = NULL; const PetscInt numCorners = 4; const PetscInt numCells = out->numberoftetrahedra; const PetscInt numVertices = out->numberofpoints; double *meshCoords; int *cells = out->tetrahedronlist; PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; if (sizeof (PetscReal) == sizeof (double)) { meshCoords = (double *) out->pointlist; } else { PetscInt i; ierr = PetscMalloc1(3 * numVertices,&meshCoords);CHKERRQ(ierr); for (i = 0; i < 3 * numVertices; i++) { meshCoords[i] = (PetscReal) out->pointlist[i]; } } ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); if (sizeof (PetscReal) != sizeof (double)) { ierr = PetscFree(meshCoords);CHKERRQ(ierr); } if (label) {ierr = DMCreateLabel(*dmRefined, labelName); ierr = DMGetLabel(*dmRefined, labelName, &rlabel);} /* Set labels */ for (v = 0; v < numVertices; ++v) { if (out->pointmarkerlist[v]) { if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);} } } if (interpolate) { PetscInt e, f; for (e = 0; e < out->numberofedges; e++) { if (out->edgemarkerlist[e]) { const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; const PetscInt *edges; PetscInt numEdges; ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);} ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); } } for (f = 0; f < out->numberoftrifaces; f++) { if (out->trifacemarkerlist[f]) { const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; const PetscInt *faces; PetscInt numFaces; ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); if (rlabel) {ierr = DMLabelSetValue(rlabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);} ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); } } } ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); } ierr = PLCDestroy(&in);CHKERRQ(ierr); ierr = PLCDestroy(&out);CHKERRQ(ierr); PetscFunctionReturn(0); }
PETSC_EXTERN PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) { MPI_Comm comm; const PetscInt dim = 3; const char *labelName = "marker"; PLC *in, *out; DMLabel label; PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMGetLabel(boundary, labelName, &label);CHKERRQ(ierr); ierr = PLCCreate(&in);CHKERRQ(ierr); ierr = PLCCreate(&out);CHKERRQ(ierr); in->numberofpoints = vEnd - vStart; if (in->numberofpoints > 0) { PetscSection coordSection; Vec coordinates; PetscScalar *array; ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); for (v = vStart; v < vEnd; ++v) { const PetscInt idx = v - vStart; PetscInt off, d, m = -1; ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); for (d = 0; d < dim; ++d) { in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); } if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);} in->pointmarkerlist[idx] = (int) m; } ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); } ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); in->numberoffacets = fEnd - fStart; if (in->numberoffacets > 0) { ierr = PetscMalloc1(in->numberoffacets, &in->facetlist);CHKERRQ(ierr); ierr = PetscMalloc1(in->numberoffacets, &in->facetmarkerlist);CHKERRQ(ierr); for (f = fStart; f < fEnd; ++f) { const PetscInt idx = f - fStart; PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m = -1; polygon *poly; in->facetlist[idx].numberofpolygons = 1; ierr = PetscMalloc1(in->facetlist[idx].numberofpolygons, &in->facetlist[idx].polygonlist);CHKERRQ(ierr); in->facetlist[idx].numberofholes = 0; in->facetlist[idx].holelist = NULL; ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); for (p = 0; p < numPoints*2; p += 2) { const PetscInt point = points[p]; if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; } poly = in->facetlist[idx].polygonlist; poly->numberofvertices = numVertices; ierr = PetscMalloc1(poly->numberofvertices, &poly->vertexlist);CHKERRQ(ierr); for (v = 0; v < numVertices; ++v) { const PetscInt vIdx = points[v] - vStart; poly->vertexlist[v] = vIdx; } if (label) {ierr = DMLabelGetValue(label, f, &m);CHKERRQ(ierr);} in->facetmarkerlist[idx] = (int) m; ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); } } if (!rank) { TetGenOpts t; ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); t.in = boundary; /* Should go away */ t.plc = 1; t.quality = 1; t.edgesout = 1; t.zeroindex = 1; t.quiet = 1; t.verbose = verbose; ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); } { DMLabel glabel = NULL; const PetscInt numCorners = 4; const PetscInt numCells = out->numberoftetrahedra; const PetscInt numVertices = out->numberofpoints; double *meshCoords; int *cells = out->tetrahedronlist; if (sizeof (PetscReal) == sizeof (double)) { meshCoords = (double *) out->pointlist; } else { PetscInt i; ierr = PetscMalloc1(3 * numVertices,&meshCoords);CHKERRQ(ierr); for (i = 0; i < 3 * numVertices; i++) { meshCoords[i] = (PetscReal) out->pointlist[i]; } } ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); if (sizeof (PetscReal) != sizeof (double)) { ierr = PetscFree(meshCoords);CHKERRQ(ierr); } if (label) {ierr = DMCreateLabel(*dm, labelName); ierr = DMGetLabel(*dm, labelName, &glabel);} /* Set labels */ for (v = 0; v < numVertices; ++v) { if (out->pointmarkerlist[v]) { if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);} } } if (interpolate) { PetscInt e; for (e = 0; e < out->numberofedges; e++) { if (out->edgemarkerlist[e]) { const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; const PetscInt *edges; PetscInt numEdges; ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);} ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); } } for (f = 0; f < out->numberoftrifaces; f++) { if (out->trifacemarkerlist[f]) { const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; const PetscInt *faces; PetscInt numFaces; ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); if (glabel) {ierr = DMLabelSetValue(glabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);} ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); } } } ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); } ierr = PLCDestroy(&in);CHKERRQ(ierr); ierr = PLCDestroy(&out);CHKERRQ(ierr); PetscFunctionReturn(0); }