120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 220cf1dd8SToby Isaac 32b99622eSMatthew G. Knepley /*@C 4dce8aebaSBarry Smith PetscFEGeomCreate - Create a `PetscFEGeom` object to manage geometry for a group of cells 52b99622eSMatthew G. Knepley 62b99622eSMatthew G. Knepley Input Parameters: 7dce8aebaSBarry Smith + quad - A `PetscQuadrature` determining the tabulation 82b99622eSMatthew G. Knepley . numCells - The number of cells in the group 92b99622eSMatthew G. Knepley . dimEmbed - The coordinate dimension 102b99622eSMatthew G. Knepley - faceData - Flag to construct geometry data for the faces 112b99622eSMatthew G. Knepley 122b99622eSMatthew G. Knepley Output Parameter: 13dce8aebaSBarry Smith . geom - The `PetscFEGeom` object 142b99622eSMatthew G. Knepley 152b99622eSMatthew G. Knepley Level: beginner 162b99622eSMatthew G. Knepley 1760225df5SJacob Faibussowitsch .seealso: `PetscFEGeom`, `PetscQuadrature`, `PetscFEGeomDestroy()`, `PetscFEGeomComplete()` 182b99622eSMatthew G. Knepley @*/ 19d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEGeomCreate(PetscQuadrature quad, PetscInt numCells, PetscInt dimEmbed, PetscBool faceData, PetscFEGeom **geom) 20d71ae5a4SJacob Faibussowitsch { 2120cf1dd8SToby Isaac PetscFEGeom *g; 227489efa5SMatthew G. Knepley PetscInt dim, Nq, N; 2320cf1dd8SToby Isaac const PetscReal *p; 2420cf1dd8SToby Isaac 2520cf1dd8SToby Isaac PetscFunctionBegin; 269566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, &dim, NULL, &Nq, &p, NULL)); 279566063dSJacob Faibussowitsch PetscCall(PetscNew(&g)); 2820cf1dd8SToby Isaac g->xi = p; 2920cf1dd8SToby Isaac g->numCells = numCells; 307489efa5SMatthew G. Knepley g->numPoints = Nq; 3120cf1dd8SToby Isaac g->dim = dim; 3220cf1dd8SToby Isaac g->dimEmbed = dimEmbed; 335fedec97SMatthew G. Knepley g->isCohesive = PETSC_FALSE; 347489efa5SMatthew G. Knepley N = numCells * Nq; 359566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(N * dimEmbed, &g->v, N * dimEmbed * dimEmbed, &g->J, N, &g->detJ)); 3620cf1dd8SToby Isaac if (faceData) { 379566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(numCells, &g->face, N * dimEmbed, &g->n)); 38*f4f49eeaSPierre Jolivet PetscCall(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])); 3920cf1dd8SToby Isaac } 409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(N * dimEmbed * dimEmbed, &g->invJ)); 4120cf1dd8SToby Isaac *geom = g; 423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4320cf1dd8SToby Isaac } 4420cf1dd8SToby Isaac 452b99622eSMatthew G. Knepley /*@C 46dce8aebaSBarry Smith PetscFEGeomDestroy - Destroy a `PetscFEGeom` object 472b99622eSMatthew G. Knepley 482b99622eSMatthew G. Knepley Input Parameter: 49dce8aebaSBarry Smith . geom - `PetscFEGeom` object 502b99622eSMatthew G. Knepley 512b99622eSMatthew G. Knepley Level: beginner 522b99622eSMatthew G. Knepley 53dce8aebaSBarry Smith .seealso: `PetscFEGeom`, `PetscFEGeomCreate()` 542b99622eSMatthew G. Knepley @*/ 55d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEGeomDestroy(PetscFEGeom **geom) 56d71ae5a4SJacob Faibussowitsch { 5720cf1dd8SToby Isaac PetscFunctionBegin; 583ba16761SJacob Faibussowitsch if (!*geom) PetscFunctionReturn(PETSC_SUCCESS); 599566063dSJacob Faibussowitsch PetscCall(PetscFree3((*geom)->v, (*geom)->J, (*geom)->detJ)); 609566063dSJacob Faibussowitsch PetscCall(PetscFree((*geom)->invJ)); 619566063dSJacob Faibussowitsch PetscCall(PetscFree2((*geom)->face, (*geom)->n)); 629566063dSJacob Faibussowitsch PetscCall(PetscFree6((*geom)->suppJ[0], (*geom)->suppJ[1], (*geom)->suppInvJ[0], (*geom)->suppInvJ[1], (*geom)->suppDetJ[0], (*geom)->suppDetJ[1])); 639566063dSJacob Faibussowitsch PetscCall(PetscFree(*geom)); 643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6520cf1dd8SToby Isaac } 6620cf1dd8SToby Isaac 672b99622eSMatthew G. Knepley /*@C 68dce8aebaSBarry Smith PetscFEGeomGetChunk - Get a chunk of cells in the group as a `PetscFEGeom` 692b99622eSMatthew G. Knepley 702b99622eSMatthew G. Knepley Input Parameters: 71dce8aebaSBarry Smith + geom - `PetscFEGeom` object 722b99622eSMatthew G. Knepley . cStart - The first cell in the chunk 732b99622eSMatthew G. Knepley - cEnd - The first cell not in the chunk 742b99622eSMatthew G. Knepley 752b99622eSMatthew G. Knepley Output Parameter: 762b99622eSMatthew G. Knepley . chunkGeom - The chunk of cells 772b99622eSMatthew G. Knepley 782b99622eSMatthew G. Knepley Level: intermediate 792b99622eSMatthew G. Knepley 80dce8aebaSBarry Smith Note: 81dce8aebaSBarry Smith Use `PetscFEGeomRestoreChunk()` to return the result 82dce8aebaSBarry Smith 83dce8aebaSBarry Smith .seealso: `PetscFEGeom`, `PetscFEGeomRestoreChunk()`, `PetscFEGeomCreate()` 842b99622eSMatthew G. Knepley @*/ 85d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEGeomGetChunk(PetscFEGeom *geom, PetscInt cStart, PetscInt cEnd, PetscFEGeom **chunkGeom) 86d71ae5a4SJacob Faibussowitsch { 8720cf1dd8SToby Isaac PetscInt Nq; 8820cf1dd8SToby Isaac PetscInt dE; 8920cf1dd8SToby Isaac 9020cf1dd8SToby Isaac PetscFunctionBegin; 914f572ea9SToby Isaac PetscAssertPointer(geom, 1); 924f572ea9SToby Isaac PetscAssertPointer(chunkGeom, 4); 9348a46eb9SPierre Jolivet if (!(*chunkGeom)) PetscCall(PetscNew(chunkGeom)); 9420cf1dd8SToby Isaac Nq = geom->numPoints; 9520cf1dd8SToby Isaac dE = geom->dimEmbed; 9620cf1dd8SToby Isaac (*chunkGeom)->dim = geom->dim; 9720cf1dd8SToby Isaac (*chunkGeom)->dimEmbed = geom->dimEmbed; 9820cf1dd8SToby Isaac (*chunkGeom)->numPoints = geom->numPoints; 9920cf1dd8SToby Isaac (*chunkGeom)->numCells = cEnd - cStart; 10020cf1dd8SToby Isaac (*chunkGeom)->xi = geom->xi; 1018e3a54c0SPierre Jolivet (*chunkGeom)->v = PetscSafePointerPlusOffset(geom->v, Nq * dE * cStart); 1028e3a54c0SPierre Jolivet (*chunkGeom)->J = PetscSafePointerPlusOffset(geom->J, Nq * dE * dE * cStart); 1038e3a54c0SPierre Jolivet (*chunkGeom)->invJ = PetscSafePointerPlusOffset(geom->invJ, Nq * dE * dE * cStart); 1048e3a54c0SPierre Jolivet (*chunkGeom)->detJ = PetscSafePointerPlusOffset(geom->detJ, Nq * cStart); 1058e3a54c0SPierre Jolivet (*chunkGeom)->n = PetscSafePointerPlusOffset(geom->n, Nq * dE * cStart); 1068e3a54c0SPierre Jolivet (*chunkGeom)->face = PetscSafePointerPlusOffset(geom->face, cStart); 1078e3a54c0SPierre Jolivet (*chunkGeom)->suppJ[0] = PetscSafePointerPlusOffset(geom->suppJ[0], Nq * dE * dE * cStart); 1088e3a54c0SPierre Jolivet (*chunkGeom)->suppJ[1] = PetscSafePointerPlusOffset(geom->suppJ[1], Nq * dE * dE * cStart); 1098e3a54c0SPierre Jolivet (*chunkGeom)->suppInvJ[0] = PetscSafePointerPlusOffset(geom->suppInvJ[0], Nq * dE * dE * cStart); 1108e3a54c0SPierre Jolivet (*chunkGeom)->suppInvJ[1] = PetscSafePointerPlusOffset(geom->suppInvJ[1], Nq * dE * dE * cStart); 1118e3a54c0SPierre Jolivet (*chunkGeom)->suppDetJ[0] = PetscSafePointerPlusOffset(geom->suppDetJ[0], Nq * cStart); 1128e3a54c0SPierre Jolivet (*chunkGeom)->suppDetJ[1] = PetscSafePointerPlusOffset(geom->suppDetJ[1], Nq * cStart); 11320cf1dd8SToby Isaac (*chunkGeom)->isAffine = geom->isAffine; 1143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11520cf1dd8SToby Isaac } 11620cf1dd8SToby Isaac 1172b99622eSMatthew G. Knepley /*@C 118dce8aebaSBarry Smith PetscFEGeomRestoreChunk - Restore the chunk obtained with `PetscFEGeomCreateChunk()` 1192b99622eSMatthew G. Knepley 1202b99622eSMatthew G. Knepley Input Parameters: 121dce8aebaSBarry Smith + geom - `PetscFEGeom` object 1222b99622eSMatthew G. Knepley . cStart - The first cell in the chunk 1232b99622eSMatthew G. Knepley . cEnd - The first cell not in the chunk 1242b99622eSMatthew G. Knepley - chunkGeom - The chunk of cells 1252b99622eSMatthew G. Knepley 1262b99622eSMatthew G. Knepley Level: intermediate 1272b99622eSMatthew G. Knepley 128dce8aebaSBarry Smith .seealso: `PetscFEGeom`, `PetscFEGeomGetChunk()`, `PetscFEGeomCreate()` 1292b99622eSMatthew G. Knepley @*/ 130d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEGeomRestoreChunk(PetscFEGeom *geom, PetscInt cStart, PetscInt cEnd, PetscFEGeom **chunkGeom) 131d71ae5a4SJacob Faibussowitsch { 13220cf1dd8SToby Isaac PetscFunctionBegin; 1339566063dSJacob Faibussowitsch PetscCall(PetscFree(*chunkGeom)); 1343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13520cf1dd8SToby Isaac } 13620cf1dd8SToby Isaac 1376587ee25SMatthew G. Knepley /*@C 138dce8aebaSBarry Smith PetscFEGeomGetPoint - Get the geometry for cell c at point p as a `PetscFEGeom` 1396587ee25SMatthew G. Knepley 1406587ee25SMatthew G. Knepley Input Parameters: 141dce8aebaSBarry Smith + geom - `PetscFEGeom` object 1426587ee25SMatthew G. Knepley . c - The cell 1436587ee25SMatthew G. Knepley . p - The point 1446587ee25SMatthew G. Knepley - pcoords - The reference coordinates of point p, or NULL 1456587ee25SMatthew G. Knepley 1466587ee25SMatthew G. Knepley Output Parameter: 1476587ee25SMatthew G. Knepley . pgeom - The geometry of cell c at point p 1486587ee25SMatthew G. Knepley 149dce8aebaSBarry Smith Level: intermediate 150dce8aebaSBarry Smith 151dce8aebaSBarry Smith Notes: 152dce8aebaSBarry Smith For affine geometries, this only copies to pgeom at point 0. Since we copy pointers into pgeom, 1536587ee25SMatthew G. Knepley nothing needs to be done with it afterwards. 1546587ee25SMatthew G. Knepley 1556587ee25SMatthew G. Knepley In the affine case, pgeom must have storage for the integration point coordinates in pgeom->v if pcoords is passed in. 1566587ee25SMatthew G. Knepley 157dce8aebaSBarry Smith .seealso: `PetscFEGeom`, `PetscFEGeomRestoreChunk()`, `PetscFEGeomCreate()` 1586587ee25SMatthew G. Knepley @*/ 159d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEGeomGetPoint(PetscFEGeom *geom, PetscInt c, PetscInt p, const PetscReal pcoords[], PetscFEGeom *pgeom) 160d71ae5a4SJacob Faibussowitsch { 1616587ee25SMatthew G. Knepley const PetscInt dim = geom->dim; 1626587ee25SMatthew G. Knepley const PetscInt dE = geom->dimEmbed; 1636587ee25SMatthew G. Knepley const PetscInt Np = geom->numPoints; 1646587ee25SMatthew G. Knepley 1656587ee25SMatthew G. Knepley PetscFunctionBeginHot; 1666587ee25SMatthew G. Knepley pgeom->dim = dim; 1676587ee25SMatthew G. Knepley pgeom->dimEmbed = dE; 1686587ee25SMatthew G. Knepley //pgeom->isAffine = geom->isAffine; 1696587ee25SMatthew G. Knepley if (geom->isAffine) { 1706587ee25SMatthew G. Knepley if (!p) { 1716587ee25SMatthew G. Knepley pgeom->xi = geom->xi; 1726587ee25SMatthew G. Knepley pgeom->J = &geom->J[c * Np * dE * dE]; 1736587ee25SMatthew G. Knepley pgeom->invJ = &geom->invJ[c * Np * dE * dE]; 1746587ee25SMatthew G. Knepley pgeom->detJ = &geom->detJ[c * Np]; 1758e3a54c0SPierre Jolivet pgeom->n = PetscSafePointerPlusOffset(geom->n, c * Np * dE); 1766587ee25SMatthew G. Knepley } 177ad540459SPierre Jolivet if (pcoords) CoordinatesRefToReal(dE, dim, pgeom->xi, &geom->v[c * Np * dE], pgeom->J, pcoords, pgeom->v); 1786587ee25SMatthew G. Knepley } else { 1796587ee25SMatthew G. Knepley pgeom->v = &geom->v[(c * Np + p) * dE]; 1806587ee25SMatthew G. Knepley pgeom->J = &geom->J[(c * Np + p) * dE * dE]; 1816587ee25SMatthew G. Knepley pgeom->invJ = &geom->invJ[(c * Np + p) * dE * dE]; 1826587ee25SMatthew G. Knepley pgeom->detJ = &geom->detJ[c * Np + p]; 1838e3a54c0SPierre Jolivet pgeom->n = PetscSafePointerPlusOffset(geom->n, (c * Np + p) * dE); 1846587ee25SMatthew G. Knepley } 1853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1866587ee25SMatthew G. Knepley } 1876587ee25SMatthew G. Knepley 1886587ee25SMatthew G. Knepley /*@C 189dce8aebaSBarry Smith PetscFEGeomGetCellPoint - Get the cell geometry for face f at point p as a `PetscFEGeom` 1906587ee25SMatthew G. Knepley 1916587ee25SMatthew G. Knepley Input Parameters: 192dce8aebaSBarry Smith + geom - `PetscFEGeom` object 19360225df5SJacob Faibussowitsch . c - The face 1946587ee25SMatthew G. Knepley - p - The point 1956587ee25SMatthew G. Knepley 1966587ee25SMatthew G. Knepley Output Parameter: 1976587ee25SMatthew G. Knepley . pgeom - The cell geometry of face f at point p 1986587ee25SMatthew G. Knepley 1996587ee25SMatthew G. Knepley Level: intermediate 2006587ee25SMatthew G. Knepley 201dce8aebaSBarry Smith Note: 202dce8aebaSBarry Smith For affine geometries, this only copies to pgeom at point 0. Since we copy pointers into pgeom, 203dce8aebaSBarry Smith nothing needs to be done with it afterwards. 204dce8aebaSBarry Smith 205dce8aebaSBarry Smith .seealso: `PetscFEGeom()`, `PetscFEGeomRestoreChunk()`, `PetscFEGeomCreate()` 2066587ee25SMatthew G. Knepley @*/ 207d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEGeomGetCellPoint(PetscFEGeom *geom, PetscInt c, PetscInt p, PetscFEGeom *pgeom) 208d71ae5a4SJacob Faibussowitsch { 2095fedec97SMatthew G. Knepley const PetscBool bd = geom->dimEmbed > geom->dim && !geom->isCohesive ? PETSC_TRUE : PETSC_FALSE; 2106587ee25SMatthew G. Knepley const PetscInt dim = bd ? geom->dimEmbed : geom->dim; 2116587ee25SMatthew G. Knepley const PetscInt dE = geom->dimEmbed; 2126587ee25SMatthew G. Knepley const PetscInt Np = geom->numPoints; 2136587ee25SMatthew G. Knepley 2146587ee25SMatthew G. Knepley PetscFunctionBeginHot; 2156587ee25SMatthew G. Knepley pgeom->dim = dim; 2166587ee25SMatthew G. Knepley pgeom->dimEmbed = dE; 2176587ee25SMatthew G. Knepley //pgeom->isAffine = geom->isAffine; 2186587ee25SMatthew G. Knepley if (geom->isAffine) { 2196587ee25SMatthew G. Knepley if (!p) { 2206587ee25SMatthew G. Knepley if (bd) { 2216587ee25SMatthew G. Knepley pgeom->J = &geom->suppJ[0][c * Np * dE * dE]; 2226587ee25SMatthew G. Knepley pgeom->invJ = &geom->suppInvJ[0][c * Np * dE * dE]; 2236587ee25SMatthew G. Knepley pgeom->detJ = &geom->suppDetJ[0][c * Np]; 2246587ee25SMatthew G. Knepley } else { 2256587ee25SMatthew G. Knepley pgeom->J = &geom->J[c * Np * dE * dE]; 2266587ee25SMatthew G. Knepley pgeom->invJ = &geom->invJ[c * Np * dE * dE]; 2276587ee25SMatthew G. Knepley pgeom->detJ = &geom->detJ[c * Np]; 2286587ee25SMatthew G. Knepley } 2296587ee25SMatthew G. Knepley } 2306587ee25SMatthew G. Knepley } else { 2316587ee25SMatthew G. Knepley if (bd) { 2326587ee25SMatthew G. Knepley pgeom->J = &geom->suppJ[0][(c * Np + p) * dE * dE]; 2336587ee25SMatthew G. Knepley pgeom->invJ = &geom->suppInvJ[0][(c * Np + p) * dE * dE]; 2346587ee25SMatthew G. Knepley pgeom->detJ = &geom->suppDetJ[0][c * Np + p]; 2356587ee25SMatthew G. Knepley } else { 2366587ee25SMatthew G. Knepley pgeom->J = &geom->J[(c * Np + p) * dE * dE]; 2376587ee25SMatthew G. Knepley pgeom->invJ = &geom->invJ[(c * Np + p) * dE * dE]; 2386587ee25SMatthew G. Knepley pgeom->detJ = &geom->detJ[c * Np + p]; 2396587ee25SMatthew G. Knepley } 2406587ee25SMatthew G. Knepley } 2413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2426587ee25SMatthew G. Knepley } 2436587ee25SMatthew G. Knepley 2442b99622eSMatthew G. Knepley /*@ 245dce8aebaSBarry Smith PetscFEGeomComplete - Calculate derived quantities from base geometry specification 2462b99622eSMatthew G. Knepley 2472b99622eSMatthew G. Knepley Input Parameter: 248dce8aebaSBarry Smith . geom - `PetscFEGeom` object 2492b99622eSMatthew G. Knepley 2502b99622eSMatthew G. Knepley Level: intermediate 2512b99622eSMatthew G. Knepley 252dce8aebaSBarry Smith .seealso: `PetscFEGeom`, `PetscFEGeomCreate()` 2532b99622eSMatthew G. Knepley @*/ 254d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEGeomComplete(PetscFEGeom *geom) 255d71ae5a4SJacob Faibussowitsch { 25620cf1dd8SToby Isaac PetscInt i, j, N, dE; 25720cf1dd8SToby Isaac 25820cf1dd8SToby Isaac PetscFunctionBeginHot; 25920cf1dd8SToby Isaac N = geom->numPoints * geom->numCells; 26020cf1dd8SToby Isaac dE = geom->dimEmbed; 26120cf1dd8SToby Isaac switch (dE) { 26220cf1dd8SToby Isaac case 3: 26320cf1dd8SToby Isaac for (i = 0; i < N; i++) { 26420cf1dd8SToby Isaac DMPlex_Det3D_Internal(&geom->detJ[i], &geom->J[dE * dE * i]); 26520cf1dd8SToby Isaac if (geom->invJ) DMPlex_Invert3D_Internal(&geom->invJ[dE * dE * i], &geom->J[dE * dE * i], geom->detJ[i]); 26620cf1dd8SToby Isaac } 26720cf1dd8SToby Isaac break; 26820cf1dd8SToby Isaac case 2: 26920cf1dd8SToby Isaac for (i = 0; i < N; i++) { 27020cf1dd8SToby Isaac DMPlex_Det2D_Internal(&geom->detJ[i], &geom->J[dE * dE * i]); 27120cf1dd8SToby Isaac if (geom->invJ) DMPlex_Invert2D_Internal(&geom->invJ[dE * dE * i], &geom->J[dE * dE * i], geom->detJ[i]); 27220cf1dd8SToby Isaac } 27320cf1dd8SToby Isaac break; 27420cf1dd8SToby Isaac case 1: 27520cf1dd8SToby Isaac for (i = 0; i < N; i++) { 27620cf1dd8SToby Isaac geom->detJ[i] = PetscAbsReal(geom->J[i]); 27720cf1dd8SToby Isaac if (geom->invJ) geom->invJ[i] = 1. / geom->J[i]; 27820cf1dd8SToby Isaac } 27920cf1dd8SToby Isaac break; 28020cf1dd8SToby Isaac } 28120cf1dd8SToby Isaac if (geom->n) { 28220cf1dd8SToby Isaac for (i = 0; i < N; i++) { 283ad540459SPierre Jolivet for (j = 0; j < dE; j++) geom->n[dE * i + j] = geom->J[dE * dE * i + dE * j + dE - 1] * ((dE == 2) ? -1. : 1.); 28420cf1dd8SToby Isaac } 28520cf1dd8SToby Isaac } 2863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28720cf1dd8SToby Isaac } 288