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 21c1cad2e7SMatthew G. Knepley #ifdef PETSC_HAVE_EGADS 22c1cad2e7SMatthew G. Knepley PETSC_INTERN PetscErrorCode DMPlexSnapToGeomModel_EGADS_Internal(DM, PetscInt, ego, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscScalar[]); 23c1cad2e7SMatthew G. Knepley PETSC_INTERN PetscErrorCode DMPlexSnapToGeomModel_EGADSLite_Internal(DM, PetscInt, ego, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscScalar[]); 24c1cad2e7SMatthew G. Knepley 25d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSnapToGeomModel_EGADS_Internal(DM dm, PetscInt p, ego model, PetscInt bodyID, PetscInt faceID, PetscInt edgeID, const PetscScalar mcoords[], PetscScalar gcoords[]) 26d71ae5a4SJacob Faibussowitsch { 27c1cad2e7SMatthew G. Knepley DM cdm; 28c1cad2e7SMatthew G. Knepley ego *bodies; 29c1cad2e7SMatthew G. Knepley ego geom, body, obj; 30a5b23f4aSJose E. Roman /* result has to hold derivatives, along with the value */ 31c1cad2e7SMatthew G. Knepley double params[3], result[18], paramsV[16 * 3], resultV[16 * 3], range[4]; 32c1cad2e7SMatthew G. Knepley int Nb, oclass, mtype, *senses, peri; 33c1cad2e7SMatthew G. Knepley Vec coordinatesLocal; 34c1cad2e7SMatthew G. Knepley PetscScalar *coords = NULL; 35c1cad2e7SMatthew G. Knepley PetscInt Nv, v, Np = 0, pm; 36c1cad2e7SMatthew G. Knepley PetscInt dE, d; 37c1cad2e7SMatthew G. Knepley 38c1cad2e7SMatthew G. Knepley PetscFunctionBeginHot; 399566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 409566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 419566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 429566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4363a3b9bcSJacob Faibussowitsch PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %d)", bodyID, Nb); 44c1cad2e7SMatthew G. Knepley body = bodies[bodyID]; 45c1cad2e7SMatthew G. Knepley 469371c9d4SSatish Balay if (edgeID >= 0) { 479371c9d4SSatish Balay PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &obj)); 489371c9d4SSatish Balay Np = 1; 499371c9d4SSatish Balay } else if (faceID >= 0) { 509371c9d4SSatish Balay PetscCall(EG_objectBodyTopo(body, FACE, faceID, &obj)); 519371c9d4SSatish Balay Np = 2; 529371c9d4SSatish Balay } else { 53c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55c1cad2e7SMatthew G. Knepley } 56c1cad2e7SMatthew G. Knepley 57c1cad2e7SMatthew G. Knepley /* Calculate parameters (t or u,v) for vertices */ 589566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 59c1cad2e7SMatthew G. Knepley Nv /= dE; 60c1cad2e7SMatthew G. Knepley if (Nv == 1) { 619566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 62c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64c1cad2e7SMatthew G. Knepley } 6563a3b9bcSJacob Faibussowitsch PetscCheck(Nv <= 16, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " coordinates associated to point %" PetscInt_FMT, Nv, p); 66c1cad2e7SMatthew G. Knepley 67c1cad2e7SMatthew G. Knepley /* Correct EGADSlite 2pi bug when calculating nearest point on Periodic Surfaces */ 689566063dSJacob Faibussowitsch PetscCall(EG_getRange(obj, range, &peri)); 69c1cad2e7SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 709566063dSJacob Faibussowitsch PetscCall(EG_invEvaluate(obj, &coords[v * dE], ¶msV[v * 3], &resultV[v * 3])); 71c1cad2e7SMatthew G. Knepley #if 1 72c1cad2e7SMatthew G. Knepley if (peri > 0) { 739371c9d4SSatish Balay if (paramsV[v * 3 + 0] + 1.e-4 < range[0]) { 749371c9d4SSatish Balay paramsV[v * 3 + 0] += 2. * PETSC_PI; 759371c9d4SSatish Balay } else if (paramsV[v * 3 + 0] - 1.e-4 > range[1]) { 769371c9d4SSatish Balay paramsV[v * 3 + 0] -= 2. * PETSC_PI; 779371c9d4SSatish Balay } 78c1cad2e7SMatthew G. Knepley } 79c1cad2e7SMatthew G. Knepley if (peri > 1) { 809371c9d4SSatish Balay if (paramsV[v * 3 + 1] + 1.e-4 < range[2]) { 819371c9d4SSatish Balay paramsV[v * 3 + 1] += 2. * PETSC_PI; 829371c9d4SSatish Balay } else if (paramsV[v * 3 + 1] - 1.e-4 > range[3]) { 839371c9d4SSatish Balay paramsV[v * 3 + 1] -= 2. * PETSC_PI; 849371c9d4SSatish Balay } 85c1cad2e7SMatthew G. Knepley } 86c1cad2e7SMatthew G. Knepley #endif 87c1cad2e7SMatthew G. Knepley } 889566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 89c1cad2e7SMatthew G. Knepley /* Calculate parameters (t or u,v) for new vertex at edge midpoint */ 90c1cad2e7SMatthew G. Knepley for (pm = 0; pm < Np; ++pm) { 91c1cad2e7SMatthew G. Knepley params[pm] = 0.; 92c1cad2e7SMatthew G. Knepley for (v = 0; v < Nv; ++v) params[pm] += paramsV[v * 3 + pm]; 93c1cad2e7SMatthew G. Knepley params[pm] /= Nv; 94c1cad2e7SMatthew G. Knepley } 9563a3b9bcSJacob Faibussowitsch PetscCheck(!(params[0] < range[0]) && !(params[0] > range[1]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " had bad interpolation", p); 961dca8a05SBarry Smith PetscCheck(Np <= 1 || (params[1] >= range[2] && params[1] <= range[3]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " had bad interpolation", p); 97c1cad2e7SMatthew G. Knepley /* Put coordinates for new vertex in result[] */ 989566063dSJacob Faibussowitsch PetscCall(EG_evaluate(obj, params, result)); 99c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = result[d]; 1003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101c1cad2e7SMatthew G. Knepley } 102c1cad2e7SMatthew G. Knepley #endif 103c1cad2e7SMatthew G. Knepley 104a8ededdfSMatthew G. Knepley /*@ 105a8ededdfSMatthew 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. 106a8ededdfSMatthew G. Knepley 10720f4b53cSBarry Smith Not Collective 108a8ededdfSMatthew G. Knepley 109a8ededdfSMatthew G. Knepley Input Parameters: 110a1cb98faSBarry Smith + dm - The `DMPLEX` object 111a8ededdfSMatthew G. Knepley . p - The mesh point 112d410b0cfSMatthew G. Knepley . dE - The coordinate dimension 113a8ededdfSMatthew G. Knepley - mcoords - A coordinate point lying on the mesh point 114a8ededdfSMatthew G. Knepley 115a8ededdfSMatthew G. Knepley Output Parameter: 116a8ededdfSMatthew G. Knepley . gcoords - The closest coordinate point on the geometry model associated with 'p' to the given point 117a8ededdfSMatthew G. Knepley 118a8ededdfSMatthew G. Knepley Level: intermediate 119a8ededdfSMatthew G. Knepley 120a1cb98faSBarry Smith Note: 12120f4b53cSBarry Smith Returns the original coordinates if no geometry model is found. Right now the only supported geometry model is EGADS. 12220f4b53cSBarry Smith 12320f4b53cSBarry Smith The coordinate dimension may be different from the coordinate dimension of the `dm`, for example if the transformation is extrusion. 124a1cb98faSBarry Smith 125*1cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexCreate()`, `DMPlexSetRefinementUniform()` 126a8ededdfSMatthew G. Knepley @*/ 127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSnapToGeomModel(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[]) 128d71ae5a4SJacob Faibussowitsch { 129d410b0cfSMatthew G. Knepley PetscInt d; 130a8ededdfSMatthew G. Knepley 131c1cad2e7SMatthew G. Knepley PetscFunctionBeginHot; 132a8ededdfSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS 133c1cad2e7SMatthew G. Knepley { 134c1cad2e7SMatthew G. Knepley DM_Plex *plex = (DM_Plex *)dm->data; 135c1cad2e7SMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel; 136c1cad2e7SMatthew G. Knepley PetscInt bodyID, faceID, edgeID; 137c1cad2e7SMatthew G. Knepley PetscContainer modelObj; 138c1cad2e7SMatthew G. Knepley ego model; 139c1cad2e7SMatthew G. Knepley PetscBool islite = PETSC_FALSE; 140c1cad2e7SMatthew G. Knepley 1419566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 1429566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 1439566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 144c1cad2e7SMatthew G. Knepley if (!bodyLabel || !faceLabel || !edgeLabel || plex->ignoreModel) { 145f0fcf0adSMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 1463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 147a8ededdfSMatthew G. Knepley } 1489566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 149c1cad2e7SMatthew G. Knepley if (!modelObj) { 1509566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSLite Model", (PetscObject *)&modelObj)); 151c1cad2e7SMatthew G. Knepley islite = PETSC_TRUE; 152c1cad2e7SMatthew G. Knepley } 153c1cad2e7SMatthew G. Knepley if (!modelObj) { 154c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 1553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 156c1cad2e7SMatthew G. Knepley } 1579566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 1589566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, p, &bodyID)); 1599566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, p, &faceID)); 1609566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, p, &edgeID)); 161c1cad2e7SMatthew G. Knepley /* Allows for "Connective" Plex Edges present in models with multiple non-touching Entities */ 162c1cad2e7SMatthew G. Knepley if (bodyID < 0) { 163f0fcf0adSMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 1643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 165a8ededdfSMatthew G. Knepley } 1669566063dSJacob Faibussowitsch if (islite) PetscCall(DMPlexSnapToGeomModel_EGADSLite_Internal(dm, p, model, bodyID, faceID, edgeID, mcoords, gcoords)); 1679566063dSJacob Faibussowitsch else PetscCall(DMPlexSnapToGeomModel_EGADS_Internal(dm, p, model, bodyID, faceID, edgeID, mcoords, gcoords)); 168f0fcf0adSMatthew G. Knepley } 169a8ededdfSMatthew G. Knepley #else 170f0fcf0adSMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 171a8ededdfSMatthew G. Knepley #endif 1723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 173a8ededdfSMatthew G. Knepley } 1747bee2925SMatthew Knepley 1757bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS) 176d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexEGADSPrintModel_Internal(ego model) 177d71ae5a4SJacob Faibussowitsch { 1787bee2925SMatthew Knepley ego geom, *bodies, *objs, *nobjs, *mobjs, *lobjs; 1797bee2925SMatthew Knepley int oclass, mtype, *senses; 1807bee2925SMatthew Knepley int Nb, b; 1817bee2925SMatthew Knepley 1827bee2925SMatthew Knepley PetscFunctionBeginUser; 1837bee2925SMatthew Knepley /* test bodyTopo functions */ 1849566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 1859566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of BODIES (nbodies): %d \n", Nb)); 1867bee2925SMatthew Knepley 1877bee2925SMatthew Knepley for (b = 0; b < Nb; ++b) { 1887bee2925SMatthew Knepley ego body = bodies[b]; 1897bee2925SMatthew Knepley int id, Nsh, Nf, Nl, l, Ne, e, Nv, v; 1907bee2925SMatthew Knepley 1917bee2925SMatthew Knepley /* Output Basic Model Topology */ 1929566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, SHELL, &Nsh, &objs)); 1939566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of SHELLS: %d \n", Nsh)); 1947bee2925SMatthew Knepley EG_free(objs); 1957bee2925SMatthew Knepley 1969566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &objs)); 1979566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of FACES: %d \n", Nf)); 1987bee2925SMatthew Knepley EG_free(objs); 1997bee2925SMatthew Knepley 2009566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 2019566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of LOOPS: %d \n", Nl)); 2027bee2925SMatthew Knepley 2039566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &objs)); 2049566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of EDGES: %d \n", Ne)); 2057bee2925SMatthew Knepley EG_free(objs); 2067bee2925SMatthew Knepley 2079566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &objs)); 2089566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of NODES: %d \n", Nv)); 2097bee2925SMatthew Knepley EG_free(objs); 2107bee2925SMatthew Knepley 2117bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 2127bee2925SMatthew Knepley ego loop = lobjs[l]; 2137bee2925SMatthew Knepley 2147bee2925SMatthew Knepley id = EG_indexBodyTopo(body, loop); 2159566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP ID: %d\n", id)); 2167bee2925SMatthew Knepley 2177bee2925SMatthew Knepley /* Get EDGE info which associated with the current LOOP */ 2189566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 2197bee2925SMatthew Knepley 2207bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 2217bee2925SMatthew Knepley ego edge = objs[e]; 2227bee2925SMatthew Knepley double range[4] = {0., 0., 0., 0.}; 2237bee2925SMatthew Knepley double point[3] = {0., 0., 0.}; 224266cfabeSMatthew G. Knepley double params[3] = {0., 0., 0.}; 225266cfabeSMatthew G. Knepley double result[18]; 2267bee2925SMatthew Knepley int peri; 2277bee2925SMatthew Knepley 2285f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, edge); 2299566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE ID: %d (%d)\n", id, e)); 2307bee2925SMatthew Knepley 2319566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, &peri)); 2329566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Range = %lf, %lf, %lf, %lf \n", range[0], range[1], range[2], range[3])); 2337bee2925SMatthew Knepley 2347bee2925SMatthew Knepley /* Get NODE info which associated with the current EDGE */ 2359566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 236266cfabeSMatthew G. Knepley if (mtype == DEGENERATE) { 2379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE %d is DEGENERATE \n", id)); 238266cfabeSMatthew G. Knepley } else { 239266cfabeSMatthew G. Knepley params[0] = range[0]; 2409566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, params, result)); 2419566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " between (%lf, %lf, %lf)", result[0], result[1], result[2])); 242266cfabeSMatthew G. Knepley params[0] = range[1]; 2439566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, params, result)); 2449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " and (%lf, %lf, %lf)\n", result[0], result[1], result[2])); 245266cfabeSMatthew G. Knepley } 2467bee2925SMatthew Knepley 2477bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 2487bee2925SMatthew Knepley ego vertex = nobjs[v]; 2497bee2925SMatthew Knepley double limits[4]; 2507bee2925SMatthew Knepley int dummy; 2517bee2925SMatthew Knepley 2529566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 2537bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 2549566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " NODE ID: %d \n", id)); 2559566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " (x, y, z) = (%lf, %lf, %lf) \n", limits[0], limits[1], limits[2])); 2567bee2925SMatthew Knepley 2577bee2925SMatthew Knepley point[0] = point[0] + limits[0]; 2587bee2925SMatthew Knepley point[1] = point[1] + limits[1]; 2597bee2925SMatthew Knepley point[2] = point[2] + limits[2]; 2607bee2925SMatthew Knepley } 2617bee2925SMatthew Knepley } 2627bee2925SMatthew Knepley } 2637bee2925SMatthew Knepley EG_free(lobjs); 2647bee2925SMatthew Knepley } 2653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2667bee2925SMatthew Knepley } 2677bee2925SMatthew Knepley 268d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexEGADSDestroy_Private(void *context) 269d71ae5a4SJacob Faibussowitsch { 2707bee2925SMatthew Knepley if (context) EG_close((ego)context); 2717bee2925SMatthew Knepley return 0; 2727bee2925SMatthew Knepley } 2737bee2925SMatthew Knepley 274d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateEGADS_Internal(MPI_Comm comm, ego context, ego model, DM *newdm) 275d71ae5a4SJacob Faibussowitsch { 276c1cad2e7SMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 2777bee2925SMatthew Knepley PetscInt cStart, cEnd, c; 2787bee2925SMatthew Knepley /* EGADSLite variables */ 2797bee2925SMatthew Knepley ego geom, *bodies, *objs, *nobjs, *mobjs, *lobjs; 2807bee2925SMatthew Knepley int oclass, mtype, nbodies, *senses; 2817bee2925SMatthew Knepley int b; 2827bee2925SMatthew Knepley /* PETSc variables */ 2837bee2925SMatthew Knepley DM dm; 2847bee2925SMatthew Knepley PetscHMapI edgeMap = NULL; 2857bee2925SMatthew 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; 2867bee2925SMatthew Knepley PetscInt *cells = NULL, *cone = NULL; 2877bee2925SMatthew Knepley PetscReal *coords = NULL; 2887bee2925SMatthew Knepley PetscMPIInt rank; 2897bee2925SMatthew Knepley 2907bee2925SMatthew Knepley PetscFunctionBegin; 2919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 292dd400576SPatrick Sanan if (rank == 0) { 293266cfabeSMatthew G. Knepley const PetscInt debug = 0; 294266cfabeSMatthew G. Knepley 2957bee2925SMatthew Knepley /* --------------------------------------------------------------------------------------------------- 2967bee2925SMatthew Knepley Generate Petsc Plex 2977bee2925SMatthew Knepley Get all Nodes in model, record coordinates in a correctly formatted array 2987bee2925SMatthew Knepley Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array 2997bee2925SMatthew Knepley We need to uniformly refine the initial geometry to guarantee a valid mesh 3007bee2925SMatthew Knepley */ 3017bee2925SMatthew Knepley 3027bee2925SMatthew Knepley /* Calculate cell and vertex sizes */ 3039566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 3049566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&edgeMap)); 3057bee2925SMatthew Knepley numEdges = 0; 3067bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 3077bee2925SMatthew Knepley ego body = bodies[b]; 3087bee2925SMatthew Knepley int id, Nl, l, Nv, v; 3097bee2925SMatthew Knepley 3109566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 3117bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 3127bee2925SMatthew Knepley ego loop = lobjs[l]; 3137bee2925SMatthew Knepley int Ner = 0, Ne, e, Nc; 3147bee2925SMatthew Knepley 3159566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 3167bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 3177bee2925SMatthew Knepley ego edge = objs[e]; 3187bee2925SMatthew Knepley int Nv, id; 3197bee2925SMatthew Knepley PetscHashIter iter; 3207bee2925SMatthew Knepley PetscBool found; 3217bee2925SMatthew Knepley 3229566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 3237bee2925SMatthew Knepley if (mtype == DEGENERATE) continue; 3245f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, edge); 3259566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, id - 1, &iter, &found)); 3269566063dSJacob Faibussowitsch if (!found) PetscCall(PetscHMapISet(edgeMap, id - 1, numEdges++)); 3277bee2925SMatthew Knepley ++Ner; 3287bee2925SMatthew Knepley } 3299371c9d4SSatish Balay if (Ner == 2) { 3309371c9d4SSatish Balay Nc = 2; 3319371c9d4SSatish Balay } else if (Ner == 3) { 3329371c9d4SSatish Balay Nc = 4; 3339371c9d4SSatish Balay } else if (Ner == 4) { 3349371c9d4SSatish Balay Nc = 8; 3359371c9d4SSatish Balay ++numQuads; 3369371c9d4SSatish Balay } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot support loop with %d edges", Ner); 3377bee2925SMatthew Knepley numCells += Nc; 3387bee2925SMatthew Knepley newCells += Nc - 1; 3397bee2925SMatthew Knepley maxCorners = PetscMax(Ner * 2 + 1, maxCorners); 3407bee2925SMatthew Knepley } 3419566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 3427bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 3437bee2925SMatthew Knepley ego vertex = nobjs[v]; 3447bee2925SMatthew Knepley 3457bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 3467bee2925SMatthew Knepley /* TODO: Instead of assuming contiguous ids, we could use a hash table */ 3477bee2925SMatthew Knepley numVertices = PetscMax(id, numVertices); 3487bee2925SMatthew Knepley } 3497bee2925SMatthew Knepley EG_free(lobjs); 3507bee2925SMatthew Knepley EG_free(nobjs); 3517bee2925SMatthew Knepley } 3529566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(edgeMap, &numEdges)); 3537bee2925SMatthew Knepley newVertices = numEdges + numQuads; 3547bee2925SMatthew Knepley numVertices += newVertices; 3557bee2925SMatthew Knepley 3567bee2925SMatthew Knepley dim = 2; /* Assume 3D Models :: Need to update to handle 2D Models in the future */ 3577bee2925SMatthew Knepley cdim = 3; /* Assume 3D Models :: Need to update to handle 2D Models in the future */ 3587bee2925SMatthew Knepley numCorners = 3; /* Split cells into triangles */ 3599566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(numVertices * cdim, &coords, numCells * numCorners, &cells, maxCorners, &cone)); 3607bee2925SMatthew Knepley 3617bee2925SMatthew Knepley /* Get vertex coordinates */ 3627bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 3637bee2925SMatthew Knepley ego body = bodies[b]; 3647bee2925SMatthew Knepley int id, Nv, v; 3657bee2925SMatthew Knepley 3669566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 3677bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 3687bee2925SMatthew Knepley ego vertex = nobjs[v]; 3697bee2925SMatthew Knepley double limits[4]; 3707bee2925SMatthew Knepley int dummy; 3717bee2925SMatthew Knepley 3729566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 3735f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, vertex); 3747bee2925SMatthew Knepley coords[(id - 1) * cdim + 0] = limits[0]; 3757bee2925SMatthew Knepley coords[(id - 1) * cdim + 1] = limits[1]; 3767bee2925SMatthew Knepley coords[(id - 1) * cdim + 2] = limits[2]; 3777bee2925SMatthew Knepley } 3787bee2925SMatthew Knepley EG_free(nobjs); 3797bee2925SMatthew Knepley } 3809566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(edgeMap)); 3817bee2925SMatthew Knepley fOff = numVertices - newVertices + numEdges; 3827bee2925SMatthew Knepley numEdges = 0; 3837bee2925SMatthew Knepley numQuads = 0; 3847bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 3857bee2925SMatthew Knepley ego body = bodies[b]; 3867bee2925SMatthew Knepley int Nl, l; 3877bee2925SMatthew Knepley 3889566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 3897bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 3907bee2925SMatthew Knepley ego loop = lobjs[l]; 3917bee2925SMatthew Knepley int lid, Ner = 0, Ne, e; 3927bee2925SMatthew Knepley 3935f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 3949566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 3957bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 3967bee2925SMatthew Knepley ego edge = objs[e]; 3977bee2925SMatthew Knepley int eid, Nv; 3987bee2925SMatthew Knepley PetscHashIter iter; 3997bee2925SMatthew Knepley PetscBool found; 4007bee2925SMatthew Knepley 4019566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 4027bee2925SMatthew Knepley if (mtype == DEGENERATE) continue; 4037bee2925SMatthew Knepley ++Ner; 4045f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 4059566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, eid - 1, &iter, &found)); 4067bee2925SMatthew Knepley if (!found) { 4077bee2925SMatthew Knepley PetscInt v = numVertices - newVertices + numEdges; 4087bee2925SMatthew Knepley double range[4], params[3] = {0., 0., 0.}, result[18]; 4097bee2925SMatthew Knepley int periodic[2]; 4107bee2925SMatthew Knepley 4119566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(edgeMap, eid - 1, numEdges++)); 4129566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, periodic)); 4137bee2925SMatthew Knepley params[0] = 0.5 * (range[0] + range[1]); 4149566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, params, result)); 4157bee2925SMatthew Knepley coords[v * cdim + 0] = result[0]; 4167bee2925SMatthew Knepley coords[v * cdim + 1] = result[1]; 4177bee2925SMatthew Knepley coords[v * cdim + 2] = result[2]; 4187bee2925SMatthew Knepley } 4197bee2925SMatthew Knepley } 4207bee2925SMatthew Knepley if (Ner == 4) { 4217bee2925SMatthew Knepley PetscInt v = fOff + numQuads++; 422266cfabeSMatthew G. Knepley ego *fobjs, face; 4237bee2925SMatthew Knepley double range[4], params[3] = {0., 0., 0.}, result[18]; 424266cfabeSMatthew G. Knepley int Nf, fid, periodic[2]; 4257bee2925SMatthew Knepley 4269566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 427266cfabeSMatthew G. Knepley face = fobjs[0]; 4285f80ce2aSJacob Faibussowitsch fid = EG_indexBodyTopo(body, face); 42908401ef6SPierre Jolivet PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Loop %d has %d faces, instead of 1 (%d)", lid - 1, Nf, fid); 4309566063dSJacob Faibussowitsch PetscCall(EG_getRange(face, range, periodic)); 4317bee2925SMatthew Knepley params[0] = 0.5 * (range[0] + range[1]); 4327bee2925SMatthew Knepley params[1] = 0.5 * (range[2] + range[3]); 4339566063dSJacob Faibussowitsch PetscCall(EG_evaluate(face, params, result)); 4347bee2925SMatthew Knepley coords[v * cdim + 0] = result[0]; 4357bee2925SMatthew Knepley coords[v * cdim + 1] = result[1]; 4367bee2925SMatthew Knepley coords[v * cdim + 2] = result[2]; 4377bee2925SMatthew Knepley } 4387bee2925SMatthew Knepley } 4397bee2925SMatthew Knepley } 4401dca8a05SBarry Smith PetscCheck(numEdges + numQuads == newVertices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of new vertices %" PetscInt_FMT " != %" PetscInt_FMT " previous count", numEdges + numQuads, newVertices); 4417bee2925SMatthew Knepley 4427bee2925SMatthew Knepley /* Get cell vertices by traversing loops */ 4437bee2925SMatthew Knepley numQuads = 0; 4447bee2925SMatthew Knepley cOff = 0; 4457bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 4467bee2925SMatthew Knepley ego body = bodies[b]; 4477bee2925SMatthew Knepley int id, Nl, l; 4487bee2925SMatthew Knepley 4499566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 4507bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 4517bee2925SMatthew Knepley ego loop = lobjs[l]; 4527bee2925SMatthew Knepley int lid, Ner = 0, Ne, e, nc = 0, c, Nt, t; 4537bee2925SMatthew Knepley 4545f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 4559566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 4567bee2925SMatthew Knepley 4577bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 4587bee2925SMatthew Knepley ego edge = objs[e]; 4597bee2925SMatthew Knepley int points[3]; 4607bee2925SMatthew Knepley int eid, Nv, v, tmp; 4617bee2925SMatthew Knepley 4627bee2925SMatthew Knepley eid = EG_indexBodyTopo(body, edge); 4639566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 464266cfabeSMatthew G. Knepley if (mtype == DEGENERATE) continue; 465266cfabeSMatthew G. Knepley else ++Ner; 46608401ef6SPierre Jolivet PetscCheck(Nv == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Edge %d has %d vertices != 2", eid, Nv); 4677bee2925SMatthew Knepley 4687bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 4697bee2925SMatthew Knepley ego vertex = nobjs[v]; 4707bee2925SMatthew Knepley 4717bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 4727bee2925SMatthew Knepley points[v * 2] = id - 1; 4737bee2925SMatthew Knepley } 4747bee2925SMatthew Knepley { 4757bee2925SMatthew Knepley PetscInt edgeNum; 4767bee2925SMatthew Knepley 4779566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum)); 4787bee2925SMatthew Knepley points[1] = numVertices - newVertices + edgeNum; 4797bee2925SMatthew Knepley } 4807bee2925SMatthew Knepley /* EGADS loops are not oriented, but seem to be in order, so we must piece them together */ 4817bee2925SMatthew Knepley if (!nc) { 4827bee2925SMatthew Knepley for (v = 0; v < Nv + 1; ++v) cone[nc++] = points[v]; 4837bee2925SMatthew Knepley } else { 4849371c9d4SSatish Balay if (cone[nc - 1] == points[0]) { 4859371c9d4SSatish Balay cone[nc++] = points[1]; 4869371c9d4SSatish Balay if (cone[0] != points[2]) cone[nc++] = points[2]; 4879371c9d4SSatish Balay } else if (cone[nc - 1] == points[2]) { 4889371c9d4SSatish Balay cone[nc++] = points[1]; 4899371c9d4SSatish Balay if (cone[0] != points[0]) cone[nc++] = points[0]; 4909371c9d4SSatish Balay } else if (cone[nc - 3] == points[0]) { 4919371c9d4SSatish Balay tmp = cone[nc - 3]; 4929371c9d4SSatish Balay cone[nc - 3] = cone[nc - 1]; 4939371c9d4SSatish Balay cone[nc - 1] = tmp; 4949371c9d4SSatish Balay cone[nc++] = points[1]; 4959371c9d4SSatish Balay if (cone[0] != points[2]) cone[nc++] = points[2]; 4969371c9d4SSatish Balay } else if (cone[nc - 3] == points[2]) { 4979371c9d4SSatish Balay tmp = cone[nc - 3]; 4989371c9d4SSatish Balay cone[nc - 3] = cone[nc - 1]; 4999371c9d4SSatish Balay cone[nc - 1] = tmp; 5009371c9d4SSatish Balay cone[nc++] = points[1]; 5019371c9d4SSatish Balay if (cone[0] != points[0]) cone[nc++] = points[0]; 5029371c9d4SSatish Balay } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %d does not match its predecessor", eid); 5037bee2925SMatthew Knepley } 5047bee2925SMatthew Knepley } 50563a3b9bcSJacob Faibussowitsch PetscCheck(nc == 2 * Ner, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " != %" PetscInt_FMT, nc, 2 * Ner); 506ad540459SPierre Jolivet if (Ner == 4) cone[nc++] = numVertices - newVertices + numEdges + numQuads++; 50763a3b9bcSJacob Faibussowitsch PetscCheck(nc <= maxCorners, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " > %" PetscInt_FMT " max", nc, maxCorners); 5087bee2925SMatthew Knepley /* Triangulate the loop */ 5097bee2925SMatthew Knepley switch (Ner) { 5107bee2925SMatthew Knepley case 2: /* Bi-Segment -> 2 triangles */ 5117bee2925SMatthew Knepley Nt = 2; 5127bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0]; 5137bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1]; 5147bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[2]; 5157bee2925SMatthew Knepley ++cOff; 5167bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0]; 5177bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2]; 5187bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3]; 5197bee2925SMatthew Knepley ++cOff; 5207bee2925SMatthew Knepley break; 5217bee2925SMatthew Knepley case 3: /* Triangle -> 4 triangles */ 5227bee2925SMatthew Knepley Nt = 4; 5237bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0]; 5247bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1]; 5257bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5]; 5267bee2925SMatthew Knepley ++cOff; 5277bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1]; 5287bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2]; 5297bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3]; 5307bee2925SMatthew Knepley ++cOff; 5317bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[5]; 5327bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3]; 5337bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[4]; 5347bee2925SMatthew Knepley ++cOff; 5357bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1]; 5367bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3]; 5377bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5]; 5387bee2925SMatthew Knepley ++cOff; 5397bee2925SMatthew Knepley break; 5407bee2925SMatthew Knepley case 4: /* Quad -> 8 triangles */ 5417bee2925SMatthew Knepley Nt = 8; 5427bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0]; 5437bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1]; 5447bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7]; 5457bee2925SMatthew Knepley ++cOff; 5467bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1]; 5477bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2]; 5487bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3]; 5497bee2925SMatthew Knepley ++cOff; 5507bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[3]; 5517bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[4]; 5527bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5]; 5537bee2925SMatthew Knepley ++cOff; 5547bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[5]; 5557bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[6]; 5567bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7]; 5577bee2925SMatthew Knepley ++cOff; 5587bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8]; 5597bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1]; 5607bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3]; 5617bee2925SMatthew Knepley ++cOff; 5627bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8]; 5637bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3]; 5647bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5]; 5657bee2925SMatthew Knepley ++cOff; 5667bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8]; 5677bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[5]; 5687bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7]; 5697bee2925SMatthew Knepley ++cOff; 5707bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8]; 5717bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[7]; 5727bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[1]; 5737bee2925SMatthew Knepley ++cOff; 5747bee2925SMatthew Knepley break; 575d71ae5a4SJacob Faibussowitsch default: 576d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d edges, which we do not support", lid, Ner); 5777bee2925SMatthew Knepley } 578266cfabeSMatthew G. Knepley if (debug) { 5797bee2925SMatthew Knepley for (t = 0; t < Nt; ++t) { 58063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP Corner NODEs Triangle %" PetscInt_FMT " (", t)); 5817bee2925SMatthew Knepley for (c = 0; c < numCorners; ++c) { 5829566063dSJacob Faibussowitsch if (c > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); 58363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT, cells[(cOff - Nt + t) * numCorners + c])); 5847bee2925SMatthew Knepley } 5859566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n")); 5867bee2925SMatthew Knepley } 5877bee2925SMatthew Knepley } 588266cfabeSMatthew G. Knepley } 5897bee2925SMatthew Knepley EG_free(lobjs); 5907bee2925SMatthew Knepley } 5917bee2925SMatthew Knepley } 59263a3b9bcSJacob Faibussowitsch PetscCheck(cOff == numCells, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count of total cells %" PetscInt_FMT " != %" PetscInt_FMT " previous count", cOff, numCells); 5939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numVertices, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 5949566063dSJacob Faibussowitsch PetscCall(PetscFree3(coords, cells, cone)); 59563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %" PetscInt_FMT " (%" PetscInt_FMT ")\n", numCells, newCells)); 59663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %" PetscInt_FMT " (%" PetscInt_FMT ")\n", numVertices, newVertices)); 5977bee2925SMatthew Knepley /* Embed EGADS model in DM */ 5987bee2925SMatthew Knepley { 5997bee2925SMatthew Knepley PetscContainer modelObj, contextObj; 6007bee2925SMatthew Knepley 6019566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 6029566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model)); 6039566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 6049566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj)); 6057bee2925SMatthew Knepley 6069566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 6079566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context)); 6089566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(contextObj, DMPlexEGADSDestroy_Private)); 6099566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 6109566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj)); 6117bee2925SMatthew Knepley } 6127bee2925SMatthew Knepley /* Label points */ 6139566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 6149566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 6159566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 6169566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 6179566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 6189566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 6199566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 6209566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 6217bee2925SMatthew Knepley cOff = 0; 6227bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 6237bee2925SMatthew Knepley ego body = bodies[b]; 6247bee2925SMatthew Knepley int id, Nl, l; 6257bee2925SMatthew Knepley 6269566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 6277bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 6287bee2925SMatthew Knepley ego loop = lobjs[l]; 6297bee2925SMatthew Knepley ego *fobjs; 6307bee2925SMatthew Knepley int lid, Nf, fid, Ner = 0, Ne, e, Nt = 0, t; 6317bee2925SMatthew Knepley 6325f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 6339566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 63408401ef6SPierre Jolivet PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf); 6355f80ce2aSJacob Faibussowitsch fid = EG_indexBodyTopo(body, fobjs[0]); 6367bee2925SMatthew Knepley EG_free(fobjs); 6379566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 6387bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 6397bee2925SMatthew Knepley ego edge = objs[e]; 6407bee2925SMatthew Knepley int eid, Nv, v; 6417bee2925SMatthew Knepley PetscInt points[3], support[2], numEdges, edgeNum; 6427bee2925SMatthew Knepley const PetscInt *edges; 6437bee2925SMatthew Knepley 6447bee2925SMatthew Knepley eid = EG_indexBodyTopo(body, edge); 6459566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 6467bee2925SMatthew Knepley if (mtype == DEGENERATE) continue; 6477bee2925SMatthew Knepley else ++Ner; 6487bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 6497bee2925SMatthew Knepley ego vertex = nobjs[v]; 6507bee2925SMatthew Knepley 6517bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 6529566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, numCells + id - 1, eid)); 6537bee2925SMatthew Knepley points[v * 2] = numCells + id - 1; 6547bee2925SMatthew Knepley } 6559566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum)); 6567bee2925SMatthew Knepley points[1] = numCells + numVertices - newVertices + edgeNum; 6577bee2925SMatthew Knepley 6589566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, points[1], eid)); 6597bee2925SMatthew Knepley support[0] = points[0]; 6607bee2925SMatthew Knepley support[1] = points[1]; 6619566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges)); 66263a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%" PetscInt_FMT ", %" PetscInt_FMT ") should only bound 1 edge, not %" PetscInt_FMT, support[0], support[1], numEdges); 6639566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid)); 6649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges)); 6657bee2925SMatthew Knepley support[0] = points[1]; 6667bee2925SMatthew Knepley support[1] = points[2]; 6679566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges)); 66863a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%" PetscInt_FMT ", %" PetscInt_FMT ") should only bound 1 edge, not %" PetscInt_FMT, support[0], support[1], numEdges); 6699566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid)); 6709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges)); 6717bee2925SMatthew Knepley } 6727bee2925SMatthew Knepley switch (Ner) { 673d71ae5a4SJacob Faibussowitsch case 2: 674d71ae5a4SJacob Faibussowitsch Nt = 2; 675d71ae5a4SJacob Faibussowitsch break; 676d71ae5a4SJacob Faibussowitsch case 3: 677d71ae5a4SJacob Faibussowitsch Nt = 4; 678d71ae5a4SJacob Faibussowitsch break; 679d71ae5a4SJacob Faibussowitsch case 4: 680d71ae5a4SJacob Faibussowitsch Nt = 8; 681d71ae5a4SJacob Faibussowitsch break; 682d71ae5a4SJacob Faibussowitsch default: 683d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Loop with %d edges is unsupported", Ner); 6847bee2925SMatthew Knepley } 6857bee2925SMatthew Knepley for (t = 0; t < Nt; ++t) { 6869566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cOff + t, b)); 6879566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cOff + t, fid)); 6887bee2925SMatthew Knepley } 6897bee2925SMatthew Knepley cOff += Nt; 6907bee2925SMatthew Knepley } 6917bee2925SMatthew Knepley EG_free(lobjs); 6927bee2925SMatthew Knepley } 6939566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&edgeMap)); 6949566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 6957bee2925SMatthew Knepley for (c = cStart; c < cEnd; ++c) { 6967bee2925SMatthew Knepley PetscInt *closure = NULL; 6977bee2925SMatthew Knepley PetscInt clSize, cl, bval, fval; 6987bee2925SMatthew Knepley 6999566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 7009566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, c, &bval)); 7019566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, c, &fval)); 7027bee2925SMatthew Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 7039566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, closure[cl], bval)); 7049566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, closure[cl], fval)); 7057bee2925SMatthew Knepley } 7069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 7077bee2925SMatthew Knepley } 7087bee2925SMatthew Knepley *newdm = dm; 7093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7107bee2925SMatthew Knepley } 711c1cad2e7SMatthew G. Knepley 712d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateEGADS(MPI_Comm comm, ego context, ego model, DM *newdm) 713d71ae5a4SJacob Faibussowitsch { 714c1cad2e7SMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 715c1cad2e7SMatthew G. Knepley // EGADS/EGADSLite variables 716c1cad2e7SMatthew G. Knepley ego geom, *bodies, *mobjs, *fobjs, *lobjs, *eobjs, *nobjs; 717c1cad2e7SMatthew G. Knepley ego topRef, prev, next; 718c1cad2e7SMatthew G. Knepley int oclass, mtype, nbodies, *senses, *lSenses, *eSenses; 719c1cad2e7SMatthew G. Knepley int b; 720c1cad2e7SMatthew G. Knepley // PETSc variables 721c1cad2e7SMatthew G. Knepley DM dm; 722c1cad2e7SMatthew G. Knepley PetscHMapI edgeMap = NULL, bodyIndexMap = NULL, bodyVertexMap = NULL, bodyEdgeMap = NULL, bodyFaceMap = NULL, bodyEdgeGlobalMap = NULL; 723c1cad2e7SMatthew G. Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, numVertices = 0, numEdges = 0, numFaces = 0, numCells = 0, edgeCntr = 0; 724c1cad2e7SMatthew G. Knepley PetscInt cellCntr = 0, numPoints = 0; 725c1cad2e7SMatthew G. Knepley PetscInt *cells = NULL; 726c1cad2e7SMatthew G. Knepley const PetscInt *cone = NULL; 727c1cad2e7SMatthew G. Knepley PetscReal *coords = NULL; 728c1cad2e7SMatthew G. Knepley PetscMPIInt rank; 729c1cad2e7SMatthew G. Knepley 730c1cad2e7SMatthew G. Knepley PetscFunctionBeginUser; 7319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 732c5853193SPierre Jolivet if (rank == 0) { 733c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 734c1cad2e7SMatthew G. Knepley // Generate Petsc Plex 735c1cad2e7SMatthew G. Knepley // Get all Nodes in model, record coordinates in a correctly formatted array 736c1cad2e7SMatthew G. Knepley // Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array 737c1cad2e7SMatthew G. Knepley // We need to uniformly refine the initial geometry to guarantee a valid mesh 738c1cad2e7SMatthew G. Knepley 739d5b43468SJose E. Roman // Calculate cell and vertex sizes 7409566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 741c1cad2e7SMatthew G. Knepley 7429566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&edgeMap)); 7439566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyIndexMap)); 7449566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyVertexMap)); 7459566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyEdgeMap)); 7469566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyEdgeGlobalMap)); 7479566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyFaceMap)); 748c1cad2e7SMatthew G. Knepley 749c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 750c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 751c1cad2e7SMatthew G. Knepley int Nf, Ne, Nv; 752c1cad2e7SMatthew G. Knepley PetscHashIter BIiter, BViter, BEiter, BEGiter, BFiter, EMiter; 753c1cad2e7SMatthew G. Knepley PetscBool BIfound, BVfound, BEfound, BEGfound, BFfound, EMfound; 754c1cad2e7SMatthew G. Knepley 7559566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyIndexMap, b, &BIiter, &BIfound)); 7569566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 7579566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 7589566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 7599566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 760c1cad2e7SMatthew G. Knepley 7619566063dSJacob Faibussowitsch if (!BIfound) PetscCall(PetscHMapISet(bodyIndexMap, b, numFaces + numEdges + numVertices)); 7629566063dSJacob Faibussowitsch if (!BVfound) PetscCall(PetscHMapISet(bodyVertexMap, b, numVertices)); 7639566063dSJacob Faibussowitsch if (!BEfound) PetscCall(PetscHMapISet(bodyEdgeMap, b, numEdges)); 7649566063dSJacob Faibussowitsch if (!BEGfound) PetscCall(PetscHMapISet(bodyEdgeGlobalMap, b, edgeCntr)); 7659566063dSJacob Faibussowitsch if (!BFfound) PetscCall(PetscHMapISet(bodyFaceMap, b, numFaces)); 766c1cad2e7SMatthew G. Knepley 7679566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 7689566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 7699566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 770c1cad2e7SMatthew G. Knepley EG_free(fobjs); 771c1cad2e7SMatthew G. Knepley EG_free(eobjs); 772c1cad2e7SMatthew G. Knepley EG_free(nobjs); 773c1cad2e7SMatthew G. Knepley 774c1cad2e7SMatthew G. Knepley // Remove DEGENERATE EDGES from Edge count 7759566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 776c1cad2e7SMatthew G. Knepley int Netemp = 0; 777c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 778c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 779c1cad2e7SMatthew G. Knepley int eid; 780c1cad2e7SMatthew G. Knepley 7819566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 7825f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 783c1cad2e7SMatthew G. Knepley 7849566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, edgeCntr + eid - 1, &EMiter, &EMfound)); 785c1cad2e7SMatthew G. Knepley if (mtype == DEGENERATE) { 7869566063dSJacob Faibussowitsch if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, -1)); 7879371c9d4SSatish Balay } else { 788c1cad2e7SMatthew G. Knepley ++Netemp; 7899566063dSJacob Faibussowitsch if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, Netemp)); 790c1cad2e7SMatthew G. Knepley } 791c1cad2e7SMatthew G. Knepley } 792c1cad2e7SMatthew G. Knepley EG_free(eobjs); 793c1cad2e7SMatthew G. Knepley 794c1cad2e7SMatthew G. Knepley // Determine Number of Cells 7959566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 796c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 797c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 798c1cad2e7SMatthew G. Knepley int edgeTemp = 0; 799c1cad2e7SMatthew G. Knepley 8009566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 801c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 802c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 803c1cad2e7SMatthew G. Knepley 8049566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 805ad540459SPierre Jolivet if (mtype != DEGENERATE) ++edgeTemp; 806c1cad2e7SMatthew G. Knepley } 807c1cad2e7SMatthew G. Knepley numCells += (2 * edgeTemp); 808c1cad2e7SMatthew G. Knepley EG_free(eobjs); 809c1cad2e7SMatthew G. Knepley } 810c1cad2e7SMatthew G. Knepley EG_free(fobjs); 811c1cad2e7SMatthew G. Knepley 812c1cad2e7SMatthew G. Knepley numFaces += Nf; 813c1cad2e7SMatthew G. Knepley numEdges += Netemp; 814c1cad2e7SMatthew G. Knepley numVertices += Nv; 815c1cad2e7SMatthew G. Knepley edgeCntr += Ne; 816c1cad2e7SMatthew G. Knepley } 817c1cad2e7SMatthew G. Knepley 818c1cad2e7SMatthew G. Knepley // Set up basic DMPlex parameters 81935cb6cd3SPierre Jolivet dim = 2; // Assumes 3D Models :: Need to handle 2D models in the future 82035cb6cd3SPierre Jolivet cdim = 3; // Assumes 3D Models :: Need to update to handle 2D models in future 821c1cad2e7SMatthew G. Knepley numCorners = 3; // Split Faces into triangles 822c1cad2e7SMatthew G. Knepley numPoints = numVertices + numEdges + numFaces; // total number of coordinate points 823c1cad2e7SMatthew G. Knepley 8249566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPoints * cdim, &coords, numCells * numCorners, &cells)); 825c1cad2e7SMatthew G. Knepley 826c1cad2e7SMatthew G. Knepley // Get Vertex Coordinates and Set up Cells 827c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 828c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 829c1cad2e7SMatthew G. Knepley int Nf, Ne, Nv; 830c1cad2e7SMatthew G. Knepley PetscInt bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart; 831c1cad2e7SMatthew G. Knepley PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter; 832c1cad2e7SMatthew G. Knepley PetscBool BVfound, BEfound, BEGfound, BFfound, EMfound; 833c1cad2e7SMatthew G. Knepley 834c1cad2e7SMatthew G. Knepley // Vertices on Current Body 8359566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 836c1cad2e7SMatthew G. Knepley 8379566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 83828b400f6SJacob Faibussowitsch PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyVertexMap", b); 8399566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart)); 840c1cad2e7SMatthew G. Knepley 841c1cad2e7SMatthew G. Knepley for (int v = 0; v < Nv; ++v) { 842c1cad2e7SMatthew G. Knepley ego vertex = nobjs[v]; 843c1cad2e7SMatthew G. Knepley double limits[4]; 844c1cad2e7SMatthew G. Knepley int id, dummy; 845c1cad2e7SMatthew G. Knepley 8469566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 8475f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, vertex); 848c1cad2e7SMatthew G. Knepley 849c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 0] = limits[0]; 850c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 1] = limits[1]; 851c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 2] = limits[2]; 852c1cad2e7SMatthew G. Knepley } 853c1cad2e7SMatthew G. Knepley EG_free(nobjs); 854c1cad2e7SMatthew G. Knepley 855c1cad2e7SMatthew G. Knepley // Edge Midpoint Vertices on Current Body 8569566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 857c1cad2e7SMatthew G. Knepley 8589566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 85928b400f6SJacob Faibussowitsch PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeMap", b); 8609566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart)); 861c1cad2e7SMatthew G. Knepley 8629566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 86328b400f6SJacob Faibussowitsch PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeGlobalMap", b); 8649566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart)); 865c1cad2e7SMatthew G. Knepley 866c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 867c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 868c1cad2e7SMatthew G. Knepley double range[2], avgt[1], cntrPnt[9]; 869c1cad2e7SMatthew G. Knepley int eid, eOffset; 870c1cad2e7SMatthew G. Knepley int periodic; 871c1cad2e7SMatthew G. Knepley 8729566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 873ad540459SPierre Jolivet if (mtype == DEGENERATE) continue; 874c1cad2e7SMatthew G. Knepley 8755f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 876c1cad2e7SMatthew G. Knepley 877c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector 8789566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 87928b400f6SJacob Faibussowitsch PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %d not found in edgeMap", bodyEdgeGlobalIndexStart + eid - 1); 8809566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 881c1cad2e7SMatthew G. Knepley 8829566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, &periodic)); 883c1cad2e7SMatthew G. Knepley avgt[0] = (range[0] + range[1]) / 2.; 884c1cad2e7SMatthew G. Knepley 8859566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, avgt, cntrPnt)); 886c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 0] = cntrPnt[0]; 887c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 1] = cntrPnt[1]; 888c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 2] = cntrPnt[2]; 889c1cad2e7SMatthew G. Knepley } 890c1cad2e7SMatthew G. Knepley EG_free(eobjs); 891c1cad2e7SMatthew G. Knepley 892c1cad2e7SMatthew G. Knepley // Face Midpoint Vertices on Current Body 8939566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 894c1cad2e7SMatthew G. Knepley 8959566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 89628b400f6SJacob Faibussowitsch PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b); 8979566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart)); 898c1cad2e7SMatthew G. Knepley 899c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 900c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 901c1cad2e7SMatthew G. Knepley double range[4], avgUV[2], cntrPnt[18]; 902c1cad2e7SMatthew G. Knepley int peri, id; 903c1cad2e7SMatthew G. Knepley 904c1cad2e7SMatthew G. Knepley id = EG_indexBodyTopo(body, face); 9059566063dSJacob Faibussowitsch PetscCall(EG_getRange(face, range, &peri)); 906c1cad2e7SMatthew G. Knepley 907c1cad2e7SMatthew G. Knepley avgUV[0] = (range[0] + range[1]) / 2.; 908c1cad2e7SMatthew G. Knepley avgUV[1] = (range[2] + range[3]) / 2.; 9099566063dSJacob Faibussowitsch PetscCall(EG_evaluate(face, avgUV, cntrPnt)); 910c1cad2e7SMatthew G. Knepley 911c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 0] = cntrPnt[0]; 912c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 1] = cntrPnt[1]; 913c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 2] = cntrPnt[2]; 914c1cad2e7SMatthew G. Knepley } 915c1cad2e7SMatthew G. Knepley EG_free(fobjs); 916c1cad2e7SMatthew G. Knepley 917c1cad2e7SMatthew G. Knepley // Define Cells :: Note - This could be incorporated in the Face Midpoint Vertices Loop but was kept separate for clarity 9189566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 919c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 920c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 921c1cad2e7SMatthew G. Knepley int fID, midFaceID, midPntID, startID, endID, Nl; 922c1cad2e7SMatthew G. Knepley 9235f80ce2aSJacob Faibussowitsch fID = EG_indexBodyTopo(body, face); 924c1cad2e7SMatthew G. Knepley midFaceID = numVertices + numEdges + bodyFaceIndexStart + fID - 1; 925c1cad2e7SMatthew G. Knepley // Must Traverse Loop to ensure we have all necessary information like the sense (+/- 1) of the edges. 926c1cad2e7SMatthew G. Knepley // TODO :: Only handles single loop faces (No holes). The choices for handling multiloop faces are: 927c1cad2e7SMatthew G. Knepley // 1) Use the DMPlexCreateEGADSFromFile() with the -dm_plex_egads_with_tess = 1 option. 928c1cad2e7SMatthew G. Knepley // This will use a default EGADS tessellation as an initial surface mesh. 929d5b43468SJose E. Roman // 2) Create the initial surface mesh via a 2D mesher :: Currently not available (?future?) 930c1cad2e7SMatthew G. Knepley // May I suggest the XXXX as a starting point? 931c1cad2e7SMatthew G. Knepley 9329566063dSJacob Faibussowitsch PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses)); 933c1cad2e7SMatthew G. Knepley 93408401ef6SPierre Jolivet PetscCheck(Nl <= 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face has %d Loops. Can only handle Faces with 1 Loop. Please use --dm_plex_egads_with_tess = 1 Option", Nl); 935c1cad2e7SMatthew G. Knepley for (int l = 0; l < Nl; ++l) { 936c1cad2e7SMatthew G. Knepley ego loop = lobjs[l]; 937c1cad2e7SMatthew G. Knepley 9389566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 939c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 940c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 941c1cad2e7SMatthew G. Knepley int eid, eOffset; 942c1cad2e7SMatthew G. Knepley 9439566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 944c1cad2e7SMatthew G. Knepley eid = EG_indexBodyTopo(body, edge); 945ad540459SPierre Jolivet if (mtype == DEGENERATE) continue; 946c1cad2e7SMatthew G. Knepley 947c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector 9489566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 94928b400f6SJacob Faibussowitsch PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %d of Body %d not found in edgeMap. Global Edge ID :: %d", eid, b, bodyEdgeGlobalIndexStart + eid - 1); 9509566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 951c1cad2e7SMatthew G. Knepley 952c1cad2e7SMatthew G. Knepley midPntID = numVertices + bodyEdgeIndexStart + eOffset - 1; 953c1cad2e7SMatthew G. Knepley 9549566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 955c1cad2e7SMatthew G. Knepley 9569371c9d4SSatish Balay if (eSenses[e] > 0) { 9579371c9d4SSatish Balay startID = EG_indexBodyTopo(body, nobjs[0]); 9589371c9d4SSatish Balay endID = EG_indexBodyTopo(body, nobjs[1]); 9599371c9d4SSatish Balay } else { 9609371c9d4SSatish Balay startID = EG_indexBodyTopo(body, nobjs[1]); 9619371c9d4SSatish Balay endID = EG_indexBodyTopo(body, nobjs[0]); 9629371c9d4SSatish Balay } 963c1cad2e7SMatthew G. Knepley 964c1cad2e7SMatthew G. Knepley // Define 2 Cells per Edge with correct orientation 965c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 0] = midFaceID; 966c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 1] = bodyVertexIndexStart + startID - 1; 967c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 2] = midPntID; 968c1cad2e7SMatthew G. Knepley 969c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 3] = midFaceID; 970c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 4] = midPntID; 971c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 5] = bodyVertexIndexStart + endID - 1; 972c1cad2e7SMatthew G. Knepley 973c1cad2e7SMatthew G. Knepley cellCntr = cellCntr + 2; 974c1cad2e7SMatthew G. Knepley } 975c1cad2e7SMatthew G. Knepley } 976c1cad2e7SMatthew G. Knepley } 977c1cad2e7SMatthew G. Knepley EG_free(fobjs); 978c1cad2e7SMatthew G. Knepley } 979c1cad2e7SMatthew G. Knepley } 980c1cad2e7SMatthew G. Knepley 981c1cad2e7SMatthew G. Knepley // Generate DMPlex 9829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 9839566063dSJacob Faibussowitsch PetscCall(PetscFree2(coords, cells)); 98463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %" PetscInt_FMT " \n", numCells)); 98563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %" PetscInt_FMT " \n", numVertices)); 986c1cad2e7SMatthew G. Knepley 987c1cad2e7SMatthew G. Knepley // Embed EGADS model in DM 988c1cad2e7SMatthew G. Knepley { 989c1cad2e7SMatthew G. Knepley PetscContainer modelObj, contextObj; 990c1cad2e7SMatthew G. Knepley 9919566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 9929566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model)); 9939566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 9949566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj)); 995c1cad2e7SMatthew G. Knepley 9969566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 9979566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context)); 9989566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(contextObj, DMPlexEGADSDestroy_Private)); 9999566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 10009566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj)); 1001c1cad2e7SMatthew G. Knepley } 1002c1cad2e7SMatthew G. Knepley // Label points 1003c1cad2e7SMatthew G. Knepley PetscInt nStart, nEnd; 1004c1cad2e7SMatthew G. Knepley 10059566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 10069566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 10079566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 10089566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 10099566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 10109566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 10119566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 10129566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 1013c1cad2e7SMatthew G. Knepley 10149566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd)); 1015c1cad2e7SMatthew G. Knepley 1016c1cad2e7SMatthew G. Knepley cellCntr = 0; 1017c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 1018c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 1019c1cad2e7SMatthew G. Knepley int Nv, Ne, Nf; 1020c1cad2e7SMatthew G. Knepley PetscInt bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart; 1021c1cad2e7SMatthew G. Knepley PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter; 1022c1cad2e7SMatthew G. Knepley PetscBool BVfound, BEfound, BEGfound, BFfound, EMfound; 1023c1cad2e7SMatthew G. Knepley 10249566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 102528b400f6SJacob Faibussowitsch PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyVertexMap", b); 10269566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart)); 1027c1cad2e7SMatthew G. Knepley 10289566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 102928b400f6SJacob Faibussowitsch PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeMap", b); 10309566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart)); 1031c1cad2e7SMatthew G. Knepley 10329566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 103328b400f6SJacob Faibussowitsch PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b); 10349566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart)); 1035c1cad2e7SMatthew G. Knepley 10369566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 103728b400f6SJacob Faibussowitsch PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeGlobalMap", b); 10389566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart)); 1039c1cad2e7SMatthew G. Knepley 10409566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1041c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 1042c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 1043c1cad2e7SMatthew G. Knepley int fID, Nl; 1044c1cad2e7SMatthew G. Knepley 10455f80ce2aSJacob Faibussowitsch fID = EG_indexBodyTopo(body, face); 1046c1cad2e7SMatthew G. Knepley 10479566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, face, LOOP, &Nl, &lobjs)); 1048c1cad2e7SMatthew G. Knepley for (int l = 0; l < Nl; ++l) { 1049c1cad2e7SMatthew G. Knepley ego loop = lobjs[l]; 1050c1cad2e7SMatthew G. Knepley int lid; 1051c1cad2e7SMatthew G. Knepley 10525f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 105308401ef6SPierre Jolivet PetscCheck(Nl <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf); 1054c1cad2e7SMatthew G. Knepley 10559566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1056c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 1057c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 1058c1cad2e7SMatthew G. Knepley int eid, eOffset; 1059c1cad2e7SMatthew G. Knepley 1060c1cad2e7SMatthew G. Knepley // Skip DEGENERATE Edges 10619566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1062ad540459SPierre Jolivet if (mtype == DEGENERATE) continue; 10635f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 1064c1cad2e7SMatthew G. Knepley 1065c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector 10669566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 106728b400f6SJacob Faibussowitsch PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %d of Body %d not found in edgeMap. Global Edge ID :: %d", eid, b, bodyEdgeGlobalIndexStart + eid - 1); 10689566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 1069c1cad2e7SMatthew G. Knepley 10709566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, edge, NODE, &Nv, &nobjs)); 1071c1cad2e7SMatthew G. Knepley for (int v = 0; v < Nv; ++v) { 1072c1cad2e7SMatthew G. Knepley ego vertex = nobjs[v]; 1073c1cad2e7SMatthew G. Knepley int vID; 1074c1cad2e7SMatthew G. Knepley 10755f80ce2aSJacob Faibussowitsch vID = EG_indexBodyTopo(body, vertex); 10769566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + bodyVertexIndexStart + vID - 1, b)); 10779566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(vertexLabel, nStart + bodyVertexIndexStart + vID - 1, vID)); 1078c1cad2e7SMatthew G. Knepley } 1079c1cad2e7SMatthew G. Knepley EG_free(nobjs); 1080c1cad2e7SMatthew G. Knepley 10819566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, b)); 10829566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, eid)); 1083c1cad2e7SMatthew G. Knepley 1084c1cad2e7SMatthew G. Knepley // Define Cell faces 1085c1cad2e7SMatthew G. Knepley for (int jj = 0; jj < 2; ++jj) { 10869566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cellCntr, b)); 10879566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cellCntr, fID)); 10889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cellCntr, &cone)); 1089c1cad2e7SMatthew G. Knepley 10909566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[0], b)); 10919566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[0], fID)); 1092c1cad2e7SMatthew G. Knepley 10939566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[1], b)); 10949566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, cone[1], eid)); 1095c1cad2e7SMatthew G. Knepley 10969566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[2], b)); 10979566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[2], fID)); 1098c1cad2e7SMatthew G. Knepley 1099c1cad2e7SMatthew G. Knepley cellCntr = cellCntr + 1; 1100c1cad2e7SMatthew G. Knepley } 1101c1cad2e7SMatthew G. Knepley } 1102c1cad2e7SMatthew G. Knepley } 1103c1cad2e7SMatthew G. Knepley EG_free(lobjs); 1104c1cad2e7SMatthew G. Knepley 11059566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, b)); 11069566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, fID)); 1107c1cad2e7SMatthew G. Knepley } 1108c1cad2e7SMatthew G. Knepley EG_free(fobjs); 1109c1cad2e7SMatthew G. Knepley } 1110c1cad2e7SMatthew G. Knepley 11119566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&edgeMap)); 11129566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyIndexMap)); 11139566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyVertexMap)); 11149566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyEdgeMap)); 11159566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyEdgeGlobalMap)); 11169566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyFaceMap)); 1117c1cad2e7SMatthew G. Knepley 1118c1cad2e7SMatthew G. Knepley *newdm = dm; 11193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1120c1cad2e7SMatthew G. Knepley } 1121c1cad2e7SMatthew G. Knepley 1122d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateEGADS_Tess_Internal(MPI_Comm comm, ego context, ego model, DM *newdm) 1123d71ae5a4SJacob Faibussowitsch { 1124c1cad2e7SMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 1125c1cad2e7SMatthew G. Knepley /* EGADSLite variables */ 1126c1cad2e7SMatthew G. Knepley ego geom, *bodies, *fobjs; 1127c1cad2e7SMatthew G. Knepley int b, oclass, mtype, nbodies, *senses; 1128c1cad2e7SMatthew G. Knepley int totalNumTris = 0, totalNumPoints = 0; 1129c1cad2e7SMatthew G. Knepley double boundBox[6] = {0., 0., 0., 0., 0., 0.}, tessSize; 1130c1cad2e7SMatthew G. Knepley /* PETSc variables */ 1131c1cad2e7SMatthew G. Knepley DM dm; 1132c1cad2e7SMatthew G. Knepley PetscHMapI pointIndexStartMap = NULL, triIndexStartMap = NULL, pTypeLabelMap = NULL, pIndexLabelMap = NULL; 1133c1cad2e7SMatthew G. Knepley PetscHMapI pBodyIndexLabelMap = NULL, triFaceIDLabelMap = NULL, triBodyIDLabelMap = NULL; 1134c1cad2e7SMatthew G. Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, counter = 0; 1135c1cad2e7SMatthew G. Knepley PetscInt *cells = NULL; 1136c1cad2e7SMatthew G. Knepley const PetscInt *cone = NULL; 1137c1cad2e7SMatthew G. Knepley PetscReal *coords = NULL; 1138c1cad2e7SMatthew G. Knepley PetscMPIInt rank; 1139c1cad2e7SMatthew G. Knepley 1140c1cad2e7SMatthew G. Knepley PetscFunctionBeginUser; 11419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1142c5853193SPierre Jolivet if (rank == 0) { 1143c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 1144c1cad2e7SMatthew G. Knepley // Generate Petsc Plex from EGADSlite created Tessellation of geometry 1145c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 1146c1cad2e7SMatthew G. Knepley 1147d5b43468SJose E. Roman // Calculate cell and vertex sizes 11489566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 1149c1cad2e7SMatthew G. Knepley 11509566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pointIndexStartMap)); 11519566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triIndexStartMap)); 11529566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pTypeLabelMap)); 11539566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pIndexLabelMap)); 11549566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pBodyIndexLabelMap)); 11559566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triFaceIDLabelMap)); 11569566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triBodyIDLabelMap)); 1157c1cad2e7SMatthew G. Knepley 1158c1cad2e7SMatthew G. Knepley /* Create Tessellation of Bodies */ 1159c1cad2e7SMatthew G. Knepley ego tessArray[nbodies]; 1160c1cad2e7SMatthew G. Knepley 1161c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 1162c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 1163c1cad2e7SMatthew G. Knepley double params[3] = {0.0, 0.0, 0.0}; // Parameters for Tessellation 1164c1cad2e7SMatthew G. Knepley int Nf, bodyNumPoints = 0, bodyNumTris = 0; 1165c1cad2e7SMatthew G. Knepley PetscHashIter PISiter, TISiter; 1166c1cad2e7SMatthew G. Knepley PetscBool PISfound, TISfound; 1167c1cad2e7SMatthew G. Knepley 1168c1cad2e7SMatthew G. Knepley /* Store Start Index for each Body's Point and Tris */ 11699566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound)); 11709566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triIndexStartMap, b, &TISiter, &TISfound)); 1171c1cad2e7SMatthew G. Knepley 11729566063dSJacob Faibussowitsch if (!PISfound) PetscCall(PetscHMapISet(pointIndexStartMap, b, totalNumPoints)); 11739566063dSJacob Faibussowitsch if (!TISfound) PetscCall(PetscHMapISet(triIndexStartMap, b, totalNumTris)); 1174c1cad2e7SMatthew G. Knepley 1175c1cad2e7SMatthew G. Knepley /* Calculate Tessellation parameters based on Bounding Box */ 1176c1cad2e7SMatthew G. Knepley /* Get Bounding Box Dimensions of the BODY */ 11779566063dSJacob Faibussowitsch PetscCall(EG_getBoundingBox(body, boundBox)); 1178c1cad2e7SMatthew G. Knepley tessSize = boundBox[3] - boundBox[0]; 1179c1cad2e7SMatthew G. Knepley if (tessSize < boundBox[4] - boundBox[1]) tessSize = boundBox[4] - boundBox[1]; 1180c1cad2e7SMatthew G. Knepley if (tessSize < boundBox[5] - boundBox[2]) tessSize = boundBox[5] - boundBox[2]; 1181c1cad2e7SMatthew G. Knepley 1182c1cad2e7SMatthew G. Knepley // TODO :: May want to give users tessellation parameter options // 1183c1cad2e7SMatthew G. Knepley params[0] = 0.0250 * tessSize; 1184c1cad2e7SMatthew G. Knepley params[1] = 0.0075 * tessSize; 1185c1cad2e7SMatthew G. Knepley params[2] = 15.0; 1186c1cad2e7SMatthew G. Knepley 11879566063dSJacob Faibussowitsch PetscCall(EG_makeTessBody(body, params, &tessArray[b])); 1188c1cad2e7SMatthew G. Knepley 11899566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1190c1cad2e7SMatthew G. Knepley 1191c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 1192c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 1193c1cad2e7SMatthew G. Knepley int len, fID, ntris; 1194c1cad2e7SMatthew G. Knepley const int *ptype, *pindex, *ptris, *ptric; 1195c1cad2e7SMatthew G. Knepley const double *pxyz, *puv; 1196c1cad2e7SMatthew G. Knepley 1197c1cad2e7SMatthew G. Knepley // Get Face ID // 1198c1cad2e7SMatthew G. Knepley fID = EG_indexBodyTopo(body, face); 1199c1cad2e7SMatthew G. Knepley 1200c1cad2e7SMatthew G. Knepley // Checkout the Surface Tessellation // 12019566063dSJacob Faibussowitsch PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 1202c1cad2e7SMatthew G. Knepley 1203c1cad2e7SMatthew G. Knepley // Determine total number of triangle cells in the tessellation // 1204c1cad2e7SMatthew G. Knepley bodyNumTris += (int)ntris; 1205c1cad2e7SMatthew G. Knepley 1206c1cad2e7SMatthew G. Knepley // Check out the point index and coordinate // 1207c1cad2e7SMatthew G. Knepley for (int p = 0; p < len; ++p) { 1208c1cad2e7SMatthew G. Knepley int global; 1209c1cad2e7SMatthew G. Knepley 12109566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global)); 1211c1cad2e7SMatthew G. Knepley 1212c1cad2e7SMatthew G. Knepley // Determine the total number of points in the tessellation // 1213c1cad2e7SMatthew G. Knepley bodyNumPoints = PetscMax(bodyNumPoints, global); 1214c1cad2e7SMatthew G. Knepley } 1215c1cad2e7SMatthew G. Knepley } 1216c1cad2e7SMatthew G. Knepley EG_free(fobjs); 1217c1cad2e7SMatthew G. Knepley 1218c1cad2e7SMatthew G. Knepley totalNumPoints += bodyNumPoints; 1219c1cad2e7SMatthew G. Knepley totalNumTris += bodyNumTris; 1220c1cad2e7SMatthew G. Knepley } 1221c5853193SPierre Jolivet //} - Original End of (rank == 0) 1222c1cad2e7SMatthew G. Knepley 1223c1cad2e7SMatthew G. Knepley dim = 2; 1224c1cad2e7SMatthew G. Knepley cdim = 3; 1225c1cad2e7SMatthew G. Knepley numCorners = 3; 1226c1cad2e7SMatthew G. Knepley //PetscInt counter = 0; 1227c1cad2e7SMatthew G. Knepley 1228c1cad2e7SMatthew G. Knepley /* NEED TO DEFINE MATRICES/VECTORS TO STORE GEOM REFERENCE DATA */ 1229c1cad2e7SMatthew G. Knepley /* Fill in below and use to define DMLabels after DMPlex creation */ 12309566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(totalNumPoints * cdim, &coords, totalNumTris * numCorners, &cells)); 1231c1cad2e7SMatthew G. Knepley 1232c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 1233c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 1234c1cad2e7SMatthew G. Knepley int Nf; 1235c1cad2e7SMatthew G. Knepley PetscInt pointIndexStart; 1236c1cad2e7SMatthew G. Knepley PetscHashIter PISiter; 1237c1cad2e7SMatthew G. Knepley PetscBool PISfound; 1238c1cad2e7SMatthew G. Knepley 12399566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound)); 124028b400f6SJacob Faibussowitsch PetscCheck(PISfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in pointIndexStartMap", b); 12419566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pointIndexStartMap, b, &pointIndexStart)); 1242c1cad2e7SMatthew G. Knepley 12439566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1244c1cad2e7SMatthew G. Knepley 1245c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 1246c1cad2e7SMatthew G. Knepley /* Get Face Object */ 1247c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 1248c1cad2e7SMatthew G. Knepley int len, fID, ntris; 1249c1cad2e7SMatthew G. Knepley const int *ptype, *pindex, *ptris, *ptric; 1250c1cad2e7SMatthew G. Knepley const double *pxyz, *puv; 1251c1cad2e7SMatthew G. Knepley 1252c1cad2e7SMatthew G. Knepley /* Get Face ID */ 1253c1cad2e7SMatthew G. Knepley fID = EG_indexBodyTopo(body, face); 1254c1cad2e7SMatthew G. Knepley 1255c1cad2e7SMatthew G. Knepley /* Checkout the Surface Tessellation */ 12569566063dSJacob Faibussowitsch PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 1257c1cad2e7SMatthew G. Knepley 1258c1cad2e7SMatthew G. Knepley /* Check out the point index and coordinate */ 1259c1cad2e7SMatthew G. Knepley for (int p = 0; p < len; ++p) { 1260c1cad2e7SMatthew G. Knepley int global; 1261c1cad2e7SMatthew G. Knepley PetscHashIter PTLiter, PILiter, PBLiter; 1262c1cad2e7SMatthew G. Knepley PetscBool PTLfound, PILfound, PBLfound; 1263c1cad2e7SMatthew G. Knepley 12649566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global)); 1265c1cad2e7SMatthew G. Knepley 1266c1cad2e7SMatthew G. Knepley /* Set the coordinates array for DAG */ 1267c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 0] = pxyz[(p * 3) + 0]; 1268c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 1] = pxyz[(p * 3) + 1]; 1269c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 2] = pxyz[(p * 3) + 2]; 1270c1cad2e7SMatthew G. Knepley 1271c1cad2e7SMatthew G. Knepley /* Store Geometry Label Information for DMLabel assignment later */ 12729566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pTypeLabelMap, global - 1 + pointIndexStart, &PTLiter, &PTLfound)); 12739566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pIndexLabelMap, global - 1 + pointIndexStart, &PILiter, &PILfound)); 12749566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pBodyIndexLabelMap, global - 1 + pointIndexStart, &PBLiter, &PBLfound)); 1275c1cad2e7SMatthew G. Knepley 12769566063dSJacob Faibussowitsch if (!PTLfound) PetscCall(PetscHMapISet(pTypeLabelMap, global - 1 + pointIndexStart, ptype[p])); 12779566063dSJacob Faibussowitsch if (!PILfound) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, pindex[p])); 12789566063dSJacob Faibussowitsch if (!PBLfound) PetscCall(PetscHMapISet(pBodyIndexLabelMap, global - 1 + pointIndexStart, b)); 1279c1cad2e7SMatthew G. Knepley 12809566063dSJacob Faibussowitsch if (ptype[p] < 0) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, fID)); 1281c1cad2e7SMatthew G. Knepley } 1282c1cad2e7SMatthew G. Knepley 1283c1cad2e7SMatthew G. Knepley for (int t = 0; t < (int)ntris; ++t) { 1284c1cad2e7SMatthew G. Knepley int global, globalA, globalB; 1285c1cad2e7SMatthew G. Knepley PetscHashIter TFLiter, TBLiter; 1286c1cad2e7SMatthew G. Knepley PetscBool TFLfound, TBLfound; 1287c1cad2e7SMatthew G. Knepley 12889566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global)); 1289c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 0] = global - 1 + pointIndexStart; 1290c1cad2e7SMatthew G. Knepley 12919566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA)); 1292c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 1] = globalA - 1 + pointIndexStart; 1293c1cad2e7SMatthew G. Knepley 12949566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB)); 1295c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 2] = globalB - 1 + pointIndexStart; 1296c1cad2e7SMatthew G. Knepley 12979566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triFaceIDLabelMap, counter, &TFLiter, &TFLfound)); 12989566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triBodyIDLabelMap, counter, &TBLiter, &TBLfound)); 1299c1cad2e7SMatthew G. Knepley 13009566063dSJacob Faibussowitsch if (!TFLfound) PetscCall(PetscHMapISet(triFaceIDLabelMap, counter, fID)); 13019566063dSJacob Faibussowitsch if (!TBLfound) PetscCall(PetscHMapISet(triBodyIDLabelMap, counter, b)); 1302c1cad2e7SMatthew G. Knepley 1303c1cad2e7SMatthew G. Knepley counter += 1; 1304c1cad2e7SMatthew G. Knepley } 1305c1cad2e7SMatthew G. Knepley } 1306c1cad2e7SMatthew G. Knepley EG_free(fobjs); 1307c1cad2e7SMatthew G. Knepley } 1308c1cad2e7SMatthew G. Knepley } 1309c1cad2e7SMatthew G. Knepley 1310c1cad2e7SMatthew G. Knepley //Build DMPlex 13119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, totalNumTris, totalNumPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 13129566063dSJacob Faibussowitsch PetscCall(PetscFree2(coords, cells)); 1313c1cad2e7SMatthew G. Knepley 1314c1cad2e7SMatthew G. Knepley // Embed EGADS model in DM 1315c1cad2e7SMatthew G. Knepley { 1316c1cad2e7SMatthew G. Knepley PetscContainer modelObj, contextObj; 1317c1cad2e7SMatthew G. Knepley 13189566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 13199566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model)); 13209566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 13219566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj)); 1322c1cad2e7SMatthew G. Knepley 13239566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 13249566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context)); 13259566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(contextObj, DMPlexEGADSDestroy_Private)); 13269566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 13279566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj)); 1328c1cad2e7SMatthew G. Knepley } 1329c1cad2e7SMatthew G. Knepley 1330c1cad2e7SMatthew G. Knepley // Label Points 13319566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 13329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 13339566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 13349566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 13359566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 13369566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 13379566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 13389566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 1339c1cad2e7SMatthew G. Knepley 1340c1cad2e7SMatthew G. Knepley /* Get Number of DAG Nodes at each level */ 1341c1cad2e7SMatthew G. Knepley int fStart, fEnd, eStart, eEnd, nStart, nEnd; 1342c1cad2e7SMatthew G. Knepley 13439566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &fStart, &fEnd)); 13449566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &eStart, &eEnd)); 13459566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd)); 1346c1cad2e7SMatthew G. Knepley 1347c1cad2e7SMatthew G. Knepley /* Set DMLabels for NODES */ 1348c1cad2e7SMatthew G. Knepley for (int n = nStart; n < nEnd; ++n) { 1349c1cad2e7SMatthew G. Knepley int pTypeVal, pIndexVal, pBodyVal; 1350c1cad2e7SMatthew G. Knepley PetscHashIter PTLiter, PILiter, PBLiter; 1351c1cad2e7SMatthew G. Knepley PetscBool PTLfound, PILfound, PBLfound; 1352c1cad2e7SMatthew G. Knepley 1353c1cad2e7SMatthew G. Knepley //Converted to Hash Tables 13549566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pTypeLabelMap, n - nStart, &PTLiter, &PTLfound)); 135528b400f6SJacob Faibussowitsch PetscCheck(PTLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in pTypeLabelMap", n); 13569566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pTypeLabelMap, n - nStart, &pTypeVal)); 1357c1cad2e7SMatthew G. Knepley 13589566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pIndexLabelMap, n - nStart, &PILiter, &PILfound)); 135928b400f6SJacob Faibussowitsch PetscCheck(PILfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in pIndexLabelMap", n); 13609566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pIndexLabelMap, n - nStart, &pIndexVal)); 1361c1cad2e7SMatthew G. Knepley 13629566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pBodyIndexLabelMap, n - nStart, &PBLiter, &PBLfound)); 136328b400f6SJacob Faibussowitsch PetscCheck(PBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in pBodyLabelMap", n); 13649566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pBodyIndexLabelMap, n - nStart, &pBodyVal)); 1365c1cad2e7SMatthew G. Knepley 13669566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, n, pBodyVal)); 13679566063dSJacob Faibussowitsch if (pTypeVal == 0) PetscCall(DMLabelSetValue(vertexLabel, n, pIndexVal)); 13689566063dSJacob Faibussowitsch if (pTypeVal > 0) PetscCall(DMLabelSetValue(edgeLabel, n, pIndexVal)); 13699566063dSJacob Faibussowitsch if (pTypeVal < 0) PetscCall(DMLabelSetValue(faceLabel, n, pIndexVal)); 1370c1cad2e7SMatthew G. Knepley } 1371c1cad2e7SMatthew G. Knepley 1372c1cad2e7SMatthew G. Knepley /* Set DMLabels for Edges - Based on the DMLabels of the EDGE's NODES */ 1373c1cad2e7SMatthew G. Knepley for (int e = eStart; e < eEnd; ++e) { 1374c1cad2e7SMatthew G. Knepley int bodyID_0, vertexID_0, vertexID_1, edgeID_0, edgeID_1, faceID_0, faceID_1; 1375c1cad2e7SMatthew G. Knepley 13769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 13779566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, cone[0], &bodyID_0)); // Do I need to check the other end? 13789566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, cone[0], &vertexID_0)); 13799566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, cone[1], &vertexID_1)); 13809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[0], &edgeID_0)); 13819566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[1], &edgeID_1)); 13829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, cone[0], &faceID_0)); 13839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, cone[1], &faceID_1)); 1384c1cad2e7SMatthew G. Knepley 13859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, e, bodyID_0)); 1386c1cad2e7SMatthew G. Knepley 13879566063dSJacob Faibussowitsch if (edgeID_0 == edgeID_1) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0)); 13889566063dSJacob Faibussowitsch else if (vertexID_0 > 0 && edgeID_1 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_1)); 13899566063dSJacob Faibussowitsch else if (vertexID_1 > 0 && edgeID_0 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0)); 1390c1cad2e7SMatthew G. Knepley else { /* Do Nothing */ } 1391c1cad2e7SMatthew G. Knepley } 1392c1cad2e7SMatthew G. Knepley 1393c1cad2e7SMatthew G. Knepley /* Set DMLabels for Cells */ 1394c1cad2e7SMatthew G. Knepley for (int f = fStart; f < fEnd; ++f) { 1395c1cad2e7SMatthew G. Knepley int edgeID_0; 1396c1cad2e7SMatthew G. Knepley PetscInt triBodyVal, triFaceVal; 1397c1cad2e7SMatthew G. Knepley PetscHashIter TFLiter, TBLiter; 1398c1cad2e7SMatthew G. Knepley PetscBool TFLfound, TBLfound; 1399c1cad2e7SMatthew G. Knepley 1400c1cad2e7SMatthew G. Knepley // Convert to Hash Table 14019566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triFaceIDLabelMap, f - fStart, &TFLiter, &TFLfound)); 140228b400f6SJacob Faibussowitsch PetscCheck(TFLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in triFaceIDLabelMap", f); 14039566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(triFaceIDLabelMap, f - fStart, &triFaceVal)); 1404c1cad2e7SMatthew G. Knepley 14059566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triBodyIDLabelMap, f - fStart, &TBLiter, &TBLfound)); 140628b400f6SJacob Faibussowitsch PetscCheck(TBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %d not found in triBodyIDLabelMap", f); 14079566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(triBodyIDLabelMap, f - fStart, &triBodyVal)); 1408c1cad2e7SMatthew G. Knepley 14099566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, f, triBodyVal)); 14109566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, f, triFaceVal)); 1411c1cad2e7SMatthew G. Knepley 1412c1cad2e7SMatthew G. Knepley /* Finish Labeling previously unlabeled DMPlex Edges - Assumes Triangular Cell (3 Edges Max) */ 14139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, f, &cone)); 1414c1cad2e7SMatthew G. Knepley 1415c1cad2e7SMatthew G. Knepley for (int jj = 0; jj < 3; ++jj) { 14169566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[jj], &edgeID_0)); 1417c1cad2e7SMatthew G. Knepley 1418c1cad2e7SMatthew G. Knepley if (edgeID_0 < 0) { 14199566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[jj], triBodyVal)); 14209566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[jj], triFaceVal)); 1421c1cad2e7SMatthew G. Knepley } 1422c1cad2e7SMatthew G. Knepley } 1423c1cad2e7SMatthew G. Knepley } 1424c1cad2e7SMatthew G. Knepley 1425c1cad2e7SMatthew G. Knepley *newdm = dm; 14263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1427c1cad2e7SMatthew G. Knepley } 14287bee2925SMatthew Knepley #endif 14297bee2925SMatthew Knepley 1430c1cad2e7SMatthew G. Knepley /*@ 143120f4b53cSBarry Smith DMPlexInflateToGeomModel - Snaps the vertex coordinates of a `DMPLEX` object representing the mesh to its geometry if some vertices depart from the model. 143220f4b53cSBarry Smith This usually happens with non-conforming refinement. 1433c1cad2e7SMatthew G. Knepley 143420f4b53cSBarry Smith Collective 1435c1cad2e7SMatthew G. Knepley 1436c1cad2e7SMatthew G. Knepley Input Parameter: 1437a1cb98faSBarry Smith . dm - The uninflated `DM` object representing the mesh 1438c1cad2e7SMatthew G. Knepley 1439c1cad2e7SMatthew G. Knepley Level: intermediate 1440c1cad2e7SMatthew G. Knepley 1441*1cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()` 1442c1cad2e7SMatthew G. Knepley @*/ 1443d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInflateToGeomModel(DM dm) 1444d71ae5a4SJacob Faibussowitsch { 1445c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS) 1446c1cad2e7SMatthew G. Knepley /* EGADS Variables */ 1447c1cad2e7SMatthew G. Knepley ego model, geom, body, face, edge; 1448c1cad2e7SMatthew G. Knepley ego *bodies; 1449c1cad2e7SMatthew G. Knepley int Nb, oclass, mtype, *senses; 1450c1cad2e7SMatthew G. Knepley double result[3]; 1451c1cad2e7SMatthew G. Knepley /* PETSc Variables */ 1452c1cad2e7SMatthew G. Knepley DM cdm; 1453c1cad2e7SMatthew G. Knepley PetscContainer modelObj; 1454c1cad2e7SMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 1455c1cad2e7SMatthew G. Knepley Vec coordinates; 1456c1cad2e7SMatthew G. Knepley PetscScalar *coords; 1457c1cad2e7SMatthew G. Knepley PetscInt bodyID, faceID, edgeID, vertexID; 1458c1cad2e7SMatthew G. Knepley PetscInt cdim, d, vStart, vEnd, v; 1459c1cad2e7SMatthew G. Knepley #endif 1460c1cad2e7SMatthew G. Knepley 1461c1cad2e7SMatthew G. Knepley PetscFunctionBegin; 1462c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS) 14639566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 14643ba16761SJacob Faibussowitsch if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 14659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 14669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 14679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 14689566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 14699566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 14709566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 14719566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 1472c1cad2e7SMatthew G. Knepley 14739566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 14749566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 1475c1cad2e7SMatthew G. Knepley 14769566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 14779566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 1478c1cad2e7SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 1479c1cad2e7SMatthew G. Knepley PetscScalar *vcoords; 1480c1cad2e7SMatthew G. Knepley 14819566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 14829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 14839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 14849566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 1485c1cad2e7SMatthew G. Knepley 148663a3b9bcSJacob Faibussowitsch PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %d)", bodyID, Nb); 1487c1cad2e7SMatthew G. Knepley body = bodies[bodyID]; 1488c1cad2e7SMatthew G. Knepley 14899566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 1490c1cad2e7SMatthew G. Knepley if (edgeID > 0) { 1491c1cad2e7SMatthew G. Knepley /* Snap to EDGE at nearest location */ 1492c1cad2e7SMatthew G. Knepley double params[1]; 14939566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 14949566063dSJacob Faibussowitsch PetscCall(EG_invEvaluate(edge, vcoords, params, result)); // Get (x,y,z) of nearest point on EDGE 1495c1cad2e7SMatthew G. Knepley for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 1496c1cad2e7SMatthew G. Knepley } else if (faceID > 0) { 1497c1cad2e7SMatthew G. Knepley /* Snap to FACE at nearest location */ 1498c1cad2e7SMatthew G. Knepley double params[2]; 14999566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 15009566063dSJacob Faibussowitsch PetscCall(EG_invEvaluate(face, vcoords, params, result)); // Get (x,y,z) of nearest point on FACE 1501c1cad2e7SMatthew G. Knepley for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 1502c1cad2e7SMatthew G. Knepley } 1503c1cad2e7SMatthew G. Knepley } 15049566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 1505c1cad2e7SMatthew G. Knepley /* Clear out global coordinates */ 15066858538eSMatthew G. Knepley PetscCall(VecDestroy(&dm->coordinates[0].x)); 1507c1cad2e7SMatthew G. Knepley #endif 15083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1509c1cad2e7SMatthew G. Knepley } 1510c1cad2e7SMatthew G. Knepley 15117bee2925SMatthew Knepley /*@C 1512a1cb98faSBarry Smith DMPlexCreateEGADSFromFile - Create a `DMPLEX` mesh from an EGADS, IGES, or STEP file. 15137bee2925SMatthew Knepley 15147bee2925SMatthew Knepley Collective 15157bee2925SMatthew Knepley 15167bee2925SMatthew Knepley Input Parameters: 15177bee2925SMatthew Knepley + comm - The MPI communicator 1518c1cad2e7SMatthew G. Knepley - filename - The name of the EGADS, IGES, or STEP file 15197bee2925SMatthew Knepley 15207bee2925SMatthew Knepley Output Parameter: 1521a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 15227bee2925SMatthew Knepley 15237bee2925SMatthew Knepley Level: beginner 15247bee2925SMatthew Knepley 1525*1cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`, `DMPlexCreateEGADSLiteFromFile()` 15267bee2925SMatthew Knepley @*/ 1527d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateEGADSFromFile(MPI_Comm comm, const char filename[], DM *dm) 1528d71ae5a4SJacob Faibussowitsch { 15297bee2925SMatthew Knepley PetscMPIInt rank; 15307bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS) 15317bee2925SMatthew Knepley ego context = NULL, model = NULL; 15327bee2925SMatthew Knepley #endif 1533c1cad2e7SMatthew G. Knepley PetscBool printModel = PETSC_FALSE, tessModel = PETSC_FALSE, newModel = PETSC_FALSE; 15347bee2925SMatthew Knepley 15357bee2925SMatthew Knepley PetscFunctionBegin; 15367bee2925SMatthew Knepley PetscValidCharPointer(filename, 2); 15379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_egads_print_model", &printModel, NULL)); 15389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_egads_tess_model", &tessModel, NULL)); 15399566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_egads_new_model", &newModel, NULL)); 15409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15417bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS) 1542dd400576SPatrick Sanan if (rank == 0) { 15439566063dSJacob Faibussowitsch PetscCall(EG_open(&context)); 15449566063dSJacob Faibussowitsch PetscCall(EG_loadModel(context, 0, filename, &model)); 15459566063dSJacob Faibussowitsch if (printModel) PetscCall(DMPlexEGADSPrintModel_Internal(model)); 15467bee2925SMatthew Knepley } 15479566063dSJacob Faibussowitsch if (tessModel) PetscCall(DMPlexCreateEGADS_Tess_Internal(comm, context, model, dm)); 15489566063dSJacob Faibussowitsch else if (newModel) PetscCall(DMPlexCreateEGADS(comm, context, model, dm)); 15499566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateEGADS_Internal(comm, context, model, dm)); 15503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15517bee2925SMatthew Knepley #else 1552c1cad2e7SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 15537bee2925SMatthew Knepley #endif 15547bee2925SMatthew Knepley } 1555