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