xref: /petsc/src/dm/impls/plex/plexegads.c (revision 7bee292536c6234ced93c4c61d7c2141d1b085f2)
1a8ededdfSMatthew G. Knepley #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2*7bee2925SMatthew 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 /*@
23a8ededdfSMatthew 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.
24a8ededdfSMatthew G. Knepley 
25a8ededdfSMatthew G. Knepley   Not collective
26a8ededdfSMatthew G. Knepley 
27a8ededdfSMatthew G. Knepley   Input Parameters:
28a8ededdfSMatthew G. Knepley + dm      - The DMPlex object
29a8ededdfSMatthew G. Knepley . p       - The mesh point
30a8ededdfSMatthew G. Knepley - mcoords - A coordinate point lying on the mesh point
31a8ededdfSMatthew G. Knepley 
32a8ededdfSMatthew G. Knepley   Output Parameter:
33a8ededdfSMatthew G. Knepley . gcoords - The closest coordinate point on the geometry model associated with 'p' to the given point
34a8ededdfSMatthew G. Knepley 
35a8ededdfSMatthew G. Knepley   Note: Returns the original coordinates if no geometry model is found. Right now the only supported geometry model is EGADS.
36a8ededdfSMatthew G. Knepley 
37a8ededdfSMatthew G. Knepley   Level: intermediate
38a8ededdfSMatthew G. Knepley 
39a8ededdfSMatthew G. Knepley .seealso: DMRefine(), DMPlexCreate(), DMPlexSetRefinementUniform()
40a8ededdfSMatthew G. Knepley @*/
41a8ededdfSMatthew G. Knepley PetscErrorCode DMPlexSnapToGeomModel(DM dm, PetscInt p, const PetscScalar mcoords[], PetscScalar gcoords[])
42a8ededdfSMatthew G. Knepley {
43a8ededdfSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
44f0fcf0adSMatthew G. Knepley   DM             cdm;
45a8ededdfSMatthew G. Knepley   DMLabel        bodyLabel, faceLabel, edgeLabel;
46a8ededdfSMatthew G. Knepley   PetscContainer modelObj;
47a8ededdfSMatthew G. Knepley   PetscInt       bodyID, faceID, edgeID;
48a8ededdfSMatthew G. Knepley   ego           *bodies;
49f0fcf0adSMatthew G. Knepley   ego            model, geom, body, obj;
50f0fcf0adSMatthew G. Knepley   /* result has to hold derviatives, along with the value */
51f0fcf0adSMatthew G. Knepley   double         params[3], result[18], paramsV[16*3], resultV[16*3];
52a8ededdfSMatthew G. Knepley   int            Nb, oclass, mtype, *senses;
53f0fcf0adSMatthew G. Knepley   Vec            coordinatesLocal;
54f0fcf0adSMatthew G. Knepley   PetscScalar   *coords = NULL;
55f0fcf0adSMatthew G. Knepley   PetscInt       Nv, v, Np = 0, pm;
56a8ededdfSMatthew G. Knepley #endif
57f0fcf0adSMatthew G. Knepley   PetscInt       dE, d;
58a8ededdfSMatthew G. Knepley   PetscErrorCode ierr;
59a8ededdfSMatthew G. Knepley 
60a8ededdfSMatthew G. Knepley   PetscFunctionBegin;
61f0fcf0adSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr);
62a8ededdfSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS
63a8ededdfSMatthew G. Knepley   ierr = DMGetLabel(dm, "EGADS Body ID",   &bodyLabel);CHKERRQ(ierr);
64a8ededdfSMatthew G. Knepley   ierr = DMGetLabel(dm, "EGADS Face ID",   &faceLabel);CHKERRQ(ierr);
65a8ededdfSMatthew G. Knepley   ierr = DMGetLabel(dm, "EGADS Edge ID",   &edgeLabel);CHKERRQ(ierr);
66a8ededdfSMatthew G. Knepley   if (!bodyLabel || !faceLabel || !edgeLabel) {
67f0fcf0adSMatthew G. Knepley     for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
68a8ededdfSMatthew G. Knepley     PetscFunctionReturn(0);
69a8ededdfSMatthew G. Knepley   }
70f0fcf0adSMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
71f0fcf0adSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinatesLocal);CHKERRQ(ierr);
72a8ededdfSMatthew G. Knepley   ierr = DMLabelGetValue(bodyLabel,   p, &bodyID);CHKERRQ(ierr);
73a8ededdfSMatthew G. Knepley   ierr = DMLabelGetValue(faceLabel,   p, &faceID);CHKERRQ(ierr);
74a8ededdfSMatthew G. Knepley   ierr = DMLabelGetValue(edgeLabel,   p, &edgeID);CHKERRQ(ierr);
75a8ededdfSMatthew G. Knepley   ierr = PetscObjectQuery((PetscObject) dm, "EGADS Model", (PetscObject *) &modelObj);CHKERRQ(ierr);
76a8ededdfSMatthew G. Knepley   ierr = PetscContainerGetPointer(modelObj, (void **) &model);CHKERRQ(ierr);
77a8ededdfSMatthew G. Knepley   ierr = EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses);CHKERRQ(ierr);
78f0fcf0adSMatthew G. Knepley   if (bodyID < 0 || bodyID >= Nb) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %D is not in [0, %d)", bodyID, Nb);
79a8ededdfSMatthew G. Knepley   body = bodies[bodyID];
80f0fcf0adSMatthew G. Knepley 
81f0fcf0adSMatthew G. Knepley   if (edgeID >= 0)      {ierr = EG_objectBodyTopo(body, EDGE, edgeID, &obj);CHKERRQ(ierr); Np = 1;}
82f0fcf0adSMatthew G. Knepley   else if (faceID >= 0) {ierr = EG_objectBodyTopo(body, FACE, faceID, &obj);CHKERRQ(ierr); Np = 2;}
83f0fcf0adSMatthew G. Knepley   else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D is not in edge or face label for EGADS", p);
84f0fcf0adSMatthew G. Knepley   /* Calculate parameters (t or u,v) for vertices */
85f0fcf0adSMatthew G. Knepley   ierr = DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords);CHKERRQ(ierr);
86f0fcf0adSMatthew G. Knepley   Nv  /= dE;
87f0fcf0adSMatthew G. Knepley   if (Nv == 1) {
88f0fcf0adSMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords);CHKERRQ(ierr);
89f0fcf0adSMatthew G. Knepley     for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
90f0fcf0adSMatthew G. Knepley     PetscFunctionReturn(0);
91a8ededdfSMatthew G. Knepley   }
92f0fcf0adSMatthew G. Knepley   if (Nv > 16) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %D coordinates associated to point %D", Nv, p);
93f0fcf0adSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {ierr = EG_invEvaluate(obj, &coords[v*dE], &paramsV[v*3], &resultV[v*3]);CHKERRQ(ierr);}
94f0fcf0adSMatthew G. Knepley   ierr = DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords);CHKERRQ(ierr);
95f0fcf0adSMatthew G. Knepley   /* Calculate parameters (t or u,v) for new vertex at edge midpoint */
96f0fcf0adSMatthew G. Knepley   for (pm = 0; pm < Np; ++pm) {
97f0fcf0adSMatthew G. Knepley     params[pm] = 0.;
98f0fcf0adSMatthew G. Knepley     for (v = 0; v < Nv; ++v) {params[pm] += paramsV[v*3+pm];}
99f0fcf0adSMatthew G. Knepley     params[pm] /= Nv;
100f0fcf0adSMatthew G. Knepley   }
101f0fcf0adSMatthew G. Knepley   /* TODO Check
102f0fcf0adSMatthew G. Knepley     double range[4]; // [umin, umax, vmin, vmax]
103f0fcf0adSMatthew G. Knepley     int    peri;
104f0fcf0adSMatthew G. Knepley     ierr = EG_getRange(face, range, &peri);CHKERRQ(ierr);
105f0fcf0adSMatthew G. Knepley     if ((paramsNew[0] < range[0]) || (paramsNew[0] > range[1]) || (paramsNew[1] < range[2]) || (paramsNew[1] > range[3])) SETERRQ();
106f0fcf0adSMatthew G. Knepley   */
107f0fcf0adSMatthew G. Knepley   /* Put coordinates for new vertex in result[] */
108f0fcf0adSMatthew G. Knepley   ierr = EG_evaluate(obj, params, result);CHKERRQ(ierr);
109f0fcf0adSMatthew G. Knepley   for (d = 0; d < dE; ++d) gcoords[d] = result[d];
110a8ededdfSMatthew G. Knepley #else
111f0fcf0adSMatthew G. Knepley   for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
112a8ededdfSMatthew G. Knepley #endif
113a8ededdfSMatthew G. Knepley   PetscFunctionReturn(0);
114a8ededdfSMatthew G. Knepley }
115*7bee2925SMatthew Knepley 
116*7bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
117*7bee2925SMatthew Knepley static PetscErrorCode DMPlexEGADSPrintModel(ego model)
118*7bee2925SMatthew Knepley {
119*7bee2925SMatthew Knepley   ego            geom, *bodies, *objs, *nobjs, *mobjs, *lobjs;
120*7bee2925SMatthew Knepley   int            oclass, mtype, *senses;
121*7bee2925SMatthew Knepley   int            Nb, b;
122*7bee2925SMatthew Knepley   PetscErrorCode ierr;
123*7bee2925SMatthew Knepley 
124*7bee2925SMatthew Knepley   PetscFunctionBeginUser;
125*7bee2925SMatthew Knepley   /* test bodyTopo functions */
126*7bee2925SMatthew Knepley   ierr = EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses);CHKERRQ(ierr);
127*7bee2925SMatthew Knepley   ierr = PetscPrintf(PETSC_COMM_SELF, " Number of BODIES (nbodies): %d \n", Nb);CHKERRQ(ierr);
128*7bee2925SMatthew Knepley 
129*7bee2925SMatthew Knepley   for (b = 0; b < Nb; ++b) {
130*7bee2925SMatthew Knepley     ego body = bodies[b];
131*7bee2925SMatthew Knepley     int id, Nsh, Nf, Nl, l, Ne, e, Nv, v;
132*7bee2925SMatthew Knepley 
133*7bee2925SMatthew Knepley     /* Output Basic Model Topology */
134*7bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, SHELL, &Nsh, &objs);CHKERRQ(ierr);
135*7bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of SHELLS: %d \n", Nsh);CHKERRQ(ierr);
136*7bee2925SMatthew Knepley     EG_free(objs);
137*7bee2925SMatthew Knepley 
138*7bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, FACE,  &Nf, &objs);CHKERRQ(ierr);
139*7bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of FACES: %d \n", Nf);CHKERRQ(ierr);
140*7bee2925SMatthew Knepley     EG_free(objs);
141*7bee2925SMatthew Knepley 
142*7bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, LOOP,  &Nl, &lobjs);CHKERRQ(ierr);
143*7bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of LOOPS: %d \n", Nl);CHKERRQ(ierr);
144*7bee2925SMatthew Knepley 
145*7bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, EDGE,  &Ne, &objs);CHKERRQ(ierr);
146*7bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of EDGES: %d \n", Ne);CHKERRQ(ierr);
147*7bee2925SMatthew Knepley     EG_free(objs);
148*7bee2925SMatthew Knepley 
149*7bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, NODE,  &Nv, &objs);CHKERRQ(ierr);
150*7bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "   Number of NODES: %d \n", Nv);CHKERRQ(ierr);
151*7bee2925SMatthew Knepley     EG_free(objs);
152*7bee2925SMatthew Knepley 
153*7bee2925SMatthew Knepley     for (l = 0; l < Nl; ++l) {
154*7bee2925SMatthew Knepley       ego loop = lobjs[l];
155*7bee2925SMatthew Knepley 
156*7bee2925SMatthew Knepley       id   = EG_indexBodyTopo(body, loop);
157*7bee2925SMatthew Knepley       ierr = PetscPrintf(PETSC_COMM_SELF, "          LOOP ID: %d\n", id);CHKERRQ(ierr);
158*7bee2925SMatthew Knepley 
159*7bee2925SMatthew Knepley       /* Get EDGE info which associated with the current LOOP */
160*7bee2925SMatthew Knepley       ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
161*7bee2925SMatthew Knepley 
162*7bee2925SMatthew Knepley       for (e = 0; e < Ne; ++e) {
163*7bee2925SMatthew Knepley         ego    edge     = objs[e];
164*7bee2925SMatthew Knepley         double range[4] = {0., 0., 0., 0.};
165*7bee2925SMatthew Knepley         double point[3] = {0., 0., 0.};
166*7bee2925SMatthew Knepley         int    peri;
167*7bee2925SMatthew Knepley 
168*7bee2925SMatthew Knepley         id = EG_indexBodyTopo(body, edge);CHKERRQ(ierr);
169*7bee2925SMatthew Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "            EDGE ID: %d\n", id);CHKERRQ(ierr);
170*7bee2925SMatthew Knepley 
171*7bee2925SMatthew Knepley         ierr = EG_getRange(objs[e], range, &peri);CHKERRQ(ierr);
172*7bee2925SMatthew Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, " Range = %lf, %lf, %lf, %lf \n", range[0], range[1], range[2], range[3]);
173*7bee2925SMatthew Knepley 
174*7bee2925SMatthew Knepley         /* Get NODE info which associated with the current EDGE */
175*7bee2925SMatthew Knepley         ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);CHKERRQ(ierr);
176*7bee2925SMatthew Knepley 
177*7bee2925SMatthew Knepley         for (v = 0; v < Nv; ++v) {
178*7bee2925SMatthew Knepley           ego    vertex = nobjs[v];
179*7bee2925SMatthew Knepley           double limits[4];
180*7bee2925SMatthew Knepley           int    dummy;
181*7bee2925SMatthew Knepley 
182*7bee2925SMatthew Knepley           ierr = EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses);CHKERRQ(ierr);
183*7bee2925SMatthew Knepley           id   = EG_indexBodyTopo(body, vertex);
184*7bee2925SMatthew Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "              NODE ID: %d \n", id);CHKERRQ(ierr);
185*7bee2925SMatthew Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "                 (x, y, z) = (%lf, %lf, %lf) \n", limits[0], limits[1], limits[2]);
186*7bee2925SMatthew Knepley 
187*7bee2925SMatthew Knepley           point[0] = point[0] + limits[0];
188*7bee2925SMatthew Knepley           point[1] = point[1] + limits[1];
189*7bee2925SMatthew Knepley           point[2] = point[2] + limits[2];
190*7bee2925SMatthew Knepley         }
191*7bee2925SMatthew Knepley       }
192*7bee2925SMatthew Knepley     }
193*7bee2925SMatthew Knepley     EG_free(lobjs);
194*7bee2925SMatthew Knepley   }
195*7bee2925SMatthew Knepley   PetscFunctionReturn(0);
196*7bee2925SMatthew Knepley }
197*7bee2925SMatthew Knepley 
198*7bee2925SMatthew Knepley static PetscErrorCode DMPlexEGADSDestroy_Private(void *context)
199*7bee2925SMatthew Knepley {
200*7bee2925SMatthew Knepley   if (context) EG_close((ego) context);
201*7bee2925SMatthew Knepley   return 0;
202*7bee2925SMatthew Knepley }
203*7bee2925SMatthew Knepley 
204*7bee2925SMatthew Knepley static PetscErrorCode DMPlexCreateEGADS(MPI_Comm comm, ego context, ego model, DM *newdm)
205*7bee2925SMatthew Knepley {
206*7bee2925SMatthew Knepley   DMLabel        bodyLabel, faceLabel, edgeLabel;
207*7bee2925SMatthew Knepley   PetscInt       cStart, cEnd, c;
208*7bee2925SMatthew Knepley   /* EGADSLite variables */
209*7bee2925SMatthew Knepley   ego            geom, *bodies, *objs, *nobjs, *mobjs, *lobjs;
210*7bee2925SMatthew Knepley   int            oclass, mtype, nbodies, *senses;
211*7bee2925SMatthew Knepley   int            b;
212*7bee2925SMatthew Knepley   /* PETSc variables */
213*7bee2925SMatthew Knepley   DM             dm;
214*7bee2925SMatthew Knepley   PetscHMapI     edgeMap = NULL;
215*7bee2925SMatthew 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;
216*7bee2925SMatthew Knepley   PetscInt      *cells  = NULL, *cone = NULL;
217*7bee2925SMatthew Knepley   PetscReal     *coords = NULL;
218*7bee2925SMatthew Knepley   PetscMPIInt    rank;
219*7bee2925SMatthew Knepley   PetscErrorCode ierr;
220*7bee2925SMatthew Knepley 
221*7bee2925SMatthew Knepley   PetscFunctionBegin;
222*7bee2925SMatthew Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
223*7bee2925SMatthew Knepley   if (!rank) {
224*7bee2925SMatthew Knepley     /* ---------------------------------------------------------------------------------------------------
225*7bee2925SMatthew Knepley     Generate Petsc Plex
226*7bee2925SMatthew Knepley       Get all Nodes in model, record coordinates in a correctly formatted array
227*7bee2925SMatthew Knepley       Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array
228*7bee2925SMatthew Knepley       We need to uniformly refine the initial geometry to guarantee a valid mesh
229*7bee2925SMatthew Knepley     */
230*7bee2925SMatthew Knepley 
231*7bee2925SMatthew Knepley     /* Calculate cell and vertex sizes */
232*7bee2925SMatthew Knepley     ierr = EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses);CHKERRQ(ierr);
233*7bee2925SMatthew Knepley     ierr = PetscHMapICreate(&edgeMap);CHKERRQ(ierr);
234*7bee2925SMatthew Knepley     numEdges = 0;
235*7bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
236*7bee2925SMatthew Knepley       ego body = bodies[b];
237*7bee2925SMatthew Knepley       int id, Nl, l, Nv, v;
238*7bee2925SMatthew Knepley 
239*7bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs);CHKERRQ(ierr);
240*7bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
241*7bee2925SMatthew Knepley         ego loop = lobjs[l];
242*7bee2925SMatthew Knepley         int Ner  = 0, Ne, e, Nc;
243*7bee2925SMatthew Knepley 
244*7bee2925SMatthew Knepley         ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
245*7bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
246*7bee2925SMatthew Knepley           ego edge = objs[e];
247*7bee2925SMatthew Knepley           int Nv, id;
248*7bee2925SMatthew Knepley           PetscHashIter iter;
249*7bee2925SMatthew Knepley           PetscBool     found;
250*7bee2925SMatthew Knepley 
251*7bee2925SMatthew Knepley           ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);
252*7bee2925SMatthew Knepley           if (mtype == DEGENERATE) continue;
253*7bee2925SMatthew Knepley           id   = EG_indexBodyTopo(body, edge);CHKERRQ(ierr);
254*7bee2925SMatthew Knepley           ierr = PetscHMapIFind(edgeMap, id-1, &iter, &found);CHKERRQ(ierr);
255*7bee2925SMatthew Knepley           if (!found) {ierr = PetscHMapISet(edgeMap, id-1, numEdges++);CHKERRQ(ierr);}
256*7bee2925SMatthew Knepley           ++Ner;
257*7bee2925SMatthew Knepley         }
258*7bee2925SMatthew Knepley         if (Ner == 2)      {Nc = 2;}
259*7bee2925SMatthew Knepley         else if (Ner == 3) {Nc = 4;}
260*7bee2925SMatthew Knepley         else if (Ner == 4) {Nc = 8; ++numQuads;}
261*7bee2925SMatthew Knepley         else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot support loop with %d edges", Ner);
262*7bee2925SMatthew Knepley         numCells += Nc;
263*7bee2925SMatthew Knepley         newCells += Nc-1;
264*7bee2925SMatthew Knepley         maxCorners = PetscMax(Ner*2+1, maxCorners);
265*7bee2925SMatthew Knepley       }
266*7bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs);CHKERRQ(ierr);
267*7bee2925SMatthew Knepley       for (v = 0; v < Nv; ++v) {
268*7bee2925SMatthew Knepley         ego vertex = nobjs[v];
269*7bee2925SMatthew Knepley 
270*7bee2925SMatthew Knepley         id = EG_indexBodyTopo(body, vertex);
271*7bee2925SMatthew Knepley         /* TODO: Instead of assuming contiguous ids, we could use a hash table */
272*7bee2925SMatthew Knepley         numVertices = PetscMax(id, numVertices);
273*7bee2925SMatthew Knepley       }
274*7bee2925SMatthew Knepley       EG_free(lobjs);
275*7bee2925SMatthew Knepley       EG_free(nobjs);
276*7bee2925SMatthew Knepley     }
277*7bee2925SMatthew Knepley     ierr = PetscHMapIGetSize(edgeMap, &numEdges);CHKERRQ(ierr);
278*7bee2925SMatthew Knepley     newVertices  = numEdges + numQuads;
279*7bee2925SMatthew Knepley     numVertices += newVertices;
280*7bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "\nPLEX Input Array Checkouts\n");CHKERRQ(ierr);
281*7bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, " Total Number of Unique Cells    = %D (%D)\n", numCells, newCells);CHKERRQ(ierr);
282*7bee2925SMatthew Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, " Total Number of Unique Vertices = %D (%D) \n", numVertices, newVertices);CHKERRQ(ierr);
283*7bee2925SMatthew Knepley 
284*7bee2925SMatthew Knepley     dim        = 2; /* Assume 3D Models :: Need to update to handle 2D Models in the future */
285*7bee2925SMatthew Knepley     cdim       = 3; /* Assume 3D Models :: Need to update to handle 2D Models in the future */
286*7bee2925SMatthew Knepley     numCorners = 3; /* Split cells into triangles */
287*7bee2925SMatthew Knepley     ierr = PetscMalloc3(numVertices*cdim, &coords, numCells*numCorners, &cells, maxCorners, &cone);CHKERRQ(ierr);
288*7bee2925SMatthew Knepley 
289*7bee2925SMatthew Knepley     /* Get vertex coordinates */
290*7bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
291*7bee2925SMatthew Knepley       ego body = bodies[b];
292*7bee2925SMatthew Knepley       int id, Nv, v;
293*7bee2925SMatthew Knepley 
294*7bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs);CHKERRQ(ierr);
295*7bee2925SMatthew Knepley       for (v = 0; v < Nv; ++v) {
296*7bee2925SMatthew Knepley         ego    vertex = nobjs[v];
297*7bee2925SMatthew Knepley         double limits[4];
298*7bee2925SMatthew Knepley         int    dummy;
299*7bee2925SMatthew Knepley 
300*7bee2925SMatthew Knepley         ierr = EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses);CHKERRQ(ierr);
301*7bee2925SMatthew Knepley         id   = EG_indexBodyTopo(body, vertex);CHKERRQ(ierr);
302*7bee2925SMatthew Knepley         coords[(id-1)*cdim+0] = limits[0];
303*7bee2925SMatthew Knepley         coords[(id-1)*cdim+1] = limits[1];
304*7bee2925SMatthew Knepley         coords[(id-1)*cdim+2] = limits[2];
305*7bee2925SMatthew Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "    Node ID = %d (%d)\n", id, id-1);
306*7bee2925SMatthew Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "      (x,y,z) = (%lf, %lf, %lf) \n \n", coords[(id-1)*cdim+0], coords[(id-1)*cdim+1],coords[(id-1)*cdim+2]);
307*7bee2925SMatthew Knepley       }
308*7bee2925SMatthew Knepley       EG_free(nobjs);
309*7bee2925SMatthew Knepley     }
310*7bee2925SMatthew Knepley     ierr = PetscHMapIClear(edgeMap);CHKERRQ(ierr);
311*7bee2925SMatthew Knepley     fOff     = numVertices - newVertices + numEdges;
312*7bee2925SMatthew Knepley     numEdges = 0;
313*7bee2925SMatthew Knepley     numQuads = 0;
314*7bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
315*7bee2925SMatthew Knepley       ego body = bodies[b];
316*7bee2925SMatthew Knepley       int Nl, l;
317*7bee2925SMatthew Knepley 
318*7bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs);CHKERRQ(ierr);
319*7bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
320*7bee2925SMatthew Knepley         ego loop = lobjs[l];
321*7bee2925SMatthew Knepley         int lid, Ner = 0, Ne, e;
322*7bee2925SMatthew Knepley 
323*7bee2925SMatthew Knepley         lid  = EG_indexBodyTopo(body, loop);CHKERRQ(ierr);
324*7bee2925SMatthew Knepley         ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
325*7bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
326*7bee2925SMatthew Knepley           ego       edge = objs[e];
327*7bee2925SMatthew Knepley           int       eid, Nv;
328*7bee2925SMatthew Knepley           PetscHashIter iter;
329*7bee2925SMatthew Knepley           PetscBool     found;
330*7bee2925SMatthew Knepley 
331*7bee2925SMatthew Knepley           ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);
332*7bee2925SMatthew Knepley           if (mtype == DEGENERATE) continue;
333*7bee2925SMatthew Knepley           ++Ner;
334*7bee2925SMatthew Knepley           eid  = EG_indexBodyTopo(body, edge);CHKERRQ(ierr);
335*7bee2925SMatthew Knepley           ierr = PetscHMapIFind(edgeMap, eid-1, &iter, &found);CHKERRQ(ierr);
336*7bee2925SMatthew Knepley           if (!found) {
337*7bee2925SMatthew Knepley             PetscInt v = numVertices - newVertices + numEdges;
338*7bee2925SMatthew Knepley             double range[4], params[3] = {0., 0., 0.}, result[18];
339*7bee2925SMatthew Knepley             int    periodic[2];
340*7bee2925SMatthew Knepley 
341*7bee2925SMatthew Knepley             ierr = PetscHMapISet(edgeMap, eid-1, numEdges++);CHKERRQ(ierr);
342*7bee2925SMatthew Knepley             ierr = EG_getRange(edge, range, periodic);CHKERRQ(ierr);
343*7bee2925SMatthew Knepley             params[0] = 0.5*(range[0] + range[1]);
344*7bee2925SMatthew Knepley             ierr = EG_evaluate(edge, params, result);CHKERRQ(ierr);
345*7bee2925SMatthew Knepley             coords[v*cdim+0] = result[0];
346*7bee2925SMatthew Knepley             coords[v*cdim+1] = result[1];
347*7bee2925SMatthew Knepley             coords[v*cdim+2] = result[2];
348*7bee2925SMatthew Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, "    Edge ID = %d (%D) \n", eid, v);
349*7bee2925SMatthew Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, "      (x,y,z) = (%lf, %lf, %lf)\n", coords[v*cdim+0], coords[v*cdim+1],coords[v*cdim+2]);
350*7bee2925SMatthew Knepley             params[0] = range[0];
351*7bee2925SMatthew Knepley             ierr = EG_evaluate(edge, params, result);CHKERRQ(ierr);
352*7bee2925SMatthew Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, "      between (%lf, %lf, %lf)", result[0], result[1], result[2]);
353*7bee2925SMatthew Knepley             params[0] = range[1];
354*7bee2925SMatthew Knepley             ierr = EG_evaluate(edge, params, result);CHKERRQ(ierr);
355*7bee2925SMatthew Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, " and (%lf, %lf, %lf)\n\n", result[0], result[1], result[2]);
356*7bee2925SMatthew Knepley           }
357*7bee2925SMatthew Knepley         }
358*7bee2925SMatthew Knepley         if (Ner == 4) {
359*7bee2925SMatthew Knepley           PetscInt v = fOff + numQuads++;
360*7bee2925SMatthew Knepley           ego     *fobjs;
361*7bee2925SMatthew Knepley           double   range[4], params[3] = {0., 0., 0.}, result[18];
362*7bee2925SMatthew Knepley           int      Nf, face, periodic[2];
363*7bee2925SMatthew Knepley 
364*7bee2925SMatthew Knepley           ierr = EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs);CHKERRQ(ierr);
365*7bee2925SMatthew Knepley           if (Nf != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Loop %d has %d faces, instead of 1", lid-1, Nf);
366*7bee2925SMatthew Knepley           face = EG_indexBodyTopo(body, fobjs[0]);CHKERRQ(ierr);
367*7bee2925SMatthew Knepley           ierr = EG_getRange(fobjs[0], range, periodic);CHKERRQ(ierr);
368*7bee2925SMatthew Knepley           params[0] = 0.5*(range[0] + range[1]);
369*7bee2925SMatthew Knepley           params[1] = 0.5*(range[2] + range[3]);
370*7bee2925SMatthew Knepley           ierr = EG_evaluate(fobjs[0], params, result);CHKERRQ(ierr);
371*7bee2925SMatthew Knepley           coords[v*cdim+0] = result[0];
372*7bee2925SMatthew Knepley           coords[v*cdim+1] = result[1];
373*7bee2925SMatthew Knepley           coords[v*cdim+2] = result[2];
374*7bee2925SMatthew Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "    Face ID = %d (%D) \n", face-1, v);
375*7bee2925SMatthew Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "      (x,y,z) = (%lf, %lf, %lf) \n \n", coords[v*cdim+0], coords[v*cdim+1],coords[v*cdim+2]);
376*7bee2925SMatthew Knepley         }
377*7bee2925SMatthew Knepley       }
378*7bee2925SMatthew Knepley     }
379*7bee2925SMatthew Knepley     if (numEdges + numQuads != newVertices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of new vertices %D != %D previous count", numEdges + numQuads, newVertices);
380*7bee2925SMatthew Knepley     CHKMEMQ;
381*7bee2925SMatthew Knepley 
382*7bee2925SMatthew Knepley     /* Get cell vertices by traversing loops */
383*7bee2925SMatthew Knepley     numQuads = 0;
384*7bee2925SMatthew Knepley     cOff     = 0;
385*7bee2925SMatthew Knepley     for (b = 0; b < nbodies; ++b) {
386*7bee2925SMatthew Knepley       ego body = bodies[b];
387*7bee2925SMatthew Knepley       int id, Nl, l;
388*7bee2925SMatthew Knepley 
389*7bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs);CHKERRQ(ierr);
390*7bee2925SMatthew Knepley       for (l = 0; l < Nl; ++l) {
391*7bee2925SMatthew Knepley         ego loop = lobjs[l];
392*7bee2925SMatthew Knepley         int lid, Ner = 0, Ne, e, nc = 0, c, Nt, t;
393*7bee2925SMatthew Knepley 
394*7bee2925SMatthew Knepley         lid  = EG_indexBodyTopo(body, loop);CHKERRQ(ierr);
395*7bee2925SMatthew Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "    LOOP ID: %d \n", lid);CHKERRQ(ierr);
396*7bee2925SMatthew Knepley         ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
397*7bee2925SMatthew Knepley 
398*7bee2925SMatthew Knepley         for (e = 0; e < Ne; ++e) {
399*7bee2925SMatthew Knepley           ego edge = objs[e];
400*7bee2925SMatthew Knepley           int points[3];
401*7bee2925SMatthew Knepley           int eid, Nv, v, tmp;
402*7bee2925SMatthew Knepley 
403*7bee2925SMatthew Knepley           eid  = EG_indexBodyTopo(body, edge);
404*7bee2925SMatthew Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "      EDGE ID: %d \n", eid);CHKERRQ(ierr);
405*7bee2925SMatthew Knepley           ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);
406*7bee2925SMatthew Knepley           if (mtype == DEGENERATE) {ierr = PetscPrintf(PETSC_COMM_SELF, "        EGDE %d is DEGENERATE \n", eid);CHKERRQ(ierr); continue;}
407*7bee2925SMatthew Knepley           else                     {++Ner;}
408*7bee2925SMatthew Knepley           if (Nv != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Edge %d has %d vertices != 2", eid, Nv);
409*7bee2925SMatthew Knepley 
410*7bee2925SMatthew Knepley           for (v = 0; v < Nv; ++v) {
411*7bee2925SMatthew Knepley             ego vertex = nobjs[v];
412*7bee2925SMatthew Knepley 
413*7bee2925SMatthew Knepley             id = EG_indexBodyTopo(body, vertex);
414*7bee2925SMatthew Knepley             points[v*2] = id-1;
415*7bee2925SMatthew Knepley           }
416*7bee2925SMatthew Knepley           {
417*7bee2925SMatthew Knepley             PetscInt edgeNum;
418*7bee2925SMatthew Knepley 
419*7bee2925SMatthew Knepley             ierr = PetscHMapIGet(edgeMap, eid-1, &edgeNum);CHKERRQ(ierr);
420*7bee2925SMatthew Knepley             points[1] = numVertices - newVertices + edgeNum;
421*7bee2925SMatthew Knepley           }
422*7bee2925SMatthew Knepley           /* EGADS loops are not oriented, but seem to be in order, so we must piece them together */
423*7bee2925SMatthew Knepley           if (!nc) {
424*7bee2925SMatthew Knepley             for (v = 0; v < Nv+1; ++v) cone[nc++] = points[v];
425*7bee2925SMatthew Knepley           } else {
426*7bee2925SMatthew Knepley             if (cone[nc-1] == points[0])      {cone[nc++] = points[1]; if (cone[0] != points[2]) cone[nc++] = points[2];}
427*7bee2925SMatthew Knepley             else if (cone[nc-1] == points[2]) {cone[nc++] = points[1]; if (cone[0] != points[0]) cone[nc++] = points[0];}
428*7bee2925SMatthew 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];}
429*7bee2925SMatthew 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];}
430*7bee2925SMatthew Knepley             else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %d does not match its predecessor", eid);
431*7bee2925SMatthew Knepley           }
432*7bee2925SMatthew Knepley         }
433*7bee2925SMatthew Knepley         if (nc != 2*Ner)     SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %D != %D", nc, 2*Ner);
434*7bee2925SMatthew Knepley         if (Ner == 4) {cone[nc++] = numVertices - newVertices + numEdges + numQuads++;}
435*7bee2925SMatthew Knepley         if (nc > maxCorners) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %D > %D max", nc, maxCorners);
436*7bee2925SMatthew Knepley         /* Triangulate the loop */
437*7bee2925SMatthew Knepley         switch (Ner) {
438*7bee2925SMatthew Knepley           case 2: /* Bi-Segment -> 2 triangles */
439*7bee2925SMatthew Knepley             Nt = 2;
440*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[0];
441*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[1];
442*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[2];
443*7bee2925SMatthew Knepley             ++cOff;
444*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[0];
445*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[2];
446*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[3];
447*7bee2925SMatthew Knepley             ++cOff;
448*7bee2925SMatthew Knepley             break;
449*7bee2925SMatthew Knepley           case 3: /* Triangle   -> 4 triangles */
450*7bee2925SMatthew Knepley             Nt = 4;
451*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[0];
452*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[1];
453*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[5];
454*7bee2925SMatthew Knepley             ++cOff;
455*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[1];
456*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[2];
457*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[3];
458*7bee2925SMatthew Knepley             ++cOff;
459*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[5];
460*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[3];
461*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[4];
462*7bee2925SMatthew Knepley             ++cOff;
463*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[1];
464*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[3];
465*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[5];
466*7bee2925SMatthew Knepley             ++cOff;
467*7bee2925SMatthew Knepley             break;
468*7bee2925SMatthew Knepley           case 4: /* Quad       -> 8 triangles */
469*7bee2925SMatthew Knepley             Nt = 8;
470*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[0];
471*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[1];
472*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[7];
473*7bee2925SMatthew Knepley             ++cOff;
474*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[1];
475*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[2];
476*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[3];
477*7bee2925SMatthew Knepley             ++cOff;
478*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[3];
479*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[4];
480*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[5];
481*7bee2925SMatthew Knepley             ++cOff;
482*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[5];
483*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[6];
484*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[7];
485*7bee2925SMatthew Knepley             ++cOff;
486*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[8];
487*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[1];
488*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[3];
489*7bee2925SMatthew Knepley             ++cOff;
490*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[8];
491*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[3];
492*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[5];
493*7bee2925SMatthew Knepley             ++cOff;
494*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[8];
495*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[5];
496*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[7];
497*7bee2925SMatthew Knepley             ++cOff;
498*7bee2925SMatthew Knepley             cells[cOff*numCorners+0] = cone[8];
499*7bee2925SMatthew Knepley             cells[cOff*numCorners+1] = cone[7];
500*7bee2925SMatthew Knepley             cells[cOff*numCorners+2] = cone[1];
501*7bee2925SMatthew Knepley             ++cOff;
502*7bee2925SMatthew Knepley             break;
503*7bee2925SMatthew Knepley           default: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d edges, which we do not support", lid, Ner);
504*7bee2925SMatthew Knepley         }
505*7bee2925SMatthew Knepley         for (t = 0; t < Nt; ++t) {
506*7bee2925SMatthew Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "      LOOP Corner NODEs Triangle %D (", t);CHKERRQ(ierr);
507*7bee2925SMatthew Knepley           for (c = 0; c < numCorners; ++c) {
508*7bee2925SMatthew Knepley             if (c > 0) {ierr = PetscPrintf(PETSC_COMM_SELF, ", ");CHKERRQ(ierr);}
509*7bee2925SMatthew Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, "%D", cells[(cOff-Nt+t)*numCorners+c]);CHKERRQ(ierr);
510*7bee2925SMatthew Knepley           }
511*7bee2925SMatthew Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, ")\n");CHKERRQ(ierr);
512*7bee2925SMatthew Knepley         }
513*7bee2925SMatthew Knepley       }
514*7bee2925SMatthew Knepley       EG_free(lobjs);
515*7bee2925SMatthew Knepley     }
516*7bee2925SMatthew Knepley   }
517*7bee2925SMatthew Knepley   if (cOff != numCells) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count of total cells %D != %D previous count", cOff, numCells);
518*7bee2925SMatthew Knepley   ierr = DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numVertices, numCorners, PETSC_TRUE, cells, cdim, coords, &dm);CHKERRQ(ierr);
519*7bee2925SMatthew Knepley   ierr = PetscFree3(coords, cells, cone);CHKERRQ(ierr);
520*7bee2925SMatthew Knepley   /* Embed EGADS model in DM */
521*7bee2925SMatthew Knepley   {
522*7bee2925SMatthew Knepley     PetscContainer modelObj, contextObj;
523*7bee2925SMatthew Knepley 
524*7bee2925SMatthew Knepley     ierr = PetscContainerCreate(PETSC_COMM_SELF, &modelObj);CHKERRQ(ierr);
525*7bee2925SMatthew Knepley     ierr = PetscContainerSetPointer(modelObj, model);CHKERRQ(ierr);
526*7bee2925SMatthew Knepley     ierr = PetscObjectCompose((PetscObject) dm, "EGADS Model", (PetscObject) modelObj);CHKERRQ(ierr);
527*7bee2925SMatthew Knepley     ierr = PetscContainerDestroy(&modelObj);CHKERRQ(ierr);
528*7bee2925SMatthew Knepley 
529*7bee2925SMatthew Knepley     ierr = PetscContainerCreate(PETSC_COMM_SELF, &contextObj);CHKERRQ(ierr);
530*7bee2925SMatthew Knepley     ierr = PetscContainerSetPointer(contextObj, context);CHKERRQ(ierr);
531*7bee2925SMatthew Knepley     ierr = PetscContainerSetUserDestroy(contextObj, DMPlexEGADSDestroy_Private);CHKERRQ(ierr);
532*7bee2925SMatthew Knepley     ierr = PetscObjectCompose((PetscObject) dm, "EGADS Context", (PetscObject) contextObj);CHKERRQ(ierr);
533*7bee2925SMatthew Knepley     ierr = PetscContainerDestroy(&contextObj);CHKERRQ(ierr);
534*7bee2925SMatthew Knepley   }
535*7bee2925SMatthew Knepley   /* Label points */
536*7bee2925SMatthew Knepley   ierr = DMCreateLabel(dm, "EGADS Body ID");CHKERRQ(ierr);
537*7bee2925SMatthew Knepley   ierr = DMGetLabel(dm, "EGADS Body ID", &bodyLabel);CHKERRQ(ierr);
538*7bee2925SMatthew Knepley   ierr = DMCreateLabel(dm, "EGADS Face ID");CHKERRQ(ierr);
539*7bee2925SMatthew Knepley   ierr = DMGetLabel(dm, "EGADS Face ID", &faceLabel);CHKERRQ(ierr);
540*7bee2925SMatthew Knepley   ierr = DMCreateLabel(dm, "EGADS Edge ID");CHKERRQ(ierr);
541*7bee2925SMatthew Knepley   ierr = DMGetLabel(dm, "EGADS Edge ID", &edgeLabel);CHKERRQ(ierr);
542*7bee2925SMatthew Knepley   cOff = 0;
543*7bee2925SMatthew Knepley   for (b = 0; b < nbodies; ++b) {
544*7bee2925SMatthew Knepley     ego body = bodies[b];
545*7bee2925SMatthew Knepley     int id, Nl, l;
546*7bee2925SMatthew Knepley 
547*7bee2925SMatthew Knepley     ierr = EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs);CHKERRQ(ierr);
548*7bee2925SMatthew Knepley     for (l = 0; l < Nl; ++l) {
549*7bee2925SMatthew Knepley       ego  loop = lobjs[l];
550*7bee2925SMatthew Knepley       ego *fobjs;
551*7bee2925SMatthew Knepley       int  lid, Nf, fid, Ner = 0, Ne, e, Nt = 0, t;
552*7bee2925SMatthew Knepley 
553*7bee2925SMatthew Knepley       lid  = EG_indexBodyTopo(body, loop);CHKERRQ(ierr);
554*7bee2925SMatthew Knepley       ierr = EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs);CHKERRQ(ierr);
555*7bee2925SMatthew Knepley       if (Nf > 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf);CHKERRQ(ierr);
556*7bee2925SMatthew Knepley       fid  = EG_indexBodyTopo(body, fobjs[0]);CHKERRQ(ierr);
557*7bee2925SMatthew Knepley       EG_free(fobjs);
558*7bee2925SMatthew Knepley       ierr = EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses);CHKERRQ(ierr);
559*7bee2925SMatthew Knepley       for (e = 0; e < Ne; ++e) {
560*7bee2925SMatthew Knepley         ego             edge = objs[e];
561*7bee2925SMatthew Knepley         int             eid, Nv, v;
562*7bee2925SMatthew Knepley         PetscInt        points[3], support[2], numEdges, edgeNum;
563*7bee2925SMatthew Knepley         const PetscInt *edges;
564*7bee2925SMatthew Knepley 
565*7bee2925SMatthew Knepley         eid  = EG_indexBodyTopo(body, edge);
566*7bee2925SMatthew Knepley         ierr = EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses);
567*7bee2925SMatthew Knepley         if (mtype == DEGENERATE) continue;
568*7bee2925SMatthew Knepley         else                     ++Ner;
569*7bee2925SMatthew Knepley         for (v = 0; v < Nv; ++v) {
570*7bee2925SMatthew Knepley           ego vertex = nobjs[v];
571*7bee2925SMatthew Knepley 
572*7bee2925SMatthew Knepley           id   = EG_indexBodyTopo(body, vertex);
573*7bee2925SMatthew Knepley           ierr = DMLabelSetValue(edgeLabel, numCells + id-1, eid);CHKERRQ(ierr);
574*7bee2925SMatthew Knepley           points[v*2] = numCells + id-1;
575*7bee2925SMatthew Knepley         }
576*7bee2925SMatthew Knepley         ierr = PetscHMapIGet(edgeMap, eid-1, &edgeNum);CHKERRQ(ierr);
577*7bee2925SMatthew Knepley         points[1] = numCells + numVertices - newVertices + edgeNum;
578*7bee2925SMatthew Knepley 
579*7bee2925SMatthew Knepley         ierr = DMLabelSetValue(edgeLabel, points[1], eid);CHKERRQ(ierr);
580*7bee2925SMatthew Knepley         support[0] = points[0];
581*7bee2925SMatthew Knepley         support[1] = points[1];
582*7bee2925SMatthew Knepley         ierr = DMPlexGetJoin(dm, 2, support, &numEdges, &edges);CHKERRQ(ierr);
583*7bee2925SMatthew 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);
584*7bee2925SMatthew Knepley         ierr = DMLabelSetValue(edgeLabel, edges[0], eid);CHKERRQ(ierr);
585*7bee2925SMatthew Knepley         ierr = DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges);CHKERRQ(ierr);
586*7bee2925SMatthew Knepley         support[0] = points[1];
587*7bee2925SMatthew Knepley         support[1] = points[2];
588*7bee2925SMatthew Knepley         ierr = DMPlexGetJoin(dm, 2, support, &numEdges, &edges);CHKERRQ(ierr);
589*7bee2925SMatthew 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);
590*7bee2925SMatthew Knepley         ierr = DMLabelSetValue(edgeLabel, edges[0], eid);CHKERRQ(ierr);
591*7bee2925SMatthew Knepley         ierr = DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges);CHKERRQ(ierr);
592*7bee2925SMatthew Knepley       }
593*7bee2925SMatthew Knepley       switch (Ner) {
594*7bee2925SMatthew Knepley         case 2: Nt = 2;break;
595*7bee2925SMatthew Knepley         case 3: Nt = 4;break;
596*7bee2925SMatthew Knepley         case 4: Nt = 8;break;
597*7bee2925SMatthew Knepley         default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Loop with %d edges is unsupported", Ner);
598*7bee2925SMatthew Knepley       }
599*7bee2925SMatthew Knepley       for (t = 0; t < Nt; ++t) {
600*7bee2925SMatthew Knepley         ierr = DMLabelSetValue(bodyLabel, cOff+t, b);CHKERRQ(ierr);
601*7bee2925SMatthew Knepley         ierr = DMLabelSetValue(faceLabel, cOff+t, fid);CHKERRQ(ierr);
602*7bee2925SMatthew Knepley       }
603*7bee2925SMatthew Knepley       cOff += Nt;
604*7bee2925SMatthew Knepley     }
605*7bee2925SMatthew Knepley     EG_free(lobjs);
606*7bee2925SMatthew Knepley   }
607*7bee2925SMatthew Knepley   ierr = PetscHMapIDestroy(&edgeMap);CHKERRQ(ierr);
608*7bee2925SMatthew Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
609*7bee2925SMatthew Knepley   for (c = cStart; c < cEnd; ++c) {
610*7bee2925SMatthew Knepley     PetscInt *closure = NULL;
611*7bee2925SMatthew Knepley     PetscInt  clSize, cl, bval, fval;
612*7bee2925SMatthew Knepley 
613*7bee2925SMatthew Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
614*7bee2925SMatthew Knepley     ierr = DMLabelGetValue(bodyLabel, c, &bval);CHKERRQ(ierr);
615*7bee2925SMatthew Knepley     ierr = DMLabelGetValue(faceLabel, c, &fval);CHKERRQ(ierr);
616*7bee2925SMatthew Knepley     for (cl = 0; cl < clSize*2; cl += 2) {
617*7bee2925SMatthew Knepley       ierr = DMLabelSetValue(bodyLabel, closure[cl], bval);CHKERRQ(ierr);
618*7bee2925SMatthew Knepley       ierr = DMLabelSetValue(faceLabel, closure[cl], fval);CHKERRQ(ierr);
619*7bee2925SMatthew Knepley     }
620*7bee2925SMatthew Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
621*7bee2925SMatthew Knepley   }
622*7bee2925SMatthew Knepley   *newdm = dm;
623*7bee2925SMatthew Knepley   PetscFunctionReturn(0);
624*7bee2925SMatthew Knepley }
625*7bee2925SMatthew Knepley #endif
626*7bee2925SMatthew Knepley 
627*7bee2925SMatthew Knepley /*@C
628*7bee2925SMatthew Knepley   DMPlexCreateEGADSFromFile - Create a DMPlex mesh from an EGADSLite file.
629*7bee2925SMatthew Knepley 
630*7bee2925SMatthew Knepley   Collective
631*7bee2925SMatthew Knepley 
632*7bee2925SMatthew Knepley   Input Parameters:
633*7bee2925SMatthew Knepley + comm     - The MPI communicator
634*7bee2925SMatthew Knepley - filename - The name of the ExodusII file
635*7bee2925SMatthew Knepley 
636*7bee2925SMatthew Knepley   Output Parameter:
637*7bee2925SMatthew Knepley . dm       - The DM object representing the mesh
638*7bee2925SMatthew Knepley 
639*7bee2925SMatthew Knepley   Level: beginner
640*7bee2925SMatthew Knepley 
641*7bee2925SMatthew Knepley .seealso: DMPLEX, DMCreate(), DMPlexCreateEGADS()
642*7bee2925SMatthew Knepley @*/
643*7bee2925SMatthew Knepley PetscErrorCode DMPlexCreateEGADSFromFile(MPI_Comm comm, const char filename[], DM *dm)
644*7bee2925SMatthew Knepley {
645*7bee2925SMatthew Knepley   PetscMPIInt    rank;
646*7bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
647*7bee2925SMatthew Knepley   ego            context= NULL, model = NULL;
648*7bee2925SMatthew Knepley #endif
649*7bee2925SMatthew Knepley   PetscBool      printModel;
650*7bee2925SMatthew Knepley   PetscErrorCode ierr;
651*7bee2925SMatthew Knepley 
652*7bee2925SMatthew Knepley   PetscFunctionBegin;
653*7bee2925SMatthew Knepley   PetscValidCharPointer(filename, 2);
654*7bee2925SMatthew Knepley   ierr = PetscOptionsGetBool(NULL, NULL, "-dm_plex_egads_print_model", &printModel, NULL);CHKERRQ(ierr);
655*7bee2925SMatthew Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
656*7bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS)
657*7bee2925SMatthew Knepley   if (!rank) {
658*7bee2925SMatthew Knepley 
659*7bee2925SMatthew Knepley     ierr = EG_open(&context);CHKERRQ(ierr);
660*7bee2925SMatthew Knepley     ierr = EG_loadModel(context, 0, filename, &model);CHKERRQ(ierr);
661*7bee2925SMatthew Knepley     if (printModel) {ierr = DMPlexEGADSPrintModel(model);CHKERRQ(ierr);}
662*7bee2925SMatthew Knepley 
663*7bee2925SMatthew Knepley   }
664*7bee2925SMatthew Knepley   ierr = DMPlexCreateEGADS(comm, context, model, dm);CHKERRQ(ierr);
665*7bee2925SMatthew Knepley #else
666*7bee2925SMatthew Knepley   SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADSLite support. Reconfigure using --download-egads");
667*7bee2925SMatthew Knepley #endif
668*7bee2925SMatthew Knepley   PetscFunctionReturn(0);
669*7bee2925SMatthew Knepley }
670