15552b385SBrandon #include "petscsys.h"
2a8ededdfSMatthew G. Knepley #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/
37bee2925SMatthew Knepley #include <petsc/private/hashmapi.h>
4a8ededdfSMatthew G. Knepley
5337bb527SBarry Smith /* We need to understand how to natively parse STEP files. There seems to be only one open-source implementation of
6a8ededdfSMatthew G. Knepley the STEP parser contained in the OpenCASCADE package. It is enough to make a strong man weep:
7a8ededdfSMatthew G. Knepley
8a8ededdfSMatthew G. Knepley https://github.com/tpaviot/oce/tree/master/src/STEPControl
9a8ededdfSMatthew G. Knepley
10a8ededdfSMatthew G. Knepley The STEP, and inner EXPRESS, formats are ISO standards, so they are documented
11a8ededdfSMatthew G. Knepley
12a8ededdfSMatthew G. Knepley https://stackoverflow.com/questions/26774037/documentation-or-specification-for-step-and-stp-files
13a8ededdfSMatthew G. Knepley http://stepmod.sourceforge.net/express_model_spec/
14a8ededdfSMatthew G. Knepley
15a8ededdfSMatthew G. Knepley but again it seems that there has been a deliberate effort at obfuscation, probably to raise the bar for entrants.
16a8ededdfSMatthew G. Knepley */
17a8ededdfSMatthew G. Knepley
18c1cad2e7SMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
195552b385SBrandon #include <petscdmplexegads.h>
20c1cad2e7SMatthew G. Knepley
215552b385SBrandon PETSC_INTERN PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM, PetscInt, ego, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscScalar[], PetscBool);
225552b385SBrandon PETSC_INTERN PetscErrorCode DMPlex_Geom_EDGE_XYZtoUV_Internal(const PetscScalar[], ego, const PetscScalar[], const PetscInt, const PetscInt, PetscScalar[], PetscBool);
235552b385SBrandon PETSC_INTERN PetscErrorCode DMPlex_Geom_FACE_XYZtoUV_Internal(const PetscScalar[], ego, const PetscScalar[], const PetscInt, const PetscInt, PetscScalar[], PetscBool);
245552b385SBrandon
DMPlex_EGADS_GeomDecode_Internal(const PetscInt geomClass,const PetscInt geomType,char ** retClass,char ** retType)255552b385SBrandon PetscErrorCode DMPlex_EGADS_GeomDecode_Internal(const PetscInt geomClass, const PetscInt geomType, char **retClass, char **retType)
26d71ae5a4SJacob Faibussowitsch {
275552b385SBrandon PetscFunctionBeginHot;
285552b385SBrandon /* EGADS Object Type */
29ac530a7eSPierre Jolivet if (geomClass == CONTXT) *retClass = (char *)"CONTEXT";
30ac530a7eSPierre Jolivet if (geomClass == TRANSFORM) *retClass = (char *)"TRANSFORM";
31ac530a7eSPierre Jolivet if (geomClass == TESSELLATION) *retClass = (char *)"TESSELLATION";
32ac530a7eSPierre Jolivet if (geomClass == NIL) *retClass = (char *)"NIL";
33ac530a7eSPierre Jolivet if (geomClass == EMPTY) *retClass = (char *)"EMPTY";
34ac530a7eSPierre Jolivet if (geomClass == REFERENCE) *retClass = (char *)"REFERENCE";
35ac530a7eSPierre Jolivet if (geomClass == PCURVE) *retClass = (char *)"PCURVE";
36ac530a7eSPierre Jolivet if (geomClass == CURVE) *retClass = (char *)"CURVE";
37ac530a7eSPierre Jolivet if (geomClass == SURFACE) *retClass = (char *)"SURFACE";
38ac530a7eSPierre Jolivet if (geomClass == NODE) *retClass = (char *)"NODE";
39ac530a7eSPierre Jolivet if (geomClass == EDGE) *retClass = (char *)"EDGE";
40ac530a7eSPierre Jolivet if (geomClass == LOOP) *retClass = (char *)"LOOP";
41ac530a7eSPierre Jolivet if (geomClass == FACE) *retClass = (char *)"FACE";
42ac530a7eSPierre Jolivet if (geomClass == SHELL) *retClass = (char *)"SHELL";
43ac530a7eSPierre Jolivet if (geomClass == BODY) *retClass = (char *)"BODY";
44ac530a7eSPierre Jolivet if (geomClass == MODEL) *retClass = (char *)"MODEL";
455552b385SBrandon
465552b385SBrandon /* PCURVES & CURVES */
475552b385SBrandon if (geomClass == PCURVE || geomClass == CURVE) {
48ac530a7eSPierre Jolivet if (geomType == LINE) *retType = (char *)"LINE";
49ac530a7eSPierre Jolivet if (geomType == CIRCLE) *retType = (char *)"CIRCLE";
50ac530a7eSPierre Jolivet if (geomType == ELLIPSE) *retType = (char *)"ELLIPSE";
51ac530a7eSPierre Jolivet if (geomType == PARABOLA) *retType = (char *)"PARABOLA";
52ac530a7eSPierre Jolivet if (geomType == HYPERBOLA) *retType = (char *)"HYPERBOLA";
53ac530a7eSPierre Jolivet if (geomType == TRIMMED) *retType = (char *)"TRIMMED";
54ac530a7eSPierre Jolivet if (geomType == BEZIER) *retType = (char *)"BEZIER";
55ac530a7eSPierre Jolivet if (geomType == BSPLINE) *retType = (char *)"BSPLINE";
56ac530a7eSPierre Jolivet if (geomType == OFFSET) *retType = (char *)"OFFSET";
575552b385SBrandon }
585552b385SBrandon
595552b385SBrandon /* SURFACE */
605552b385SBrandon if (geomClass == SURFACE) {
61ac530a7eSPierre Jolivet if (geomType == PLANE) *retType = (char *)"PLANE";
62ac530a7eSPierre Jolivet if (geomType == SPHERICAL) *retType = (char *)"SPHERICAL";
63ac530a7eSPierre Jolivet if (geomType == CYLINDRICAL) *retType = (char *)"CYLINDRICAL";
64ac530a7eSPierre Jolivet if (geomType == REVOLUTION) *retType = (char *)"REVOLUTION";
65ac530a7eSPierre Jolivet if (geomType == TOROIDAL) *retType = (char *)"TOROIDAL";
66ac530a7eSPierre Jolivet if (geomType == CONICAL) *retType = (char *)"CONICAL";
67ac530a7eSPierre Jolivet if (geomType == EXTRUSION) *retType = (char *)"EXTRUSION";
68ac530a7eSPierre Jolivet if (geomType == BEZIER) *retType = (char *)"BEZIER";
69ac530a7eSPierre Jolivet if (geomType == BSPLINE) *retType = (char *)"BSPLINE";
705552b385SBrandon }
715552b385SBrandon
725552b385SBrandon /* TOPOLOGY */
735552b385SBrandon if (geomClass == NODE || geomClass == EDGE || geomClass == LOOP || geomClass == FACE || geomClass == SHELL || geomClass == BODY || geomClass == MODEL) {
74ac530a7eSPierre Jolivet if (geomType == SREVERSE) *retType = (char *)"SREVERSE";
75ac530a7eSPierre Jolivet if (geomType == NOMTYPE) *retType = (char *)"NOMTYPE";
76ac530a7eSPierre Jolivet if (geomType == SFORWARD && geomClass == FACE) *retType = (char *)"SFORWARD";
77ac530a7eSPierre Jolivet if (geomType == ONENODE && geomClass == EDGE) *retType = (char *)"ONENODE";
78ac530a7eSPierre Jolivet if (geomType == TWONODE) *retType = (char *)"TWONODE";
79ac530a7eSPierre Jolivet if (geomType == OPEN) *retType = (char *)"OPEN";
80ac530a7eSPierre Jolivet if (geomType == CLOSED) *retType = (char *)"CLOSED";
81ac530a7eSPierre Jolivet if (geomType == DEGENERATE) *retType = (char *)"DEGENERATE";
82ac530a7eSPierre Jolivet if (geomType == WIREBODY) *retType = (char *)"WIREBODY";
83ac530a7eSPierre Jolivet if (geomType == FACEBODY) *retType = (char *)"FACEBODY";
84ac530a7eSPierre Jolivet if (geomType == SHEETBODY) *retType = (char *)"SHEETBODY";
85ac530a7eSPierre Jolivet if (geomType == SOLIDBODY) *retType = (char *)"SOLIDBODY";
865552b385SBrandon }
875552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
885552b385SBrandon }
895552b385SBrandon
DMPlex_EGADS_EDGE_XYZtoUV_Internal(const PetscScalar coords[],ego obj,const PetscScalar range[],const PetscInt v,const PetscInt dE,PetscScalar paramsV[])905552b385SBrandon PetscErrorCode DMPlex_EGADS_EDGE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[])
915552b385SBrandon {
925552b385SBrandon //
935552b385SBrandon //
945552b385SBrandon // Depreciated. Changed all references to DMPlex_Geom_FACE_XYZtoUV_Internal()
955552b385SBrandon //
965552b385SBrandon //
975552b385SBrandon
985552b385SBrandon PetscInt loopCntr = 0;
995552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, obj_old, obj_tmp, target;
1005552b385SBrandon PetscScalar delta, A, b;
1015552b385SBrandon PetscScalar ts[2], tt[2], eval[18], data[18];
1025552b385SBrandon
1035552b385SBrandon PetscFunctionBeginHot;
1045552b385SBrandon /* Initialize Levenberg-Marquardt parameters */
1055552b385SBrandon lambda = 1.0;
1065552b385SBrandon tolr = 1.0;
1075552b385SBrandon target = 1.0E-20;
1085552b385SBrandon ts[0] = (range[0] + range[1]) / 2.;
1095552b385SBrandon
1105552b385SBrandon while (tolr >= target) {
1115552b385SBrandon PetscCall(EG_evaluate(obj, ts, eval));
1125552b385SBrandon dx = coords[v * dE + 0] - eval[0];
1135552b385SBrandon dy = coords[v * dE + 1] - eval[1];
1145552b385SBrandon dz = coords[v * dE + 2] - eval[2];
1155552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz;
1165552b385SBrandon
1175552b385SBrandon if (obj_old < target) {
1185552b385SBrandon tolr = obj_old;
1195552b385SBrandon break;
1205552b385SBrandon }
1215552b385SBrandon
1225552b385SBrandon A = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda);
1235552b385SBrandon if (A == 0.0) {
1245552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "A = 0.0 \n"));
1255552b385SBrandon break;
1265552b385SBrandon }
1275552b385SBrandon b = eval[3] * dx + eval[4] * dy + eval[5] * dz;
1285552b385SBrandon
1295552b385SBrandon /* Solve A*delta = b */
1305552b385SBrandon delta = b / A;
1315552b385SBrandon
1325552b385SBrandon /* Find a temp (u,v) and associated objective function */
1335552b385SBrandon tt[0] = ts[0] + delta;
1345552b385SBrandon if (tt[0] < range[0]) {
1355552b385SBrandon tt[0] = range[0];
1365552b385SBrandon delta = tt[0] - ts[0];
1375552b385SBrandon }
1385552b385SBrandon if (tt[0] > range[1]) {
1395552b385SBrandon tt[0] = range[1];
1405552b385SBrandon delta = tt[0] - ts[0];
1415552b385SBrandon }
1425552b385SBrandon
1435552b385SBrandon PetscCall(EG_evaluate(obj, tt, data));
1445552b385SBrandon
1455552b385SBrandon obj_tmp = (coords[v * dE + 0] - data[0]) * (coords[v * dE + 0] - data[0]) + (coords[v * dE + 1] - data[1]) * (coords[v * dE + 1] - data[1]) + (coords[v * dE + 2] - data[2]) * (coords[v * dE + 2] - data[2]);
1465552b385SBrandon
1475552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */
1485552b385SBrandon if (obj_tmp < obj_old) {
1495552b385SBrandon obj_old = obj_tmp;
1505552b385SBrandon ts[0] = tt[0];
1515552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj];
1525552b385SBrandon lambda /= 2.0;
1535552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14;
1545552b385SBrandon if (obj_old < target) {
1555552b385SBrandon tolr = obj_old;
1565552b385SBrandon break;
1575552b385SBrandon }
1585552b385SBrandon } else {
1595552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */
1605552b385SBrandon lambda *= 2.0;
1615552b385SBrandon }
1625552b385SBrandon
1635552b385SBrandon if ((tt[0] == range[0]) || (tt[0] == range[1])) break;
1645552b385SBrandon if (fabs(delta) < target) {
1655552b385SBrandon tolr = obj_old;
1665552b385SBrandon break;
1675552b385SBrandon }
1685552b385SBrandon
1695552b385SBrandon tolr = obj_old;
1705552b385SBrandon
1715552b385SBrandon loopCntr += 1;
1725552b385SBrandon if (loopCntr > 100) break;
1735552b385SBrandon }
1745552b385SBrandon paramsV[v * 3 + 0] = ts[0];
1755552b385SBrandon paramsV[v * 3 + 1] = 0.;
1765552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
1775552b385SBrandon }
1785552b385SBrandon
DMPlex_Geom_EDGE_XYZtoUV_Internal(const PetscScalar coords[],ego obj,const PetscScalar range[],const PetscInt v,const PetscInt dE,PetscScalar paramsV[],PetscBool islite)1795552b385SBrandon PetscErrorCode DMPlex_Geom_EDGE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[], PetscBool islite)
1805552b385SBrandon {
1815552b385SBrandon PetscInt loopCntr = 0;
1825552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, obj_old, obj_tmp, target;
1835552b385SBrandon PetscScalar delta, A, b;
1845552b385SBrandon PetscScalar ts[2], tt[2], eval[18], data[18];
1855552b385SBrandon
1865552b385SBrandon PetscFunctionBeginHot;
1875552b385SBrandon /* Initialize Levenberg-Marquardt parameters */
1885552b385SBrandon lambda = 1.0;
1895552b385SBrandon tolr = 1.0;
1905552b385SBrandon target = 1.0E-20;
1915552b385SBrandon ts[0] = (range[0] + range[1]) / 2.;
1925552b385SBrandon
1935552b385SBrandon while (tolr >= target) {
1945552b385SBrandon if (islite) {
1955552b385SBrandon PetscCall(EGlite_evaluate(obj, ts, eval));
1965552b385SBrandon } else {
1975552b385SBrandon PetscCall(EG_evaluate(obj, ts, eval));
1985552b385SBrandon }
1995552b385SBrandon
2005552b385SBrandon dx = coords[v * dE + 0] - eval[0];
2015552b385SBrandon dy = coords[v * dE + 1] - eval[1];
2025552b385SBrandon dz = coords[v * dE + 2] - eval[2];
2035552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz;
2045552b385SBrandon
2055552b385SBrandon if (obj_old < target) {
2065552b385SBrandon tolr = obj_old;
2075552b385SBrandon break;
2085552b385SBrandon }
2095552b385SBrandon
2105552b385SBrandon A = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda);
2115552b385SBrandon if (A == 0.0) {
2125552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "A = 0.0 \n"));
2135552b385SBrandon break;
2145552b385SBrandon }
2155552b385SBrandon b = eval[3] * dx + eval[4] * dy + eval[5] * dz;
2165552b385SBrandon
2175552b385SBrandon /* Solve A*delta = b */
2185552b385SBrandon delta = b / A;
2195552b385SBrandon
2205552b385SBrandon /* Find a temp (u,v) and associated objective function */
2215552b385SBrandon tt[0] = ts[0] + delta;
2225552b385SBrandon if (tt[0] < range[0]) {
2235552b385SBrandon tt[0] = range[0];
2245552b385SBrandon delta = tt[0] - ts[0];
2255552b385SBrandon }
2265552b385SBrandon if (tt[0] > range[1]) {
2275552b385SBrandon tt[0] = range[1];
2285552b385SBrandon delta = tt[0] - ts[0];
2295552b385SBrandon }
2305552b385SBrandon
2315552b385SBrandon if (islite) {
2325552b385SBrandon PetscCall(EGlite_evaluate(obj, tt, data));
2335552b385SBrandon } else {
2345552b385SBrandon PetscCall(EG_evaluate(obj, tt, data));
2355552b385SBrandon }
2365552b385SBrandon
2375552b385SBrandon obj_tmp = (coords[v * dE + 0] - data[0]) * (coords[v * dE + 0] - data[0]) + (coords[v * dE + 1] - data[1]) * (coords[v * dE + 1] - data[1]) + (coords[v * dE + 2] - data[2]) * (coords[v * dE + 2] - data[2]);
2385552b385SBrandon
2395552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */
2405552b385SBrandon if (obj_tmp < obj_old) {
2415552b385SBrandon obj_old = obj_tmp;
2425552b385SBrandon ts[0] = tt[0];
2435552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj];
2445552b385SBrandon lambda /= 2.0;
2455552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14;
2465552b385SBrandon if (obj_old < target) {
2475552b385SBrandon tolr = obj_old;
2485552b385SBrandon break;
2495552b385SBrandon }
2505552b385SBrandon } else {
2515552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */
2525552b385SBrandon lambda *= 2.0;
2535552b385SBrandon }
2545552b385SBrandon
2555552b385SBrandon if ((tt[0] == range[0]) || (tt[0] == range[1])) break;
2565552b385SBrandon if (fabs(delta) < target) {
2575552b385SBrandon tolr = obj_old;
2585552b385SBrandon break;
2595552b385SBrandon }
2605552b385SBrandon
2615552b385SBrandon tolr = obj_old;
2625552b385SBrandon
2635552b385SBrandon loopCntr += 1;
2645552b385SBrandon if (loopCntr > 100) break;
2655552b385SBrandon }
2665552b385SBrandon paramsV[v * 3 + 0] = ts[0];
2675552b385SBrandon paramsV[v * 3 + 1] = 0.;
2685552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
2695552b385SBrandon }
2705552b385SBrandon
DMPlex_EGADS_FACE_XYZtoUV_Internal(const PetscScalar coords[],ego obj,const PetscScalar range[],const PetscInt v,const PetscInt dE,PetscScalar paramsV[])2715552b385SBrandon PetscErrorCode DMPlex_EGADS_FACE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[])
2725552b385SBrandon {
2735552b385SBrandon //
2745552b385SBrandon //
2755552b385SBrandon // Depreciated. Changed all references to DMPlex_Geom_FACE_XYZtoUV_Internal()
2765552b385SBrandon //
2775552b385SBrandon //
2785552b385SBrandon
2795552b385SBrandon PetscInt loopCntr = 0;
2805552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, denom, obj_old, obj_tmp, target;
2815552b385SBrandon PetscScalar uvs[2], uvt[2], delta[2], A[4], b[2], eval[18], data[18];
2825552b385SBrandon
2835552b385SBrandon PetscFunctionBeginHot;
2845552b385SBrandon /* Initialize Levenberg-Marquardt parameters */
2855552b385SBrandon lambda = 1.0;
2865552b385SBrandon tolr = 1.0;
2875552b385SBrandon target = 1.0E-20;
2885552b385SBrandon uvs[0] = (range[0] + range[1]) / 2.;
2895552b385SBrandon uvs[1] = (range[2] + range[3]) / 2.;
2905552b385SBrandon
2915552b385SBrandon while (tolr >= target) {
2925552b385SBrandon PetscCall(EG_evaluate(obj, uvs, eval));
2935552b385SBrandon dx = coords[v * dE + 0] - eval[0];
2945552b385SBrandon dy = coords[v * dE + 1] - eval[1];
2955552b385SBrandon dz = coords[v * dE + 2] - eval[2];
2965552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz;
2975552b385SBrandon
2985552b385SBrandon if (obj_old < target) {
2995552b385SBrandon tolr = obj_old;
3005552b385SBrandon break;
3015552b385SBrandon }
3025552b385SBrandon
3035552b385SBrandon A[0] = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda);
3045552b385SBrandon A[1] = eval[3] * eval[6] + eval[4] * eval[7] + eval[5] * eval[8];
3055552b385SBrandon A[2] = A[1];
3065552b385SBrandon A[3] = (eval[6] * eval[6] + eval[7] * eval[7] + eval[8] * eval[8]) * (1.0 + lambda);
3075552b385SBrandon
3085552b385SBrandon b[0] = eval[3] * dx + eval[4] * dy + eval[5] * dz;
3095552b385SBrandon b[1] = eval[6] * dx + eval[7] * dy + eval[8] * dz;
3105552b385SBrandon
3115552b385SBrandon /* Solve A*delta = b using Cramer's Rule */
3125552b385SBrandon denom = A[0] * A[3] - A[2] * A[1];
3133a7d0413SPierre Jolivet if (denom == 0.0) PetscCall(PetscPrintf(PETSC_COMM_SELF, "denom = 0.0 \n"));
3145552b385SBrandon delta[0] = (b[0] * A[3] - b[1] * A[1]) / denom;
3155552b385SBrandon delta[1] = (A[0] * b[1] - A[2] * b[0]) / denom;
3165552b385SBrandon
3175552b385SBrandon /* Find a temp (u,v) and associated objective function */
3185552b385SBrandon uvt[0] = uvs[0] + delta[0];
3195552b385SBrandon uvt[1] = uvs[1] + delta[1];
3205552b385SBrandon
3215552b385SBrandon if (uvt[0] < range[0]) {
3225552b385SBrandon uvt[0] = range[0];
3235552b385SBrandon delta[0] = uvt[0] - uvs[0];
3245552b385SBrandon }
3255552b385SBrandon if (uvt[0] > range[1]) {
3265552b385SBrandon uvt[0] = range[1];
3275552b385SBrandon delta[0] = uvt[0] - uvs[0];
3285552b385SBrandon }
3295552b385SBrandon if (uvt[1] < range[2]) {
3305552b385SBrandon uvt[1] = range[2];
3315552b385SBrandon delta[1] = uvt[1] - uvs[1];
3325552b385SBrandon }
3335552b385SBrandon if (uvt[1] > range[3]) {
3345552b385SBrandon uvt[1] = range[3];
3355552b385SBrandon delta[1] = uvt[1] - uvs[1];
3365552b385SBrandon }
3375552b385SBrandon
3385552b385SBrandon PetscCall(EG_evaluate(obj, uvt, data));
3395552b385SBrandon
3405552b385SBrandon obj_tmp = (coords[v * dE + 0] - data[0]) * (coords[v * dE + 0] - data[0]) + (coords[v * dE + 1] - data[1]) * (coords[v * dE + 1] - data[1]) + (coords[v * dE + 2] - data[2]) * (coords[v * dE + 2] - data[2]);
3415552b385SBrandon
3425552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */
3435552b385SBrandon if (obj_tmp < obj_old) {
3445552b385SBrandon obj_old = obj_tmp;
3455552b385SBrandon uvs[0] = uvt[0];
3465552b385SBrandon uvs[1] = uvt[1];
3475552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj];
3485552b385SBrandon lambda /= 2.0;
3495552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14;
3505552b385SBrandon if (obj_old < target) {
3515552b385SBrandon tolr = obj_old;
3525552b385SBrandon break;
3535552b385SBrandon }
3545552b385SBrandon } else {
3555552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */
3565552b385SBrandon lambda *= 2.0;
3575552b385SBrandon }
3585552b385SBrandon
3595552b385SBrandon if (sqrt(delta[0] * delta[0] + delta[1] * delta[1]) < target) {
3605552b385SBrandon tolr = obj_old;
3615552b385SBrandon break;
3625552b385SBrandon }
3635552b385SBrandon
3645552b385SBrandon tolr = obj_old;
3655552b385SBrandon
3665552b385SBrandon loopCntr += 1;
3675552b385SBrandon if (loopCntr > 100) break;
3685552b385SBrandon }
3695552b385SBrandon paramsV[v * 3 + 0] = uvs[0];
3705552b385SBrandon paramsV[v * 3 + 1] = uvs[1];
3715552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
3725552b385SBrandon }
3735552b385SBrandon
DMPlex_Geom_FACE_XYZtoUV_Internal(const PetscScalar coords[],ego obj,const PetscScalar range[],const PetscInt v,const PetscInt dE,PetscScalar paramsV[],PetscBool islite)3745552b385SBrandon PetscErrorCode DMPlex_Geom_FACE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[], PetscBool islite)
3755552b385SBrandon {
3765552b385SBrandon PetscInt loopCntr = 0;
3775552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, denom, obj_old, obj_tmp, target;
3785552b385SBrandon PetscScalar uvs[2], uvt[2], delta[2], A[4], b[2], eval[18], data[18];
3795552b385SBrandon
3805552b385SBrandon PetscFunctionBeginHot;
3815552b385SBrandon /* Initialize Levenberg-Marquardt parameters */
3825552b385SBrandon lambda = 1.0;
3835552b385SBrandon tolr = 1.0;
3845552b385SBrandon target = 1.0E-20;
3855552b385SBrandon uvs[0] = (range[0] + range[1]) / 2.;
3865552b385SBrandon uvs[1] = (range[2] + range[3]) / 2.;
3875552b385SBrandon
3885552b385SBrandon while (tolr >= target) {
3895552b385SBrandon if (islite) {
3905552b385SBrandon PetscCallEGADS(EGlite_evaluate, (obj, uvs, eval));
3915552b385SBrandon } else {
3925552b385SBrandon PetscCallEGADS(EG_evaluate, (obj, uvs, eval));
3935552b385SBrandon }
3945552b385SBrandon
3955552b385SBrandon dx = coords[v * dE + 0] - eval[0];
3965552b385SBrandon dy = coords[v * dE + 1] - eval[1];
3975552b385SBrandon dz = coords[v * dE + 2] - eval[2];
3985552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz;
3995552b385SBrandon
4005552b385SBrandon if (obj_old < target) {
4015552b385SBrandon tolr = obj_old;
4025552b385SBrandon break;
4035552b385SBrandon }
4045552b385SBrandon
4055552b385SBrandon A[0] = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda);
4065552b385SBrandon A[1] = eval[3] * eval[6] + eval[4] * eval[7] + eval[5] * eval[8];
4075552b385SBrandon A[2] = A[1];
4085552b385SBrandon A[3] = (eval[6] * eval[6] + eval[7] * eval[7] + eval[8] * eval[8]) * (1.0 + lambda);
4095552b385SBrandon
4105552b385SBrandon b[0] = eval[3] * dx + eval[4] * dy + eval[5] * dz;
4115552b385SBrandon b[1] = eval[6] * dx + eval[7] * dy + eval[8] * dz;
4125552b385SBrandon
4135552b385SBrandon /* Solve A*delta = b using Cramer's Rule */
4145552b385SBrandon denom = A[0] * A[3] - A[2] * A[1];
4153a7d0413SPierre Jolivet if (denom == 0.0) PetscCall(PetscPrintf(PETSC_COMM_SELF, "denom = 0.0 \n"));
4165552b385SBrandon delta[0] = (b[0] * A[3] - b[1] * A[1]) / denom;
4175552b385SBrandon delta[1] = (A[0] * b[1] - A[2] * b[0]) / denom;
4185552b385SBrandon
4195552b385SBrandon /* Find a temp (u,v) and associated objective function */
4205552b385SBrandon uvt[0] = uvs[0] + delta[0];
4215552b385SBrandon uvt[1] = uvs[1] + delta[1];
4225552b385SBrandon
4235552b385SBrandon if (uvt[0] < range[0]) {
4245552b385SBrandon uvt[0] = range[0];
4255552b385SBrandon delta[0] = uvt[0] - uvs[0];
4265552b385SBrandon }
4275552b385SBrandon if (uvt[0] > range[1]) {
4285552b385SBrandon uvt[0] = range[1];
4295552b385SBrandon delta[0] = uvt[0] - uvs[0];
4305552b385SBrandon }
4315552b385SBrandon if (uvt[1] < range[2]) {
4325552b385SBrandon uvt[1] = range[2];
4335552b385SBrandon delta[1] = uvt[1] - uvs[1];
4345552b385SBrandon }
4355552b385SBrandon if (uvt[1] > range[3]) {
4365552b385SBrandon uvt[1] = range[3];
4375552b385SBrandon delta[1] = uvt[1] - uvs[1];
4385552b385SBrandon }
4395552b385SBrandon
4405552b385SBrandon if (islite) {
4415552b385SBrandon PetscCall(EGlite_evaluate(obj, uvt, data));
4425552b385SBrandon } else {
4435552b385SBrandon PetscCall(EG_evaluate(obj, uvt, data));
4445552b385SBrandon }
4455552b385SBrandon
4465552b385SBrandon obj_tmp = (coords[v * dE + 0] - data[0]) * (coords[v * dE + 0] - data[0]) + (coords[v * dE + 1] - data[1]) * (coords[v * dE + 1] - data[1]) + (coords[v * dE + 2] - data[2]) * (coords[v * dE + 2] - data[2]);
4475552b385SBrandon
4485552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */
4495552b385SBrandon if (obj_tmp < obj_old) {
4505552b385SBrandon obj_old = obj_tmp;
4515552b385SBrandon uvs[0] = uvt[0];
4525552b385SBrandon uvs[1] = uvt[1];
4535552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj];
4545552b385SBrandon lambda /= 2.0;
4555552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14;
4565552b385SBrandon if (obj_old < target) {
4575552b385SBrandon tolr = obj_old;
4585552b385SBrandon break;
4595552b385SBrandon }
4605552b385SBrandon } else {
4615552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */
4625552b385SBrandon lambda *= 2.0;
4635552b385SBrandon }
4645552b385SBrandon
4655552b385SBrandon if (sqrt(delta[0] * delta[0] + delta[1] * delta[1]) < target) {
4665552b385SBrandon tolr = obj_old;
4675552b385SBrandon break;
4685552b385SBrandon }
4695552b385SBrandon
4705552b385SBrandon tolr = obj_old;
4715552b385SBrandon
4725552b385SBrandon loopCntr += 1;
4735552b385SBrandon if (loopCntr > 100) break;
4745552b385SBrandon }
4755552b385SBrandon paramsV[v * 3 + 0] = uvs[0];
4765552b385SBrandon paramsV[v * 3 + 1] = uvs[1];
4775552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
4785552b385SBrandon }
4795552b385SBrandon
DMSnapToGeomModel_EGADS_Internal(DM dm,PetscInt p,ego model,PetscInt bodyID,PetscInt faceID,PetscInt edgeID,const PetscScalar mcoords[],PetscScalar gcoords[],PetscBool islite)4805552b385SBrandon PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM dm, PetscInt p, ego model, PetscInt bodyID, PetscInt faceID, PetscInt edgeID, const PetscScalar mcoords[], PetscScalar gcoords[], PetscBool islite)
4815552b385SBrandon {
4825552b385SBrandon /* PETSc Variables */
483c1cad2e7SMatthew G. Knepley DM cdm;
484c1cad2e7SMatthew G. Knepley ego *bodies;
485c1cad2e7SMatthew G. Knepley ego geom, body, obj;
486bfe80ac4SPierre Jolivet /* result has to hold derivatives, along with the value */
4875552b385SBrandon double params[3], result[18], paramsV[16 * 3], range[4];
488c1cad2e7SMatthew G. Knepley int Nb, oclass, mtype, *senses, peri;
489c1cad2e7SMatthew G. Knepley Vec coordinatesLocal;
490c1cad2e7SMatthew G. Knepley PetscScalar *coords = NULL;
491c1cad2e7SMatthew G. Knepley PetscInt Nv, v, Np = 0, pm;
492c1cad2e7SMatthew G. Knepley PetscInt dE, d;
4935552b385SBrandon PetscReal pTolr = 1.0e-14;
494c1cad2e7SMatthew G. Knepley
495c1cad2e7SMatthew G. Knepley PetscFunctionBeginHot;
4969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm));
4979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE));
4989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
4995552b385SBrandon
5005552b385SBrandon if (islite) {
5015552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
5025552b385SBrandon } else {
5039566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
5045552b385SBrandon }
5055552b385SBrandon
5065552b385SBrandon PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bodyID, Nb);
507c1cad2e7SMatthew G. Knepley body = bodies[bodyID];
508c1cad2e7SMatthew G. Knepley
5099371c9d4SSatish Balay if (edgeID >= 0) {
5105552b385SBrandon if (islite) {
5115552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &obj));
5125552b385SBrandon Np = 1;
5135552b385SBrandon } else {
5149371c9d4SSatish Balay PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &obj));
5159371c9d4SSatish Balay Np = 1;
5165552b385SBrandon }
5179371c9d4SSatish Balay } else if (faceID >= 0) {
5185552b385SBrandon if (islite) {
5195552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &obj));
5205552b385SBrandon Np = 2;
5215552b385SBrandon } else {
5229371c9d4SSatish Balay PetscCall(EG_objectBodyTopo(body, FACE, faceID, &obj));
5239371c9d4SSatish Balay Np = 2;
5245552b385SBrandon }
5259371c9d4SSatish Balay } else {
526c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
5273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
528c1cad2e7SMatthew G. Knepley }
529c1cad2e7SMatthew G. Knepley
530c1cad2e7SMatthew G. Knepley /* Calculate parameters (t or u,v) for vertices */
5319566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords));
532c1cad2e7SMatthew G. Knepley Nv /= dE;
533c1cad2e7SMatthew G. Knepley if (Nv == 1) {
5349566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords));
535c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
5363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
537c1cad2e7SMatthew G. Knepley }
53863a3b9bcSJacob Faibussowitsch PetscCheck(Nv <= 16, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " coordinates associated to point %" PetscInt_FMT, Nv, p);
539c1cad2e7SMatthew G. Knepley
5405552b385SBrandon /* Correct EGADS/EGADSlite 2pi bug when calculating nearest point on Periodic Surfaces */
5415552b385SBrandon if (islite) {
5425552b385SBrandon PetscCall(EGlite_getRange(obj, range, &peri));
5435552b385SBrandon } else {
5449566063dSJacob Faibussowitsch PetscCall(EG_getRange(obj, range, &peri));
5455552b385SBrandon }
5465552b385SBrandon
547c1cad2e7SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
5485552b385SBrandon if (edgeID > 0) {
5495552b385SBrandon PetscCall(DMPlex_Geom_EDGE_XYZtoUV_Internal(coords, obj, range, v, dE, paramsV, islite));
5505552b385SBrandon } else {
5515552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, obj, range, v, dE, paramsV, islite));
5529371c9d4SSatish Balay }
553c1cad2e7SMatthew G. Knepley }
5549566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords));
5555552b385SBrandon
556c1cad2e7SMatthew G. Knepley /* Calculate parameters (t or u,v) for new vertex at edge midpoint */
557c1cad2e7SMatthew G. Knepley for (pm = 0; pm < Np; ++pm) {
558c1cad2e7SMatthew G. Knepley params[pm] = 0.;
559c1cad2e7SMatthew G. Knepley for (v = 0; v < Nv; ++v) params[pm] += paramsV[v * 3 + pm];
560c1cad2e7SMatthew G. Knepley params[pm] /= Nv;
561c1cad2e7SMatthew G. Knepley }
5625552b385SBrandon PetscCheck((params[0] + pTolr >= range[0]) || (params[0] - pTolr <= range[1]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " had bad interpolation", p);
5635552b385SBrandon PetscCheck(Np < 2 || ((params[1] + pTolr >= range[2]) || (params[1] - pTolr <= range[3])), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d had bad interpolation on v", p);
5645552b385SBrandon
565c1cad2e7SMatthew G. Knepley /* Put coordinates for new vertex in result[] */
5665552b385SBrandon if (islite) {
5675552b385SBrandon PetscCall(EGlite_evaluate(obj, params, result));
5685552b385SBrandon } else {
5699566063dSJacob Faibussowitsch PetscCall(EG_evaluate(obj, params, result));
5705552b385SBrandon }
5715552b385SBrandon
572c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = result[d];
5733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
574c1cad2e7SMatthew G. Knepley }
575c1cad2e7SMatthew G. Knepley #endif
576c1cad2e7SMatthew G. Knepley
DMSnapToGeomModel_EGADS(DM dm,PetscInt p,PetscInt dE,const PetscScalar mcoords[],PetscScalar gcoords[])5777625649eSMatthew G. Knepley PetscErrorCode DMSnapToGeomModel_EGADS(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[])
5787625649eSMatthew G. Knepley {
5797625649eSMatthew G. Knepley PetscFunctionBeginHot;
5807625649eSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
5817625649eSMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel;
5827625649eSMatthew G. Knepley PetscInt bodyID, faceID, edgeID;
5837625649eSMatthew G. Knepley PetscContainer modelObj;
5847625649eSMatthew G. Knepley ego model;
5855552b385SBrandon PetscBool islite = PETSC_FALSE;
5867625649eSMatthew G. Knepley
5875552b385SBrandon // FIXME: Change -dm_plex_refine_without_snap_to_geom to DM to shut off snapping
5887625649eSMatthew G. Knepley PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
5897625649eSMatthew G. Knepley PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
5907625649eSMatthew G. Knepley PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
5917625649eSMatthew G. Knepley PetscCheck(bodyLabel && faceLabel && edgeLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADS meshes must have body, face, and edge labels defined");
5927625649eSMatthew G. Knepley PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
5935552b385SBrandon if (!modelObj) {
5945552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
5955552b385SBrandon islite = PETSC_TRUE;
5965552b385SBrandon }
5977625649eSMatthew G. Knepley PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADS mesh missing model object");
5987625649eSMatthew G. Knepley
5992a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(modelObj, &model));
6007625649eSMatthew G. Knepley PetscCall(DMLabelGetValue(bodyLabel, p, &bodyID));
6017625649eSMatthew G. Knepley PetscCall(DMLabelGetValue(faceLabel, p, &faceID));
6027625649eSMatthew G. Knepley PetscCall(DMLabelGetValue(edgeLabel, p, &edgeID));
6037625649eSMatthew G. Knepley /* Allows for "Connective" Plex Edges present in models with multiple non-touching Entities */
6047625649eSMatthew G. Knepley if (bodyID < 0) {
6057625649eSMatthew G. Knepley for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
6067625649eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
6077625649eSMatthew G. Knepley }
6085552b385SBrandon PetscCall(DMSnapToGeomModel_EGADS_Internal(dm, p, model, bodyID, faceID, edgeID, mcoords, gcoords, islite));
609a8ededdfSMatthew G. Knepley #endif
6103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
611a8ededdfSMatthew G. Knepley }
6127bee2925SMatthew Knepley
6137bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
DMPlexGeomPrintModel_Internal(ego model,PetscBool islite)6145552b385SBrandon PetscErrorCode DMPlexGeomPrintModel_Internal(ego model, PetscBool islite)
615d71ae5a4SJacob Faibussowitsch {
6165552b385SBrandon /* PETSc Variables */
6175552b385SBrandon ego geom, *bodies, *nobjs, *mobjs, *lobjs, *shobjs, *fobjs, *eobjs;
6185552b385SBrandon int oclass, mtype, *senses, *shsenses, *fsenses, *lsenses, *esenses;
6197bee2925SMatthew Knepley int Nb, b;
6207bee2925SMatthew Knepley
6217bee2925SMatthew Knepley PetscFunctionBeginUser;
6227bee2925SMatthew Knepley /* test bodyTopo functions */
6235552b385SBrandon if (islite) {
6245552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
6255552b385SBrandon } else {
6269566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
6275552b385SBrandon }
6285552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of BODIES (nbodies): %" PetscInt_FMT " \n", Nb));
6297bee2925SMatthew Knepley
6307bee2925SMatthew Knepley for (b = 0; b < Nb; ++b) {
6317bee2925SMatthew Knepley ego body = bodies[b];
6325552b385SBrandon int id, sh, Nsh, f, Nf, l, Nl, e, Ne, v, Nv;
6335552b385SBrandon
6345552b385SBrandon /* List Topology of Bodies */
6355552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
6365552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " BODY %d TOPOLOGY SUMMARY \n", b));
6377bee2925SMatthew Knepley
6387bee2925SMatthew Knepley /* Output Basic Model Topology */
6395552b385SBrandon if (islite) {
6405552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, &Nsh, &shobjs));
6415552b385SBrandon } else {
6425552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, SHELL, &Nsh, &shobjs));
6435552b385SBrandon }
6449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of SHELLS: %d \n", Nsh));
6457bee2925SMatthew Knepley
6465552b385SBrandon if (islite) {
6475552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
6485552b385SBrandon } else {
6495552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
6505552b385SBrandon }
6519566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of FACES: %d \n", Nf));
6527bee2925SMatthew Knepley
6535552b385SBrandon if (islite) {
6545552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
6555552b385SBrandon } else {
6569566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
6575552b385SBrandon }
6589566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of LOOPS: %d \n", Nl));
6597bee2925SMatthew Knepley
6605552b385SBrandon if (islite) {
6615552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
6625552b385SBrandon } else {
6635552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
6645552b385SBrandon }
6659566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of EDGES: %d \n", Ne));
6667bee2925SMatthew Knepley
6675552b385SBrandon if (islite) {
6685552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
6695552b385SBrandon } else {
6705552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
6715552b385SBrandon }
6729566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of NODES: %d \n", Nv));
6735552b385SBrandon
6745552b385SBrandon if (islite) {
6755552b385SBrandon EGlite_free(shobjs);
6765552b385SBrandon EGlite_free(fobjs);
6775552b385SBrandon EGlite_free(lobjs);
6785552b385SBrandon EGlite_free(eobjs);
6795552b385SBrandon EGlite_free(nobjs);
6805552b385SBrandon } else {
6815552b385SBrandon EG_free(shobjs);
6825552b385SBrandon EG_free(fobjs);
6835552b385SBrandon EG_free(lobjs);
6845552b385SBrandon EG_free(eobjs);
6855552b385SBrandon EG_free(nobjs);
6865552b385SBrandon }
6875552b385SBrandon
6885552b385SBrandon /* List Topology of Bodies */
6895552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
6905552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " BODY %d TOPOLOGY DETAILS \n", b));
6915552b385SBrandon
6925552b385SBrandon /* Get SHELL info which associated with the current BODY */
6935552b385SBrandon if (islite) {
6945552b385SBrandon PetscCall(EGlite_getTopology(body, &geom, &oclass, &mtype, NULL, &Nsh, &shobjs, &shsenses));
6955552b385SBrandon } else {
6965552b385SBrandon PetscCall(EG_getTopology(body, &geom, &oclass, &mtype, NULL, &Nsh, &shobjs, &shsenses));
6975552b385SBrandon }
6985552b385SBrandon
6995552b385SBrandon for (sh = 0; sh < Nsh; ++sh) {
7005552b385SBrandon ego shell = shobjs[sh];
7015552b385SBrandon int shsense = shsenses[sh];
7025552b385SBrandon
7035552b385SBrandon if (islite) {
7045552b385SBrandon id = EGlite_indexBodyTopo(body, shell);
7055552b385SBrandon } else {
7065552b385SBrandon id = EG_indexBodyTopo(body, shell);
7075552b385SBrandon }
7085552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " SHELL ID: %d :: sense = %d\n", id, shsense));
7095552b385SBrandon
710bfe80ac4SPierre Jolivet /* Get FACE information associated with current SHELL */
7115552b385SBrandon if (islite) {
7125552b385SBrandon PetscCall(EGlite_getTopology(shell, &geom, &oclass, &mtype, NULL, &Nf, &fobjs, &fsenses));
7135552b385SBrandon } else {
7145552b385SBrandon PetscCall(EG_getTopology(shell, &geom, &oclass, &mtype, NULL, &Nf, &fobjs, &fsenses));
7155552b385SBrandon }
7165552b385SBrandon
7175552b385SBrandon for (f = 0; f < Nf; ++f) {
7185552b385SBrandon ego face = fobjs[f];
7195552b385SBrandon ego gRef, gPrev, gNext;
7205552b385SBrandon int goclass, gmtype, *gpinfo;
7215552b385SBrandon double *gprv;
7225552b385SBrandon char *gClass = (char *)"", *gType = (char *)"";
7235552b385SBrandon double fdata[4];
7245552b385SBrandon ego fRef, fPrev, fNext;
7255552b385SBrandon int foclass, fmtype;
7265552b385SBrandon
7275552b385SBrandon if (islite) {
7285552b385SBrandon id = EGlite_indexBodyTopo(body, face);
7295552b385SBrandon } else {
7305552b385SBrandon id = EG_indexBodyTopo(body, face);
7315552b385SBrandon }
7325552b385SBrandon
7335552b385SBrandon /* Get LOOP info associated with current FACE */
7345552b385SBrandon if (islite) {
7355552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, fdata, &Nl, &lobjs, &lsenses));
7365552b385SBrandon PetscCall(EGlite_getInfo(face, &foclass, &fmtype, &fRef, &fPrev, &fNext));
7375552b385SBrandon PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv));
7385552b385SBrandon PetscCall(EGlite_getInfo(geom, &goclass, &gmtype, &gRef, &gPrev, &gNext));
7395552b385SBrandon } else {
7405552b385SBrandon PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, fdata, &Nl, &lobjs, &lsenses));
7415552b385SBrandon PetscCall(EG_getInfo(face, &foclass, &fmtype, &fRef, &fPrev, &fNext));
7425552b385SBrandon PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv));
7435552b385SBrandon PetscCall(EG_getInfo(geom, &goclass, &gmtype, &gRef, &gPrev, &gNext));
7445552b385SBrandon }
7455552b385SBrandon
7465552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType));
7475552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " FACE ID: %d :: sense = %d \n", id, fmtype));
7485552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY CLASS: %s \n", gClass));
7495552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY TYPE: %s \n\n", gType));
7505552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " RANGE (umin, umax) = (%f, %f) \n", fdata[0], fdata[1]));
7515552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " (vmin, vmax) = (%f, %f) \n\n", fdata[2], fdata[3]));
7527bee2925SMatthew Knepley
7537bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) {
7547bee2925SMatthew Knepley ego loop = lobjs[l];
7555552b385SBrandon int lsense = lsenses[l];
7567bee2925SMatthew Knepley
7575552b385SBrandon if (islite) {
7585552b385SBrandon id = EGlite_indexBodyTopo(body, loop);
7595552b385SBrandon } else {
7607bee2925SMatthew Knepley id = EG_indexBodyTopo(body, loop);
7615552b385SBrandon }
7627bee2925SMatthew Knepley
7635552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP ID: %d :: sense = %d\n", id, lsense));
7645552b385SBrandon
7655552b385SBrandon /* Get EDGE info associated with the current LOOP */
7665552b385SBrandon if (islite) {
7675552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &esenses));
7685552b385SBrandon } else {
7695552b385SBrandon PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &esenses));
7705552b385SBrandon }
7717bee2925SMatthew Knepley
7727bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) {
7735552b385SBrandon ego edge = eobjs[e];
7745552b385SBrandon ego topRef, prev, next;
7755552b385SBrandon int esense = esenses[e];
7767bee2925SMatthew Knepley double range[4] = {0., 0., 0., 0.};
7777bee2925SMatthew Knepley int peri;
7785552b385SBrandon ego gEref, gEprev, gEnext;
7795552b385SBrandon int gEoclass, gEmtype;
7805552b385SBrandon char *gEclass = (char *)"", *gEtype = (char *)"";
7817bee2925SMatthew Knepley
7825552b385SBrandon if (islite) {
7835552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
7843a7d0413SPierre Jolivet if (mtype != DEGENERATE) PetscCall(EGlite_getInfo(geom, &gEoclass, &gEmtype, &gEref, &gEprev, &gEnext));
785266cfabeSMatthew G. Knepley } else {
7865552b385SBrandon PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
7875552b385SBrandon PetscCall(EG_getInfo(geom, &gEoclass, &gEmtype, &gEref, &gEprev, &gEnext));
7885552b385SBrandon }
7895552b385SBrandon
7903a7d0413SPierre Jolivet if (mtype != DEGENERATE) PetscCall(DMPlex_EGADS_GeomDecode_Internal(gEoclass, gEmtype, &gEclass, &gEtype));
7915552b385SBrandon
7925552b385SBrandon if (islite) {
7935552b385SBrandon id = EGlite_indexBodyTopo(body, edge);
7945552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
7955552b385SBrandon } else {
7965552b385SBrandon id = EG_indexBodyTopo(body, edge);
7975552b385SBrandon PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
7985552b385SBrandon }
7995552b385SBrandon
8005552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE ID: %d :: sense = %d\n", id, esense));
8015552b385SBrandon if (mtype != DEGENERATE) {
8025552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY CLASS: %s \n", gEclass));
8035552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY TYPE: %s \n", gEtype));
8045552b385SBrandon }
8055552b385SBrandon
8063a7d0413SPierre Jolivet if (mtype == DEGENERATE) PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE %d is DEGENERATE \n", id));
8075552b385SBrandon
8085552b385SBrandon if (islite) {
8095552b385SBrandon PetscCall(EGlite_getRange(edge, range, &peri));
8105552b385SBrandon } else {
8115552b385SBrandon PetscCall(EG_getRange(edge, range, &peri));
8125552b385SBrandon }
8135552b385SBrandon
8145552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " Peri = %d :: Range = %lf, %lf, %lf, %lf \n", peri, range[0], range[1], range[2], range[3]));
8155552b385SBrandon
8165552b385SBrandon /* Get NODE info associated with the current EDGE */
8175552b385SBrandon if (islite) {
8185552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
8195552b385SBrandon } else {
8205552b385SBrandon PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
821266cfabeSMatthew G. Knepley }
8227bee2925SMatthew Knepley
8237bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) {
8247bee2925SMatthew Knepley ego vertex = nobjs[v];
8257bee2925SMatthew Knepley double limits[4];
8262a8381b2SBarry Smith int unused;
8277bee2925SMatthew Knepley
8285552b385SBrandon if (islite) {
8292a8381b2SBarry Smith PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &unused, &mobjs, &senses));
8305552b385SBrandon id = EGlite_indexBodyTopo(body, vertex);
8315552b385SBrandon } else {
8322a8381b2SBarry Smith PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &unused, &mobjs, &senses));
8337bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex);
8345552b385SBrandon }
8359566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " NODE ID: %d \n", id));
8369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " (x, y, z) = (%lf, %lf, %lf) \n", limits[0], limits[1], limits[2]));
8377bee2925SMatthew Knepley }
8387bee2925SMatthew Knepley }
8397bee2925SMatthew Knepley }
8407bee2925SMatthew Knepley }
8415552b385SBrandon }
8425552b385SBrandon }
8435552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n\n"));
8443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8457bee2925SMatthew Knepley }
8467bee2925SMatthew Knepley
DMPlexEGADSDestroy_Private(PetscCtxRt context)8472a8381b2SBarry Smith static PetscErrorCode DMPlexEGADSDestroy_Private(PetscCtxRt context)
848d71ae5a4SJacob Faibussowitsch {
8492a8381b2SBarry Smith if (*(void **)context) EG_deleteObject((ego) * (void **)context);
850b6555650SPierre Jolivet return PETSC_SUCCESS;
8515552b385SBrandon }
8525552b385SBrandon
DMPlexEGADSClose_Private(PetscCtxRt context)8532a8381b2SBarry Smith static PetscErrorCode DMPlexEGADSClose_Private(PetscCtxRt context)
8545552b385SBrandon {
8552a8381b2SBarry Smith if (*(void **)context) EG_close((ego) * (void **)context);
856b6555650SPierre Jolivet return PETSC_SUCCESS;
8575552b385SBrandon }
8585552b385SBrandon
DMPlexEGADSliteDestroy_Private(PetscCtxRt context)8592a8381b2SBarry Smith PetscErrorCode DMPlexEGADSliteDestroy_Private(PetscCtxRt context)
8605552b385SBrandon {
8612a8381b2SBarry Smith if (*(void **)context) EGlite_deleteObject((ego) * (void **)context);
862b6555650SPierre Jolivet return PETSC_SUCCESS;
8637bee2925SMatthew Knepley }
8647bee2925SMatthew Knepley
DMPlexEGADSliteClose_Private(PetscCtxRt context)8652a8381b2SBarry Smith PetscErrorCode DMPlexEGADSliteClose_Private(PetscCtxRt context)
866d71ae5a4SJacob Faibussowitsch {
8672a8381b2SBarry Smith if (*(void **)context) EGlite_close((ego) * (void **)context);
868b6555650SPierre Jolivet return PETSC_SUCCESS;
8695552b385SBrandon }
8705552b385SBrandon
DMPlexCreateGeom_Internal(MPI_Comm comm,ego context,ego model,DM * newdm,PetscBool islite)8715552b385SBrandon PetscErrorCode DMPlexCreateGeom_Internal(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite)
8725552b385SBrandon {
8735552b385SBrandon /* EGADS variables */
8747bee2925SMatthew Knepley ego geom, *bodies, *objs, *nobjs, *mobjs, *lobjs;
8757bee2925SMatthew Knepley int oclass, mtype, nbodies, *senses;
8767bee2925SMatthew Knepley int b;
8777bee2925SMatthew Knepley /* PETSc variables */
8787bee2925SMatthew Knepley DM dm;
8795552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
8807bee2925SMatthew Knepley PetscHMapI edgeMap = NULL;
8815552b385SBrandon PetscInt cStart, cEnd, c;
8827bee2925SMatthew Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, maxCorners = 0, numVertices = 0, newVertices = 0, numEdges = 0, numCells = 0, newCells = 0, numQuads = 0, cOff = 0, fOff = 0;
8837bee2925SMatthew Knepley PetscInt *cells = NULL, *cone = NULL;
8847bee2925SMatthew Knepley PetscReal *coords = NULL;
8857bee2925SMatthew Knepley PetscMPIInt rank;
8867bee2925SMatthew Knepley
8877bee2925SMatthew Knepley PetscFunctionBegin;
8889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
889dd400576SPatrick Sanan if (rank == 0) {
890266cfabeSMatthew G. Knepley const PetscInt debug = 0;
891266cfabeSMatthew G. Knepley
892*21789920SBarry Smith /*
893f0b74427SPierre Jolivet Generate PETSc DMPlex
8947bee2925SMatthew Knepley Get all Nodes in model, record coordinates in a correctly formatted array
8957bee2925SMatthew Knepley Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array
8967bee2925SMatthew Knepley We need to uniformly refine the initial geometry to guarantee a valid mesh
8977bee2925SMatthew Knepley */
8987bee2925SMatthew Knepley
8997bee2925SMatthew Knepley /* Calculate cell and vertex sizes */
9005552b385SBrandon if (islite) {
9015552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
9025552b385SBrandon } else {
9039566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
9045552b385SBrandon }
9055552b385SBrandon
9069566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&edgeMap));
9077bee2925SMatthew Knepley numEdges = 0;
9087bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) {
9097bee2925SMatthew Knepley ego body = bodies[b];
9107bee2925SMatthew Knepley int id, Nl, l, Nv, v;
9117bee2925SMatthew Knepley
9125552b385SBrandon if (islite) {
9135552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
9145552b385SBrandon } else {
9159566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
9165552b385SBrandon }
9175552b385SBrandon
9187bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) {
9197bee2925SMatthew Knepley ego loop = lobjs[l];
9207bee2925SMatthew Knepley int Ner = 0, Ne, e, Nc;
9217bee2925SMatthew Knepley
9225552b385SBrandon if (islite) {
9235552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
9245552b385SBrandon } else {
9259566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
9265552b385SBrandon }
9275552b385SBrandon
9287bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) {
9297bee2925SMatthew Knepley ego edge = objs[e];
9307bee2925SMatthew Knepley int Nv, id;
9317bee2925SMatthew Knepley PetscHashIter iter;
9327bee2925SMatthew Knepley PetscBool found;
9337bee2925SMatthew Knepley
9345552b385SBrandon if (islite) {
9355552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
9365552b385SBrandon } else {
9379566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
9385552b385SBrandon }
9395552b385SBrandon
9407bee2925SMatthew Knepley if (mtype == DEGENERATE) continue;
9415552b385SBrandon
9425552b385SBrandon if (islite) {
9435552b385SBrandon id = EGlite_indexBodyTopo(body, edge);
9445552b385SBrandon } else {
9455f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, edge);
9465552b385SBrandon }
9475552b385SBrandon
9489566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, id - 1, &iter, &found));
9493a7d0413SPierre Jolivet if (!found) PetscCall(PetscHMapISet(edgeMap, id - 1, numEdges++));
9507bee2925SMatthew Knepley ++Ner;
9517bee2925SMatthew Knepley }
9529371c9d4SSatish Balay if (Ner == 2) {
9539371c9d4SSatish Balay Nc = 2;
9549371c9d4SSatish Balay } else if (Ner == 3) {
9559371c9d4SSatish Balay Nc = 4;
9569371c9d4SSatish Balay } else if (Ner == 4) {
9579371c9d4SSatish Balay Nc = 8;
9589371c9d4SSatish Balay ++numQuads;
9599371c9d4SSatish Balay } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot support loop with %d edges", Ner);
9607bee2925SMatthew Knepley numCells += Nc;
9617bee2925SMatthew Knepley newCells += Nc - 1;
9627bee2925SMatthew Knepley maxCorners = PetscMax(Ner * 2 + 1, maxCorners);
9637bee2925SMatthew Knepley }
9645552b385SBrandon if (islite) {
9655552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
9665552b385SBrandon } else {
9679566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
9685552b385SBrandon }
9695552b385SBrandon
9707bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) {
9717bee2925SMatthew Knepley ego vertex = nobjs[v];
9727bee2925SMatthew Knepley
9735552b385SBrandon if (islite) {
9745552b385SBrandon id = EGlite_indexBodyTopo(body, vertex);
9755552b385SBrandon } else {
9767bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex);
9775552b385SBrandon }
9787bee2925SMatthew Knepley /* TODO: Instead of assuming contiguous ids, we could use a hash table */
9797bee2925SMatthew Knepley numVertices = PetscMax(id, numVertices);
9807bee2925SMatthew Knepley }
9815552b385SBrandon if (islite) {
9825552b385SBrandon EGlite_free(lobjs);
9835552b385SBrandon EGlite_free(nobjs);
9845552b385SBrandon } else {
9857bee2925SMatthew Knepley EG_free(lobjs);
9867bee2925SMatthew Knepley EG_free(nobjs);
9877bee2925SMatthew Knepley }
9885552b385SBrandon }
9899566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(edgeMap, &numEdges));
9907bee2925SMatthew Knepley newVertices = numEdges + numQuads;
9917bee2925SMatthew Knepley numVertices += newVertices;
9927bee2925SMatthew Knepley
9937bee2925SMatthew Knepley dim = 2; /* Assume 3D Models :: Need to update to handle 2D Models in the future */
9947bee2925SMatthew Knepley cdim = 3; /* Assume 3D Models :: Need to update to handle 2D Models in the future */
9957bee2925SMatthew Knepley numCorners = 3; /* Split cells into triangles */
9969566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(numVertices * cdim, &coords, numCells * numCorners, &cells, maxCorners, &cone));
9977bee2925SMatthew Knepley
9987bee2925SMatthew Knepley /* Get vertex coordinates */
9997bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) {
10007bee2925SMatthew Knepley ego body = bodies[b];
10017bee2925SMatthew Knepley int id, Nv, v;
10027bee2925SMatthew Knepley
10035552b385SBrandon if (islite) {
10045552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
10055552b385SBrandon } else {
10069566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
10075552b385SBrandon }
10085552b385SBrandon
10097bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) {
10107bee2925SMatthew Knepley ego vertex = nobjs[v];
10117bee2925SMatthew Knepley double limits[4];
10122a8381b2SBarry Smith int unused;
10137bee2925SMatthew Knepley
10145552b385SBrandon if (islite) {
10152a8381b2SBarry Smith PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &unused, &mobjs, &senses));
10165552b385SBrandon id = EGlite_indexBodyTopo(body, vertex);
10175552b385SBrandon } else {
10182a8381b2SBarry Smith PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &unused, &mobjs, &senses));
10195f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, vertex);
10205552b385SBrandon }
10215552b385SBrandon
10227bee2925SMatthew Knepley coords[(id - 1) * cdim + 0] = limits[0];
10237bee2925SMatthew Knepley coords[(id - 1) * cdim + 1] = limits[1];
10247bee2925SMatthew Knepley coords[(id - 1) * cdim + 2] = limits[2];
10257bee2925SMatthew Knepley }
10265552b385SBrandon if (islite) {
10275552b385SBrandon EGlite_free(nobjs);
10285552b385SBrandon } else {
10297bee2925SMatthew Knepley EG_free(nobjs);
10307bee2925SMatthew Knepley }
10315552b385SBrandon }
10329566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(edgeMap));
10337bee2925SMatthew Knepley fOff = numVertices - newVertices + numEdges;
10347bee2925SMatthew Knepley numEdges = 0;
10357bee2925SMatthew Knepley numQuads = 0;
10367bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) {
10377bee2925SMatthew Knepley ego body = bodies[b];
10387bee2925SMatthew Knepley int Nl, l;
10397bee2925SMatthew Knepley
10405552b385SBrandon if (islite) {
10415552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
10425552b385SBrandon } else {
10439566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
10445552b385SBrandon }
10455552b385SBrandon
10467bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) {
10477bee2925SMatthew Knepley ego loop = lobjs[l];
10487bee2925SMatthew Knepley int lid, Ner = 0, Ne, e;
10497bee2925SMatthew Knepley
10505552b385SBrandon if (islite) {
10515552b385SBrandon lid = EGlite_indexBodyTopo(body, loop);
10525552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
10535552b385SBrandon } else {
10545f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop);
10559566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
10565552b385SBrandon }
10575552b385SBrandon
10587bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) {
10597bee2925SMatthew Knepley ego edge = objs[e];
10607bee2925SMatthew Knepley int eid, Nv;
10617bee2925SMatthew Knepley PetscHashIter iter;
10627bee2925SMatthew Knepley PetscBool found;
10637bee2925SMatthew Knepley
10645552b385SBrandon if (islite) {
10655552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
10665552b385SBrandon } else {
10679566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
10685552b385SBrandon }
10695552b385SBrandon
10707bee2925SMatthew Knepley if (mtype == DEGENERATE) continue;
10717bee2925SMatthew Knepley ++Ner;
10725552b385SBrandon
10735552b385SBrandon if (islite) {
10745552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
10755552b385SBrandon } else {
10765f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge);
10775552b385SBrandon }
10785552b385SBrandon
10799566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, eid - 1, &iter, &found));
10807bee2925SMatthew Knepley if (!found) {
10817bee2925SMatthew Knepley PetscInt v = numVertices - newVertices + numEdges;
10827bee2925SMatthew Knepley double range[4], params[3] = {0., 0., 0.}, result[18];
10837bee2925SMatthew Knepley int periodic[2];
10847bee2925SMatthew Knepley
10859566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(edgeMap, eid - 1, numEdges++));
10865552b385SBrandon
10875552b385SBrandon if (islite) {
10885552b385SBrandon PetscCall(EGlite_getRange(edge, range, periodic));
10895552b385SBrandon } else {
10909566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, periodic));
10915552b385SBrandon }
10925552b385SBrandon
10937bee2925SMatthew Knepley params[0] = 0.5 * (range[0] + range[1]);
10945552b385SBrandon if (islite) {
10955552b385SBrandon PetscCall(EGlite_evaluate(edge, params, result));
10965552b385SBrandon } else {
10979566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, params, result));
10985552b385SBrandon }
10997bee2925SMatthew Knepley coords[v * cdim + 0] = result[0];
11007bee2925SMatthew Knepley coords[v * cdim + 1] = result[1];
11017bee2925SMatthew Knepley coords[v * cdim + 2] = result[2];
11027bee2925SMatthew Knepley }
11037bee2925SMatthew Knepley }
11047bee2925SMatthew Knepley if (Ner == 4) {
11057bee2925SMatthew Knepley PetscInt v = fOff + numQuads++;
1106266cfabeSMatthew G. Knepley ego *fobjs, face;
11077bee2925SMatthew Knepley double range[4], params[3] = {0., 0., 0.}, result[18];
1108266cfabeSMatthew G. Knepley int Nf, fid, periodic[2];
11097bee2925SMatthew Knepley
11105552b385SBrandon if (islite) {
11115552b385SBrandon PetscCall(EGlite_getBodyTopos(body, loop, FACE, &Nf, &fobjs));
11125552b385SBrandon } else {
11139566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs));
11145552b385SBrandon }
1115266cfabeSMatthew G. Knepley face = fobjs[0];
11165552b385SBrandon
11175552b385SBrandon if (islite) {
11185552b385SBrandon fid = EGlite_indexBodyTopo(body, face);
11195552b385SBrandon } else {
11205f80ce2aSJacob Faibussowitsch fid = EG_indexBodyTopo(body, face);
11215552b385SBrandon }
11225552b385SBrandon
11235552b385SBrandon PetscCheck(Nf != 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Loop %d has %" PetscInt_FMT " faces, instead of 1 (%" PetscInt_FMT ")", lid - 1, Nf, fid);
11245552b385SBrandon if (islite) {
11255552b385SBrandon PetscCall(EGlite_getRange(face, range, periodic));
11265552b385SBrandon } else {
11279566063dSJacob Faibussowitsch PetscCall(EG_getRange(face, range, periodic));
11285552b385SBrandon }
11297bee2925SMatthew Knepley params[0] = 0.5 * (range[0] + range[1]);
11307bee2925SMatthew Knepley params[1] = 0.5 * (range[2] + range[3]);
11315552b385SBrandon if (islite) {
11325552b385SBrandon PetscCall(EGlite_evaluate(face, params, result));
11335552b385SBrandon } else {
11349566063dSJacob Faibussowitsch PetscCall(EG_evaluate(face, params, result));
11355552b385SBrandon }
11367bee2925SMatthew Knepley coords[v * cdim + 0] = result[0];
11377bee2925SMatthew Knepley coords[v * cdim + 1] = result[1];
11387bee2925SMatthew Knepley coords[v * cdim + 2] = result[2];
11397bee2925SMatthew Knepley }
11407bee2925SMatthew Knepley }
11417bee2925SMatthew Knepley }
11425552b385SBrandon PetscCheck(numEdges + numQuads == newVertices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of new vertices %d != %d previous count", numEdges + numQuads, newVertices);
11437bee2925SMatthew Knepley
11447bee2925SMatthew Knepley /* Get cell vertices by traversing loops */
11457bee2925SMatthew Knepley numQuads = 0;
11467bee2925SMatthew Knepley cOff = 0;
11477bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) {
11487bee2925SMatthew Knepley ego body = bodies[b];
11497bee2925SMatthew Knepley int id, Nl, l;
11507bee2925SMatthew Knepley
11515552b385SBrandon if (islite) {
11525552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
11535552b385SBrandon } else {
11549566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
11555552b385SBrandon }
11567bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) {
11577bee2925SMatthew Knepley ego loop = lobjs[l];
11587bee2925SMatthew Knepley int lid, Ner = 0, Ne, e, nc = 0, c, Nt, t;
11597bee2925SMatthew Knepley
11605552b385SBrandon if (islite) {
11615552b385SBrandon lid = EGlite_indexBodyTopo(body, loop);
11625552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
11635552b385SBrandon } else {
11645f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop);
11659566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
11665552b385SBrandon }
11677bee2925SMatthew Knepley
11687bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) {
11697bee2925SMatthew Knepley ego edge = objs[e];
11707bee2925SMatthew Knepley int points[3];
11717bee2925SMatthew Knepley int eid, Nv, v, tmp;
11727bee2925SMatthew Knepley
11735552b385SBrandon if (islite) {
11745552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
11755552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
11765552b385SBrandon } else {
11777bee2925SMatthew Knepley eid = EG_indexBodyTopo(body, edge);
11789566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
11795552b385SBrandon }
11805552b385SBrandon
1181266cfabeSMatthew G. Knepley if (mtype == DEGENERATE) continue;
1182266cfabeSMatthew G. Knepley else ++Ner;
11835552b385SBrandon PetscCheck(Nv == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Edge %" PetscInt_FMT " has %" PetscInt_FMT " vertices != 2", eid, Nv);
11847bee2925SMatthew Knepley
11857bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) {
11867bee2925SMatthew Knepley ego vertex = nobjs[v];
11877bee2925SMatthew Knepley
11885552b385SBrandon if (islite) {
11895552b385SBrandon id = EGlite_indexBodyTopo(body, vertex);
11905552b385SBrandon } else {
11917bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex);
11925552b385SBrandon }
11937bee2925SMatthew Knepley points[v * 2] = id - 1;
11947bee2925SMatthew Knepley }
11957bee2925SMatthew Knepley {
11967bee2925SMatthew Knepley PetscInt edgeNum;
11977bee2925SMatthew Knepley
11989566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum));
11997bee2925SMatthew Knepley points[1] = numVertices - newVertices + edgeNum;
12007bee2925SMatthew Knepley }
12017bee2925SMatthew Knepley /* EGADS loops are not oriented, but seem to be in order, so we must piece them together */
12027bee2925SMatthew Knepley if (!nc) {
12037bee2925SMatthew Knepley for (v = 0; v < Nv + 1; ++v) cone[nc++] = points[v];
12047bee2925SMatthew Knepley } else {
12059371c9d4SSatish Balay if (cone[nc - 1] == points[0]) {
12069371c9d4SSatish Balay cone[nc++] = points[1];
12079371c9d4SSatish Balay if (cone[0] != points[2]) cone[nc++] = points[2];
12089371c9d4SSatish Balay } else if (cone[nc - 1] == points[2]) {
12099371c9d4SSatish Balay cone[nc++] = points[1];
12109371c9d4SSatish Balay if (cone[0] != points[0]) cone[nc++] = points[0];
12119371c9d4SSatish Balay } else if (cone[nc - 3] == points[0]) {
12129371c9d4SSatish Balay tmp = cone[nc - 3];
12139371c9d4SSatish Balay cone[nc - 3] = cone[nc - 1];
12149371c9d4SSatish Balay cone[nc - 1] = tmp;
12159371c9d4SSatish Balay cone[nc++] = points[1];
12169371c9d4SSatish Balay if (cone[0] != points[2]) cone[nc++] = points[2];
12179371c9d4SSatish Balay } else if (cone[nc - 3] == points[2]) {
12189371c9d4SSatish Balay tmp = cone[nc - 3];
12199371c9d4SSatish Balay cone[nc - 3] = cone[nc - 1];
12209371c9d4SSatish Balay cone[nc - 1] = tmp;
12219371c9d4SSatish Balay cone[nc++] = points[1];
12229371c9d4SSatish Balay if (cone[0] != points[0]) cone[nc++] = points[0];
12239371c9d4SSatish Balay } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %d does not match its predecessor", eid);
12247bee2925SMatthew Knepley }
12257bee2925SMatthew Knepley }
122663a3b9bcSJacob Faibussowitsch PetscCheck(nc == 2 * Ner, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " != %" PetscInt_FMT, nc, 2 * Ner);
1227ac530a7eSPierre Jolivet if (Ner == 4) cone[nc++] = numVertices - newVertices + numEdges + numQuads++;
122863a3b9bcSJacob Faibussowitsch PetscCheck(nc <= maxCorners, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " > %" PetscInt_FMT " max", nc, maxCorners);
12297bee2925SMatthew Knepley /* Triangulate the loop */
12307bee2925SMatthew Knepley switch (Ner) {
12317bee2925SMatthew Knepley case 2: /* Bi-Segment -> 2 triangles */
12327bee2925SMatthew Knepley Nt = 2;
12337bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0];
12347bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1];
12357bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[2];
12367bee2925SMatthew Knepley ++cOff;
12377bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0];
12387bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2];
12397bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3];
12407bee2925SMatthew Knepley ++cOff;
12417bee2925SMatthew Knepley break;
12427bee2925SMatthew Knepley case 3: /* Triangle -> 4 triangles */
12437bee2925SMatthew Knepley Nt = 4;
12447bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0];
12457bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1];
12467bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5];
12477bee2925SMatthew Knepley ++cOff;
12487bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1];
12497bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2];
12507bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3];
12517bee2925SMatthew Knepley ++cOff;
12527bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[5];
12537bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3];
12547bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[4];
12557bee2925SMatthew Knepley ++cOff;
12567bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1];
12577bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3];
12587bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5];
12597bee2925SMatthew Knepley ++cOff;
12607bee2925SMatthew Knepley break;
12617bee2925SMatthew Knepley case 4: /* Quad -> 8 triangles */
12627bee2925SMatthew Knepley Nt = 8;
12637bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0];
12647bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1];
12657bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7];
12667bee2925SMatthew Knepley ++cOff;
12677bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1];
12687bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2];
12697bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3];
12707bee2925SMatthew Knepley ++cOff;
12717bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[3];
12727bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[4];
12737bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5];
12747bee2925SMatthew Knepley ++cOff;
12757bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[5];
12767bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[6];
12777bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7];
12787bee2925SMatthew Knepley ++cOff;
12797bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8];
12807bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1];
12817bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3];
12827bee2925SMatthew Knepley ++cOff;
12837bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8];
12847bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3];
12857bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5];
12867bee2925SMatthew Knepley ++cOff;
12877bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8];
12887bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[5];
12897bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7];
12907bee2925SMatthew Knepley ++cOff;
12917bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8];
12927bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[7];
12937bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[1];
12947bee2925SMatthew Knepley ++cOff;
12957bee2925SMatthew Knepley break;
1296d71ae5a4SJacob Faibussowitsch default:
1297d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d edges, which we do not support", lid, Ner);
12987bee2925SMatthew Knepley }
1299266cfabeSMatthew G. Knepley if (debug) {
13007bee2925SMatthew Knepley for (t = 0; t < Nt; ++t) {
13015552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP Corner NODEs Triangle %d (", t));
13027bee2925SMatthew Knepley for (c = 0; c < numCorners; ++c) {
13033a7d0413SPierre Jolivet if (c > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
13045552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "%d", cells[(cOff - Nt + t) * numCorners + c]));
13057bee2925SMatthew Knepley }
13069566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n"));
13077bee2925SMatthew Knepley }
13087bee2925SMatthew Knepley }
1309266cfabeSMatthew G. Knepley }
13105552b385SBrandon if (islite) {
13115552b385SBrandon EGlite_free(lobjs);
13125552b385SBrandon } else {
13137bee2925SMatthew Knepley EG_free(lobjs);
13147bee2925SMatthew Knepley }
13157bee2925SMatthew Knepley }
13165552b385SBrandon }
13175552b385SBrandon PetscCheck(cOff == numCells, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count of total cells %d != %d previous count", cOff, numCells);
13189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numVertices, numCorners, PETSC_TRUE, cells, cdim, coords, &dm));
13199566063dSJacob Faibussowitsch PetscCall(PetscFree3(coords, cells, cone));
13205552b385SBrandon PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %d (%d)\n", numCells, newCells));
13215552b385SBrandon PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %d (%d)\n", numVertices, newVertices));
13227bee2925SMatthew Knepley /* Embed EGADS model in DM */
13237bee2925SMatthew Knepley {
13247bee2925SMatthew Knepley PetscContainer modelObj, contextObj;
13257bee2925SMatthew Knepley
13269566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj));
13279566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model));
13285552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSDestroy_Private));
13299566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj));
13309566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj));
13317bee2925SMatthew Knepley
13329566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj));
13339566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context));
13345552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSClose_Private));
13359566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj));
13369566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj));
13377bee2925SMatthew Knepley }
13387bee2925SMatthew Knepley /* Label points */
13399566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID"));
13409566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
13419566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID"));
13429566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
13439566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID"));
13449566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
13459566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID"));
13469566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
13477bee2925SMatthew Knepley cOff = 0;
13487bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) {
13497bee2925SMatthew Knepley ego body = bodies[b];
13507bee2925SMatthew Knepley int id, Nl, l;
13517bee2925SMatthew Knepley
13525552b385SBrandon if (islite) {
13535552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
13545552b385SBrandon } else {
13559566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
13565552b385SBrandon }
13577bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) {
13587bee2925SMatthew Knepley ego loop = lobjs[l];
13597bee2925SMatthew Knepley ego *fobjs;
13607bee2925SMatthew Knepley int lid, Nf, fid, Ner = 0, Ne, e, Nt = 0, t;
13617bee2925SMatthew Knepley
13625552b385SBrandon if (islite) {
13635552b385SBrandon lid = EGlite_indexBodyTopo(body, loop);
13645552b385SBrandon PetscCall(EGlite_getBodyTopos(body, loop, FACE, &Nf, &fobjs));
13655552b385SBrandon } else {
13665f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop);
13679566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs));
13685552b385SBrandon }
13695552b385SBrandon
137008401ef6SPierre Jolivet PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf);
13715552b385SBrandon if (islite) {
13725552b385SBrandon fid = EGlite_indexBodyTopo(body, fobjs[0]);
13735552b385SBrandon EGlite_free(fobjs);
13745552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
13755552b385SBrandon } else {
13765f80ce2aSJacob Faibussowitsch fid = EG_indexBodyTopo(body, fobjs[0]);
13777bee2925SMatthew Knepley EG_free(fobjs);
13789566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
13795552b385SBrandon }
13805552b385SBrandon
13817bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) {
13827bee2925SMatthew Knepley ego edge = objs[e];
13837bee2925SMatthew Knepley int eid, Nv, v;
13847bee2925SMatthew Knepley PetscInt points[3], support[2], numEdges, edgeNum;
13857bee2925SMatthew Knepley const PetscInt *edges;
13867bee2925SMatthew Knepley
13875552b385SBrandon if (islite) {
13885552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
13895552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
13905552b385SBrandon } else {
13917bee2925SMatthew Knepley eid = EG_indexBodyTopo(body, edge);
13929566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
13935552b385SBrandon }
13945552b385SBrandon
13957bee2925SMatthew Knepley if (mtype == DEGENERATE) continue;
13967bee2925SMatthew Knepley else ++Ner;
13977bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) {
13987bee2925SMatthew Knepley ego vertex = nobjs[v];
13997bee2925SMatthew Knepley
14005552b385SBrandon if (islite) {
14015552b385SBrandon id = EGlite_indexBodyTopo(body, vertex);
14025552b385SBrandon } else {
14037bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex);
14045552b385SBrandon }
14055552b385SBrandon
14069566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, numCells + id - 1, eid));
14077bee2925SMatthew Knepley points[v * 2] = numCells + id - 1;
14087bee2925SMatthew Knepley }
14099566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum));
14107bee2925SMatthew Knepley points[1] = numCells + numVertices - newVertices + edgeNum;
14117bee2925SMatthew Knepley
14129566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, points[1], eid));
14137bee2925SMatthew Knepley support[0] = points[0];
14147bee2925SMatthew Knepley support[1] = points[1];
14159566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges));
14165552b385SBrandon PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%d, %d) should only bound 1 edge, not %d", support[0], support[1], numEdges);
14179566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid));
14189566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges));
14197bee2925SMatthew Knepley support[0] = points[1];
14207bee2925SMatthew Knepley support[1] = points[2];
14219566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges));
14225552b385SBrandon PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%d, %d) should only bound 1 edge, not %d", support[0], support[1], numEdges);
14239566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid));
14249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges));
14257bee2925SMatthew Knepley }
14267bee2925SMatthew Knepley switch (Ner) {
1427d71ae5a4SJacob Faibussowitsch case 2:
1428d71ae5a4SJacob Faibussowitsch Nt = 2;
1429d71ae5a4SJacob Faibussowitsch break;
1430d71ae5a4SJacob Faibussowitsch case 3:
1431d71ae5a4SJacob Faibussowitsch Nt = 4;
1432d71ae5a4SJacob Faibussowitsch break;
1433d71ae5a4SJacob Faibussowitsch case 4:
1434d71ae5a4SJacob Faibussowitsch Nt = 8;
1435d71ae5a4SJacob Faibussowitsch break;
1436d71ae5a4SJacob Faibussowitsch default:
1437d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Loop with %d edges is unsupported", Ner);
14387bee2925SMatthew Knepley }
14397bee2925SMatthew Knepley for (t = 0; t < Nt; ++t) {
14409566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cOff + t, b));
14419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cOff + t, fid));
14427bee2925SMatthew Knepley }
14437bee2925SMatthew Knepley cOff += Nt;
14447bee2925SMatthew Knepley }
14455552b385SBrandon if (islite) {
14465552b385SBrandon EGlite_free(lobjs);
14475552b385SBrandon } else {
14487bee2925SMatthew Knepley EG_free(lobjs);
14497bee2925SMatthew Knepley }
14505552b385SBrandon }
14519566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&edgeMap));
14529566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
14537bee2925SMatthew Knepley for (c = cStart; c < cEnd; ++c) {
14547bee2925SMatthew Knepley PetscInt *closure = NULL;
14557bee2925SMatthew Knepley PetscInt clSize, cl, bval, fval;
14567bee2925SMatthew Knepley
14579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
14589566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, c, &bval));
14599566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, c, &fval));
14607bee2925SMatthew Knepley for (cl = 0; cl < clSize * 2; cl += 2) {
14619566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, closure[cl], bval));
14629566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, closure[cl], fval));
14637bee2925SMatthew Knepley }
14649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
14657bee2925SMatthew Knepley }
14667bee2925SMatthew Knepley *newdm = dm;
1467b6555650SPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS);
14687bee2925SMatthew Knepley }
1469c1cad2e7SMatthew G. Knepley
DMPlexCreateGeom(MPI_Comm comm,ego context,ego model,DM * newdm,PetscBool islite)14705552b385SBrandon PetscErrorCode DMPlexCreateGeom(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite)
1471d71ae5a4SJacob Faibussowitsch {
14725552b385SBrandon // EGADS variables
1473c1cad2e7SMatthew G. Knepley ego geom, *bodies, *mobjs, *fobjs, *lobjs, *eobjs, *nobjs;
1474c1cad2e7SMatthew G. Knepley ego topRef, prev, next;
1475c1cad2e7SMatthew G. Knepley int oclass, mtype, nbodies, *senses, *lSenses, *eSenses;
1476c1cad2e7SMatthew G. Knepley int b;
1477c1cad2e7SMatthew G. Knepley // PETSc variables
1478c1cad2e7SMatthew G. Knepley DM dm;
14795552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
1480c1cad2e7SMatthew G. Knepley PetscHMapI edgeMap = NULL, bodyIndexMap = NULL, bodyVertexMap = NULL, bodyEdgeMap = NULL, bodyFaceMap = NULL, bodyEdgeGlobalMap = NULL;
1481c1cad2e7SMatthew G. Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, numVertices = 0, numEdges = 0, numFaces = 0, numCells = 0, edgeCntr = 0;
1482c1cad2e7SMatthew G. Knepley PetscInt cellCntr = 0, numPoints = 0;
1483c1cad2e7SMatthew G. Knepley PetscInt *cells = NULL;
1484c1cad2e7SMatthew G. Knepley const PetscInt *cone = NULL;
1485c1cad2e7SMatthew G. Knepley PetscReal *coords = NULL;
1486c1cad2e7SMatthew G. Knepley PetscMPIInt rank;
1487c1cad2e7SMatthew G. Knepley
1488c1cad2e7SMatthew G. Knepley PetscFunctionBeginUser;
14899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
1490c5853193SPierre Jolivet if (rank == 0) {
1491f0b74427SPierre Jolivet // Generate PETSc DMPlex
1492c1cad2e7SMatthew G. Knepley // Get all Nodes in model, record coordinates in a correctly formatted array
1493c1cad2e7SMatthew G. Knepley // Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array
1494c1cad2e7SMatthew G. Knepley // We need to uniformly refine the initial geometry to guarantee a valid mesh
1495c1cad2e7SMatthew G. Knepley
1496d5b43468SJose E. Roman // Calculate cell and vertex sizes
14975552b385SBrandon if (islite) {
14985552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
14995552b385SBrandon } else {
15009566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
15015552b385SBrandon }
15029566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&edgeMap));
15039566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyIndexMap));
15049566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyVertexMap));
15059566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyEdgeMap));
15069566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyEdgeGlobalMap));
15079566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyFaceMap));
1508c1cad2e7SMatthew G. Knepley
1509c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) {
1510c1cad2e7SMatthew G. Knepley ego body = bodies[b];
1511c1cad2e7SMatthew G. Knepley int Nf, Ne, Nv;
1512c1cad2e7SMatthew G. Knepley PetscHashIter BIiter, BViter, BEiter, BEGiter, BFiter, EMiter;
1513c1cad2e7SMatthew G. Knepley PetscBool BIfound, BVfound, BEfound, BEGfound, BFfound, EMfound;
1514c1cad2e7SMatthew G. Knepley
15159566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyIndexMap, b, &BIiter, &BIfound));
15169566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound));
15179566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound));
15189566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound));
15199566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound));
1520c1cad2e7SMatthew G. Knepley
15219566063dSJacob Faibussowitsch if (!BIfound) PetscCall(PetscHMapISet(bodyIndexMap, b, numFaces + numEdges + numVertices));
15229566063dSJacob Faibussowitsch if (!BVfound) PetscCall(PetscHMapISet(bodyVertexMap, b, numVertices));
15239566063dSJacob Faibussowitsch if (!BEfound) PetscCall(PetscHMapISet(bodyEdgeMap, b, numEdges));
15249566063dSJacob Faibussowitsch if (!BEGfound) PetscCall(PetscHMapISet(bodyEdgeGlobalMap, b, edgeCntr));
15259566063dSJacob Faibussowitsch if (!BFfound) PetscCall(PetscHMapISet(bodyFaceMap, b, numFaces));
1526c1cad2e7SMatthew G. Knepley
15275552b385SBrandon if (islite) {
15285552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
15295552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
15305552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
15315552b385SBrandon EGlite_free(fobjs);
15325552b385SBrandon EGlite_free(eobjs);
15335552b385SBrandon EGlite_free(nobjs);
15345552b385SBrandon } else {
15359566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
15369566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
15379566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
1538c1cad2e7SMatthew G. Knepley EG_free(fobjs);
1539c1cad2e7SMatthew G. Knepley EG_free(eobjs);
1540c1cad2e7SMatthew G. Knepley EG_free(nobjs);
15415552b385SBrandon }
1542c1cad2e7SMatthew G. Knepley
1543c1cad2e7SMatthew G. Knepley // Remove DEGENERATE EDGES from Edge count
15445552b385SBrandon if (islite) {
15455552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
15465552b385SBrandon } else {
15479566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
15485552b385SBrandon }
15495552b385SBrandon
1550c1cad2e7SMatthew G. Knepley int Netemp = 0;
1551c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) {
1552c1cad2e7SMatthew G. Knepley ego edge = eobjs[e];
1553c1cad2e7SMatthew G. Knepley int eid;
1554c1cad2e7SMatthew G. Knepley
15555552b385SBrandon if (islite) {
15565552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
15575552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
15585552b385SBrandon } else {
15599566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
15605f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge);
15615552b385SBrandon }
1562c1cad2e7SMatthew G. Knepley
15639566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, edgeCntr + eid - 1, &EMiter, &EMfound));
1564c1cad2e7SMatthew G. Knepley if (mtype == DEGENERATE) {
15659566063dSJacob Faibussowitsch if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, -1));
15669371c9d4SSatish Balay } else {
1567c1cad2e7SMatthew G. Knepley ++Netemp;
15689566063dSJacob Faibussowitsch if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, Netemp));
1569c1cad2e7SMatthew G. Knepley }
1570c1cad2e7SMatthew G. Knepley }
15715552b385SBrandon if (islite) {
15725552b385SBrandon EGlite_free(eobjs);
15735552b385SBrandon } else {
1574c1cad2e7SMatthew G. Knepley EG_free(eobjs);
15755552b385SBrandon }
1576c1cad2e7SMatthew G. Knepley
1577c1cad2e7SMatthew G. Knepley // Determine Number of Cells
15785552b385SBrandon if (islite) {
15795552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
15805552b385SBrandon } else {
15819566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
15825552b385SBrandon }
15835552b385SBrandon
1584c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) {
1585c1cad2e7SMatthew G. Knepley ego face = fobjs[f];
1586c1cad2e7SMatthew G. Knepley int edgeTemp = 0;
1587c1cad2e7SMatthew G. Knepley
15885552b385SBrandon if (islite) {
15895552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs));
15905552b385SBrandon } else {
15919566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs));
15925552b385SBrandon }
15935552b385SBrandon
1594c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) {
1595c1cad2e7SMatthew G. Knepley ego edge = eobjs[e];
1596c1cad2e7SMatthew G. Knepley
15975552b385SBrandon if (islite) {
15985552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
15995552b385SBrandon } else {
16009566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
16015552b385SBrandon }
1602ad540459SPierre Jolivet if (mtype != DEGENERATE) ++edgeTemp;
1603c1cad2e7SMatthew G. Knepley }
1604c1cad2e7SMatthew G. Knepley numCells += (2 * edgeTemp);
16055552b385SBrandon if (islite) {
16065552b385SBrandon EGlite_free(eobjs);
16075552b385SBrandon } else {
1608c1cad2e7SMatthew G. Knepley EG_free(eobjs);
1609c1cad2e7SMatthew G. Knepley }
16105552b385SBrandon }
16115552b385SBrandon if (islite) {
16125552b385SBrandon EGlite_free(fobjs);
16135552b385SBrandon } else {
1614c1cad2e7SMatthew G. Knepley EG_free(fobjs);
16155552b385SBrandon }
1616c1cad2e7SMatthew G. Knepley
1617c1cad2e7SMatthew G. Knepley numFaces += Nf;
1618c1cad2e7SMatthew G. Knepley numEdges += Netemp;
1619c1cad2e7SMatthew G. Knepley numVertices += Nv;
1620c1cad2e7SMatthew G. Knepley edgeCntr += Ne;
1621c1cad2e7SMatthew G. Knepley }
1622c1cad2e7SMatthew G. Knepley
1623c1cad2e7SMatthew G. Knepley // Set up basic DMPlex parameters
162435cb6cd3SPierre Jolivet dim = 2; // Assumes 3D Models :: Need to handle 2D models in the future
162535cb6cd3SPierre Jolivet cdim = 3; // Assumes 3D Models :: Need to update to handle 2D models in future
1626c1cad2e7SMatthew G. Knepley numCorners = 3; // Split Faces into triangles
1627c1cad2e7SMatthew G. Knepley numPoints = numVertices + numEdges + numFaces; // total number of coordinate points
1628c1cad2e7SMatthew G. Knepley
16299566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPoints * cdim, &coords, numCells * numCorners, &cells));
1630c1cad2e7SMatthew G. Knepley
1631c1cad2e7SMatthew G. Knepley // Get Vertex Coordinates and Set up Cells
1632c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) {
1633c1cad2e7SMatthew G. Knepley ego body = bodies[b];
1634c1cad2e7SMatthew G. Knepley int Nf, Ne, Nv;
1635c1cad2e7SMatthew G. Knepley PetscInt bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart;
1636c1cad2e7SMatthew G. Knepley PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter;
1637c1cad2e7SMatthew G. Knepley PetscBool BVfound, BEfound, BEGfound, BFfound, EMfound;
1638c1cad2e7SMatthew G. Knepley
1639c1cad2e7SMatthew G. Knepley // Vertices on Current Body
16405552b385SBrandon if (islite) {
16415552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
16425552b385SBrandon } else {
16439566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
16445552b385SBrandon }
1645c1cad2e7SMatthew G. Knepley
16469566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound));
16475552b385SBrandon PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyVertexMap", b);
16489566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart));
1649c1cad2e7SMatthew G. Knepley
1650c1cad2e7SMatthew G. Knepley for (int v = 0; v < Nv; ++v) {
1651c1cad2e7SMatthew G. Knepley ego vertex = nobjs[v];
1652c1cad2e7SMatthew G. Knepley double limits[4];
16532a8381b2SBarry Smith int id, unused;
1654c1cad2e7SMatthew G. Knepley
16555552b385SBrandon if (islite) {
16562a8381b2SBarry Smith PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &unused, &mobjs, &senses));
16575552b385SBrandon id = EGlite_indexBodyTopo(body, vertex);
16585552b385SBrandon } else {
16592a8381b2SBarry Smith PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &unused, &mobjs, &senses));
16605f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, vertex);
16615552b385SBrandon }
1662c1cad2e7SMatthew G. Knepley
1663c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 0] = limits[0];
1664c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 1] = limits[1];
1665c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 2] = limits[2];
1666c1cad2e7SMatthew G. Knepley }
16675552b385SBrandon if (islite) {
16685552b385SBrandon EGlite_free(nobjs);
16695552b385SBrandon } else {
1670c1cad2e7SMatthew G. Knepley EG_free(nobjs);
16715552b385SBrandon }
1672c1cad2e7SMatthew G. Knepley
1673c1cad2e7SMatthew G. Knepley // Edge Midpoint Vertices on Current Body
16745552b385SBrandon if (islite) {
16755552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
16765552b385SBrandon } else {
16779566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
16785552b385SBrandon }
1679c1cad2e7SMatthew G. Knepley
16809566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound));
16815552b385SBrandon PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyEdgeMap", b);
16829566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart));
1683c1cad2e7SMatthew G. Knepley
16849566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound));
16855552b385SBrandon PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyEdgeGlobalMap", b);
16869566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart));
1687c1cad2e7SMatthew G. Knepley
1688c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) {
1689c1cad2e7SMatthew G. Knepley ego edge = eobjs[e];
1690c1cad2e7SMatthew G. Knepley double range[2], avgt[1], cntrPnt[9];
1691c1cad2e7SMatthew G. Knepley int eid, eOffset;
1692c1cad2e7SMatthew G. Knepley int periodic;
1693c1cad2e7SMatthew G. Knepley
16945552b385SBrandon if (islite) {
16955552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
16965552b385SBrandon } else {
16979566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
16985552b385SBrandon }
1699ad540459SPierre Jolivet if (mtype == DEGENERATE) continue;
1700c1cad2e7SMatthew G. Knepley
17015552b385SBrandon if (islite) {
17025552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
17035552b385SBrandon } else {
17045f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge);
17055552b385SBrandon }
1706c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector
17079566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound));
17085552b385SBrandon PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %" PetscInt_FMT " not found in edgeMap", bodyEdgeGlobalIndexStart + eid - 1);
17099566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset));
1710c1cad2e7SMatthew G. Knepley
17115552b385SBrandon if (islite) {
17125552b385SBrandon PetscCall(EGlite_getRange(edge, range, &periodic));
17135552b385SBrandon } else {
17149566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, &periodic));
17155552b385SBrandon }
1716c1cad2e7SMatthew G. Knepley avgt[0] = (range[0] + range[1]) / 2.;
1717c1cad2e7SMatthew G. Knepley
17185552b385SBrandon if (islite) {
17195552b385SBrandon PetscCall(EGlite_evaluate(edge, avgt, cntrPnt));
17205552b385SBrandon } else {
17219566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, avgt, cntrPnt));
17225552b385SBrandon }
1723c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 0] = cntrPnt[0];
1724c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 1] = cntrPnt[1];
1725c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 2] = cntrPnt[2];
1726c1cad2e7SMatthew G. Knepley }
17275552b385SBrandon if (islite) {
17285552b385SBrandon EGlite_free(eobjs);
17295552b385SBrandon } else {
1730c1cad2e7SMatthew G. Knepley EG_free(eobjs);
17315552b385SBrandon }
1732c1cad2e7SMatthew G. Knepley // Face Midpoint Vertices on Current Body
17335552b385SBrandon if (islite) {
17345552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
17355552b385SBrandon } else {
17369566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
17375552b385SBrandon }
17389566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound));
173928b400f6SJacob Faibussowitsch PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b);
17409566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart));
1741c1cad2e7SMatthew G. Knepley
1742c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) {
1743c1cad2e7SMatthew G. Knepley ego face = fobjs[f];
1744c1cad2e7SMatthew G. Knepley double range[4], avgUV[2], cntrPnt[18];
1745c1cad2e7SMatthew G. Knepley int peri, id;
1746c1cad2e7SMatthew G. Knepley
17475552b385SBrandon if (islite) {
17485552b385SBrandon id = EGlite_indexBodyTopo(body, face);
17495552b385SBrandon PetscCall(EGlite_getRange(face, range, &peri));
17505552b385SBrandon } else {
1751c1cad2e7SMatthew G. Knepley id = EG_indexBodyTopo(body, face);
17529566063dSJacob Faibussowitsch PetscCall(EG_getRange(face, range, &peri));
17535552b385SBrandon }
1754c1cad2e7SMatthew G. Knepley
1755c1cad2e7SMatthew G. Knepley avgUV[0] = (range[0] + range[1]) / 2.;
1756c1cad2e7SMatthew G. Knepley avgUV[1] = (range[2] + range[3]) / 2.;
17575552b385SBrandon
17585552b385SBrandon if (islite) {
17595552b385SBrandon PetscCall(EGlite_evaluate(face, avgUV, cntrPnt));
17605552b385SBrandon } else {
17619566063dSJacob Faibussowitsch PetscCall(EG_evaluate(face, avgUV, cntrPnt));
17625552b385SBrandon }
1763c1cad2e7SMatthew G. Knepley
1764c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 0] = cntrPnt[0];
1765c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 1] = cntrPnt[1];
1766c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 2] = cntrPnt[2];
1767c1cad2e7SMatthew G. Knepley }
17685552b385SBrandon if (islite) {
17695552b385SBrandon EGlite_free(fobjs);
17705552b385SBrandon } else {
1771c1cad2e7SMatthew G. Knepley EG_free(fobjs);
17725552b385SBrandon }
1773c1cad2e7SMatthew G. Knepley
1774c1cad2e7SMatthew G. Knepley // Define Cells :: Note - This could be incorporated in the Face Midpoint Vertices Loop but was kept separate for clarity
17755552b385SBrandon if (islite) {
17765552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
17775552b385SBrandon } else {
17789566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
17795552b385SBrandon }
1780c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) {
1781c1cad2e7SMatthew G. Knepley ego face = fobjs[f];
1782c1cad2e7SMatthew G. Knepley int fID, midFaceID, midPntID, startID, endID, Nl;
1783c1cad2e7SMatthew G. Knepley
17845552b385SBrandon if (islite) {
17855552b385SBrandon fID = EGlite_indexBodyTopo(body, face);
17865552b385SBrandon } else {
17875f80ce2aSJacob Faibussowitsch fID = EG_indexBodyTopo(body, face);
17885552b385SBrandon }
17895552b385SBrandon
1790c1cad2e7SMatthew G. Knepley midFaceID = numVertices + numEdges + bodyFaceIndexStart + fID - 1;
1791c1cad2e7SMatthew G. Knepley // Must Traverse Loop to ensure we have all necessary information like the sense (+/- 1) of the edges.
1792c1cad2e7SMatthew G. Knepley // TODO :: Only handles single loop faces (No holes). The choices for handling multiloop faces are:
17935552b385SBrandon // 1) Use the DMPlexCreateGeomFromFile() with the -dm_plex_geom_with_tess = 1 option.
1794c1cad2e7SMatthew G. Knepley // This will use a default EGADS tessellation as an initial surface mesh.
1795d5b43468SJose E. Roman // 2) Create the initial surface mesh via a 2D mesher :: Currently not available (?future?)
1796c1cad2e7SMatthew G. Knepley // May I suggest the XXXX as a starting point?
1797c1cad2e7SMatthew G. Knepley
17985552b385SBrandon if (islite) {
17995552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses));
18005552b385SBrandon } else {
18019566063dSJacob Faibussowitsch PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses));
18025552b385SBrandon }
1803c1cad2e7SMatthew G. Knepley
18045552b385SBrandon PetscCheck(Nl == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face has %" PetscInt_FMT " Loops. Can only handle Faces with 1 Loop. Please use --dm_plex_geom_with_tess = 1 Option", Nl);
1805c1cad2e7SMatthew G. Knepley for (int l = 0; l < Nl; ++l) {
1806c1cad2e7SMatthew G. Knepley ego loop = lobjs[l];
1807c1cad2e7SMatthew G. Knepley
18085552b385SBrandon if (islite) {
18095552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses));
18105552b385SBrandon } else {
18119566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses));
18125552b385SBrandon }
18135552b385SBrandon
1814c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) {
1815c1cad2e7SMatthew G. Knepley ego edge = eobjs[e];
1816c1cad2e7SMatthew G. Knepley int eid, eOffset;
1817c1cad2e7SMatthew G. Knepley
18185552b385SBrandon if (islite) {
18195552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
18205552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
18215552b385SBrandon } else {
18229566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
1823c1cad2e7SMatthew G. Knepley eid = EG_indexBodyTopo(body, edge);
18245552b385SBrandon }
1825ad540459SPierre Jolivet if (mtype == DEGENERATE) continue;
1826c1cad2e7SMatthew G. Knepley
1827c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector
18289566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound));
18295552b385SBrandon PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %" PetscInt_FMT " of Body %" PetscInt_FMT " not found in edgeMap. Global Edge ID :: %" PetscInt_FMT, eid, b, bodyEdgeGlobalIndexStart + eid - 1);
18309566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset));
1831c1cad2e7SMatthew G. Knepley
1832c1cad2e7SMatthew G. Knepley midPntID = numVertices + bodyEdgeIndexStart + eOffset - 1;
1833c1cad2e7SMatthew G. Knepley
18345552b385SBrandon if (islite) {
18355552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
18365552b385SBrandon } else {
18379566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
18385552b385SBrandon }
1839c1cad2e7SMatthew G. Knepley
18409371c9d4SSatish Balay if (eSenses[e] > 0) {
18415552b385SBrandon if (islite) {
18425552b385SBrandon startID = EGlite_indexBodyTopo(body, nobjs[0]);
18435552b385SBrandon endID = EGlite_indexBodyTopo(body, nobjs[1]);
18445552b385SBrandon } else {
18459371c9d4SSatish Balay startID = EG_indexBodyTopo(body, nobjs[0]);
18469371c9d4SSatish Balay endID = EG_indexBodyTopo(body, nobjs[1]);
18475552b385SBrandon }
18485552b385SBrandon } else {
18495552b385SBrandon if (islite) {
18505552b385SBrandon startID = EGlite_indexBodyTopo(body, nobjs[1]);
18515552b385SBrandon endID = EGlite_indexBodyTopo(body, nobjs[0]);
18529371c9d4SSatish Balay } else {
18539371c9d4SSatish Balay startID = EG_indexBodyTopo(body, nobjs[1]);
18549371c9d4SSatish Balay endID = EG_indexBodyTopo(body, nobjs[0]);
18559371c9d4SSatish Balay }
18565552b385SBrandon }
1857c1cad2e7SMatthew G. Knepley
1858c1cad2e7SMatthew G. Knepley // Define 2 Cells per Edge with correct orientation
1859c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 0] = midFaceID;
1860c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 1] = bodyVertexIndexStart + startID - 1;
1861c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 2] = midPntID;
1862c1cad2e7SMatthew G. Knepley
1863c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 3] = midFaceID;
1864c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 4] = midPntID;
1865c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 5] = bodyVertexIndexStart + endID - 1;
1866c1cad2e7SMatthew G. Knepley
1867c1cad2e7SMatthew G. Knepley cellCntr = cellCntr + 2;
1868c1cad2e7SMatthew G. Knepley }
1869c1cad2e7SMatthew G. Knepley }
1870c1cad2e7SMatthew G. Knepley }
18715552b385SBrandon if (islite) {
18725552b385SBrandon EGlite_free(fobjs);
18735552b385SBrandon } else {
1874c1cad2e7SMatthew G. Knepley EG_free(fobjs);
1875c1cad2e7SMatthew G. Knepley }
1876c1cad2e7SMatthew G. Knepley }
18775552b385SBrandon }
1878c1cad2e7SMatthew G. Knepley
1879c1cad2e7SMatthew G. Knepley // Generate DMPlex
18809566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm));
18819566063dSJacob Faibussowitsch PetscCall(PetscFree2(coords, cells));
188263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %" PetscInt_FMT " \n", numCells));
188363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %" PetscInt_FMT " \n", numVertices));
1884c1cad2e7SMatthew G. Knepley
1885c1cad2e7SMatthew G. Knepley // Embed EGADS model in DM
1886c1cad2e7SMatthew G. Knepley {
1887c1cad2e7SMatthew G. Knepley PetscContainer modelObj, contextObj;
1888c1cad2e7SMatthew G. Knepley
18899566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj));
18909566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model));
18915552b385SBrandon if (islite) {
18925552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSliteDestroy_Private));
18935552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Model", (PetscObject)modelObj));
18945552b385SBrandon } else {
18955552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSDestroy_Private));
18969566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj));
18975552b385SBrandon }
18989566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj));
1899c1cad2e7SMatthew G. Knepley
19009566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj));
19019566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context));
19025552b385SBrandon
19035552b385SBrandon if (islite) {
19045552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSliteClose_Private));
19055552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Context", (PetscObject)contextObj));
19065552b385SBrandon } else {
19075552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSClose_Private));
19089566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj));
19095552b385SBrandon }
19109566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj));
1911c1cad2e7SMatthew G. Knepley }
1912c1cad2e7SMatthew G. Knepley // Label points
1913c1cad2e7SMatthew G. Knepley PetscInt nStart, nEnd;
1914c1cad2e7SMatthew G. Knepley
19159566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID"));
19169566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
19179566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID"));
19189566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
19199566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID"));
19209566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
19219566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID"));
19229566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
1923c1cad2e7SMatthew G. Knepley
19249566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd));
1925c1cad2e7SMatthew G. Knepley
1926c1cad2e7SMatthew G. Knepley cellCntr = 0;
1927c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) {
1928c1cad2e7SMatthew G. Knepley ego body = bodies[b];
1929c1cad2e7SMatthew G. Knepley int Nv, Ne, Nf;
1930c1cad2e7SMatthew G. Knepley PetscInt bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart;
1931c1cad2e7SMatthew G. Knepley PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter;
1932c1cad2e7SMatthew G. Knepley PetscBool BVfound, BEfound, BEGfound, BFfound, EMfound;
1933c1cad2e7SMatthew G. Knepley
19349566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound));
193528b400f6SJacob Faibussowitsch PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyVertexMap", b);
19369566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart));
1937c1cad2e7SMatthew G. Knepley
19389566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound));
193928b400f6SJacob Faibussowitsch PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeMap", b);
19409566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart));
1941c1cad2e7SMatthew G. Knepley
19429566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound));
194328b400f6SJacob Faibussowitsch PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b);
19449566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart));
1945c1cad2e7SMatthew G. Knepley
19469566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound));
194728b400f6SJacob Faibussowitsch PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeGlobalMap", b);
19489566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart));
1949c1cad2e7SMatthew G. Knepley
19505552b385SBrandon if (islite) {
19515552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
19525552b385SBrandon } else {
19539566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
19545552b385SBrandon }
19555552b385SBrandon
1956c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) {
1957c1cad2e7SMatthew G. Knepley ego face = fobjs[f];
1958c1cad2e7SMatthew G. Knepley int fID, Nl;
1959c1cad2e7SMatthew G. Knepley
19605552b385SBrandon if (islite) {
19615552b385SBrandon fID = EGlite_indexBodyTopo(body, face);
19625552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, LOOP, &Nl, &lobjs));
19635552b385SBrandon } else {
19645f80ce2aSJacob Faibussowitsch fID = EG_indexBodyTopo(body, face);
19659566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, face, LOOP, &Nl, &lobjs));
19665552b385SBrandon }
19675552b385SBrandon
1968c1cad2e7SMatthew G. Knepley for (int l = 0; l < Nl; ++l) {
1969c1cad2e7SMatthew G. Knepley ego loop = lobjs[l];
1970c1cad2e7SMatthew G. Knepley int lid;
1971c1cad2e7SMatthew G. Knepley
19725552b385SBrandon if (islite) {
19735552b385SBrandon lid = EGlite_indexBodyTopo(body, loop);
19745552b385SBrandon } else {
19755f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop);
19765552b385SBrandon }
1977c1cad2e7SMatthew G. Knepley
19785552b385SBrandon PetscCheck(Nl == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %" PetscInt_FMT " has %" PetscInt_FMT " > 1 faces, which is not supported", lid, Nf);
19795552b385SBrandon
19805552b385SBrandon if (islite) {
19815552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses));
19825552b385SBrandon } else {
19839566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses));
19845552b385SBrandon }
19855552b385SBrandon
1986c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) {
1987c1cad2e7SMatthew G. Knepley ego edge = eobjs[e];
1988c1cad2e7SMatthew G. Knepley int eid, eOffset;
1989c1cad2e7SMatthew G. Knepley
1990c1cad2e7SMatthew G. Knepley // Skip DEGENERATE Edges
19915552b385SBrandon if (islite) {
19925552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
19935552b385SBrandon } else {
19949566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
19955552b385SBrandon }
19965552b385SBrandon
1997ac530a7eSPierre Jolivet if (mtype == DEGENERATE) continue;
19985552b385SBrandon
19995552b385SBrandon if (islite) {
20005552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
20015552b385SBrandon } else {
20025f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge);
20035552b385SBrandon }
2004c1cad2e7SMatthew G. Knepley
2005c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector
20069566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound));
20075552b385SBrandon PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %" PetscInt_FMT " of Body %" PetscInt_FMT " not found in edgeMap. Global Edge ID :: %" PetscInt_FMT, eid, b, bodyEdgeGlobalIndexStart + eid - 1);
20089566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset));
2009c1cad2e7SMatthew G. Knepley
20105552b385SBrandon if (islite) {
20115552b385SBrandon PetscCall(EGlite_getBodyTopos(body, edge, NODE, &Nv, &nobjs));
20125552b385SBrandon } else {
20139566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, edge, NODE, &Nv, &nobjs));
20145552b385SBrandon }
20155552b385SBrandon
2016c1cad2e7SMatthew G. Knepley for (int v = 0; v < Nv; ++v) {
2017c1cad2e7SMatthew G. Knepley ego vertex = nobjs[v];
2018c1cad2e7SMatthew G. Knepley int vID;
2019c1cad2e7SMatthew G. Knepley
20205552b385SBrandon if (islite) {
20215552b385SBrandon vID = EGlite_indexBodyTopo(body, vertex);
20225552b385SBrandon } else {
20235f80ce2aSJacob Faibussowitsch vID = EG_indexBodyTopo(body, vertex);
20245552b385SBrandon }
20255552b385SBrandon
20269566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + bodyVertexIndexStart + vID - 1, b));
20279566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(vertexLabel, nStart + bodyVertexIndexStart + vID - 1, vID));
2028c1cad2e7SMatthew G. Knepley }
20295552b385SBrandon if (islite) {
20305552b385SBrandon EGlite_free(nobjs);
20315552b385SBrandon } else {
2032c1cad2e7SMatthew G. Knepley EG_free(nobjs);
20335552b385SBrandon }
2034c1cad2e7SMatthew G. Knepley
20359566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, b));
20369566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, eid));
2037c1cad2e7SMatthew G. Knepley
2038c1cad2e7SMatthew G. Knepley // Define Cell faces
2039c1cad2e7SMatthew G. Knepley for (int jj = 0; jj < 2; ++jj) {
20409566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cellCntr, b));
20419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cellCntr, fID));
20429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cellCntr, &cone));
2043c1cad2e7SMatthew G. Knepley
20449566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[0], b));
20459566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[0], fID));
2046c1cad2e7SMatthew G. Knepley
20479566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[1], b));
20489566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, cone[1], eid));
2049c1cad2e7SMatthew G. Knepley
20509566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[2], b));
20519566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[2], fID));
2052c1cad2e7SMatthew G. Knepley
2053c1cad2e7SMatthew G. Knepley cellCntr = cellCntr + 1;
2054c1cad2e7SMatthew G. Knepley }
2055c1cad2e7SMatthew G. Knepley }
2056c1cad2e7SMatthew G. Knepley }
20575552b385SBrandon if (islite) {
20585552b385SBrandon EGlite_free(lobjs);
20595552b385SBrandon } else {
2060c1cad2e7SMatthew G. Knepley EG_free(lobjs);
20615552b385SBrandon }
2062c1cad2e7SMatthew G. Knepley
20639566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, b));
20649566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, fID));
2065c1cad2e7SMatthew G. Knepley }
20665552b385SBrandon if (islite) {
20675552b385SBrandon EGlite_free(fobjs);
20685552b385SBrandon } else {
2069c1cad2e7SMatthew G. Knepley EG_free(fobjs);
2070c1cad2e7SMatthew G. Knepley }
20715552b385SBrandon }
2072c1cad2e7SMatthew G. Knepley
20739566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&edgeMap));
20749566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyIndexMap));
20759566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyVertexMap));
20769566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyEdgeMap));
20779566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyEdgeGlobalMap));
20789566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyFaceMap));
2079c1cad2e7SMatthew G. Knepley
2080c1cad2e7SMatthew G. Knepley *newdm = dm;
20813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2082c1cad2e7SMatthew G. Knepley }
2083c1cad2e7SMatthew G. Knepley
DMPlexCreateGeom_Tess_Internal(MPI_Comm comm,ego context,ego model,DM * newdm,PetscBool islite)20845552b385SBrandon PetscErrorCode DMPlexCreateGeom_Tess_Internal(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite)
2085d71ae5a4SJacob Faibussowitsch {
20865552b385SBrandon /* EGADSlite variables */
2087c1cad2e7SMatthew G. Knepley ego geom, *bodies, *fobjs;
2088c1cad2e7SMatthew G. Knepley int b, oclass, mtype, nbodies, *senses;
2089c1cad2e7SMatthew G. Knepley int totalNumTris = 0, totalNumPoints = 0;
2090c1cad2e7SMatthew G. Knepley double boundBox[6] = {0., 0., 0., 0., 0., 0.}, tessSize;
2091c1cad2e7SMatthew G. Knepley /* PETSc variables */
2092c1cad2e7SMatthew G. Knepley DM dm;
20935552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
2094c1cad2e7SMatthew G. Knepley PetscHMapI pointIndexStartMap = NULL, triIndexStartMap = NULL, pTypeLabelMap = NULL, pIndexLabelMap = NULL;
2095c1cad2e7SMatthew G. Knepley PetscHMapI pBodyIndexLabelMap = NULL, triFaceIDLabelMap = NULL, triBodyIDLabelMap = NULL;
2096c1cad2e7SMatthew G. Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, counter = 0;
2097c1cad2e7SMatthew G. Knepley PetscInt *cells = NULL;
2098c1cad2e7SMatthew G. Knepley const PetscInt *cone = NULL;
2099c1cad2e7SMatthew G. Knepley PetscReal *coords = NULL;
2100c1cad2e7SMatthew G. Knepley PetscMPIInt rank;
2101c1cad2e7SMatthew G. Knepley
2102c1cad2e7SMatthew G. Knepley PetscFunctionBeginUser;
21039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
2104c5853193SPierre Jolivet if (rank == 0) {
2105f0b74427SPierre Jolivet // Generate PETSc DMPlex from EGADSlite created Tessellation of geometry
2106c1cad2e7SMatthew G. Knepley
2107d5b43468SJose E. Roman // Calculate cell and vertex sizes
21085552b385SBrandon if (islite) {
21095552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
21105552b385SBrandon } else {
21119566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
21125552b385SBrandon }
2113c1cad2e7SMatthew G. Knepley
21149566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pointIndexStartMap));
21159566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triIndexStartMap));
21169566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pTypeLabelMap));
21179566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pIndexLabelMap));
21189566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pBodyIndexLabelMap));
21199566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triFaceIDLabelMap));
21209566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triBodyIDLabelMap));
2121c1cad2e7SMatthew G. Knepley
2122c1cad2e7SMatthew G. Knepley /* Create Tessellation of Bodies */
21235552b385SBrandon ego *tessArray;
2124c1cad2e7SMatthew G. Knepley
21255552b385SBrandon PetscCall(PetscMalloc1(nbodies, &tessArray));
2126c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) {
2127c1cad2e7SMatthew G. Knepley ego body = bodies[b];
2128c1cad2e7SMatthew G. Knepley double params[3] = {0.0, 0.0, 0.0}; // Parameters for Tessellation
2129c1cad2e7SMatthew G. Knepley int Nf, bodyNumPoints = 0, bodyNumTris = 0;
2130c1cad2e7SMatthew G. Knepley PetscHashIter PISiter, TISiter;
2131c1cad2e7SMatthew G. Knepley PetscBool PISfound, TISfound;
2132c1cad2e7SMatthew G. Knepley
2133c1cad2e7SMatthew G. Knepley /* Store Start Index for each Body's Point and Tris */
21349566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound));
21359566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triIndexStartMap, b, &TISiter, &TISfound));
2136c1cad2e7SMatthew G. Knepley
21379566063dSJacob Faibussowitsch if (!PISfound) PetscCall(PetscHMapISet(pointIndexStartMap, b, totalNumPoints));
21389566063dSJacob Faibussowitsch if (!TISfound) PetscCall(PetscHMapISet(triIndexStartMap, b, totalNumTris));
2139c1cad2e7SMatthew G. Knepley
2140c1cad2e7SMatthew G. Knepley /* Calculate Tessellation parameters based on Bounding Box */
2141c1cad2e7SMatthew G. Knepley /* Get Bounding Box Dimensions of the BODY */
21425552b385SBrandon if (islite) {
21435552b385SBrandon PetscCall(EGlite_getBoundingBox(body, boundBox));
21445552b385SBrandon } else {
21459566063dSJacob Faibussowitsch PetscCall(EG_getBoundingBox(body, boundBox));
21465552b385SBrandon }
21475552b385SBrandon
2148c1cad2e7SMatthew G. Knepley tessSize = boundBox[3] - boundBox[0];
2149c1cad2e7SMatthew G. Knepley if (tessSize < boundBox[4] - boundBox[1]) tessSize = boundBox[4] - boundBox[1];
2150c1cad2e7SMatthew G. Knepley if (tessSize < boundBox[5] - boundBox[2]) tessSize = boundBox[5] - boundBox[2];
2151c1cad2e7SMatthew G. Knepley
2152c1cad2e7SMatthew G. Knepley // TODO :: May want to give users tessellation parameter options //
2153c1cad2e7SMatthew G. Knepley params[0] = 0.0250 * tessSize;
2154c1cad2e7SMatthew G. Knepley params[1] = 0.0075 * tessSize;
2155c1cad2e7SMatthew G. Knepley params[2] = 15.0;
2156c1cad2e7SMatthew G. Knepley
21575552b385SBrandon if (islite) {
21585552b385SBrandon PetscCall(EGlite_makeTessBody(body, params, &tessArray[b]));
21595552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
21605552b385SBrandon } else {
21619566063dSJacob Faibussowitsch PetscCall(EG_makeTessBody(body, params, &tessArray[b]));
21629566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
21635552b385SBrandon }
2164c1cad2e7SMatthew G. Knepley
2165c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) {
2166c1cad2e7SMatthew G. Knepley ego face = fobjs[f];
2167c1cad2e7SMatthew G. Knepley int len, fID, ntris;
2168c1cad2e7SMatthew G. Knepley const int *ptype, *pindex, *ptris, *ptric;
2169c1cad2e7SMatthew G. Knepley const double *pxyz, *puv;
2170c1cad2e7SMatthew G. Knepley
2171c1cad2e7SMatthew G. Knepley // Get Face ID //
21725552b385SBrandon if (islite) {
21735552b385SBrandon fID = EGlite_indexBodyTopo(body, face);
21745552b385SBrandon } else {
2175c1cad2e7SMatthew G. Knepley fID = EG_indexBodyTopo(body, face);
21765552b385SBrandon }
2177c1cad2e7SMatthew G. Knepley
2178c1cad2e7SMatthew G. Knepley // Checkout the Surface Tessellation //
21795552b385SBrandon if (islite) {
21805552b385SBrandon PetscCall(EGlite_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric));
21815552b385SBrandon } else {
21829566063dSJacob Faibussowitsch PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric));
21835552b385SBrandon }
2184c1cad2e7SMatthew G. Knepley
2185c1cad2e7SMatthew G. Knepley // Determine total number of triangle cells in the tessellation //
2186c1cad2e7SMatthew G. Knepley bodyNumTris += (int)ntris;
2187c1cad2e7SMatthew G. Knepley
2188c1cad2e7SMatthew G. Knepley // Check out the point index and coordinate //
2189c1cad2e7SMatthew G. Knepley for (int p = 0; p < len; ++p) {
2190c1cad2e7SMatthew G. Knepley int global;
2191c1cad2e7SMatthew G. Knepley
21925552b385SBrandon if (islite) {
21935552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, p + 1, &global));
21945552b385SBrandon } else {
21959566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global));
21965552b385SBrandon }
2197c1cad2e7SMatthew G. Knepley
2198c1cad2e7SMatthew G. Knepley // Determine the total number of points in the tessellation //
2199c1cad2e7SMatthew G. Knepley bodyNumPoints = PetscMax(bodyNumPoints, global);
2200c1cad2e7SMatthew G. Knepley }
2201c1cad2e7SMatthew G. Knepley }
22025552b385SBrandon if (islite) {
22035552b385SBrandon EGlite_free(fobjs);
22045552b385SBrandon } else {
2205c1cad2e7SMatthew G. Knepley EG_free(fobjs);
22065552b385SBrandon }
2207c1cad2e7SMatthew G. Knepley
2208c1cad2e7SMatthew G. Knepley totalNumPoints += bodyNumPoints;
2209c1cad2e7SMatthew G. Knepley totalNumTris += bodyNumTris;
2210c1cad2e7SMatthew G. Knepley }
2211c1cad2e7SMatthew G. Knepley
2212c1cad2e7SMatthew G. Knepley dim = 2;
2213c1cad2e7SMatthew G. Knepley cdim = 3;
2214c1cad2e7SMatthew G. Knepley numCorners = 3;
2215c1cad2e7SMatthew G. Knepley
2216c1cad2e7SMatthew G. Knepley /* NEED TO DEFINE MATRICES/VECTORS TO STORE GEOM REFERENCE DATA */
2217c1cad2e7SMatthew G. Knepley /* Fill in below and use to define DMLabels after DMPlex creation */
22189566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(totalNumPoints * cdim, &coords, totalNumTris * numCorners, &cells));
2219c1cad2e7SMatthew G. Knepley
2220c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) {
2221c1cad2e7SMatthew G. Knepley ego body = bodies[b];
2222c1cad2e7SMatthew G. Knepley int Nf;
2223c1cad2e7SMatthew G. Knepley PetscInt pointIndexStart;
2224c1cad2e7SMatthew G. Knepley PetscHashIter PISiter;
2225c1cad2e7SMatthew G. Knepley PetscBool PISfound;
2226c1cad2e7SMatthew G. Knepley
22279566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound));
22285552b385SBrandon PetscCheck(PISfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in pointIndexStartMap", b);
22299566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pointIndexStartMap, b, &pointIndexStart));
2230c1cad2e7SMatthew G. Knepley
22315552b385SBrandon if (islite) {
22325552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
22335552b385SBrandon } else {
22349566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
22355552b385SBrandon }
2236c1cad2e7SMatthew G. Knepley
2237c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) {
2238c1cad2e7SMatthew G. Knepley /* Get Face Object */
2239c1cad2e7SMatthew G. Knepley ego face = fobjs[f];
2240c1cad2e7SMatthew G. Knepley int len, fID, ntris;
2241c1cad2e7SMatthew G. Knepley const int *ptype, *pindex, *ptris, *ptric;
2242c1cad2e7SMatthew G. Knepley const double *pxyz, *puv;
2243c1cad2e7SMatthew G. Knepley
2244c1cad2e7SMatthew G. Knepley /* Get Face ID */
22455552b385SBrandon if (islite) {
22465552b385SBrandon fID = EGlite_indexBodyTopo(body, face);
22475552b385SBrandon } else {
2248c1cad2e7SMatthew G. Knepley fID = EG_indexBodyTopo(body, face);
22495552b385SBrandon }
2250c1cad2e7SMatthew G. Knepley
2251c1cad2e7SMatthew G. Knepley /* Checkout the Surface Tessellation */
22525552b385SBrandon if (islite) {
22535552b385SBrandon PetscCall(EGlite_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric));
22545552b385SBrandon } else {
22559566063dSJacob Faibussowitsch PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric));
22565552b385SBrandon }
2257c1cad2e7SMatthew G. Knepley
2258c1cad2e7SMatthew G. Knepley /* Check out the point index and coordinate */
2259c1cad2e7SMatthew G. Knepley for (int p = 0; p < len; ++p) {
2260c1cad2e7SMatthew G. Knepley int global;
2261c1cad2e7SMatthew G. Knepley PetscHashIter PTLiter, PILiter, PBLiter;
2262c1cad2e7SMatthew G. Knepley PetscBool PTLfound, PILfound, PBLfound;
2263c1cad2e7SMatthew G. Knepley
22645552b385SBrandon if (islite) {
22655552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, p + 1, &global));
22665552b385SBrandon } else {
22679566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global));
22685552b385SBrandon }
2269c1cad2e7SMatthew G. Knepley
2270c1cad2e7SMatthew G. Knepley /* Set the coordinates array for DAG */
2271c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 0] = pxyz[(p * 3) + 0];
2272c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 1] = pxyz[(p * 3) + 1];
2273c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 2] = pxyz[(p * 3) + 2];
2274c1cad2e7SMatthew G. Knepley
2275c1cad2e7SMatthew G. Knepley /* Store Geometry Label Information for DMLabel assignment later */
22769566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pTypeLabelMap, global - 1 + pointIndexStart, &PTLiter, &PTLfound));
22779566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pIndexLabelMap, global - 1 + pointIndexStart, &PILiter, &PILfound));
22789566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pBodyIndexLabelMap, global - 1 + pointIndexStart, &PBLiter, &PBLfound));
2279c1cad2e7SMatthew G. Knepley
22809566063dSJacob Faibussowitsch if (!PTLfound) PetscCall(PetscHMapISet(pTypeLabelMap, global - 1 + pointIndexStart, ptype[p]));
22819566063dSJacob Faibussowitsch if (!PILfound) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, pindex[p]));
22829566063dSJacob Faibussowitsch if (!PBLfound) PetscCall(PetscHMapISet(pBodyIndexLabelMap, global - 1 + pointIndexStart, b));
2283c1cad2e7SMatthew G. Knepley
22849566063dSJacob Faibussowitsch if (ptype[p] < 0) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, fID));
2285c1cad2e7SMatthew G. Knepley }
2286c1cad2e7SMatthew G. Knepley
2287c1cad2e7SMatthew G. Knepley for (int t = 0; t < (int)ntris; ++t) {
2288c1cad2e7SMatthew G. Knepley int global, globalA, globalB;
2289c1cad2e7SMatthew G. Knepley PetscHashIter TFLiter, TBLiter;
2290c1cad2e7SMatthew G. Knepley PetscBool TFLfound, TBLfound;
2291c1cad2e7SMatthew G. Knepley
22925552b385SBrandon if (islite) {
22935552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global));
22945552b385SBrandon } else {
22959566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global));
22965552b385SBrandon }
2297c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 0] = global - 1 + pointIndexStart;
2298c1cad2e7SMatthew G. Knepley
22995552b385SBrandon if (islite) {
23005552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA));
23015552b385SBrandon } else {
23029566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA));
23035552b385SBrandon }
2304c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 1] = globalA - 1 + pointIndexStart;
2305c1cad2e7SMatthew G. Knepley
23065552b385SBrandon if (islite) {
23075552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB));
23085552b385SBrandon } else {
23099566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB));
23105552b385SBrandon }
2311c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 2] = globalB - 1 + pointIndexStart;
2312c1cad2e7SMatthew G. Knepley
23139566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triFaceIDLabelMap, counter, &TFLiter, &TFLfound));
23149566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triBodyIDLabelMap, counter, &TBLiter, &TBLfound));
2315c1cad2e7SMatthew G. Knepley
23169566063dSJacob Faibussowitsch if (!TFLfound) PetscCall(PetscHMapISet(triFaceIDLabelMap, counter, fID));
23179566063dSJacob Faibussowitsch if (!TBLfound) PetscCall(PetscHMapISet(triBodyIDLabelMap, counter, b));
2318c1cad2e7SMatthew G. Knepley
2319c1cad2e7SMatthew G. Knepley counter += 1;
2320c1cad2e7SMatthew G. Knepley }
2321c1cad2e7SMatthew G. Knepley }
23225552b385SBrandon if (islite) {
23235552b385SBrandon EGlite_free(fobjs);
23245552b385SBrandon } else {
2325c1cad2e7SMatthew G. Knepley EG_free(fobjs);
2326c1cad2e7SMatthew G. Knepley }
2327c1cad2e7SMatthew G. Knepley }
23285552b385SBrandon PetscCall(PetscFree(tessArray));
23295552b385SBrandon }
2330c1cad2e7SMatthew G. Knepley
2331c1cad2e7SMatthew G. Knepley //Build DMPlex
23329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, totalNumTris, totalNumPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm));
23339566063dSJacob Faibussowitsch PetscCall(PetscFree2(coords, cells));
2334c1cad2e7SMatthew G. Knepley
2335c1cad2e7SMatthew G. Knepley // Embed EGADS model in DM
2336c1cad2e7SMatthew G. Knepley {
2337c1cad2e7SMatthew G. Knepley PetscContainer modelObj, contextObj;
2338c1cad2e7SMatthew G. Knepley
23399566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj));
23409566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model));
23415552b385SBrandon if (islite) {
23422a8381b2SBarry Smith PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSliteDestroy_Private));
23435552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Model", (PetscObject)modelObj));
23445552b385SBrandon } else {
23452a8381b2SBarry Smith PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSDestroy_Private));
23469566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj));
23475552b385SBrandon }
23489566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj));
2349c1cad2e7SMatthew G. Knepley
23509566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj));
23519566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context));
23525552b385SBrandon
23535552b385SBrandon if (islite) {
23542a8381b2SBarry Smith PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSliteClose_Private));
23555552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Context", (PetscObject)contextObj));
23565552b385SBrandon } else {
23572a8381b2SBarry Smith PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSClose_Private));
23589566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj));
23595552b385SBrandon }
23609566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj));
2361c1cad2e7SMatthew G. Knepley }
2362c1cad2e7SMatthew G. Knepley
2363c1cad2e7SMatthew G. Knepley // Label Points
23649566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID"));
23659566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
23669566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID"));
23679566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
23689566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID"));
23699566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
23709566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID"));
23719566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
2372c1cad2e7SMatthew G. Knepley
2373c1cad2e7SMatthew G. Knepley /* Get Number of DAG Nodes at each level */
2374c1cad2e7SMatthew G. Knepley int fStart, fEnd, eStart, eEnd, nStart, nEnd;
2375c1cad2e7SMatthew G. Knepley
23769566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &fStart, &fEnd));
23779566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &eStart, &eEnd));
23789566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd));
2379c1cad2e7SMatthew G. Knepley
2380c1cad2e7SMatthew G. Knepley /* Set DMLabels for NODES */
2381c1cad2e7SMatthew G. Knepley for (int n = nStart; n < nEnd; ++n) {
2382c1cad2e7SMatthew G. Knepley int pTypeVal, pIndexVal, pBodyVal;
2383c1cad2e7SMatthew G. Knepley PetscHashIter PTLiter, PILiter, PBLiter;
2384c1cad2e7SMatthew G. Knepley PetscBool PTLfound, PILfound, PBLfound;
2385c1cad2e7SMatthew G. Knepley
2386c1cad2e7SMatthew G. Knepley //Converted to Hash Tables
23879566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pTypeLabelMap, n - nStart, &PTLiter, &PTLfound));
23885552b385SBrandon PetscCheck(PTLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pTypeLabelMap", n);
23899566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pTypeLabelMap, n - nStart, &pTypeVal));
2390c1cad2e7SMatthew G. Knepley
23919566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pIndexLabelMap, n - nStart, &PILiter, &PILfound));
23925552b385SBrandon PetscCheck(PILfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pIndexLabelMap", n);
23939566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pIndexLabelMap, n - nStart, &pIndexVal));
2394c1cad2e7SMatthew G. Knepley
23959566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pBodyIndexLabelMap, n - nStart, &PBLiter, &PBLfound));
23965552b385SBrandon PetscCheck(PBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pBodyLabelMap", n);
23979566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pBodyIndexLabelMap, n - nStart, &pBodyVal));
2398c1cad2e7SMatthew G. Knepley
23999566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, n, pBodyVal));
24009566063dSJacob Faibussowitsch if (pTypeVal == 0) PetscCall(DMLabelSetValue(vertexLabel, n, pIndexVal));
24019566063dSJacob Faibussowitsch if (pTypeVal > 0) PetscCall(DMLabelSetValue(edgeLabel, n, pIndexVal));
24029566063dSJacob Faibussowitsch if (pTypeVal < 0) PetscCall(DMLabelSetValue(faceLabel, n, pIndexVal));
2403c1cad2e7SMatthew G. Knepley }
2404c1cad2e7SMatthew G. Knepley
2405c1cad2e7SMatthew G. Knepley /* Set DMLabels for Edges - Based on the DMLabels of the EDGE's NODES */
2406c1cad2e7SMatthew G. Knepley for (int e = eStart; e < eEnd; ++e) {
2407c1cad2e7SMatthew G. Knepley int bodyID_0, vertexID_0, vertexID_1, edgeID_0, edgeID_1, faceID_0, faceID_1;
2408c1cad2e7SMatthew G. Knepley
24099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone));
24109566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, cone[0], &bodyID_0)); // Do I need to check the other end?
24119566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, cone[0], &vertexID_0));
24129566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, cone[1], &vertexID_1));
24139566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[0], &edgeID_0));
24149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[1], &edgeID_1));
24159566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, cone[0], &faceID_0));
24169566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, cone[1], &faceID_1));
2417c1cad2e7SMatthew G. Knepley
24189566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, e, bodyID_0));
2419c1cad2e7SMatthew G. Knepley
24209566063dSJacob Faibussowitsch if (edgeID_0 == edgeID_1) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0));
24219566063dSJacob Faibussowitsch else if (vertexID_0 > 0 && edgeID_1 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_1));
24229566063dSJacob Faibussowitsch else if (vertexID_1 > 0 && edgeID_0 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0));
2423c1cad2e7SMatthew G. Knepley else { /* Do Nothing */ }
2424c1cad2e7SMatthew G. Knepley }
2425c1cad2e7SMatthew G. Knepley
2426c1cad2e7SMatthew G. Knepley /* Set DMLabels for Cells */
2427c1cad2e7SMatthew G. Knepley for (int f = fStart; f < fEnd; ++f) {
2428c1cad2e7SMatthew G. Knepley int edgeID_0;
2429c1cad2e7SMatthew G. Knepley PetscInt triBodyVal, triFaceVal;
2430c1cad2e7SMatthew G. Knepley PetscHashIter TFLiter, TBLiter;
2431c1cad2e7SMatthew G. Knepley PetscBool TFLfound, TBLfound;
2432c1cad2e7SMatthew G. Knepley
2433c1cad2e7SMatthew G. Knepley // Convert to Hash Table
24349566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triFaceIDLabelMap, f - fStart, &TFLiter, &TFLfound));
24355552b385SBrandon PetscCheck(TFLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in triFaceIDLabelMap", f);
24369566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(triFaceIDLabelMap, f - fStart, &triFaceVal));
2437c1cad2e7SMatthew G. Knepley
24389566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triBodyIDLabelMap, f - fStart, &TBLiter, &TBLfound));
24395552b385SBrandon PetscCheck(TBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in triBodyIDLabelMap", f);
24409566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(triBodyIDLabelMap, f - fStart, &triBodyVal));
2441c1cad2e7SMatthew G. Knepley
24429566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, f, triBodyVal));
24439566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, f, triFaceVal));
2444c1cad2e7SMatthew G. Knepley
2445c1cad2e7SMatthew G. Knepley /* Finish Labeling previously unlabeled DMPlex Edges - Assumes Triangular Cell (3 Edges Max) */
24469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, f, &cone));
2447c1cad2e7SMatthew G. Knepley
2448c1cad2e7SMatthew G. Knepley for (int jj = 0; jj < 3; ++jj) {
24499566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[jj], &edgeID_0));
2450c1cad2e7SMatthew G. Knepley
2451c1cad2e7SMatthew G. Knepley if (edgeID_0 < 0) {
24529566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[jj], triBodyVal));
24539566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[jj], triFaceVal));
2454c1cad2e7SMatthew G. Knepley }
2455c1cad2e7SMatthew G. Knepley }
2456c1cad2e7SMatthew G. Knepley }
2457c1cad2e7SMatthew G. Knepley
2458c1cad2e7SMatthew G. Knepley *newdm = dm;
24593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2460c1cad2e7SMatthew G. Knepley }
24617bee2925SMatthew Knepley #endif
24627bee2925SMatthew Knepley
24635552b385SBrandon /*@C
24645552b385SBrandon DMPlexInflateToGeomModelUseXYZ - Snaps the vertex coordinates of a `DMPLEX` object representing the mesh to its geometry if some vertices depart from the model. This usually happens with non-conforming refinement.
2465c1cad2e7SMatthew G. Knepley
246620f4b53cSBarry Smith Collective
2467c1cad2e7SMatthew G. Knepley
2468c1cad2e7SMatthew G. Knepley Input Parameter:
2469a1cb98faSBarry Smith . dm - The uninflated `DM` object representing the mesh
2470c1cad2e7SMatthew G. Knepley
2471c1cad2e7SMatthew G. Knepley Level: intermediate
2472c1cad2e7SMatthew G. Knepley
24731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`
2474c1cad2e7SMatthew G. Knepley @*/
DMPlexInflateToGeomModelUseXYZ(DM dm)2475ce78bad3SBarry Smith PetscErrorCode DMPlexInflateToGeomModelUseXYZ(DM dm) PeNS
2476d71ae5a4SJacob Faibussowitsch {
2477ce78bad3SBarry Smith // please don't fucking write code like this with #ifdef all of the place!
2478c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS)
2479c1cad2e7SMatthew G. Knepley /* EGADS Variables */
24805552b385SBrandon ego model, geom, body, face, edge, vertex;
2481c1cad2e7SMatthew G. Knepley ego *bodies;
2482c1cad2e7SMatthew G. Knepley int Nb, oclass, mtype, *senses;
24835552b385SBrandon double result[4];
2484c1cad2e7SMatthew G. Knepley /* PETSc Variables */
2485c1cad2e7SMatthew G. Knepley DM cdm;
2486c1cad2e7SMatthew G. Knepley PetscContainer modelObj;
2487c1cad2e7SMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
2488c1cad2e7SMatthew G. Knepley Vec coordinates;
2489c1cad2e7SMatthew G. Knepley PetscScalar *coords;
2490c1cad2e7SMatthew G. Knepley PetscInt bodyID, faceID, edgeID, vertexID;
2491c1cad2e7SMatthew G. Knepley PetscInt cdim, d, vStart, vEnd, v;
24925552b385SBrandon PetscBool islite = PETSC_FALSE;
2493c1cad2e7SMatthew G. Knepley #endif
2494c1cad2e7SMatthew G. Knepley
2495c1cad2e7SMatthew G. Knepley PetscFunctionBegin;
2496c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS)
24979566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
24985552b385SBrandon if (!modelObj) {
24995552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
25005552b385SBrandon islite = PETSC_TRUE;
25015552b385SBrandon }
25023ba16761SJacob Faibussowitsch if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS);
25039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim));
25049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm));
25059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
25069566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
25079566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
25089566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
25099566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
2510c1cad2e7SMatthew G. Knepley
25112a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(modelObj, &model));
25125552b385SBrandon
25135552b385SBrandon if (islite) {
25145552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
25155552b385SBrandon } else {
25169566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
25175552b385SBrandon }
2518c1cad2e7SMatthew G. Knepley
25199566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
25209566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords));
2521c1cad2e7SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) {
2522c1cad2e7SMatthew G. Knepley PetscScalar *vcoords;
2523c1cad2e7SMatthew G. Knepley
25249566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID));
25259566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, v, &faceID));
25269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID));
25279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID));
2528c1cad2e7SMatthew G. Knepley
25295552b385SBrandon PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bodyID, Nb);
25305552b385SBrandon body = bodies[bodyID];
25315552b385SBrandon
25325552b385SBrandon PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords));
25335552b385SBrandon if (vertexID > 0) {
25345552b385SBrandon if (islite) {
25355552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex));
25365552b385SBrandon PetscCall(EGlite_evaluate(vertex, NULL, result));
25375552b385SBrandon } else {
25385552b385SBrandon PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex));
25395552b385SBrandon PetscCall(EG_evaluate(vertex, NULL, result));
25405552b385SBrandon }
25415552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d];
25425552b385SBrandon } else if (edgeID > 0) {
25435552b385SBrandon /* Snap to EDGE at nearest location */
25445552b385SBrandon double params[1];
25455552b385SBrandon if (islite) {
25465552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge));
25475552b385SBrandon PetscCall(EGlite_invEvaluate(edge, vcoords, params, result));
25485552b385SBrandon } // Get (x,y,z) of nearest point on EDGE
25495552b385SBrandon else {
25505552b385SBrandon PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge));
25515552b385SBrandon PetscCall(EG_invEvaluate(edge, vcoords, params, result));
25525552b385SBrandon }
25535552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d];
25545552b385SBrandon } else if (faceID > 0) {
25555552b385SBrandon /* Snap to FACE at nearest location */
25565552b385SBrandon double params[2];
25575552b385SBrandon if (islite) {
25585552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face));
25595552b385SBrandon PetscCall(EGlite_invEvaluate(face, vcoords, params, result));
25605552b385SBrandon } // Get (x,y,z) of nearest point on FACE
25615552b385SBrandon else {
25625552b385SBrandon PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face));
25635552b385SBrandon PetscCall(EG_invEvaluate(face, vcoords, params, result));
25645552b385SBrandon }
25655552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d];
25665552b385SBrandon }
25675552b385SBrandon }
25685552b385SBrandon PetscCall(VecRestoreArrayWrite(coordinates, &coords));
25695552b385SBrandon /* Clear out global coordinates */
25705552b385SBrandon PetscCall(VecDestroy(&dm->coordinates[0].x));
25715552b385SBrandon #endif
25725552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
25735552b385SBrandon }
25745552b385SBrandon
25755552b385SBrandon #if defined(PETSC_HAVE_EGADS)
25765552b385SBrandon // This replaces the model in-place
ConvertGeomModelToAllBSplines(PetscBool islite,ego * model)2577ce78bad3SBarry Smith PetscErrorCode ConvertGeomModelToAllBSplines(PetscBool islite, ego *model) PeNS
25785552b385SBrandon {
25795552b385SBrandon /* EGADS/EGADSlite Variables */
25805552b385SBrandon ego context = NULL, geom, *bodies, *fobjs;
25815552b385SBrandon int oclass, mtype;
25825552b385SBrandon int *senses;
25835552b385SBrandon int Nb, Nf;
25845552b385SBrandon
25855552b385SBrandon PetscFunctionBegin;
25865552b385SBrandon // Get the number of bodies and body objects in the model
25875552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
25885552b385SBrandon else PetscCallEGADS(EG_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
25895552b385SBrandon
25905552b385SBrandon // Get all Faces on the body <-- Only working with 1 body at the moment.
25915552b385SBrandon ego body = bodies[0];
25925552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs));
25935552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs));
25945552b385SBrandon ego newGeom[Nf];
25955552b385SBrandon ego newFaces[Nf];
25965552b385SBrandon
25975552b385SBrandon // Convert the 1st Face to a BSpline Geometry
25985552b385SBrandon for (int ii = 0; ii < Nf; ++ii) {
25995552b385SBrandon ego face = fobjs[ii];
26005552b385SBrandon ego gRef, gPrev, gNext, *lobjs;
26015552b385SBrandon int goclass, gmtype, *gpinfo;
26025552b385SBrandon int Nl, *lsenses;
26035552b385SBrandon double *gprv;
26045552b385SBrandon char *gClass = (char *)"", *gType = (char *)"";
26055552b385SBrandon
26065552b385SBrandon /* Shape Optimization is NOT available for EGADSlite geometry files. */
26075552b385SBrandon /* Note :: islite options are left below in case future versions of EGADSlite includes this capability */
26085552b385SBrandon PetscCheck(!islite, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot convert geometric entities to all BSplines for geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep");
26095552b385SBrandon
26105552b385SBrandon if (islite) {
26115552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_
26125552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info
26135552b385SBrandon PetscCallEGADS(EGlite_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext));
26145552b385SBrandon } // Get geometry info
26155552b385SBrandon else {
26165552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_
26175552b385SBrandon PetscCallEGADS(EG_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info
26185552b385SBrandon PetscCallEGADS(EG_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext));
26195552b385SBrandon } // Get geometry info
26205552b385SBrandon
26215552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType)); // Decode Geometry integers
26225552b385SBrandon
26235552b385SBrandon // Convert current FACE to a BSpline Surface
26245552b385SBrandon ego bspline;
26255552b385SBrandon ego bRef, bPrev, bNext;
26265552b385SBrandon int boclass, bmtype, *bpinfo;
26275552b385SBrandon double *bprv;
26285552b385SBrandon char *bClass = (char *)"", *bType = (char *)"";
26295552b385SBrandon
26305552b385SBrandon PetscCallEGADS(EG_convertToBSpline, (face, &bspline)); // Does not have an EGlite_ version
26315552b385SBrandon
26325552b385SBrandon if (islite) {
26335552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info
26345552b385SBrandon PetscCallEGADS(EGlite_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext));
26355552b385SBrandon } // Get geometry info
26365552b385SBrandon else {
26375552b385SBrandon PetscCallEGADS(EG_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info
26385552b385SBrandon PetscCallEGADS(EG_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext));
26395552b385SBrandon } // Get geometry info
26405552b385SBrandon
26415552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(boclass, bmtype, &bClass, &bType)); // Decode Geometry integers
26425552b385SBrandon
26435552b385SBrandon // Get Context from FACE
26445552b385SBrandon context = NULL;
26455552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version
26465552b385SBrandon
26475552b385SBrandon // Silence WARNING Regarding OPENCASCADE 7.5
26485552b385SBrandon if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 0));
26495552b385SBrandon else PetscCallEGADS(EG_setOutLevel, (context, 0));
26505552b385SBrandon
26515552b385SBrandon ego newgeom;
26525552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version
26535552b385SBrandon
26545552b385SBrandon PetscCallEGADS(EG_deleteObject, (bspline));
26555552b385SBrandon
26565552b385SBrandon // Create new FACE based on new SURFACE geometry
26575552b385SBrandon double data[4];
26585552b385SBrandon int periodic;
26595552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic));
26605552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic));
26615552b385SBrandon
26625552b385SBrandon ego newface;
26635552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version
26645552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newgeom));
26655552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newface));
26665552b385SBrandon newFaces[ii] = newface;
26675552b385SBrandon newGeom[ii] = newgeom;
26685552b385SBrandon
26695552b385SBrandon // Reinstate WARNING Regarding OPENCASCADE 7.5
26705552b385SBrandon if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 1));
26715552b385SBrandon else PetscCallEGADS(EG_setOutLevel, (context, 1));
26725552b385SBrandon }
26735552b385SBrandon
26745552b385SBrandon // Sew New Faces together to get a new model
26755552b385SBrandon ego newmodel;
26765552b385SBrandon PetscCallEGADS(EG_sewFaces, (Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version
26775552b385SBrandon for (int ii = 0; ii < Nf; ++ii) {
26785552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[ii]));
26795552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[ii]));
26805552b385SBrandon }
26815552b385SBrandon PetscCallEGADS(EG_deleteObject, (*model));
26825552b385SBrandon *model = newmodel;
26835552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
26845552b385SBrandon }
26855552b385SBrandon #endif
26865552b385SBrandon
26875552b385SBrandon /*@C
26885552b385SBrandon DMPlexCreateGeomFromFile - Create a `DMPLEX` mesh from an EGADS, IGES, or STEP file.
26895552b385SBrandon
26905552b385SBrandon Collective
26915552b385SBrandon
26925552b385SBrandon Input Parameters:
26935552b385SBrandon + comm - The MPI communicator
26945552b385SBrandon . filename - The name of the EGADS, IGES, or STEP file
26955552b385SBrandon - islite - Flag for EGADSlite support
26965552b385SBrandon
26975552b385SBrandon Output Parameter:
26985552b385SBrandon . dm - The `DM` object representing the mesh
26995552b385SBrandon
27005552b385SBrandon Level: beginner
27015552b385SBrandon
27025552b385SBrandon .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`, `DMPlexCreateEGADSliteFromFile()`
27035552b385SBrandon @*/
DMPlexCreateGeomFromFile(MPI_Comm comm,const char filename[],DM * dm,PetscBool islite)2704ce78bad3SBarry Smith PetscErrorCode DMPlexCreateGeomFromFile(MPI_Comm comm, const char filename[], DM *dm, PetscBool islite) PeNS
27055552b385SBrandon {
27065552b385SBrandon /* PETSc Variables */
27075552b385SBrandon PetscMPIInt rank;
27085552b385SBrandon PetscBool printModel = PETSC_FALSE, tessModel = PETSC_FALSE, newModel = PETSC_FALSE;
27095552b385SBrandon PetscBool shapeOpt = PETSC_FALSE;
27105552b385SBrandon
27115552b385SBrandon #if defined(PETSC_HAVE_EGADS)
27125552b385SBrandon ego context = NULL, model = NULL;
27135552b385SBrandon #endif
27145552b385SBrandon
27155552b385SBrandon PetscFunctionBegin;
27165552b385SBrandon PetscAssertPointer(filename, 2);
27175552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_print_model", &printModel, NULL));
27185552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_tess_model", &tessModel, NULL));
27195552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_new_model", &newModel, NULL));
27205552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_shape_opt", &shapeOpt, NULL));
27215552b385SBrandon PetscCallMPI(MPI_Comm_rank(comm, &rank));
27225552b385SBrandon #if defined(PETSC_HAVE_EGADS)
27235552b385SBrandon if (rank == 0) {
27245552b385SBrandon /* EGADSlite files cannot be used for Shape Optimization Work. It lacks the ability to make new geometry. */
27255552b385SBrandon /* Must use EGADS, STEP, IGES or BRep files to perform this work. */
27265552b385SBrandon if (islite) {
27275552b385SBrandon PetscCallEGADS(EGlite_open, (&context));
27285552b385SBrandon PetscCallEGADS(EGlite_loadModel, (context, 0, filename, &model));
27295552b385SBrandon if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model));
27305552b385SBrandon if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite));
27315552b385SBrandon } else {
27325552b385SBrandon PetscCallEGADS(EG_open, (&context));
27335552b385SBrandon PetscCallEGADS(EG_loadModel, (context, 0, filename, &model));
27345552b385SBrandon if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model));
27355552b385SBrandon if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite));
27365552b385SBrandon }
27375552b385SBrandon }
27385552b385SBrandon if (tessModel) PetscCall(DMPlexCreateGeom_Tess_Internal(comm, context, model, dm, islite));
27395552b385SBrandon else if (newModel) PetscCall(DMPlexCreateGeom_Internal(comm, context, model, dm, islite));
27403a7d0413SPierre Jolivet else PetscCall(DMPlexCreateGeom(comm, context, model, dm, islite));
27415552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
27425552b385SBrandon #else
27435552b385SBrandon SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads");
27445552b385SBrandon #endif
27455552b385SBrandon }
27465552b385SBrandon
27475552b385SBrandon #if defined(PETSC_HAVE_EGADS)
27485552b385SBrandon /*@C
27495552b385SBrandon DMPlex_Surface_Grad - Exposes the Geometry's Control Points and Weights and Calculates the Mesh Topology Boundary Nodes Gradient
27505552b385SBrandon with respect the associated geometry's Control Points and Weights.
27515552b385SBrandon
27525552b385SBrandon // ----- Depreciated ---- See DMPlexGeomDataAndGrads ------ //
27535552b385SBrandon
27545552b385SBrandon Collective
27555552b385SBrandon
27565552b385SBrandon Input Parameters:
27575552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model
27585552b385SBrandon
27595552b385SBrandon Output Parameter:
27605552b385SBrandon . dm - The DM object representing the mesh with PetscContainers containing the EGADS geometry model, Array-Hash Table Geometry Control Point Pair, Array-Hash Table Geometry Weights Pair and Matrix-Hash Table Surface Gradient Pair
27615552b385SBrandon
27625552b385SBrandon Level: intermediate
27635552b385SBrandon
27645552b385SBrandon .seealso:
27655552b385SBrandon @*/
DMPlex_Surface_Grad(DM dm)27665552b385SBrandon PetscErrorCode DMPlex_Surface_Grad(DM dm)
27675552b385SBrandon {
27685552b385SBrandon ego model, geom, *bodies, *fobjs;
27695552b385SBrandon PetscContainer modelObj;
27705552b385SBrandon int oclass, mtype, *senses;
27715552b385SBrandon int Nb, Nf;
27725552b385SBrandon PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL;
27735552b385SBrandon PetscHMapI pointSurfGradRow_Start = NULL;
27745552b385SBrandon Mat pointSurfGrad;
27755552b385SBrandon IS faceLabelValues, edgeLabelValues, vertexLabelValues;
27765552b385SBrandon PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize;
27775552b385SBrandon PetscBool islite = PETSC_FALSE;
27785552b385SBrandon
27795552b385SBrandon PetscFunctionBegin;
27805552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
27815552b385SBrandon if (!modelObj) {
27825552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
27835552b385SBrandon islite = PETSC_TRUE;
27845552b385SBrandon SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, " Cannot provide geometric data or associated calculated gradients for geometries defined by EGADSlite (.egadslite)! \n Please use another geometry file format STEP, IGES, EGADS or BRep");
27855552b385SBrandon }
27865552b385SBrandon
27875552b385SBrandon // Get attached EGADS model (pointer)
27882a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(modelObj, &model));
27895552b385SBrandon
27905552b385SBrandon // Get the bodies in the model
27915552b385SBrandon if (islite) {
27925552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
27935552b385SBrandon } else {
27945552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
27955552b385SBrandon }
27965552b385SBrandon
27975552b385SBrandon ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body.
27985552b385SBrandon
27995552b385SBrandon // Get the total number of FACEs in the model
28005552b385SBrandon if (islite) {
28015552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
28025552b385SBrandon } else {
28035552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
28045552b385SBrandon }
28055552b385SBrandon
28065552b385SBrandon // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label"
28075552b385SBrandon // This will provide the total number of DMPlex points on the boundary of the geometry
28085552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues));
28095552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize));
28105552b385SBrandon
28115552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues));
28125552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize));
28135552b385SBrandon
28145552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues));
28155552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize));
28165552b385SBrandon
28175552b385SBrandon const PetscInt *faceIndices, *edgeIndices, *vertexIndices;
28185552b385SBrandon PetscCall(ISGetIndices(faceLabelValues, &faceIndices));
28195552b385SBrandon PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices));
28205552b385SBrandon PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices));
28215552b385SBrandon
28225552b385SBrandon // Get the points associated with each FACE, EDGE and VERTEX label in the DM
28235552b385SBrandon PetscInt totalNumPoints = 0;
28245552b385SBrandon for (int ii = 0; ii < faceLabelSize; ++ii) {
28255552b385SBrandon // Cycle through FACE labels
28265552b385SBrandon PetscInt size;
28275552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[ii], &size));
28285552b385SBrandon totalNumPoints += size;
28295552b385SBrandon }
28305552b385SBrandon PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices));
28315552b385SBrandon PetscCall(ISDestroy(&faceLabelValues));
28325552b385SBrandon
28335552b385SBrandon for (int ii = 0; ii < edgeLabelSize; ++ii) {
28345552b385SBrandon // Cycle Through EDGE Labels
28355552b385SBrandon PetscInt size;
28365552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[ii], &size));
28375552b385SBrandon totalNumPoints += size;
28385552b385SBrandon }
28395552b385SBrandon PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices));
28405552b385SBrandon PetscCall(ISDestroy(&edgeLabelValues));
28415552b385SBrandon
28425552b385SBrandon for (int ii = 0; ii < vertexLabelSize; ++ii) {
28435552b385SBrandon // Cycle Through VERTEX Labels
28445552b385SBrandon PetscInt size;
28455552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size));
28465552b385SBrandon totalNumPoints += size;
28475552b385SBrandon }
28485552b385SBrandon PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices));
28495552b385SBrandon PetscCall(ISDestroy(&vertexLabelValues));
28505552b385SBrandon
28515552b385SBrandon int maxNumCPs = 0;
28525552b385SBrandon int totalNumCPs = 0;
28535552b385SBrandon ego bRef, bPrev, bNext, fgeom, *lobjs;
28545552b385SBrandon int id, boclass, bmtype, *bpinfo;
28555552b385SBrandon int foclass, fmtype, Nl, *lsenses;
28565552b385SBrandon double *bprv;
28575552b385SBrandon double fdata[4];
28585552b385SBrandon
28595552b385SBrandon // Create Hash Tables
28605552b385SBrandon PetscInt cntr = 0, wcntr = 0;
28615552b385SBrandon PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start));
28625552b385SBrandon PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start));
28635552b385SBrandon
28645552b385SBrandon for (int ii = 0; ii < Nf; ++ii) {
28655552b385SBrandon // Need to get the maximum number of Control Points defining the FACEs
28665552b385SBrandon ego face = fobjs[ii];
28675552b385SBrandon int maxNumCPs_temp;
28685552b385SBrandon
28695552b385SBrandon if (islite) {
28705552b385SBrandon id = EGlite_indexBodyTopo(body, face);
28715552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
28725552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
28735552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
28745552b385SBrandon } else {
28755552b385SBrandon id = EG_indexBodyTopo(body, face);
28765552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
28775552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
28785552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
28795552b385SBrandon }
28805552b385SBrandon
28815552b385SBrandon maxNumCPs_temp = bpinfo[2] * bpinfo[5];
28825552b385SBrandon totalNumCPs += bpinfo[2] * bpinfo[5];
28835552b385SBrandon
2884ac530a7eSPierre Jolivet if (maxNumCPs_temp > maxNumCPs) maxNumCPs = maxNumCPs_temp;
28855552b385SBrandon }
28865552b385SBrandon
28875552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr;
28885552b385SBrandon PetscInt cpCoordDataLength = 3 * totalNumCPs;
28895552b385SBrandon PetscInt wDataLength = totalNumCPs;
28905552b385SBrandon cpCoordDataLengthPtr = &cpCoordDataLength;
28915552b385SBrandon wDataLengthPtr = &wDataLength;
28925552b385SBrandon PetscScalar *cntrlPtCoords, *cntrlPtWeights;
28935552b385SBrandon PetscMalloc1(cpCoordDataLength, &cntrlPtCoords);
28945552b385SBrandon PetscMalloc1(wDataLength, &cntrlPtWeights);
28955552b385SBrandon for (int ii = 0; ii < Nf; ++ii) {
28965552b385SBrandon // Need to Populate Control Point Coordinates and Weight Vectors
28975552b385SBrandon ego face = fobjs[ii];
28985552b385SBrandon PetscHashIter hashKeyIter, wHashKeyIter;
28995552b385SBrandon PetscBool hashKeyFound, wHashKeyFound;
29005552b385SBrandon
29015552b385SBrandon if (islite) {
29025552b385SBrandon id = EGlite_indexBodyTopo(body, face);
29035552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
29045552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
29055552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
29065552b385SBrandon } else {
29075552b385SBrandon id = EG_indexBodyTopo(body, face);
29085552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
29095552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
29105552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
29115552b385SBrandon }
29125552b385SBrandon
29135552b385SBrandon // Store Face ID to 1st Row of Control Point Vector
29145552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound));
29155552b385SBrandon
29163a7d0413SPierre Jolivet if (!hashKeyFound) PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr));
29175552b385SBrandon
29185552b385SBrandon int offsetCoord = bpinfo[3] + bpinfo[6];
29195552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) {
29205552b385SBrandon cntrlPtCoords[cntr] = bprv[offsetCoord + jj];
29215552b385SBrandon cntr += 1;
29225552b385SBrandon }
29235552b385SBrandon
29245552b385SBrandon // Store Face ID to 1st Row of Control Point Weight Vector
29255552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound));
29265552b385SBrandon
29273a7d0413SPierre Jolivet if (!wHashKeyFound) PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr));
29285552b385SBrandon
29295552b385SBrandon int offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]);
29305552b385SBrandon for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) {
29315552b385SBrandon cntrlPtWeights[wcntr] = bprv[offsetWeight + jj];
29325552b385SBrandon wcntr += 1;
29335552b385SBrandon }
29345552b385SBrandon }
29355552b385SBrandon
29365552b385SBrandon // Attach Control Point and Weight Data to DM
29375552b385SBrandon {
29385552b385SBrandon PetscContainer cpOrgObj, cpCoordObj, cpCoordLengthObj;
29395552b385SBrandon PetscContainer wOrgObj, wValObj, wDataLengthObj;
29405552b385SBrandon
29415552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj));
29425552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start));
29435552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj));
29445552b385SBrandon PetscCall(PetscContainerDestroy(&cpOrgObj));
29455552b385SBrandon
29465552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordObj));
29475552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordObj, cntrlPtCoords));
29485552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cpCoordObj));
29495552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordObj));
29505552b385SBrandon
29515552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj));
29525552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr));
29535552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj));
29545552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordLengthObj));
29555552b385SBrandon
29565552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj));
29575552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start));
29585552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj));
29595552b385SBrandon PetscCall(PetscContainerDestroy(&wOrgObj));
29605552b385SBrandon
29615552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wValObj));
29625552b385SBrandon PetscCall(PetscContainerSetPointer(wValObj, cntrlPtWeights));
29635552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)wValObj));
29645552b385SBrandon PetscCall(PetscContainerDestroy(&wValObj));
29655552b385SBrandon
29665552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj));
29675552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr));
29685552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj));
29695552b385SBrandon PetscCall(PetscContainerDestroy(&wDataLengthObj));
29705552b385SBrandon }
29715552b385SBrandon
29725552b385SBrandon // Define Matrix to store Surface Gradient information dx_i/dCPj_i
29735552b385SBrandon PetscInt gcntr = 0;
29745552b385SBrandon const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints;
29755552b385SBrandon const PetscInt colSize = 4 * Nf;
29765552b385SBrandon
29775552b385SBrandon // Create Point Surface Gradient Matrix
29785552b385SBrandon MatCreate(PETSC_COMM_WORLD, &pointSurfGrad);
29795552b385SBrandon MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize);
29805552b385SBrandon MatSetType(pointSurfGrad, MATAIJ);
29815552b385SBrandon MatSetUp(pointSurfGrad);
29825552b385SBrandon
29835552b385SBrandon // Create Hash Table to store Point's stare row in surfaceGrad[][]
29845552b385SBrandon PetscCall(PetscHMapICreate(&pointSurfGradRow_Start));
29855552b385SBrandon
29865552b385SBrandon // Get Coordinates for the DMPlex point
29875552b385SBrandon DM cdm;
29885552b385SBrandon PetscInt dE, Nv;
29895552b385SBrandon Vec coordinatesLocal;
29905552b385SBrandon PetscScalar *coords = NULL;
29915552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm));
29925552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &dE));
29935552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
29945552b385SBrandon
29955552b385SBrandon // CYCLE THROUGH FACEs
29965552b385SBrandon for (int ii = 0; ii < Nf; ++ii) {
29975552b385SBrandon ego face = fobjs[ii];
29985552b385SBrandon ego *eobjs, *nobjs;
29995552b385SBrandon PetscInt fid, Ne, Nn;
30005552b385SBrandon DMLabel faceLabel, edgeLabel, nodeLabel;
30015552b385SBrandon PetscHMapI currFaceUniquePoints = NULL;
30025552b385SBrandon IS facePoints, edgePoints, nodePoints;
30035552b385SBrandon const PetscInt *fIndices, *eIndices, *nIndices;
30045552b385SBrandon PetscInt fSize, eSize, nSize;
30055552b385SBrandon PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter;
30065552b385SBrandon PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound;
30075552b385SBrandon PetscInt cfCntr = 0;
30085552b385SBrandon
30095552b385SBrandon // Get Geometry Object for the Current FACE
30105552b385SBrandon if (islite) {
30115552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
30125552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
30135552b385SBrandon } else {
30145552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
30155552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
30165552b385SBrandon }
30175552b385SBrandon
30185552b385SBrandon // Get all EDGE and NODE objects attached to the current FACE
30195552b385SBrandon if (islite) {
30205552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs));
30215552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs));
30225552b385SBrandon } else {
30235552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs));
30245552b385SBrandon PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs));
30255552b385SBrandon }
30265552b385SBrandon
30275552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use
30285552b385SBrandon if (islite) {
30295552b385SBrandon fid = EGlite_indexBodyTopo(body, face);
30305552b385SBrandon } else {
30315552b385SBrandon fid = EG_indexBodyTopo(body, face);
30325552b385SBrandon }
30335552b385SBrandon
30345552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
30355552b385SBrandon PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints));
30365552b385SBrandon PetscCall(ISGetIndices(facePoints, &fIndices));
30375552b385SBrandon PetscCall(ISGetSize(facePoints, &fSize));
30385552b385SBrandon
30395552b385SBrandon PetscCall(PetscHMapICreate(&currFaceUniquePoints));
30405552b385SBrandon
30415552b385SBrandon for (int jj = 0; jj < fSize; ++jj) {
30425552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound));
30435552b385SBrandon
30445552b385SBrandon if (!fHashKeyFound) {
30455552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr));
30465552b385SBrandon cfCntr += 1;
30475552b385SBrandon }
30485552b385SBrandon
30495552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound));
30505552b385SBrandon
30515552b385SBrandon if (!pHashKeyFound) {
30525552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr));
30535552b385SBrandon gcntr += 3 * maxNumCPs;
30545552b385SBrandon }
30555552b385SBrandon }
30565552b385SBrandon PetscCall(ISRestoreIndices(facePoints, &fIndices));
30575552b385SBrandon PetscCall(ISDestroy(&facePoints));
30585552b385SBrandon
30595552b385SBrandon // Get all DMPlex Points that have DMLable "EGADS Edge ID" attached to the current FACE and store them in a Hash Table for later use.
30605552b385SBrandon for (int jj = 0; jj < Ne; ++jj) {
30615552b385SBrandon ego edge = eobjs[jj];
30625552b385SBrandon PetscBool containLabelValue;
30635552b385SBrandon
30645552b385SBrandon if (islite) {
30655552b385SBrandon id = EGlite_indexBodyTopo(body, edge);
30665552b385SBrandon } else {
30675552b385SBrandon id = EG_indexBodyTopo(body, edge);
30685552b385SBrandon }
30695552b385SBrandon
30705552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
30715552b385SBrandon PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue));
30725552b385SBrandon
30735552b385SBrandon if (containLabelValue) {
30745552b385SBrandon PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints));
30755552b385SBrandon PetscCall(ISGetIndices(edgePoints, &eIndices));
30765552b385SBrandon PetscCall(ISGetSize(edgePoints, &eSize));
30775552b385SBrandon
30785552b385SBrandon for (int kk = 0; kk < eSize; ++kk) {
30795552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound));
30805552b385SBrandon
30815552b385SBrandon if (!eHashKeyFound) {
30825552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr));
30835552b385SBrandon cfCntr += 1;
30845552b385SBrandon }
30855552b385SBrandon
30865552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound));
30875552b385SBrandon
30885552b385SBrandon if (!pHashKeyFound) {
30895552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr));
30905552b385SBrandon gcntr += 3 * maxNumCPs;
30915552b385SBrandon }
30925552b385SBrandon }
30935552b385SBrandon PetscCall(ISRestoreIndices(edgePoints, &eIndices));
30945552b385SBrandon PetscCall(ISDestroy(&edgePoints));
30955552b385SBrandon }
30965552b385SBrandon }
30975552b385SBrandon
30985552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Vertex ID" attached to the current FACE and store them in a Hash Table for later use.
30995552b385SBrandon for (int jj = 0; jj < Nn; ++jj) {
31005552b385SBrandon ego node = nobjs[jj];
31015552b385SBrandon
31025552b385SBrandon if (islite) {
31035552b385SBrandon id = EGlite_indexBodyTopo(body, node);
31045552b385SBrandon } else {
31055552b385SBrandon id = EG_indexBodyTopo(body, node);
31065552b385SBrandon }
31075552b385SBrandon
31085552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel));
31095552b385SBrandon PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints));
31105552b385SBrandon PetscCall(ISGetIndices(nodePoints, &nIndices));
31115552b385SBrandon PetscCall(ISGetSize(nodePoints, &nSize));
31125552b385SBrandon
31135552b385SBrandon for (int kk = 0; kk < nSize; ++kk) {
31145552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound));
31155552b385SBrandon
31165552b385SBrandon if (!nHashKeyFound) {
31175552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr));
31185552b385SBrandon cfCntr += 1;
31195552b385SBrandon }
31205552b385SBrandon
31215552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound));
31225552b385SBrandon if (!pHashKeyFound) {
31235552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr));
31245552b385SBrandon gcntr += 3 * maxNumCPs;
31255552b385SBrandon }
31265552b385SBrandon }
31275552b385SBrandon PetscCall(ISRestoreIndices(nodePoints, &nIndices));
31285552b385SBrandon PetscCall(ISDestroy(&nodePoints));
31295552b385SBrandon }
31305552b385SBrandon
31315552b385SBrandon // Get the Total Number of entries in the Hash Table
31325552b385SBrandon PetscInt currFaceUPSize;
31335552b385SBrandon PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize));
31345552b385SBrandon
31355552b385SBrandon // Get Keys
31365552b385SBrandon PetscInt currFaceUPKeys[currFaceUPSize], off = 0;
31375552b385SBrandon PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys));
31385552b385SBrandon
31395552b385SBrandon // Cycle through all points on the current FACE
31405552b385SBrandon for (int jj = 0; jj < currFaceUPSize; ++jj) {
31415552b385SBrandon PetscInt currPointID = currFaceUPKeys[jj];
31425552b385SBrandon PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords));
31435552b385SBrandon
31445552b385SBrandon // Get UV position of FACE
31455552b385SBrandon double params[2], range[4], eval[18];
31465552b385SBrandon int peri;
31475552b385SBrandon
31485552b385SBrandon if (islite) {
31495552b385SBrandon PetscCall(EGlite_getRange(face, range, &peri));
31505552b385SBrandon } else {
31515552b385SBrandon PetscCall(EG_getRange(face, range, &peri));
31525552b385SBrandon }
31535552b385SBrandon
31545552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite));
31555552b385SBrandon
31565552b385SBrandon if (islite) {
31575552b385SBrandon PetscCall(EGlite_evaluate(face, params, eval));
31585552b385SBrandon } else {
31595552b385SBrandon PetscCall(EG_evaluate(face, params, eval));
31605552b385SBrandon }
31615552b385SBrandon
31625552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points
31635552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]);
31645552b385SBrandon double nbprv[prvSize];
31655552b385SBrandon
31665552b385SBrandon // Cycle through each Control Point
31675552b385SBrandon double deltaCoord = 1.0E-4;
31685552b385SBrandon int offset = bpinfo[3] + bpinfo[6];
31695552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]);
31705552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) {
31715552b385SBrandon // Cycle through each direction (x, then y, then z)
31725552b385SBrandon for (int kk = 0; kk < 4; ++kk) {
31735552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time
3174ac530a7eSPierre Jolivet for (int mm = 0; mm < prvSize; ++mm) nbprv[mm] = bprv[mm];
31755552b385SBrandon
31765552b385SBrandon if (kk == 0) { //X
31775552b385SBrandon nbprv[offset + 0] = bprv[offset + 0] + deltaCoord;
31785552b385SBrandon nbprv[offset + 1] = bprv[offset + 1];
31795552b385SBrandon nbprv[offset + 2] = bprv[offset + 2];
31805552b385SBrandon } else if (kk == 1) { //Y
31815552b385SBrandon nbprv[offset + 0] = bprv[offset + 0];
31825552b385SBrandon nbprv[offset + 1] = bprv[offset + 1] + deltaCoord;
31835552b385SBrandon nbprv[offset + 2] = bprv[offset + 2];
31845552b385SBrandon } else if (kk == 2) { //Z
31855552b385SBrandon nbprv[offset + 0] = bprv[offset + 0];
31865552b385SBrandon nbprv[offset + 1] = bprv[offset + 1];
31875552b385SBrandon nbprv[offset + 2] = bprv[offset + 2] + deltaCoord;
31885552b385SBrandon } else if (kk == 3) { // Weights
31895552b385SBrandon nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord;
31905552b385SBrandon } else {
31915552b385SBrandon // currently do nothing
31925552b385SBrandon }
31935552b385SBrandon
31945552b385SBrandon // Create New Surface Based on New Control Points or Weights
31955552b385SBrandon ego newgeom, context;
31965552b385SBrandon if (islite) {
31975552b385SBrandon PetscCall(EGlite_open(&context));
31985552b385SBrandon PetscCall(EGlite_setOutLevel(context, 0));
31995552b385SBrandon } else {
32005552b385SBrandon PetscCall(EG_open(&context));
32015552b385SBrandon PetscCall(EG_setOutLevel(context, 0));
32025552b385SBrandon }
32035552b385SBrandon
32045552b385SBrandon PetscCall(EG_makeGeometry(context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE
32055552b385SBrandon
32065552b385SBrandon if (islite) {
32075552b385SBrandon PetscCall(EGlite_setOutLevel(context, 1));
32085552b385SBrandon } else {
32095552b385SBrandon PetscCall(EG_setOutLevel(context, 1));
32105552b385SBrandon }
32115552b385SBrandon
32125552b385SBrandon // Evaluate new (x, y, z) Point Position based on new Surface Definition
32135552b385SBrandon double newCoords[18];
32145552b385SBrandon if (islite) {
32155552b385SBrandon PetscCall(EGlite_getRange(newgeom, range, &peri));
32165552b385SBrandon } else {
32175552b385SBrandon PetscCall(EG_getRange(newgeom, range, &peri));
32185552b385SBrandon }
32195552b385SBrandon
32205552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, newgeom, range, 0, dE, params, islite));
32215552b385SBrandon
32225552b385SBrandon if (islite) {
32235552b385SBrandon PetscCall(EGlite_evaluate(newgeom, params, newCoords));
32245552b385SBrandon } else {
32255552b385SBrandon PetscCall(EG_evaluate(newgeom, params, newCoords));
32265552b385SBrandon }
32275552b385SBrandon
32285552b385SBrandon // Now Calculate the Surface Gradient for the change in x-component Control Point
32295552b385SBrandon PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord;
32305552b385SBrandon PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord;
32315552b385SBrandon PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord;
32325552b385SBrandon
32335552b385SBrandon // Store Gradient Information in surfaceGrad[][] Matrix
32345552b385SBrandon PetscInt startRow;
32355552b385SBrandon PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow));
32365552b385SBrandon
3237f0b74427SPierre Jolivet // Store Results in PETSc Mat
32385552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES));
32395552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES));
32405552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES));
32415552b385SBrandon }
32425552b385SBrandon offset += 3;
32435552b385SBrandon }
32445552b385SBrandon PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords));
32455552b385SBrandon }
32465552b385SBrandon }
32475552b385SBrandon
32485552b385SBrandon // Assemble Point Surface Grad Matrix
32495552b385SBrandon MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY);
32505552b385SBrandon MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY);
32515552b385SBrandon
32525552b385SBrandon // Attach Surface Gradient Hash Table and Matrix to DM
32535552b385SBrandon {
32545552b385SBrandon PetscContainer surfGradOrgObj, surfGradObj;
32555552b385SBrandon
32565552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj));
32575552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start));
32585552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj));
32595552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradOrgObj));
32605552b385SBrandon
32615552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradObj));
32625552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradObj, pointSurfGrad));
32635552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)surfGradObj));
32645552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradObj));
32655552b385SBrandon }
32665552b385SBrandon if (islite) EGlite_free(fobjs);
32675552b385SBrandon else EG_free(fobjs);
32685552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
32695552b385SBrandon }
32705552b385SBrandon
DestroyHashMap(PetscCtxRt p)32712a8381b2SBarry Smith static PetscErrorCode DestroyHashMap(PetscCtxRt p)
32725552b385SBrandon {
32735552b385SBrandon PetscFunctionBegin;
32745552b385SBrandon PetscCall(PetscHMapIDestroy((PetscHMapI *)p));
32755552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
32765552b385SBrandon }
32775552b385SBrandon #endif
32785552b385SBrandon
32795552b385SBrandon /*@C
32805552b385SBrandon DMPlexGeomDataAndGrads - Exposes Control Points and Control Point Weights defining the underlying geometry allowing user manipulation of the geometry.
32815552b385SBrandon
32825552b385SBrandon Collective
32835552b385SBrandon
32845552b385SBrandon Input Parameters:
32855552b385SBrandon + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model
32865552b385SBrandon - fullGeomGrad - PetscBool flag. Determines how the Surface Area and Volume Gradients wrt to Control Points and Control Point Weights are calculated.
32875552b385SBrandon PETSC_FALSE :: Surface Area Gradient wrt Control Points and Control Point Weights are calculated using the change in the local
32885552b385SBrandon FACE changes (not the entire body). Volume Gradients are not calculated. Faster computations.
32895552b385SBrandon PETSC_TRUE :: Surface Area Gradietn wrt to Control Points and Control Point Weights are calculated using the change observed in
32905552b385SBrandon the entire solid body. Volume Gradients are calculated. Slower computation due to the need to generate a new solid
32915552b385SBrandon body geometry for every Control Point and Control Point Weight change.
32925552b385SBrandon
32935552b385SBrandon Output Parameter:
32945552b385SBrandon . dm - The updated DM object representing the mesh with PetscContainers containing the Control Point, Control Point Weight and Gradient Data.
32955552b385SBrandon
32965552b385SBrandon Level: intermediate
32975552b385SBrandon
32985552b385SBrandon Note:
32995552b385SBrandon Calculates the DM Point location, surface area and volume gradients wrt to Control Point and Control Point Weights using Finite Difference (small perturbation of Control Point coordinates or Control Point Weight value).
33005552b385SBrandon
33015552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexModifyEGADSGeomModel()`
33025552b385SBrandon @*/
DMPlexGeomDataAndGrads(DM dm,PetscBool fullGeomGrad)3303ce78bad3SBarry Smith PetscErrorCode DMPlexGeomDataAndGrads(DM dm, PetscBool fullGeomGrad) PeNS
33045552b385SBrandon {
33055552b385SBrandon #if defined(PETSC_HAVE_EGADS)
33065552b385SBrandon /* PETSc Variables */
33075552b385SBrandon PetscContainer modelObj;
33085552b385SBrandon PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL;
33095552b385SBrandon PetscHMapI pointSurfGradRow_Start = NULL;
33105552b385SBrandon Mat pointSurfGrad, cpEquiv;
33115552b385SBrandon IS faceLabelValues, edgeLabelValues, vertexLabelValues;
33125552b385SBrandon PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize;
33135552b385SBrandon PetscBool islite = PETSC_FALSE;
33145552b385SBrandon /* EGADS Variables */
33155552b385SBrandon ego model, geom, *bodies, *fobjs = NULL;
33165552b385SBrandon int oclass, mtype, *senses;
33175552b385SBrandon int Nb, Nf;
33185552b385SBrandon #endif
33195552b385SBrandon
33205552b385SBrandon PetscFunctionBegin;
33215552b385SBrandon #if defined(PETSC_HAVE_EGADS)
33225552b385SBrandon
33235552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
33245552b385SBrandon if (!modelObj) {
33255552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
33265552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model");
33275552b385SBrandon islite = PETSC_TRUE;
33285552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot provide geometric data or associated calculated gradients for geometries defined by EGADSlite (.egadslite)!\nPlease use another geometry file format STEP, IGES, EGADS or BRep");
33295552b385SBrandon }
33305552b385SBrandon
33315552b385SBrandon // Get attached EGADS model (pointer)
33322a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(modelObj, &model));
33335552b385SBrandon
33345552b385SBrandon // Get the bodies in the model
33355552b385SBrandon if (islite) {
33365552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
33375552b385SBrandon } else {
33385552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
33395552b385SBrandon }
33405552b385SBrandon
33415552b385SBrandon ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body.
33425552b385SBrandon
33435552b385SBrandon // Get the total number of FACEs in the model
33445552b385SBrandon if (islite) {
33455552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
33465552b385SBrandon } else {
33475552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
33485552b385SBrandon }
33495552b385SBrandon
33505552b385SBrandon // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label"
33515552b385SBrandon // This will provide the total number of DMPlex points on the boundary of the geometry
33525552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues));
33535552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize));
33545552b385SBrandon
33555552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues));
33565552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize));
33575552b385SBrandon
33585552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues));
33595552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize));
33605552b385SBrandon
33615552b385SBrandon const PetscInt *faceIndices, *edgeIndices, *vertexIndices;
33625552b385SBrandon PetscCall(ISGetIndices(faceLabelValues, &faceIndices));
33635552b385SBrandon PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices));
33645552b385SBrandon PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices));
33655552b385SBrandon
33665552b385SBrandon // Get the points associated with each FACE, EDGE and VERTEX label in the DM
33675552b385SBrandon PetscInt totalNumPoints = 0;
33685552b385SBrandon for (int f = 0; f < faceLabelSize; ++f) {
33695552b385SBrandon // Cycle through FACE labels
33705552b385SBrandon PetscInt size;
33715552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[f], &size));
33725552b385SBrandon totalNumPoints += size;
33735552b385SBrandon }
33745552b385SBrandon PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices));
33755552b385SBrandon PetscCall(ISDestroy(&faceLabelValues));
33765552b385SBrandon
33775552b385SBrandon for (int e = 0; e < edgeLabelSize; ++e) {
33785552b385SBrandon // Cycle Through EDGE Labels
33795552b385SBrandon PetscInt size;
33805552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[e], &size));
33815552b385SBrandon totalNumPoints += size;
33825552b385SBrandon }
33835552b385SBrandon PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices));
33845552b385SBrandon PetscCall(ISDestroy(&edgeLabelValues));
33855552b385SBrandon
33865552b385SBrandon for (int ii = 0; ii < vertexLabelSize; ++ii) {
33875552b385SBrandon // Cycle Through VERTEX Labels
33885552b385SBrandon PetscInt size;
33895552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size));
33905552b385SBrandon totalNumPoints += size;
33915552b385SBrandon }
33925552b385SBrandon PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices));
33935552b385SBrandon PetscCall(ISDestroy(&vertexLabelValues));
33945552b385SBrandon
33955552b385SBrandon int maxNumCPs = 0;
33965552b385SBrandon int totalNumCPs = 0;
33975552b385SBrandon ego bRef, bPrev, bNext, fgeom, *lobjs;
33985552b385SBrandon int id, boclass, bmtype, *bpinfo;
33995552b385SBrandon int foclass, fmtype, Nl, *lsenses;
34005552b385SBrandon double *bprv;
34015552b385SBrandon double fdata[4];
34025552b385SBrandon
34035552b385SBrandon // Create Hash Tables
34045552b385SBrandon PetscInt cntr = 0, wcntr = 0, vcntr = 0;
34055552b385SBrandon PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start));
34065552b385SBrandon PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start));
34075552b385SBrandon
34085552b385SBrandon for (int f = 0; f < Nf; ++f) {
34095552b385SBrandon // Need to get the maximum number of Control Points defining the FACEs
34105552b385SBrandon ego face = fobjs[f];
34115552b385SBrandon int maxNumCPs_temp;
34125552b385SBrandon
34135552b385SBrandon if (islite) {
34145552b385SBrandon id = EGlite_indexBodyTopo(body, face);
34155552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
34165552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
34175552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
34185552b385SBrandon } else {
34195552b385SBrandon id = EG_indexBodyTopo(body, face);
34205552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
34215552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
34225552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
34235552b385SBrandon }
34245552b385SBrandon maxNumCPs_temp = bpinfo[2] * bpinfo[5];
34255552b385SBrandon totalNumCPs += bpinfo[2] * bpinfo[5];
34265552b385SBrandon
3427ac530a7eSPierre Jolivet if (maxNumCPs_temp > maxNumCPs) maxNumCPs = maxNumCPs_temp;
34285552b385SBrandon }
34295552b385SBrandon
34305552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr;
34315552b385SBrandon PetscInt cpCoordDataLength = 3 * totalNumCPs;
34325552b385SBrandon PetscInt wDataLength = totalNumCPs;
34335552b385SBrandon cpCoordDataLengthPtr = &cpCoordDataLength;
34345552b385SBrandon wDataLengthPtr = &wDataLength;
34355552b385SBrandon
34365552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec;
34375552b385SBrandon PetscScalar *cntrlPtCoords, *cntrlPtWeights;
34385552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &cntrlPtCoordsVec));
34395552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &cntrlPtWeightsVec));
34405552b385SBrandon
34415552b385SBrandon // For dSA/dCPi
34425552b385SBrandon Vec gradSACPVec, gradSAWVec, gradVCPVec, gradVWVec;
34435552b385SBrandon PetscScalar *gradSACP, *gradSAW, *gradVCP, *gradVW;
34445552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradSACPVec));
34455552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradSAWVec));
34465552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradVCPVec));
34475552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradVWVec));
34485552b385SBrandon
34495552b385SBrandon // Control Point - Vertex/Edge/Face Relationship
34505552b385SBrandon PetscInt *cp_vertex, *cp_edge, *cp_face;
34515552b385SBrandon PetscInt *w_vertex, *w_edge, *w_face;
34525552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_vertex));
34535552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_edge));
34545552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_face));
34555552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_vertex));
34565552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_edge));
34575552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_face));
34585552b385SBrandon
34595552b385SBrandon for (int f = 0; f < Nf; ++f) {
34605552b385SBrandon // Need to Populate Control Point Coordinates and Weight Vectors
34615552b385SBrandon ego face = fobjs[f];
34625552b385SBrandon ego *vobjs, *eobjs;
34635552b385SBrandon int offsetCoord, offsetWeight;
34645552b385SBrandon PetscInt Nv, Ne, wRowStart = 0;
34655552b385SBrandon PetscHashIter hashKeyIter, wHashKeyIter;
34665552b385SBrandon PetscBool hashKeyFound, wHashKeyFound;
34675552b385SBrandon
34685552b385SBrandon if (islite) {
34695552b385SBrandon id = EGlite_indexBodyTopo(body, face);
34705552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
34715552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
34725552b385SBrandon PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
34735552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, face, NODE, &Nv, &vobjs));
34745552b385SBrandon } else {
34755552b385SBrandon id = EG_indexBodyTopo(body, face);
34765552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
34775552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
34785552b385SBrandon PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
34795552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, face, NODE, &Nv, &vobjs));
34805552b385SBrandon }
34815552b385SBrandon
34825552b385SBrandon // Store Face ID to 1st Row of Control Point Vector
34835552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound));
34845552b385SBrandon
34855552b385SBrandon if (!hashKeyFound) PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr));
34865552b385SBrandon
34875552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords));
34885552b385SBrandon offsetCoord = bpinfo[3] + bpinfo[6];
34895552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) {
34905552b385SBrandon cntrlPtCoords[cntr] = bprv[offsetCoord + jj];
34915552b385SBrandon cntr += 1;
34925552b385SBrandon }
34935552b385SBrandon
34945552b385SBrandon // Store Face ID to 1st Row of Control Point Weight Vector
34955552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound));
34965552b385SBrandon
34975552b385SBrandon if (!wHashKeyFound) {
34985552b385SBrandon PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr));
34995552b385SBrandon wRowStart = wcntr;
35005552b385SBrandon }
35015552b385SBrandon
35025552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights));
35035552b385SBrandon offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]);
35045552b385SBrandon for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) {
35055552b385SBrandon cntrlPtWeights[wcntr] = bprv[offsetWeight + jj];
35065552b385SBrandon cp_face[wcntr] = id;
35075552b385SBrandon w_face[wcntr] = id;
35085552b385SBrandon wcntr += 1;
35095552b385SBrandon }
35105552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights));
35115552b385SBrandon
3512bfe80ac4SPierre Jolivet // Associate Control Points with Vertex IDs
35135552b385SBrandon PetscScalar xcp, ycp, zcp;
35145552b385SBrandon offsetCoord = bpinfo[3] + bpinfo[6];
35155552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; jj += 3) {
35165552b385SBrandon xcp = bprv[offsetCoord + jj + 0];
35175552b385SBrandon ycp = bprv[offsetCoord + jj + 1];
35185552b385SBrandon zcp = bprv[offsetCoord + jj + 2];
35195552b385SBrandon
35205552b385SBrandon //Initialize Control Point and Weight to Vertex ID relationship to -1
35215552b385SBrandon cp_vertex[vcntr] = -1;
35225552b385SBrandon w_vertex[vcntr] = -1;
35235552b385SBrandon cp_edge[vcntr] = -1;
35245552b385SBrandon w_edge[vcntr] = -1;
35255552b385SBrandon
35265552b385SBrandon for (int kk = 0; kk < Nv; ++kk) {
35275552b385SBrandon int vid;
35285552b385SBrandon double vCoords[3];
35295552b385SBrandon PetscScalar vDelta;
35305552b385SBrandon ego vertex = vobjs[kk];
35315552b385SBrandon
35325552b385SBrandon if (islite) {
35335552b385SBrandon vid = EGlite_indexBodyTopo(body, vertex);
35345552b385SBrandon PetscCallEGADS(EGlite_evaluate, (vertex, NULL, vCoords));
35355552b385SBrandon } else {
35365552b385SBrandon vid = EG_indexBodyTopo(body, vertex);
35375552b385SBrandon PetscCallEGADS(EG_evaluate, (vertex, NULL, vCoords));
35385552b385SBrandon }
35395552b385SBrandon vDelta = PetscSqrtReal(PetscSqr(vCoords[0] - xcp) + PetscSqr(vCoords[1] - ycp) + PetscSqr(vCoords[2] - zcp));
35405552b385SBrandon
35415552b385SBrandon if (vDelta < 1.0E-15) {
35425552b385SBrandon cp_vertex[vcntr] = vid;
35435552b385SBrandon w_vertex[vcntr] = vid;
35445552b385SBrandon }
35455552b385SBrandon }
35465552b385SBrandon vcntr += 1;
35475552b385SBrandon }
35485552b385SBrandon // These two line could be replaced with DMPlexFreeGeomObject()
35495552b385SBrandon if (islite) EGlite_free(vobjs);
35505552b385SBrandon else EG_free(vobjs);
35515552b385SBrandon
35525552b385SBrandon // Associate Control Points with Edge IDs
35535552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, face, EDGE, &Ne, &eobjs));
35545552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, face, EDGE, &Ne, &eobjs));
35555552b385SBrandon
35565552b385SBrandon int cpV1, cpV2;
35575552b385SBrandon int minID, maxID;
35585552b385SBrandon
35595552b385SBrandon // Along vmin axis
35605552b385SBrandon minID = wRowStart;
35615552b385SBrandon maxID = wRowStart + (bpinfo[2] - 1);
35625552b385SBrandon cpV1 = cp_vertex[minID];
35635552b385SBrandon cpV2 = cp_vertex[maxID];
35645552b385SBrandon for (int jj = 0; jj < Ne; ++jj) {
35655552b385SBrandon ego edge = eobjs[jj];
35665552b385SBrandon ego egeom, *nobjs;
35675552b385SBrandon int eoclass, emtype, Nn, *nsenses;
35685552b385SBrandon int n1ID, n2ID, eid;
35695552b385SBrandon
35705552b385SBrandon if (islite) {
35715552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
35725552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses));
35735552b385SBrandon } else {
35745552b385SBrandon eid = EG_indexBodyTopo(body, edge);
35755552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses));
35765552b385SBrandon }
35775552b385SBrandon
35785552b385SBrandon if (emtype != DEGENERATE) {
35795552b385SBrandon // Get IDs for current Edge's End Vertices
35805552b385SBrandon if (islite) {
35815552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]);
35825552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]);
35835552b385SBrandon } else {
35845552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]);
35855552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]);
35865552b385SBrandon }
35875552b385SBrandon
35885552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) {
35895552b385SBrandon for (int kk = minID + 1; kk < maxID; ++kk) {
35905552b385SBrandon cp_edge[kk] = eid;
35915552b385SBrandon w_edge[kk] = eid;
35925552b385SBrandon }
35935552b385SBrandon }
35945552b385SBrandon }
35955552b385SBrandon }
35965552b385SBrandon
35975552b385SBrandon // Along vmax axis
35985552b385SBrandon minID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1));
35995552b385SBrandon maxID = wRowStart + (bpinfo[2] * bpinfo[5] - 1);
36005552b385SBrandon
36015552b385SBrandon cpV1 = cp_vertex[minID];
36025552b385SBrandon cpV2 = cp_vertex[maxID];
36035552b385SBrandon for (int jj = 0; jj < Ne; ++jj) {
36045552b385SBrandon ego edge = eobjs[jj];
36055552b385SBrandon ego egeom, *nobjs;
36065552b385SBrandon int eoclass, emtype, Nn, *nsenses;
36075552b385SBrandon int n1ID, n2ID, eid;
36085552b385SBrandon
36095552b385SBrandon if (islite) {
36105552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
36115552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses));
36125552b385SBrandon } else {
36135552b385SBrandon eid = EG_indexBodyTopo(body, edge);
36145552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses));
36155552b385SBrandon }
36165552b385SBrandon
36175552b385SBrandon if (emtype != DEGENERATE) {
36185552b385SBrandon // Get IDs for current Edge's End Vertices
36195552b385SBrandon if (islite) {
36205552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]);
36215552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]);
36225552b385SBrandon } else {
36235552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]);
36245552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]);
36255552b385SBrandon }
36265552b385SBrandon
36275552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) {
36285552b385SBrandon for (int kk = minID + 1; kk < maxID - 1; ++kk) {
36295552b385SBrandon cp_edge[kk] = eid;
36305552b385SBrandon w_edge[kk] = eid;
36315552b385SBrandon }
36325552b385SBrandon }
36335552b385SBrandon }
36345552b385SBrandon }
36355552b385SBrandon
36365552b385SBrandon // Along umin axis
36375552b385SBrandon minID = wRowStart;
36385552b385SBrandon maxID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1));
36395552b385SBrandon
36405552b385SBrandon cpV1 = cp_vertex[minID];
36415552b385SBrandon cpV2 = cp_vertex[maxID];
36425552b385SBrandon for (int jj = 0; jj < Ne; ++jj) {
36435552b385SBrandon ego edge = eobjs[jj];
36445552b385SBrandon ego egeom, *nobjs;
36455552b385SBrandon int eoclass, emtype, Nn, *nsenses;
36465552b385SBrandon int n1ID, n2ID, eid;
36475552b385SBrandon
36485552b385SBrandon if (islite) {
36495552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
36505552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses));
36515552b385SBrandon } else {
36525552b385SBrandon eid = EG_indexBodyTopo(body, edge);
36535552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses));
36545552b385SBrandon }
36555552b385SBrandon
36565552b385SBrandon if (emtype != DEGENERATE) {
36575552b385SBrandon // Get IDs for current Edge's End Vertices
36585552b385SBrandon if (islite) {
36595552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]);
36605552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]);
36615552b385SBrandon } else {
36625552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]);
36635552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]);
36645552b385SBrandon }
36655552b385SBrandon
36665552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) {
36675552b385SBrandon for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) {
36685552b385SBrandon cp_edge[kk] = eid;
36695552b385SBrandon w_edge[kk] = eid;
36705552b385SBrandon }
36715552b385SBrandon }
36725552b385SBrandon }
36735552b385SBrandon }
36745552b385SBrandon
36755552b385SBrandon // Along umax axis
36765552b385SBrandon minID = wRowStart + (bpinfo[2] - 1);
36775552b385SBrandon maxID = wRowStart + (bpinfo[2] * bpinfo[5]) - 1;
36785552b385SBrandon cpV1 = cp_vertex[minID];
36795552b385SBrandon cpV2 = cp_vertex[maxID];
36805552b385SBrandon for (int jj = 0; jj < Ne; ++jj) {
36815552b385SBrandon ego edge = eobjs[jj];
36825552b385SBrandon ego egeom, *nobjs;
36835552b385SBrandon int eoclass, emtype, Nn, *nsenses;
36845552b385SBrandon int n1ID, n2ID, eid;
36855552b385SBrandon
36865552b385SBrandon if (islite) {
36875552b385SBrandon eid = EGlite_indexBodyTopo(body, edge);
36885552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses));
36895552b385SBrandon } else {
36905552b385SBrandon eid = EG_indexBodyTopo(body, edge);
36915552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses));
36925552b385SBrandon }
36935552b385SBrandon
36945552b385SBrandon if (emtype != DEGENERATE) {
36955552b385SBrandon // Get IDs for current Edge's End Vertices
36965552b385SBrandon if (islite) {
36975552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]);
36985552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]);
36995552b385SBrandon } else {
37005552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]);
37015552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]);
37025552b385SBrandon }
37035552b385SBrandon
37045552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) {
37055552b385SBrandon for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) {
37065552b385SBrandon cp_edge[kk] = eid;
37075552b385SBrandon w_edge[kk] = eid;
37085552b385SBrandon }
37095552b385SBrandon }
37105552b385SBrandon }
37115552b385SBrandon }
37125552b385SBrandon // These two lines could be replaced with DMPlexFreeGeomObject()
37135552b385SBrandon if (islite) EGlite_free(eobjs);
37145552b385SBrandon else EG_free(eobjs);
37155552b385SBrandon }
37165552b385SBrandon
3717bfe80ac4SPierre Jolivet // Determine Control Point Equivalence Matrix relating Control Points between Surfaces
37185552b385SBrandon // Note: The Weights will also be tied together in the same manner
37195552b385SBrandon // Also can use the Weight Hash Table for Row Start ID of each Face
37205552b385SBrandon const PetscInt cpRowSize = totalNumCPs;
37215552b385SBrandon const PetscInt cpColSize = cpRowSize;
37225552b385SBrandon PetscInt *maxNumRelatePtr;
37235552b385SBrandon PetscInt maxNumRelate = 0;
37245552b385SBrandon
37255552b385SBrandon // Create Point Surface Gradient Matrix
37265552b385SBrandon PetscCall(MatCreate(PETSC_COMM_WORLD, &cpEquiv));
37275552b385SBrandon PetscCall(MatSetSizes(cpEquiv, PETSC_DECIDE, PETSC_DECIDE, cpRowSize, cpColSize));
37285552b385SBrandon PetscCall(MatSetType(cpEquiv, MATAIJ));
37295552b385SBrandon PetscCall(MatSetUp(cpEquiv));
37305552b385SBrandon
37315552b385SBrandon for (int ii = 0; ii < totalNumCPs; ++ii) {
37325552b385SBrandon PetscScalar x1, y1, z1;
37335552b385SBrandon PetscInt maxRelateTemp = 0;
37345552b385SBrandon
37355552b385SBrandon x1 = cntrlPtCoords[(3 * ii) + 0];
37365552b385SBrandon y1 = cntrlPtCoords[(3 * ii) + 1];
37375552b385SBrandon z1 = cntrlPtCoords[(3 * ii) + 2];
37385552b385SBrandon
37395552b385SBrandon for (int jj = 0; jj < totalNumCPs; ++jj) {
37405552b385SBrandon PetscScalar x2, y2, z2;
37415552b385SBrandon PetscScalar cpDelta, eqFactor;
37425552b385SBrandon x2 = cntrlPtCoords[(3 * jj) + 0];
37435552b385SBrandon y2 = cntrlPtCoords[(3 * jj) + 1];
37445552b385SBrandon z2 = cntrlPtCoords[(3 * jj) + 2];
37455552b385SBrandon
37465552b385SBrandon cpDelta = PetscSqrtReal(PetscSqr(x2 - x1) + PetscSqr(y2 - y1) + PetscSqr(z2 - z1));
37475552b385SBrandon if (cpDelta < 1.0E-15) {
37485552b385SBrandon eqFactor = 1.0;
37495552b385SBrandon maxRelateTemp += 1;
37505552b385SBrandon } else {
37515552b385SBrandon eqFactor = 0.0;
37525552b385SBrandon }
37535552b385SBrandon
3754f0b74427SPierre Jolivet // Store Results in PETSc Mat
37555552b385SBrandon PetscCall(MatSetValue(cpEquiv, ii, jj, eqFactor, INSERT_VALUES));
37565552b385SBrandon }
37575552b385SBrandon if (maxRelateTemp > maxNumRelate) maxNumRelate = maxRelateTemp;
37585552b385SBrandon }
37595552b385SBrandon maxNumRelatePtr = &maxNumRelate;
37605552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords));
37615552b385SBrandon
37625552b385SBrandon // Assemble Point Surface Grad Matrix
37635552b385SBrandon PetscCall(MatAssemblyBegin(cpEquiv, MAT_FINAL_ASSEMBLY));
37645552b385SBrandon PetscCall(MatAssemblyEnd(cpEquiv, MAT_FINAL_ASSEMBLY));
37655552b385SBrandon
37665552b385SBrandon // Attach Control Point and Weight Data to DM
37675552b385SBrandon {
37685552b385SBrandon PetscContainer cpOrgObj, cpCoordLengthObj;
37695552b385SBrandon PetscContainer wOrgObj, wDataLengthObj;
37705552b385SBrandon PetscContainer cp_faceObj, cp_edgeObj, cp_vertexObj;
37715552b385SBrandon PetscContainer w_faceObj, w_edgeObj, w_vertexObj;
37725552b385SBrandon PetscContainer maxNumRelateObj;
37735552b385SBrandon
37745552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpOrgObj));
37755552b385SBrandon if (!cpOrgObj) {
37765552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj));
37775552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start));
37785552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj));
37795552b385SBrandon PetscCall(PetscContainerDestroy(&cpOrgObj));
37805552b385SBrandon } else {
37815552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start));
37825552b385SBrandon }
37835552b385SBrandon
37845552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cntrlPtCoordsVec));
37855552b385SBrandon PetscCall(VecDestroy(&cntrlPtCoordsVec));
37865552b385SBrandon
37875552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordLengthObj));
37885552b385SBrandon if (!cpCoordLengthObj) {
37895552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj));
37905552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr));
37915552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj));
37925552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordLengthObj));
37935552b385SBrandon } else {
37945552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr));
37955552b385SBrandon }
37965552b385SBrandon
37975552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wOrgObj));
37985552b385SBrandon if (!wOrgObj) {
37995552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj));
38005552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start));
38015552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj));
38025552b385SBrandon PetscCall(PetscContainerDestroy(&wOrgObj));
38035552b385SBrandon } else {
38045552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start));
38055552b385SBrandon }
38065552b385SBrandon
38075552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)cntrlPtWeightsVec));
38085552b385SBrandon PetscCall(VecDestroy(&cntrlPtWeightsVec));
38095552b385SBrandon
38105552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj));
38115552b385SBrandon if (!wDataLengthObj) {
38125552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj));
38135552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr));
38145552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj));
38155552b385SBrandon PetscCall(PetscContainerDestroy(&wDataLengthObj));
38165552b385SBrandon } else {
38175552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr));
38185552b385SBrandon }
38195552b385SBrandon
3820bfe80ac4SPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Equivalency Matrix", (PetscObject)cpEquiv));
38215552b385SBrandon
38225552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj));
38235552b385SBrandon if (!maxNumRelateObj) {
38245552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &maxNumRelateObj));
38255552b385SBrandon PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr));
38265552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject)maxNumRelateObj));
38275552b385SBrandon PetscCall(PetscContainerDestroy(&maxNumRelateObj));
38285552b385SBrandon } else {
38295552b385SBrandon PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr));
38305552b385SBrandon }
38315552b385SBrandon
38325552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cp_faceObj));
38335552b385SBrandon if (!cp_faceObj) {
38345552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_faceObj));
38355552b385SBrandon PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face));
38365552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_faceObj, PetscCtxDestroyDefault));
38375552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Face Map", (PetscObject)cp_faceObj));
38385552b385SBrandon PetscCall(PetscContainerDestroy(&cp_faceObj));
38395552b385SBrandon } else {
38405552b385SBrandon void *tmp;
38415552b385SBrandon
38425552b385SBrandon PetscCall(PetscContainerGetPointer(cp_faceObj, &tmp));
38435552b385SBrandon PetscCall(PetscFree(tmp));
38445552b385SBrandon PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face));
38455552b385SBrandon }
38465552b385SBrandon
38475552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&w_faceObj));
38485552b385SBrandon if (!w_faceObj) {
38495552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_faceObj));
38505552b385SBrandon PetscCall(PetscContainerSetPointer(w_faceObj, w_face));
38515552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_faceObj, PetscCtxDestroyDefault));
38525552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject)w_faceObj));
38535552b385SBrandon PetscCall(PetscContainerDestroy(&w_faceObj));
38545552b385SBrandon } else {
38555552b385SBrandon void *tmp;
38565552b385SBrandon
38575552b385SBrandon PetscCall(PetscContainerGetPointer(w_faceObj, &tmp));
38585552b385SBrandon PetscCall(PetscFree(tmp));
38595552b385SBrandon PetscCall(PetscContainerSetPointer(w_faceObj, w_face));
38605552b385SBrandon }
38615552b385SBrandon
38625552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cp_edgeObj));
38635552b385SBrandon if (!cp_edgeObj) {
38645552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_edgeObj));
38655552b385SBrandon PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge));
38665552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_edgeObj, PetscCtxDestroyDefault));
38675552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Edge Map", (PetscObject)cp_edgeObj));
38685552b385SBrandon PetscCall(PetscContainerDestroy(&cp_edgeObj));
38695552b385SBrandon } else {
38705552b385SBrandon void *tmp;
38715552b385SBrandon
38725552b385SBrandon PetscCall(PetscContainerGetPointer(cp_edgeObj, &tmp));
38735552b385SBrandon PetscCall(PetscFree(tmp));
38745552b385SBrandon PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge));
38755552b385SBrandon }
38765552b385SBrandon
38775552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&w_edgeObj));
38785552b385SBrandon if (!w_edgeObj) {
38795552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_edgeObj));
38805552b385SBrandon PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge));
38815552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_edgeObj, PetscCtxDestroyDefault));
38825552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject)w_edgeObj));
38835552b385SBrandon PetscCall(PetscContainerDestroy(&w_edgeObj));
38845552b385SBrandon } else {
38855552b385SBrandon void *tmp;
38865552b385SBrandon
38875552b385SBrandon PetscCall(PetscContainerGetPointer(w_edgeObj, &tmp));
38885552b385SBrandon PetscCall(PetscFree(tmp));
38895552b385SBrandon PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge));
38905552b385SBrandon }
38915552b385SBrandon
38925552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cp_vertexObj));
38935552b385SBrandon if (!cp_vertexObj) {
38945552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_vertexObj));
38955552b385SBrandon PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex));
38965552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_vertexObj, PetscCtxDestroyDefault));
38975552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Vertex Map", (PetscObject)cp_vertexObj));
38985552b385SBrandon PetscCall(PetscContainerDestroy(&cp_vertexObj));
38995552b385SBrandon } else {
39005552b385SBrandon void *tmp;
39015552b385SBrandon
39025552b385SBrandon PetscCall(PetscContainerGetPointer(cp_vertexObj, &tmp));
39035552b385SBrandon PetscCall(PetscFree(tmp));
39045552b385SBrandon PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex));
39055552b385SBrandon }
39065552b385SBrandon
39075552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&w_vertexObj));
39085552b385SBrandon if (!w_vertexObj) {
39095552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_vertexObj));
39105552b385SBrandon PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex));
39115552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_vertexObj, PetscCtxDestroyDefault));
39125552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject)w_vertexObj));
39135552b385SBrandon PetscCall(PetscContainerDestroy(&w_vertexObj));
39145552b385SBrandon } else {
39155552b385SBrandon void *tmp;
39165552b385SBrandon
39175552b385SBrandon PetscCall(PetscContainerGetPointer(w_vertexObj, &tmp));
39185552b385SBrandon PetscCall(PetscFree(tmp));
39195552b385SBrandon PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex));
39205552b385SBrandon }
39215552b385SBrandon }
39225552b385SBrandon
39235552b385SBrandon // Define Matrix to store Geometry Gradient information dGeom_i/dCPj_i
39245552b385SBrandon PetscInt gcntr = 0;
39255552b385SBrandon const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints;
39265552b385SBrandon const PetscInt colSize = 4 * Nf;
39275552b385SBrandon
39285552b385SBrandon // Create Point Surface Gradient Matrix
39295552b385SBrandon PetscCall(MatCreate(PETSC_COMM_WORLD, &pointSurfGrad));
39305552b385SBrandon PetscCall(MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize));
39315552b385SBrandon PetscCall(MatSetType(pointSurfGrad, MATAIJ));
39325552b385SBrandon PetscCall(MatSetUp(pointSurfGrad));
39335552b385SBrandon
39345552b385SBrandon // Create Hash Table to store Point's stare row in surfaceGrad[][]
39355552b385SBrandon PetscCall(PetscHMapICreate(&pointSurfGradRow_Start));
39365552b385SBrandon
39375552b385SBrandon // Get Coordinates for the DMPlex point
39385552b385SBrandon DM cdm;
39395552b385SBrandon PetscInt dE, Nv;
39405552b385SBrandon Vec coordinatesLocal;
39415552b385SBrandon PetscScalar *coords = NULL;
39425552b385SBrandon
39435552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm));
39445552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &dE));
39455552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
39465552b385SBrandon
39475552b385SBrandon // CYCLE THROUGH FACEs
39485552b385SBrandon PetscScalar maxGrad = 0.;
39495552b385SBrandon PetscCall(VecGetArrayWrite(gradSACPVec, &gradSACP));
39505552b385SBrandon PetscCall(VecGetArrayWrite(gradSAWVec, &gradSAW));
39515552b385SBrandon PetscCall(VecGetArrayWrite(gradVCPVec, &gradVCP));
39525552b385SBrandon PetscCall(VecGetArrayWrite(gradVWVec, &gradVW));
39535552b385SBrandon for (int f = 0; f < Nf; ++f) {
39545552b385SBrandon ego face = fobjs[f];
39555552b385SBrandon ego *eobjs, *nobjs;
39565552b385SBrandon PetscInt fid, Ne, Nn;
39575552b385SBrandon DMLabel faceLabel, edgeLabel, nodeLabel;
39585552b385SBrandon PetscHMapI currFaceUniquePoints = NULL;
39595552b385SBrandon IS facePoints, edgePoints, nodePoints;
39605552b385SBrandon const PetscInt *fIndices, *eIndices, *nIndices;
39615552b385SBrandon PetscInt fSize, eSize, nSize;
39625552b385SBrandon PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter;
39635552b385SBrandon PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound;
39645552b385SBrandon PetscInt cfCntr = 0;
39655552b385SBrandon
39665552b385SBrandon // Get Geometry Object for the Current FACE
39675552b385SBrandon if (islite) {
39685552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
39695552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
39705552b385SBrandon } else {
39715552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
39725552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
39735552b385SBrandon }
39745552b385SBrandon
39755552b385SBrandon // Get all EDGE and NODE objects attached to the current FACE
39765552b385SBrandon if (islite) {
39775552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs));
39785552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs));
39795552b385SBrandon } else {
39805552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs));
39815552b385SBrandon PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs));
39825552b385SBrandon }
39835552b385SBrandon
39845552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use
39855552b385SBrandon if (islite) {
39865552b385SBrandon fid = EGlite_indexBodyTopo(body, face);
39875552b385SBrandon } else {
39885552b385SBrandon fid = EG_indexBodyTopo(body, face);
39895552b385SBrandon }
39905552b385SBrandon
39915552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
39925552b385SBrandon PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints));
39935552b385SBrandon PetscCall(ISGetIndices(facePoints, &fIndices));
39945552b385SBrandon PetscCall(ISGetSize(facePoints, &fSize));
39955552b385SBrandon
39965552b385SBrandon PetscCall(PetscHMapICreate(&currFaceUniquePoints));
39975552b385SBrandon
39985552b385SBrandon for (int jj = 0; jj < fSize; ++jj) {
39995552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound));
40005552b385SBrandon
40015552b385SBrandon if (!fHashKeyFound) {
40025552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr));
40035552b385SBrandon cfCntr += 1;
40045552b385SBrandon }
40055552b385SBrandon
40065552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound));
40075552b385SBrandon
40085552b385SBrandon if (!pHashKeyFound) {
40095552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr));
40105552b385SBrandon gcntr += 3 * maxNumCPs;
40115552b385SBrandon }
40125552b385SBrandon }
40135552b385SBrandon PetscCall(ISRestoreIndices(facePoints, &fIndices));
40145552b385SBrandon PetscCall(ISDestroy(&facePoints));
40155552b385SBrandon
40165552b385SBrandon // Get all DMPlex Points that have DMLable "EGADS Edge ID" attached to the current FACE and store them in a Hash Table for later use.
40175552b385SBrandon for (int jj = 0; jj < Ne; ++jj) {
40185552b385SBrandon ego edge = eobjs[jj];
40195552b385SBrandon PetscBool containLabelValue;
40205552b385SBrandon
40215552b385SBrandon if (islite) {
40225552b385SBrandon id = EGlite_indexBodyTopo(body, edge);
40235552b385SBrandon } else {
40245552b385SBrandon id = EG_indexBodyTopo(body, edge);
40255552b385SBrandon }
40265552b385SBrandon
40275552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
40285552b385SBrandon PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue));
40295552b385SBrandon
40305552b385SBrandon if (containLabelValue) {
40315552b385SBrandon PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints));
40325552b385SBrandon PetscCall(ISGetIndices(edgePoints, &eIndices));
40335552b385SBrandon PetscCall(ISGetSize(edgePoints, &eSize));
40345552b385SBrandon
40355552b385SBrandon for (int kk = 0; kk < eSize; ++kk) {
40365552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound));
40375552b385SBrandon
40385552b385SBrandon if (!eHashKeyFound) {
40395552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr));
40405552b385SBrandon cfCntr += 1;
40415552b385SBrandon }
40425552b385SBrandon
40435552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound));
40445552b385SBrandon
40455552b385SBrandon if (!pHashKeyFound) {
40465552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr));
40475552b385SBrandon gcntr += 3 * maxNumCPs;
40485552b385SBrandon }
40495552b385SBrandon }
40505552b385SBrandon PetscCall(ISRestoreIndices(edgePoints, &eIndices));
40515552b385SBrandon PetscCall(ISDestroy(&edgePoints));
40525552b385SBrandon }
40535552b385SBrandon }
40545552b385SBrandon
40555552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Vertex ID" attached to the current FACE and store them in a Hash Table for later use.
40565552b385SBrandon for (int jj = 0; jj < Nn; ++jj) {
40575552b385SBrandon ego node = nobjs[jj];
40585552b385SBrandon
40595552b385SBrandon if (islite) {
40605552b385SBrandon id = EGlite_indexBodyTopo(body, node);
40615552b385SBrandon } else {
40625552b385SBrandon id = EG_indexBodyTopo(body, node);
40635552b385SBrandon }
40645552b385SBrandon
40655552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel));
40665552b385SBrandon PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints));
40675552b385SBrandon PetscCall(ISGetIndices(nodePoints, &nIndices));
40685552b385SBrandon PetscCall(ISGetSize(nodePoints, &nSize));
40695552b385SBrandon
40705552b385SBrandon for (int kk = 0; kk < nSize; ++kk) {
40715552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound));
40725552b385SBrandon
40735552b385SBrandon if (!nHashKeyFound) {
40745552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr));
40755552b385SBrandon cfCntr += 1;
40765552b385SBrandon }
40775552b385SBrandon
40785552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound));
40795552b385SBrandon if (!pHashKeyFound) {
40805552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr));
40815552b385SBrandon gcntr += 3 * maxNumCPs;
40825552b385SBrandon }
40835552b385SBrandon }
40845552b385SBrandon PetscCall(ISRestoreIndices(nodePoints, &nIndices));
40855552b385SBrandon PetscCall(ISDestroy(&nodePoints));
40865552b385SBrandon }
40875552b385SBrandon
40885552b385SBrandon // Get the Total Number of entries in the Hash Table
40895552b385SBrandon PetscInt currFaceUPSize;
40905552b385SBrandon PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize));
40915552b385SBrandon
40925552b385SBrandon // Get Keys
40935552b385SBrandon PetscInt currFaceUPKeys[currFaceUPSize], off = 0;
40945552b385SBrandon PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys));
40955552b385SBrandon PetscCall(PetscHMapIDestroy(&currFaceUniquePoints));
40965552b385SBrandon
40975552b385SBrandon // Get Current Face Surface Area
40985552b385SBrandon PetscScalar fSA, faceData[14];
40995552b385SBrandon PetscCall(EG_getMassProperties(face, faceData)); // This doesn't have a EGlite version. Will it work for EGADSlite files?? KNOWN_ISSUE
41005552b385SBrandon fSA = faceData[1];
41015552b385SBrandon
41025552b385SBrandon // Get Start Row in cpEquiv Matrix
41035552b385SBrandon PetscHashIter Witer;
41045552b385SBrandon PetscBool Wfound;
41055552b385SBrandon PetscInt faceWStartRow;
41065552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound));
41075552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table");
41085552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow));
41095552b385SBrandon
41105552b385SBrandon // Cycle through all points on the current FACE
41115552b385SBrandon for (int jj = 0; jj < currFaceUPSize; ++jj) {
41125552b385SBrandon PetscInt currPointID = currFaceUPKeys[jj];
41135552b385SBrandon PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords));
41145552b385SBrandon
41155552b385SBrandon // Get UV position of FACE
41165552b385SBrandon double params[2], range[4], eval[18];
41175552b385SBrandon int peri;
41185552b385SBrandon
41195552b385SBrandon if (islite) PetscCall(EGlite_getRange(face, range, &peri));
41205552b385SBrandon else PetscCall(EG_getRange(face, range, &peri));
41215552b385SBrandon
41225552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite));
41235552b385SBrandon
41245552b385SBrandon if (islite) PetscCall(EGlite_evaluate(face, params, eval));
41255552b385SBrandon else PetscCall(EG_evaluate(face, params, eval));
41265552b385SBrandon
41275552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points
41285552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]);
41295552b385SBrandon double nbprv[prvSize];
41305552b385SBrandon
41315552b385SBrandon // Cycle through each Control Point
41325552b385SBrandon double denomNew, denomOld;
41335552b385SBrandon double deltaCoord = 1.0E-4;
41345552b385SBrandon int offset = bpinfo[3] + bpinfo[6];
41355552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]);
41365552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) {
41375552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d", f, jj, ii);
41385552b385SBrandon #if 0
41395552b385SBrandon // Cycle through each direction (x, then y, then z)
41405552b385SBrandon if (jj == 0) {
41415552b385SBrandon // Get the Number Control Points that are the same as the current points
41425552b385SBrandon // We are looking for repeated Control Points
41435552b385SBrandon PetscInt commonCPcntr = 0;
41445552b385SBrandon for (int mm = 0; mm < bpinfo[2]*bpinfo[5]; ++mm) {
41455552b385SBrandon PetscScalar matValue;
41465552b385SBrandon PetscCall(MatGetValue(cpEquiv, faceWStartRow + ii, faceWStartRow + mm, &matValue));
41475552b385SBrandon
41485552b385SBrandon if (matValue > 0.0) commonCPcntr += 1;
41495552b385SBrandon }
41505552b385SBrandon }
41515552b385SBrandon #endif
41525552b385SBrandon
41535552b385SBrandon for (int kk = 0; kk < 4; ++kk) {
41545552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time
4155ac530a7eSPierre Jolivet for (int mm = 0; mm < prvSize; ++mm) nbprv[mm] = bprv[mm];
41565552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk);
41575552b385SBrandon
41585552b385SBrandon if (kk == 0) { //X
41595552b385SBrandon nbprv[offset + 0] = bprv[offset + 0] + deltaCoord;
41605552b385SBrandon nbprv[offset + 1] = bprv[offset + 1];
41615552b385SBrandon nbprv[offset + 2] = bprv[offset + 2];
41625552b385SBrandon denomNew = nbprv[offset + 0];
41635552b385SBrandon denomOld = bprv[offset + 0];
41645552b385SBrandon } else if (kk == 1) { //Y
41655552b385SBrandon nbprv[offset + 0] = bprv[offset + 0];
41665552b385SBrandon nbprv[offset + 1] = bprv[offset + 1] + deltaCoord;
41675552b385SBrandon nbprv[offset + 2] = bprv[offset + 2];
41685552b385SBrandon denomNew = nbprv[offset + 1];
41695552b385SBrandon denomOld = bprv[offset + 1];
41705552b385SBrandon } else if (kk == 2) { //Z
41715552b385SBrandon nbprv[offset + 0] = bprv[offset + 0];
41725552b385SBrandon nbprv[offset + 1] = bprv[offset + 1];
41735552b385SBrandon nbprv[offset + 2] = bprv[offset + 2] + deltaCoord;
41745552b385SBrandon denomNew = nbprv[offset + 2];
41755552b385SBrandon denomOld = bprv[offset + 2];
41765552b385SBrandon } else if (kk == 3) { // Weights
41775552b385SBrandon nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord;
41785552b385SBrandon denomNew = nbprv[wOffset + ii];
41795552b385SBrandon denomOld = bprv[wOffset + ii];
41805552b385SBrandon } else {
41815552b385SBrandon // currently do nothing
41825552b385SBrandon }
41835552b385SBrandon
41845552b385SBrandon // Create New Surface Based on New Control Points or Weights
41855552b385SBrandon ego newgeom, context;
41865552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // This does not have an EGlite_ version KNOWN_ISSUE
41875552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // This does not have an EGlite_ version KNOWN_ISSUE
41885552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk);
41895552b385SBrandon
41905552b385SBrandon // Evaluate new (x, y, z) Point Position based on new Surface Definition
41915552b385SBrandon double newCoords[18];
41925552b385SBrandon if (islite) PetscCall(EGlite_getRange(newgeom, range, &peri));
41935552b385SBrandon else PetscCall(EG_getRange(newgeom, range, &peri));
41945552b385SBrandon
41955552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite));
41965552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk);
41975552b385SBrandon
41985552b385SBrandon if (islite) PetscCall(EGlite_evaluate(newgeom, params, newCoords));
41995552b385SBrandon else PetscCall(EG_evaluate(newgeom, params, newCoords));
42005552b385SBrandon
42015552b385SBrandon // Calculate Surface Area Gradients wrt Control Points and Weights using the local discrete FACE only
42025552b385SBrandon // NOTE 1: Will not provide Volume Gradient wrt to Control Points and Weights.
42035552b385SBrandon // NOTE 2: This is faster than below where an entire new solid geometry is created for each
42045552b385SBrandon // Control Point and Weight gradient
42055552b385SBrandon if (!fullGeomGrad) {
42065552b385SBrandon // Create new FACE based on new SURFACE geometry
42075552b385SBrandon if (jj == 0) { // only for 1st DMPlex Point because we only per CP or Weight
42085552b385SBrandon double newFaceRange[4];
42095552b385SBrandon int newFacePeri;
42105552b385SBrandon if (islite) PetscCall(EGlite_getRange(newgeom, newFaceRange, &newFacePeri));
42115552b385SBrandon else PetscCall(EG_getRange(newgeom, newFaceRange, &newFacePeri));
42125552b385SBrandon
42135552b385SBrandon ego newface;
42145552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have EGlite version KNOWN_ISSUE
42155552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk);
42165552b385SBrandon
42175552b385SBrandon // Get New Face Surface Area
42185552b385SBrandon PetscScalar newfSA, newFaceData[14];
42195552b385SBrandon PetscCall(EG_getMassProperties(newface, newFaceData)); // Does not have EGlite version KNOWN_ISSUE
42205552b385SBrandon newfSA = newFaceData[1];
42215552b385SBrandon PetscCallEGADS(EG_deleteObject, (newface));
42225552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk);
42235552b385SBrandon
42245552b385SBrandon // Update Control Points
42255552b385SBrandon PetscHashIter CPiter, Witer;
42265552b385SBrandon PetscBool CPfound, Wfound;
42275552b385SBrandon PetscInt faceCPStartRow, faceWStartRow;
42285552b385SBrandon
42295552b385SBrandon PetscScalar dSAdCPi;
42305552b385SBrandon dSAdCPi = (newfSA - fSA) / (denomNew - denomOld);
42315552b385SBrandon
42325552b385SBrandon if (kk < 3) {
42335552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, fid, &CPiter, &CPfound));
42345552b385SBrandon PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table");
42355552b385SBrandon PetscCall(PetscHMapIGet(faceCntrlPtRow_Start, fid, &faceCPStartRow));
42365552b385SBrandon
42375552b385SBrandon gradSACP[faceCPStartRow + (ii * 3) + kk] = dSAdCPi;
42385552b385SBrandon
42395552b385SBrandon if (PetscAbsReal(dSAdCPi) > maxGrad) maxGrad = PetscAbsReal(dSAdCPi);
42405552b385SBrandon
42415552b385SBrandon } else if (kk == 3) {
42425552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound));
42435552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table");
42445552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow));
42455552b385SBrandon
42465552b385SBrandon gradSAW[faceWStartRow + ii] = dSAdCPi;
42475552b385SBrandon
42485552b385SBrandon } else {
42495552b385SBrandon // Do Nothing
42505552b385SBrandon }
42515552b385SBrandon }
42525552b385SBrandon }
42535552b385SBrandon PetscCallEGADS(EG_deleteObject, (newgeom));
42545552b385SBrandon
42555552b385SBrandon // Now Calculate the Surface Gradient for the change in x-component Control Point
42565552b385SBrandon PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord;
42575552b385SBrandon PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord;
42585552b385SBrandon PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord;
42595552b385SBrandon
42605552b385SBrandon // Store Gradient Information in surfaceGrad[][] Matrix
42615552b385SBrandon PetscInt startRow;
42625552b385SBrandon PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow));
42635552b385SBrandon
4264f0b74427SPierre Jolivet // Store Results in PETSc Mat
42655552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES));
42665552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES));
42675552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES));
42685552b385SBrandon
42695552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newgeom));
42705552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face is corrupted");
42715552b385SBrandon }
42725552b385SBrandon offset += 3;
42735552b385SBrandon }
42745552b385SBrandon PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords));
42755552b385SBrandon }
42765552b385SBrandon }
42775552b385SBrandon
42785552b385SBrandon // Assemble Point Surface Grad Matrix
42795552b385SBrandon PetscCall(MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY));
42805552b385SBrandon PetscCall(MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY));
42815552b385SBrandon
42825552b385SBrandon if (fullGeomGrad) {
42835552b385SBrandon // Calculate Surface Area and Volume Control Point and Control Point Weight Gradients
42845552b385SBrandon // Note: This is much slower than above due to a new solid geometry being created for
42855552b385SBrandon // each change in Control Point and Control Point Weight. However, this method
42865552b385SBrandon // will provide the Volume Gradient.
42875552b385SBrandon
42885552b385SBrandon // Get Current Face Surface Area
42895552b385SBrandon PetscScalar bodyVol, bodySA, bodyData[14];
4290bfe80ac4SPierre Jolivet PetscCall(EG_getMassProperties(body, bodyData)); // Does not have an EGlite version KNOWN_ISSUE
42915552b385SBrandon bodyVol = bodyData[0];
42925552b385SBrandon bodySA = bodyData[1];
42935552b385SBrandon
42945552b385SBrandon // Cycle through Control Points
42955552b385SBrandon for (int ii = 0; ii < totalNumCPs; ++ii) { // ii should also be the row in cpEquiv for the Control Point
42965552b385SBrandon // Cycle through X, Y, Z, W changes
42975552b385SBrandon for (int jj = 0; jj < 4; ++jj) {
42985552b385SBrandon // Cycle Through Faces
42995552b385SBrandon double denomNew = 0.0, denomOld = 0.0;
43005552b385SBrandon double deltaCoord = 1.0E-4;
43015552b385SBrandon ego newGeom[Nf];
43025552b385SBrandon ego newFaces[Nf];
43035552b385SBrandon for (int kk = 0; kk < Nf; ++kk) {
43045552b385SBrandon ego face;
43055552b385SBrandon PetscInt currFID = kk + 1;
43065552b385SBrandon
43075552b385SBrandon if (islite) {
43085552b385SBrandon // Get Current FACE
43095552b385SBrandon PetscCallEGADS(EGlite_objectBodyTopo, (body, FACE, currFID, &face));
43105552b385SBrandon
43115552b385SBrandon // Get Geometry Object for the Current FACE
43125552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
43135552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
43145552b385SBrandon } else {
43155552b385SBrandon // Get Current FACE
43165552b385SBrandon PetscCallEGADS(EG_objectBodyTopo, (body, FACE, currFID, &face));
43175552b385SBrandon
43185552b385SBrandon // Get Geometry Object for the Current FACE
43195552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses));
43205552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
43215552b385SBrandon }
43225552b385SBrandon
43235552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points
43245552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]);
43255552b385SBrandon double nbprv[prvSize];
43265552b385SBrandon
43275552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time
43285552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) nbprv[mm] = bprv[mm];
43295552b385SBrandon
43305552b385SBrandon // Get Control Point Row and Column Start for cpEquiv
43315552b385SBrandon PetscHashIter Witer;
43325552b385SBrandon PetscBool Wfound;
43335552b385SBrandon PetscInt faceWStartRow;
43345552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, currFID, &Witer, &Wfound));
43355552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table");
43365552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, currFID, &faceWStartRow));
43375552b385SBrandon
43385552b385SBrandon // Modify the Current Control Point on this FACE and All Other FACES
43395552b385SBrandon // IMPORTANT!!! If you do not move all identical Control Points on other FACES
43405552b385SBrandon // you will not generate a solid body. You will generate a set of
43415552b385SBrandon // disconnected surfaces that have gap(s) between them.
43425552b385SBrandon int offset = bpinfo[3] + bpinfo[6];
43435552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]);
43445552b385SBrandon for (int mm = 0; mm < bpinfo[2] * bpinfo[5]; ++mm) {
43455552b385SBrandon PetscScalar matValue;
43465552b385SBrandon PetscCall(MatGetValue(cpEquiv, ii, faceWStartRow + mm, &matValue));
43475552b385SBrandon
43485552b385SBrandon if (matValue > 0.0) {
43495552b385SBrandon if (jj == 0) { //X
43505552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0] + deltaCoord;
43515552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1];
43525552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2];
43535552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 0];
43545552b385SBrandon denomOld = bprv[offset + (3 * mm) + 0];
43555552b385SBrandon } else if (jj == 1) { //Y
43565552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0];
43575552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1] + deltaCoord;
43585552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2];
43595552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 1];
43605552b385SBrandon denomOld = bprv[offset + (3 * mm) + 1];
43615552b385SBrandon } else if (jj == 2) { //Z
43625552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0];
43635552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1];
43645552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2] + deltaCoord;
43655552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 2];
43665552b385SBrandon denomOld = bprv[offset + (3 * mm) + 2];
43675552b385SBrandon } else if (jj == 3) { // Weights
43685552b385SBrandon nbprv[wOffset + mm] = bprv[wOffset + mm] + deltaCoord;
43695552b385SBrandon denomNew = nbprv[wOffset + mm];
43705552b385SBrandon denomOld = bprv[wOffset + mm];
43715552b385SBrandon } else {
43725552b385SBrandon // currently do nothing
43735552b385SBrandon }
43745552b385SBrandon }
43755552b385SBrandon }
43765552b385SBrandon
43775552b385SBrandon // Create New Surface Based on New Control Points or Weights
43785552b385SBrandon ego newgeom, context;
43795552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ versions KNOWN_ISSUE
43805552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE
43815552b385SBrandon
43825552b385SBrandon // Create New FACE based on modified geometry
43835552b385SBrandon double newFaceRange[4];
43845552b385SBrandon int newFacePeri;
43855552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, newFaceRange, &newFacePeri));
43865552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, newFaceRange, &newFacePeri));
43875552b385SBrandon
43885552b385SBrandon ego newface;
43895552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE
43905552b385SBrandon
43915552b385SBrandon // store new face for later assembly
43925552b385SBrandon newGeom[kk] = newgeom;
43935552b385SBrandon newFaces[kk] = newface;
43945552b385SBrandon }
43955552b385SBrandon
43965552b385SBrandon // X-WANT TO BUILD THE NEW GEOMETRY, X-GET NEW SA AND PERFORM dSA/dCPi CALCS HERE <---
43975552b385SBrandon // Sew New Faces together to get a new model
43985552b385SBrandon ego newmodel;
43995552b385SBrandon PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE
44005552b385SBrandon
44015552b385SBrandon // Get Surface Area and Volume of New/Updated Solid Body
44025552b385SBrandon PetscScalar newData[14];
44035552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
44045552b385SBrandon else PetscCallEGADS(EG_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
44055552b385SBrandon
44065552b385SBrandon ego nbody = bodies[0];
44075552b385SBrandon PetscCall(EG_getMassProperties(nbody, newData)); // Does not have an EGlite_ version KNOWN_ISSUE
44085552b385SBrandon
44095552b385SBrandon PetscScalar dSAdCPi, dVdCPi;
44105552b385SBrandon PetscScalar nbodyVol = newData[0], nbodySA = newData[1];
44115552b385SBrandon
44125552b385SBrandon // Calculate Gradients wrt to Control Points and Control Points Weights depending on jj value
44135552b385SBrandon dSAdCPi = (nbodySA - bodySA) / (denomNew - denomOld);
44145552b385SBrandon dVdCPi = (nbodyVol - bodyVol) / (denomNew - denomOld);
44155552b385SBrandon
44165552b385SBrandon if (jj < 3) {
44175552b385SBrandon // Gradienst wrt to Control Points
44185552b385SBrandon gradSACP[(ii * 3) + jj] = dSAdCPi;
44195552b385SBrandon gradVCP[(ii * 3) + jj] = dVdCPi;
44205552b385SBrandon } else if (jj == 3) {
44215552b385SBrandon // Gradients wrt to Control Point Weights
44225552b385SBrandon gradSAW[ii] = dSAdCPi;
44235552b385SBrandon gradVW[ii] = dVdCPi;
44245552b385SBrandon } else {
44255552b385SBrandon // Do Nothing
44265552b385SBrandon }
44275552b385SBrandon PetscCallEGADS(EG_deleteObject, (newmodel));
44285552b385SBrandon for (int kk = 0; kk < Nf; ++kk) {
44295552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[kk]));
44305552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[kk]));
44315552b385SBrandon }
44325552b385SBrandon }
44335552b385SBrandon }
44345552b385SBrandon }
44355552b385SBrandon PetscCall(VecRestoreArrayWrite(gradSACPVec, &gradSACP));
44365552b385SBrandon PetscCall(VecRestoreArrayWrite(gradSAWVec, &gradSAW));
44375552b385SBrandon PetscCall(VecRestoreArrayWrite(gradVCPVec, &gradVCP));
44385552b385SBrandon PetscCall(VecRestoreArrayWrite(gradVWVec, &gradVW));
44395552b385SBrandon PetscCall(MatDestroy(&cpEquiv));
44405552b385SBrandon
44415552b385SBrandon // Attach Surface Gradient Hash Table and Matrix to DM
44425552b385SBrandon {
44435552b385SBrandon PetscContainer surfGradOrgObj;
44445552b385SBrandon
44455552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&surfGradOrgObj));
44465552b385SBrandon if (!surfGradOrgObj) {
44475552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj));
44485552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start));
44495552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(surfGradOrgObj, DestroyHashMap));
44505552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj));
44515552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradOrgObj));
44525552b385SBrandon } else {
44535552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start));
44545552b385SBrandon }
44555552b385SBrandon
44565552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)pointSurfGrad));
44575552b385SBrandon PetscCall(MatDestroy(&pointSurfGrad));
44585552b385SBrandon
44595552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject)gradSACPVec));
44605552b385SBrandon PetscCall(VecDestroy(&gradSACPVec));
44615552b385SBrandon
44625552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject)gradSAWVec));
44635552b385SBrandon PetscCall(VecDestroy(&gradSAWVec));
44645552b385SBrandon
44655552b385SBrandon if (fullGeomGrad) {
44665552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Control Point Gradient", (PetscObject)gradVCPVec));
44675552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Weights Gradient", (PetscObject)gradVWVec));
44685552b385SBrandon }
44695552b385SBrandon PetscCall(VecDestroy(&gradVCPVec));
44705552b385SBrandon PetscCall(VecDestroy(&gradVWVec));
44715552b385SBrandon }
44725552b385SBrandon
44735552b385SBrandon // Could be replaced with DMPlexFreeGeomObject()
44745552b385SBrandon if (islite) EGlite_free(fobjs);
44755552b385SBrandon else EG_free(fobjs);
44765552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
44775552b385SBrandon #else
44785552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads");
44795552b385SBrandon #endif
44805552b385SBrandon }
44815552b385SBrandon
44825552b385SBrandon /*@C
44835552b385SBrandon DMPlexModifyGeomModel - Generates a new EGADS geometry model based in user provided Control Points and Control Points Weights. Optionally, the function will inflate the DM to the new geometry and save the new geometry to a file.
44845552b385SBrandon
44855552b385SBrandon Collective
44865552b385SBrandon
44875552b385SBrandon Input Parameters:
44885552b385SBrandon + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model
44895552b385SBrandon . comm - MPI_Comm object
44905552b385SBrandon . newCP - C Array of [x, y, z] New/Updated Control Point Coordinates defining the geometry (See DMPlexGeomDataAndGrads() for format)
44915552b385SBrandon . newW - C Array of New/Updated Control Point Weights associated with the Control Points defining the new geometry (See DMPlexGemGrads() for format)
44925552b385SBrandon . autoInflate - PetscBool Flag denoting if the user would like to inflate the DM points to the new geometry.
44935552b385SBrandon . saveGeom - PetscBool Flag denoting if the user would iike to save the new geometry to a file.
44945552b385SBrandon - stpName - Char Array indicating the name of the file to save the new geometry to. Extension must be included and will denote type of file written.
44955552b385SBrandon *.stp or *.step = STEP File
44965552b385SBrandon *.igs or *.iges = IGES File
44975552b385SBrandon *.egads = EGADS File
44985552b385SBrandon *.brep = BRep File (OpenCASCADE File)
44995552b385SBrandon
45005552b385SBrandon Output Parameter:
45015552b385SBrandon . dm - The updated DM object representing the mesh with PetscContainers containing the updated/modified geometry
45025552b385SBrandon
45035552b385SBrandon Level: intermediate
45045552b385SBrandon
45055552b385SBrandon Note:
45065552b385SBrandon Functionality not available for DMPlexes with attached EGADSlite geometry files (.egadslite).
45075552b385SBrandon
45085552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()`
45095552b385SBrandon @*/
DMPlexModifyGeomModel(DM dm,MPI_Comm comm,PetscScalar newCP[],PetscScalar newW[],PetscBool autoInflate,PetscBool saveGeom,const char * stpName)4510ce78bad3SBarry Smith PetscErrorCode DMPlexModifyGeomModel(DM dm, MPI_Comm comm, PetscScalar newCP[], PetscScalar newW[], PetscBool autoInflate, PetscBool saveGeom, const char *stpName) PeNS
45115552b385SBrandon {
45125552b385SBrandon #if defined(PETSC_HAVE_EGADS)
45135552b385SBrandon /* EGADS/EGADSlite variables */
45145552b385SBrandon ego context, model, geom, *bodies, *lobjs, *fobjs;
45155552b385SBrandon int oclass, mtype, *senses, *lsenses;
45165552b385SBrandon int Nb, Nf, Nl, id;
45175552b385SBrandon /* PETSc variables */
45185552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
45195552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj;
45205552b385SBrandon PetscHMapI cpHashTable = NULL, wHashTable = NULL;
45215552b385SBrandon PetscBool islite = PETSC_FALSE;
45225552b385SBrandon #endif
45235552b385SBrandon
45245552b385SBrandon #if defined(PETSC_HAVE_EGADS)
45255552b385SBrandon PetscFunctionBegin;
45265552b385SBrandon // Look to see if DM has a Container with either a EGADS or EGADSlite Model
45275552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
45285552b385SBrandon if (!modelObj) {
45295552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
45305552b385SBrandon islite = PETSC_TRUE;
45315552b385SBrandon }
45325552b385SBrandon PetscCheck(!islite, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot modify geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep");
45335552b385SBrandon PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have a EGADS Geometry Model attached to it!");
45345552b385SBrandon
45355552b385SBrandon // Get attached EGADS model (pointer)
45362a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(modelObj, &model));
45375552b385SBrandon
45385552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data
45395552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj));
45405552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj));
45415552b385SBrandon
45425552b385SBrandon PetscCheck(cpHashTableObj && wHashTableObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have required Geometry Data attached! Please run DMPlexGeomDataAndGrads() Function first.");
45435552b385SBrandon
45445552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer)
45452a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cpHashTableObj, &cpHashTable));
45462a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(wHashTableObj, &wHashTable));
45475552b385SBrandon
45485552b385SBrandon // Get the number of bodies and body objects in the model
45495552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
45505552b385SBrandon else PetscCallEGADS(EG_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
45515552b385SBrandon
45525552b385SBrandon // Get all Faces on the body
45535552b385SBrandon ego body = bodies[0];
45545552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs));
45555552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs));
45565552b385SBrandon
45575552b385SBrandon ego newGeom[Nf];
45585552b385SBrandon ego newFaces[Nf];
45595552b385SBrandon
45605552b385SBrandon // Update Control Point and Weight definitions for each surface
45615552b385SBrandon for (int jj = 0; jj < Nf; ++jj) {
45625552b385SBrandon ego face = fobjs[jj];
45635552b385SBrandon ego bRef, bPrev, bNext;
45645552b385SBrandon ego fgeom;
45655552b385SBrandon int offset;
45665552b385SBrandon int boclass, bmtype, *bpinfo;
45675552b385SBrandon double *bprv;
45685552b385SBrandon
45695552b385SBrandon // Get FACE ID and other Geometry Data
45705552b385SBrandon if (islite) {
45715552b385SBrandon id = EGlite_indexBodyTopo(body, face);
45725552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses));
45735552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
45745552b385SBrandon PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
45755552b385SBrandon } else {
45765552b385SBrandon id = EG_indexBodyTopo(body, face);
45775552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses));
45785552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv));
45795552b385SBrandon PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext));
45805552b385SBrandon }
45815552b385SBrandon
45825552b385SBrandon // Update Control Points
45835552b385SBrandon PetscHashIter CPiter, Witer;
45845552b385SBrandon PetscBool CPfound, Wfound;
45855552b385SBrandon PetscInt faceCPStartRow, faceWStartRow;
45865552b385SBrandon
45875552b385SBrandon PetscCall(PetscHMapIFind(cpHashTable, id, &CPiter, &CPfound));
45885552b385SBrandon PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table");
45895552b385SBrandon PetscCall(PetscHMapIGet(cpHashTable, id, &faceCPStartRow));
45905552b385SBrandon
45915552b385SBrandon PetscCall(PetscHMapIFind(wHashTable, id, &Witer, &Wfound));
45925552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table");
45935552b385SBrandon PetscCall(PetscHMapIGet(wHashTable, id, &faceWStartRow));
45945552b385SBrandon
45955552b385SBrandon // UPDATE CONTROL POINTS Locations
45965552b385SBrandon offset = bpinfo[3] + bpinfo[6];
4597ac530a7eSPierre Jolivet for (int ii = 0; ii < 3 * bpinfo[2] * bpinfo[5]; ++ii) bprv[offset + ii] = newCP[faceCPStartRow + ii];
45985552b385SBrandon
45995552b385SBrandon // UPDATE CONTROL POINT WEIGHTS
46005552b385SBrandon offset = bpinfo[3] + bpinfo[6] + 3 * bpinfo[2] * bpinfo[5];
4601ac530a7eSPierre Jolivet for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) bprv[offset + ii] = newW[faceWStartRow + ii];
46025552b385SBrandon
46035552b385SBrandon // Get Context from FACE
46045552b385SBrandon context = NULL;
46055552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version KNOWN_ISSUE
46065552b385SBrandon
46075552b385SBrandon // Create New Surface
46085552b385SBrandon ego newgeom;
46095552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE
46105552b385SBrandon
46115552b385SBrandon // Create new FACE based on new SURFACE geometry
46125552b385SBrandon double data[4];
46135552b385SBrandon int periodic;
46145552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic));
46155552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic));
46165552b385SBrandon
46175552b385SBrandon ego newface;
46185552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE
46195552b385SBrandon newGeom[jj] = newgeom;
46205552b385SBrandon newFaces[jj] = newface;
46215552b385SBrandon }
46225552b385SBrandon // Could be replaced by DMPlexFreeGeomObject
46235552b385SBrandon if (islite) EGlite_free(fobjs);
46245552b385SBrandon else EG_free(fobjs);
46255552b385SBrandon
46265552b385SBrandon // Sew New Faces together to get a new model
46275552b385SBrandon ego newmodel;
46285552b385SBrandon PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE
46295552b385SBrandon for (PetscInt f = 0; f < Nf; ++f) {
46305552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[f]));
46315552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[f]));
46325552b385SBrandon }
46335552b385SBrandon
46345552b385SBrandon // Get the total number of NODEs on the original geometry. (This will be the same for the new geometry)
46355552b385SBrandon int totalNumNode;
46365552b385SBrandon ego *nobjTotal;
46375552b385SBrandon if (islite) {
46385552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal));
46395552b385SBrandon EGlite_free(nobjTotal);
46405552b385SBrandon } else {
46415552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal));
46425552b385SBrandon EG_free(nobjTotal);
46435552b385SBrandon } // Could be replaced with DMPlexFreeGeomObject
46445552b385SBrandon
46455552b385SBrandon // Initialize vector to store equivalent NODE indices between the 2 geometries
46465552b385SBrandon // FORMAT :: vector index is the Original Geometry's NODE ID, the vector Value is the New Geometry's NODE ID
46475552b385SBrandon int nodeIDEquiv[totalNumNode + 1];
46485552b385SBrandon
46495552b385SBrandon // Now we need to Map the NODE and EDGE IDs from each Model
46505552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs));
46515552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs));
46525552b385SBrandon
46535552b385SBrandon // New CAD
46545552b385SBrandon ego *newbodies, newgeomtest, *nfobjs;
46555552b385SBrandon int nNf, newNb, newoclass, newmtype, *newsenses;
46565552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses));
46575552b385SBrandon else PetscCallEGADS(EG_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses));
46585552b385SBrandon
46595552b385SBrandon ego newbody = newbodies[0];
46605552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs));
46615552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs));
46625552b385SBrandon
46635552b385SBrandon PetscCheck(newNb == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ERROR :: newNb > 1 || newNb = %d", newNb);
46645552b385SBrandon
46655552b385SBrandon // Find Equivalent Nodes
46665552b385SBrandon for (int ii = 0; ii < Nf; ++ii) {
46675552b385SBrandon double fdata[4];
46685552b385SBrandon int peri;
46695552b385SBrandon
46705552b385SBrandon // Get Current FACE [u, v] Ranges
46715552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (fobjs[ii], fdata, &peri));
46725552b385SBrandon else PetscCallEGADS(EG_getRange, (fobjs[ii], fdata, &peri));
46735552b385SBrandon
46745552b385SBrandon // Equate NODE IDs between 2 FACEs by working through (u, v) limits of FACE
46755552b385SBrandon for (int jj = 0; jj < 2; ++jj) {
46765552b385SBrandon for (int kk = 2; kk < 4; ++kk) {
46775552b385SBrandon double params[2] = {fdata[jj], fdata[kk]};
46785552b385SBrandon double eval[18];
46795552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (fobjs[ii], params, eval));
46805552b385SBrandon else PetscCallEGADS(EG_evaluate, (fobjs[ii], params, eval));
46815552b385SBrandon
46825552b385SBrandon // Original Body
46835552b385SBrandon ego *nobjsOrigFace;
46845552b385SBrandon int origNn;
46855552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace));
46865552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace));
46875552b385SBrandon
46885552b385SBrandon double minVal = 1.0E10;
46895552b385SBrandon double evalCheck[18];
46905552b385SBrandon int equivOrigNodeID = -1;
46915552b385SBrandon for (int mm = 0; mm < origNn; ++mm) {
46925552b385SBrandon double delta = 1.0E10;
46935552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsOrigFace[mm], NULL, evalCheck));
46945552b385SBrandon else PetscCallEGADS(EG_evaluate, (nobjsOrigFace[mm], NULL, evalCheck));
46955552b385SBrandon
46965552b385SBrandon delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2]));
46975552b385SBrandon
46985552b385SBrandon if (delta < minVal) {
46995552b385SBrandon if (islite) equivOrigNodeID = EGlite_indexBodyTopo(body, nobjsOrigFace[mm]);
47005552b385SBrandon else equivOrigNodeID = EG_indexBodyTopo(body, nobjsOrigFace[mm]);
47015552b385SBrandon
47025552b385SBrandon minVal = delta;
47035552b385SBrandon }
47045552b385SBrandon }
47055552b385SBrandon // Could be replaced with DMPlexFreeGeomObject
47065552b385SBrandon if (islite) EGlite_free(nobjsOrigFace);
47075552b385SBrandon else EG_free(nobjsOrigFace);
47085552b385SBrandon
47095552b385SBrandon // New Body
47105552b385SBrandon ego *nobjsNewFace;
47115552b385SBrandon int newNn;
47125552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace));
47135552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace));
47145552b385SBrandon
47155552b385SBrandon minVal = 1.0E10;
47165552b385SBrandon int equivNewNodeID = -1;
47175552b385SBrandon for (int mm = 0; mm < newNn; ++mm) {
47185552b385SBrandon double delta = 1.0E10;
47195552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsNewFace[mm], NULL, evalCheck));
47205552b385SBrandon else PetscCallEGADS(EG_evaluate, (nobjsNewFace[mm], NULL, evalCheck));
47215552b385SBrandon
47225552b385SBrandon delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2]));
47235552b385SBrandon
47245552b385SBrandon if (delta < minVal) {
47255552b385SBrandon if (islite) equivNewNodeID = EGlite_indexBodyTopo(newbody, nobjsNewFace[mm]);
47265552b385SBrandon else equivNewNodeID = EG_indexBodyTopo(newbody, nobjsNewFace[mm]);
47275552b385SBrandon
47285552b385SBrandon minVal = delta;
47295552b385SBrandon }
47305552b385SBrandon }
47315552b385SBrandon if (islite) EGlite_free(nobjsNewFace);
47325552b385SBrandon else EG_free(nobjsNewFace);
47335552b385SBrandon
47345552b385SBrandon // Store equivalent NODE IDs
47355552b385SBrandon nodeIDEquiv[equivOrigNodeID] = equivNewNodeID;
47365552b385SBrandon }
47375552b385SBrandon }
47385552b385SBrandon }
47395552b385SBrandon
47405552b385SBrandon // Find Equivalent EDGEs
47415552b385SBrandon // Get total number of EDGEs on Original Geometry
47425552b385SBrandon int totalNumEdge;
47435552b385SBrandon ego *eobjsOrig;
47445552b385SBrandon if (islite) {
47455552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig));
47465552b385SBrandon EGlite_free(eobjsOrig);
47475552b385SBrandon } else {
47485552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig));
47495552b385SBrandon EG_free(eobjsOrig);
47505552b385SBrandon }
47515552b385SBrandon
47525552b385SBrandon // Get total number of EDGEs on New Geometry
47535552b385SBrandon int totalNumEdgeNew;
47545552b385SBrandon ego *eobjsNew;
47555552b385SBrandon if (islite) {
47565552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew));
47575552b385SBrandon EGlite_free(eobjsNew);
47585552b385SBrandon } else {
47595552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew));
47605552b385SBrandon EG_free(eobjsNew);
47615552b385SBrandon }
47625552b385SBrandon
47635552b385SBrandon // Initialize EDGE ID equivalent vector
47645552b385SBrandon // FORMAT :: vector index is the Original Geometry's EDGE ID, the vector Value is the New Geometry's EDGE ID
47655552b385SBrandon int edgeIDEquiv[totalNumEdge + 1];
47665552b385SBrandon
47675552b385SBrandon // Find Equivalent EDGEs
47685552b385SBrandon for (int ii = 0; ii < Nf; ++ii) {
47695552b385SBrandon // Get Original Geometry EDGE's NODEs
47705552b385SBrandon int numOrigEdge, numNewEdge;
47715552b385SBrandon if (islite) {
47725552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig));
47735552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew));
47745552b385SBrandon } else {
47755552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig));
47765552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew));
47775552b385SBrandon }
47785552b385SBrandon
47795552b385SBrandon // new loop below
47805552b385SBrandon for (int nn = 0; nn < numOrigEdge; ++nn) {
47815552b385SBrandon ego origEdge = eobjsOrig[nn];
47825552b385SBrandon ego geomEdgeOrig, *nobjsOrig;
47835552b385SBrandon int oclassEdgeOrig, mtypeEdgeOrig;
47845552b385SBrandon int NnOrig, *nsensesEdgeOrig;
47855552b385SBrandon
47865552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig));
47875552b385SBrandon else PetscCallEGADS(EG_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig));
47885552b385SBrandon
47895552b385SBrandon PetscBool isSame = PETSC_FALSE;
47905552b385SBrandon for (int jj = 0; jj < numNewEdge; ++jj) {
47915552b385SBrandon ego newEdge = eobjsNew[jj];
47925552b385SBrandon ego geomEdgeNew, *nobjsNew;
47935552b385SBrandon int oclassEdgeNew, mtypeEdgeNew;
47945552b385SBrandon int NnNew, *nsensesEdgeNew;
47955552b385SBrandon
47965552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew));
47975552b385SBrandon else PetscCallEGADS(EG_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew));
47985552b385SBrandon
47995552b385SBrandon if (mtypeEdgeOrig == mtypeEdgeNew) {
48005552b385SBrandon // Only operate if the EDGE types are the same
48015552b385SBrandon for (int kk = 0; kk < NnNew; ++kk) {
48025552b385SBrandon int nodeIDOrigGeom, nodeIDNewGeom;
48035552b385SBrandon if (islite) {
48045552b385SBrandon nodeIDOrigGeom = EGlite_indexBodyTopo(body, nobjsOrig[kk]);
48055552b385SBrandon nodeIDNewGeom = EGlite_indexBodyTopo(newbody, nobjsNew[kk]);
48065552b385SBrandon } else {
48075552b385SBrandon nodeIDOrigGeom = EG_indexBodyTopo(body, nobjsOrig[kk]);
48085552b385SBrandon nodeIDNewGeom = EG_indexBodyTopo(newbody, nobjsNew[kk]);
48095552b385SBrandon }
48105552b385SBrandon
48115552b385SBrandon if (nodeIDNewGeom == nodeIDEquiv[nodeIDOrigGeom]) {
48125552b385SBrandon isSame = PETSC_TRUE;
48135552b385SBrandon } else {
48145552b385SBrandon isSame = PETSC_FALSE;
48155552b385SBrandon kk = NnNew; // skip ahead because first NODE failed test and order is important
48165552b385SBrandon }
48175552b385SBrandon }
48185552b385SBrandon
48195552b385SBrandon if (isSame == PETSC_TRUE) {
48205552b385SBrandon int edgeIDOrig, edgeIDNew;
48215552b385SBrandon if (islite) {
48225552b385SBrandon edgeIDOrig = EGlite_indexBodyTopo(body, origEdge);
48235552b385SBrandon edgeIDNew = EGlite_indexBodyTopo(newbody, newEdge);
48245552b385SBrandon } else {
48255552b385SBrandon edgeIDOrig = EG_indexBodyTopo(body, origEdge);
48265552b385SBrandon edgeIDNew = EG_indexBodyTopo(newbody, newEdge);
48275552b385SBrandon }
48285552b385SBrandon
48295552b385SBrandon edgeIDEquiv[edgeIDOrig] = edgeIDNew;
48305552b385SBrandon jj = numNewEdge;
48315552b385SBrandon }
48325552b385SBrandon }
48335552b385SBrandon }
48345552b385SBrandon }
48355552b385SBrandon if (islite) {
48365552b385SBrandon EGlite_free(eobjsOrig);
48375552b385SBrandon EGlite_free(eobjsNew);
48385552b385SBrandon } else {
48395552b385SBrandon EG_free(eobjsOrig);
48405552b385SBrandon EG_free(eobjsNew);
48415552b385SBrandon }
48425552b385SBrandon }
48435552b385SBrandon if (islite) {
48445552b385SBrandon EGlite_free(fobjs);
48455552b385SBrandon EGlite_free(nfobjs);
48465552b385SBrandon } else {
48475552b385SBrandon EG_free(fobjs);
48485552b385SBrandon EG_free(nfobjs);
48495552b385SBrandon }
48505552b385SBrandon
48515552b385SBrandon // Modify labels to point to the IDs on the new Geometry
48525552b385SBrandon IS isNodeID, isEdgeID;
48535552b385SBrandon
48545552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
48555552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
48565552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
48575552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
48585552b385SBrandon
48595552b385SBrandon PetscCall(ISCreateGeneral(comm, totalNumNode + 1, nodeIDEquiv, PETSC_COPY_VALUES, &isNodeID));
48605552b385SBrandon PetscCall(ISCreateGeneral(comm, totalNumEdge + 1, edgeIDEquiv, PETSC_COPY_VALUES, &isEdgeID));
48615552b385SBrandon /* Do not perform check. Np may != Nv due to Degenerate Geometry which is not stored in labels. */
48625552b385SBrandon /* We do not know in advance which IDs have been omitted. This may also change due to geometry modifications. */
48635552b385SBrandon PetscCall(DMLabelRewriteValues(vertexLabel, isNodeID));
48645552b385SBrandon PetscCall(DMLabelRewriteValues(edgeLabel, isEdgeID));
48655552b385SBrandon PetscCall(ISDestroy(&isNodeID));
48665552b385SBrandon PetscCall(ISDestroy(&isEdgeID));
48675552b385SBrandon
48685552b385SBrandon // Attempt to point to the new geometry
48695552b385SBrandon PetscCallEGADS(EG_deleteObject, (model));
48705552b385SBrandon PetscCall(PetscContainerSetPointer(modelObj, newmodel));
48715552b385SBrandon
48725552b385SBrandon // save updated model to file
48735552b385SBrandon if (saveGeom == PETSC_TRUE && stpName != NULL) PetscCall(EG_saveModel(newmodel, stpName));
48745552b385SBrandon
48755552b385SBrandon // Inflate Mesh to EGADS Model
48765552b385SBrandon if (autoInflate == PETSC_TRUE) PetscCall(DMPlexInflateToGeomModel(dm, PETSC_TRUE));
48775552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
48785552b385SBrandon #else
48795552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads");
48805552b385SBrandon #endif
48815552b385SBrandon }
48825552b385SBrandon
48835552b385SBrandon /*@C
48845552b385SBrandon DMPlexGetGeomModelTUV - Gets the [t] (EDGES) and [u, v] (FACES) geometry parameters of DM points that are associated geometry relationships. Requires a DM with a EGADS model attached.
48855552b385SBrandon
48865552b385SBrandon Collective
48875552b385SBrandon
48885552b385SBrandon Input Parameter:
48895552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model
48905552b385SBrandon
48915552b385SBrandon Level: intermediate
48925552b385SBrandon
48935552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()`
48945552b385SBrandon @*/
DMPlexGetGeomModelTUV(DM dm)4895ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelTUV(DM dm) PeNS
48965552b385SBrandon {
48975552b385SBrandon #if defined(PETSC_HAVE_EGADS)
48985552b385SBrandon /* EGADS Variables */
48995552b385SBrandon ego model, geom, body, face, edge;
49005552b385SBrandon ego *bodies;
49015552b385SBrandon int Nb, oclass, mtype, *senses;
49025552b385SBrandon double result[4];
49035552b385SBrandon /* PETSc Variables */
49045552b385SBrandon DM cdm;
49055552b385SBrandon PetscContainer modelObj;
49065552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
49075552b385SBrandon Vec coordinates;
49085552b385SBrandon PetscScalar *coords;
49095552b385SBrandon PetscInt bodyID, faceID, edgeID, vertexID;
49105552b385SBrandon PetscInt cdim, vStart, vEnd, v;
49115552b385SBrandon PetscBool islite = PETSC_FALSE;
49125552b385SBrandon #endif
49135552b385SBrandon
49145552b385SBrandon PetscFunctionBegin;
49155552b385SBrandon #if defined(PETSC_HAVE_EGADS)
49165552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
49175552b385SBrandon if (!modelObj) {
49185552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
49195552b385SBrandon islite = PETSC_TRUE;
49205552b385SBrandon }
4921b6555650SPierre Jolivet if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS);
49225552b385SBrandon
49235552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &cdim));
49245552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm));
49255552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
49265552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
49275552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
49285552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
49295552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
49305552b385SBrandon
49312a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(modelObj, &model));
49325552b385SBrandon
49335552b385SBrandon if (islite) PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
49345552b385SBrandon else PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
49355552b385SBrandon
49365552b385SBrandon PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
49375552b385SBrandon PetscCall(VecGetArrayWrite(coordinates, &coords));
49385552b385SBrandon
49395552b385SBrandon // Define t, u, v arrays to be stored in a PetscContainer after populated
49405552b385SBrandon PetscScalar *t_point, *u_point, *v_point;
49415552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &t_point));
49425552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &u_point));
49435552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &v_point));
49445552b385SBrandon
49455552b385SBrandon for (v = vStart; v < vEnd; ++v) {
49465552b385SBrandon PetscScalar *vcoords;
49475552b385SBrandon
49485552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID));
49495552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, v, &faceID));
49505552b385SBrandon PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID));
49515552b385SBrandon PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID));
49525552b385SBrandon
49535552b385SBrandon // TODO Figure out why this is unknown sometimes
49545552b385SBrandon if (bodyID < 0 && Nb == 1) bodyID = 0;
49555552b385SBrandon PetscCheck(bodyID >= 0 && bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " for vertex %" PetscInt_FMT " is not in [0, %d)", bodyID, v, Nb);
4956c1cad2e7SMatthew G. Knepley body = bodies[bodyID];
4957c1cad2e7SMatthew G. Knepley
49589566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords));
4959c1cad2e7SMatthew G. Knepley if (edgeID > 0) {
4960c1cad2e7SMatthew G. Knepley /* Snap to EDGE at nearest location */
4961c1cad2e7SMatthew G. Knepley double params[1];
49625552b385SBrandon
49635552b385SBrandon if (islite) {
49645552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge));
49655552b385SBrandon PetscCall(EGlite_invEvaluate(edge, vcoords, params, result));
49665552b385SBrandon } // Get (t) of nearest point on EDGE
49675552b385SBrandon else {
49689566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge));
49695552b385SBrandon PetscCall(EG_invEvaluate(edge, vcoords, params, result));
49705552b385SBrandon } // Get (t) of nearest point on EDGE
49715552b385SBrandon
49725552b385SBrandon t_point[v - vStart] = params[0];
49735552b385SBrandon u_point[v - vStart] = 0.0;
49745552b385SBrandon v_point[v - vStart] = 0.0;
4975c1cad2e7SMatthew G. Knepley } else if (faceID > 0) {
4976c1cad2e7SMatthew G. Knepley /* Snap to FACE at nearest location */
4977c1cad2e7SMatthew G. Knepley double params[2];
49785552b385SBrandon
49795552b385SBrandon if (islite) {
49805552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face));
49815552b385SBrandon PetscCall(EGlite_invEvaluate(face, vcoords, params, result));
49825552b385SBrandon } // Get (x,y,z) of nearest point on FACE
49835552b385SBrandon else {
49849566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face));
49855552b385SBrandon PetscCall(EG_invEvaluate(face, vcoords, params, result));
49865552b385SBrandon } // Get (x,y,z) of nearest point on FACE
49875552b385SBrandon
49885552b385SBrandon t_point[v - vStart] = 0.0;
49895552b385SBrandon u_point[v - vStart] = params[0];
49905552b385SBrandon v_point[v - vStart] = params[1];
49915552b385SBrandon } else {
49925552b385SBrandon t_point[v - vStart] = 0.0;
49935552b385SBrandon u_point[v - vStart] = 0.0;
49945552b385SBrandon v_point[v - vStart] = 0.0;
49955552b385SBrandon }
49965552b385SBrandon }
49975552b385SBrandon PetscCall(VecRestoreArrayWrite(coordinates, &coords));
49985552b385SBrandon /* Clear out global coordinates */
49995552b385SBrandon PetscCall(VecDestroy(&dm->coordinates[0].x));
50005552b385SBrandon
50015552b385SBrandon /* Store in PetscContainters */
50025552b385SBrandon {
50035552b385SBrandon PetscContainer t_pointObj, u_pointObj, v_pointObj;
50045552b385SBrandon
50055552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj));
50065552b385SBrandon if (!t_pointObj) {
50075552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &t_pointObj));
50085552b385SBrandon PetscCall(PetscContainerSetPointer(t_pointObj, t_point));
50095552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Edge t Parameter", (PetscObject)t_pointObj));
50105552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(t_pointObj, PetscCtxDestroyDefault));
50115552b385SBrandon PetscCall(PetscContainerDestroy(&t_pointObj));
50125552b385SBrandon } else {
50135552b385SBrandon void *old;
50145552b385SBrandon
50155552b385SBrandon PetscCall(PetscContainerGetPointer(t_pointObj, &old));
50165552b385SBrandon PetscCall(PetscFree(old));
50175552b385SBrandon PetscCall(PetscContainerSetPointer(t_pointObj, t_point));
50185552b385SBrandon }
50195552b385SBrandon
50205552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj));
50215552b385SBrandon if (!u_pointObj) {
50225552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &u_pointObj));
50235552b385SBrandon PetscCall(PetscContainerSetPointer(u_pointObj, u_point));
50245552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face u Parameter", (PetscObject)u_pointObj));
50255552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(u_pointObj, PetscCtxDestroyDefault));
50265552b385SBrandon PetscCall(PetscContainerDestroy(&u_pointObj));
50275552b385SBrandon } else {
50285552b385SBrandon void *old;
50295552b385SBrandon
50305552b385SBrandon PetscCall(PetscContainerGetPointer(u_pointObj, &old));
50315552b385SBrandon PetscCall(PetscFree(old));
50325552b385SBrandon PetscCall(PetscContainerSetPointer(u_pointObj, u_point));
50335552b385SBrandon }
50345552b385SBrandon
50355552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj));
50365552b385SBrandon if (!v_pointObj) {
50375552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &v_pointObj));
50385552b385SBrandon PetscCall(PetscContainerSetPointer(v_pointObj, v_point));
50395552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face v Parameter", (PetscObject)v_pointObj));
50405552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(v_pointObj, PetscCtxDestroyDefault));
50415552b385SBrandon PetscCall(PetscContainerDestroy(&v_pointObj));
50425552b385SBrandon } else {
50435552b385SBrandon void *old;
50445552b385SBrandon
50455552b385SBrandon PetscCall(PetscContainerGetPointer(v_pointObj, &old));
50465552b385SBrandon PetscCall(PetscFree(old));
50475552b385SBrandon PetscCall(PetscContainerSetPointer(v_pointObj, v_point));
50485552b385SBrandon }
50495552b385SBrandon }
50505552b385SBrandon #endif
50515552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
50525552b385SBrandon }
50535552b385SBrandon
50545552b385SBrandon /*@C
50555552b385SBrandon DMPlexInflateToGeomModelUseTUV - Inflates the DM to the associated underlying geometry using the [t] {EDGES) and [u, v] (FACES} associated parameters. Requires a DM with an EGADS model attached and a previous call to DMPlexGetGeomModelTUV().
50565552b385SBrandon
50575552b385SBrandon Collective
50585552b385SBrandon
50595552b385SBrandon Input Parameter:
50605552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model
50615552b385SBrandon
50625552b385SBrandon Level: intermediate
50635552b385SBrandon
50645552b385SBrandon Note:
50655552b385SBrandon The updated DM object inflated to the associated underlying geometry. This updates the [x, y, z] coordinates of DM points associated with geometry.
50665552b385SBrandon
50675552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()`, `DMPlexGetGeomModelTUV()`
50685552b385SBrandon @*/
DMPlexInflateToGeomModelUseTUV(DM dm)5069ce78bad3SBarry Smith PetscErrorCode DMPlexInflateToGeomModelUseTUV(DM dm) PeNS
50705552b385SBrandon {
50715552b385SBrandon #if defined(PETSC_HAVE_EGADS)
50725552b385SBrandon /* EGADS Variables */
50735552b385SBrandon ego model, geom, body, face, edge, vertex;
50745552b385SBrandon ego *bodies;
50755552b385SBrandon int Nb, oclass, mtype, *senses;
50765552b385SBrandon double result[18], params[2];
50775552b385SBrandon /* PETSc Variables */
50785552b385SBrandon DM cdm;
50795552b385SBrandon PetscContainer modelObj;
50805552b385SBrandon PetscContainer t_pointObj, u_pointObj, v_pointObj;
50815552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
50825552b385SBrandon Vec coordinates;
50835552b385SBrandon PetscScalar *coords;
50845552b385SBrandon PetscScalar *t_point, *u_point, *v_point;
50855552b385SBrandon PetscInt bodyID, faceID, edgeID, vertexID;
50865552b385SBrandon PetscInt cdim, d, vStart, vEnd, v;
50875552b385SBrandon PetscBool islite = PETSC_FALSE;
50885552b385SBrandon #endif
50895552b385SBrandon
50905552b385SBrandon PetscFunctionBegin;
50915552b385SBrandon #if defined(PETSC_HAVE_EGADS)
50925552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
50935552b385SBrandon if (!modelObj) {
50945552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
50955552b385SBrandon islite = PETSC_TRUE;
50965552b385SBrandon }
50975552b385SBrandon
50985552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj));
50995552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj));
51005552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj));
51015552b385SBrandon
51025552b385SBrandon if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS);
51035552b385SBrandon if (!t_pointObj) PetscFunctionReturn(PETSC_SUCCESS);
51045552b385SBrandon if (!u_pointObj) PetscFunctionReturn(PETSC_SUCCESS);
51055552b385SBrandon if (!v_pointObj) PetscFunctionReturn(PETSC_SUCCESS);
51065552b385SBrandon
51075552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &cdim));
51085552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm));
51095552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
51105552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
51115552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
51125552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
51135552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
51145552b385SBrandon
51152a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(t_pointObj, &t_point));
51162a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(u_pointObj, &u_point));
51172a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(v_pointObj, &v_point));
51185552b385SBrandon
51192a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(modelObj, &model));
51205552b385SBrandon
51215552b385SBrandon if (islite) {
51225552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
51235552b385SBrandon } else {
51245552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
51255552b385SBrandon }
51265552b385SBrandon
51275552b385SBrandon PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
51285552b385SBrandon PetscCall(VecGetArrayWrite(coordinates, &coords));
51295552b385SBrandon
51305552b385SBrandon for (v = vStart; v < vEnd; ++v) {
51315552b385SBrandon PetscScalar *vcoords;
51325552b385SBrandon
51335552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID));
51345552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, v, &faceID));
51355552b385SBrandon PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID));
51365552b385SBrandon PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID));
51375552b385SBrandon
51385552b385SBrandon // TODO Figure out why this is unknown sometimes
51395552b385SBrandon if (bodyID < 0 && Nb == 1) bodyID = 0;
51405552b385SBrandon PetscCheck(bodyID >= 0 && bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " for vertex %" PetscInt_FMT " is not in [0, %d)", bodyID, v, Nb);
51415552b385SBrandon body = bodies[bodyID];
51425552b385SBrandon
51435552b385SBrandon PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords));
51445552b385SBrandon if (vertexID > 0) {
51455552b385SBrandon /* Snap to Vertices */
51465552b385SBrandon if (islite) {
51475552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex));
51485552b385SBrandon PetscCall(EGlite_evaluate(vertex, NULL, result));
51495552b385SBrandon } else {
51505552b385SBrandon PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex));
51515552b385SBrandon PetscCall(EG_evaluate(vertex, NULL, result));
51525552b385SBrandon }
51535552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d];
51545552b385SBrandon } else if (edgeID > 0) {
51555552b385SBrandon /* Snap to EDGE */
51565552b385SBrandon params[0] = t_point[v - vStart];
51575552b385SBrandon if (islite) {
51585552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge));
51595552b385SBrandon PetscCall(EGlite_evaluate(edge, params, result));
51605552b385SBrandon } else {
51615552b385SBrandon PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge));
51625552b385SBrandon PetscCall(EG_evaluate(edge, params, result));
51635552b385SBrandon }
51645552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d];
51655552b385SBrandon } else if (faceID > 0) {
51665552b385SBrandon /* Snap to FACE */
51675552b385SBrandon params[0] = u_point[v - vStart];
51685552b385SBrandon params[1] = v_point[v - vStart];
51695552b385SBrandon if (islite) {
51705552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face));
51715552b385SBrandon PetscCall(EGlite_evaluate(face, params, result));
51725552b385SBrandon } else {
51735552b385SBrandon PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face));
51745552b385SBrandon PetscCall(EG_evaluate(face, params, result));
51755552b385SBrandon }
5176c1cad2e7SMatthew G. Knepley for (d = 0; d < cdim; ++d) vcoords[d] = result[d];
5177c1cad2e7SMatthew G. Knepley }
5178c1cad2e7SMatthew G. Knepley }
51799566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords));
5180c1cad2e7SMatthew G. Knepley /* Clear out global coordinates */
51816858538eSMatthew G. Knepley PetscCall(VecDestroy(&dm->coordinates[0].x));
5182c1cad2e7SMatthew G. Knepley #endif
51833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5184c1cad2e7SMatthew G. Knepley }
5185c1cad2e7SMatthew G. Knepley
5186cc4c1da9SBarry Smith /*@
51875552b385SBrandon DMPlexInflateToGeomModel - Wrapper function allowing two methods for inflating refined meshes to the underlying geometric domain.
51887bee2925SMatthew Knepley
51897bee2925SMatthew Knepley Collective
51907bee2925SMatthew Knepley
51917bee2925SMatthew Knepley Input Parameters:
51925552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
51935552b385SBrandon - useTUV - PetscBool indicating if the user would like to inflate the DMPlex to the underlying geometry
51945552b385SBrandon using (t) for nodes on EDGEs and (u, v) for nodes on FACEs or using the nodes (x, y, z) coordinates
51955552b385SBrandon and shortest distance routine.
51965552b385SBrandon If useTUV = PETSC_TRUE, use the (t) or (u, v) parameters to inflate the DMPlex to the CAD geometry.
51975552b385SBrandon If useTUV = PETSC_FALSE, use the nodes (x, y, z) coordinates and the shortest disctance routine.
51985552b385SBrandon
51995552b385SBrandon Notes:
52005552b385SBrandon DM with nodal coordinates modified so that they lie on the EDGEs and FACEs of the underlying geometry.
52015552b385SBrandon
52025552b385SBrandon (t) and (u, v) parameters for all DMPlex nodes on EDGEs and FACEs are stored in arrays within PetscContainers attached to the DM.
52035552b385SBrandon The containers have names "Point - Edge t Parameter", "Point - Face u Parameter", and "Point - Face v Parameter".
52045552b385SBrandon The arrays are organized by Point 0-based ID (i.e. [v-vstart] as defined in the DMPlex.
52055552b385SBrandon
52065552b385SBrandon Level: intermediate
52075552b385SBrandon
52085552b385SBrandon .seealso: `DMPlexGetGeomModelTUV()`, `DMPlexInflateToGeomModelUseTUV()`, `DMPlexInflateToGeomModelUseXYZ()`
52095552b385SBrandon @*/
DMPlexInflateToGeomModel(DM dm,PetscBool useTUV)5210ce78bad3SBarry Smith PetscErrorCode DMPlexInflateToGeomModel(DM dm, PetscBool useTUV) PeNS
52115552b385SBrandon {
52125552b385SBrandon PetscFunctionBeginHot;
52135552b385SBrandon if (useTUV) {
52145552b385SBrandon PetscCall(DMPlexGetGeomModelTUV(dm));
52155552b385SBrandon PetscCall(DMPlexInflateToGeomModelUseTUV(dm));
52165552b385SBrandon } else {
52175552b385SBrandon PetscCall(DMPlexInflateToGeomModelUseXYZ(dm));
52185552b385SBrandon }
52195552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
52205552b385SBrandon }
52215552b385SBrandon
52225552b385SBrandon #ifdef PETSC_HAVE_EGADS
52235552b385SBrandon /*@C
5224bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodies - Returns an array of `PetscGeom` BODY objects attached to the referenced geometric model entity as well as the number of BODYs.
52255552b385SBrandon
52265552b385SBrandon Collective
52275552b385SBrandon
52285552b385SBrandon Input Parameter:
52295552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
52305552b385SBrandon
52315552b385SBrandon Output Parameters:
52325552b385SBrandon + bodies - Array of PetscGeom BODY objects referenced by the geometric model.
52335552b385SBrandon - numBodies - Number of BODYs referenced by the geometric model. Also the size of **bodies array.
52345552b385SBrandon
52355552b385SBrandon Level: intermediate
52365552b385SBrandon
52375552b385SBrandon .seealso:
52385552b385SBrandon @*/
DMPlexGetGeomModelBodies(DM dm,PetscGeom ** bodies,PetscInt * numBodies)5239ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodies(DM dm, PetscGeom **bodies, PetscInt *numBodies) PeNS
52405552b385SBrandon {
52415552b385SBrandon PetscFunctionBeginHot;
52425552b385SBrandon PetscContainer modelObj;
52435552b385SBrandon PetscBool islite = PETSC_FALSE;
52445552b385SBrandon ego model, geom;
52455552b385SBrandon int oclass, mtype;
52465552b385SBrandon int *senses;
52475552b385SBrandon
52485552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
52495552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
52505552b385SBrandon if (!modelObj) {
52515552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
52525552b385SBrandon islite = PETSC_TRUE;
52535552b385SBrandon }
52545552b385SBrandon
52555552b385SBrandon // Get attached EGADS or EGADSlite model (pointer)
52562a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(modelObj, &model));
52575552b385SBrandon
52585552b385SBrandon if (islite) {
52595552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses));
52605552b385SBrandon } else {
52615552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses));
52625552b385SBrandon }
52635552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
52645552b385SBrandon }
52655552b385SBrandon
52665552b385SBrandon /*@C
5267bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyShells - Returns an array of `PetscGeom` SHELL objects attached to the referenced BODY geometric entity as well as the number of SHELLs.
52685552b385SBrandon
52695552b385SBrandon Collective
52705552b385SBrandon
52715552b385SBrandon Input Parameters:
52725552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
52735552b385SBrandon - body - PetscGeom BODY object containing the SHELL objects of interest.
52745552b385SBrandon
52755552b385SBrandon Output Parameters:
52765552b385SBrandon + shells - Array of PetscGeom SHELL objects referenced by the PetscGeom BODY object
52775552b385SBrandon - numShells - Number of SHELLs referenced by the PetscGeom BODY object. Also the size of **shells array.
52785552b385SBrandon
52795552b385SBrandon Level: intermediate
52805552b385SBrandon
52815552b385SBrandon .seealso:
52825552b385SBrandon @*/
DMPlexGetGeomModelBodyShells(DM dm,PetscGeom body,PetscGeom ** shells,PetscInt * numShells)5283ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyShells(DM dm, PetscGeom body, PetscGeom **shells, PetscInt *numShells) PeNS
52845552b385SBrandon {
52855552b385SBrandon PetscFunctionBeginHot;
52865552b385SBrandon #ifdef PETSC_HAVE_EGADS
52875552b385SBrandon PetscContainer modelObj;
52885552b385SBrandon PetscBool islite = PETSC_FALSE;
52895552b385SBrandon
52905552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
52915552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
52925552b385SBrandon if (!modelObj) {
52935552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
52945552b385SBrandon islite = PETSC_TRUE;
52955552b385SBrandon }
52965552b385SBrandon
52975552b385SBrandon if (islite) {
52985552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, numShells, shells));
52995552b385SBrandon } else {
53005552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, SHELL, numShells, shells));
53015552b385SBrandon }
53025552b385SBrandon #endif
53035552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
53045552b385SBrandon }
53055552b385SBrandon
53065552b385SBrandon /*@C
5307bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyFaces - Returns an array of `PetscGeom` FACE objects attached to the referenced BODY geometric entity as well as the number of FACEs.
53085552b385SBrandon
53095552b385SBrandon Collective
53105552b385SBrandon
53115552b385SBrandon Input Parameters:
53125552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
53135552b385SBrandon - body - PetscGeom BODY object containing the FACE objects of interest.
53145552b385SBrandon
53155552b385SBrandon Output Parameters:
53165552b385SBrandon + faces - Array of PetscGeom FACE objects referenced by the PetscGeom BODY object
53175552b385SBrandon - numFaces - Number of FACEs referenced by the PetscGeom BODY object. Also the size of **faces array.
53185552b385SBrandon
53195552b385SBrandon Level: intermediate
53205552b385SBrandon
53215552b385SBrandon .seealso:
53225552b385SBrandon @*/
DMPlexGetGeomModelBodyFaces(DM dm,PetscGeom body,PetscGeom ** faces,PetscInt * numFaces)5323ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyFaces(DM dm, PetscGeom body, PetscGeom **faces, PetscInt *numFaces) PeNS
53245552b385SBrandon {
53255552b385SBrandon PetscFunctionBeginHot;
53265552b385SBrandon #ifdef PETSC_HAVE_EGADS
53275552b385SBrandon PetscContainer modelObj;
53285552b385SBrandon PetscBool islite = PETSC_FALSE;
53295552b385SBrandon
53305552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
53315552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
53325552b385SBrandon if (!modelObj) {
53335552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
53345552b385SBrandon islite = PETSC_TRUE;
53355552b385SBrandon }
53365552b385SBrandon
53375552b385SBrandon if (islite) {
53385552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, numFaces, faces));
53395552b385SBrandon } else {
53405552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, numFaces, faces));
53415552b385SBrandon }
53425552b385SBrandon #endif
53435552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
53445552b385SBrandon }
53455552b385SBrandon
53465552b385SBrandon /*@C
5347bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyLoops - Returns an array of `PetscGeom` Loop objects attached to the referenced BODY geometric entity as well as the number of LOOPs.
53485552b385SBrandon
53495552b385SBrandon Collective
53505552b385SBrandon
53515552b385SBrandon Input Parameters:
53525552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
53535552b385SBrandon - body - PetscGeom BODY object containing the LOOP objects of interest.
53545552b385SBrandon
53555552b385SBrandon Output Parameters:
53565552b385SBrandon + loops - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object
53575552b385SBrandon - numLoops - Number of LOOPs referenced by the PetscGeom BODY object. Also the size of **loops array.
53585552b385SBrandon
53595552b385SBrandon Level: intermediate
53605552b385SBrandon
53615552b385SBrandon .seealso:
53625552b385SBrandon @*/
DMPlexGetGeomModelBodyLoops(DM dm,PetscGeom body,PetscGeom ** loops,PetscInt * numLoops)5363ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyLoops(DM dm, PetscGeom body, PetscGeom **loops, PetscInt *numLoops) PeNS
53645552b385SBrandon {
53655552b385SBrandon PetscFunctionBeginHot;
53665552b385SBrandon #ifdef PETSC_HAVE_EGADS
53675552b385SBrandon PetscContainer modelObj;
53685552b385SBrandon PetscBool islite = PETSC_FALSE;
53695552b385SBrandon
53705552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
53715552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
53725552b385SBrandon if (!modelObj) {
53735552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
53745552b385SBrandon islite = PETSC_TRUE;
53755552b385SBrandon }
53765552b385SBrandon
53775552b385SBrandon if (islite) {
53785552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, numLoops, loops));
53795552b385SBrandon } else {
53805552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, LOOP, numLoops, loops));
53815552b385SBrandon }
53825552b385SBrandon #endif
53835552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
53845552b385SBrandon }
53855552b385SBrandon
53865552b385SBrandon /*@C
5387bfe80ac4SPierre Jolivet DMPlexGetGeomModelShellFaces - Returns an array of `PetscGeom` FACE objects attached to the referenced SHELL geometric entity as well as the number of FACEs.
53885552b385SBrandon
53895552b385SBrandon Collective
53905552b385SBrandon
53915552b385SBrandon Input Parameters:
53925552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
53935552b385SBrandon . body - PetscGeom BODY object containing the FACE objects of interest.
53945552b385SBrandon - shell - PetscGeom SHELL object with FACEs of interest.
53955552b385SBrandon
53965552b385SBrandon Output Parameters:
53975552b385SBrandon + faces - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object
53985552b385SBrandon - numFaces - Number of FACEs referenced by the PetscGeom SHELL object. Also the size of **faces array.
53995552b385SBrandon
54005552b385SBrandon Level: intermediate
54015552b385SBrandon
54025552b385SBrandon .seealso:
54035552b385SBrandon @*/
DMPlexGetGeomModelShellFaces(DM dm,PetscGeom body,PetscGeom shell,PetscGeom ** faces,PetscInt * numFaces)5404ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelShellFaces(DM dm, PetscGeom body, PetscGeom shell, PetscGeom **faces, PetscInt *numFaces) PeNS
54055552b385SBrandon {
54065552b385SBrandon PetscFunctionBeginHot;
54075552b385SBrandon #ifdef PETSC_HAVE_EGADS
54085552b385SBrandon PetscContainer modelObj;
54095552b385SBrandon PetscBool islite = PETSC_FALSE;
54105552b385SBrandon
54115552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
54125552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
54135552b385SBrandon if (!modelObj) {
54145552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
54155552b385SBrandon islite = PETSC_TRUE;
54165552b385SBrandon }
54175552b385SBrandon
54185552b385SBrandon if (islite) {
54195552b385SBrandon PetscCall(EGlite_getBodyTopos(body, shell, FACE, numFaces, faces));
54205552b385SBrandon } else {
54215552b385SBrandon PetscCall(EG_getBodyTopos(body, shell, FACE, numFaces, faces));
54225552b385SBrandon }
54235552b385SBrandon #endif
54245552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
54255552b385SBrandon }
54265552b385SBrandon
54275552b385SBrandon /*@C
5428bfe80ac4SPierre Jolivet DMPlexGetGeomModelFaceLoops - Returns an array of `PetscGeom` LOOP objects attached to the referenced FACE geometric entity as well as the number of LOOPs.
54295552b385SBrandon
54305552b385SBrandon Collective
54315552b385SBrandon
54325552b385SBrandon Input Parameters:
54335552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
54345552b385SBrandon . body - PetscGeom BODY object containing the LOOP objects of interest.
54355552b385SBrandon - face - PetscGeom FACE object with LOOPs of interest.
54365552b385SBrandon
54375552b385SBrandon Output Parameters:
54385552b385SBrandon + loops - Array of PetscGeom LOOP objects referenced by the PetscGeom FACE object
54395552b385SBrandon - numLoops - Number of LOOPs referenced by the PetscGeom FACE object. Also the size of **loops array.
54405552b385SBrandon
54415552b385SBrandon Level: intermediate
54425552b385SBrandon
54435552b385SBrandon .seealso:
54445552b385SBrandon @*/
DMPlexGetGeomModelFaceLoops(DM dm,PetscGeom body,PetscGeom face,PetscGeom ** loops,PetscInt * numLoops)5445ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelFaceLoops(DM dm, PetscGeom body, PetscGeom face, PetscGeom **loops, PetscInt *numLoops) PeNS
54465552b385SBrandon {
54475552b385SBrandon PetscFunctionBeginHot;
54485552b385SBrandon #ifdef PETSC_HAVE_EGADS
54495552b385SBrandon PetscContainer modelObj;
54505552b385SBrandon PetscBool islite = PETSC_FALSE;
54515552b385SBrandon
54525552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
54535552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
54545552b385SBrandon if (!modelObj) {
54555552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
54565552b385SBrandon islite = PETSC_TRUE;
54575552b385SBrandon }
54585552b385SBrandon
54595552b385SBrandon if (islite) {
54605552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, LOOP, numLoops, loops));
54615552b385SBrandon } else {
54625552b385SBrandon PetscCall(EG_getBodyTopos(body, face, LOOP, numLoops, loops));
54635552b385SBrandon }
54645552b385SBrandon #endif
54655552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
54665552b385SBrandon }
54675552b385SBrandon
54685552b385SBrandon /*@C
5469bfe80ac4SPierre Jolivet DMPlexGetGeomModelFaceEdges - Returns an array of `PetscGeom` EDGE objects attached to the referenced FACE geometric entity as well as the number of EDGEs.
54705552b385SBrandon
54715552b385SBrandon Collective
54725552b385SBrandon
54735552b385SBrandon Input Parameters:
54745552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
54755552b385SBrandon . body - PetscGeom Body object containing the EDGE objects of interest.
54765552b385SBrandon - face - PetscGeom FACE object with EDGEs of interest.
54775552b385SBrandon
54785552b385SBrandon Output Parameters:
54795552b385SBrandon + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom FACE object
54805552b385SBrandon - numEdges - Number of EDGEs referenced by the PetscGeom FACE object. Also the size of **edges array.
54815552b385SBrandon
54825552b385SBrandon Level: intermediate
54835552b385SBrandon
54845552b385SBrandon .seealso:
54855552b385SBrandon @*/
DMPlexGetGeomModelFaceEdges(DM dm,PetscGeom body,PetscGeom face,PetscGeom ** edges,PetscInt * numEdges)5486ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelFaceEdges(DM dm, PetscGeom body, PetscGeom face, PetscGeom **edges, PetscInt *numEdges) PeNS
54875552b385SBrandon {
54885552b385SBrandon PetscFunctionBeginHot;
54895552b385SBrandon #ifdef PETSC_HAVE_EGADS
54905552b385SBrandon PetscContainer modelObj;
54915552b385SBrandon PetscBool islite = PETSC_FALSE;
54925552b385SBrandon
54935552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
54945552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
54955552b385SBrandon if (!modelObj) {
54965552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
54975552b385SBrandon islite = PETSC_TRUE;
54985552b385SBrandon }
54995552b385SBrandon
55005552b385SBrandon if (islite) {
55015552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, numEdges, edges));
55025552b385SBrandon } else {
55035552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, numEdges, edges));
55045552b385SBrandon }
55055552b385SBrandon #endif
55065552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
55075552b385SBrandon }
55085552b385SBrandon
55095552b385SBrandon /*@C
5510bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyEdges - Returns an array of `PetscGeom` EDGE objects attached to the referenced BODY geometric entity as well as the number of EDGEs.
55115552b385SBrandon
55125552b385SBrandon Collective
55135552b385SBrandon
55145552b385SBrandon Input Parameters:
55155552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
55165552b385SBrandon - body - PetscGeom body object of interest.
55175552b385SBrandon
55185552b385SBrandon Output Parameters:
55195552b385SBrandon + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom BODY object
55205552b385SBrandon - numEdges - Number of EDGEs referenced by the PetscGeom BODY object. Also the size of **edges array.
55215552b385SBrandon
55225552b385SBrandon Level: intermediate
55235552b385SBrandon
55245552b385SBrandon .seealso:
55255552b385SBrandon @*/
DMPlexGetGeomModelBodyEdges(DM dm,PetscGeom body,PetscGeom ** edges,PetscInt * numEdges)5526ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyEdges(DM dm, PetscGeom body, PetscGeom **edges, PetscInt *numEdges) PeNS
55275552b385SBrandon {
55285552b385SBrandon PetscFunctionBeginHot;
55295552b385SBrandon #ifdef PETSC_HAVE_EGADS
55305552b385SBrandon PetscContainer modelObj;
55315552b385SBrandon PetscBool islite = PETSC_FALSE;
55325552b385SBrandon
55335552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
55345552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
55355552b385SBrandon if (!modelObj) {
55365552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
55375552b385SBrandon islite = PETSC_TRUE;
55385552b385SBrandon }
55395552b385SBrandon
55405552b385SBrandon if (islite) {
55415552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, numEdges, edges));
55425552b385SBrandon } else {
55435552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, EDGE, numEdges, edges));
55445552b385SBrandon }
55455552b385SBrandon #endif
55465552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
55475552b385SBrandon }
55485552b385SBrandon
55495552b385SBrandon /*@C
5550bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyNodes - Returns an array of `PetscGeom` NODE objects attached to the referenced BODY geometric entity as well as the number of NODES.
55515552b385SBrandon
55525552b385SBrandon Collective
55535552b385SBrandon
55545552b385SBrandon Input Parameters:
55555552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
55565552b385SBrandon - body - PetscGeom body object of interest.
55575552b385SBrandon
55585552b385SBrandon Output Parameters:
55595552b385SBrandon + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom BODY object
55605552b385SBrandon - numNodes - Number of NODEs referenced by the PetscGeom BODY object. Also the size of **nodes array.
55615552b385SBrandon
55625552b385SBrandon Level: intermediate
55635552b385SBrandon
55645552b385SBrandon .seealso:
55655552b385SBrandon @*/
DMPlexGetGeomModelBodyNodes(DM dm,PetscGeom body,PetscGeom ** nodes,PetscInt * numNodes)5566ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyNodes(DM dm, PetscGeom body, PetscGeom **nodes, PetscInt *numNodes) PeNS
55675552b385SBrandon {
55685552b385SBrandon PetscFunctionBeginHot;
55695552b385SBrandon #ifdef PETSC_HAVE_EGADS
55705552b385SBrandon PetscContainer modelObj;
55715552b385SBrandon PetscBool islite = PETSC_FALSE;
55725552b385SBrandon
55735552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
55745552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
55755552b385SBrandon if (!modelObj) {
55765552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
55775552b385SBrandon islite = PETSC_TRUE;
55785552b385SBrandon }
55795552b385SBrandon
55805552b385SBrandon if (islite) {
55815552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, numNodes, nodes));
55825552b385SBrandon } else {
55835552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, NODE, numNodes, nodes));
55845552b385SBrandon }
55855552b385SBrandon #endif
55865552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
55875552b385SBrandon }
55885552b385SBrandon
55895552b385SBrandon /*@C
5590bfe80ac4SPierre Jolivet DMPlexGetGeomModelEdgeNodes - Returns an array of `PetscGeom` NODE objects attached to the referenced EDGE geometric entity as well as the number of NODES.
55915552b385SBrandon
55925552b385SBrandon Collective
55935552b385SBrandon
55945552b385SBrandon Input Parameters:
55955552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
55965552b385SBrandon . body - PetscGeom body object containing the EDGE object of interest.
55975552b385SBrandon - edge - PetscGeom EDGE object with NODEs of interest.
55985552b385SBrandon
55995552b385SBrandon Output Parameters:
56005552b385SBrandon + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom EDGE object
56015552b385SBrandon - numNodes - Number of Nodes referenced by the PetscGeom EDGE object. Also the size of **nodes array.
56025552b385SBrandon
56035552b385SBrandon Level: intermediate
56045552b385SBrandon
56055552b385SBrandon .seealso:
56065552b385SBrandon @*/
DMPlexGetGeomModelEdgeNodes(DM dm,PetscGeom body,PetscGeom edge,PetscGeom ** nodes,PetscInt * numNodes)5607ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelEdgeNodes(DM dm, PetscGeom body, PetscGeom edge, PetscGeom **nodes, PetscInt *numNodes) PeNS
56085552b385SBrandon {
56095552b385SBrandon PetscFunctionBeginHot;
56105552b385SBrandon #ifdef PETSC_HAVE_EGADS
56115552b385SBrandon PetscContainer modelObj;
56125552b385SBrandon PetscBool islite = PETSC_FALSE;
56135552b385SBrandon
56145552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
56155552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
56165552b385SBrandon if (!modelObj) {
56175552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
56185552b385SBrandon islite = PETSC_TRUE;
56195552b385SBrandon }
56205552b385SBrandon
56215552b385SBrandon if (islite) {
56225552b385SBrandon PetscCall(EGlite_getBodyTopos(body, edge, NODE, numNodes, nodes));
56235552b385SBrandon } else {
56245552b385SBrandon PetscCall(EG_getBodyTopos(body, edge, NODE, numNodes, nodes));
56255552b385SBrandon }
56265552b385SBrandon #endif
56275552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
56285552b385SBrandon }
56295552b385SBrandon
56305552b385SBrandon /*@C
56315552b385SBrandon DMPlexGetGeomID - Returns ID number of the entity in the geometric (CAD) model
56325552b385SBrandon
56335552b385SBrandon Collective
56345552b385SBrandon
56355552b385SBrandon Input Parameters:
56365552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
56375552b385SBrandon . body - PetscGeom body object containing the lower level entity the ID number is being requested.
56385552b385SBrandon - topoObj - PetscGeom SHELL, FACE, LOOP, EDGE, or NODE object for which ID number is being requested.
56397bee2925SMatthew Knepley
56407bee2925SMatthew Knepley Output Parameter:
56415552b385SBrandon . id - ID number of the entity
56427bee2925SMatthew Knepley
56435552b385SBrandon Level: intermediate
56447bee2925SMatthew Knepley
56455552b385SBrandon .seealso:
56467bee2925SMatthew Knepley @*/
DMPlexGetGeomID(DM dm,PetscGeom body,PetscGeom topoObj,PetscInt * id)5647ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomID(DM dm, PetscGeom body, PetscGeom topoObj, PetscInt *id) PeNS
5648d71ae5a4SJacob Faibussowitsch {
56495552b385SBrandon PetscFunctionBeginHot;
56505552b385SBrandon #ifdef PETSC_HAVE_EGADS
56515552b385SBrandon PetscContainer modelObj;
56525552b385SBrandon PetscBool islite = PETSC_FALSE;
56535552b385SBrandon int topoID;
56545552b385SBrandon
56555552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
56565552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
56575552b385SBrandon if (!modelObj) {
56585552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
56595552b385SBrandon islite = PETSC_TRUE;
56605552b385SBrandon }
56615552b385SBrandon
56625552b385SBrandon // Get Topology Object's ID
56635552b385SBrandon if (islite) {
56645552b385SBrandon topoID = EGlite_indexBodyTopo(body, topoObj);
56655552b385SBrandon } else {
56665552b385SBrandon topoID = EG_indexBodyTopo(body, topoObj);
56675552b385SBrandon }
56685552b385SBrandon
56695552b385SBrandon *id = topoID;
56707bee2925SMatthew Knepley #endif
56715552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
56725552b385SBrandon }
56735552b385SBrandon
56745552b385SBrandon /*@C
56755552b385SBrandon DMPlexGetGeomObject - Returns Geometry Object using the objects ID in the geometric (CAD) model
56765552b385SBrandon
56775552b385SBrandon Collective
56785552b385SBrandon
56795552b385SBrandon Input Parameters:
56805552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
56815552b385SBrandon . body - PetscGeom body object containing the lower level entity the referenced by the ID.
56825552b385SBrandon . geomType - Keyword SHELL, FACE, LOOP, EDGE, or NODE of the geometry type for which ID number is being requested.
56835552b385SBrandon - geomID - ID number of the geometry entity being requested.
56845552b385SBrandon
56855552b385SBrandon Output Parameter:
56865552b385SBrandon . geomObj - Geometry Object referenced by the ID number requested.
56875552b385SBrandon
56885552b385SBrandon Level: intermediate
56895552b385SBrandon
56905552b385SBrandon .seealso:
56915552b385SBrandon @*/
DMPlexGetGeomObject(DM dm,PetscGeom body,PetscInt geomType,PetscInt geomID,PetscGeom * geomObj)5692ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomObject(DM dm, PetscGeom body, PetscInt geomType, PetscInt geomID, PetscGeom *geomObj) PeNS
56935552b385SBrandon {
56945552b385SBrandon PetscFunctionBeginHot;
56955552b385SBrandon #ifdef PETSC_HAVE_EGADS
56965552b385SBrandon PetscContainer modelObj;
56975552b385SBrandon PetscBool islite = PETSC_FALSE;
56985552b385SBrandon
56995552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
57005552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
57015552b385SBrandon if (!modelObj) {
57025552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
57035552b385SBrandon islite = PETSC_TRUE;
57045552b385SBrandon }
57055552b385SBrandon
57065552b385SBrandon // Get Topology Object's ID
57075552b385SBrandon if (islite) {
57085552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, geomType, geomID, geomObj));
57095552b385SBrandon } else {
57105552b385SBrandon PetscCall(EG_objectBodyTopo(body, geomType, geomID, geomObj));
57115552b385SBrandon }
57125552b385SBrandon #endif
57135552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
57145552b385SBrandon }
57155552b385SBrandon
57165552b385SBrandon /*@C
57175552b385SBrandon DMPlexGetGeomFaceNumOfControlPoints - Returns the total number of Control Points (and associated Weights) defining a FACE of a Geometry
57185552b385SBrandon
57195552b385SBrandon Not collective
57205552b385SBrandon
57215552b385SBrandon Input Parameters:
57225552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
57235552b385SBrandon - face - PetscGeom FACE object
57245552b385SBrandon
57255552b385SBrandon Output Parameter:
57265552b385SBrandon . numCntrlPnts - Number of Control Points (and Weights) defining the FACE
57275552b385SBrandon
57285552b385SBrandon Level: intermediate
57295552b385SBrandon
57305552b385SBrandon .seealso:
57315552b385SBrandon @*/
DMPlexGetGeomFaceNumOfControlPoints(DM dm,PetscGeom face,PetscInt * numCntrlPnts)5732ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomFaceNumOfControlPoints(DM dm, PetscGeom face, PetscInt *numCntrlPnts) PeNS
57335552b385SBrandon {
57345552b385SBrandon PetscFunctionBeginHot;
57355552b385SBrandon #ifdef PETSC_HAVE_EGADS
57365552b385SBrandon PetscContainer modelObj;
57375552b385SBrandon PetscBool islite = PETSC_FALSE;
57385552b385SBrandon PetscGeom geom, gRef;
57395552b385SBrandon PetscGeom *lobjs;
57405552b385SBrandon int Nl, oclass, mtype, goclass, gmtype;
57415552b385SBrandon int *lsenses, *gpinfo;
57425552b385SBrandon double *gprv;
57435552b385SBrandon
57445552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
57455552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
57465552b385SBrandon if (!modelObj) {
57475552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
57485552b385SBrandon islite = PETSC_TRUE;
57495552b385SBrandon }
57505552b385SBrandon
57515552b385SBrandon // Get Total Number of Control Points on FACE
57525552b385SBrandon if (islite) {
57535552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses));
57545552b385SBrandon PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv));
57555552b385SBrandon } else {
57565552b385SBrandon PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses));
57575552b385SBrandon PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv));
57585552b385SBrandon }
57595552b385SBrandon
57605552b385SBrandon *numCntrlPnts = gpinfo[2] * gpinfo[5];
57615552b385SBrandon #endif
57625552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
57635552b385SBrandon }
57645552b385SBrandon
57655552b385SBrandon /*@C
57665552b385SBrandon DMPlexGetGeomBodyMassProperties - Returns the Volume, Surface Area, Center of Gravity, and Inertia about the Body's Center of Gravity
57675552b385SBrandon
57685552b385SBrandon Not collective
57695552b385SBrandon
57705552b385SBrandon Input Parameters:
57715552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
57725552b385SBrandon - body - PetscGeom BODY object
57735552b385SBrandon
57745552b385SBrandon Output Parameters:
57755552b385SBrandon + volume - Volume of the CAD Body attached to the DM Plex
57765552b385SBrandon . surfArea - Surface Area of the CAD Body attached to the DM Plex
57775552b385SBrandon . centerOfGravity - Array with the Center of Gravity coordinates of the CAD Body attached to the DM Plex [x, y, z]
57785552b385SBrandon . COGszie - Size of centerOfGravity[] Array
57795552b385SBrandon . inertiaMatrixCOG - Array containing the Inertia about the Body's Center of Gravity [Ixx, Ixy, Ixz, Iyx, Iyy, Iyz, Izx, Izy, Izz]
57805552b385SBrandon - IMCOGsize - Size of inertiaMatrixCOG[] Array
57815552b385SBrandon
57825552b385SBrandon Level: intermediate
57835552b385SBrandon
57845552b385SBrandon .seealso:
57855552b385SBrandon @*/
DMPlexGetGeomBodyMassProperties(DM dm,PetscGeom body,PetscScalar * volume,PetscScalar * surfArea,PetscScalar ** centerOfGravity,PetscInt * COGsize,PetscScalar ** inertiaMatrixCOG,PetscInt * IMCOGsize)5786ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) PeNS
57875552b385SBrandon {
57885552b385SBrandon PetscFunctionBeginHot;
57895552b385SBrandon #ifdef PETSC_HAVE_EGADS
57905552b385SBrandon PetscContainer modelObj;
57915552b385SBrandon PetscBool islite = PETSC_FALSE;
57925552b385SBrandon PetscScalar geomData[14];
57935552b385SBrandon
57945552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
57955552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
57965552b385SBrandon if (!modelObj) {
57975552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
57985552b385SBrandon islite = PETSC_TRUE;
57995552b385SBrandon PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot provide geometric mass properties for geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep");
58005552b385SBrandon }
58015552b385SBrandon
58025552b385SBrandon if (islite) {
58035552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " WARNING!! This functionality is not supported for EGADSlite files. \n"));
58045552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " All returned values are equal to 0 \n"));
58055552b385SBrandon } else {
58065552b385SBrandon PetscCall(EG_getMassProperties(body, geomData));
58075552b385SBrandon }
58085552b385SBrandon
58095552b385SBrandon PetscCall(PetscMalloc2(3, centerOfGravity, 9, inertiaMatrixCOG));
58105552b385SBrandon
58115552b385SBrandon if (!islite) {
58125552b385SBrandon *volume = geomData[0];
58135552b385SBrandon *surfArea = geomData[1];
5814ac530a7eSPierre Jolivet for (int ii = 2; ii < 5; ++ii) (*centerOfGravity)[ii - 2] = geomData[ii];
58155552b385SBrandon *COGsize = 3;
5816ac530a7eSPierre Jolivet for (int ii = 5; ii < 14; ++ii) (*inertiaMatrixCOG)[ii - 5] = geomData[ii];
58175552b385SBrandon *IMCOGsize = 9;
58185552b385SBrandon } else {
58195552b385SBrandon *volume = 0.;
58205552b385SBrandon *surfArea = 0.;
5821ac530a7eSPierre Jolivet for (int ii = 2; ii < 5; ++ii) (*centerOfGravity)[ii - 2] = 0.;
58225552b385SBrandon *COGsize = 0;
5823ac530a7eSPierre Jolivet for (int ii = 5; ii < 14; ++ii) (*inertiaMatrixCOG)[ii - 5] = 0.;
58245552b385SBrandon *IMCOGsize = 0;
58255552b385SBrandon }
58265552b385SBrandon #endif
58275552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
58285552b385SBrandon }
58295552b385SBrandon
DMPlexRestoreGeomBodyMassProperties(DM dm,PetscGeom body,PetscScalar * volume,PetscScalar * surfArea,PetscScalar ** centerOfGravity,PetscInt * COGsize,PetscScalar ** inertiaMatrixCOG,PetscInt * IMCOGsize)5830ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) PeNS
58315552b385SBrandon {
58325552b385SBrandon PetscFunctionBegin;
58335552b385SBrandon PetscCall(PetscFree2(*centerOfGravity, *inertiaMatrixCOG));
58345552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
58355552b385SBrandon }
58365552b385SBrandon
58375552b385SBrandon /*@C
58385552b385SBrandon DMPlexFreeGeomObject - Frees PetscGeom Objects
58395552b385SBrandon
58405552b385SBrandon Not collective
58415552b385SBrandon
58425552b385SBrandon Input Parameters:
58435552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
58445552b385SBrandon - geomObj - PetscGeom object
58455552b385SBrandon
58465552b385SBrandon Level: intermediate
58475552b385SBrandon
58485552b385SBrandon .seealso:
58495552b385SBrandon @*/
DMPlexFreeGeomObject(DM dm,PetscGeom * geomObj)5850ce78bad3SBarry Smith PetscErrorCode DMPlexFreeGeomObject(DM dm, PetscGeom *geomObj) PeNS
58515552b385SBrandon {
58525552b385SBrandon PetscFunctionBeginHot;
58535552b385SBrandon #ifdef PETSC_HAVE_EGADS
58545552b385SBrandon PetscContainer modelObj;
58555552b385SBrandon PetscBool islite = PETSC_FALSE;
58565552b385SBrandon
58575552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
58585552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
58595552b385SBrandon if (!modelObj) {
58605552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
58615552b385SBrandon islite = PETSC_TRUE;
58625552b385SBrandon }
58635552b385SBrandon
58645552b385SBrandon if (islite) {
58655552b385SBrandon EGlite_free(geomObj);
58665552b385SBrandon } else {
58675552b385SBrandon EG_free(geomObj);
58685552b385SBrandon }
58695552b385SBrandon #endif
58705552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
58715552b385SBrandon }
58725552b385SBrandon
58735552b385SBrandon /*@C
58745552b385SBrandon DMPlexGetGeomCntrlPntAndWeightData - Gets Control Point and Associated Weight Data for the Geometry attached to the DMPlex
58755552b385SBrandon
58765552b385SBrandon Not collective
58775552b385SBrandon
58785552b385SBrandon Input Parameter:
58795552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
58805552b385SBrandon
58815552b385SBrandon Output Parameters:
58825552b385SBrandon + cpHashTable - Hash Table containing the relationship between FACE ID and Control Point IDs.
58835552b385SBrandon . cpCoordDataLength - Length of cpCoordData Array.
58845552b385SBrandon . cpCoordData - Array holding the Geometry Control Point Coordinate Data.
58855552b385SBrandon . maxNumEquiv - Maximum Number of Equivalent Control Points (Control Points with the same coordinates but different IDs).
58865552b385SBrandon . cpEquiv - Matrix with a size(Number of Control Points, Number or Control Points) which stores a value of 1.0 in locations where Control Points with different IDS (row or column) have the same coordinates
58875552b385SBrandon . wHashTable - Hash Table containing the relationship between FACE ID and Control Point Weight.
58885552b385SBrandon . wDataLength - Length of wData Array.
58895552b385SBrandon - wData - Array holding the Weight for an associated Geometry Control Point.
58905552b385SBrandon
58915552b385SBrandon Note:
58925552b385SBrandon Must Call DMPLexGeomDataAndGrads() before calling this function.
58935552b385SBrandon
58945552b385SBrandon Level: intermediate
58955552b385SBrandon
58965552b385SBrandon .seealso:
58975552b385SBrandon @*/
DMPlexGetGeomCntrlPntAndWeightData(DM dm,PetscHMapI * cpHashTable,PetscInt * cpCoordDataLength,PetscScalar ** cpCoordData,PetscInt * maxNumEquiv,Mat * cpEquiv,PetscHMapI * wHashTable,PetscInt * wDataLength,PetscScalar ** wData)5898ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) PeNS
58995552b385SBrandon {
59005552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj, cpCoordDataLengthObj, wDataLengthObj, maxNumRelateObj;
59015552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec;
59025552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr, *maxNumEquivPtr;
59035552b385SBrandon PetscHMapI cpHashTableTemp, wHashTableTemp;
59045552b385SBrandon
59055552b385SBrandon PetscFunctionBeginHot;
59065552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
59075552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
59083a7d0413SPierre Jolivet if (!modelObj) PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
59095552b385SBrandon
5910ac530a7eSPierre Jolivet if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS);
59115552b385SBrandon
59125552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data
59135552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj));
59145552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec));
59155552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordDataLengthObj));
59165552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj));
59175552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec));
59185552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj));
5919bfe80ac4SPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Equivalency Matrix", (PetscObject *)cpEquiv));
59205552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj));
59215552b385SBrandon
59225552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer)
59232a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cpHashTableObj, &cpHashTableTemp));
59242a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cpCoordDataLengthObj, &cpCoordDataLengthPtr));
59252a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(wHashTableObj, &wHashTableTemp));
59262a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(wDataLengthObj, &wDataLengthPtr));
59272a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(maxNumRelateObj, &maxNumEquivPtr));
59285552b385SBrandon
59295552b385SBrandon *cpCoordDataLength = *cpCoordDataLengthPtr;
59305552b385SBrandon *wDataLength = *wDataLengthPtr;
59315552b385SBrandon *maxNumEquiv = *maxNumEquivPtr;
59325552b385SBrandon *cpHashTable = cpHashTableTemp;
59335552b385SBrandon *wHashTable = wHashTableTemp;
59345552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, cpCoordData));
59355552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, wData));
59365552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
59375552b385SBrandon }
59385552b385SBrandon
DMPlexRestoreGeomCntrlPntAndWeightData(DM dm,PetscHMapI * cpHashTable,PetscInt * cpCoordDataLength,PetscScalar ** cpCoordData,PetscInt * maxNumEquiv,Mat * cpEquiv,PetscHMapI * wHashTable,PetscInt * wDataLength,PetscScalar ** wData)59395552b385SBrandon PetscErrorCode DMPlexRestoreGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData)
59405552b385SBrandon {
59415552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec;
59425552b385SBrandon
59435552b385SBrandon PetscFunctionBeginHot;
59445552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec));
59455552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, cpCoordData));
59465552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec));
59475552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, wData));
59485552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
59495552b385SBrandon }
59505552b385SBrandon
59515552b385SBrandon /*@C
59525552b385SBrandon DMPlexGetGeomGradData - Gets Point, Surface and Volume Gradients with respect to changes in Control Points and their associated Weights for the Geometry attached to the DMPlex .
59535552b385SBrandon
59545552b385SBrandon Not collective
59555552b385SBrandon
59565552b385SBrandon Input Parameter:
59575552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
59585552b385SBrandon
59595552b385SBrandon Output Parameters:
59605552b385SBrandon + cpSurfGradHashTable - Hash Table Relating the Control Point ID to the the Row in the cpSurfGrad Matrix
59615552b385SBrandon . cpSurfGrad - Matrix containing the Surface Gradient with respect to the Control Point Data. Data is ranged where the Row corresponds to Control Point ID and the Columns are associated with the Geometric FACE.
59625552b385SBrandon . cpArraySize - The size of arrays gradSACP and gradVolCP and is equal to 3 * total number of Control Points in the Geometry
59635552b385SBrandon . gradSACP - Array containing the Surface Area Gradient with respect to Control Point Data. Data is arranged by Control Point ID * 3 where 3 is for the coordinate dimension.
5964bfe80ac4SPierre Jolivet . gradVolCP - Array containing the Volume Gradient with respect to Control Point Data. Data is arranged by Control Point ID * 3 where 3 is for the coordinate dimension.
59655552b385SBrandon . wArraySize - The size of arrayws gradSAW and gradVolW and is equal to the total number of Control Points in the Geometry.
59665552b385SBrandon . gradSAW - Array containing the Surface Area Gradient with respect to Control Point Weight. Data is arranged by Control Point ID.
59675552b385SBrandon - gradVolW - Array containing the Volume Gradient with respect to Control Point Weight. Data is arranged by Control Point ID.
59685552b385SBrandon
59695552b385SBrandon Notes:
59705552b385SBrandon Must Call DMPLexGeomDataAndGrads() before calling this function.
59715552b385SBrandon
59725552b385SBrandon gradVolCP and gradVolW are only available when DMPlexGeomDataAndGrads() is called with fullGeomGrad = PETSC_TRUE.
59735552b385SBrandon
59745552b385SBrandon Level: intermediate
59755552b385SBrandon
59765552b385SBrandon .seealso: DMPlexGeomDataAndGrads
59775552b385SBrandon @*/
DMPlexGetGeomGradData(DM dm,PetscHMapI * cpSurfGradHashTable,Mat * cpSurfGrad,PetscInt * cpArraySize,PetscScalar ** gradSACP,PetscScalar ** gradVolCP,PetscInt * wArraySize,PetscScalar ** gradSAW,PetscScalar ** gradVolW)59785552b385SBrandon PetscErrorCode DMPlexGetGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW)
59795552b385SBrandon {
59805552b385SBrandon PetscContainer modelObj, cpSurfGradHashTableObj, cpArraySizeObj, wArraySizeObj;
59815552b385SBrandon Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec;
59825552b385SBrandon PetscInt *cpArraySizePtr, *wArraySizePtr;
59835552b385SBrandon PetscHMapI cpSurfGradHashTableTemp;
59845552b385SBrandon
59855552b385SBrandon PetscFunctionBeginHot;
59865552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
59875552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
59883a7d0413SPierre Jolivet if (!modelObj) PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
59895552b385SBrandon
5990ac530a7eSPierre Jolivet if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS);
59915552b385SBrandon
59925552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data
59935552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&cpSurfGradHashTableObj));
59945552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Matrix", (PetscObject *)cpSurfGrad));
59955552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpArraySizeObj));
59965552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec));
59975552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec));
59985552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wArraySizeObj));
59995552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec));
60005552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec));
60015552b385SBrandon
60025552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer)
60035552b385SBrandon if (cpSurfGradHashTableObj) {
60042a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cpSurfGradHashTableObj, &cpSurfGradHashTableTemp));
60055552b385SBrandon *cpSurfGradHashTable = cpSurfGradHashTableTemp;
60065552b385SBrandon }
60075552b385SBrandon
60085552b385SBrandon if (cpArraySizeObj) {
60092a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cpArraySizeObj, &cpArraySizePtr));
60105552b385SBrandon *cpArraySize = *cpArraySizePtr;
60115552b385SBrandon }
60125552b385SBrandon
60135552b385SBrandon if (gradSACPVec) PetscCall(VecGetArrayWrite(gradSACPVec, gradSACP));
60145552b385SBrandon if (gradVolCPVec) PetscCall(VecGetArrayWrite(gradVolCPVec, gradVolCP));
60155552b385SBrandon if (gradSAWVec) PetscCall(VecGetArrayWrite(gradSAWVec, gradSAW));
60165552b385SBrandon if (gradVolWVec) PetscCall(VecGetArrayWrite(gradVolWVec, gradVolW));
60175552b385SBrandon
60185552b385SBrandon if (wArraySizeObj) {
60192a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(wArraySizeObj, &wArraySizePtr));
60205552b385SBrandon *wArraySize = *wArraySizePtr;
60215552b385SBrandon }
60225552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
60235552b385SBrandon }
60245552b385SBrandon
DMPlexRestoreGeomGradData(DM dm,PetscHMapI * cpSurfGradHashTable,Mat * cpSurfGrad,PetscInt * cpArraySize,PetscScalar ** gradSACP,PetscScalar ** gradVolCP,PetscInt * wArraySize,PetscScalar ** gradSAW,PetscScalar ** gradVolW)60255552b385SBrandon PetscErrorCode DMPlexRestoreGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW)
60265552b385SBrandon {
60275552b385SBrandon Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec;
60287bee2925SMatthew Knepley
60297bee2925SMatthew Knepley PetscFunctionBegin;
60305552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec));
60315552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec));
60325552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec));
60335552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec));
60345552b385SBrandon
60355552b385SBrandon if (gradSACPVec) PetscCall(VecRestoreArrayWrite(gradSACPVec, gradSACP));
60365552b385SBrandon if (gradVolCPVec) PetscCall(VecRestoreArrayWrite(gradVolCPVec, gradVolCP));
60375552b385SBrandon if (gradSAWVec) PetscCall(VecRestoreArrayWrite(gradSAWVec, gradSAW));
60385552b385SBrandon if (gradVolWVec) PetscCall(VecRestoreArrayWrite(gradVolWVec, gradVolW));
60393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
60407bee2925SMatthew Knepley }
60415552b385SBrandon
60425552b385SBrandon /*@C
60435552b385SBrandon DMPlexGetGeomCntrlPntMaps - Gets arrays which maps Control Point IDs to their associated Geometry FACE, EDGE, and VERTEX.
60445552b385SBrandon
60455552b385SBrandon Not collective
60465552b385SBrandon
60475552b385SBrandon Input Parameter:
60485552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object
60495552b385SBrandon
60505552b385SBrandon Output Parameters:
60515552b385SBrandon + numCntrlPnts - Number of Control Points defining the Geometry attached to the DMPlex
60525552b385SBrandon . cntrlPntFaceMap - Array containing the FACE ID for the Control Point. Array index corresponds to Control Point ID.
60535552b385SBrandon . cntrlPntWeightFaceMap - Array containing the FACE ID for the Control Point Weight. Array index corresponds to Control Point ID.
60545552b385SBrandon . cntrlPntEdgeMap - Array containing the EDGE ID for the Control Point. Array index corresponds to Control Point ID.
60555552b385SBrandon . cntrlPntWeightEdgeMap - Array containing the EDGE ID for the Control Point Weight. Array index corresponds to Control Point ID.
60565552b385SBrandon . cntrlPntVertexMap - Array containing the VERTEX ID for the Control Point. Array index corresponds to Control Point ID.
60575552b385SBrandon - cntrlPntWeightVertexMap - Array containing the VERTEX ID for the Control Point Weight. Array index corresponds to Control Point ID.
60585552b385SBrandon
60595552b385SBrandon Note:
60605552b385SBrandon Arrays are initialized to -1. Array elements with a -1 value indicates that the Control Point or Control Point Weight not associated with the referenced Geometric entity in the array name.
60615552b385SBrandon
60625552b385SBrandon Level: intermediate
60635552b385SBrandon
60645552b385SBrandon .seealso: DMPlexGeomDataAndGrads
60655552b385SBrandon @*/
DMPlexGetGeomCntrlPntMaps(DM dm,PetscInt * numCntrlPnts,PetscInt ** cntrlPntFaceMap,PetscInt ** cntrlPntWeightFaceMap,PetscInt ** cntrlPntEdgeMap,PetscInt ** cntrlPntWeightEdgeMap,PetscInt ** cntrlPntVertexMap,PetscInt ** cntrlPntWeightVertexMap)60665552b385SBrandon PetscErrorCode DMPlexGetGeomCntrlPntMaps(DM dm, PetscInt *numCntrlPnts, PetscInt **cntrlPntFaceMap, PetscInt **cntrlPntWeightFaceMap, PetscInt **cntrlPntEdgeMap, PetscInt **cntrlPntWeightEdgeMap, PetscInt **cntrlPntVertexMap, PetscInt **cntrlPntWeightVertexMap)
60675552b385SBrandon {
60685552b385SBrandon PetscFunctionBeginHot;
60695552b385SBrandon #ifdef PETSC_HAVE_EGADS
60705552b385SBrandon PetscContainer modelObj, numCntrlPntsObj, cntrlPntFaceMapObj, cntrlPntWeightFaceMapObj, cntrlPntEdgeMapObj, cntrlPntWeightEdgeMapObj, cntrlPntVertexMapObj, cntrlPntWeightVertexMapObj;
60715552b385SBrandon PetscInt *numCntrlPntsPtr, *cntrlPntFaceMapPtr, *cntrlPntWeightFaceMapPtr, *cntrlPntEdgeMapPtr, *cntrlPntWeightEdgeMapPtr, *cntrlPntVertexMapPtr, *cntrlPntWeightVertexMapPtr;
60725552b385SBrandon
60735552b385SBrandon /* Determine which type of EGADS model is attached to the DM */
60745552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
60753a7d0413SPierre Jolivet if (!modelObj) PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj));
60765552b385SBrandon
6077ac530a7eSPierre Jolivet if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS);
60785552b385SBrandon
60795552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data
60805552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&numCntrlPntsObj));
60815552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cntrlPntFaceMapObj));
60825552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&cntrlPntWeightFaceMapObj));
60835552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cntrlPntEdgeMapObj));
60845552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&cntrlPntWeightEdgeMapObj));
60855552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cntrlPntVertexMapObj));
60865552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&cntrlPntWeightVertexMapObj));
60875552b385SBrandon
60885552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer)
60895552b385SBrandon if (numCntrlPntsObj) {
60902a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(numCntrlPntsObj, &numCntrlPntsPtr));
60915552b385SBrandon *numCntrlPnts = *numCntrlPntsPtr;
60925552b385SBrandon }
60935552b385SBrandon
60945552b385SBrandon if (cntrlPntFaceMapObj) {
60952a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cntrlPntFaceMapObj, &cntrlPntFaceMapPtr));
60965552b385SBrandon *cntrlPntFaceMap = cntrlPntFaceMapPtr;
60975552b385SBrandon }
60985552b385SBrandon
60995552b385SBrandon if (cntrlPntWeightFaceMapObj) {
61002a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cntrlPntWeightFaceMapObj, &cntrlPntWeightFaceMapPtr));
61015552b385SBrandon *cntrlPntWeightFaceMap = cntrlPntWeightFaceMapPtr;
61025552b385SBrandon }
61035552b385SBrandon
61045552b385SBrandon if (cntrlPntEdgeMapObj) {
61052a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cntrlPntEdgeMapObj, &cntrlPntEdgeMapPtr));
61065552b385SBrandon *cntrlPntEdgeMap = cntrlPntEdgeMapPtr;
61075552b385SBrandon }
61085552b385SBrandon
61095552b385SBrandon if (cntrlPntWeightEdgeMapObj) {
61102a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cntrlPntWeightEdgeMapObj, &cntrlPntWeightEdgeMapPtr));
61115552b385SBrandon *cntrlPntWeightEdgeMap = cntrlPntWeightEdgeMapPtr;
61125552b385SBrandon }
61135552b385SBrandon
61145552b385SBrandon if (cntrlPntVertexMapObj) {
61152a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cntrlPntVertexMapObj, &cntrlPntVertexMapPtr));
61165552b385SBrandon *cntrlPntVertexMap = cntrlPntVertexMapPtr;
61175552b385SBrandon }
61185552b385SBrandon
61195552b385SBrandon if (cntrlPntWeightVertexMapObj) {
61202a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(cntrlPntWeightVertexMapObj, &cntrlPntWeightVertexMapPtr));
61215552b385SBrandon *cntrlPntWeightVertexMap = cntrlPntWeightVertexMapPtr;
61225552b385SBrandon }
61235552b385SBrandon
61245552b385SBrandon #endif
61255552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS);
61265552b385SBrandon }
61275552b385SBrandon
61285552b385SBrandon #endif
6129