/*@ DMPlexReverseCell - Give a mesh cell the opposite orientation Input Parameters: + dm - The DM - cell - The cell number Note: The modification of the DM is done in-place. Level: advanced .seealso: DMPlexOrient(), DMCreate(), DMPLEX @*/ PetscErrorCode DMPlexReverseCell(DM dm, PetscInt cell) { /* Note that the reverse orientation ro of a face with orientation o is: ro = o >= 0 ? -(faceSize - o) : faceSize + o where faceSize is the size of the cone for the face. */ const PetscInt *cone, *coneO, *support; PetscInt *revcone, *revconeO; PetscInt maxConeSize, coneSize, supportSize, faceSize, cp, sp; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPlexGetMaxSizes(dm, &maxConeSize, NULL);CHKERRQ(ierr); ierr = DMGetWorkArray(dm, maxConeSize, MPIU_INT, &revcone);CHKERRQ(ierr); ierr = DMGetWorkArray(dm, maxConeSize, MPIU_INT, &revconeO);CHKERRQ(ierr); /* Reverse cone, and reverse orientations of faces */ ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); ierr = DMPlexGetConeOrientation(dm, cell, &coneO);CHKERRQ(ierr); for (cp = 0; cp < coneSize; ++cp) { const PetscInt rcp = coneSize-cp-1; ierr = DMPlexGetConeSize(dm, cone[rcp], &faceSize);CHKERRQ(ierr); revcone[cp] = cone[rcp]; revconeO[cp] = coneO[rcp] >= 0 ? -(faceSize-coneO[rcp]) : faceSize+coneO[rcp]; } ierr = DMPlexSetCone(dm, cell, revcone);CHKERRQ(ierr); ierr = DMPlexSetConeOrientation(dm, cell, revconeO);CHKERRQ(ierr); /* Reverse orientation of this cell in the support hypercells */ faceSize = coneSize; ierr = DMPlexGetSupportSize(dm, cell, &supportSize);CHKERRQ(ierr); ierr = DMPlexGetSupport(dm, cell, &support);CHKERRQ(ierr); for (sp = 0; sp < supportSize; ++sp) { ierr = DMPlexGetConeSize(dm, support[sp], &coneSize);CHKERRQ(ierr); ierr = DMPlexGetCone(dm, support[sp], &cone);CHKERRQ(ierr); ierr = DMPlexGetConeOrientation(dm, support[sp], &coneO);CHKERRQ(ierr); for (cp = 0; cp < coneSize; ++cp) { if (cone[cp] != cell) continue; ierr = DMPlexInsertConeOrientation(dm, support[sp], cp, coneO[cp] >= 0 ? -(faceSize-coneO[cp]) : faceSize+coneO[cp]);CHKERRQ(ierr); } } ierr = DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &revcone);CHKERRQ(ierr); ierr = DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &revconeO);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMDARestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useClosure, PetscInt *closureSize, PetscInt **closure) { PetscErrorCode ierr; PetscFunctionBegin; ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, closure);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* DMPlexRestoreFaces_Internal - Restores the array */ PetscErrorCode DMPlexRestoreFaces_Internal(DM dm, PetscInt dim, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) { PetscErrorCode ierr; PetscFunctionBegin; ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) faces);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMDARestoreClosureScalar(DM dm, PetscSection section, PetscInt p, PetscScalar *vArray, PetscInt *csize, PetscScalar **values) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidPointer(values, 6); ierr = DMRestoreWorkArray(dm, csize ? *csize : 0, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); PetscFunctionReturn(0); }
PETSC_STATIC_INLINE PetscErrorCode RestorePointArray_Private(DM dm,PetscInt *rn,const PetscInt **rpoints) { PetscErrorCode ierr; PetscFunctionBegin; if (rn) *rn = 0; if (rpoints) { ierr = DMRestoreWorkArray(dm,*rn, PETSC_INT, (void*) rpoints);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* This takes as input the common mesh generator output, a list of the vertices for each cell */ PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) { PetscInt *cone, c, p; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); for (c = 0; c < numCells; ++c) { ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); } ierr = DMSetUp(dm);CHKERRQ(ierr); ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); for (c = 0; c < numCells; ++c) { for (p = 0; p < numCorners; ++p) { cone[p] = cells[c*numCorners+p]+numCells; } ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); } ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); ierr = DMPlexStratify(dm);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* DMPlexGetFaces_Internal - Gets groups of vertices that correspond to faces for the given cell */ static PetscErrorCode DMPlexGetFaces_Internal(DM dm, PetscInt dim, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) { const PetscInt *cone = NULL; PetscInt *facesTmp; PetscInt maxConeSize, maxSupportSize, coneSize; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); ierr = DMGetWorkArray(dm, PetscSqr(PetscMax(maxConeSize, maxSupportSize)), PETSC_INT, &facesTmp);CHKERRQ(ierr); ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); switch (dim) { case 2: switch (coneSize) { case 3: if (faces) { facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; facesTmp[4] = cone[2]; facesTmp[5] = cone[0]; *faces = facesTmp; } if (numFaces) *numFaces = 3; if (faceSize) *faceSize = 2; break; case 4: /* Vertices follow right hand rule */ if (faces) { facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; facesTmp[4] = cone[2]; facesTmp[5] = cone[3]; facesTmp[6] = cone[3]; facesTmp[7] = cone[0]; *faces = facesTmp; } if (numFaces) *numFaces = 4; if (faceSize) *faceSize = 2; if (faces) *faces = facesTmp; break; default: SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); } break; case 3: switch (coneSize) { case 3: if (faces) { facesTmp[0] = cone[0]; facesTmp[1] = cone[1]; facesTmp[2] = cone[1]; facesTmp[3] = cone[2]; facesTmp[4] = cone[2]; facesTmp[5] = cone[0]; *faces = facesTmp; } if (numFaces) *numFaces = 3; if (faceSize) *faceSize = 2; if (faces) *faces = facesTmp; break; case 4: /* Vertices of first face follow right hand rule and normal points towards last vertex */ if (faces) { facesTmp[0] = cone[0]; facesTmp[1] = cone[2]; facesTmp[2] = cone[1]; facesTmp[3] = cone[0]; facesTmp[4] = cone[1]; facesTmp[5] = cone[3]; facesTmp[6] = cone[0]; facesTmp[7] = cone[3]; facesTmp[8] = cone[2]; facesTmp[9] = cone[1]; facesTmp[10] = cone[2]; facesTmp[11] = cone[3]; *faces = facesTmp; } if (numFaces) *numFaces = 4; if (faceSize) *faceSize = 3; if (faces) *faces = facesTmp; break; case 8: if (faces) { facesTmp[0] = cone[0]; facesTmp[1] = cone[3]; facesTmp[2] = cone[2]; facesTmp[3] = cone[1]; facesTmp[4] = cone[4]; facesTmp[5] = cone[5]; facesTmp[6] = cone[6]; facesTmp[7] = cone[7]; facesTmp[8] = cone[0]; facesTmp[9] = cone[1]; facesTmp[10] = cone[5]; facesTmp[11] = cone[4]; facesTmp[12] = cone[2]; facesTmp[13] = cone[3]; facesTmp[14] = cone[7]; facesTmp[15] = cone[6]; facesTmp[16] = cone[1]; facesTmp[17] = cone[2]; facesTmp[18] = cone[6]; facesTmp[19] = cone[5]; facesTmp[20] = cone[0]; facesTmp[21] = cone[4]; facesTmp[22] = cone[7]; facesTmp[23] = cone[3]; *faces = facesTmp; } if (numFaces) *numFaces = 6; if (faceSize) *faceSize = 4; break; default: SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); } break; default: SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); } ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, &facesTmp);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMPlexGetIndex - Get the index of 'point'. It returns the global indices. Not collective Input Parameters: + dm - The DM . section - The section describing the layout in v, or NULL to use the default section . globalSection - The section describing the layout in v, or NULL to use the default global section . point - The sieve point in the DM . NumOfIndices - The number of the indices for this point . indices - The indices of this point Level: intermediate .seealso DMPlexVecSetClosure() @*/ PetscErrorCode DMPlexGetIndex(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *NumOfIndices, PetscInt index[]) { PetscSection clSection; IS clPoints; PetscInt *points = NULL; const PetscInt *clp; PetscInt *indices; PetscInt offsets[32]; PetscInt numFields, numIndices, numPoints, dof, off, globalOff, pStart, pEnd, p, q, f; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); if (!clPoints) { ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); /* Compress out points not in the section */ ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); for (p = 0, q = 0; p < numPoints*2; p += 2) { if ((points[p] >= pStart) && (points[p] < pEnd)) { points[q*2] = points[p]; points[q*2+1] = points[p+1]; ++q; } } numPoints = q; } else { PetscInt dof, off; ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); numPoints = dof/2; ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); points = (PetscInt *) &clp[off]; } for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { PetscInt fdof; ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); for (f = 0; f < numFields; ++f) { ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); offsets[f+1] += fdof; } numIndices += dof; } for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); if (numFields) { for (p = 0; p < numPoints*2; p += 2) { PetscInt o = points[p+1]; ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); } } else { for (p = 0, off = 0; p < numPoints*2; p += 2) { PetscInt o = points[p+1]; ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); } } if (!clPoints) { ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); } else { ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); } { /*Out put the number of indices and the value of indices on this point*/ PetscInt j; *NumOfIndices = numIndices; for(j = 0; j < numIndices; j++){ index[j] = indices[j]; } } ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 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); }
PetscErrorCode PetscFEGetTabulation_Composite(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscReal *B, PetscReal *D, PetscReal *H) { PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data; DM dm; PetscInt pdim; /* Dimension of FE space P */ PetscInt spdim; /* Dimension of subelement FE space P */ PetscInt dim; /* Spatial dimension */ PetscInt comp; /* Field components */ PetscInt *subpoints; PetscReal *tmpB, *tmpD, *tmpH, *subpoint; PetscInt p, s, d, e, j, k; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr); ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); ierr = PetscSpaceGetDimension(fem->basisSpace, &spdim);CHKERRQ(ierr); ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr); ierr = PetscFEGetNumComponents(fem, &comp);CHKERRQ(ierr); /* Divide points into subelements */ ierr = DMGetWorkArray(dm, npoints, MPIU_INT, &subpoints);CHKERRQ(ierr); ierr = DMGetWorkArray(dm, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); for (p = 0; p < npoints; ++p) { for (s = 0; s < cmp->numSubelements; ++s) { PetscBool inside; /* Apply transform, and check that point is inside cell */ for (d = 0; d < dim; ++d) { subpoint[d] = -1.0; for (e = 0; e < dim; ++e) subpoint[d] += cmp->invjac[(s*dim + d)*dim+e]*(points[p*dim+e] - cmp->v0[s*dim+e]); } ierr = CellRefinerInCellTest_Internal(cmp->cellRefiner, subpoint, &inside);CHKERRQ(ierr); if (inside) {subpoints[p] = s; break;} } if (s >= cmp->numSubelements) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %d was not found in any subelement", p); } ierr = DMRestoreWorkArray(dm, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); /* Evaluate the prime basis functions at all points */ if (B) {ierr = DMGetWorkArray(dm, npoints*spdim, MPIU_REAL, &tmpB);CHKERRQ(ierr);} if (D) {ierr = DMGetWorkArray(dm, npoints*spdim*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);} if (H) {ierr = DMGetWorkArray(dm, npoints*spdim*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);} ierr = PetscSpaceEvaluate(fem->basisSpace, npoints, points, B ? tmpB : NULL, D ? tmpD : NULL, H ? tmpH : NULL);CHKERRQ(ierr); /* Translate to the nodal basis */ if (B) {ierr = PetscMemzero(B, npoints*pdim*comp * sizeof(PetscReal));CHKERRQ(ierr);} if (D) {ierr = PetscMemzero(D, npoints*pdim*comp*dim * sizeof(PetscReal));CHKERRQ(ierr);} if (H) {ierr = PetscMemzero(H, npoints*pdim*comp*dim*dim * sizeof(PetscReal));CHKERRQ(ierr);} for (p = 0; p < npoints; ++p) { const PetscInt s = subpoints[p]; if (B) { /* Multiply by V^{-1} (spdim x spdim) */ for (j = 0; j < spdim; ++j) { const PetscInt i = (p*pdim + cmp->embedding[s*spdim+j])*comp; B[i] = 0.0; for (k = 0; k < spdim; ++k) { B[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpB[p*spdim + k]; } } } if (D) { /* Multiply by V^{-1} (spdim x spdim) */ for (j = 0; j < spdim; ++j) { for (d = 0; d < dim; ++d) { const PetscInt i = ((p*pdim + cmp->embedding[s*spdim+j])*comp + 0)*dim + d; D[i] = 0.0; for (k = 0; k < spdim; ++k) { D[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpD[(p*spdim + k)*dim + d]; } } } } if (H) { /* Multiply by V^{-1} (pdim x pdim) */ for (j = 0; j < spdim; ++j) { for (d = 0; d < dim*dim; ++d) { const PetscInt i = ((p*pdim + cmp->embedding[s*spdim+j])*comp + 0)*dim*dim + d; H[i] = 0.0; for (k = 0; k < spdim; ++k) { H[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpH[(p*spdim + k)*dim*dim + d]; } } } } } ierr = DMRestoreWorkArray(dm, npoints, MPIU_INT, &subpoints);CHKERRQ(ierr); if (B) {ierr = DMRestoreWorkArray(dm, npoints*spdim, MPIU_REAL, &tmpB);CHKERRQ(ierr);} if (D) {ierr = DMRestoreWorkArray(dm, npoints*spdim*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);} if (H) {ierr = DMRestoreWorkArray(dm, npoints*spdim*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);} PetscFunctionReturn(0); }
PetscErrorCode PetscFESetUp_Composite(PetscFE fem) { PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data; DM K; PetscReal *subpoint; PetscBLASInt *pivots; PetscBLASInt n, info; PetscScalar *work, *invVscalar; PetscInt dim, pdim, spdim, j, s; PetscErrorCode ierr; PetscFunctionBegin; /* Get affine mapping from reference cell to each subcell */ ierr = PetscDualSpaceGetDM(fem->dualSpace, &K);CHKERRQ(ierr); ierr = DMGetDimension(K, &dim);CHKERRQ(ierr); ierr = DMPlexGetCellRefiner_Internal(K, &cmp->cellRefiner);CHKERRQ(ierr); ierr = CellRefinerGetAffineTransforms_Internal(cmp->cellRefiner, &cmp->numSubelements, &cmp->v0, &cmp->jac, &cmp->invjac);CHKERRQ(ierr); /* Determine dof embedding into subelements */ ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr); ierr = PetscSpaceGetDimension(fem->basisSpace, &spdim);CHKERRQ(ierr); ierr = PetscMalloc1(cmp->numSubelements*spdim,&cmp->embedding);CHKERRQ(ierr); ierr = DMGetWorkArray(K, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); for (s = 0; s < cmp->numSubelements; ++s) { PetscInt sd = 0; for (j = 0; j < pdim; ++j) { PetscBool inside; PetscQuadrature f; PetscInt d, e; ierr = PetscDualSpaceGetFunctional(fem->dualSpace, j, &f);CHKERRQ(ierr); /* Apply transform to first point, and check that point is inside subcell */ for (d = 0; d < dim; ++d) { subpoint[d] = -1.0; for (e = 0; e < dim; ++e) subpoint[d] += cmp->invjac[(s*dim + d)*dim+e]*(f->points[e] - cmp->v0[s*dim+e]); } ierr = CellRefinerInCellTest_Internal(cmp->cellRefiner, subpoint, &inside);CHKERRQ(ierr); if (inside) {cmp->embedding[s*spdim+sd++] = j;} } if (sd != spdim) SETERRQ3(PetscObjectComm((PetscObject) fem), PETSC_ERR_PLIB, "Subelement %d has %d dual basis vectors != %d", s, sd, spdim); } ierr = DMRestoreWorkArray(K, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); /* Construct the change of basis from prime basis to nodal basis for each subelement */ ierr = PetscMalloc1(cmp->numSubelements*spdim*spdim,&fem->invV);CHKERRQ(ierr); ierr = PetscMalloc2(spdim,&pivots,spdim,&work);CHKERRQ(ierr); #if defined(PETSC_USE_COMPLEX) ierr = PetscMalloc1(cmp->numSubelements*spdim*spdim,&invVscalar);CHKERRQ(ierr); #else invVscalar = fem->invV; #endif for (s = 0; s < cmp->numSubelements; ++s) { for (j = 0; j < spdim; ++j) { PetscReal *Bf; PetscQuadrature f; const PetscReal *points, *weights; PetscInt Nc, Nq, q, k; ierr = PetscDualSpaceGetFunctional(fem->dualSpace, cmp->embedding[s*spdim+j], &f);CHKERRQ(ierr); ierr = PetscQuadratureGetData(f, NULL, &Nc, &Nq, &points, &weights);CHKERRQ(ierr); ierr = PetscMalloc1(f->numPoints*spdim*Nc,&Bf);CHKERRQ(ierr); ierr = PetscSpaceEvaluate(fem->basisSpace, Nq, points, Bf, NULL, NULL);CHKERRQ(ierr); for (k = 0; k < spdim; ++k) { /* n_j \cdot \phi_k */ invVscalar[(s*spdim + j)*spdim+k] = 0.0; for (q = 0; q < Nq; ++q) { invVscalar[(s*spdim + j)*spdim+k] += Bf[q*spdim+k]*weights[q]; } } ierr = PetscFree(Bf);CHKERRQ(ierr); } n = spdim; PetscStackCallBLAS("LAPACKgetrf", LAPACKgetrf_(&n, &n, &invVscalar[s*spdim*spdim], &n, pivots, &info)); PetscStackCallBLAS("LAPACKgetri", LAPACKgetri_(&n, &invVscalar[s*spdim*spdim], &n, pivots, work, &n, &info)); } #if defined(PETSC_USE_COMPLEX) for (s = 0; s <cmp->numSubelements*spdim*spdim; s++) fem->invV[s] = PetscRealPart(invVscalar[s]); ierr = PetscFree(invVscalar);CHKERRQ(ierr); #endif ierr = PetscFree2(pivots,work);CHKERRQ(ierr); PetscFunctionReturn(0); }