#include /*I "petscfe.h" I*/ /*@C PetscFEGeomCreate - Create a PetscFEGeom object to manage geometry for a group of cells Input Parameters: + quad - A PetscQuadrature determining the tabulation . numCells - The number of cells in the group . dimEmbed - The coordinate dimension - faceData - Flag to construct geometry data for the faces Output Parameter: . geom - The PetscFEGeom object Level: beginner .seealso: PetscFEGeomDestroy(), PetscFEGeomComplete() @*/ PetscErrorCode PetscFEGeomCreate(PetscQuadrature quad, PetscInt numCells, PetscInt dimEmbed, PetscBool faceData, PetscFEGeom **geom) { PetscFEGeom *g; PetscInt dim, Nq, N; const PetscReal *p; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscQuadratureGetData(quad,&dim,NULL,&Nq,&p,NULL);CHKERRQ(ierr); ierr = PetscNew(&g);CHKERRQ(ierr); g->xi = p; g->numCells = numCells; g->numPoints = Nq; g->dim = dim; g->dimEmbed = dimEmbed; g->isHybrid = PETSC_FALSE; N = numCells * Nq; ierr = PetscCalloc3(N * dimEmbed, &g->v, N * dimEmbed * dimEmbed, &g->J, N, &g->detJ);CHKERRQ(ierr); if (faceData) { ierr = PetscCalloc2(numCells, &g->face, N * dimEmbed, &g->n);CHKERRQ(ierr); ierr = PetscCalloc6(N * dimEmbed * dimEmbed, &(g->suppJ[0]), N * dimEmbed * dimEmbed, &(g->suppJ[1]), N * dimEmbed * dimEmbed, &(g->suppInvJ[0]), N * dimEmbed * dimEmbed, &(g->suppInvJ[1]), N, &(g->suppDetJ[0]), N, &(g->suppDetJ[1]));CHKERRQ(ierr); } ierr = PetscCalloc1(N * dimEmbed * dimEmbed, &g->invJ);CHKERRQ(ierr); *geom = g; PetscFunctionReturn(0); } /*@C PetscFEGeomDestroy - Destroy a PetscFEGeom object Input Parameter: . geom - PetscFEGeom object Level: beginner .seealso: PetscFEGeomCreate() @*/ PetscErrorCode PetscFEGeomDestroy(PetscFEGeom **geom) { PetscErrorCode ierr; PetscFunctionBegin; if (!*geom) PetscFunctionReturn(0); ierr = PetscFree3((*geom)->v,(*geom)->J,(*geom)->detJ);CHKERRQ(ierr); ierr = PetscFree((*geom)->invJ);CHKERRQ(ierr); ierr = PetscFree2((*geom)->face,(*geom)->n);CHKERRQ(ierr); ierr = PetscFree6((*geom)->suppJ[0],(*geom)->suppJ[1],(*geom)->suppInvJ[0],(*geom)->suppInvJ[1],(*geom)->suppDetJ[0],(*geom)->suppDetJ[1]);CHKERRQ(ierr); ierr = PetscFree(*geom);CHKERRQ(ierr); PetscFunctionReturn(0); } /*@C PetscFEGeomGetChunk - Get a chunk of cells in the group as a PetscFEGeom Input Parameters: + geom - PetscFEGeom object . cStart - The first cell in the chunk - cEnd - The first cell not in the chunk Output Parameter: . chunkGeom - The chunk of cells Level: intermediate .seealso: PetscFEGeomRestoreChunk(), PetscFEGeomCreate() @*/ PetscErrorCode PetscFEGeomGetChunk(PetscFEGeom *geom, PetscInt cStart, PetscInt cEnd, PetscFEGeom **chunkGeom) { PetscInt Nq; PetscInt dE; PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(geom,1); PetscValidPointer(chunkGeom,4); if (!(*chunkGeom)) { ierr = PetscNew(chunkGeom);CHKERRQ(ierr); } Nq = geom->numPoints; dE= geom->dimEmbed; (*chunkGeom)->dim = geom->dim; (*chunkGeom)->dimEmbed = geom->dimEmbed; (*chunkGeom)->numPoints = geom->numPoints; (*chunkGeom)->numCells = cEnd - cStart; (*chunkGeom)->xi = geom->xi; (*chunkGeom)->v = &geom->v[Nq*dE*cStart]; (*chunkGeom)->J = &geom->J[Nq*dE*dE*cStart]; (*chunkGeom)->invJ = (geom->invJ) ? &geom->invJ[Nq*dE*dE*cStart] : NULL; (*chunkGeom)->detJ = &geom->detJ[Nq*cStart]; (*chunkGeom)->n = geom->n ? &geom->n[Nq*dE*cStart] : NULL; (*chunkGeom)->face = geom->face ? &geom->face[cStart] : NULL; (*chunkGeom)->suppJ[0] = geom->suppJ[0] ? &geom->suppJ[0][Nq*dE*dE*cStart] : NULL; (*chunkGeom)->suppJ[1] = geom->suppJ[1] ? &geom->suppJ[1][Nq*dE*dE*cStart] : NULL; (*chunkGeom)->suppInvJ[0] = geom->suppInvJ[0] ? &geom->suppInvJ[0][Nq*dE*dE*cStart] : NULL; (*chunkGeom)->suppInvJ[1] = geom->suppInvJ[1] ? &geom->suppInvJ[1][Nq*dE*dE*cStart] : NULL; (*chunkGeom)->suppDetJ[0] = geom->suppDetJ[0] ? &geom->suppDetJ[0][Nq*cStart] : NULL; (*chunkGeom)->suppDetJ[1] = geom->suppDetJ[1] ? &geom->suppDetJ[1][Nq*cStart] : NULL; (*chunkGeom)->isAffine = geom->isAffine; PetscFunctionReturn(0); } /*@C PetscFEGeomRestoreChunk - Restore the chunk Input Parameters: + geom - PetscFEGeom object . cStart - The first cell in the chunk . cEnd - The first cell not in the chunk - chunkGeom - The chunk of cells Level: intermediate .seealso: PetscFEGeomGetChunk(), PetscFEGeomCreate() @*/ PetscErrorCode PetscFEGeomRestoreChunk(PetscFEGeom *geom, PetscInt cStart, PetscInt cEnd, PetscFEGeom **chunkGeom) { PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscFree(*chunkGeom);CHKERRQ(ierr); PetscFunctionReturn(0); } /*@C PetscFEGeomGetPoint - Get the geometry for cell c at point p as a PetscFEGeom Input Parameters: + geom - PetscFEGeom object . c - The cell . p - The point - pcoords - The reference coordinates of point p, or NULL Output Parameter: . pgeom - The geometry of cell c at point p Note: For affine geometries, this only copies to pgeom at point 0. Since we copy pointers into pgeom, nothing needs to be done with it afterwards. In the affine case, pgeom must have storage for the integration point coordinates in pgeom->v if pcoords is passed in. Level: intermediate .seealso: PetscFEGeomRestoreChunk(), PetscFEGeomCreate() @*/ PetscErrorCode PetscFEGeomGetPoint(PetscFEGeom *geom, PetscInt c, PetscInt p, const PetscReal pcoords[], PetscFEGeom *pgeom) { const PetscInt dim = geom->dim; const PetscInt dE = geom->dimEmbed; const PetscInt Np = geom->numPoints; PetscFunctionBeginHot; pgeom->dim = dim; pgeom->dimEmbed = dE; //pgeom->isAffine = geom->isAffine; if (geom->isAffine) { if (!p) { pgeom->xi = geom->xi; pgeom->J = &geom->J[c*Np*dE*dE]; pgeom->invJ = &geom->invJ[c*Np*dE*dE]; pgeom->detJ = &geom->detJ[c*Np]; pgeom->n = geom->n ? &geom->n[c*Np*dE] : NULL; } if (pcoords) {CoordinatesRefToReal(dE, dim, pgeom->xi, &geom->v[c*Np*dE], pgeom->J, pcoords, pgeom->v);} } else { pgeom->v = &geom->v[(c*Np+p)*dE]; pgeom->J = &geom->J[(c*Np+p)*dE*dE]; pgeom->invJ = &geom->invJ[(c*Np+p)*dE*dE]; pgeom->detJ = &geom->detJ[c*Np+p]; pgeom->n = geom->n ? &geom->n[(c*Np+p)*dE] : NULL; } PetscFunctionReturn(0); } /*@C PetscFEGeomGetCellPoint - Get the cell geometry for face f at point p as a PetscFEGeom Input Parameters: + geom - PetscFEGeom object . f - The face - p - The point Output Parameter: . pgeom - The cell geometry of face f at point p Note: For affine geometries, this only copies to pgeom at point 0. Since we copy pointers into pgeom, nothing needs to be done with it afterwards. Level: intermediate .seealso: PetscFEGeomRestoreChunk(), PetscFEGeomCreate() @*/ PetscErrorCode PetscFEGeomGetCellPoint(PetscFEGeom *geom, PetscInt c, PetscInt p, PetscFEGeom *pgeom) { const PetscBool bd = geom->dimEmbed > geom->dim && !geom->isHybrid ? PETSC_TRUE : PETSC_FALSE; const PetscInt dim = bd ? geom->dimEmbed : geom->dim; const PetscInt dE = geom->dimEmbed; const PetscInt Np = geom->numPoints; PetscFunctionBeginHot; pgeom->dim = dim; pgeom->dimEmbed = dE; //pgeom->isAffine = geom->isAffine; if (geom->isAffine) { if (!p) { if (bd) { pgeom->J = &geom->suppJ[0][c*Np*dE*dE]; pgeom->invJ = &geom->suppInvJ[0][c*Np*dE*dE]; pgeom->detJ = &geom->suppDetJ[0][c*Np]; } else { pgeom->J = &geom->J[c*Np*dE*dE]; pgeom->invJ = &geom->invJ[c*Np*dE*dE]; pgeom->detJ = &geom->detJ[c*Np]; } } } else { if (bd) { pgeom->J = &geom->suppJ[0][(c*Np+p)*dE*dE]; pgeom->invJ = &geom->suppInvJ[0][(c*Np+p)*dE*dE]; pgeom->detJ = &geom->suppDetJ[0][c*Np+p]; } else { pgeom->J = &geom->J[(c*Np+p)*dE*dE]; pgeom->invJ = &geom->invJ[(c*Np+p)*dE*dE]; pgeom->detJ = &geom->detJ[c*Np+p]; } } PetscFunctionReturn(0); } /*@ PetscFEGeomComplete - Calculate derived quntites from base geometry specification Input Parameter: . geom - PetscFEGeom object Level: intermediate .seealso: PetscFEGeomCreate() @*/ PetscErrorCode PetscFEGeomComplete(PetscFEGeom *geom) { PetscInt i, j, N, dE; PetscFunctionBeginHot; N = geom->numPoints * geom->numCells; dE = geom->dimEmbed; switch (dE) { case 3: for (i = 0; i < N; i++) { DMPlex_Det3D_Internal(&geom->detJ[i], &geom->J[dE*dE*i]); if (geom->invJ) DMPlex_Invert3D_Internal(&geom->invJ[dE*dE*i], &geom->J[dE*dE*i], geom->detJ[i]); } break; case 2: for (i = 0; i < N; i++) { DMPlex_Det2D_Internal(&geom->detJ[i], &geom->J[dE*dE*i]); if (geom->invJ) DMPlex_Invert2D_Internal(&geom->invJ[dE*dE*i], &geom->J[dE*dE*i], geom->detJ[i]); } break; case 1: for (i = 0; i < N; i++) { geom->detJ[i] = PetscAbsReal(geom->J[i]); if (geom->invJ) geom->invJ[i] = 1. / geom->J[i]; } break; } if (geom->n) { for (i = 0; i < N; i++) { for (j = 0; j < dE; j++) { geom->n[dE*i + j] = geom->J[dE*dE*i + dE*j + dE-1] * ((dE == 2) ? -1. : 1.); } } } PetscFunctionReturn(0); }