xref: /petsc/src/dm/impls/plex/plexegads.c (revision 1e1ea65d8de51fde77ce8a787efbef25e407badc)
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 
8a8ededdfSMatthew G. Knepley /* 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 
21a8ededdfSMatthew G. Knepley /*@
22a8ededdfSMatthew G. Knepley   DMPlexSnapToGeomModel - Given a coordinate point 'mcoords' on the mesh point 'p', return the closest coordinate point 'gcoords' on the geometry model associated with that point.
23a8ededdfSMatthew G. Knepley 
24a8ededdfSMatthew G. Knepley   Not collective
25a8ededdfSMatthew G. Knepley 
26a8ededdfSMatthew G. Knepley   Input Parameters:
27a8ededdfSMatthew G. Knepley + dm      - The DMPlex object
28a8ededdfSMatthew G. Knepley . p       - The mesh point
29a8ededdfSMatthew G. Knepley - mcoords - A coordinate point lying on the mesh point
30a8ededdfSMatthew G. Knepley 
31a8ededdfSMatthew G. Knepley   Output Parameter:
32a8ededdfSMatthew G. Knepley . gcoords - The closest coordinate point on the geometry model associated with 'p' to the given point
33a8ededdfSMatthew G. Knepley 
34a8ededdfSMatthew G. Knepley   Note: Returns the original coordinates if no geometry model is found. Right now the only supported geometry model is EGADS.
35a8ededdfSMatthew G. Knepley 
36a8ededdfSMatthew G. Knepley   Level: intermediate
37a8ededdfSMatthew G. Knepley 
38a8ededdfSMatthew G. Knepley .seealso: DMRefine(), DMPlexCreate(), DMPlexSetRefinementUniform()
39a8ededdfSMatthew G. Knepley @*/
40a8ededdfSMatthew G. Knepley PetscErrorCode DMPlexSnapToGeomModel(DM dm, PetscInt p, const PetscScalar mcoords[], PetscScalar gcoords[])
41a8ededdfSMatthew G. Knepley {
42a8ededdfSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
43f0fcf0adSMatthew G. Knepley   DM             cdm;
44a8ededdfSMatthew G. Knepley   DMLabel        bodyLabel, faceLabel, edgeLabel;
45a8ededdfSMatthew G. Knepley   PetscContainer modelObj;
46a8ededdfSMatthew G. Knepley   PetscInt       bodyID, faceID, edgeID;
47a8ededdfSMatthew G. Knepley   ego           *bodies;
48f0fcf0adSMatthew G. Knepley   ego            model, geom, body, obj;
49f0fcf0adSMatthew G. Knepley   /* result has to hold derviatives, along with the value */
50f0fcf0adSMatthew G. Knepley   double         params[3], result[18], paramsV[16*3], resultV[16*3];
51a8ededdfSMatthew G. Knepley   int            Nb, oclass, mtype, *senses;
52f0fcf0adSMatthew G. Knepley   Vec            coordinatesLocal;
53f0fcf0adSMatthew G. Knepley   PetscScalar   *coords = NULL;
54f0fcf0adSMatthew G. Knepley   PetscInt       Nv, v, Np = 0, pm;
55a8ededdfSMatthew G. Knepley #endif
56f0fcf0adSMatthew G. Knepley   PetscInt       dE, d;
57a8ededdfSMatthew G. Knepley   PetscErrorCode ierr;
58a8ededdfSMatthew G. Knepley 
59a8ededdfSMatthew G. Knepley   PetscFunctionBegin;
60f0fcf0adSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr);
61a8ededdfSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
62a8ededdfSMatthew G. Knepley   ierr = DMGetLabel(dm, "EGADS Body ID",   &bodyLabel);CHKERRQ(ierr);
63a8ededdfSMatthew G. Knepley   ierr = DMGetLabel(dm, "EGADS Face ID",   &faceLabel);CHKERRQ(ierr);
64a8ededdfSMatthew G. Knepley   ierr = DMGetLabel(dm, "EGADS Edge ID",   &edgeLabel);CHKERRQ(ierr);
65a8ededdfSMatthew G. Knepley   if (!bodyLabel || !faceLabel || !edgeLabel) {
66f0fcf0adSMatthew G. Knepley     for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
67a8ededdfSMatthew G. Knepley     PetscFunctionReturn(0);
68a8ededdfSMatthew G. Knepley   }
69f0fcf0adSMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
70f0fcf0adSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinatesLocal);CHKERRQ(ierr);
71a8ededdfSMatthew G. Knepley   ierr = DMLabelGetValue(bodyLabel,   p, &bodyID);CHKERRQ(ierr);
72a8ededdfSMatthew G. Knepley   ierr = DMLabelGetValue(faceLabel,   p, &faceID);CHKERRQ(ierr);
73a8ededdfSMatthew G. Knepley   ierr = DMLabelGetValue(edgeLabel,   p, &edgeID);CHKERRQ(ierr);
74a8ededdfSMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "EGADS Model", (PetscObject *) &modelObj);CHKERRQ(ierr);
75a8ededdfSMatthew G. Knepley   ierr = PetscContainerGetPointer(modelObj, (void **) &model);CHKERRQ(ierr);
76a8ededdfSMatthew G. Knepley   ierr = EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses);CHKERRQ(ierr);
77f0fcf0adSMatthew G. Knepley   if (bodyID < 0 || bodyID >= Nb) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %D is not in [0, %d)", bodyID, Nb);
78a8ededdfSMatthew G. Knepley   body = bodies[bodyID];
79f0fcf0adSMatthew G. Knepley 
80f0fcf0adSMatthew G. Knepley   if (edgeID >= 0)      {ierr = EG_objectBodyTopo(body, EDGE, edgeID, &obj);CHKERRQ(ierr); Np = 1;}
81f0fcf0adSMatthew G. Knepley   else if (faceID >= 0) {ierr = EG_objectBodyTopo(body, FACE, faceID, &obj);CHKERRQ(ierr); Np = 2;}
82f0fcf0adSMatthew G. Knepley   else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D is not in edge or face label for EGADS", p);
83f0fcf0adSMatthew G. Knepley   /* Calculate parameters (t or u,v) for vertices */
84f0fcf0adSMatthew G. Knepley   ierr = DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords);CHKERRQ(ierr);
85f0fcf0adSMatthew G. Knepley   Nv  /= dE;
86f0fcf0adSMatthew G. Knepley   if (Nv == 1) {
87f0fcf0adSMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords);CHKERRQ(ierr);
88f0fcf0adSMatthew G. Knepley     for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
89f0fcf0adSMatthew G. Knepley     PetscFunctionReturn(0);
90a8ededdfSMatthew G. Knepley   }
91f0fcf0adSMatthew G. Knepley   if (Nv > 16) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %D coordinates associated to point %D", Nv, p);
92f0fcf0adSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {ierr = EG_invEvaluate(obj, &coords[v*dE], &paramsV[v*3], &resultV[v*3]);CHKERRQ(ierr);}
93f0fcf0adSMatthew G. Knepley   ierr = DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords);CHKERRQ(ierr);
94f0fcf0adSMatthew G. Knepley   /* Calculate parameters (t or u,v) for new vertex at edge midpoint */
95f0fcf0adSMatthew G. Knepley   for (pm = 0; pm < Np; ++pm) {
96f0fcf0adSMatthew G. Knepley     params[pm] = 0.;
97f0fcf0adSMatthew G. Knepley     for (v = 0; v < Nv; ++v) {params[pm] += paramsV[v*3+pm];}
98f0fcf0adSMatthew G. Knepley     params[pm] /= Nv;
99f0fcf0adSMatthew G. Knepley   }
100f0fcf0adSMatthew G. Knepley   /* TODO Check
101f0fcf0adSMatthew G. Knepley     double range[4]; // [umin, umax, vmin, vmax]
102f0fcf0adSMatthew G. Knepley     int    peri;
103f0fcf0adSMatthew G. Knepley     ierr = EG_getRange(face, range, &peri);CHKERRQ(ierr);
104d8185827SBarry Smith     if ((paramsNew[0] < range[0]) || (paramsNew[0] > range[1]) || (paramsNew[1] < range[2]) || (paramsNew[1] > range[3])) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE);
105f0fcf0adSMatthew G. Knepley   */
106f0fcf0adSMatthew G. Knepley   /* Put coordinates for new vertex in result[] */
107f0fcf0adSMatthew G. Knepley   ierr = EG_evaluate(obj, params, result);CHKERRQ(ierr);
108f0fcf0adSMatthew G. Knepley   for (d = 0; d < dE; ++d) gcoords[d] = result[d];
109a8ededdfSMatthew G. Knepley #else
110f0fcf0adSMatthew G. Knepley   for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
111a8ededdfSMatthew G. Knepley #endif
112a8ededdfSMatthew G. Knepley   PetscFunctionReturn(0);
113a8ededdfSMatthew G. Knepley }
1147bee2925SMatthew Knepley 
1157bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
1167bee2925SMatthew Knepley static PetscErrorCode DMPlexEGADSPrintModel(ego model)
1177bee2925SMatthew Knepley {
1187bee2925SMatthew Knepley   ego            geom, *bodies, *objs, *nobjs, *mobjs, *lobjs;
1197bee2925SMatthew Knepley   int            oclass, mtype, *senses;
1207bee2925SMatthew Knepley   int            Nb, b;
1217bee2925SMatthew Knepley   PetscErrorCode ierr;
1227bee2925SMatthew Knepley 
1237bee2925SMatthew Knepley   PetscFunctionBeginUser;
1247bee2925SMatthew Knepley   /* test bodyTopo functions */
1257bee2925SMatthew Knepley   ierr = EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses);CHKERRQ(ierr);
1267bee2925SMatthew Knepley   ierr = PetscPrintf(PETSC_COMM_SELF, " Number of BODIES (nbodies): %d \n", Nb);CHKERRQ(ierr);
1277bee2925SMatthew Knepley 
1287bee2925SMatthew Knepley   for (b = 0; b < Nb; ++b) {
1297bee2925SMatthew Knepley     ego body = bodies[b];
1307bee2925SMatthew Knepley     int id, Nsh, Nf, Nl, l, Ne, e, Nv, v;
1317bee2925SMatthew Knepley 
1327bee2925SMatthew Knepley     /* Output Basic Model Topology */
1337bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, SHELL, &Nsh, &objs);CHKERRQ(ierr);
1347bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of SHELLS: %d \n", Nsh);CHKERRQ(ierr);
1357bee2925SMatthew Knepley     EG_free(objs);
1367bee2925SMatthew Knepley 
1377bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, FACE,  &Nf, &objs);CHKERRQ(ierr);
1387bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of FACES: %d \n", Nf);CHKERRQ(ierr);
1397bee2925SMatthew Knepley     EG_free(objs);
1407bee2925SMatthew Knepley 
1417bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, LOOP,  &Nl, &lobjs);CHKERRQ(ierr);
1427bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of LOOPS: %d \n", Nl);CHKERRQ(ierr);
1437bee2925SMatthew Knepley 
1447bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, EDGE,  &Ne, &objs);CHKERRQ(ierr);
1457bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of EDGES: %d \n", Ne);CHKERRQ(ierr);
1467bee2925SMatthew Knepley     EG_free(objs);
1477bee2925SMatthew Knepley 
1487bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, NODE,  &Nv, &objs);CHKERRQ(ierr);
1497bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of NODES: %d \n", Nv);CHKERRQ(ierr);
1507bee2925SMatthew Knepley     EG_free(objs);
1517bee2925SMatthew Knepley 
1527bee2925SMatthew Knepley     for (l = 0; l < Nl; ++l) {
1537bee2925SMatthew Knepley       ego loop = lobjs[l];
1547bee2925SMatthew Knepley 
1557bee2925SMatthew Knepley       id   = EG_indexBodyTopo(body, loop);
1567bee2925SMatthew Knepley       ierr = PetscPrintf(PETSC_COMM_SELF, "          LOOP ID: %d\n", id);CHKERRQ(ierr);
1577bee2925SMatthew Knepley 
1587bee2925SMatthew Knepley       /* Get EDGE info which associated with the current LOOP */
1597bee2925SMatthew Knepley       ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
1607bee2925SMatthew Knepley 
1617bee2925SMatthew Knepley       for (e = 0; e < Ne; ++e) {
1627bee2925SMatthew Knepley         ego    edge      = objs[e];
1637bee2925SMatthew Knepley         double range[4]  = {0., 0., 0., 0.};
1647bee2925SMatthew Knepley         double point[3]  = {0., 0., 0.};
165266cfabeSMatthew G. Knepley         double params[3] = {0., 0., 0.};
166266cfabeSMatthew G. Knepley         double result[18];
1677bee2925SMatthew Knepley         int    peri;
1687bee2925SMatthew Knepley 
1697bee2925SMatthew Knepley         id   = EG_indexBodyTopo(body, edge);CHKERRQ(ierr);
170266cfabeSMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "            EDGE ID: %d (%d)\n", id, e);CHKERRQ(ierr);
1717bee2925SMatthew Knepley 
172266cfabeSMatthew G. Knepley         ierr = EG_getRange(edge, range, &peri);CHKERRQ(ierr);
173*1e1ea65dSPierre Jolivet         ierr = PetscPrintf(PETSC_COMM_SELF, "  Range = %lf, %lf, %lf, %lf \n", range[0], range[1], range[2], range[3]);CHKERRQ(ierr);
1747bee2925SMatthew Knepley 
1757bee2925SMatthew Knepley         /* Get NODE info which associated with the current EDGE */
1767bee2925SMatthew Knepley         ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);CHKERRQ(ierr);
177266cfabeSMatthew G. Knepley         if (mtype == DEGENERATE) {
178266cfabeSMatthew G. Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "  EDGE %d is DEGENERATE \n", id);CHKERRQ(ierr);
179266cfabeSMatthew G. Knepley         } else {
180266cfabeSMatthew G. Knepley           params[0] = range[0];
181266cfabeSMatthew G. Knepley           ierr = EG_evaluate(edge, params, result);CHKERRQ(ierr);
182*1e1ea65dSPierre Jolivet           ierr = PetscPrintf(PETSC_COMM_SELF, "   between (%lf, %lf, %lf)", result[0], result[1], result[2]);CHKERRQ(ierr);
183266cfabeSMatthew G. Knepley           params[0] = range[1];
184266cfabeSMatthew G. Knepley           ierr = EG_evaluate(edge, params, result);CHKERRQ(ierr);
185*1e1ea65dSPierre Jolivet           ierr = PetscPrintf(PETSC_COMM_SELF, " and (%lf, %lf, %lf)\n", result[0], result[1], result[2]);CHKERRQ(ierr);
186266cfabeSMatthew G. Knepley         }
1877bee2925SMatthew Knepley 
1887bee2925SMatthew Knepley         for (v = 0; v < Nv; ++v) {
1897bee2925SMatthew Knepley           ego    vertex = nobjs[v];
1907bee2925SMatthew Knepley           double limits[4];
1917bee2925SMatthew Knepley           int    dummy;
1927bee2925SMatthew Knepley 
1937bee2925SMatthew Knepley           ierr = EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses);CHKERRQ(ierr);
1947bee2925SMatthew Knepley           id   = EG_indexBodyTopo(body, vertex);
1957bee2925SMatthew Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "              NODE ID: %d \n", id);CHKERRQ(ierr);
196*1e1ea65dSPierre Jolivet           ierr = PetscPrintf(PETSC_COMM_SELF, "                 (x, y, z) = (%lf, %lf, %lf) \n", limits[0], limits[1], limits[2]);CHKERRQ(ierr);
1977bee2925SMatthew Knepley 
1987bee2925SMatthew Knepley           point[0] = point[0] + limits[0];
1997bee2925SMatthew Knepley           point[1] = point[1] + limits[1];
2007bee2925SMatthew Knepley           point[2] = point[2] + limits[2];
2017bee2925SMatthew Knepley         }
2027bee2925SMatthew Knepley       }
2037bee2925SMatthew Knepley     }
2047bee2925SMatthew Knepley     EG_free(lobjs);
2057bee2925SMatthew Knepley   }
2067bee2925SMatthew Knepley   PetscFunctionReturn(0);
2077bee2925SMatthew Knepley }
2087bee2925SMatthew Knepley 
2097bee2925SMatthew Knepley static PetscErrorCode DMPlexEGADSDestroy_Private(void *context)
2107bee2925SMatthew Knepley {
2117bee2925SMatthew Knepley   if (context) EG_close((ego) context);
2127bee2925SMatthew Knepley   return 0;
2137bee2925SMatthew Knepley }
2147bee2925SMatthew Knepley 
2157bee2925SMatthew Knepley static PetscErrorCode DMPlexCreateEGADS(MPI_Comm comm, ego context, ego model, DM *newdm)
2167bee2925SMatthew Knepley {
2177bee2925SMatthew Knepley   DMLabel        bodyLabel, faceLabel, edgeLabel;
2187bee2925SMatthew Knepley   PetscInt       cStart, cEnd, c;
2197bee2925SMatthew Knepley   /* EGADSLite variables */
2207bee2925SMatthew Knepley   ego            geom, *bodies, *objs, *nobjs, *mobjs, *lobjs;
2217bee2925SMatthew Knepley   int            oclass, mtype, nbodies, *senses;
2227bee2925SMatthew Knepley   int            b;
2237bee2925SMatthew Knepley   /* PETSc variables */
2247bee2925SMatthew Knepley   DM             dm;
2257bee2925SMatthew Knepley   PetscHMapI     edgeMap = NULL;
2267bee2925SMatthew 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;
2277bee2925SMatthew Knepley   PetscInt      *cells  = NULL, *cone = NULL;
2287bee2925SMatthew Knepley   PetscReal     *coords = NULL;
2297bee2925SMatthew Knepley   PetscMPIInt    rank;
2307bee2925SMatthew Knepley   PetscErrorCode ierr;
2317bee2925SMatthew Knepley 
2327bee2925SMatthew Knepley   PetscFunctionBegin;
23355b25c41SPierre Jolivet   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
2347bee2925SMatthew Knepley   if (!rank) {
235266cfabeSMatthew G. Knepley     const PetscInt debug = 0;
236266cfabeSMatthew G. Knepley 
2377bee2925SMatthew Knepley     /* ---------------------------------------------------------------------------------------------------
2387bee2925SMatthew Knepley     Generate Petsc Plex
2397bee2925SMatthew Knepley       Get all Nodes in model, record coordinates in a correctly formatted array
2407bee2925SMatthew Knepley       Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array
2417bee2925SMatthew Knepley       We need to uniformly refine the initial geometry to guarantee a valid mesh
2427bee2925SMatthew Knepley     */
2437bee2925SMatthew Knepley 
2447bee2925SMatthew Knepley     /* Calculate cell and vertex sizes */
2457bee2925SMatthew Knepley     ierr = EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses);CHKERRQ(ierr);
2467bee2925SMatthew Knepley     ierr = PetscHMapICreate(&edgeMap);CHKERRQ(ierr);
2477bee2925SMatthew Knepley     numEdges = 0;
2487bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
2497bee2925SMatthew Knepley       ego body = bodies[b];
2507bee2925SMatthew Knepley       int id, Nl, l, Nv, v;
2517bee2925SMatthew Knepley 
2527bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs);CHKERRQ(ierr);
2537bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
2547bee2925SMatthew Knepley         ego loop = lobjs[l];
2557bee2925SMatthew Knepley         int Ner  = 0, Ne, e, Nc;
2567bee2925SMatthew Knepley 
2577bee2925SMatthew Knepley         ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
2587bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
2597bee2925SMatthew Knepley           ego edge = objs[e];
2607bee2925SMatthew Knepley           int Nv, id;
2617bee2925SMatthew Knepley           PetscHashIter iter;
2627bee2925SMatthew Knepley           PetscBool     found;
2637bee2925SMatthew Knepley 
2647bee2925SMatthew Knepley           ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);
2657bee2925SMatthew Knepley           if (mtype == DEGENERATE) continue;
2667bee2925SMatthew Knepley           id   = EG_indexBodyTopo(body, edge);CHKERRQ(ierr);
2677bee2925SMatthew Knepley           ierr = PetscHMapIFind(edgeMap, id-1, &iter, &found);CHKERRQ(ierr);
2687bee2925SMatthew Knepley           if (!found) {ierr = PetscHMapISet(edgeMap, id-1, numEdges++);CHKERRQ(ierr);}
2697bee2925SMatthew Knepley           ++Ner;
2707bee2925SMatthew Knepley         }
2717bee2925SMatthew Knepley         if (Ner == 2)      {Nc = 2;}
2727bee2925SMatthew Knepley         else if (Ner == 3) {Nc = 4;}
2737bee2925SMatthew Knepley         else if (Ner == 4) {Nc = 8; ++numQuads;}
2747bee2925SMatthew Knepley         else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot support loop with %d edges", Ner);
2757bee2925SMatthew Knepley         numCells += Nc;
2767bee2925SMatthew Knepley         newCells += Nc-1;
2777bee2925SMatthew Knepley         maxCorners = PetscMax(Ner*2+1, maxCorners);
2787bee2925SMatthew Knepley       }
2797bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs);CHKERRQ(ierr);
2807bee2925SMatthew Knepley       for (v = 0; v < Nv; ++v) {
2817bee2925SMatthew Knepley         ego vertex = nobjs[v];
2827bee2925SMatthew Knepley 
2837bee2925SMatthew Knepley         id = EG_indexBodyTopo(body, vertex);
2847bee2925SMatthew Knepley         /* TODO: Instead of assuming contiguous ids, we could use a hash table */
2857bee2925SMatthew Knepley         numVertices = PetscMax(id, numVertices);
2867bee2925SMatthew Knepley       }
2877bee2925SMatthew Knepley       EG_free(lobjs);
2887bee2925SMatthew Knepley       EG_free(nobjs);
2897bee2925SMatthew Knepley     }
2907bee2925SMatthew Knepley     ierr = PetscHMapIGetSize(edgeMap, &numEdges);CHKERRQ(ierr);
2917bee2925SMatthew Knepley     newVertices  = numEdges + numQuads;
2927bee2925SMatthew Knepley     numVertices += newVertices;
2937bee2925SMatthew Knepley 
2947bee2925SMatthew Knepley     dim        = 2; /* Assume 3D Models :: Need to update to handle 2D Models in the future */
2957bee2925SMatthew Knepley     cdim       = 3; /* Assume 3D Models :: Need to update to handle 2D Models in the future */
2967bee2925SMatthew Knepley     numCorners = 3; /* Split cells into triangles */
2977bee2925SMatthew Knepley     ierr = PetscMalloc3(numVertices*cdim, &coords, numCells*numCorners, &cells, maxCorners, &cone);CHKERRQ(ierr);
2987bee2925SMatthew Knepley 
2997bee2925SMatthew Knepley     /* Get vertex coordinates */
3007bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
3017bee2925SMatthew Knepley       ego body = bodies[b];
3027bee2925SMatthew Knepley       int id, Nv, v;
3037bee2925SMatthew Knepley 
3047bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs);CHKERRQ(ierr);
3057bee2925SMatthew Knepley       for (v = 0; v < Nv; ++v) {
3067bee2925SMatthew Knepley         ego    vertex = nobjs[v];
3077bee2925SMatthew Knepley         double limits[4];
3087bee2925SMatthew Knepley         int    dummy;
3097bee2925SMatthew Knepley 
3107bee2925SMatthew Knepley         ierr = EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses);CHKERRQ(ierr);
3117bee2925SMatthew Knepley         id   = EG_indexBodyTopo(body, vertex);CHKERRQ(ierr);
3127bee2925SMatthew Knepley         coords[(id-1)*cdim+0] = limits[0];
3137bee2925SMatthew Knepley         coords[(id-1)*cdim+1] = limits[1];
3147bee2925SMatthew Knepley         coords[(id-1)*cdim+2] = limits[2];
3157bee2925SMatthew Knepley       }
3167bee2925SMatthew Knepley       EG_free(nobjs);
3177bee2925SMatthew Knepley     }
3187bee2925SMatthew Knepley     ierr = PetscHMapIClear(edgeMap);CHKERRQ(ierr);
3197bee2925SMatthew Knepley     fOff     = numVertices - newVertices + numEdges;
3207bee2925SMatthew Knepley     numEdges = 0;
3217bee2925SMatthew Knepley     numQuads = 0;
3227bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
3237bee2925SMatthew Knepley       ego body = bodies[b];
3247bee2925SMatthew Knepley       int Nl, l;
3257bee2925SMatthew Knepley 
3267bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs);CHKERRQ(ierr);
3277bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
3287bee2925SMatthew Knepley         ego loop = lobjs[l];
3297bee2925SMatthew Knepley         int lid, Ner = 0, Ne, e;
3307bee2925SMatthew Knepley 
3317bee2925SMatthew Knepley         lid  = EG_indexBodyTopo(body, loop);CHKERRQ(ierr);
3327bee2925SMatthew Knepley         ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
3337bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
3347bee2925SMatthew Knepley           ego       edge = objs[e];
3357bee2925SMatthew Knepley           int       eid, Nv;
3367bee2925SMatthew Knepley           PetscHashIter iter;
3377bee2925SMatthew Knepley           PetscBool     found;
3387bee2925SMatthew Knepley 
3397bee2925SMatthew Knepley           ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);
3407bee2925SMatthew Knepley           if (mtype == DEGENERATE) continue;
3417bee2925SMatthew Knepley           ++Ner;
3427bee2925SMatthew Knepley           eid  = EG_indexBodyTopo(body, edge);CHKERRQ(ierr);
3437bee2925SMatthew Knepley           ierr = PetscHMapIFind(edgeMap, eid-1, &iter, &found);CHKERRQ(ierr);
3447bee2925SMatthew Knepley           if (!found) {
3457bee2925SMatthew Knepley             PetscInt v = numVertices - newVertices + numEdges;
3467bee2925SMatthew Knepley             double range[4], params[3] = {0., 0., 0.}, result[18];
3477bee2925SMatthew Knepley             int    periodic[2];
3487bee2925SMatthew Knepley 
3497bee2925SMatthew Knepley             ierr = PetscHMapISet(edgeMap, eid-1, numEdges++);CHKERRQ(ierr);
3507bee2925SMatthew Knepley             ierr = EG_getRange(edge, range, periodic);CHKERRQ(ierr);
3517bee2925SMatthew Knepley             params[0] = 0.5*(range[0] + range[1]);
3527bee2925SMatthew Knepley             ierr = EG_evaluate(edge, params, result);CHKERRQ(ierr);
3537bee2925SMatthew Knepley             coords[v*cdim+0] = result[0];
3547bee2925SMatthew Knepley             coords[v*cdim+1] = result[1];
3557bee2925SMatthew Knepley             coords[v*cdim+2] = result[2];
3567bee2925SMatthew Knepley           }
3577bee2925SMatthew Knepley         }
3587bee2925SMatthew Knepley         if (Ner == 4) {
3597bee2925SMatthew Knepley           PetscInt v = fOff + numQuads++;
360266cfabeSMatthew G. Knepley           ego     *fobjs, face;
3617bee2925SMatthew Knepley           double   range[4], params[3] = {0., 0., 0.}, result[18];
362266cfabeSMatthew G. Knepley           int      Nf, fid, periodic[2];
3637bee2925SMatthew Knepley 
3647bee2925SMatthew Knepley           ierr = EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs);CHKERRQ(ierr);
365266cfabeSMatthew G. Knepley           face = fobjs[0];
366266cfabeSMatthew G. Knepley           fid  = EG_indexBodyTopo(body, face);CHKERRQ(ierr);
367266cfabeSMatthew G. Knepley           if (Nf != 1) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Loop %d has %d faces, instead of 1 (%d)", lid-1, Nf, fid);
368266cfabeSMatthew G. Knepley           ierr = EG_getRange(face, range, periodic);CHKERRQ(ierr);
3697bee2925SMatthew Knepley           params[0] = 0.5*(range[0] + range[1]);
3707bee2925SMatthew Knepley           params[1] = 0.5*(range[2] + range[3]);
371266cfabeSMatthew G. Knepley           ierr = EG_evaluate(face, params, result);CHKERRQ(ierr);
3727bee2925SMatthew Knepley           coords[v*cdim+0] = result[0];
3737bee2925SMatthew Knepley           coords[v*cdim+1] = result[1];
3747bee2925SMatthew Knepley           coords[v*cdim+2] = result[2];
3757bee2925SMatthew Knepley         }
3767bee2925SMatthew Knepley       }
3777bee2925SMatthew Knepley     }
3787bee2925SMatthew Knepley     if (numEdges + numQuads != newVertices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of new vertices %D != %D previous count", numEdges + numQuads, newVertices);
3797bee2925SMatthew Knepley     CHKMEMQ;
3807bee2925SMatthew Knepley 
3817bee2925SMatthew Knepley     /* Get cell vertices by traversing loops */
3827bee2925SMatthew Knepley     numQuads = 0;
3837bee2925SMatthew Knepley     cOff     = 0;
3847bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
3857bee2925SMatthew Knepley       ego body = bodies[b];
3867bee2925SMatthew Knepley       int id, Nl, l;
3877bee2925SMatthew Knepley 
3887bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs);CHKERRQ(ierr);
3897bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
3907bee2925SMatthew Knepley         ego loop = lobjs[l];
3917bee2925SMatthew Knepley         int lid, Ner = 0, Ne, e, nc = 0, c, Nt, t;
3927bee2925SMatthew Knepley 
3937bee2925SMatthew Knepley         lid  = EG_indexBodyTopo(body, loop);CHKERRQ(ierr);
3947bee2925SMatthew Knepley         ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
3957bee2925SMatthew Knepley 
3967bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
3977bee2925SMatthew Knepley           ego edge = objs[e];
3987bee2925SMatthew Knepley           int points[3];
3997bee2925SMatthew Knepley           int eid, Nv, v, tmp;
4007bee2925SMatthew Knepley 
4017bee2925SMatthew Knepley           eid  = EG_indexBodyTopo(body, edge);
4027bee2925SMatthew Knepley           ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);
403266cfabeSMatthew G. Knepley           if (mtype == DEGENERATE) continue;
404266cfabeSMatthew G. Knepley           else                     ++Ner;
4057bee2925SMatthew Knepley           if (Nv != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Edge %d has %d vertices != 2", eid, Nv);
4067bee2925SMatthew Knepley 
4077bee2925SMatthew Knepley           for (v = 0; v < Nv; ++v) {
4087bee2925SMatthew Knepley             ego vertex = nobjs[v];
4097bee2925SMatthew Knepley 
4107bee2925SMatthew Knepley             id = EG_indexBodyTopo(body, vertex);
4117bee2925SMatthew Knepley             points[v*2] = id-1;
4127bee2925SMatthew Knepley           }
4137bee2925SMatthew Knepley           {
4147bee2925SMatthew Knepley             PetscInt edgeNum;
4157bee2925SMatthew Knepley 
4167bee2925SMatthew Knepley             ierr = PetscHMapIGet(edgeMap, eid-1, &edgeNum);CHKERRQ(ierr);
4177bee2925SMatthew Knepley             points[1] = numVertices - newVertices + edgeNum;
4187bee2925SMatthew Knepley           }
4197bee2925SMatthew Knepley           /* EGADS loops are not oriented, but seem to be in order, so we must piece them together */
4207bee2925SMatthew Knepley           if (!nc) {
4217bee2925SMatthew Knepley             for (v = 0; v < Nv+1; ++v) cone[nc++] = points[v];
4227bee2925SMatthew Knepley           } else {
4237bee2925SMatthew Knepley             if (cone[nc-1] == points[0])      {cone[nc++] = points[1]; if (cone[0] != points[2]) cone[nc++] = points[2];}
4247bee2925SMatthew Knepley             else if (cone[nc-1] == points[2]) {cone[nc++] = points[1]; if (cone[0] != points[0]) cone[nc++] = points[0];}
4257bee2925SMatthew Knepley             else if (cone[nc-3] == points[0]) {tmp = cone[nc-3]; cone[nc-3] = cone[nc-1]; cone[nc-1] = tmp; cone[nc++] = points[1]; if (cone[0] != points[2]) cone[nc++] = points[2];}
4267bee2925SMatthew Knepley             else if (cone[nc-3] == points[2]) {tmp = cone[nc-3]; cone[nc-3] = cone[nc-1]; cone[nc-1] = tmp; cone[nc++] = points[1]; if (cone[0] != points[0]) cone[nc++] = points[0];}
4277bee2925SMatthew Knepley             else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %d does not match its predecessor", eid);
4287bee2925SMatthew Knepley           }
4297bee2925SMatthew Knepley         }
4307bee2925SMatthew Knepley         if (nc != 2*Ner)     SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %D != %D", nc, 2*Ner);
4317bee2925SMatthew Knepley         if (Ner == 4) {cone[nc++] = numVertices - newVertices + numEdges + numQuads++;}
4327bee2925SMatthew Knepley         if (nc > maxCorners) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %D > %D max", nc, maxCorners);
4337bee2925SMatthew Knepley         /* Triangulate the loop */
4347bee2925SMatthew Knepley         switch (Ner) {
4357bee2925SMatthew Knepley           case 2: /* Bi-Segment -> 2 triangles */
4367bee2925SMatthew Knepley             Nt = 2;
4377bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[0];
4387bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[1];
4397bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[2];
4407bee2925SMatthew Knepley             ++cOff;
4417bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[0];
4427bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[2];
4437bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[3];
4447bee2925SMatthew Knepley             ++cOff;
4457bee2925SMatthew Knepley             break;
4467bee2925SMatthew Knepley           case 3: /* Triangle   -> 4 triangles */
4477bee2925SMatthew Knepley             Nt = 4;
4487bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[0];
4497bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[1];
4507bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[5];
4517bee2925SMatthew Knepley             ++cOff;
4527bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[1];
4537bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[2];
4547bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[3];
4557bee2925SMatthew Knepley             ++cOff;
4567bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[5];
4577bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[3];
4587bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[4];
4597bee2925SMatthew Knepley             ++cOff;
4607bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[1];
4617bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[3];
4627bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[5];
4637bee2925SMatthew Knepley             ++cOff;
4647bee2925SMatthew Knepley             break;
4657bee2925SMatthew Knepley           case 4: /* Quad       -> 8 triangles */
4667bee2925SMatthew Knepley             Nt = 8;
4677bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[0];
4687bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[1];
4697bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[7];
4707bee2925SMatthew Knepley             ++cOff;
4717bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[1];
4727bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[2];
4737bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[3];
4747bee2925SMatthew Knepley             ++cOff;
4757bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[3];
4767bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[4];
4777bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[5];
4787bee2925SMatthew Knepley             ++cOff;
4797bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[5];
4807bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[6];
4817bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[7];
4827bee2925SMatthew Knepley             ++cOff;
4837bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[8];
4847bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[1];
4857bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[3];
4867bee2925SMatthew Knepley             ++cOff;
4877bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[8];
4887bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[3];
4897bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[5];
4907bee2925SMatthew Knepley             ++cOff;
4917bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[8];
4927bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[5];
4937bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[7];
4947bee2925SMatthew Knepley             ++cOff;
4957bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[8];
4967bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[7];
4977bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[1];
4987bee2925SMatthew Knepley             ++cOff;
4997bee2925SMatthew Knepley             break;
5007bee2925SMatthew Knepley           default: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d edges, which we do not support", lid, Ner);
5017bee2925SMatthew Knepley         }
502266cfabeSMatthew G. Knepley         if (debug) {
5037bee2925SMatthew Knepley           for (t = 0; t < Nt; ++t) {
5047bee2925SMatthew Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, "  LOOP Corner NODEs Triangle %D (", t);CHKERRQ(ierr);
5057bee2925SMatthew Knepley             for (c = 0; c < numCorners; ++c) {
5067bee2925SMatthew Knepley               if (c > 0) {ierr = PetscPrintf(PETSC_COMM_SELF, ", ");CHKERRQ(ierr);}
5077bee2925SMatthew Knepley               ierr = PetscPrintf(PETSC_COMM_SELF, "%D", cells[(cOff-Nt+t)*numCorners+c]);CHKERRQ(ierr);
5087bee2925SMatthew Knepley             }
5097bee2925SMatthew Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, ")\n");CHKERRQ(ierr);
5107bee2925SMatthew Knepley           }
5117bee2925SMatthew Knepley         }
512266cfabeSMatthew G. Knepley       }
5137bee2925SMatthew Knepley       EG_free(lobjs);
5147bee2925SMatthew Knepley     }
5157bee2925SMatthew Knepley   }
5167bee2925SMatthew Knepley   if (cOff != numCells) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count of total cells %D != %D previous count", cOff, numCells);
5177bee2925SMatthew Knepley   ierr = DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numVertices, numCorners, PETSC_TRUE, cells, cdim, coords, &dm);CHKERRQ(ierr);
5187bee2925SMatthew Knepley   ierr = PetscFree3(coords, cells, cone);CHKERRQ(ierr);
519266cfabeSMatthew G. Knepley   ierr = PetscInfo2(dm, " Total Number of Unique Cells    = %D (%D)\n", numCells, newCells);CHKERRQ(ierr);
520266cfabeSMatthew G. Knepley   ierr = PetscInfo2(dm, " Total Number of Unique Vertices = %D (%D)\n", numVertices, newVertices);CHKERRQ(ierr);
5217bee2925SMatthew Knepley   /* Embed EGADS model in DM */
5227bee2925SMatthew Knepley   {
5237bee2925SMatthew Knepley     PetscContainer modelObj, contextObj;
5247bee2925SMatthew Knepley 
5257bee2925SMatthew Knepley     ierr = PetscContainerCreate(PETSC_COMM_SELF, &modelObj);CHKERRQ(ierr);
5267bee2925SMatthew Knepley     ierr = PetscContainerSetPointer(modelObj, model);CHKERRQ(ierr);
5277bee2925SMatthew Knepley     ierr = PetscObjectCompose((PetscObject) dm, "EGADS Model", (PetscObject) modelObj);CHKERRQ(ierr);
5287bee2925SMatthew Knepley     ierr = PetscContainerDestroy(&modelObj);CHKERRQ(ierr);
5297bee2925SMatthew Knepley 
5307bee2925SMatthew Knepley     ierr = PetscContainerCreate(PETSC_COMM_SELF, &contextObj);CHKERRQ(ierr);
5317bee2925SMatthew Knepley     ierr = PetscContainerSetPointer(contextObj, context);CHKERRQ(ierr);
5327bee2925SMatthew Knepley     ierr = PetscContainerSetUserDestroy(contextObj, DMPlexEGADSDestroy_Private);CHKERRQ(ierr);
5337bee2925SMatthew Knepley     ierr = PetscObjectCompose((PetscObject) dm, "EGADS Context", (PetscObject) contextObj);CHKERRQ(ierr);
5347bee2925SMatthew Knepley     ierr = PetscContainerDestroy(&contextObj);CHKERRQ(ierr);
5357bee2925SMatthew Knepley   }
5367bee2925SMatthew Knepley   /* Label points */
5377bee2925SMatthew Knepley   ierr = DMCreateLabel(dm, "EGADS Body ID");CHKERRQ(ierr);
5387bee2925SMatthew Knepley   ierr = DMGetLabel(dm, "EGADS Body ID", &bodyLabel);CHKERRQ(ierr);
5397bee2925SMatthew Knepley   ierr = DMCreateLabel(dm, "EGADS Face ID");CHKERRQ(ierr);
5407bee2925SMatthew Knepley   ierr = DMGetLabel(dm, "EGADS Face ID", &faceLabel);CHKERRQ(ierr);
5417bee2925SMatthew Knepley   ierr = DMCreateLabel(dm, "EGADS Edge ID");CHKERRQ(ierr);
5427bee2925SMatthew Knepley   ierr = DMGetLabel(dm, "EGADS Edge ID", &edgeLabel);CHKERRQ(ierr);
5437bee2925SMatthew Knepley   cOff = 0;
5447bee2925SMatthew Knepley   for (b = 0; b < nbodies; ++b) {
5457bee2925SMatthew Knepley     ego body = bodies[b];
5467bee2925SMatthew Knepley     int id, Nl, l;
5477bee2925SMatthew Knepley 
5487bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs);CHKERRQ(ierr);
5497bee2925SMatthew Knepley     for (l = 0; l < Nl; ++l) {
5507bee2925SMatthew Knepley       ego  loop = lobjs[l];
5517bee2925SMatthew Knepley       ego *fobjs;
5527bee2925SMatthew Knepley       int  lid, Nf, fid, Ner = 0, Ne, e, Nt = 0, t;
5537bee2925SMatthew Knepley 
5547bee2925SMatthew Knepley       lid  = EG_indexBodyTopo(body, loop);CHKERRQ(ierr);
5557bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs);CHKERRQ(ierr);
5562758c9b9SBarry Smith       if (Nf > 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf);
5577bee2925SMatthew Knepley       fid  = EG_indexBodyTopo(body, fobjs[0]);CHKERRQ(ierr);
5587bee2925SMatthew Knepley       EG_free(fobjs);
5597bee2925SMatthew Knepley       ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
5607bee2925SMatthew Knepley       for (e = 0; e < Ne; ++e) {
5617bee2925SMatthew Knepley         ego             edge = objs[e];
5627bee2925SMatthew Knepley         int             eid, Nv, v;
5637bee2925SMatthew Knepley         PetscInt        points[3], support[2], numEdges, edgeNum;
5647bee2925SMatthew Knepley         const PetscInt *edges;
5657bee2925SMatthew Knepley 
5667bee2925SMatthew Knepley         eid  = EG_indexBodyTopo(body, edge);
5677bee2925SMatthew Knepley         ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);
5687bee2925SMatthew Knepley         if (mtype == DEGENERATE) continue;
5697bee2925SMatthew Knepley         else                     ++Ner;
5707bee2925SMatthew Knepley         for (v = 0; v < Nv; ++v) {
5717bee2925SMatthew Knepley           ego vertex = nobjs[v];
5727bee2925SMatthew Knepley 
5737bee2925SMatthew Knepley           id   = EG_indexBodyTopo(body, vertex);
5747bee2925SMatthew Knepley           ierr = DMLabelSetValue(edgeLabel, numCells + id-1, eid);CHKERRQ(ierr);
5757bee2925SMatthew Knepley           points[v*2] = numCells + id-1;
5767bee2925SMatthew Knepley         }
5777bee2925SMatthew Knepley         ierr = PetscHMapIGet(edgeMap, eid-1, &edgeNum);CHKERRQ(ierr);
5787bee2925SMatthew Knepley         points[1] = numCells + numVertices - newVertices + edgeNum;
5797bee2925SMatthew Knepley 
5807bee2925SMatthew Knepley         ierr = DMLabelSetValue(edgeLabel, points[1], eid);CHKERRQ(ierr);
5817bee2925SMatthew Knepley         support[0] = points[0];
5827bee2925SMatthew Knepley         support[1] = points[1];
5837bee2925SMatthew Knepley         ierr = DMPlexGetJoin(dm, 2, support, &numEdges, &edges);CHKERRQ(ierr);
5847bee2925SMatthew Knepley         if (numEdges != 1) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%D, %D) should only bound 1 edge, not %D", support[0], support[1], numEdges);
5857bee2925SMatthew Knepley         ierr = DMLabelSetValue(edgeLabel, edges[0], eid);CHKERRQ(ierr);
5867bee2925SMatthew Knepley         ierr = DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges);CHKERRQ(ierr);
5877bee2925SMatthew Knepley         support[0] = points[1];
5887bee2925SMatthew Knepley         support[1] = points[2];
5897bee2925SMatthew Knepley         ierr = DMPlexGetJoin(dm, 2, support, &numEdges, &edges);CHKERRQ(ierr);
5907bee2925SMatthew Knepley         if (numEdges != 1) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%D, %D) should only bound 1 edge, not %D", support[0], support[1], numEdges);
5917bee2925SMatthew Knepley         ierr = DMLabelSetValue(edgeLabel, edges[0], eid);CHKERRQ(ierr);
5927bee2925SMatthew Knepley         ierr = DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges);CHKERRQ(ierr);
5937bee2925SMatthew Knepley       }
5947bee2925SMatthew Knepley       switch (Ner) {
5957bee2925SMatthew Knepley         case 2: Nt = 2;break;
5967bee2925SMatthew Knepley         case 3: Nt = 4;break;
5977bee2925SMatthew Knepley         case 4: Nt = 8;break;
5987bee2925SMatthew Knepley         default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Loop with %d edges is unsupported", Ner);
5997bee2925SMatthew Knepley       }
6007bee2925SMatthew Knepley       for (t = 0; t < Nt; ++t) {
6017bee2925SMatthew Knepley         ierr = DMLabelSetValue(bodyLabel, cOff+t, b);CHKERRQ(ierr);
6027bee2925SMatthew Knepley         ierr = DMLabelSetValue(faceLabel, cOff+t, fid);CHKERRQ(ierr);
6037bee2925SMatthew Knepley       }
6047bee2925SMatthew Knepley       cOff += Nt;
6057bee2925SMatthew Knepley     }
6067bee2925SMatthew Knepley     EG_free(lobjs);
6077bee2925SMatthew Knepley   }
6087bee2925SMatthew Knepley   ierr = PetscHMapIDestroy(&edgeMap);CHKERRQ(ierr);
6097bee2925SMatthew Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
6107bee2925SMatthew Knepley   for (c = cStart; c < cEnd; ++c) {
6117bee2925SMatthew Knepley     PetscInt *closure = NULL;
6127bee2925SMatthew Knepley     PetscInt  clSize, cl, bval, fval;
6137bee2925SMatthew Knepley 
6147bee2925SMatthew Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
6157bee2925SMatthew Knepley     ierr = DMLabelGetValue(bodyLabel, c, &bval);CHKERRQ(ierr);
6167bee2925SMatthew Knepley     ierr = DMLabelGetValue(faceLabel, c, &fval);CHKERRQ(ierr);
6177bee2925SMatthew Knepley     for (cl = 0; cl < clSize*2; cl += 2) {
6187bee2925SMatthew Knepley       ierr = DMLabelSetValue(bodyLabel, closure[cl], bval);CHKERRQ(ierr);
6197bee2925SMatthew Knepley       ierr = DMLabelSetValue(faceLabel, closure[cl], fval);CHKERRQ(ierr);
6207bee2925SMatthew Knepley     }
6217bee2925SMatthew Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
6227bee2925SMatthew Knepley   }
6237bee2925SMatthew Knepley   *newdm = dm;
6247bee2925SMatthew Knepley   PetscFunctionReturn(0);
6257bee2925SMatthew Knepley }
6267bee2925SMatthew Knepley #endif
6277bee2925SMatthew Knepley 
6287bee2925SMatthew Knepley /*@C
6297bee2925SMatthew Knepley   DMPlexCreateEGADSFromFile - Create a DMPlex mesh from an EGADSLite file.
6307bee2925SMatthew Knepley 
6317bee2925SMatthew Knepley   Collective
6327bee2925SMatthew Knepley 
6337bee2925SMatthew Knepley   Input Parameters:
6347bee2925SMatthew Knepley + comm     - The MPI communicator
6357bee2925SMatthew Knepley - filename - The name of the ExodusII file
6367bee2925SMatthew Knepley 
6377bee2925SMatthew Knepley   Output Parameter:
6387bee2925SMatthew Knepley . dm       - The DM object representing the mesh
6397bee2925SMatthew Knepley 
6407bee2925SMatthew Knepley   Level: beginner
6417bee2925SMatthew Knepley 
6427bee2925SMatthew Knepley .seealso: DMPLEX, DMCreate(), DMPlexCreateEGADS()
6437bee2925SMatthew Knepley @*/
6447bee2925SMatthew Knepley PetscErrorCode DMPlexCreateEGADSFromFile(MPI_Comm comm, const char filename[], DM *dm)
6457bee2925SMatthew Knepley {
6467bee2925SMatthew Knepley   PetscMPIInt    rank;
6477bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
6487bee2925SMatthew Knepley   ego            context= NULL, model = NULL;
6497bee2925SMatthew Knepley #endif
650266cfabeSMatthew G. Knepley   PetscBool      printModel = PETSC_FALSE;
6517bee2925SMatthew Knepley   PetscErrorCode ierr;
6527bee2925SMatthew Knepley 
6537bee2925SMatthew Knepley   PetscFunctionBegin;
6547bee2925SMatthew Knepley   PetscValidCharPointer(filename, 2);
6557bee2925SMatthew Knepley   ierr = PetscOptionsGetBool(NULL, NULL, "-dm_plex_egads_print_model", &printModel, NULL);CHKERRQ(ierr);
65655b25c41SPierre Jolivet   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
6577bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
6587bee2925SMatthew Knepley   if (!rank) {
6597bee2925SMatthew Knepley 
6607bee2925SMatthew Knepley     ierr = EG_open(&context);CHKERRQ(ierr);
6617bee2925SMatthew Knepley     ierr = EG_loadModel(context, 0, filename, &model);CHKERRQ(ierr);
6627bee2925SMatthew Knepley     if (printModel) {ierr = DMPlexEGADSPrintModel(model);CHKERRQ(ierr);}
6637bee2925SMatthew Knepley 
6647bee2925SMatthew Knepley   }
6657bee2925SMatthew Knepley   ierr = DMPlexCreateEGADS(comm, context, model, dm);CHKERRQ(ierr);
666c03d1177SJose E. Roman   PetscFunctionReturn(0);
6677bee2925SMatthew Knepley #else
6687bee2925SMatthew Knepley   SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADSLite support. Reconfigure using --download-egads");
6697bee2925SMatthew Knepley #endif
6707bee2925SMatthew Knepley }
671