xref: /petsc/src/dm/impls/plex/plexegads.c (revision 49abdd8a111d9c2ef7fc48ade253ef64e07f9b37)
1a8ededdfSMatthew G. Knepley #include <petsc/private/dmpleximpl.h> /*I      "petscdmplex.h"   I*/
27bee2925SMatthew Knepley #include <petsc/private/hashmapi.h>
3a8ededdfSMatthew G. Knepley 
4a8ededdfSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
5a8ededdfSMatthew G. Knepley   #include <egads.h>
6a8ededdfSMatthew G. Knepley #endif
7a8ededdfSMatthew G. Knepley 
8337bb527SBarry Smith /* We need to understand how to natively parse STEP files. There seems to be only one open-source implementation of
9a8ededdfSMatthew G. Knepley    the STEP parser contained in the OpenCASCADE package. It is enough to make a strong man weep:
10a8ededdfSMatthew G. Knepley 
11a8ededdfSMatthew G. Knepley      https://github.com/tpaviot/oce/tree/master/src/STEPControl
12a8ededdfSMatthew G. Knepley 
13a8ededdfSMatthew G. Knepley    The STEP, and inner EXPRESS, formats are ISO standards, so they are documented
14a8ededdfSMatthew G. Knepley 
15a8ededdfSMatthew G. Knepley      https://stackoverflow.com/questions/26774037/documentation-or-specification-for-step-and-stp-files
16a8ededdfSMatthew G. Knepley      http://stepmod.sourceforge.net/express_model_spec/
17a8ededdfSMatthew G. Knepley 
18a8ededdfSMatthew G. Knepley    but again it seems that there has been a deliberate effort at obfuscation, probably to raise the bar for entrants.
19a8ededdfSMatthew G. Knepley */
20a8ededdfSMatthew G. Knepley 
21c1cad2e7SMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
227625649eSMatthew G. Knepley PETSC_INTERN PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM, PetscInt, ego, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscScalar[]);
237625649eSMatthew G. Knepley PETSC_INTERN PetscErrorCode DMSnapToGeomModel_EGADSLite_Internal(DM, PetscInt, ego, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscScalar[]);
24c1cad2e7SMatthew G. Knepley 
257625649eSMatthew G. Knepley PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM dm, PetscInt p, ego model, PetscInt bodyID, PetscInt faceID, PetscInt edgeID, const PetscScalar mcoords[], PetscScalar gcoords[])
26d71ae5a4SJacob Faibussowitsch {
27c1cad2e7SMatthew G. Knepley   DM   cdm;
28c1cad2e7SMatthew G. Knepley   ego *bodies;
29c1cad2e7SMatthew G. Knepley   ego  geom, body, obj;
30a5b23f4aSJose E. Roman   /* result has to hold derivatives, along with the value */
31c1cad2e7SMatthew G. Knepley   double       params[3], result[18], paramsV[16 * 3], resultV[16 * 3], range[4];
32c1cad2e7SMatthew G. Knepley   int          Nb, oclass, mtype, *senses, peri;
33c1cad2e7SMatthew G. Knepley   Vec          coordinatesLocal;
34c1cad2e7SMatthew G. Knepley   PetscScalar *coords = NULL;
35c1cad2e7SMatthew G. Knepley   PetscInt     Nv, v, Np = 0, pm;
36c1cad2e7SMatthew G. Knepley   PetscInt     dE, d;
37c1cad2e7SMatthew G. Knepley 
38c1cad2e7SMatthew G. Knepley   PetscFunctionBeginHot;
399566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
409566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
419566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
429566063dSJacob Faibussowitsch   PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
4363a3b9bcSJacob Faibussowitsch   PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %d)", bodyID, Nb);
44c1cad2e7SMatthew G. Knepley   body = bodies[bodyID];
45c1cad2e7SMatthew G. Knepley 
469371c9d4SSatish Balay   if (edgeID >= 0) {
479371c9d4SSatish Balay     PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &obj));
489371c9d4SSatish Balay     Np = 1;
499371c9d4SSatish Balay   } else if (faceID >= 0) {
509371c9d4SSatish Balay     PetscCall(EG_objectBodyTopo(body, FACE, faceID, &obj));
519371c9d4SSatish Balay     Np = 2;
529371c9d4SSatish Balay   } else {
53c1cad2e7SMatthew G. Knepley     for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
543ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
55c1cad2e7SMatthew G. Knepley   }
56c1cad2e7SMatthew G. Knepley 
57c1cad2e7SMatthew G. Knepley   /* Calculate parameters (t or u,v) for vertices */
589566063dSJacob Faibussowitsch   PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords));
59c1cad2e7SMatthew G. Knepley   Nv /= dE;
60c1cad2e7SMatthew G. Knepley   if (Nv == 1) {
619566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords));
62c1cad2e7SMatthew G. Knepley     for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
633ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
64c1cad2e7SMatthew G. Knepley   }
6563a3b9bcSJacob Faibussowitsch   PetscCheck(Nv <= 16, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " coordinates associated to point %" PetscInt_FMT, Nv, p);
66c1cad2e7SMatthew G. Knepley 
67c1cad2e7SMatthew G. Knepley   /* Correct EGADSlite 2pi bug when calculating nearest point on Periodic Surfaces */
689566063dSJacob Faibussowitsch   PetscCall(EG_getRange(obj, range, &peri));
69c1cad2e7SMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
709566063dSJacob Faibussowitsch     PetscCall(EG_invEvaluate(obj, &coords[v * dE], &paramsV[v * 3], &resultV[v * 3]));
71c1cad2e7SMatthew G. Knepley   #if 1
72c1cad2e7SMatthew G. Knepley     if (peri > 0) {
739371c9d4SSatish Balay       if (paramsV[v * 3 + 0] + 1.e-4 < range[0]) {
749371c9d4SSatish Balay         paramsV[v * 3 + 0] += 2. * PETSC_PI;
759371c9d4SSatish Balay       } else if (paramsV[v * 3 + 0] - 1.e-4 > range[1]) {
769371c9d4SSatish Balay         paramsV[v * 3 + 0] -= 2. * PETSC_PI;
779371c9d4SSatish Balay       }
78c1cad2e7SMatthew G. Knepley     }
79c1cad2e7SMatthew G. Knepley     if (peri > 1) {
809371c9d4SSatish Balay       if (paramsV[v * 3 + 1] + 1.e-4 < range[2]) {
819371c9d4SSatish Balay         paramsV[v * 3 + 1] += 2. * PETSC_PI;
829371c9d4SSatish Balay       } else if (paramsV[v * 3 + 1] - 1.e-4 > range[3]) {
839371c9d4SSatish Balay         paramsV[v * 3 + 1] -= 2. * PETSC_PI;
849371c9d4SSatish Balay       }
85c1cad2e7SMatthew G. Knepley     }
86c1cad2e7SMatthew G. Knepley   #endif
87c1cad2e7SMatthew G. Knepley   }
889566063dSJacob Faibussowitsch   PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords));
89c1cad2e7SMatthew G. Knepley   /* Calculate parameters (t or u,v) for new vertex at edge midpoint */
90c1cad2e7SMatthew G. Knepley   for (pm = 0; pm < Np; ++pm) {
91c1cad2e7SMatthew G. Knepley     params[pm] = 0.;
92c1cad2e7SMatthew G. Knepley     for (v = 0; v < Nv; ++v) params[pm] += paramsV[v * 3 + pm];
93c1cad2e7SMatthew G. Knepley     params[pm] /= Nv;
94c1cad2e7SMatthew G. Knepley   }
9563a3b9bcSJacob Faibussowitsch   PetscCheck(!(params[0] < range[0]) && !(params[0] > range[1]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " had bad interpolation", p);
961dca8a05SBarry Smith   PetscCheck(Np <= 1 || (params[1] >= range[2] && params[1] <= range[3]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " had bad interpolation", p);
97c1cad2e7SMatthew G. Knepley   /* Put coordinates for new vertex in result[] */
989566063dSJacob Faibussowitsch   PetscCall(EG_evaluate(obj, params, result));
99c1cad2e7SMatthew G. Knepley   for (d = 0; d < dE; ++d) gcoords[d] = result[d];
1003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
101c1cad2e7SMatthew G. Knepley }
102c1cad2e7SMatthew G. Knepley #endif
103c1cad2e7SMatthew G. Knepley 
1047625649eSMatthew G. Knepley PetscErrorCode DMSnapToGeomModel_EGADSLite(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[])
105d71ae5a4SJacob Faibussowitsch {
106c1cad2e7SMatthew G. Knepley   PetscFunctionBeginHot;
107a8ededdfSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
108c1cad2e7SMatthew G. Knepley   DMLabel        bodyLabel, faceLabel, edgeLabel;
109c1cad2e7SMatthew G. Knepley   PetscInt       bodyID, faceID, edgeID;
110c1cad2e7SMatthew G. Knepley   PetscContainer modelObj;
111c1cad2e7SMatthew G. Knepley   ego            model;
112c1cad2e7SMatthew G. Knepley 
1139566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
1149566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
1159566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
1167625649eSMatthew G. Knepley   PetscCheck(bodyLabel && faceLabel && edgeLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADSLite meshes must have body, face, and edge labels defined");
1179566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSLite Model", (PetscObject *)&modelObj));
1187625649eSMatthew G. Knepley   PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADSLite mesh missing model object");
1197625649eSMatthew G. Knepley 
1209566063dSJacob Faibussowitsch   PetscCall(PetscContainerGetPointer(modelObj, (void **)&model));
1219566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(bodyLabel, p, &bodyID));
1229566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(faceLabel, p, &faceID));
1239566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(edgeLabel, p, &edgeID));
124c1cad2e7SMatthew G. Knepley   /* Allows for "Connective" Plex Edges present in models with multiple non-touching Entities */
125c1cad2e7SMatthew G. Knepley   if (bodyID < 0) {
1267625649eSMatthew G. Knepley     for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
1273ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
128a8ededdfSMatthew G. Knepley   }
1297625649eSMatthew G. Knepley   PetscCall(DMSnapToGeomModel_EGADSLite_Internal(dm, p, model, bodyID, faceID, edgeID, mcoords, gcoords));
1307625649eSMatthew G. Knepley #endif
1317625649eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
132f0fcf0adSMatthew G. Knepley }
1337625649eSMatthew G. Knepley 
1347625649eSMatthew G. Knepley PetscErrorCode DMSnapToGeomModel_EGADS(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[])
1357625649eSMatthew G. Knepley {
1367625649eSMatthew G. Knepley   PetscFunctionBeginHot;
1377625649eSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
1387625649eSMatthew G. Knepley   DMLabel        bodyLabel, faceLabel, edgeLabel;
1397625649eSMatthew G. Knepley   PetscInt       bodyID, faceID, edgeID;
1407625649eSMatthew G. Knepley   PetscContainer modelObj;
1417625649eSMatthew G. Knepley   ego            model;
1427625649eSMatthew G. Knepley 
1437625649eSMatthew G. Knepley   PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
1447625649eSMatthew G. Knepley   PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
1457625649eSMatthew G. Knepley   PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
1467625649eSMatthew G. Knepley   PetscCheck(bodyLabel && faceLabel && edgeLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADS meshes must have body, face, and edge labels defined");
1477625649eSMatthew G. Knepley   PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
1487625649eSMatthew G. Knepley   PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADS mesh missing model object");
1497625649eSMatthew G. Knepley 
1507625649eSMatthew G. Knepley   PetscCall(PetscContainerGetPointer(modelObj, (void **)&model));
1517625649eSMatthew G. Knepley   PetscCall(DMLabelGetValue(bodyLabel, p, &bodyID));
1527625649eSMatthew G. Knepley   PetscCall(DMLabelGetValue(faceLabel, p, &faceID));
1537625649eSMatthew G. Knepley   PetscCall(DMLabelGetValue(edgeLabel, p, &edgeID));
1547625649eSMatthew G. Knepley   /* Allows for "Connective" Plex Edges present in models with multiple non-touching Entities */
1557625649eSMatthew G. Knepley   if (bodyID < 0) {
1567625649eSMatthew G. Knepley     for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
1577625649eSMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
1587625649eSMatthew G. Knepley   }
1597625649eSMatthew G. Knepley   PetscCall(DMSnapToGeomModel_EGADS_Internal(dm, p, model, bodyID, faceID, edgeID, mcoords, gcoords));
160a8ededdfSMatthew G. Knepley #endif
1613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
162a8ededdfSMatthew G. Knepley }
1637bee2925SMatthew Knepley 
1647bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
165d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexEGADSPrintModel_Internal(ego model)
166d71ae5a4SJacob Faibussowitsch {
1677bee2925SMatthew Knepley   ego geom, *bodies, *objs, *nobjs, *mobjs, *lobjs;
1687bee2925SMatthew Knepley   int oclass, mtype, *senses;
1697bee2925SMatthew Knepley   int Nb, b;
1707bee2925SMatthew Knepley 
1717bee2925SMatthew Knepley   PetscFunctionBeginUser;
1727bee2925SMatthew Knepley   /* test bodyTopo functions */
1739566063dSJacob Faibussowitsch   PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
1749566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of BODIES (nbodies): %d \n", Nb));
1757bee2925SMatthew Knepley 
1767bee2925SMatthew Knepley   for (b = 0; b < Nb; ++b) {
1777bee2925SMatthew Knepley     ego body = bodies[b];
1787bee2925SMatthew Knepley     int id, Nsh, Nf, Nl, l, Ne, e, Nv, v;
1797bee2925SMatthew Knepley 
1807bee2925SMatthew Knepley     /* Output Basic Model Topology */
1819566063dSJacob Faibussowitsch     PetscCall(EG_getBodyTopos(body, NULL, SHELL, &Nsh, &objs));
1829566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "   Number of SHELLS: %d \n", Nsh));
1837bee2925SMatthew Knepley     EG_free(objs);
1847bee2925SMatthew Knepley 
1859566063dSJacob Faibussowitsch     PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &objs));
1869566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "   Number of FACES: %d \n", Nf));
1877bee2925SMatthew Knepley     EG_free(objs);
1887bee2925SMatthew Knepley 
1899566063dSJacob Faibussowitsch     PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
1909566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "   Number of LOOPS: %d \n", Nl));
1917bee2925SMatthew Knepley 
1929566063dSJacob Faibussowitsch     PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &objs));
1939566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "   Number of EDGES: %d \n", Ne));
1947bee2925SMatthew Knepley     EG_free(objs);
1957bee2925SMatthew Knepley 
1969566063dSJacob Faibussowitsch     PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &objs));
1979566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "   Number of NODES: %d \n", Nv));
1987bee2925SMatthew Knepley     EG_free(objs);
1997bee2925SMatthew Knepley 
2007bee2925SMatthew Knepley     for (l = 0; l < Nl; ++l) {
2017bee2925SMatthew Knepley       ego loop = lobjs[l];
2027bee2925SMatthew Knepley 
2037bee2925SMatthew Knepley       id = EG_indexBodyTopo(body, loop);
2049566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "          LOOP ID: %d\n", id));
2057bee2925SMatthew Knepley 
2067bee2925SMatthew Knepley       /* Get EDGE info which associated with the current LOOP */
2079566063dSJacob Faibussowitsch       PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
2087bee2925SMatthew Knepley 
2097bee2925SMatthew Knepley       for (e = 0; e < Ne; ++e) {
2107bee2925SMatthew Knepley         ego    edge      = objs[e];
2117bee2925SMatthew Knepley         double range[4]  = {0., 0., 0., 0.};
2127bee2925SMatthew Knepley         double point[3]  = {0., 0., 0.};
213266cfabeSMatthew G. Knepley         double params[3] = {0., 0., 0.};
214266cfabeSMatthew G. Knepley         double result[18];
2157bee2925SMatthew Knepley         int    peri;
2167bee2925SMatthew Knepley 
2175f80ce2aSJacob Faibussowitsch         id = EG_indexBodyTopo(body, edge);
2189566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "            EDGE ID: %d (%d)\n", id, e));
2197bee2925SMatthew Knepley 
2209566063dSJacob Faibussowitsch         PetscCall(EG_getRange(edge, range, &peri));
2219566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Range = %lf, %lf, %lf, %lf \n", range[0], range[1], range[2], range[3]));
2227bee2925SMatthew Knepley 
2237bee2925SMatthew Knepley         /* Get NODE info which associated with the current EDGE */
2249566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
225266cfabeSMatthew G. Knepley         if (mtype == DEGENERATE) {
2269566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "  EDGE %d is DEGENERATE \n", id));
227266cfabeSMatthew G. Knepley         } else {
228266cfabeSMatthew G. Knepley           params[0] = range[0];
2299566063dSJacob Faibussowitsch           PetscCall(EG_evaluate(edge, params, result));
2309566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "   between (%lf, %lf, %lf)", result[0], result[1], result[2]));
231266cfabeSMatthew G. Knepley           params[0] = range[1];
2329566063dSJacob Faibussowitsch           PetscCall(EG_evaluate(edge, params, result));
2339566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, " and (%lf, %lf, %lf)\n", result[0], result[1], result[2]));
234266cfabeSMatthew G. Knepley         }
2357bee2925SMatthew Knepley 
2367bee2925SMatthew Knepley         for (v = 0; v < Nv; ++v) {
2377bee2925SMatthew Knepley           ego    vertex = nobjs[v];
2387bee2925SMatthew Knepley           double limits[4];
2397bee2925SMatthew Knepley           int    dummy;
2407bee2925SMatthew Knepley 
2419566063dSJacob Faibussowitsch           PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses));
2427bee2925SMatthew Knepley           id = EG_indexBodyTopo(body, vertex);
2439566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "              NODE ID: %d \n", id));
2449566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "                 (x, y, z) = (%lf, %lf, %lf) \n", limits[0], limits[1], limits[2]));
2457bee2925SMatthew Knepley 
2467bee2925SMatthew Knepley           point[0] = point[0] + limits[0];
2477bee2925SMatthew Knepley           point[1] = point[1] + limits[1];
2487bee2925SMatthew Knepley           point[2] = point[2] + limits[2];
2497bee2925SMatthew Knepley         }
2507bee2925SMatthew Knepley       }
2517bee2925SMatthew Knepley     }
2527bee2925SMatthew Knepley     EG_free(lobjs);
2537bee2925SMatthew Knepley   }
2543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2557bee2925SMatthew Knepley }
2567bee2925SMatthew Knepley 
257*49abdd8aSBarry Smith static PetscErrorCode DMPlexEGADSDestroy_Private(void **context)
258d71ae5a4SJacob Faibussowitsch {
259*49abdd8aSBarry Smith   if (context) EG_close((ego)*context);
2607bee2925SMatthew Knepley   return 0;
2617bee2925SMatthew Knepley }
2627bee2925SMatthew Knepley 
263d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateEGADS_Internal(MPI_Comm comm, ego context, ego model, DM *newdm)
264d71ae5a4SJacob Faibussowitsch {
265c1cad2e7SMatthew G. Knepley   DMLabel  bodyLabel, faceLabel, edgeLabel, vertexLabel;
2667bee2925SMatthew Knepley   PetscInt cStart, cEnd, c;
2677bee2925SMatthew Knepley   /* EGADSLite variables */
2687bee2925SMatthew Knepley   ego geom, *bodies, *objs, *nobjs, *mobjs, *lobjs;
2697bee2925SMatthew Knepley   int oclass, mtype, nbodies, *senses;
2707bee2925SMatthew Knepley   int b;
2717bee2925SMatthew Knepley   /* PETSc variables */
2727bee2925SMatthew Knepley   DM          dm;
2737bee2925SMatthew Knepley   PetscHMapI  edgeMap = NULL;
2747bee2925SMatthew 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;
2757bee2925SMatthew Knepley   PetscInt   *cells = NULL, *cone = NULL;
2767bee2925SMatthew Knepley   PetscReal  *coords = NULL;
2777bee2925SMatthew Knepley   PetscMPIInt rank;
2787bee2925SMatthew Knepley 
2797bee2925SMatthew Knepley   PetscFunctionBegin;
2809566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
281dd400576SPatrick Sanan   if (rank == 0) {
282266cfabeSMatthew G. Knepley     const PetscInt debug = 0;
283266cfabeSMatthew G. Knepley 
2847bee2925SMatthew Knepley     /* ---------------------------------------------------------------------------------------------------
2857bee2925SMatthew Knepley     Generate Petsc Plex
2867bee2925SMatthew Knepley       Get all Nodes in model, record coordinates in a correctly formatted array
2877bee2925SMatthew Knepley       Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array
2887bee2925SMatthew Knepley       We need to uniformly refine the initial geometry to guarantee a valid mesh
2897bee2925SMatthew Knepley     */
2907bee2925SMatthew Knepley 
2917bee2925SMatthew Knepley     /* Calculate cell and vertex sizes */
2929566063dSJacob Faibussowitsch     PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
2939566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&edgeMap));
2947bee2925SMatthew Knepley     numEdges = 0;
2957bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
2967bee2925SMatthew Knepley       ego body = bodies[b];
2977bee2925SMatthew Knepley       int id, Nl, l, Nv, v;
2987bee2925SMatthew Knepley 
2999566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
3007bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
3017bee2925SMatthew Knepley         ego loop = lobjs[l];
3027bee2925SMatthew Knepley         int Ner  = 0, Ne, e, Nc;
3037bee2925SMatthew Knepley 
3049566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
3057bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
3067bee2925SMatthew Knepley           ego           edge = objs[e];
3077bee2925SMatthew Knepley           int           Nv, id;
3087bee2925SMatthew Knepley           PetscHashIter iter;
3097bee2925SMatthew Knepley           PetscBool     found;
3107bee2925SMatthew Knepley 
3119566063dSJacob Faibussowitsch           PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
3127bee2925SMatthew Knepley           if (mtype == DEGENERATE) continue;
3135f80ce2aSJacob Faibussowitsch           id = EG_indexBodyTopo(body, edge);
3149566063dSJacob Faibussowitsch           PetscCall(PetscHMapIFind(edgeMap, id - 1, &iter, &found));
3159566063dSJacob Faibussowitsch           if (!found) PetscCall(PetscHMapISet(edgeMap, id - 1, numEdges++));
3167bee2925SMatthew Knepley           ++Ner;
3177bee2925SMatthew Knepley         }
3189371c9d4SSatish Balay         if (Ner == 2) {
3199371c9d4SSatish Balay           Nc = 2;
3209371c9d4SSatish Balay         } else if (Ner == 3) {
3219371c9d4SSatish Balay           Nc = 4;
3229371c9d4SSatish Balay         } else if (Ner == 4) {
3239371c9d4SSatish Balay           Nc = 8;
3249371c9d4SSatish Balay           ++numQuads;
3259371c9d4SSatish Balay         } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot support loop with %d edges", Ner);
3267bee2925SMatthew Knepley         numCells += Nc;
3277bee2925SMatthew Knepley         newCells += Nc - 1;
3287bee2925SMatthew Knepley         maxCorners = PetscMax(Ner * 2 + 1, maxCorners);
3297bee2925SMatthew Knepley       }
3309566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
3317bee2925SMatthew Knepley       for (v = 0; v < Nv; ++v) {
3327bee2925SMatthew Knepley         ego vertex = nobjs[v];
3337bee2925SMatthew Knepley 
3347bee2925SMatthew Knepley         id = EG_indexBodyTopo(body, vertex);
3357bee2925SMatthew Knepley         /* TODO: Instead of assuming contiguous ids, we could use a hash table */
3367bee2925SMatthew Knepley         numVertices = PetscMax(id, numVertices);
3377bee2925SMatthew Knepley       }
3387bee2925SMatthew Knepley       EG_free(lobjs);
3397bee2925SMatthew Knepley       EG_free(nobjs);
3407bee2925SMatthew Knepley     }
3419566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(edgeMap, &numEdges));
3427bee2925SMatthew Knepley     newVertices = numEdges + numQuads;
3437bee2925SMatthew Knepley     numVertices += newVertices;
3447bee2925SMatthew Knepley 
3457bee2925SMatthew Knepley     dim        = 2; /* Assume 3D Models :: Need to update to handle 2D Models in the future */
3467bee2925SMatthew Knepley     cdim       = 3; /* Assume 3D Models :: Need to update to handle 2D Models in the future */
3477bee2925SMatthew Knepley     numCorners = 3; /* Split cells into triangles */
3489566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(numVertices * cdim, &coords, numCells * numCorners, &cells, maxCorners, &cone));
3497bee2925SMatthew Knepley 
3507bee2925SMatthew Knepley     /* Get vertex coordinates */
3517bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
3527bee2925SMatthew Knepley       ego body = bodies[b];
3537bee2925SMatthew Knepley       int id, Nv, v;
3547bee2925SMatthew Knepley 
3559566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
3567bee2925SMatthew Knepley       for (v = 0; v < Nv; ++v) {
3577bee2925SMatthew Knepley         ego    vertex = nobjs[v];
3587bee2925SMatthew Knepley         double limits[4];
3597bee2925SMatthew Knepley         int    dummy;
3607bee2925SMatthew Knepley 
3619566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses));
3625f80ce2aSJacob Faibussowitsch         id                          = EG_indexBodyTopo(body, vertex);
3637bee2925SMatthew Knepley         coords[(id - 1) * cdim + 0] = limits[0];
3647bee2925SMatthew Knepley         coords[(id - 1) * cdim + 1] = limits[1];
3657bee2925SMatthew Knepley         coords[(id - 1) * cdim + 2] = limits[2];
3667bee2925SMatthew Knepley       }
3677bee2925SMatthew Knepley       EG_free(nobjs);
3687bee2925SMatthew Knepley     }
3699566063dSJacob Faibussowitsch     PetscCall(PetscHMapIClear(edgeMap));
3707bee2925SMatthew Knepley     fOff     = numVertices - newVertices + numEdges;
3717bee2925SMatthew Knepley     numEdges = 0;
3727bee2925SMatthew Knepley     numQuads = 0;
3737bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
3747bee2925SMatthew Knepley       ego body = bodies[b];
3757bee2925SMatthew Knepley       int Nl, l;
3767bee2925SMatthew Knepley 
3779566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
3787bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
3797bee2925SMatthew Knepley         ego loop = lobjs[l];
3807bee2925SMatthew Knepley         int lid, Ner = 0, Ne, e;
3817bee2925SMatthew Knepley 
3825f80ce2aSJacob Faibussowitsch         lid = EG_indexBodyTopo(body, loop);
3839566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
3847bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
3857bee2925SMatthew Knepley           ego           edge = objs[e];
3867bee2925SMatthew Knepley           int           eid, Nv;
3877bee2925SMatthew Knepley           PetscHashIter iter;
3887bee2925SMatthew Knepley           PetscBool     found;
3897bee2925SMatthew Knepley 
3909566063dSJacob Faibussowitsch           PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
3917bee2925SMatthew Knepley           if (mtype == DEGENERATE) continue;
3927bee2925SMatthew Knepley           ++Ner;
3935f80ce2aSJacob Faibussowitsch           eid = EG_indexBodyTopo(body, edge);
3949566063dSJacob Faibussowitsch           PetscCall(PetscHMapIFind(edgeMap, eid - 1, &iter, &found));
3957bee2925SMatthew Knepley           if (!found) {
3967bee2925SMatthew Knepley             PetscInt v = numVertices - newVertices + numEdges;
3977bee2925SMatthew Knepley             double   range[4], params[3] = {0., 0., 0.}, result[18];
3987bee2925SMatthew Knepley             int      periodic[2];
3997bee2925SMatthew Knepley 
4009566063dSJacob Faibussowitsch             PetscCall(PetscHMapISet(edgeMap, eid - 1, numEdges++));
4019566063dSJacob Faibussowitsch             PetscCall(EG_getRange(edge, range, periodic));
4027bee2925SMatthew Knepley             params[0] = 0.5 * (range[0] + range[1]);
4039566063dSJacob Faibussowitsch             PetscCall(EG_evaluate(edge, params, result));
4047bee2925SMatthew Knepley             coords[v * cdim + 0] = result[0];
4057bee2925SMatthew Knepley             coords[v * cdim + 1] = result[1];
4067bee2925SMatthew Knepley             coords[v * cdim + 2] = result[2];
4077bee2925SMatthew Knepley           }
4087bee2925SMatthew Knepley         }
4097bee2925SMatthew Knepley         if (Ner == 4) {
4107bee2925SMatthew Knepley           PetscInt v = fOff + numQuads++;
411266cfabeSMatthew G. Knepley           ego     *fobjs, face;
4127bee2925SMatthew Knepley           double   range[4], params[3] = {0., 0., 0.}, result[18];
413266cfabeSMatthew G. Knepley           int      Nf, fid, periodic[2];
4147bee2925SMatthew Knepley 
4159566063dSJacob Faibussowitsch           PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs));
416266cfabeSMatthew G. Knepley           face = fobjs[0];
4175f80ce2aSJacob Faibussowitsch           fid  = EG_indexBodyTopo(body, face);
41808401ef6SPierre Jolivet           PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Loop %d has %d faces, instead of 1 (%d)", lid - 1, Nf, fid);
4199566063dSJacob Faibussowitsch           PetscCall(EG_getRange(face, range, periodic));
4207bee2925SMatthew Knepley           params[0] = 0.5 * (range[0] + range[1]);
4217bee2925SMatthew Knepley           params[1] = 0.5 * (range[2] + range[3]);
4229566063dSJacob Faibussowitsch           PetscCall(EG_evaluate(face, params, result));
4237bee2925SMatthew Knepley           coords[v * cdim + 0] = result[0];
4247bee2925SMatthew Knepley           coords[v * cdim + 1] = result[1];
4257bee2925SMatthew Knepley           coords[v * cdim + 2] = result[2];
4267bee2925SMatthew Knepley         }
4277bee2925SMatthew Knepley       }
4287bee2925SMatthew Knepley     }
4291dca8a05SBarry Smith     PetscCheck(numEdges + numQuads == newVertices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of new vertices %" PetscInt_FMT " != %" PetscInt_FMT " previous count", numEdges + numQuads, newVertices);
4307bee2925SMatthew Knepley 
4317bee2925SMatthew Knepley     /* Get cell vertices by traversing loops */
4327bee2925SMatthew Knepley     numQuads = 0;
4337bee2925SMatthew Knepley     cOff     = 0;
4347bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
4357bee2925SMatthew Knepley       ego body = bodies[b];
4367bee2925SMatthew Knepley       int id, Nl, l;
4377bee2925SMatthew Knepley 
4389566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
4397bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
4407bee2925SMatthew Knepley         ego loop = lobjs[l];
4417bee2925SMatthew Knepley         int lid, Ner = 0, Ne, e, nc = 0, c, Nt, t;
4427bee2925SMatthew Knepley 
4435f80ce2aSJacob Faibussowitsch         lid = EG_indexBodyTopo(body, loop);
4449566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
4457bee2925SMatthew Knepley 
4467bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
4477bee2925SMatthew Knepley           ego edge = objs[e];
4487bee2925SMatthew Knepley           int points[3];
4497bee2925SMatthew Knepley           int eid, Nv, v, tmp;
4507bee2925SMatthew Knepley 
4517bee2925SMatthew Knepley           eid = EG_indexBodyTopo(body, edge);
4529566063dSJacob Faibussowitsch           PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
453266cfabeSMatthew G. Knepley           if (mtype == DEGENERATE) continue;
454266cfabeSMatthew G. Knepley           else ++Ner;
45508401ef6SPierre Jolivet           PetscCheck(Nv == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Edge %d has %d vertices != 2", eid, Nv);
4567bee2925SMatthew Knepley 
4577bee2925SMatthew Knepley           for (v = 0; v < Nv; ++v) {
4587bee2925SMatthew Knepley             ego vertex = nobjs[v];
4597bee2925SMatthew Knepley 
4607bee2925SMatthew Knepley             id            = EG_indexBodyTopo(body, vertex);
4617bee2925SMatthew Knepley             points[v * 2] = id - 1;
4627bee2925SMatthew Knepley           }
4637bee2925SMatthew Knepley           {
4647bee2925SMatthew Knepley             PetscInt edgeNum;
4657bee2925SMatthew Knepley 
4669566063dSJacob Faibussowitsch             PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum));
4677bee2925SMatthew Knepley             points[1] = numVertices - newVertices + edgeNum;
4687bee2925SMatthew Knepley           }
4697bee2925SMatthew Knepley           /* EGADS loops are not oriented, but seem to be in order, so we must piece them together */
4707bee2925SMatthew Knepley           if (!nc) {
4717bee2925SMatthew Knepley             for (v = 0; v < Nv + 1; ++v) cone[nc++] = points[v];
4727bee2925SMatthew Knepley           } else {
4739371c9d4SSatish Balay             if (cone[nc - 1] == points[0]) {
4749371c9d4SSatish Balay               cone[nc++] = points[1];
4759371c9d4SSatish Balay               if (cone[0] != points[2]) cone[nc++] = points[2];
4769371c9d4SSatish Balay             } else if (cone[nc - 1] == points[2]) {
4779371c9d4SSatish Balay               cone[nc++] = points[1];
4789371c9d4SSatish Balay               if (cone[0] != points[0]) cone[nc++] = points[0];
4799371c9d4SSatish Balay             } else if (cone[nc - 3] == points[0]) {
4809371c9d4SSatish Balay               tmp          = cone[nc - 3];
4819371c9d4SSatish Balay               cone[nc - 3] = cone[nc - 1];
4829371c9d4SSatish Balay               cone[nc - 1] = tmp;
4839371c9d4SSatish Balay               cone[nc++]   = points[1];
4849371c9d4SSatish Balay               if (cone[0] != points[2]) cone[nc++] = points[2];
4859371c9d4SSatish Balay             } else if (cone[nc - 3] == points[2]) {
4869371c9d4SSatish Balay               tmp          = cone[nc - 3];
4879371c9d4SSatish Balay               cone[nc - 3] = cone[nc - 1];
4889371c9d4SSatish Balay               cone[nc - 1] = tmp;
4899371c9d4SSatish Balay               cone[nc++]   = points[1];
4909371c9d4SSatish Balay               if (cone[0] != points[0]) cone[nc++] = points[0];
4919371c9d4SSatish Balay             } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %d does not match its predecessor", eid);
4927bee2925SMatthew Knepley           }
4937bee2925SMatthew Knepley         }
49463a3b9bcSJacob Faibussowitsch         PetscCheck(nc == 2 * Ner, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " != %" PetscInt_FMT, nc, 2 * Ner);
495ad540459SPierre Jolivet         if (Ner == 4) cone[nc++] = numVertices - newVertices + numEdges + numQuads++;
49663a3b9bcSJacob Faibussowitsch         PetscCheck(nc <= maxCorners, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " > %" PetscInt_FMT " max", nc, maxCorners);
4977bee2925SMatthew Knepley         /* Triangulate the loop */
4987bee2925SMatthew Knepley         switch (Ner) {
4997bee2925SMatthew Knepley         case 2: /* Bi-Segment -> 2 triangles */
5007bee2925SMatthew Knepley           Nt                           = 2;
5017bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[0];
5027bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[1];
5037bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[2];
5047bee2925SMatthew Knepley           ++cOff;
5057bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[0];
5067bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[2];
5077bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[3];
5087bee2925SMatthew Knepley           ++cOff;
5097bee2925SMatthew Knepley           break;
5107bee2925SMatthew Knepley         case 3: /* Triangle   -> 4 triangles */
5117bee2925SMatthew Knepley           Nt                           = 4;
5127bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[0];
5137bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[1];
5147bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[5];
5157bee2925SMatthew Knepley           ++cOff;
5167bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[1];
5177bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[2];
5187bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[3];
5197bee2925SMatthew Knepley           ++cOff;
5207bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[5];
5217bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[3];
5227bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[4];
5237bee2925SMatthew Knepley           ++cOff;
5247bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[1];
5257bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[3];
5267bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[5];
5277bee2925SMatthew Knepley           ++cOff;
5287bee2925SMatthew Knepley           break;
5297bee2925SMatthew Knepley         case 4: /* Quad       -> 8 triangles */
5307bee2925SMatthew Knepley           Nt                           = 8;
5317bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[0];
5327bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[1];
5337bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[7];
5347bee2925SMatthew Knepley           ++cOff;
5357bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[1];
5367bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[2];
5377bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[3];
5387bee2925SMatthew Knepley           ++cOff;
5397bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[3];
5407bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[4];
5417bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[5];
5427bee2925SMatthew Knepley           ++cOff;
5437bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[5];
5447bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[6];
5457bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[7];
5467bee2925SMatthew Knepley           ++cOff;
5477bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[8];
5487bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[1];
5497bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[3];
5507bee2925SMatthew Knepley           ++cOff;
5517bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[8];
5527bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[3];
5537bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[5];
5547bee2925SMatthew Knepley           ++cOff;
5557bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[8];
5567bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[5];
5577bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[7];
5587bee2925SMatthew Knepley           ++cOff;
5597bee2925SMatthew Knepley           cells[cOff * numCorners + 0] = cone[8];
5607bee2925SMatthew Knepley           cells[cOff * numCorners + 1] = cone[7];
5617bee2925SMatthew Knepley           cells[cOff * numCorners + 2] = cone[1];
5627bee2925SMatthew Knepley           ++cOff;
5637bee2925SMatthew Knepley           break;
564d71ae5a4SJacob Faibussowitsch         default:
565d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d edges, which we do not support", lid, Ner);
5667bee2925SMatthew Knepley         }
567266cfabeSMatthew G. Knepley         if (debug) {
5687bee2925SMatthew Knepley           for (t = 0; t < Nt; ++t) {
56963a3b9bcSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "  LOOP Corner NODEs Triangle %" PetscInt_FMT " (", t));
5707bee2925SMatthew Knepley             for (c = 0; c < numCorners; ++c) {
5719566063dSJacob Faibussowitsch               if (c > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
57263a3b9bcSJacob Faibussowitsch               PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT, cells[(cOff - Nt + t) * numCorners + c]));
5737bee2925SMatthew Knepley             }
5749566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n"));
5757bee2925SMatthew Knepley           }
5767bee2925SMatthew Knepley         }
577266cfabeSMatthew G. Knepley       }
5787bee2925SMatthew Knepley       EG_free(lobjs);
5797bee2925SMatthew Knepley     }
5807bee2925SMatthew Knepley   }
58163a3b9bcSJacob Faibussowitsch   PetscCheck(cOff == numCells, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count of total cells %" PetscInt_FMT " != %" PetscInt_FMT " previous count", cOff, numCells);
5829566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numVertices, numCorners, PETSC_TRUE, cells, cdim, coords, &dm));
5839566063dSJacob Faibussowitsch   PetscCall(PetscFree3(coords, cells, cone));
58463a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(dm, " Total Number of Unique Cells    = %" PetscInt_FMT " (%" PetscInt_FMT ")\n", numCells, newCells));
58563a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %" PetscInt_FMT " (%" PetscInt_FMT ")\n", numVertices, newVertices));
5867bee2925SMatthew Knepley   /* Embed EGADS model in DM */
5877bee2925SMatthew Knepley   {
5887bee2925SMatthew Knepley     PetscContainer modelObj, contextObj;
5897bee2925SMatthew Knepley 
5909566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj));
5919566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(modelObj, model));
5929566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj));
5939566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&modelObj));
5947bee2925SMatthew Knepley 
5959566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj));
5969566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(contextObj, context));
597*49abdd8aSBarry Smith     PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSDestroy_Private));
5989566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj));
5999566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&contextObj));
6007bee2925SMatthew Knepley   }
6017bee2925SMatthew Knepley   /* Label points */
6029566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Body ID"));
6039566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
6049566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Face ID"));
6059566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
6069566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Edge ID"));
6079566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
6089566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Vertex ID"));
6099566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
6107bee2925SMatthew Knepley   cOff = 0;
6117bee2925SMatthew Knepley   for (b = 0; b < nbodies; ++b) {
6127bee2925SMatthew Knepley     ego body = bodies[b];
6137bee2925SMatthew Knepley     int id, Nl, l;
6147bee2925SMatthew Knepley 
6159566063dSJacob Faibussowitsch     PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs));
6167bee2925SMatthew Knepley     for (l = 0; l < Nl; ++l) {
6177bee2925SMatthew Knepley       ego  loop = lobjs[l];
6187bee2925SMatthew Knepley       ego *fobjs;
6197bee2925SMatthew Knepley       int  lid, Nf, fid, Ner = 0, Ne, e, Nt = 0, t;
6207bee2925SMatthew Knepley 
6215f80ce2aSJacob Faibussowitsch       lid = EG_indexBodyTopo(body, loop);
6229566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs));
62308401ef6SPierre Jolivet       PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf);
6245f80ce2aSJacob Faibussowitsch       fid = EG_indexBodyTopo(body, fobjs[0]);
6257bee2925SMatthew Knepley       EG_free(fobjs);
6269566063dSJacob Faibussowitsch       PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses));
6277bee2925SMatthew Knepley       for (e = 0; e < Ne; ++e) {
6287bee2925SMatthew Knepley         ego             edge = objs[e];
6297bee2925SMatthew Knepley         int             eid, Nv, v;
6307bee2925SMatthew Knepley         PetscInt        points[3], support[2], numEdges, edgeNum;
6317bee2925SMatthew Knepley         const PetscInt *edges;
6327bee2925SMatthew Knepley 
6337bee2925SMatthew Knepley         eid = EG_indexBodyTopo(body, edge);
6349566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
6357bee2925SMatthew Knepley         if (mtype == DEGENERATE) continue;
6367bee2925SMatthew Knepley         else ++Ner;
6377bee2925SMatthew Knepley         for (v = 0; v < Nv; ++v) {
6387bee2925SMatthew Knepley           ego vertex = nobjs[v];
6397bee2925SMatthew Knepley 
6407bee2925SMatthew Knepley           id = EG_indexBodyTopo(body, vertex);
6419566063dSJacob Faibussowitsch           PetscCall(DMLabelSetValue(edgeLabel, numCells + id - 1, eid));
6427bee2925SMatthew Knepley           points[v * 2] = numCells + id - 1;
6437bee2925SMatthew Knepley         }
6449566063dSJacob Faibussowitsch         PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum));
6457bee2925SMatthew Knepley         points[1] = numCells + numVertices - newVertices + edgeNum;
6467bee2925SMatthew Knepley 
6479566063dSJacob Faibussowitsch         PetscCall(DMLabelSetValue(edgeLabel, points[1], eid));
6487bee2925SMatthew Knepley         support[0] = points[0];
6497bee2925SMatthew Knepley         support[1] = points[1];
6509566063dSJacob Faibussowitsch         PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges));
65163a3b9bcSJacob Faibussowitsch         PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%" PetscInt_FMT ", %" PetscInt_FMT ") should only bound 1 edge, not %" PetscInt_FMT, support[0], support[1], numEdges);
6529566063dSJacob Faibussowitsch         PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid));
6539566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges));
6547bee2925SMatthew Knepley         support[0] = points[1];
6557bee2925SMatthew Knepley         support[1] = points[2];
6569566063dSJacob Faibussowitsch         PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges));
65763a3b9bcSJacob Faibussowitsch         PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%" PetscInt_FMT ", %" PetscInt_FMT ") should only bound 1 edge, not %" PetscInt_FMT, support[0], support[1], numEdges);
6589566063dSJacob Faibussowitsch         PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid));
6599566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges));
6607bee2925SMatthew Knepley       }
6617bee2925SMatthew Knepley       switch (Ner) {
662d71ae5a4SJacob Faibussowitsch       case 2:
663d71ae5a4SJacob Faibussowitsch         Nt = 2;
664d71ae5a4SJacob Faibussowitsch         break;
665d71ae5a4SJacob Faibussowitsch       case 3:
666d71ae5a4SJacob Faibussowitsch         Nt = 4;
667d71ae5a4SJacob Faibussowitsch         break;
668d71ae5a4SJacob Faibussowitsch       case 4:
669d71ae5a4SJacob Faibussowitsch         Nt = 8;
670d71ae5a4SJacob Faibussowitsch         break;
671d71ae5a4SJacob Faibussowitsch       default:
672d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Loop with %d edges is unsupported", Ner);
6737bee2925SMatthew Knepley       }
6747bee2925SMatthew Knepley       for (t = 0; t < Nt; ++t) {
6759566063dSJacob Faibussowitsch         PetscCall(DMLabelSetValue(bodyLabel, cOff + t, b));
6769566063dSJacob Faibussowitsch         PetscCall(DMLabelSetValue(faceLabel, cOff + t, fid));
6777bee2925SMatthew Knepley       }
6787bee2925SMatthew Knepley       cOff += Nt;
6797bee2925SMatthew Knepley     }
6807bee2925SMatthew Knepley     EG_free(lobjs);
6817bee2925SMatthew Knepley   }
6829566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&edgeMap));
6839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
6847bee2925SMatthew Knepley   for (c = cStart; c < cEnd; ++c) {
6857bee2925SMatthew Knepley     PetscInt *closure = NULL;
6867bee2925SMatthew Knepley     PetscInt  clSize, cl, bval, fval;
6877bee2925SMatthew Knepley 
6889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
6899566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(bodyLabel, c, &bval));
6909566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(faceLabel, c, &fval));
6917bee2925SMatthew Knepley     for (cl = 0; cl < clSize * 2; cl += 2) {
6929566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(bodyLabel, closure[cl], bval));
6939566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(faceLabel, closure[cl], fval));
6947bee2925SMatthew Knepley     }
6959566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
6967bee2925SMatthew Knepley   }
6977bee2925SMatthew Knepley   *newdm = dm;
6983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6997bee2925SMatthew Knepley }
700c1cad2e7SMatthew G. Knepley 
701d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateEGADS(MPI_Comm comm, ego context, ego model, DM *newdm)
702d71ae5a4SJacob Faibussowitsch {
703c1cad2e7SMatthew G. Knepley   DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
704c1cad2e7SMatthew G. Knepley   // EGADS/EGADSLite variables
705c1cad2e7SMatthew G. Knepley   ego geom, *bodies, *mobjs, *fobjs, *lobjs, *eobjs, *nobjs;
706c1cad2e7SMatthew G. Knepley   ego topRef, prev, next;
707c1cad2e7SMatthew G. Knepley   int oclass, mtype, nbodies, *senses, *lSenses, *eSenses;
708c1cad2e7SMatthew G. Knepley   int b;
709c1cad2e7SMatthew G. Knepley   // PETSc variables
710c1cad2e7SMatthew G. Knepley   DM              dm;
711c1cad2e7SMatthew G. Knepley   PetscHMapI      edgeMap = NULL, bodyIndexMap = NULL, bodyVertexMap = NULL, bodyEdgeMap = NULL, bodyFaceMap = NULL, bodyEdgeGlobalMap = NULL;
712c1cad2e7SMatthew G. Knepley   PetscInt        dim = -1, cdim = -1, numCorners = 0, numVertices = 0, numEdges = 0, numFaces = 0, numCells = 0, edgeCntr = 0;
713c1cad2e7SMatthew G. Knepley   PetscInt        cellCntr = 0, numPoints = 0;
714c1cad2e7SMatthew G. Knepley   PetscInt       *cells  = NULL;
715c1cad2e7SMatthew G. Knepley   const PetscInt *cone   = NULL;
716c1cad2e7SMatthew G. Knepley   PetscReal      *coords = NULL;
717c1cad2e7SMatthew G. Knepley   PetscMPIInt     rank;
718c1cad2e7SMatthew G. Knepley 
719c1cad2e7SMatthew G. Knepley   PetscFunctionBeginUser;
7209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
721c5853193SPierre Jolivet   if (rank == 0) {
722c1cad2e7SMatthew G. Knepley     // ---------------------------------------------------------------------------------------------------
723c1cad2e7SMatthew G. Knepley     // Generate Petsc Plex
724c1cad2e7SMatthew G. Knepley     //  Get all Nodes in model, record coordinates in a correctly formatted array
725c1cad2e7SMatthew G. Knepley     //  Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array
726c1cad2e7SMatthew G. Knepley     //  We need to uniformly refine the initial geometry to guarantee a valid mesh
727c1cad2e7SMatthew G. Knepley 
728d5b43468SJose E. Roman     // Calculate cell and vertex sizes
7299566063dSJacob Faibussowitsch     PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
730c1cad2e7SMatthew G. Knepley 
7319566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&edgeMap));
7329566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&bodyIndexMap));
7339566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&bodyVertexMap));
7349566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&bodyEdgeMap));
7359566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&bodyEdgeGlobalMap));
7369566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&bodyFaceMap));
737c1cad2e7SMatthew G. Knepley 
738c1cad2e7SMatthew G. Knepley     for (b = 0; b < nbodies; ++b) {
739c1cad2e7SMatthew G. Knepley       ego           body = bodies[b];
740c1cad2e7SMatthew G. Knepley       int           Nf, Ne, Nv;
741c1cad2e7SMatthew G. Knepley       PetscHashIter BIiter, BViter, BEiter, BEGiter, BFiter, EMiter;
742c1cad2e7SMatthew G. Knepley       PetscBool     BIfound, BVfound, BEfound, BEGfound, BFfound, EMfound;
743c1cad2e7SMatthew G. Knepley 
7449566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyIndexMap, b, &BIiter, &BIfound));
7459566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound));
7469566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound));
7479566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound));
7489566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound));
749c1cad2e7SMatthew G. Knepley 
7509566063dSJacob Faibussowitsch       if (!BIfound) PetscCall(PetscHMapISet(bodyIndexMap, b, numFaces + numEdges + numVertices));
7519566063dSJacob Faibussowitsch       if (!BVfound) PetscCall(PetscHMapISet(bodyVertexMap, b, numVertices));
7529566063dSJacob Faibussowitsch       if (!BEfound) PetscCall(PetscHMapISet(bodyEdgeMap, b, numEdges));
7539566063dSJacob Faibussowitsch       if (!BEGfound) PetscCall(PetscHMapISet(bodyEdgeGlobalMap, b, edgeCntr));
7549566063dSJacob Faibussowitsch       if (!BFfound) PetscCall(PetscHMapISet(bodyFaceMap, b, numFaces));
755c1cad2e7SMatthew G. Knepley 
7569566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
7579566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
7589566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
759c1cad2e7SMatthew G. Knepley       EG_free(fobjs);
760c1cad2e7SMatthew G. Knepley       EG_free(eobjs);
761c1cad2e7SMatthew G. Knepley       EG_free(nobjs);
762c1cad2e7SMatthew G. Knepley 
763c1cad2e7SMatthew G. Knepley       // Remove DEGENERATE EDGES from Edge count
7649566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
765c1cad2e7SMatthew G. Knepley       int Netemp = 0;
766c1cad2e7SMatthew G. Knepley       for (int e = 0; e < Ne; ++e) {
767c1cad2e7SMatthew G. Knepley         ego edge = eobjs[e];
768c1cad2e7SMatthew G. Knepley         int eid;
769c1cad2e7SMatthew G. Knepley 
7709566063dSJacob Faibussowitsch         PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
7715f80ce2aSJacob Faibussowitsch         eid = EG_indexBodyTopo(body, edge);
772c1cad2e7SMatthew G. Knepley 
7739566063dSJacob Faibussowitsch         PetscCall(PetscHMapIFind(edgeMap, edgeCntr + eid - 1, &EMiter, &EMfound));
774c1cad2e7SMatthew G. Knepley         if (mtype == DEGENERATE) {
7759566063dSJacob Faibussowitsch           if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, -1));
7769371c9d4SSatish Balay         } else {
777c1cad2e7SMatthew G. Knepley           ++Netemp;
7789566063dSJacob Faibussowitsch           if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, Netemp));
779c1cad2e7SMatthew G. Knepley         }
780c1cad2e7SMatthew G. Knepley       }
781c1cad2e7SMatthew G. Knepley       EG_free(eobjs);
782c1cad2e7SMatthew G. Knepley 
783c1cad2e7SMatthew G. Knepley       // Determine Number of Cells
7849566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
785c1cad2e7SMatthew G. Knepley       for (int f = 0; f < Nf; ++f) {
786c1cad2e7SMatthew G. Knepley         ego face     = fobjs[f];
787c1cad2e7SMatthew G. Knepley         int edgeTemp = 0;
788c1cad2e7SMatthew G. Knepley 
7899566063dSJacob Faibussowitsch         PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs));
790c1cad2e7SMatthew G. Knepley         for (int e = 0; e < Ne; ++e) {
791c1cad2e7SMatthew G. Knepley           ego edge = eobjs[e];
792c1cad2e7SMatthew G. Knepley 
7939566063dSJacob Faibussowitsch           PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
794ad540459SPierre Jolivet           if (mtype != DEGENERATE) ++edgeTemp;
795c1cad2e7SMatthew G. Knepley         }
796c1cad2e7SMatthew G. Knepley         numCells += (2 * edgeTemp);
797c1cad2e7SMatthew G. Knepley         EG_free(eobjs);
798c1cad2e7SMatthew G. Knepley       }
799c1cad2e7SMatthew G. Knepley       EG_free(fobjs);
800c1cad2e7SMatthew G. Knepley 
801c1cad2e7SMatthew G. Knepley       numFaces += Nf;
802c1cad2e7SMatthew G. Knepley       numEdges += Netemp;
803c1cad2e7SMatthew G. Knepley       numVertices += Nv;
804c1cad2e7SMatthew G. Knepley       edgeCntr += Ne;
805c1cad2e7SMatthew G. Knepley     }
806c1cad2e7SMatthew G. Knepley 
807c1cad2e7SMatthew G. Knepley     // Set up basic DMPlex parameters
80835cb6cd3SPierre Jolivet     dim        = 2;                                 // Assumes 3D Models :: Need to handle 2D models in the future
80935cb6cd3SPierre Jolivet     cdim       = 3;                                 // Assumes 3D Models :: Need to update to handle 2D models in future
810c1cad2e7SMatthew G. Knepley     numCorners = 3;                                 // Split Faces into triangles
811c1cad2e7SMatthew G. Knepley     numPoints  = numVertices + numEdges + numFaces; // total number of coordinate points
812c1cad2e7SMatthew G. Knepley 
8139566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(numPoints * cdim, &coords, numCells * numCorners, &cells));
814c1cad2e7SMatthew G. Knepley 
815c1cad2e7SMatthew G. Knepley     // Get Vertex Coordinates and Set up Cells
816c1cad2e7SMatthew G. Knepley     for (b = 0; b < nbodies; ++b) {
817c1cad2e7SMatthew G. Knepley       ego           body = bodies[b];
818c1cad2e7SMatthew G. Knepley       int           Nf, Ne, Nv;
819c1cad2e7SMatthew G. Knepley       PetscInt      bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart;
820c1cad2e7SMatthew G. Knepley       PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter;
821c1cad2e7SMatthew G. Knepley       PetscBool     BVfound, BEfound, BEGfound, BFfound, EMfound;
822c1cad2e7SMatthew G. Knepley 
823c1cad2e7SMatthew G. Knepley       // Vertices on Current Body
8249566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs));
825c1cad2e7SMatthew G. Knepley 
8269566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound));
82728b400f6SJacob Faibussowitsch       PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyVertexMap", b);
8289566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart));
829c1cad2e7SMatthew G. Knepley 
830c1cad2e7SMatthew G. Knepley       for (int v = 0; v < Nv; ++v) {
831c1cad2e7SMatthew G. Knepley         ego    vertex = nobjs[v];
832c1cad2e7SMatthew G. Knepley         double limits[4];
833c1cad2e7SMatthew G. Knepley         int    id, dummy;
834c1cad2e7SMatthew G. Knepley 
8359566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses));
8365f80ce2aSJacob Faibussowitsch         id = EG_indexBodyTopo(body, vertex);
837c1cad2e7SMatthew G. Knepley 
838c1cad2e7SMatthew G. Knepley         coords[(bodyVertexIndexStart + id - 1) * cdim + 0] = limits[0];
839c1cad2e7SMatthew G. Knepley         coords[(bodyVertexIndexStart + id - 1) * cdim + 1] = limits[1];
840c1cad2e7SMatthew G. Knepley         coords[(bodyVertexIndexStart + id - 1) * cdim + 2] = limits[2];
841c1cad2e7SMatthew G. Knepley       }
842c1cad2e7SMatthew G. Knepley       EG_free(nobjs);
843c1cad2e7SMatthew G. Knepley 
844c1cad2e7SMatthew G. Knepley       // Edge Midpoint Vertices on Current Body
8459566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs));
846c1cad2e7SMatthew G. Knepley 
8479566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound));
84828b400f6SJacob Faibussowitsch       PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeMap", b);
8499566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart));
850c1cad2e7SMatthew G. Knepley 
8519566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound));
85228b400f6SJacob Faibussowitsch       PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeGlobalMap", b);
8539566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart));
854c1cad2e7SMatthew G. Knepley 
855c1cad2e7SMatthew G. Knepley       for (int e = 0; e < Ne; ++e) {
856c1cad2e7SMatthew G. Knepley         ego    edge = eobjs[e];
857c1cad2e7SMatthew G. Knepley         double range[2], avgt[1], cntrPnt[9];
858c1cad2e7SMatthew G. Knepley         int    eid, eOffset;
859c1cad2e7SMatthew G. Knepley         int    periodic;
860c1cad2e7SMatthew G. Knepley 
8619566063dSJacob Faibussowitsch         PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
862ad540459SPierre Jolivet         if (mtype == DEGENERATE) continue;
863c1cad2e7SMatthew G. Knepley 
8645f80ce2aSJacob Faibussowitsch         eid = EG_indexBodyTopo(body, edge);
865c1cad2e7SMatthew G. Knepley 
866c1cad2e7SMatthew G. Knepley         // get relative offset from globalEdgeID Vector
8679566063dSJacob Faibussowitsch         PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound));
86828b400f6SJacob Faibussowitsch         PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %d not found in edgeMap", bodyEdgeGlobalIndexStart + eid - 1);
8699566063dSJacob Faibussowitsch         PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset));
870c1cad2e7SMatthew G. Knepley 
8719566063dSJacob Faibussowitsch         PetscCall(EG_getRange(edge, range, &periodic));
872c1cad2e7SMatthew G. Knepley         avgt[0] = (range[0] + range[1]) / 2.;
873c1cad2e7SMatthew G. Knepley 
8749566063dSJacob Faibussowitsch         PetscCall(EG_evaluate(edge, avgt, cntrPnt));
875c1cad2e7SMatthew G. Knepley         coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 0] = cntrPnt[0];
876c1cad2e7SMatthew G. Knepley         coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 1] = cntrPnt[1];
877c1cad2e7SMatthew G. Knepley         coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 2] = cntrPnt[2];
878c1cad2e7SMatthew G. Knepley       }
879c1cad2e7SMatthew G. Knepley       EG_free(eobjs);
880c1cad2e7SMatthew G. Knepley 
881c1cad2e7SMatthew G. Knepley       // Face Midpoint Vertices on Current Body
8829566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
883c1cad2e7SMatthew G. Knepley 
8849566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound));
88528b400f6SJacob Faibussowitsch       PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b);
8869566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart));
887c1cad2e7SMatthew G. Knepley 
888c1cad2e7SMatthew G. Knepley       for (int f = 0; f < Nf; ++f) {
889c1cad2e7SMatthew G. Knepley         ego    face = fobjs[f];
890c1cad2e7SMatthew G. Knepley         double range[4], avgUV[2], cntrPnt[18];
891c1cad2e7SMatthew G. Knepley         int    peri, id;
892c1cad2e7SMatthew G. Knepley 
893c1cad2e7SMatthew G. Knepley         id = EG_indexBodyTopo(body, face);
8949566063dSJacob Faibussowitsch         PetscCall(EG_getRange(face, range, &peri));
895c1cad2e7SMatthew G. Knepley 
896c1cad2e7SMatthew G. Knepley         avgUV[0] = (range[0] + range[1]) / 2.;
897c1cad2e7SMatthew G. Knepley         avgUV[1] = (range[2] + range[3]) / 2.;
8989566063dSJacob Faibussowitsch         PetscCall(EG_evaluate(face, avgUV, cntrPnt));
899c1cad2e7SMatthew G. Knepley 
900c1cad2e7SMatthew G. Knepley         coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 0] = cntrPnt[0];
901c1cad2e7SMatthew G. Knepley         coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 1] = cntrPnt[1];
902c1cad2e7SMatthew G. Knepley         coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 2] = cntrPnt[2];
903c1cad2e7SMatthew G. Knepley       }
904c1cad2e7SMatthew G. Knepley       EG_free(fobjs);
905c1cad2e7SMatthew G. Knepley 
906c1cad2e7SMatthew G. Knepley       // Define Cells :: Note - This could be incorporated in the Face Midpoint Vertices Loop but was kept separate for clarity
9079566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
908c1cad2e7SMatthew G. Knepley       for (int f = 0; f < Nf; ++f) {
909c1cad2e7SMatthew G. Knepley         ego face = fobjs[f];
910c1cad2e7SMatthew G. Knepley         int fID, midFaceID, midPntID, startID, endID, Nl;
911c1cad2e7SMatthew G. Knepley 
9125f80ce2aSJacob Faibussowitsch         fID       = EG_indexBodyTopo(body, face);
913c1cad2e7SMatthew G. Knepley         midFaceID = numVertices + numEdges + bodyFaceIndexStart + fID - 1;
914c1cad2e7SMatthew G. Knepley         // Must Traverse Loop to ensure we have all necessary information like the sense (+/- 1) of the edges.
915c1cad2e7SMatthew G. Knepley         // TODO :: Only handles single loop faces (No holes). The choices for handling multiloop faces are:
916c1cad2e7SMatthew G. Knepley         //            1) Use the DMPlexCreateEGADSFromFile() with the -dm_plex_egads_with_tess = 1 option.
917c1cad2e7SMatthew G. Knepley         //               This will use a default EGADS tessellation as an initial surface mesh.
918d5b43468SJose E. Roman         //            2) Create the initial surface mesh via a 2D mesher :: Currently not available (?future?)
919c1cad2e7SMatthew G. Knepley         //               May I suggest the XXXX as a starting point?
920c1cad2e7SMatthew G. Knepley 
9219566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses));
922c1cad2e7SMatthew G. Knepley 
92308401ef6SPierre Jolivet         PetscCheck(Nl <= 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face has %d Loops. Can only handle Faces with 1 Loop. Please use --dm_plex_egads_with_tess = 1 Option", Nl);
924c1cad2e7SMatthew G. Knepley         for (int l = 0; l < Nl; ++l) {
925c1cad2e7SMatthew G. Knepley           ego loop = lobjs[l];
926c1cad2e7SMatthew G. Knepley 
9279566063dSJacob Faibussowitsch           PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses));
928c1cad2e7SMatthew G. Knepley           for (int e = 0; e < Ne; ++e) {
929c1cad2e7SMatthew G. Knepley             ego edge = eobjs[e];
930c1cad2e7SMatthew G. Knepley             int eid, eOffset;
931c1cad2e7SMatthew G. Knepley 
9329566063dSJacob Faibussowitsch             PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
933c1cad2e7SMatthew G. Knepley             eid = EG_indexBodyTopo(body, edge);
934ad540459SPierre Jolivet             if (mtype == DEGENERATE) continue;
935c1cad2e7SMatthew G. Knepley 
936c1cad2e7SMatthew G. Knepley             // get relative offset from globalEdgeID Vector
9379566063dSJacob Faibussowitsch             PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound));
93828b400f6SJacob Faibussowitsch             PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %d of Body %d not found in edgeMap. Global Edge ID :: %d", eid, b, bodyEdgeGlobalIndexStart + eid - 1);
9399566063dSJacob Faibussowitsch             PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset));
940c1cad2e7SMatthew G. Knepley 
941c1cad2e7SMatthew G. Knepley             midPntID = numVertices + bodyEdgeIndexStart + eOffset - 1;
942c1cad2e7SMatthew G. Knepley 
9439566063dSJacob Faibussowitsch             PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses));
944c1cad2e7SMatthew G. Knepley 
9459371c9d4SSatish Balay             if (eSenses[e] > 0) {
9469371c9d4SSatish Balay               startID = EG_indexBodyTopo(body, nobjs[0]);
9479371c9d4SSatish Balay               endID   = EG_indexBodyTopo(body, nobjs[1]);
9489371c9d4SSatish Balay             } else {
9499371c9d4SSatish Balay               startID = EG_indexBodyTopo(body, nobjs[1]);
9509371c9d4SSatish Balay               endID   = EG_indexBodyTopo(body, nobjs[0]);
9519371c9d4SSatish Balay             }
952c1cad2e7SMatthew G. Knepley 
953c1cad2e7SMatthew G. Knepley             // Define 2 Cells per Edge with correct orientation
954c1cad2e7SMatthew G. Knepley             cells[cellCntr * numCorners + 0] = midFaceID;
955c1cad2e7SMatthew G. Knepley             cells[cellCntr * numCorners + 1] = bodyVertexIndexStart + startID - 1;
956c1cad2e7SMatthew G. Knepley             cells[cellCntr * numCorners + 2] = midPntID;
957c1cad2e7SMatthew G. Knepley 
958c1cad2e7SMatthew G. Knepley             cells[cellCntr * numCorners + 3] = midFaceID;
959c1cad2e7SMatthew G. Knepley             cells[cellCntr * numCorners + 4] = midPntID;
960c1cad2e7SMatthew G. Knepley             cells[cellCntr * numCorners + 5] = bodyVertexIndexStart + endID - 1;
961c1cad2e7SMatthew G. Knepley 
962c1cad2e7SMatthew G. Knepley             cellCntr = cellCntr + 2;
963c1cad2e7SMatthew G. Knepley           }
964c1cad2e7SMatthew G. Knepley         }
965c1cad2e7SMatthew G. Knepley       }
966c1cad2e7SMatthew G. Knepley       EG_free(fobjs);
967c1cad2e7SMatthew G. Knepley     }
968c1cad2e7SMatthew G. Knepley   }
969c1cad2e7SMatthew G. Knepley 
970c1cad2e7SMatthew G. Knepley   // Generate DMPlex
9719566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm));
9729566063dSJacob Faibussowitsch   PetscCall(PetscFree2(coords, cells));
97363a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(dm, " Total Number of Unique Cells    = %" PetscInt_FMT " \n", numCells));
97463a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %" PetscInt_FMT " \n", numVertices));
975c1cad2e7SMatthew G. Knepley 
976c1cad2e7SMatthew G. Knepley   // Embed EGADS model in DM
977c1cad2e7SMatthew G. Knepley   {
978c1cad2e7SMatthew G. Knepley     PetscContainer modelObj, contextObj;
979c1cad2e7SMatthew G. Knepley 
9809566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj));
9819566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(modelObj, model));
9829566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj));
9839566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&modelObj));
984c1cad2e7SMatthew G. Knepley 
9859566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj));
9869566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(contextObj, context));
987*49abdd8aSBarry Smith     PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSDestroy_Private));
9889566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj));
9899566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&contextObj));
990c1cad2e7SMatthew G. Knepley   }
991c1cad2e7SMatthew G. Knepley   // Label points
992c1cad2e7SMatthew G. Knepley   PetscInt nStart, nEnd;
993c1cad2e7SMatthew G. Knepley 
9949566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Body ID"));
9959566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
9969566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Face ID"));
9979566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
9989566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Edge ID"));
9999566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
10009566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Vertex ID"));
10019566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
1002c1cad2e7SMatthew G. Knepley 
10039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd));
1004c1cad2e7SMatthew G. Knepley 
1005c1cad2e7SMatthew G. Knepley   cellCntr = 0;
1006c1cad2e7SMatthew G. Knepley   for (b = 0; b < nbodies; ++b) {
1007c1cad2e7SMatthew G. Knepley     ego           body = bodies[b];
1008c1cad2e7SMatthew G. Knepley     int           Nv, Ne, Nf;
1009c1cad2e7SMatthew G. Knepley     PetscInt      bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart;
1010c1cad2e7SMatthew G. Knepley     PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter;
1011c1cad2e7SMatthew G. Knepley     PetscBool     BVfound, BEfound, BEGfound, BFfound, EMfound;
1012c1cad2e7SMatthew G. Knepley 
10139566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound));
101428b400f6SJacob Faibussowitsch     PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyVertexMap", b);
10159566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart));
1016c1cad2e7SMatthew G. Knepley 
10179566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound));
101828b400f6SJacob Faibussowitsch     PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeMap", b);
10199566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart));
1020c1cad2e7SMatthew G. Knepley 
10219566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound));
102228b400f6SJacob Faibussowitsch     PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b);
10239566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart));
1024c1cad2e7SMatthew G. Knepley 
10259566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound));
102628b400f6SJacob Faibussowitsch     PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeGlobalMap", b);
10279566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart));
1028c1cad2e7SMatthew G. Knepley 
10299566063dSJacob Faibussowitsch     PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
1030c1cad2e7SMatthew G. Knepley     for (int f = 0; f < Nf; ++f) {
1031c1cad2e7SMatthew G. Knepley       ego face = fobjs[f];
1032c1cad2e7SMatthew G. Knepley       int fID, Nl;
1033c1cad2e7SMatthew G. Knepley 
10345f80ce2aSJacob Faibussowitsch       fID = EG_indexBodyTopo(body, face);
1035c1cad2e7SMatthew G. Knepley 
10369566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, face, LOOP, &Nl, &lobjs));
1037c1cad2e7SMatthew G. Knepley       for (int l = 0; l < Nl; ++l) {
1038c1cad2e7SMatthew G. Knepley         ego loop = lobjs[l];
1039c1cad2e7SMatthew G. Knepley         int lid;
1040c1cad2e7SMatthew G. Knepley 
10415f80ce2aSJacob Faibussowitsch         lid = EG_indexBodyTopo(body, loop);
104208401ef6SPierre Jolivet         PetscCheck(Nl <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf);
1043c1cad2e7SMatthew G. Knepley 
10449566063dSJacob Faibussowitsch         PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses));
1045c1cad2e7SMatthew G. Knepley         for (int e = 0; e < Ne; ++e) {
1046c1cad2e7SMatthew G. Knepley           ego edge = eobjs[e];
1047c1cad2e7SMatthew G. Knepley           int eid, eOffset;
1048c1cad2e7SMatthew G. Knepley 
1049c1cad2e7SMatthew G. Knepley           // Skip DEGENERATE Edges
10509566063dSJacob Faibussowitsch           PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next));
1051ad540459SPierre Jolivet           if (mtype == DEGENERATE) continue;
10525f80ce2aSJacob Faibussowitsch           eid = EG_indexBodyTopo(body, edge);
1053c1cad2e7SMatthew G. Knepley 
1054c1cad2e7SMatthew G. Knepley           // get relative offset from globalEdgeID Vector
10559566063dSJacob Faibussowitsch           PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound));
105628b400f6SJacob Faibussowitsch           PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %d of Body %d not found in edgeMap. Global Edge ID :: %d", eid, b, bodyEdgeGlobalIndexStart + eid - 1);
10579566063dSJacob Faibussowitsch           PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset));
1058c1cad2e7SMatthew G. Knepley 
10599566063dSJacob Faibussowitsch           PetscCall(EG_getBodyTopos(body, edge, NODE, &Nv, &nobjs));
1060c1cad2e7SMatthew G. Knepley           for (int v = 0; v < Nv; ++v) {
1061c1cad2e7SMatthew G. Knepley             ego vertex = nobjs[v];
1062c1cad2e7SMatthew G. Knepley             int vID;
1063c1cad2e7SMatthew G. Knepley 
10645f80ce2aSJacob Faibussowitsch             vID = EG_indexBodyTopo(body, vertex);
10659566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(bodyLabel, nStart + bodyVertexIndexStart + vID - 1, b));
10669566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(vertexLabel, nStart + bodyVertexIndexStart + vID - 1, vID));
1067c1cad2e7SMatthew G. Knepley           }
1068c1cad2e7SMatthew G. Knepley           EG_free(nobjs);
1069c1cad2e7SMatthew G. Knepley 
10709566063dSJacob Faibussowitsch           PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, b));
10719566063dSJacob Faibussowitsch           PetscCall(DMLabelSetValue(edgeLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, eid));
1072c1cad2e7SMatthew G. Knepley 
1073c1cad2e7SMatthew G. Knepley           // Define Cell faces
1074c1cad2e7SMatthew G. Knepley           for (int jj = 0; jj < 2; ++jj) {
10759566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(bodyLabel, cellCntr, b));
10769566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(faceLabel, cellCntr, fID));
10779566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cellCntr, &cone));
1078c1cad2e7SMatthew G. Knepley 
10799566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(bodyLabel, cone[0], b));
10809566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(faceLabel, cone[0], fID));
1081c1cad2e7SMatthew G. Knepley 
10829566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(bodyLabel, cone[1], b));
10839566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(edgeLabel, cone[1], eid));
1084c1cad2e7SMatthew G. Knepley 
10859566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(bodyLabel, cone[2], b));
10869566063dSJacob Faibussowitsch             PetscCall(DMLabelSetValue(faceLabel, cone[2], fID));
1087c1cad2e7SMatthew G. Knepley 
1088c1cad2e7SMatthew G. Knepley             cellCntr = cellCntr + 1;
1089c1cad2e7SMatthew G. Knepley           }
1090c1cad2e7SMatthew G. Knepley         }
1091c1cad2e7SMatthew G. Knepley       }
1092c1cad2e7SMatthew G. Knepley       EG_free(lobjs);
1093c1cad2e7SMatthew G. Knepley 
10949566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, b));
10959566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(faceLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, fID));
1096c1cad2e7SMatthew G. Knepley     }
1097c1cad2e7SMatthew G. Knepley     EG_free(fobjs);
1098c1cad2e7SMatthew G. Knepley   }
1099c1cad2e7SMatthew G. Knepley 
11009566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&edgeMap));
11019566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&bodyIndexMap));
11029566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&bodyVertexMap));
11039566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&bodyEdgeMap));
11049566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&bodyEdgeGlobalMap));
11059566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&bodyFaceMap));
1106c1cad2e7SMatthew G. Knepley 
1107c1cad2e7SMatthew G. Knepley   *newdm = dm;
11083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1109c1cad2e7SMatthew G. Knepley }
1110c1cad2e7SMatthew G. Knepley 
1111d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateEGADS_Tess_Internal(MPI_Comm comm, ego context, ego model, DM *newdm)
1112d71ae5a4SJacob Faibussowitsch {
1113c1cad2e7SMatthew G. Knepley   DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel;
1114c1cad2e7SMatthew G. Knepley   /* EGADSLite variables */
1115c1cad2e7SMatthew G. Knepley   ego    geom, *bodies, *fobjs;
1116c1cad2e7SMatthew G. Knepley   int    b, oclass, mtype, nbodies, *senses;
1117c1cad2e7SMatthew G. Knepley   int    totalNumTris = 0, totalNumPoints = 0;
1118c1cad2e7SMatthew G. Knepley   double boundBox[6] = {0., 0., 0., 0., 0., 0.}, tessSize;
1119c1cad2e7SMatthew G. Knepley   /* PETSc variables */
1120c1cad2e7SMatthew G. Knepley   DM              dm;
1121c1cad2e7SMatthew G. Knepley   PetscHMapI      pointIndexStartMap = NULL, triIndexStartMap = NULL, pTypeLabelMap = NULL, pIndexLabelMap = NULL;
1122c1cad2e7SMatthew G. Knepley   PetscHMapI      pBodyIndexLabelMap = NULL, triFaceIDLabelMap = NULL, triBodyIDLabelMap = NULL;
1123c1cad2e7SMatthew G. Knepley   PetscInt        dim = -1, cdim = -1, numCorners = 0, counter = 0;
1124c1cad2e7SMatthew G. Knepley   PetscInt       *cells  = NULL;
1125c1cad2e7SMatthew G. Knepley   const PetscInt *cone   = NULL;
1126c1cad2e7SMatthew G. Knepley   PetscReal      *coords = NULL;
1127c1cad2e7SMatthew G. Knepley   PetscMPIInt     rank;
1128c1cad2e7SMatthew G. Knepley 
1129c1cad2e7SMatthew G. Knepley   PetscFunctionBeginUser;
11309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1131c5853193SPierre Jolivet   if (rank == 0) {
1132c1cad2e7SMatthew G. Knepley     // ---------------------------------------------------------------------------------------------------
1133c1cad2e7SMatthew G. Knepley     // Generate Petsc Plex from EGADSlite created Tessellation of geometry
1134c1cad2e7SMatthew G. Knepley     // ---------------------------------------------------------------------------------------------------
1135c1cad2e7SMatthew G. Knepley 
1136d5b43468SJose E. Roman     // Calculate cell and vertex sizes
11379566063dSJacob Faibussowitsch     PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses));
1138c1cad2e7SMatthew G. Knepley 
11399566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&pointIndexStartMap));
11409566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&triIndexStartMap));
11419566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&pTypeLabelMap));
11429566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&pIndexLabelMap));
11439566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&pBodyIndexLabelMap));
11449566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&triFaceIDLabelMap));
11459566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&triBodyIDLabelMap));
1146c1cad2e7SMatthew G. Knepley 
1147c1cad2e7SMatthew G. Knepley     /* Create Tessellation of Bodies */
1148c1cad2e7SMatthew G. Knepley     ego tessArray[nbodies];
1149c1cad2e7SMatthew G. Knepley 
1150c1cad2e7SMatthew G. Knepley     for (b = 0; b < nbodies; ++b) {
1151c1cad2e7SMatthew G. Knepley       ego           body      = bodies[b];
1152c1cad2e7SMatthew G. Knepley       double        params[3] = {0.0, 0.0, 0.0}; // Parameters for Tessellation
1153c1cad2e7SMatthew G. Knepley       int           Nf, bodyNumPoints = 0, bodyNumTris = 0;
1154c1cad2e7SMatthew G. Knepley       PetscHashIter PISiter, TISiter;
1155c1cad2e7SMatthew G. Knepley       PetscBool     PISfound, TISfound;
1156c1cad2e7SMatthew G. Knepley 
1157c1cad2e7SMatthew G. Knepley       /* Store Start Index for each Body's Point and Tris */
11589566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound));
11599566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(triIndexStartMap, b, &TISiter, &TISfound));
1160c1cad2e7SMatthew G. Knepley 
11619566063dSJacob Faibussowitsch       if (!PISfound) PetscCall(PetscHMapISet(pointIndexStartMap, b, totalNumPoints));
11629566063dSJacob Faibussowitsch       if (!TISfound) PetscCall(PetscHMapISet(triIndexStartMap, b, totalNumTris));
1163c1cad2e7SMatthew G. Knepley 
1164c1cad2e7SMatthew G. Knepley       /* Calculate Tessellation parameters based on Bounding Box */
1165c1cad2e7SMatthew G. Knepley       /* Get Bounding Box Dimensions of the BODY */
11669566063dSJacob Faibussowitsch       PetscCall(EG_getBoundingBox(body, boundBox));
1167c1cad2e7SMatthew G. Knepley       tessSize = boundBox[3] - boundBox[0];
1168c1cad2e7SMatthew G. Knepley       if (tessSize < boundBox[4] - boundBox[1]) tessSize = boundBox[4] - boundBox[1];
1169c1cad2e7SMatthew G. Knepley       if (tessSize < boundBox[5] - boundBox[2]) tessSize = boundBox[5] - boundBox[2];
1170c1cad2e7SMatthew G. Knepley 
1171c1cad2e7SMatthew G. Knepley       // TODO :: May want to give users tessellation parameter options //
1172c1cad2e7SMatthew G. Knepley       params[0] = 0.0250 * tessSize;
1173c1cad2e7SMatthew G. Knepley       params[1] = 0.0075 * tessSize;
1174c1cad2e7SMatthew G. Knepley       params[2] = 15.0;
1175c1cad2e7SMatthew G. Knepley 
11769566063dSJacob Faibussowitsch       PetscCall(EG_makeTessBody(body, params, &tessArray[b]));
1177c1cad2e7SMatthew G. Knepley 
11789566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
1179c1cad2e7SMatthew G. Knepley 
1180c1cad2e7SMatthew G. Knepley       for (int f = 0; f < Nf; ++f) {
1181c1cad2e7SMatthew G. Knepley         ego           face = fobjs[f];
1182c1cad2e7SMatthew G. Knepley         int           len, fID, ntris;
1183c1cad2e7SMatthew G. Knepley         const int    *ptype, *pindex, *ptris, *ptric;
1184c1cad2e7SMatthew G. Knepley         const double *pxyz, *puv;
1185c1cad2e7SMatthew G. Knepley 
1186c1cad2e7SMatthew G. Knepley         // Get Face ID //
1187c1cad2e7SMatthew G. Knepley         fID = EG_indexBodyTopo(body, face);
1188c1cad2e7SMatthew G. Knepley 
1189c1cad2e7SMatthew G. Knepley         // Checkout the Surface Tessellation //
11909566063dSJacob Faibussowitsch         PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric));
1191c1cad2e7SMatthew G. Knepley 
1192c1cad2e7SMatthew G. Knepley         // Determine total number of triangle cells in the tessellation //
1193c1cad2e7SMatthew G. Knepley         bodyNumTris += (int)ntris;
1194c1cad2e7SMatthew G. Knepley 
1195c1cad2e7SMatthew G. Knepley         // Check out the point index and coordinate //
1196c1cad2e7SMatthew G. Knepley         for (int p = 0; p < len; ++p) {
1197c1cad2e7SMatthew G. Knepley           int global;
1198c1cad2e7SMatthew G. Knepley 
11999566063dSJacob Faibussowitsch           PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global));
1200c1cad2e7SMatthew G. Knepley 
1201c1cad2e7SMatthew G. Knepley           // Determine the total number of points in the tessellation //
1202c1cad2e7SMatthew G. Knepley           bodyNumPoints = PetscMax(bodyNumPoints, global);
1203c1cad2e7SMatthew G. Knepley         }
1204c1cad2e7SMatthew G. Knepley       }
1205c1cad2e7SMatthew G. Knepley       EG_free(fobjs);
1206c1cad2e7SMatthew G. Knepley 
1207c1cad2e7SMatthew G. Knepley       totalNumPoints += bodyNumPoints;
1208c1cad2e7SMatthew G. Knepley       totalNumTris += bodyNumTris;
1209c1cad2e7SMatthew G. Knepley     }
1210c5853193SPierre Jolivet     //}  - Original End of (rank == 0)
1211c1cad2e7SMatthew G. Knepley 
1212c1cad2e7SMatthew G. Knepley     dim        = 2;
1213c1cad2e7SMatthew G. Knepley     cdim       = 3;
1214c1cad2e7SMatthew G. Knepley     numCorners = 3;
1215c1cad2e7SMatthew G. Knepley     //PetscInt counter = 0;
1216c1cad2e7SMatthew G. Knepley 
1217c1cad2e7SMatthew G. Knepley     /* NEED TO DEFINE MATRICES/VECTORS TO STORE GEOM REFERENCE DATA   */
1218c1cad2e7SMatthew G. Knepley     /* Fill in below and use to define DMLabels after DMPlex creation */
12199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(totalNumPoints * cdim, &coords, totalNumTris * numCorners, &cells));
1220c1cad2e7SMatthew G. Knepley 
1221c1cad2e7SMatthew G. Knepley     for (b = 0; b < nbodies; ++b) {
1222c1cad2e7SMatthew G. Knepley       ego           body = bodies[b];
1223c1cad2e7SMatthew G. Knepley       int           Nf;
1224c1cad2e7SMatthew G. Knepley       PetscInt      pointIndexStart;
1225c1cad2e7SMatthew G. Knepley       PetscHashIter PISiter;
1226c1cad2e7SMatthew G. Knepley       PetscBool     PISfound;
1227c1cad2e7SMatthew G. Knepley 
12289566063dSJacob Faibussowitsch       PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound));
122928b400f6SJacob Faibussowitsch       PetscCheck(PISfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in pointIndexStartMap", b);
12309566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(pointIndexStartMap, b, &pointIndexStart));
1231c1cad2e7SMatthew G. Knepley 
12329566063dSJacob Faibussowitsch       PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs));
1233c1cad2e7SMatthew G. Knepley 
1234c1cad2e7SMatthew G. Knepley       for (int f = 0; f < Nf; ++f) {
1235c1cad2e7SMatthew G. Knepley         /* Get Face Object */
1236c1cad2e7SMatthew G. Knepley         ego           face = fobjs[f];
1237c1cad2e7SMatthew G. Knepley         int           len, fID, ntris;
1238c1cad2e7SMatthew G. Knepley         const int    *ptype, *pindex, *ptris, *ptric;
1239c1cad2e7SMatthew G. Knepley         const double *pxyz, *puv;
1240c1cad2e7SMatthew G. Knepley 
1241c1cad2e7SMatthew G. Knepley         /* Get Face ID */
1242c1cad2e7SMatthew G. Knepley         fID = EG_indexBodyTopo(body, face);
1243c1cad2e7SMatthew G. Knepley 
1244c1cad2e7SMatthew G. Knepley         /* Checkout the Surface Tessellation */
12459566063dSJacob Faibussowitsch         PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric));
1246c1cad2e7SMatthew G. Knepley 
1247c1cad2e7SMatthew G. Knepley         /* Check out the point index and coordinate */
1248c1cad2e7SMatthew G. Knepley         for (int p = 0; p < len; ++p) {
1249c1cad2e7SMatthew G. Knepley           int           global;
1250c1cad2e7SMatthew G. Knepley           PetscHashIter PTLiter, PILiter, PBLiter;
1251c1cad2e7SMatthew G. Knepley           PetscBool     PTLfound, PILfound, PBLfound;
1252c1cad2e7SMatthew G. Knepley 
12539566063dSJacob Faibussowitsch           PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global));
1254c1cad2e7SMatthew G. Knepley 
1255c1cad2e7SMatthew G. Knepley           /* Set the coordinates array for DAG */
1256c1cad2e7SMatthew G. Knepley           coords[((global - 1 + pointIndexStart) * 3) + 0] = pxyz[(p * 3) + 0];
1257c1cad2e7SMatthew G. Knepley           coords[((global - 1 + pointIndexStart) * 3) + 1] = pxyz[(p * 3) + 1];
1258c1cad2e7SMatthew G. Knepley           coords[((global - 1 + pointIndexStart) * 3) + 2] = pxyz[(p * 3) + 2];
1259c1cad2e7SMatthew G. Knepley 
1260c1cad2e7SMatthew G. Knepley           /* Store Geometry Label Information for DMLabel assignment later */
12619566063dSJacob Faibussowitsch           PetscCall(PetscHMapIFind(pTypeLabelMap, global - 1 + pointIndexStart, &PTLiter, &PTLfound));
12629566063dSJacob Faibussowitsch           PetscCall(PetscHMapIFind(pIndexLabelMap, global - 1 + pointIndexStart, &PILiter, &PILfound));
12639566063dSJacob Faibussowitsch           PetscCall(PetscHMapIFind(pBodyIndexLabelMap, global - 1 + pointIndexStart, &PBLiter, &PBLfound));
1264c1cad2e7SMatthew G. Knepley 
12659566063dSJacob Faibussowitsch           if (!PTLfound) PetscCall(PetscHMapISet(pTypeLabelMap, global - 1 + pointIndexStart, ptype[p]));
12669566063dSJacob Faibussowitsch           if (!PILfound) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, pindex[p]));
12679566063dSJacob Faibussowitsch           if (!PBLfound) PetscCall(PetscHMapISet(pBodyIndexLabelMap, global - 1 + pointIndexStart, b));
1268c1cad2e7SMatthew G. Knepley 
12699566063dSJacob Faibussowitsch           if (ptype[p] < 0) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, fID));
1270c1cad2e7SMatthew G. Knepley         }
1271c1cad2e7SMatthew G. Knepley 
1272c1cad2e7SMatthew G. Knepley         for (int t = 0; t < (int)ntris; ++t) {
1273c1cad2e7SMatthew G. Knepley           int           global, globalA, globalB;
1274c1cad2e7SMatthew G. Knepley           PetscHashIter TFLiter, TBLiter;
1275c1cad2e7SMatthew G. Knepley           PetscBool     TFLfound, TBLfound;
1276c1cad2e7SMatthew G. Knepley 
12779566063dSJacob Faibussowitsch           PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global));
1278c1cad2e7SMatthew G. Knepley           cells[(counter * 3) + 0] = global - 1 + pointIndexStart;
1279c1cad2e7SMatthew G. Knepley 
12809566063dSJacob Faibussowitsch           PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA));
1281c1cad2e7SMatthew G. Knepley           cells[(counter * 3) + 1] = globalA - 1 + pointIndexStart;
1282c1cad2e7SMatthew G. Knepley 
12839566063dSJacob Faibussowitsch           PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB));
1284c1cad2e7SMatthew G. Knepley           cells[(counter * 3) + 2] = globalB - 1 + pointIndexStart;
1285c1cad2e7SMatthew G. Knepley 
12869566063dSJacob Faibussowitsch           PetscCall(PetscHMapIFind(triFaceIDLabelMap, counter, &TFLiter, &TFLfound));
12879566063dSJacob Faibussowitsch           PetscCall(PetscHMapIFind(triBodyIDLabelMap, counter, &TBLiter, &TBLfound));
1288c1cad2e7SMatthew G. Knepley 
12899566063dSJacob Faibussowitsch           if (!TFLfound) PetscCall(PetscHMapISet(triFaceIDLabelMap, counter, fID));
12909566063dSJacob Faibussowitsch           if (!TBLfound) PetscCall(PetscHMapISet(triBodyIDLabelMap, counter, b));
1291c1cad2e7SMatthew G. Knepley 
1292c1cad2e7SMatthew G. Knepley           counter += 1;
1293c1cad2e7SMatthew G. Knepley         }
1294c1cad2e7SMatthew G. Knepley       }
1295c1cad2e7SMatthew G. Knepley       EG_free(fobjs);
1296c1cad2e7SMatthew G. Knepley     }
1297c1cad2e7SMatthew G. Knepley   }
1298c1cad2e7SMatthew G. Knepley 
1299c1cad2e7SMatthew G. Knepley   //Build DMPlex
13009566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, totalNumTris, totalNumPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm));
13019566063dSJacob Faibussowitsch   PetscCall(PetscFree2(coords, cells));
1302c1cad2e7SMatthew G. Knepley 
1303c1cad2e7SMatthew G. Knepley   // Embed EGADS model in DM
1304c1cad2e7SMatthew G. Knepley   {
1305c1cad2e7SMatthew G. Knepley     PetscContainer modelObj, contextObj;
1306c1cad2e7SMatthew G. Knepley 
13079566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj));
13089566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(modelObj, model));
13099566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj));
13109566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&modelObj));
1311c1cad2e7SMatthew G. Knepley 
13129566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj));
13139566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(contextObj, context));
1314*49abdd8aSBarry Smith     PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSDestroy_Private));
13159566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj));
13169566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&contextObj));
1317c1cad2e7SMatthew G. Knepley   }
1318c1cad2e7SMatthew G. Knepley 
1319c1cad2e7SMatthew G. Knepley   // Label Points
13209566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Body ID"));
13219566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
13229566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Face ID"));
13239566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
13249566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Edge ID"));
13259566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
13269566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "EGADS Vertex ID"));
13279566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
1328c1cad2e7SMatthew G. Knepley 
1329c1cad2e7SMatthew G. Knepley   /* Get Number of DAG Nodes at each level */
1330c1cad2e7SMatthew G. Knepley   int fStart, fEnd, eStart, eEnd, nStart, nEnd;
1331c1cad2e7SMatthew G. Knepley 
13329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &fStart, &fEnd));
13339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 1, &eStart, &eEnd));
13349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd));
1335c1cad2e7SMatthew G. Knepley 
1336c1cad2e7SMatthew G. Knepley   /* Set DMLabels for NODES */
1337c1cad2e7SMatthew G. Knepley   for (int n = nStart; n < nEnd; ++n) {
1338c1cad2e7SMatthew G. Knepley     int           pTypeVal, pIndexVal, pBodyVal;
1339c1cad2e7SMatthew G. Knepley     PetscHashIter PTLiter, PILiter, PBLiter;
1340c1cad2e7SMatthew G. Knepley     PetscBool     PTLfound, PILfound, PBLfound;
1341c1cad2e7SMatthew G. Knepley 
1342c1cad2e7SMatthew G. Knepley     //Converted to Hash Tables
13439566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(pTypeLabelMap, n - nStart, &PTLiter, &PTLfound));
134428b400f6SJacob Faibussowitsch     PetscCheck(PTLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in pTypeLabelMap", n);
13459566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(pTypeLabelMap, n - nStart, &pTypeVal));
1346c1cad2e7SMatthew G. Knepley 
13479566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(pIndexLabelMap, n - nStart, &PILiter, &PILfound));
134828b400f6SJacob Faibussowitsch     PetscCheck(PILfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in pIndexLabelMap", n);
13499566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(pIndexLabelMap, n - nStart, &pIndexVal));
1350c1cad2e7SMatthew G. Knepley 
13519566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(pBodyIndexLabelMap, n - nStart, &PBLiter, &PBLfound));
135228b400f6SJacob Faibussowitsch     PetscCheck(PBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in pBodyLabelMap", n);
13539566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(pBodyIndexLabelMap, n - nStart, &pBodyVal));
1354c1cad2e7SMatthew G. Knepley 
13559566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(bodyLabel, n, pBodyVal));
13569566063dSJacob Faibussowitsch     if (pTypeVal == 0) PetscCall(DMLabelSetValue(vertexLabel, n, pIndexVal));
13579566063dSJacob Faibussowitsch     if (pTypeVal > 0) PetscCall(DMLabelSetValue(edgeLabel, n, pIndexVal));
13589566063dSJacob Faibussowitsch     if (pTypeVal < 0) PetscCall(DMLabelSetValue(faceLabel, n, pIndexVal));
1359c1cad2e7SMatthew G. Knepley   }
1360c1cad2e7SMatthew G. Knepley 
1361c1cad2e7SMatthew G. Knepley   /* Set DMLabels for Edges - Based on the DMLabels of the EDGE's NODES */
1362c1cad2e7SMatthew G. Knepley   for (int e = eStart; e < eEnd; ++e) {
1363c1cad2e7SMatthew G. Knepley     int bodyID_0, vertexID_0, vertexID_1, edgeID_0, edgeID_1, faceID_0, faceID_1;
1364c1cad2e7SMatthew G. Knepley 
13659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, e, &cone));
13669566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(bodyLabel, cone[0], &bodyID_0)); // Do I need to check the other end?
13679566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(vertexLabel, cone[0], &vertexID_0));
13689566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(vertexLabel, cone[1], &vertexID_1));
13699566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(edgeLabel, cone[0], &edgeID_0));
13709566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(edgeLabel, cone[1], &edgeID_1));
13719566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(faceLabel, cone[0], &faceID_0));
13729566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(faceLabel, cone[1], &faceID_1));
1373c1cad2e7SMatthew G. Knepley 
13749566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(bodyLabel, e, bodyID_0));
1375c1cad2e7SMatthew G. Knepley 
13769566063dSJacob Faibussowitsch     if (edgeID_0 == edgeID_1) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0));
13779566063dSJacob Faibussowitsch     else if (vertexID_0 > 0 && edgeID_1 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_1));
13789566063dSJacob Faibussowitsch     else if (vertexID_1 > 0 && edgeID_0 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0));
1379c1cad2e7SMatthew G. Knepley     else { /* Do Nothing */ }
1380c1cad2e7SMatthew G. Knepley   }
1381c1cad2e7SMatthew G. Knepley 
1382c1cad2e7SMatthew G. Knepley   /* Set DMLabels for Cells */
1383c1cad2e7SMatthew G. Knepley   for (int f = fStart; f < fEnd; ++f) {
1384c1cad2e7SMatthew G. Knepley     int           edgeID_0;
1385c1cad2e7SMatthew G. Knepley     PetscInt      triBodyVal, triFaceVal;
1386c1cad2e7SMatthew G. Knepley     PetscHashIter TFLiter, TBLiter;
1387c1cad2e7SMatthew G. Knepley     PetscBool     TFLfound, TBLfound;
1388c1cad2e7SMatthew G. Knepley 
1389c1cad2e7SMatthew G. Knepley     // Convert to Hash Table
13909566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(triFaceIDLabelMap, f - fStart, &TFLiter, &TFLfound));
139128b400f6SJacob Faibussowitsch     PetscCheck(TFLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in triFaceIDLabelMap", f);
13929566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(triFaceIDLabelMap, f - fStart, &triFaceVal));
1393c1cad2e7SMatthew G. Knepley 
13949566063dSJacob Faibussowitsch     PetscCall(PetscHMapIFind(triBodyIDLabelMap, f - fStart, &TBLiter, &TBLfound));
139528b400f6SJacob Faibussowitsch     PetscCheck(TBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in triBodyIDLabelMap", f);
13969566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(triBodyIDLabelMap, f - fStart, &triBodyVal));
1397c1cad2e7SMatthew G. Knepley 
13989566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(bodyLabel, f, triBodyVal));
13999566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(faceLabel, f, triFaceVal));
1400c1cad2e7SMatthew G. Knepley 
1401c1cad2e7SMatthew G. Knepley     /* Finish Labeling previously unlabeled DMPlex Edges - Assumes Triangular Cell (3 Edges Max) */
14029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, f, &cone));
1403c1cad2e7SMatthew G. Knepley 
1404c1cad2e7SMatthew G. Knepley     for (int jj = 0; jj < 3; ++jj) {
14059566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(edgeLabel, cone[jj], &edgeID_0));
1406c1cad2e7SMatthew G. Knepley 
1407c1cad2e7SMatthew G. Knepley       if (edgeID_0 < 0) {
14089566063dSJacob Faibussowitsch         PetscCall(DMLabelSetValue(bodyLabel, cone[jj], triBodyVal));
14099566063dSJacob Faibussowitsch         PetscCall(DMLabelSetValue(faceLabel, cone[jj], triFaceVal));
1410c1cad2e7SMatthew G. Knepley       }
1411c1cad2e7SMatthew G. Knepley     }
1412c1cad2e7SMatthew G. Knepley   }
1413c1cad2e7SMatthew G. Knepley 
1414c1cad2e7SMatthew G. Knepley   *newdm = dm;
14153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1416c1cad2e7SMatthew G. Knepley }
14177bee2925SMatthew Knepley #endif
14187bee2925SMatthew Knepley 
1419c1cad2e7SMatthew G. Knepley /*@
142020f4b53cSBarry Smith   DMPlexInflateToGeomModel - Snaps the vertex coordinates of a `DMPLEX` object representing the mesh to its geometry if some vertices depart from the model.
142120f4b53cSBarry Smith   This usually happens with non-conforming refinement.
1422c1cad2e7SMatthew G. Knepley 
142320f4b53cSBarry Smith   Collective
1424c1cad2e7SMatthew G. Knepley 
1425c1cad2e7SMatthew G. Knepley   Input Parameter:
1426a1cb98faSBarry Smith . dm - The uninflated `DM` object representing the mesh
1427c1cad2e7SMatthew G. Knepley 
1428c1cad2e7SMatthew G. Knepley   Level: intermediate
1429c1cad2e7SMatthew G. Knepley 
14301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`
1431c1cad2e7SMatthew G. Knepley @*/
1432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInflateToGeomModel(DM dm)
1433d71ae5a4SJacob Faibussowitsch {
1434c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS)
1435c1cad2e7SMatthew G. Knepley   /* EGADS Variables */
1436c1cad2e7SMatthew G. Knepley   ego    model, geom, body, face, edge;
1437c1cad2e7SMatthew G. Knepley   ego   *bodies;
1438c1cad2e7SMatthew G. Knepley   int    Nb, oclass, mtype, *senses;
1439c1cad2e7SMatthew G. Knepley   double result[3];
1440c1cad2e7SMatthew G. Knepley   /* PETSc Variables */
1441c1cad2e7SMatthew G. Knepley   DM             cdm;
1442c1cad2e7SMatthew G. Knepley   PetscContainer modelObj;
1443c1cad2e7SMatthew G. Knepley   DMLabel        bodyLabel, faceLabel, edgeLabel, vertexLabel;
1444c1cad2e7SMatthew G. Knepley   Vec            coordinates;
1445c1cad2e7SMatthew G. Knepley   PetscScalar   *coords;
1446c1cad2e7SMatthew G. Knepley   PetscInt       bodyID, faceID, edgeID, vertexID;
1447c1cad2e7SMatthew G. Knepley   PetscInt       cdim, d, vStart, vEnd, v;
1448c1cad2e7SMatthew G. Knepley #endif
1449c1cad2e7SMatthew G. Knepley 
1450c1cad2e7SMatthew G. Knepley   PetscFunctionBegin;
1451c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS)
14529566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj));
14533ba16761SJacob Faibussowitsch   if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS);
14549566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
14559566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
14569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
14579566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel));
14589566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel));
14599566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel));
14609566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel));
1461c1cad2e7SMatthew G. Knepley 
14629566063dSJacob Faibussowitsch   PetscCall(PetscContainerGetPointer(modelObj, (void **)&model));
14639566063dSJacob Faibussowitsch   PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses));
1464c1cad2e7SMatthew G. Knepley 
14659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
14669566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
1467c1cad2e7SMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
1468c1cad2e7SMatthew G. Knepley     PetscScalar *vcoords;
1469c1cad2e7SMatthew G. Knepley 
14709566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID));
14719566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(faceLabel, v, &faceID));
14729566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID));
14739566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID));
1474c1cad2e7SMatthew G. Knepley 
147563a3b9bcSJacob Faibussowitsch     PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %d)", bodyID, Nb);
1476c1cad2e7SMatthew G. Knepley     body = bodies[bodyID];
1477c1cad2e7SMatthew G. Knepley 
14789566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords));
1479c1cad2e7SMatthew G. Knepley     if (edgeID > 0) {
1480c1cad2e7SMatthew G. Knepley       /* Snap to EDGE at nearest location */
1481c1cad2e7SMatthew G. Knepley       double params[1];
14829566063dSJacob Faibussowitsch       PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge));
14839566063dSJacob Faibussowitsch       PetscCall(EG_invEvaluate(edge, vcoords, params, result)); // Get (x,y,z) of nearest point on EDGE
1484c1cad2e7SMatthew G. Knepley       for (d = 0; d < cdim; ++d) vcoords[d] = result[d];
1485c1cad2e7SMatthew G. Knepley     } else if (faceID > 0) {
1486c1cad2e7SMatthew G. Knepley       /* Snap to FACE at nearest location */
1487c1cad2e7SMatthew G. Knepley       double params[2];
14889566063dSJacob Faibussowitsch       PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face));
14899566063dSJacob Faibussowitsch       PetscCall(EG_invEvaluate(face, vcoords, params, result)); // Get (x,y,z) of nearest point on FACE
1490c1cad2e7SMatthew G. Knepley       for (d = 0; d < cdim; ++d) vcoords[d] = result[d];
1491c1cad2e7SMatthew G. Knepley     }
1492c1cad2e7SMatthew G. Knepley   }
14939566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
1494c1cad2e7SMatthew G. Knepley   /* Clear out global coordinates */
14956858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[0].x));
1496c1cad2e7SMatthew G. Knepley #endif
14973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1498c1cad2e7SMatthew G. Knepley }
1499c1cad2e7SMatthew G. Knepley 
1500cc4c1da9SBarry Smith /*@
1501a1cb98faSBarry Smith   DMPlexCreateEGADSFromFile - Create a `DMPLEX` mesh from an EGADS, IGES, or STEP file.
15027bee2925SMatthew Knepley 
15037bee2925SMatthew Knepley   Collective
15047bee2925SMatthew Knepley 
15057bee2925SMatthew Knepley   Input Parameters:
15067bee2925SMatthew Knepley + comm     - The MPI communicator
1507c1cad2e7SMatthew G. Knepley - filename - The name of the EGADS, IGES, or STEP file
15087bee2925SMatthew Knepley 
15097bee2925SMatthew Knepley   Output Parameter:
1510a1cb98faSBarry Smith . dm - The `DM` object representing the mesh
15117bee2925SMatthew Knepley 
15127bee2925SMatthew Knepley   Level: beginner
15137bee2925SMatthew Knepley 
15141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`, `DMPlexCreateEGADSLiteFromFile()`
15157bee2925SMatthew Knepley @*/
1516d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateEGADSFromFile(MPI_Comm comm, const char filename[], DM *dm)
1517d71ae5a4SJacob Faibussowitsch {
15187bee2925SMatthew Knepley   PetscMPIInt rank;
15197bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
15207bee2925SMatthew Knepley   ego context = NULL, model = NULL;
15217bee2925SMatthew Knepley #endif
1522c1cad2e7SMatthew G. Knepley   PetscBool printModel = PETSC_FALSE, tessModel = PETSC_FALSE, newModel = PETSC_FALSE;
15237bee2925SMatthew Knepley 
15247bee2925SMatthew Knepley   PetscFunctionBegin;
15254f572ea9SToby Isaac   PetscAssertPointer(filename, 2);
15269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_egads_print_model", &printModel, NULL));
15279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_egads_tess_model", &tessModel, NULL));
15289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_egads_new_model", &newModel, NULL));
15299566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
15307bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
1531dd400576SPatrick Sanan   if (rank == 0) {
15329566063dSJacob Faibussowitsch     PetscCall(EG_open(&context));
15339566063dSJacob Faibussowitsch     PetscCall(EG_loadModel(context, 0, filename, &model));
15349566063dSJacob Faibussowitsch     if (printModel) PetscCall(DMPlexEGADSPrintModel_Internal(model));
15357bee2925SMatthew Knepley   }
15369566063dSJacob Faibussowitsch   if (tessModel) PetscCall(DMPlexCreateEGADS_Tess_Internal(comm, context, model, dm));
15379566063dSJacob Faibussowitsch   else if (newModel) PetscCall(DMPlexCreateEGADS(comm, context, model, dm));
15389566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateEGADS_Internal(comm, context, model, dm));
15393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15407bee2925SMatthew Knepley #else
1541c1cad2e7SMatthew G. Knepley   SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads");
15427bee2925SMatthew Knepley #endif
15437bee2925SMatthew Knepley }
1544