15552b385SBrandon #include "petscsys.h" 2a8ededdfSMatthew G. Knepley #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 37bee2925SMatthew Knepley #include <petsc/private/hashmapi.h> 4a8ededdfSMatthew G. Knepley 5337bb527SBarry Smith /* We need to understand how to natively parse STEP files. There seems to be only one open-source implementation of 6a8ededdfSMatthew G. Knepley the STEP parser contained in the OpenCASCADE package. It is enough to make a strong man weep: 7a8ededdfSMatthew G. Knepley 8a8ededdfSMatthew G. Knepley https://github.com/tpaviot/oce/tree/master/src/STEPControl 9a8ededdfSMatthew G. Knepley 10a8ededdfSMatthew G. Knepley The STEP, and inner EXPRESS, formats are ISO standards, so they are documented 11a8ededdfSMatthew G. Knepley 12a8ededdfSMatthew G. Knepley https://stackoverflow.com/questions/26774037/documentation-or-specification-for-step-and-stp-files 13a8ededdfSMatthew G. Knepley http://stepmod.sourceforge.net/express_model_spec/ 14a8ededdfSMatthew G. Knepley 15a8ededdfSMatthew G. Knepley but again it seems that there has been a deliberate effort at obfuscation, probably to raise the bar for entrants. 16a8ededdfSMatthew G. Knepley */ 17a8ededdfSMatthew G. Knepley 18c1cad2e7SMatthew G. Knepley #ifdef PETSC_HAVE_EGADS 195552b385SBrandon #include <petscdmplexegads.h> 20c1cad2e7SMatthew G. Knepley 215552b385SBrandon PETSC_INTERN PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM, PetscInt, ego, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscScalar[], PetscBool); 225552b385SBrandon PETSC_INTERN PetscErrorCode DMPlex_Geom_EDGE_XYZtoUV_Internal(const PetscScalar[], ego, const PetscScalar[], const PetscInt, const PetscInt, PetscScalar[], PetscBool); 235552b385SBrandon PETSC_INTERN PetscErrorCode DMPlex_Geom_FACE_XYZtoUV_Internal(const PetscScalar[], ego, const PetscScalar[], const PetscInt, const PetscInt, PetscScalar[], PetscBool); 245552b385SBrandon 255552b385SBrandon PetscErrorCode DMPlex_EGADS_GeomDecode_Internal(const PetscInt geomClass, const PetscInt geomType, char **retClass, char **retType) 26d71ae5a4SJacob Faibussowitsch { 275552b385SBrandon PetscFunctionBeginHot; 285552b385SBrandon /* EGADS Object Type */ 295552b385SBrandon if (geomClass == CONTXT) { *retClass = (char *)"CONTEXT"; } 305552b385SBrandon if (geomClass == TRANSFORM) { *retClass = (char *)"TRANSFORM"; } 315552b385SBrandon if (geomClass == TESSELLATION) { *retClass = (char *)"TESSELLATION"; } 325552b385SBrandon if (geomClass == NIL) { *retClass = (char *)"NIL"; } 335552b385SBrandon if (geomClass == EMPTY) { *retClass = (char *)"EMPTY"; } 345552b385SBrandon if (geomClass == REFERENCE) { *retClass = (char *)"REFERENCE"; } 355552b385SBrandon if (geomClass == PCURVE) { *retClass = (char *)"PCURVE"; } 365552b385SBrandon if (geomClass == CURVE) { *retClass = (char *)"CURVE"; } 375552b385SBrandon if (geomClass == SURFACE) { *retClass = (char *)"SURFACE"; } 385552b385SBrandon if (geomClass == NODE) { *retClass = (char *)"NODE"; } 395552b385SBrandon if (geomClass == EDGE) { *retClass = (char *)"EDGE"; } 405552b385SBrandon if (geomClass == LOOP) { *retClass = (char *)"LOOP"; } 415552b385SBrandon if (geomClass == FACE) { *retClass = (char *)"FACE"; } 425552b385SBrandon if (geomClass == SHELL) { *retClass = (char *)"SHELL"; } 435552b385SBrandon if (geomClass == BODY) { *retClass = (char *)"BODY"; } 445552b385SBrandon if (geomClass == MODEL) { *retClass = (char *)"MODEL"; } 455552b385SBrandon 465552b385SBrandon /* PCURVES & CURVES */ 475552b385SBrandon if (geomClass == PCURVE || geomClass == CURVE) { 485552b385SBrandon if (geomType == LINE) { *retType = (char *)"LINE"; } 495552b385SBrandon if (geomType == CIRCLE) { *retType = (char *)"CIRCLE"; } 505552b385SBrandon if (geomType == ELLIPSE) { *retType = (char *)"ELLIPSE"; } 515552b385SBrandon if (geomType == PARABOLA) { *retType = (char *)"PARABOLA"; } 525552b385SBrandon if (geomType == HYPERBOLA) { *retType = (char *)"HYPERBOLA"; } 535552b385SBrandon if (geomType == TRIMMED) { *retType = (char *)"TRIMMED"; } 545552b385SBrandon if (geomType == BEZIER) { *retType = (char *)"BEZIER"; } 555552b385SBrandon if (geomType == BSPLINE) { *retType = (char *)"BSPLINE"; } 565552b385SBrandon if (geomType == OFFSET) { *retType = (char *)"OFFSET"; } 575552b385SBrandon } 585552b385SBrandon 595552b385SBrandon /* SURFACE */ 605552b385SBrandon if (geomClass == SURFACE) { 615552b385SBrandon if (geomType == PLANE) { *retType = (char *)"PLANE"; } 625552b385SBrandon if (geomType == SPHERICAL) { *retType = (char *)"SPHERICAL"; } 635552b385SBrandon if (geomType == CYLINDRICAL) { *retType = (char *)"CYLINDRICAL"; } 645552b385SBrandon if (geomType == REVOLUTION) { *retType = (char *)"REVOLUTION"; } 655552b385SBrandon if (geomType == TOROIDAL) { *retType = (char *)"TOROIDAL"; } 665552b385SBrandon if (geomType == CONICAL) { *retType = (char *)"CONICAL"; } 675552b385SBrandon if (geomType == EXTRUSION) { *retType = (char *)"EXTRUSION"; } 685552b385SBrandon if (geomType == BEZIER) { *retType = (char *)"BEZIER"; } 695552b385SBrandon if (geomType == BSPLINE) { *retType = (char *)"BSPLINE"; } 705552b385SBrandon } 715552b385SBrandon 725552b385SBrandon /* TOPOLOGY */ 735552b385SBrandon if (geomClass == NODE || geomClass == EDGE || geomClass == LOOP || geomClass == FACE || geomClass == SHELL || geomClass == BODY || geomClass == MODEL) { 745552b385SBrandon if (geomType == SREVERSE) { *retType = (char *)"SREVERSE"; } 755552b385SBrandon if (geomType == NOMTYPE) { *retType = (char *)"NOMTYPE"; } 765552b385SBrandon if (geomType == SFORWARD && geomClass == FACE) { *retType = (char *)"SFORWARD"; } 775552b385SBrandon if (geomType == ONENODE && geomClass == EDGE) { *retType = (char *)"ONENODE"; } 785552b385SBrandon if (geomType == TWONODE) { *retType = (char *)"TWONODE"; } 795552b385SBrandon if (geomType == OPEN) { *retType = (char *)"OPEN"; } 805552b385SBrandon if (geomType == CLOSED) { *retType = (char *)"CLOSED"; } 815552b385SBrandon if (geomType == DEGENERATE) { *retType = (char *)"DEGENERATE"; } 825552b385SBrandon if (geomType == WIREBODY) { *retType = (char *)"WIREBODY"; } 835552b385SBrandon if (geomType == FACEBODY) { *retType = (char *)"FACEBODY"; } 845552b385SBrandon if (geomType == SHEETBODY) { *retType = (char *)"SHEETBODY"; } 855552b385SBrandon if (geomType == SOLIDBODY) { *retType = (char *)"SOLIDBODY"; } 865552b385SBrandon } 875552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 885552b385SBrandon } 895552b385SBrandon 905552b385SBrandon PetscErrorCode DMPlex_EGADS_EDGE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[]) 915552b385SBrandon { 925552b385SBrandon // 935552b385SBrandon // 945552b385SBrandon // Depreciated. Changed all references to DMPlex_Geom_FACE_XYZtoUV_Internal() 955552b385SBrandon // 965552b385SBrandon // 975552b385SBrandon 985552b385SBrandon PetscInt loopCntr = 0; 995552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, obj_old, obj_tmp, target; 1005552b385SBrandon PetscScalar delta, A, b; 1015552b385SBrandon PetscScalar ts[2], tt[2], eval[18], data[18]; 1025552b385SBrandon 1035552b385SBrandon PetscFunctionBeginHot; 1045552b385SBrandon /* Initialize Levenberg-Marquardt parameters */ 1055552b385SBrandon lambda = 1.0; 1065552b385SBrandon tolr = 1.0; 1075552b385SBrandon target = 1.0E-20; 1085552b385SBrandon ts[0] = (range[0] + range[1]) / 2.; 1095552b385SBrandon 1105552b385SBrandon while (tolr >= target) { 1115552b385SBrandon PetscCall(EG_evaluate(obj, ts, eval)); 1125552b385SBrandon dx = coords[v * dE + 0] - eval[0]; 1135552b385SBrandon dy = coords[v * dE + 1] - eval[1]; 1145552b385SBrandon dz = coords[v * dE + 2] - eval[2]; 1155552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz; 1165552b385SBrandon 1175552b385SBrandon if (obj_old < target) { 1185552b385SBrandon tolr = obj_old; 1195552b385SBrandon break; 1205552b385SBrandon } 1215552b385SBrandon 1225552b385SBrandon A = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 1235552b385SBrandon if (A == 0.0) { 1245552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "A = 0.0 \n")); 1255552b385SBrandon break; 1265552b385SBrandon } 1275552b385SBrandon b = eval[3] * dx + eval[4] * dy + eval[5] * dz; 1285552b385SBrandon 1295552b385SBrandon /* Solve A*delta = b */ 1305552b385SBrandon delta = b / A; 1315552b385SBrandon 1325552b385SBrandon /* Find a temp (u,v) and associated objective function */ 1335552b385SBrandon tt[0] = ts[0] + delta; 1345552b385SBrandon if (tt[0] < range[0]) { 1355552b385SBrandon tt[0] = range[0]; 1365552b385SBrandon delta = tt[0] - ts[0]; 1375552b385SBrandon } 1385552b385SBrandon if (tt[0] > range[1]) { 1395552b385SBrandon tt[0] = range[1]; 1405552b385SBrandon delta = tt[0] - ts[0]; 1415552b385SBrandon } 1425552b385SBrandon 1435552b385SBrandon PetscCall(EG_evaluate(obj, tt, data)); 1445552b385SBrandon 1455552b385SBrandon obj_tmp = (coords[v * dE + 0] - data[0]) * (coords[v * dE + 0] - data[0]) + (coords[v * dE + 1] - data[1]) * (coords[v * dE + 1] - data[1]) + (coords[v * dE + 2] - data[2]) * (coords[v * dE + 2] - data[2]); 1465552b385SBrandon 1475552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */ 1485552b385SBrandon if (obj_tmp < obj_old) { 1495552b385SBrandon obj_old = obj_tmp; 1505552b385SBrandon ts[0] = tt[0]; 1515552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 1525552b385SBrandon lambda /= 2.0; 1535552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14; 1545552b385SBrandon if (obj_old < target) { 1555552b385SBrandon tolr = obj_old; 1565552b385SBrandon break; 1575552b385SBrandon } 1585552b385SBrandon } else { 1595552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 1605552b385SBrandon lambda *= 2.0; 1615552b385SBrandon } 1625552b385SBrandon 1635552b385SBrandon if ((tt[0] == range[0]) || (tt[0] == range[1])) break; 1645552b385SBrandon if (fabs(delta) < target) { 1655552b385SBrandon tolr = obj_old; 1665552b385SBrandon break; 1675552b385SBrandon } 1685552b385SBrandon 1695552b385SBrandon tolr = obj_old; 1705552b385SBrandon 1715552b385SBrandon loopCntr += 1; 1725552b385SBrandon if (loopCntr > 100) break; 1735552b385SBrandon } 1745552b385SBrandon paramsV[v * 3 + 0] = ts[0]; 1755552b385SBrandon paramsV[v * 3 + 1] = 0.; 1765552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 1775552b385SBrandon } 1785552b385SBrandon 1795552b385SBrandon PetscErrorCode DMPlex_Geom_EDGE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[], PetscBool islite) 1805552b385SBrandon { 1815552b385SBrandon PetscInt loopCntr = 0; 1825552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, obj_old, obj_tmp, target; 1835552b385SBrandon PetscScalar delta, A, b; 1845552b385SBrandon PetscScalar ts[2], tt[2], eval[18], data[18]; 1855552b385SBrandon 1865552b385SBrandon PetscFunctionBeginHot; 1875552b385SBrandon /* Initialize Levenberg-Marquardt parameters */ 1885552b385SBrandon lambda = 1.0; 1895552b385SBrandon tolr = 1.0; 1905552b385SBrandon target = 1.0E-20; 1915552b385SBrandon ts[0] = (range[0] + range[1]) / 2.; 1925552b385SBrandon 1935552b385SBrandon while (tolr >= target) { 1945552b385SBrandon if (islite) { 1955552b385SBrandon PetscCall(EGlite_evaluate(obj, ts, eval)); 1965552b385SBrandon } else { 1975552b385SBrandon PetscCall(EG_evaluate(obj, ts, eval)); 1985552b385SBrandon } 1995552b385SBrandon 2005552b385SBrandon dx = coords[v * dE + 0] - eval[0]; 2015552b385SBrandon dy = coords[v * dE + 1] - eval[1]; 2025552b385SBrandon dz = coords[v * dE + 2] - eval[2]; 2035552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz; 2045552b385SBrandon 2055552b385SBrandon if (obj_old < target) { 2065552b385SBrandon tolr = obj_old; 2075552b385SBrandon break; 2085552b385SBrandon } 2095552b385SBrandon 2105552b385SBrandon A = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 2115552b385SBrandon if (A == 0.0) { 2125552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "A = 0.0 \n")); 2135552b385SBrandon break; 2145552b385SBrandon } 2155552b385SBrandon b = eval[3] * dx + eval[4] * dy + eval[5] * dz; 2165552b385SBrandon 2175552b385SBrandon /* Solve A*delta = b */ 2185552b385SBrandon delta = b / A; 2195552b385SBrandon 2205552b385SBrandon /* Find a temp (u,v) and associated objective function */ 2215552b385SBrandon tt[0] = ts[0] + delta; 2225552b385SBrandon if (tt[0] < range[0]) { 2235552b385SBrandon tt[0] = range[0]; 2245552b385SBrandon delta = tt[0] - ts[0]; 2255552b385SBrandon } 2265552b385SBrandon if (tt[0] > range[1]) { 2275552b385SBrandon tt[0] = range[1]; 2285552b385SBrandon delta = tt[0] - ts[0]; 2295552b385SBrandon } 2305552b385SBrandon 2315552b385SBrandon if (islite) { 2325552b385SBrandon PetscCall(EGlite_evaluate(obj, tt, data)); 2335552b385SBrandon } else { 2345552b385SBrandon PetscCall(EG_evaluate(obj, tt, data)); 2355552b385SBrandon } 2365552b385SBrandon 2375552b385SBrandon obj_tmp = (coords[v * dE + 0] - data[0]) * (coords[v * dE + 0] - data[0]) + (coords[v * dE + 1] - data[1]) * (coords[v * dE + 1] - data[1]) + (coords[v * dE + 2] - data[2]) * (coords[v * dE + 2] - data[2]); 2385552b385SBrandon 2395552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */ 2405552b385SBrandon if (obj_tmp < obj_old) { 2415552b385SBrandon obj_old = obj_tmp; 2425552b385SBrandon ts[0] = tt[0]; 2435552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 2445552b385SBrandon lambda /= 2.0; 2455552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14; 2465552b385SBrandon if (obj_old < target) { 2475552b385SBrandon tolr = obj_old; 2485552b385SBrandon break; 2495552b385SBrandon } 2505552b385SBrandon } else { 2515552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 2525552b385SBrandon lambda *= 2.0; 2535552b385SBrandon } 2545552b385SBrandon 2555552b385SBrandon if ((tt[0] == range[0]) || (tt[0] == range[1])) break; 2565552b385SBrandon if (fabs(delta) < target) { 2575552b385SBrandon tolr = obj_old; 2585552b385SBrandon break; 2595552b385SBrandon } 2605552b385SBrandon 2615552b385SBrandon tolr = obj_old; 2625552b385SBrandon 2635552b385SBrandon loopCntr += 1; 2645552b385SBrandon if (loopCntr > 100) break; 2655552b385SBrandon } 2665552b385SBrandon paramsV[v * 3 + 0] = ts[0]; 2675552b385SBrandon paramsV[v * 3 + 1] = 0.; 2685552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 2695552b385SBrandon } 2705552b385SBrandon 2715552b385SBrandon PetscErrorCode DMPlex_EGADS_FACE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[]) 2725552b385SBrandon { 2735552b385SBrandon // 2745552b385SBrandon // 2755552b385SBrandon // Depreciated. Changed all references to DMPlex_Geom_FACE_XYZtoUV_Internal() 2765552b385SBrandon // 2775552b385SBrandon // 2785552b385SBrandon 2795552b385SBrandon PetscInt loopCntr = 0; 2805552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, denom, obj_old, obj_tmp, target; 2815552b385SBrandon PetscScalar uvs[2], uvt[2], delta[2], A[4], b[2], eval[18], data[18]; 2825552b385SBrandon 2835552b385SBrandon PetscFunctionBeginHot; 2845552b385SBrandon /* Initialize Levenberg-Marquardt parameters */ 2855552b385SBrandon lambda = 1.0; 2865552b385SBrandon tolr = 1.0; 2875552b385SBrandon target = 1.0E-20; 2885552b385SBrandon uvs[0] = (range[0] + range[1]) / 2.; 2895552b385SBrandon uvs[1] = (range[2] + range[3]) / 2.; 2905552b385SBrandon 2915552b385SBrandon while (tolr >= target) { 2925552b385SBrandon PetscCall(EG_evaluate(obj, uvs, eval)); 2935552b385SBrandon dx = coords[v * dE + 0] - eval[0]; 2945552b385SBrandon dy = coords[v * dE + 1] - eval[1]; 2955552b385SBrandon dz = coords[v * dE + 2] - eval[2]; 2965552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz; 2975552b385SBrandon 2985552b385SBrandon if (obj_old < target) { 2995552b385SBrandon tolr = obj_old; 3005552b385SBrandon break; 3015552b385SBrandon } 3025552b385SBrandon 3035552b385SBrandon A[0] = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 3045552b385SBrandon A[1] = eval[3] * eval[6] + eval[4] * eval[7] + eval[5] * eval[8]; 3055552b385SBrandon A[2] = A[1]; 3065552b385SBrandon A[3] = (eval[6] * eval[6] + eval[7] * eval[7] + eval[8] * eval[8]) * (1.0 + lambda); 3075552b385SBrandon 3085552b385SBrandon b[0] = eval[3] * dx + eval[4] * dy + eval[5] * dz; 3095552b385SBrandon b[1] = eval[6] * dx + eval[7] * dy + eval[8] * dz; 3105552b385SBrandon 3115552b385SBrandon /* Solve A*delta = b using Cramer's Rule */ 3125552b385SBrandon denom = A[0] * A[3] - A[2] * A[1]; 3135552b385SBrandon if (denom == 0.0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, "denom = 0.0 \n")); } 3145552b385SBrandon delta[0] = (b[0] * A[3] - b[1] * A[1]) / denom; 3155552b385SBrandon delta[1] = (A[0] * b[1] - A[2] * b[0]) / denom; 3165552b385SBrandon 3175552b385SBrandon /* Find a temp (u,v) and associated objective function */ 3185552b385SBrandon uvt[0] = uvs[0] + delta[0]; 3195552b385SBrandon uvt[1] = uvs[1] + delta[1]; 3205552b385SBrandon 3215552b385SBrandon if (uvt[0] < range[0]) { 3225552b385SBrandon uvt[0] = range[0]; 3235552b385SBrandon delta[0] = uvt[0] - uvs[0]; 3245552b385SBrandon } 3255552b385SBrandon if (uvt[0] > range[1]) { 3265552b385SBrandon uvt[0] = range[1]; 3275552b385SBrandon delta[0] = uvt[0] - uvs[0]; 3285552b385SBrandon } 3295552b385SBrandon if (uvt[1] < range[2]) { 3305552b385SBrandon uvt[1] = range[2]; 3315552b385SBrandon delta[1] = uvt[1] - uvs[1]; 3325552b385SBrandon } 3335552b385SBrandon if (uvt[1] > range[3]) { 3345552b385SBrandon uvt[1] = range[3]; 3355552b385SBrandon delta[1] = uvt[1] - uvs[1]; 3365552b385SBrandon } 3375552b385SBrandon 3385552b385SBrandon PetscCall(EG_evaluate(obj, uvt, data)); 3395552b385SBrandon 3405552b385SBrandon obj_tmp = (coords[v * dE + 0] - data[0]) * (coords[v * dE + 0] - data[0]) + (coords[v * dE + 1] - data[1]) * (coords[v * dE + 1] - data[1]) + (coords[v * dE + 2] - data[2]) * (coords[v * dE + 2] - data[2]); 3415552b385SBrandon 3425552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */ 3435552b385SBrandon if (obj_tmp < obj_old) { 3445552b385SBrandon obj_old = obj_tmp; 3455552b385SBrandon uvs[0] = uvt[0]; 3465552b385SBrandon uvs[1] = uvt[1]; 3475552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 3485552b385SBrandon lambda /= 2.0; 3495552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14; 3505552b385SBrandon if (obj_old < target) { 3515552b385SBrandon tolr = obj_old; 3525552b385SBrandon break; 3535552b385SBrandon } 3545552b385SBrandon } else { 3555552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 3565552b385SBrandon lambda *= 2.0; 3575552b385SBrandon } 3585552b385SBrandon 3595552b385SBrandon if (sqrt(delta[0] * delta[0] + delta[1] * delta[1]) < target) { 3605552b385SBrandon tolr = obj_old; 3615552b385SBrandon break; 3625552b385SBrandon } 3635552b385SBrandon 3645552b385SBrandon tolr = obj_old; 3655552b385SBrandon 3665552b385SBrandon loopCntr += 1; 3675552b385SBrandon if (loopCntr > 100) break; 3685552b385SBrandon } 3695552b385SBrandon paramsV[v * 3 + 0] = uvs[0]; 3705552b385SBrandon paramsV[v * 3 + 1] = uvs[1]; 3715552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 3725552b385SBrandon } 3735552b385SBrandon 3745552b385SBrandon PetscErrorCode DMPlex_Geom_FACE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[], PetscBool islite) 3755552b385SBrandon { 3765552b385SBrandon PetscInt loopCntr = 0; 3775552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, denom, obj_old, obj_tmp, target; 3785552b385SBrandon PetscScalar uvs[2], uvt[2], delta[2], A[4], b[2], eval[18], data[18]; 3795552b385SBrandon 3805552b385SBrandon PetscFunctionBeginHot; 3815552b385SBrandon /* Initialize Levenberg-Marquardt parameters */ 3825552b385SBrandon lambda = 1.0; 3835552b385SBrandon tolr = 1.0; 3845552b385SBrandon target = 1.0E-20; 3855552b385SBrandon uvs[0] = (range[0] + range[1]) / 2.; 3865552b385SBrandon uvs[1] = (range[2] + range[3]) / 2.; 3875552b385SBrandon 3885552b385SBrandon while (tolr >= target) { 3895552b385SBrandon if (islite) { 3905552b385SBrandon PetscCallEGADS(EGlite_evaluate, (obj, uvs, eval)); 3915552b385SBrandon } else { 3925552b385SBrandon PetscCallEGADS(EG_evaluate, (obj, uvs, eval)); 3935552b385SBrandon } 3945552b385SBrandon 3955552b385SBrandon dx = coords[v * dE + 0] - eval[0]; 3965552b385SBrandon dy = coords[v * dE + 1] - eval[1]; 3975552b385SBrandon dz = coords[v * dE + 2] - eval[2]; 3985552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz; 3995552b385SBrandon 4005552b385SBrandon if (obj_old < target) { 4015552b385SBrandon tolr = obj_old; 4025552b385SBrandon break; 4035552b385SBrandon } 4045552b385SBrandon 4055552b385SBrandon A[0] = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 4065552b385SBrandon A[1] = eval[3] * eval[6] + eval[4] * eval[7] + eval[5] * eval[8]; 4075552b385SBrandon A[2] = A[1]; 4085552b385SBrandon A[3] = (eval[6] * eval[6] + eval[7] * eval[7] + eval[8] * eval[8]) * (1.0 + lambda); 4095552b385SBrandon 4105552b385SBrandon b[0] = eval[3] * dx + eval[4] * dy + eval[5] * dz; 4115552b385SBrandon b[1] = eval[6] * dx + eval[7] * dy + eval[8] * dz; 4125552b385SBrandon 4135552b385SBrandon /* Solve A*delta = b using Cramer's Rule */ 4145552b385SBrandon denom = A[0] * A[3] - A[2] * A[1]; 4155552b385SBrandon if (denom == 0.0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, "denom = 0.0 \n")); } 4165552b385SBrandon delta[0] = (b[0] * A[3] - b[1] * A[1]) / denom; 4175552b385SBrandon delta[1] = (A[0] * b[1] - A[2] * b[0]) / denom; 4185552b385SBrandon 4195552b385SBrandon /* Find a temp (u,v) and associated objective function */ 4205552b385SBrandon uvt[0] = uvs[0] + delta[0]; 4215552b385SBrandon uvt[1] = uvs[1] + delta[1]; 4225552b385SBrandon 4235552b385SBrandon if (uvt[0] < range[0]) { 4245552b385SBrandon uvt[0] = range[0]; 4255552b385SBrandon delta[0] = uvt[0] - uvs[0]; 4265552b385SBrandon } 4275552b385SBrandon if (uvt[0] > range[1]) { 4285552b385SBrandon uvt[0] = range[1]; 4295552b385SBrandon delta[0] = uvt[0] - uvs[0]; 4305552b385SBrandon } 4315552b385SBrandon if (uvt[1] < range[2]) { 4325552b385SBrandon uvt[1] = range[2]; 4335552b385SBrandon delta[1] = uvt[1] - uvs[1]; 4345552b385SBrandon } 4355552b385SBrandon if (uvt[1] > range[3]) { 4365552b385SBrandon uvt[1] = range[3]; 4375552b385SBrandon delta[1] = uvt[1] - uvs[1]; 4385552b385SBrandon } 4395552b385SBrandon 4405552b385SBrandon if (islite) { 4415552b385SBrandon PetscCall(EGlite_evaluate(obj, uvt, data)); 4425552b385SBrandon } else { 4435552b385SBrandon PetscCall(EG_evaluate(obj, uvt, data)); 4445552b385SBrandon } 4455552b385SBrandon 4465552b385SBrandon obj_tmp = (coords[v * dE + 0] - data[0]) * (coords[v * dE + 0] - data[0]) + (coords[v * dE + 1] - data[1]) * (coords[v * dE + 1] - data[1]) + (coords[v * dE + 2] - data[2]) * (coords[v * dE + 2] - data[2]); 4475552b385SBrandon 4485552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */ 4495552b385SBrandon if (obj_tmp < obj_old) { 4505552b385SBrandon obj_old = obj_tmp; 4515552b385SBrandon uvs[0] = uvt[0]; 4525552b385SBrandon uvs[1] = uvt[1]; 4535552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 4545552b385SBrandon lambda /= 2.0; 4555552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14; 4565552b385SBrandon if (obj_old < target) { 4575552b385SBrandon tolr = obj_old; 4585552b385SBrandon break; 4595552b385SBrandon } 4605552b385SBrandon } else { 4615552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 4625552b385SBrandon lambda *= 2.0; 4635552b385SBrandon } 4645552b385SBrandon 4655552b385SBrandon if (sqrt(delta[0] * delta[0] + delta[1] * delta[1]) < target) { 4665552b385SBrandon tolr = obj_old; 4675552b385SBrandon break; 4685552b385SBrandon } 4695552b385SBrandon 4705552b385SBrandon tolr = obj_old; 4715552b385SBrandon 4725552b385SBrandon loopCntr += 1; 4735552b385SBrandon if (loopCntr > 100) break; 4745552b385SBrandon } 4755552b385SBrandon paramsV[v * 3 + 0] = uvs[0]; 4765552b385SBrandon paramsV[v * 3 + 1] = uvs[1]; 4775552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 4785552b385SBrandon } 4795552b385SBrandon 4805552b385SBrandon PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM dm, PetscInt p, ego model, PetscInt bodyID, PetscInt faceID, PetscInt edgeID, const PetscScalar mcoords[], PetscScalar gcoords[], PetscBool islite) 4815552b385SBrandon { 4825552b385SBrandon /* PETSc Variables */ 483c1cad2e7SMatthew G. Knepley DM cdm; 484c1cad2e7SMatthew G. Knepley ego *bodies; 485c1cad2e7SMatthew G. Knepley ego geom, body, obj; 486*bfe80ac4SPierre Jolivet /* result has to hold derivatives, along with the value */ 4875552b385SBrandon double params[3], result[18], paramsV[16 * 3], range[4]; 488c1cad2e7SMatthew G. Knepley int Nb, oclass, mtype, *senses, peri; 489c1cad2e7SMatthew G. Knepley Vec coordinatesLocal; 490c1cad2e7SMatthew G. Knepley PetscScalar *coords = NULL; 491c1cad2e7SMatthew G. Knepley PetscInt Nv, v, Np = 0, pm; 492c1cad2e7SMatthew G. Knepley PetscInt dE, d; 4935552b385SBrandon PetscReal pTolr = 1.0e-14; 494c1cad2e7SMatthew G. Knepley 495c1cad2e7SMatthew G. Knepley PetscFunctionBeginHot; 4969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 4979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 4989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 4995552b385SBrandon 5005552b385SBrandon if (islite) { 5015552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 5025552b385SBrandon } else { 5039566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 5045552b385SBrandon } 5055552b385SBrandon 5065552b385SBrandon PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bodyID, Nb); 507c1cad2e7SMatthew G. Knepley body = bodies[bodyID]; 508c1cad2e7SMatthew G. Knepley 5099371c9d4SSatish Balay if (edgeID >= 0) { 5105552b385SBrandon if (islite) { 5115552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &obj)); 5125552b385SBrandon Np = 1; 5135552b385SBrandon } else { 5149371c9d4SSatish Balay PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &obj)); 5159371c9d4SSatish Balay Np = 1; 5165552b385SBrandon } 5179371c9d4SSatish Balay } else if (faceID >= 0) { 5185552b385SBrandon if (islite) { 5195552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &obj)); 5205552b385SBrandon Np = 2; 5215552b385SBrandon } else { 5229371c9d4SSatish Balay PetscCall(EG_objectBodyTopo(body, FACE, faceID, &obj)); 5239371c9d4SSatish Balay Np = 2; 5245552b385SBrandon } 5259371c9d4SSatish Balay } else { 526c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 5273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 528c1cad2e7SMatthew G. Knepley } 529c1cad2e7SMatthew G. Knepley 530c1cad2e7SMatthew G. Knepley /* Calculate parameters (t or u,v) for vertices */ 5319566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 532c1cad2e7SMatthew G. Knepley Nv /= dE; 533c1cad2e7SMatthew G. Knepley if (Nv == 1) { 5349566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 535c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 5363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 537c1cad2e7SMatthew G. Knepley } 53863a3b9bcSJacob Faibussowitsch PetscCheck(Nv <= 16, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " coordinates associated to point %" PetscInt_FMT, Nv, p); 539c1cad2e7SMatthew G. Knepley 5405552b385SBrandon /* Correct EGADS/EGADSlite 2pi bug when calculating nearest point on Periodic Surfaces */ 5415552b385SBrandon if (islite) { 5425552b385SBrandon PetscCall(EGlite_getRange(obj, range, &peri)); 5435552b385SBrandon } else { 5449566063dSJacob Faibussowitsch PetscCall(EG_getRange(obj, range, &peri)); 5455552b385SBrandon } 5465552b385SBrandon 547c1cad2e7SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 5485552b385SBrandon if (edgeID > 0) { 5495552b385SBrandon PetscCall(DMPlex_Geom_EDGE_XYZtoUV_Internal(coords, obj, range, v, dE, paramsV, islite)); 5505552b385SBrandon } else { 5515552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, obj, range, v, dE, paramsV, islite)); 5529371c9d4SSatish Balay } 553c1cad2e7SMatthew G. Knepley } 5549566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 5555552b385SBrandon 556c1cad2e7SMatthew G. Knepley /* Calculate parameters (t or u,v) for new vertex at edge midpoint */ 557c1cad2e7SMatthew G. Knepley for (pm = 0; pm < Np; ++pm) { 558c1cad2e7SMatthew G. Knepley params[pm] = 0.; 559c1cad2e7SMatthew G. Knepley for (v = 0; v < Nv; ++v) params[pm] += paramsV[v * 3 + pm]; 560c1cad2e7SMatthew G. Knepley params[pm] /= Nv; 561c1cad2e7SMatthew G. Knepley } 5625552b385SBrandon PetscCheck((params[0] + pTolr >= range[0]) || (params[0] - pTolr <= range[1]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " had bad interpolation", p); 5635552b385SBrandon PetscCheck(Np < 2 || ((params[1] + pTolr >= range[2]) || (params[1] - pTolr <= range[3])), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d had bad interpolation on v", p); 5645552b385SBrandon 565c1cad2e7SMatthew G. Knepley /* Put coordinates for new vertex in result[] */ 5665552b385SBrandon if (islite) { 5675552b385SBrandon PetscCall(EGlite_evaluate(obj, params, result)); 5685552b385SBrandon } else { 5699566063dSJacob Faibussowitsch PetscCall(EG_evaluate(obj, params, result)); 5705552b385SBrandon } 5715552b385SBrandon 572c1cad2e7SMatthew G. Knepley for (d = 0; d < dE; ++d) gcoords[d] = result[d]; 5733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 574c1cad2e7SMatthew G. Knepley } 575c1cad2e7SMatthew G. Knepley #endif 576c1cad2e7SMatthew G. Knepley 5777625649eSMatthew G. Knepley PetscErrorCode DMSnapToGeomModel_EGADS(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[]) 5787625649eSMatthew G. Knepley { 5797625649eSMatthew G. Knepley PetscFunctionBeginHot; 5807625649eSMatthew G. Knepley #ifdef PETSC_HAVE_EGADS 5817625649eSMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel; 5827625649eSMatthew G. Knepley PetscInt bodyID, faceID, edgeID; 5837625649eSMatthew G. Knepley PetscContainer modelObj; 5847625649eSMatthew G. Knepley ego model; 5855552b385SBrandon PetscBool islite = PETSC_FALSE; 5867625649eSMatthew G. Knepley 5875552b385SBrandon // FIXME: Change -dm_plex_refine_without_snap_to_geom to DM to shut off snapping 5887625649eSMatthew G. Knepley PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 5897625649eSMatthew G. Knepley PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 5907625649eSMatthew G. Knepley PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 5917625649eSMatthew G. Knepley PetscCheck(bodyLabel && faceLabel && edgeLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADS meshes must have body, face, and edge labels defined"); 5927625649eSMatthew G. Knepley PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5935552b385SBrandon if (!modelObj) { 5945552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5955552b385SBrandon islite = PETSC_TRUE; 5965552b385SBrandon } 5977625649eSMatthew G. Knepley PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADS mesh missing model object"); 5987625649eSMatthew G. Knepley 5997625649eSMatthew G. Knepley PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 6007625649eSMatthew G. Knepley PetscCall(DMLabelGetValue(bodyLabel, p, &bodyID)); 6017625649eSMatthew G. Knepley PetscCall(DMLabelGetValue(faceLabel, p, &faceID)); 6027625649eSMatthew G. Knepley PetscCall(DMLabelGetValue(edgeLabel, p, &edgeID)); 6037625649eSMatthew G. Knepley /* Allows for "Connective" Plex Edges present in models with multiple non-touching Entities */ 6047625649eSMatthew G. Knepley if (bodyID < 0) { 6057625649eSMatthew G. Knepley for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 6067625649eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6077625649eSMatthew G. Knepley } 6085552b385SBrandon PetscCall(DMSnapToGeomModel_EGADS_Internal(dm, p, model, bodyID, faceID, edgeID, mcoords, gcoords, islite)); 609a8ededdfSMatthew G. Knepley #endif 6103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 611a8ededdfSMatthew G. Knepley } 6127bee2925SMatthew Knepley 6137bee2925SMatthew Knepley #if defined(PETSC_HAVE_EGADS) 6145552b385SBrandon PetscErrorCode DMPlexGeomPrintModel_Internal(ego model, PetscBool islite) 615d71ae5a4SJacob Faibussowitsch { 6165552b385SBrandon /* PETSc Variables */ 6175552b385SBrandon ego geom, *bodies, *nobjs, *mobjs, *lobjs, *shobjs, *fobjs, *eobjs; 6185552b385SBrandon int oclass, mtype, *senses, *shsenses, *fsenses, *lsenses, *esenses; 6197bee2925SMatthew Knepley int Nb, b; 6207bee2925SMatthew Knepley 6217bee2925SMatthew Knepley PetscFunctionBeginUser; 6227bee2925SMatthew Knepley /* test bodyTopo functions */ 6235552b385SBrandon if (islite) { 6245552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 6255552b385SBrandon } else { 6269566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 6275552b385SBrandon } 6285552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of BODIES (nbodies): %" PetscInt_FMT " \n", Nb)); 6297bee2925SMatthew Knepley 6307bee2925SMatthew Knepley for (b = 0; b < Nb; ++b) { 6317bee2925SMatthew Knepley ego body = bodies[b]; 6325552b385SBrandon int id, sh, Nsh, f, Nf, l, Nl, e, Ne, v, Nv; 6335552b385SBrandon 6345552b385SBrandon /* List Topology of Bodies */ 6355552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 6365552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " BODY %d TOPOLOGY SUMMARY \n", b)); 6377bee2925SMatthew Knepley 6387bee2925SMatthew Knepley /* Output Basic Model Topology */ 6395552b385SBrandon if (islite) { 6405552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, &Nsh, &shobjs)); 6415552b385SBrandon } else { 6425552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, SHELL, &Nsh, &shobjs)); 6435552b385SBrandon } 6449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of SHELLS: %d \n", Nsh)); 6457bee2925SMatthew Knepley 6465552b385SBrandon if (islite) { 6475552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 6485552b385SBrandon } else { 6495552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 6505552b385SBrandon } 6519566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of FACES: %d \n", Nf)); 6527bee2925SMatthew Knepley 6535552b385SBrandon if (islite) { 6545552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 6555552b385SBrandon } else { 6569566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 6575552b385SBrandon } 6589566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of LOOPS: %d \n", Nl)); 6597bee2925SMatthew Knepley 6605552b385SBrandon if (islite) { 6615552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 6625552b385SBrandon } else { 6635552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 6645552b385SBrandon } 6659566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of EDGES: %d \n", Ne)); 6667bee2925SMatthew Knepley 6675552b385SBrandon if (islite) { 6685552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 6695552b385SBrandon } else { 6705552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 6715552b385SBrandon } 6729566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of NODES: %d \n", Nv)); 6735552b385SBrandon 6745552b385SBrandon if (islite) { 6755552b385SBrandon EGlite_free(shobjs); 6765552b385SBrandon EGlite_free(fobjs); 6775552b385SBrandon EGlite_free(lobjs); 6785552b385SBrandon EGlite_free(eobjs); 6795552b385SBrandon EGlite_free(nobjs); 6805552b385SBrandon } else { 6815552b385SBrandon EG_free(shobjs); 6825552b385SBrandon EG_free(fobjs); 6835552b385SBrandon EG_free(lobjs); 6845552b385SBrandon EG_free(eobjs); 6855552b385SBrandon EG_free(nobjs); 6865552b385SBrandon } 6875552b385SBrandon 6885552b385SBrandon /* List Topology of Bodies */ 6895552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 6905552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " BODY %d TOPOLOGY DETAILS \n", b)); 6915552b385SBrandon 6925552b385SBrandon /* Get SHELL info which associated with the current BODY */ 6935552b385SBrandon if (islite) { 6945552b385SBrandon PetscCall(EGlite_getTopology(body, &geom, &oclass, &mtype, NULL, &Nsh, &shobjs, &shsenses)); 6955552b385SBrandon } else { 6965552b385SBrandon PetscCall(EG_getTopology(body, &geom, &oclass, &mtype, NULL, &Nsh, &shobjs, &shsenses)); 6975552b385SBrandon } 6985552b385SBrandon 6995552b385SBrandon for (sh = 0; sh < Nsh; ++sh) { 7005552b385SBrandon ego shell = shobjs[sh]; 7015552b385SBrandon int shsense = shsenses[sh]; 7025552b385SBrandon 7035552b385SBrandon if (islite) { 7045552b385SBrandon id = EGlite_indexBodyTopo(body, shell); 7055552b385SBrandon } else { 7065552b385SBrandon id = EG_indexBodyTopo(body, shell); 7075552b385SBrandon } 7085552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " SHELL ID: %d :: sense = %d\n", id, shsense)); 7095552b385SBrandon 710*bfe80ac4SPierre Jolivet /* Get FACE information associated with current SHELL */ 7115552b385SBrandon if (islite) { 7125552b385SBrandon PetscCall(EGlite_getTopology(shell, &geom, &oclass, &mtype, NULL, &Nf, &fobjs, &fsenses)); 7135552b385SBrandon } else { 7145552b385SBrandon PetscCall(EG_getTopology(shell, &geom, &oclass, &mtype, NULL, &Nf, &fobjs, &fsenses)); 7155552b385SBrandon } 7165552b385SBrandon 7175552b385SBrandon for (f = 0; f < Nf; ++f) { 7185552b385SBrandon ego face = fobjs[f]; 7195552b385SBrandon ego gRef, gPrev, gNext; 7205552b385SBrandon int goclass, gmtype, *gpinfo; 7215552b385SBrandon double *gprv; 7225552b385SBrandon char *gClass = (char *)"", *gType = (char *)""; 7235552b385SBrandon double fdata[4]; 7245552b385SBrandon ego fRef, fPrev, fNext; 7255552b385SBrandon int foclass, fmtype; 7265552b385SBrandon 7275552b385SBrandon if (islite) { 7285552b385SBrandon id = EGlite_indexBodyTopo(body, face); 7295552b385SBrandon } else { 7305552b385SBrandon id = EG_indexBodyTopo(body, face); 7315552b385SBrandon } 7325552b385SBrandon 7335552b385SBrandon /* Get LOOP info associated with current FACE */ 7345552b385SBrandon if (islite) { 7355552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, fdata, &Nl, &lobjs, &lsenses)); 7365552b385SBrandon PetscCall(EGlite_getInfo(face, &foclass, &fmtype, &fRef, &fPrev, &fNext)); 7375552b385SBrandon PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 7385552b385SBrandon PetscCall(EGlite_getInfo(geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 7395552b385SBrandon } else { 7405552b385SBrandon PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, fdata, &Nl, &lobjs, &lsenses)); 7415552b385SBrandon PetscCall(EG_getInfo(face, &foclass, &fmtype, &fRef, &fPrev, &fNext)); 7425552b385SBrandon PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 7435552b385SBrandon PetscCall(EG_getInfo(geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 7445552b385SBrandon } 7455552b385SBrandon 7465552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType)); 7475552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " FACE ID: %d :: sense = %d \n", id, fmtype)); 7485552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY CLASS: %s \n", gClass)); 7495552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY TYPE: %s \n\n", gType)); 7505552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " RANGE (umin, umax) = (%f, %f) \n", fdata[0], fdata[1])); 7515552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " (vmin, vmax) = (%f, %f) \n\n", fdata[2], fdata[3])); 7527bee2925SMatthew Knepley 7537bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 7547bee2925SMatthew Knepley ego loop = lobjs[l]; 7555552b385SBrandon int lsense = lsenses[l]; 7567bee2925SMatthew Knepley 7575552b385SBrandon if (islite) { 7585552b385SBrandon id = EGlite_indexBodyTopo(body, loop); 7595552b385SBrandon } else { 7607bee2925SMatthew Knepley id = EG_indexBodyTopo(body, loop); 7615552b385SBrandon } 7627bee2925SMatthew Knepley 7635552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP ID: %d :: sense = %d\n", id, lsense)); 7645552b385SBrandon 7655552b385SBrandon /* Get EDGE info associated with the current LOOP */ 7665552b385SBrandon if (islite) { 7675552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &esenses)); 7685552b385SBrandon } else { 7695552b385SBrandon PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &esenses)); 7705552b385SBrandon } 7717bee2925SMatthew Knepley 7727bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 7735552b385SBrandon ego edge = eobjs[e]; 7745552b385SBrandon ego topRef, prev, next; 7755552b385SBrandon int esense = esenses[e]; 7767bee2925SMatthew Knepley double range[4] = {0., 0., 0., 0.}; 7777bee2925SMatthew Knepley int peri; 7785552b385SBrandon ego gEref, gEprev, gEnext; 7795552b385SBrandon int gEoclass, gEmtype; 7805552b385SBrandon char *gEclass = (char *)"", *gEtype = (char *)""; 7817bee2925SMatthew Knepley 7825552b385SBrandon if (islite) { 7835552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 7845552b385SBrandon if (mtype != DEGENERATE) { PetscCall(EGlite_getInfo(geom, &gEoclass, &gEmtype, &gEref, &gEprev, &gEnext)); } 785266cfabeSMatthew G. Knepley } else { 7865552b385SBrandon PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 7875552b385SBrandon PetscCall(EG_getInfo(geom, &gEoclass, &gEmtype, &gEref, &gEprev, &gEnext)); 7885552b385SBrandon } 7895552b385SBrandon 7905552b385SBrandon if (mtype != DEGENERATE) { PetscCall(DMPlex_EGADS_GeomDecode_Internal(gEoclass, gEmtype, &gEclass, &gEtype)); } 7915552b385SBrandon 7925552b385SBrandon if (islite) { 7935552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 7945552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 7955552b385SBrandon } else { 7965552b385SBrandon id = EG_indexBodyTopo(body, edge); 7975552b385SBrandon PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 7985552b385SBrandon } 7995552b385SBrandon 8005552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE ID: %d :: sense = %d\n", id, esense)); 8015552b385SBrandon if (mtype != DEGENERATE) { 8025552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY CLASS: %s \n", gEclass)); 8035552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY TYPE: %s \n", gEtype)); 8045552b385SBrandon } 8055552b385SBrandon 8065552b385SBrandon if (mtype == DEGENERATE) { PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE %d is DEGENERATE \n", id)); } 8075552b385SBrandon 8085552b385SBrandon if (islite) { 8095552b385SBrandon PetscCall(EGlite_getRange(edge, range, &peri)); 8105552b385SBrandon } else { 8115552b385SBrandon PetscCall(EG_getRange(edge, range, &peri)); 8125552b385SBrandon } 8135552b385SBrandon 8145552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " Peri = %d :: Range = %lf, %lf, %lf, %lf \n", peri, range[0], range[1], range[2], range[3])); 8155552b385SBrandon 8165552b385SBrandon /* Get NODE info associated with the current EDGE */ 8175552b385SBrandon if (islite) { 8185552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 8195552b385SBrandon } else { 8205552b385SBrandon PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 821266cfabeSMatthew G. Knepley } 8227bee2925SMatthew Knepley 8237bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 8247bee2925SMatthew Knepley ego vertex = nobjs[v]; 8257bee2925SMatthew Knepley double limits[4]; 8267bee2925SMatthew Knepley int dummy; 8277bee2925SMatthew Knepley 8285552b385SBrandon if (islite) { 8295552b385SBrandon PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 8305552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 8315552b385SBrandon } else { 8329566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 8337bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 8345552b385SBrandon } 8359566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " NODE ID: %d \n", id)); 8369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " (x, y, z) = (%lf, %lf, %lf) \n", limits[0], limits[1], limits[2])); 8377bee2925SMatthew Knepley } 8387bee2925SMatthew Knepley } 8397bee2925SMatthew Knepley } 8407bee2925SMatthew Knepley } 8415552b385SBrandon } 8425552b385SBrandon } 8435552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n\n")); 8443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8457bee2925SMatthew Knepley } 8467bee2925SMatthew Knepley 84749abdd8aSBarry Smith static PetscErrorCode DMPlexEGADSDestroy_Private(void **context) 848d71ae5a4SJacob Faibussowitsch { 8495552b385SBrandon if (*context) EG_deleteObject((ego)*context); 8505552b385SBrandon return (PETSC_SUCCESS); 8515552b385SBrandon } 8525552b385SBrandon 8535552b385SBrandon static PetscErrorCode DMPlexEGADSClose_Private(void **context) 8545552b385SBrandon { 8555552b385SBrandon if (*context) EG_close((ego)*context); 8565552b385SBrandon return (PETSC_SUCCESS); 8575552b385SBrandon } 8585552b385SBrandon 8595552b385SBrandon PetscErrorCode DMPlexEGADSliteDestroy_Private(void **context) 8605552b385SBrandon { 8615552b385SBrandon if (*context) EGlite_deleteObject((ego)*context); 8627bee2925SMatthew Knepley return 0; 8637bee2925SMatthew Knepley } 8647bee2925SMatthew Knepley 8655552b385SBrandon PetscErrorCode DMPlexEGADSliteClose_Private(void **context) 866d71ae5a4SJacob Faibussowitsch { 8675552b385SBrandon if (*context) EGlite_close((ego)*context); 8685552b385SBrandon return 0; 8695552b385SBrandon } 8705552b385SBrandon 8715552b385SBrandon PetscErrorCode DMPlexCreateGeom_Internal(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 8725552b385SBrandon { 8735552b385SBrandon /* EGADS variables */ 8747bee2925SMatthew Knepley ego geom, *bodies, *objs, *nobjs, *mobjs, *lobjs; 8757bee2925SMatthew Knepley int oclass, mtype, nbodies, *senses; 8767bee2925SMatthew Knepley int b; 8777bee2925SMatthew Knepley /* PETSc variables */ 8787bee2925SMatthew Knepley DM dm; 8795552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 8807bee2925SMatthew Knepley PetscHMapI edgeMap = NULL; 8815552b385SBrandon PetscInt cStart, cEnd, c; 8827bee2925SMatthew 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; 8837bee2925SMatthew Knepley PetscInt *cells = NULL, *cone = NULL; 8847bee2925SMatthew Knepley PetscReal *coords = NULL; 8857bee2925SMatthew Knepley PetscMPIInt rank; 8867bee2925SMatthew Knepley 8877bee2925SMatthew Knepley PetscFunctionBegin; 8889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 889dd400576SPatrick Sanan if (rank == 0) { 890266cfabeSMatthew G. Knepley const PetscInt debug = 0; 891266cfabeSMatthew G. Knepley 8927bee2925SMatthew Knepley /* --------------------------------------------------------------------------------------------------- 8937bee2925SMatthew Knepley Generate Petsc Plex 8947bee2925SMatthew Knepley Get all Nodes in model, record coordinates in a correctly formatted array 8957bee2925SMatthew Knepley Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array 8967bee2925SMatthew Knepley We need to uniformly refine the initial geometry to guarantee a valid mesh 8977bee2925SMatthew Knepley */ 8987bee2925SMatthew Knepley 8997bee2925SMatthew Knepley /* Calculate cell and vertex sizes */ 9005552b385SBrandon if (islite) { 9015552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 9025552b385SBrandon } else { 9039566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 9045552b385SBrandon } 9055552b385SBrandon 9069566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&edgeMap)); 9077bee2925SMatthew Knepley numEdges = 0; 9087bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 9097bee2925SMatthew Knepley ego body = bodies[b]; 9107bee2925SMatthew Knepley int id, Nl, l, Nv, v; 9117bee2925SMatthew Knepley 9125552b385SBrandon if (islite) { 9135552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 9145552b385SBrandon } else { 9159566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 9165552b385SBrandon } 9175552b385SBrandon 9187bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 9197bee2925SMatthew Knepley ego loop = lobjs[l]; 9207bee2925SMatthew Knepley int Ner = 0, Ne, e, Nc; 9217bee2925SMatthew Knepley 9225552b385SBrandon if (islite) { 9235552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 9245552b385SBrandon } else { 9259566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 9265552b385SBrandon } 9275552b385SBrandon 9287bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 9297bee2925SMatthew Knepley ego edge = objs[e]; 9307bee2925SMatthew Knepley int Nv, id; 9317bee2925SMatthew Knepley PetscHashIter iter; 9327bee2925SMatthew Knepley PetscBool found; 9337bee2925SMatthew Knepley 9345552b385SBrandon if (islite) { 9355552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 9365552b385SBrandon } else { 9379566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 9385552b385SBrandon } 9395552b385SBrandon 9407bee2925SMatthew Knepley if (mtype == DEGENERATE) continue; 9415552b385SBrandon 9425552b385SBrandon if (islite) { 9435552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 9445552b385SBrandon } else { 9455f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, edge); 9465552b385SBrandon } 9475552b385SBrandon 9489566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, id - 1, &iter, &found)); 9495552b385SBrandon if (!found) { PetscCall(PetscHMapISet(edgeMap, id - 1, numEdges++)); } 9507bee2925SMatthew Knepley ++Ner; 9517bee2925SMatthew Knepley } 9529371c9d4SSatish Balay if (Ner == 2) { 9539371c9d4SSatish Balay Nc = 2; 9549371c9d4SSatish Balay } else if (Ner == 3) { 9559371c9d4SSatish Balay Nc = 4; 9569371c9d4SSatish Balay } else if (Ner == 4) { 9579371c9d4SSatish Balay Nc = 8; 9589371c9d4SSatish Balay ++numQuads; 9599371c9d4SSatish Balay } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot support loop with %d edges", Ner); 9607bee2925SMatthew Knepley numCells += Nc; 9617bee2925SMatthew Knepley newCells += Nc - 1; 9627bee2925SMatthew Knepley maxCorners = PetscMax(Ner * 2 + 1, maxCorners); 9637bee2925SMatthew Knepley } 9645552b385SBrandon if (islite) { 9655552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 9665552b385SBrandon } else { 9679566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 9685552b385SBrandon } 9695552b385SBrandon 9707bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 9717bee2925SMatthew Knepley ego vertex = nobjs[v]; 9727bee2925SMatthew Knepley 9735552b385SBrandon if (islite) { 9745552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 9755552b385SBrandon } else { 9767bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 9775552b385SBrandon } 9787bee2925SMatthew Knepley /* TODO: Instead of assuming contiguous ids, we could use a hash table */ 9797bee2925SMatthew Knepley numVertices = PetscMax(id, numVertices); 9807bee2925SMatthew Knepley } 9815552b385SBrandon if (islite) { 9825552b385SBrandon EGlite_free(lobjs); 9835552b385SBrandon EGlite_free(nobjs); 9845552b385SBrandon } else { 9857bee2925SMatthew Knepley EG_free(lobjs); 9867bee2925SMatthew Knepley EG_free(nobjs); 9877bee2925SMatthew Knepley } 9885552b385SBrandon } 9899566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(edgeMap, &numEdges)); 9907bee2925SMatthew Knepley newVertices = numEdges + numQuads; 9917bee2925SMatthew Knepley numVertices += newVertices; 9927bee2925SMatthew Knepley 9937bee2925SMatthew Knepley dim = 2; /* Assume 3D Models :: Need to update to handle 2D Models in the future */ 9947bee2925SMatthew Knepley cdim = 3; /* Assume 3D Models :: Need to update to handle 2D Models in the future */ 9957bee2925SMatthew Knepley numCorners = 3; /* Split cells into triangles */ 9969566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(numVertices * cdim, &coords, numCells * numCorners, &cells, maxCorners, &cone)); 9977bee2925SMatthew Knepley 9987bee2925SMatthew Knepley /* Get vertex coordinates */ 9997bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 10007bee2925SMatthew Knepley ego body = bodies[b]; 10017bee2925SMatthew Knepley int id, Nv, v; 10027bee2925SMatthew Knepley 10035552b385SBrandon if (islite) { 10045552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 10055552b385SBrandon } else { 10069566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 10075552b385SBrandon } 10085552b385SBrandon 10097bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 10107bee2925SMatthew Knepley ego vertex = nobjs[v]; 10117bee2925SMatthew Knepley double limits[4]; 10127bee2925SMatthew Knepley int dummy; 10137bee2925SMatthew Knepley 10145552b385SBrandon if (islite) { 10155552b385SBrandon PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 10165552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 10175552b385SBrandon } else { 10189566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 10195f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, vertex); 10205552b385SBrandon } 10215552b385SBrandon 10227bee2925SMatthew Knepley coords[(id - 1) * cdim + 0] = limits[0]; 10237bee2925SMatthew Knepley coords[(id - 1) * cdim + 1] = limits[1]; 10247bee2925SMatthew Knepley coords[(id - 1) * cdim + 2] = limits[2]; 10257bee2925SMatthew Knepley } 10265552b385SBrandon if (islite) { 10275552b385SBrandon EGlite_free(nobjs); 10285552b385SBrandon } else { 10297bee2925SMatthew Knepley EG_free(nobjs); 10307bee2925SMatthew Knepley } 10315552b385SBrandon } 10329566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(edgeMap)); 10337bee2925SMatthew Knepley fOff = numVertices - newVertices + numEdges; 10347bee2925SMatthew Knepley numEdges = 0; 10357bee2925SMatthew Knepley numQuads = 0; 10367bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 10377bee2925SMatthew Knepley ego body = bodies[b]; 10387bee2925SMatthew Knepley int Nl, l; 10397bee2925SMatthew Knepley 10405552b385SBrandon if (islite) { 10415552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 10425552b385SBrandon } else { 10439566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 10445552b385SBrandon } 10455552b385SBrandon 10467bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 10477bee2925SMatthew Knepley ego loop = lobjs[l]; 10487bee2925SMatthew Knepley int lid, Ner = 0, Ne, e; 10497bee2925SMatthew Knepley 10505552b385SBrandon if (islite) { 10515552b385SBrandon lid = EGlite_indexBodyTopo(body, loop); 10525552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 10535552b385SBrandon } else { 10545f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 10559566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 10565552b385SBrandon } 10575552b385SBrandon 10587bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 10597bee2925SMatthew Knepley ego edge = objs[e]; 10607bee2925SMatthew Knepley int eid, Nv; 10617bee2925SMatthew Knepley PetscHashIter iter; 10627bee2925SMatthew Knepley PetscBool found; 10637bee2925SMatthew Knepley 10645552b385SBrandon if (islite) { 10655552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 10665552b385SBrandon } else { 10679566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 10685552b385SBrandon } 10695552b385SBrandon 10707bee2925SMatthew Knepley if (mtype == DEGENERATE) continue; 10717bee2925SMatthew Knepley ++Ner; 10725552b385SBrandon 10735552b385SBrandon if (islite) { 10745552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 10755552b385SBrandon } else { 10765f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 10775552b385SBrandon } 10785552b385SBrandon 10799566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, eid - 1, &iter, &found)); 10807bee2925SMatthew Knepley if (!found) { 10817bee2925SMatthew Knepley PetscInt v = numVertices - newVertices + numEdges; 10827bee2925SMatthew Knepley double range[4], params[3] = {0., 0., 0.}, result[18]; 10837bee2925SMatthew Knepley int periodic[2]; 10847bee2925SMatthew Knepley 10859566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(edgeMap, eid - 1, numEdges++)); 10865552b385SBrandon 10875552b385SBrandon if (islite) { 10885552b385SBrandon PetscCall(EGlite_getRange(edge, range, periodic)); 10895552b385SBrandon } else { 10909566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, periodic)); 10915552b385SBrandon } 10925552b385SBrandon 10937bee2925SMatthew Knepley params[0] = 0.5 * (range[0] + range[1]); 10945552b385SBrandon if (islite) { 10955552b385SBrandon PetscCall(EGlite_evaluate(edge, params, result)); 10965552b385SBrandon } else { 10979566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, params, result)); 10985552b385SBrandon } 10997bee2925SMatthew Knepley coords[v * cdim + 0] = result[0]; 11007bee2925SMatthew Knepley coords[v * cdim + 1] = result[1]; 11017bee2925SMatthew Knepley coords[v * cdim + 2] = result[2]; 11027bee2925SMatthew Knepley } 11037bee2925SMatthew Knepley } 11047bee2925SMatthew Knepley if (Ner == 4) { 11057bee2925SMatthew Knepley PetscInt v = fOff + numQuads++; 1106266cfabeSMatthew G. Knepley ego *fobjs, face; 11077bee2925SMatthew Knepley double range[4], params[3] = {0., 0., 0.}, result[18]; 1108266cfabeSMatthew G. Knepley int Nf, fid, periodic[2]; 11097bee2925SMatthew Knepley 11105552b385SBrandon if (islite) { 11115552b385SBrandon PetscCall(EGlite_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 11125552b385SBrandon } else { 11139566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 11145552b385SBrandon } 1115266cfabeSMatthew G. Knepley face = fobjs[0]; 11165552b385SBrandon 11175552b385SBrandon if (islite) { 11185552b385SBrandon fid = EGlite_indexBodyTopo(body, face); 11195552b385SBrandon } else { 11205f80ce2aSJacob Faibussowitsch fid = EG_indexBodyTopo(body, face); 11215552b385SBrandon } 11225552b385SBrandon 11235552b385SBrandon PetscCheck(Nf != 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Loop %d has %" PetscInt_FMT " faces, instead of 1 (%" PetscInt_FMT ")", lid - 1, Nf, fid); 11245552b385SBrandon if (islite) { 11255552b385SBrandon PetscCall(EGlite_getRange(face, range, periodic)); 11265552b385SBrandon } else { 11279566063dSJacob Faibussowitsch PetscCall(EG_getRange(face, range, periodic)); 11285552b385SBrandon } 11297bee2925SMatthew Knepley params[0] = 0.5 * (range[0] + range[1]); 11307bee2925SMatthew Knepley params[1] = 0.5 * (range[2] + range[3]); 11315552b385SBrandon if (islite) { 11325552b385SBrandon PetscCall(EGlite_evaluate(face, params, result)); 11335552b385SBrandon } else { 11349566063dSJacob Faibussowitsch PetscCall(EG_evaluate(face, params, result)); 11355552b385SBrandon } 11367bee2925SMatthew Knepley coords[v * cdim + 0] = result[0]; 11377bee2925SMatthew Knepley coords[v * cdim + 1] = result[1]; 11387bee2925SMatthew Knepley coords[v * cdim + 2] = result[2]; 11397bee2925SMatthew Knepley } 11407bee2925SMatthew Knepley } 11417bee2925SMatthew Knepley } 11425552b385SBrandon PetscCheck(numEdges + numQuads == newVertices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of new vertices %d != %d previous count", numEdges + numQuads, newVertices); 11437bee2925SMatthew Knepley 11447bee2925SMatthew Knepley /* Get cell vertices by traversing loops */ 11457bee2925SMatthew Knepley numQuads = 0; 11467bee2925SMatthew Knepley cOff = 0; 11477bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 11487bee2925SMatthew Knepley ego body = bodies[b]; 11497bee2925SMatthew Knepley int id, Nl, l; 11507bee2925SMatthew Knepley 11515552b385SBrandon if (islite) { 11525552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 11535552b385SBrandon } else { 11549566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 11555552b385SBrandon } 11567bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 11577bee2925SMatthew Knepley ego loop = lobjs[l]; 11587bee2925SMatthew Knepley int lid, Ner = 0, Ne, e, nc = 0, c, Nt, t; 11597bee2925SMatthew Knepley 11605552b385SBrandon if (islite) { 11615552b385SBrandon lid = EGlite_indexBodyTopo(body, loop); 11625552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 11635552b385SBrandon } else { 11645f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 11659566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 11665552b385SBrandon } 11677bee2925SMatthew Knepley 11687bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 11697bee2925SMatthew Knepley ego edge = objs[e]; 11707bee2925SMatthew Knepley int points[3]; 11717bee2925SMatthew Knepley int eid, Nv, v, tmp; 11727bee2925SMatthew Knepley 11735552b385SBrandon if (islite) { 11745552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 11755552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 11765552b385SBrandon } else { 11777bee2925SMatthew Knepley eid = EG_indexBodyTopo(body, edge); 11789566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 11795552b385SBrandon } 11805552b385SBrandon 1181266cfabeSMatthew G. Knepley if (mtype == DEGENERATE) continue; 1182266cfabeSMatthew G. Knepley else ++Ner; 11835552b385SBrandon PetscCheck(Nv == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Edge %" PetscInt_FMT " has %" PetscInt_FMT " vertices != 2", eid, Nv); 11847bee2925SMatthew Knepley 11857bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 11867bee2925SMatthew Knepley ego vertex = nobjs[v]; 11877bee2925SMatthew Knepley 11885552b385SBrandon if (islite) { 11895552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 11905552b385SBrandon } else { 11917bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 11925552b385SBrandon } 11937bee2925SMatthew Knepley points[v * 2] = id - 1; 11947bee2925SMatthew Knepley } 11957bee2925SMatthew Knepley { 11967bee2925SMatthew Knepley PetscInt edgeNum; 11977bee2925SMatthew Knepley 11989566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum)); 11997bee2925SMatthew Knepley points[1] = numVertices - newVertices + edgeNum; 12007bee2925SMatthew Knepley } 12017bee2925SMatthew Knepley /* EGADS loops are not oriented, but seem to be in order, so we must piece them together */ 12027bee2925SMatthew Knepley if (!nc) { 12037bee2925SMatthew Knepley for (v = 0; v < Nv + 1; ++v) cone[nc++] = points[v]; 12047bee2925SMatthew Knepley } else { 12059371c9d4SSatish Balay if (cone[nc - 1] == points[0]) { 12069371c9d4SSatish Balay cone[nc++] = points[1]; 12079371c9d4SSatish Balay if (cone[0] != points[2]) cone[nc++] = points[2]; 12089371c9d4SSatish Balay } else if (cone[nc - 1] == points[2]) { 12099371c9d4SSatish Balay cone[nc++] = points[1]; 12109371c9d4SSatish Balay if (cone[0] != points[0]) cone[nc++] = points[0]; 12119371c9d4SSatish Balay } else if (cone[nc - 3] == points[0]) { 12129371c9d4SSatish Balay tmp = cone[nc - 3]; 12139371c9d4SSatish Balay cone[nc - 3] = cone[nc - 1]; 12149371c9d4SSatish Balay cone[nc - 1] = tmp; 12159371c9d4SSatish Balay cone[nc++] = points[1]; 12169371c9d4SSatish Balay if (cone[0] != points[2]) cone[nc++] = points[2]; 12179371c9d4SSatish Balay } else if (cone[nc - 3] == points[2]) { 12189371c9d4SSatish Balay tmp = cone[nc - 3]; 12199371c9d4SSatish Balay cone[nc - 3] = cone[nc - 1]; 12209371c9d4SSatish Balay cone[nc - 1] = tmp; 12219371c9d4SSatish Balay cone[nc++] = points[1]; 12229371c9d4SSatish Balay if (cone[0] != points[0]) cone[nc++] = points[0]; 12239371c9d4SSatish Balay } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %d does not match its predecessor", eid); 12247bee2925SMatthew Knepley } 12257bee2925SMatthew Knepley } 122663a3b9bcSJacob Faibussowitsch PetscCheck(nc == 2 * Ner, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " != %" PetscInt_FMT, nc, 2 * Ner); 12275552b385SBrandon if (Ner == 4) { cone[nc++] = numVertices - newVertices + numEdges + numQuads++; } 122863a3b9bcSJacob Faibussowitsch PetscCheck(nc <= maxCorners, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " > %" PetscInt_FMT " max", nc, maxCorners); 12297bee2925SMatthew Knepley /* Triangulate the loop */ 12307bee2925SMatthew Knepley switch (Ner) { 12317bee2925SMatthew Knepley case 2: /* Bi-Segment -> 2 triangles */ 12327bee2925SMatthew Knepley Nt = 2; 12337bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0]; 12347bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1]; 12357bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[2]; 12367bee2925SMatthew Knepley ++cOff; 12377bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0]; 12387bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2]; 12397bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3]; 12407bee2925SMatthew Knepley ++cOff; 12417bee2925SMatthew Knepley break; 12427bee2925SMatthew Knepley case 3: /* Triangle -> 4 triangles */ 12437bee2925SMatthew Knepley Nt = 4; 12447bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0]; 12457bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1]; 12467bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5]; 12477bee2925SMatthew Knepley ++cOff; 12487bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1]; 12497bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2]; 12507bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3]; 12517bee2925SMatthew Knepley ++cOff; 12527bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[5]; 12537bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3]; 12547bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[4]; 12557bee2925SMatthew Knepley ++cOff; 12567bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1]; 12577bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3]; 12587bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5]; 12597bee2925SMatthew Knepley ++cOff; 12607bee2925SMatthew Knepley break; 12617bee2925SMatthew Knepley case 4: /* Quad -> 8 triangles */ 12627bee2925SMatthew Knepley Nt = 8; 12637bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[0]; 12647bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1]; 12657bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7]; 12667bee2925SMatthew Knepley ++cOff; 12677bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[1]; 12687bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[2]; 12697bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3]; 12707bee2925SMatthew Knepley ++cOff; 12717bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[3]; 12727bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[4]; 12737bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5]; 12747bee2925SMatthew Knepley ++cOff; 12757bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[5]; 12767bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[6]; 12777bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7]; 12787bee2925SMatthew Knepley ++cOff; 12797bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8]; 12807bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[1]; 12817bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[3]; 12827bee2925SMatthew Knepley ++cOff; 12837bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8]; 12847bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[3]; 12857bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[5]; 12867bee2925SMatthew Knepley ++cOff; 12877bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8]; 12887bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[5]; 12897bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[7]; 12907bee2925SMatthew Knepley ++cOff; 12917bee2925SMatthew Knepley cells[cOff * numCorners + 0] = cone[8]; 12927bee2925SMatthew Knepley cells[cOff * numCorners + 1] = cone[7]; 12937bee2925SMatthew Knepley cells[cOff * numCorners + 2] = cone[1]; 12947bee2925SMatthew Knepley ++cOff; 12957bee2925SMatthew Knepley break; 1296d71ae5a4SJacob Faibussowitsch default: 1297d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d edges, which we do not support", lid, Ner); 12987bee2925SMatthew Knepley } 1299266cfabeSMatthew G. Knepley if (debug) { 13007bee2925SMatthew Knepley for (t = 0; t < Nt; ++t) { 13015552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP Corner NODEs Triangle %d (", t)); 13027bee2925SMatthew Knepley for (c = 0; c < numCorners; ++c) { 13035552b385SBrandon if (c > 0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); } 13045552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "%d", cells[(cOff - Nt + t) * numCorners + c])); 13057bee2925SMatthew Knepley } 13069566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n")); 13077bee2925SMatthew Knepley } 13087bee2925SMatthew Knepley } 1309266cfabeSMatthew G. Knepley } 13105552b385SBrandon if (islite) { 13115552b385SBrandon EGlite_free(lobjs); 13125552b385SBrandon } else { 13137bee2925SMatthew Knepley EG_free(lobjs); 13147bee2925SMatthew Knepley } 13157bee2925SMatthew Knepley } 13165552b385SBrandon } 13175552b385SBrandon PetscCheck(cOff == numCells, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count of total cells %d != %d previous count", cOff, numCells); 13189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numVertices, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 13199566063dSJacob Faibussowitsch PetscCall(PetscFree3(coords, cells, cone)); 13205552b385SBrandon PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %d (%d)\n", numCells, newCells)); 13215552b385SBrandon PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %d (%d)\n", numVertices, newVertices)); 13227bee2925SMatthew Knepley /* Embed EGADS model in DM */ 13237bee2925SMatthew Knepley { 13247bee2925SMatthew Knepley PetscContainer modelObj, contextObj; 13257bee2925SMatthew Knepley 13269566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 13279566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model)); 13285552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSDestroy_Private)); 13299566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 13309566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj)); 13317bee2925SMatthew Knepley 13329566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 13339566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context)); 13345552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSClose_Private)); 13359566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 13369566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj)); 13377bee2925SMatthew Knepley } 13387bee2925SMatthew Knepley /* Label points */ 13399566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 13409566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 13419566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 13429566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 13439566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 13449566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 13459566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 13469566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 13477bee2925SMatthew Knepley cOff = 0; 13487bee2925SMatthew Knepley for (b = 0; b < nbodies; ++b) { 13497bee2925SMatthew Knepley ego body = bodies[b]; 13507bee2925SMatthew Knepley int id, Nl, l; 13517bee2925SMatthew Knepley 13525552b385SBrandon if (islite) { 13535552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 13545552b385SBrandon } else { 13559566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 13565552b385SBrandon } 13577bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 13587bee2925SMatthew Knepley ego loop = lobjs[l]; 13597bee2925SMatthew Knepley ego *fobjs; 13607bee2925SMatthew Knepley int lid, Nf, fid, Ner = 0, Ne, e, Nt = 0, t; 13617bee2925SMatthew Knepley 13625552b385SBrandon if (islite) { 13635552b385SBrandon lid = EGlite_indexBodyTopo(body, loop); 13645552b385SBrandon PetscCall(EGlite_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 13655552b385SBrandon } else { 13665f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 13679566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 13685552b385SBrandon } 13695552b385SBrandon 137008401ef6SPierre Jolivet PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf); 13715552b385SBrandon if (islite) { 13725552b385SBrandon fid = EGlite_indexBodyTopo(body, fobjs[0]); 13735552b385SBrandon EGlite_free(fobjs); 13745552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 13755552b385SBrandon } else { 13765f80ce2aSJacob Faibussowitsch fid = EG_indexBodyTopo(body, fobjs[0]); 13777bee2925SMatthew Knepley EG_free(fobjs); 13789566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 13795552b385SBrandon } 13805552b385SBrandon 13817bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 13827bee2925SMatthew Knepley ego edge = objs[e]; 13837bee2925SMatthew Knepley int eid, Nv, v; 13847bee2925SMatthew Knepley PetscInt points[3], support[2], numEdges, edgeNum; 13857bee2925SMatthew Knepley const PetscInt *edges; 13867bee2925SMatthew Knepley 13875552b385SBrandon if (islite) { 13885552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 13895552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 13905552b385SBrandon } else { 13917bee2925SMatthew Knepley eid = EG_indexBodyTopo(body, edge); 13929566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 13935552b385SBrandon } 13945552b385SBrandon 13957bee2925SMatthew Knepley if (mtype == DEGENERATE) continue; 13967bee2925SMatthew Knepley else ++Ner; 13977bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 13987bee2925SMatthew Knepley ego vertex = nobjs[v]; 13997bee2925SMatthew Knepley 14005552b385SBrandon if (islite) { 14015552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 14025552b385SBrandon } else { 14037bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 14045552b385SBrandon } 14055552b385SBrandon 14069566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, numCells + id - 1, eid)); 14077bee2925SMatthew Knepley points[v * 2] = numCells + id - 1; 14087bee2925SMatthew Knepley } 14099566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum)); 14107bee2925SMatthew Knepley points[1] = numCells + numVertices - newVertices + edgeNum; 14117bee2925SMatthew Knepley 14129566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, points[1], eid)); 14137bee2925SMatthew Knepley support[0] = points[0]; 14147bee2925SMatthew Knepley support[1] = points[1]; 14159566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges)); 14165552b385SBrandon PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%d, %d) should only bound 1 edge, not %d", support[0], support[1], numEdges); 14179566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid)); 14189566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges)); 14197bee2925SMatthew Knepley support[0] = points[1]; 14207bee2925SMatthew Knepley support[1] = points[2]; 14219566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges)); 14225552b385SBrandon PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Vertices (%d, %d) should only bound 1 edge, not %d", support[0], support[1], numEdges); 14239566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid)); 14249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges)); 14257bee2925SMatthew Knepley } 14267bee2925SMatthew Knepley switch (Ner) { 1427d71ae5a4SJacob Faibussowitsch case 2: 1428d71ae5a4SJacob Faibussowitsch Nt = 2; 1429d71ae5a4SJacob Faibussowitsch break; 1430d71ae5a4SJacob Faibussowitsch case 3: 1431d71ae5a4SJacob Faibussowitsch Nt = 4; 1432d71ae5a4SJacob Faibussowitsch break; 1433d71ae5a4SJacob Faibussowitsch case 4: 1434d71ae5a4SJacob Faibussowitsch Nt = 8; 1435d71ae5a4SJacob Faibussowitsch break; 1436d71ae5a4SJacob Faibussowitsch default: 1437d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Loop with %d edges is unsupported", Ner); 14387bee2925SMatthew Knepley } 14397bee2925SMatthew Knepley for (t = 0; t < Nt; ++t) { 14409566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cOff + t, b)); 14419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cOff + t, fid)); 14427bee2925SMatthew Knepley } 14437bee2925SMatthew Knepley cOff += Nt; 14447bee2925SMatthew Knepley } 14455552b385SBrandon if (islite) { 14465552b385SBrandon EGlite_free(lobjs); 14475552b385SBrandon } else { 14487bee2925SMatthew Knepley EG_free(lobjs); 14497bee2925SMatthew Knepley } 14505552b385SBrandon } 14519566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&edgeMap)); 14529566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 14537bee2925SMatthew Knepley for (c = cStart; c < cEnd; ++c) { 14547bee2925SMatthew Knepley PetscInt *closure = NULL; 14557bee2925SMatthew Knepley PetscInt clSize, cl, bval, fval; 14567bee2925SMatthew Knepley 14579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 14589566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, c, &bval)); 14599566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, c, &fval)); 14607bee2925SMatthew Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 14619566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, closure[cl], bval)); 14629566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, closure[cl], fval)); 14637bee2925SMatthew Knepley } 14649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 14657bee2925SMatthew Knepley } 14667bee2925SMatthew Knepley *newdm = dm; 14675552b385SBrandon PetscFunctionReturn(0); 14687bee2925SMatthew Knepley } 1469c1cad2e7SMatthew G. Knepley 14705552b385SBrandon PetscErrorCode DMPlexCreateGeom(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 1471d71ae5a4SJacob Faibussowitsch { 14725552b385SBrandon // EGADS variables 1473c1cad2e7SMatthew G. Knepley ego geom, *bodies, *mobjs, *fobjs, *lobjs, *eobjs, *nobjs; 1474c1cad2e7SMatthew G. Knepley ego topRef, prev, next; 1475c1cad2e7SMatthew G. Knepley int oclass, mtype, nbodies, *senses, *lSenses, *eSenses; 1476c1cad2e7SMatthew G. Knepley int b; 1477c1cad2e7SMatthew G. Knepley // PETSc variables 1478c1cad2e7SMatthew G. Knepley DM dm; 14795552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 1480c1cad2e7SMatthew G. Knepley PetscHMapI edgeMap = NULL, bodyIndexMap = NULL, bodyVertexMap = NULL, bodyEdgeMap = NULL, bodyFaceMap = NULL, bodyEdgeGlobalMap = NULL; 1481c1cad2e7SMatthew G. Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, numVertices = 0, numEdges = 0, numFaces = 0, numCells = 0, edgeCntr = 0; 1482c1cad2e7SMatthew G. Knepley PetscInt cellCntr = 0, numPoints = 0; 1483c1cad2e7SMatthew G. Knepley PetscInt *cells = NULL; 1484c1cad2e7SMatthew G. Knepley const PetscInt *cone = NULL; 1485c1cad2e7SMatthew G. Knepley PetscReal *coords = NULL; 1486c1cad2e7SMatthew G. Knepley PetscMPIInt rank; 1487c1cad2e7SMatthew G. Knepley 1488c1cad2e7SMatthew G. Knepley PetscFunctionBeginUser; 14899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1490c5853193SPierre Jolivet if (rank == 0) { 1491c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 1492c1cad2e7SMatthew G. Knepley // Generate Petsc Plex 1493c1cad2e7SMatthew G. Knepley // Get all Nodes in model, record coordinates in a correctly formatted array 1494c1cad2e7SMatthew G. Knepley // Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array 1495c1cad2e7SMatthew G. Knepley // We need to uniformly refine the initial geometry to guarantee a valid mesh 1496c1cad2e7SMatthew G. Knepley 1497d5b43468SJose E. Roman // Calculate cell and vertex sizes 14985552b385SBrandon if (islite) { 14995552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 15005552b385SBrandon } else { 15019566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 15025552b385SBrandon } 15039566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&edgeMap)); 15049566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyIndexMap)); 15059566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyVertexMap)); 15069566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyEdgeMap)); 15079566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyEdgeGlobalMap)); 15089566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&bodyFaceMap)); 1509c1cad2e7SMatthew G. Knepley 1510c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 1511c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 1512c1cad2e7SMatthew G. Knepley int Nf, Ne, Nv; 1513c1cad2e7SMatthew G. Knepley PetscHashIter BIiter, BViter, BEiter, BEGiter, BFiter, EMiter; 1514c1cad2e7SMatthew G. Knepley PetscBool BIfound, BVfound, BEfound, BEGfound, BFfound, EMfound; 1515c1cad2e7SMatthew G. Knepley 15169566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyIndexMap, b, &BIiter, &BIfound)); 15179566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 15189566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 15199566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 15209566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 1521c1cad2e7SMatthew G. Knepley 15229566063dSJacob Faibussowitsch if (!BIfound) PetscCall(PetscHMapISet(bodyIndexMap, b, numFaces + numEdges + numVertices)); 15239566063dSJacob Faibussowitsch if (!BVfound) PetscCall(PetscHMapISet(bodyVertexMap, b, numVertices)); 15249566063dSJacob Faibussowitsch if (!BEfound) PetscCall(PetscHMapISet(bodyEdgeMap, b, numEdges)); 15259566063dSJacob Faibussowitsch if (!BEGfound) PetscCall(PetscHMapISet(bodyEdgeGlobalMap, b, edgeCntr)); 15269566063dSJacob Faibussowitsch if (!BFfound) PetscCall(PetscHMapISet(bodyFaceMap, b, numFaces)); 1527c1cad2e7SMatthew G. Knepley 15285552b385SBrandon if (islite) { 15295552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 15305552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 15315552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 15325552b385SBrandon EGlite_free(fobjs); 15335552b385SBrandon EGlite_free(eobjs); 15345552b385SBrandon EGlite_free(nobjs); 15355552b385SBrandon } else { 15369566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 15379566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 15389566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1539c1cad2e7SMatthew G. Knepley EG_free(fobjs); 1540c1cad2e7SMatthew G. Knepley EG_free(eobjs); 1541c1cad2e7SMatthew G. Knepley EG_free(nobjs); 15425552b385SBrandon } 1543c1cad2e7SMatthew G. Knepley 1544c1cad2e7SMatthew G. Knepley // Remove DEGENERATE EDGES from Edge count 15455552b385SBrandon if (islite) { 15465552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 15475552b385SBrandon } else { 15489566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 15495552b385SBrandon } 15505552b385SBrandon 1551c1cad2e7SMatthew G. Knepley int Netemp = 0; 1552c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 1553c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 1554c1cad2e7SMatthew G. Knepley int eid; 1555c1cad2e7SMatthew G. Knepley 15565552b385SBrandon if (islite) { 15575552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 15585552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 15595552b385SBrandon } else { 15609566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 15615f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 15625552b385SBrandon } 1563c1cad2e7SMatthew G. Knepley 15649566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, edgeCntr + eid - 1, &EMiter, &EMfound)); 1565c1cad2e7SMatthew G. Knepley if (mtype == DEGENERATE) { 15669566063dSJacob Faibussowitsch if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, -1)); 15679371c9d4SSatish Balay } else { 1568c1cad2e7SMatthew G. Knepley ++Netemp; 15699566063dSJacob Faibussowitsch if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, Netemp)); 1570c1cad2e7SMatthew G. Knepley } 1571c1cad2e7SMatthew G. Knepley } 15725552b385SBrandon if (islite) { 15735552b385SBrandon EGlite_free(eobjs); 15745552b385SBrandon } else { 1575c1cad2e7SMatthew G. Knepley EG_free(eobjs); 15765552b385SBrandon } 1577c1cad2e7SMatthew G. Knepley 1578c1cad2e7SMatthew G. Knepley // Determine Number of Cells 15795552b385SBrandon if (islite) { 15805552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 15815552b385SBrandon } else { 15829566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 15835552b385SBrandon } 15845552b385SBrandon 1585c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 1586c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 1587c1cad2e7SMatthew G. Knepley int edgeTemp = 0; 1588c1cad2e7SMatthew G. Knepley 15895552b385SBrandon if (islite) { 15905552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 15915552b385SBrandon } else { 15929566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 15935552b385SBrandon } 15945552b385SBrandon 1595c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 1596c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 1597c1cad2e7SMatthew G. Knepley 15985552b385SBrandon if (islite) { 15995552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 16005552b385SBrandon } else { 16019566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 16025552b385SBrandon } 1603ad540459SPierre Jolivet if (mtype != DEGENERATE) ++edgeTemp; 1604c1cad2e7SMatthew G. Knepley } 1605c1cad2e7SMatthew G. Knepley numCells += (2 * edgeTemp); 16065552b385SBrandon if (islite) { 16075552b385SBrandon EGlite_free(eobjs); 16085552b385SBrandon } else { 1609c1cad2e7SMatthew G. Knepley EG_free(eobjs); 1610c1cad2e7SMatthew G. Knepley } 16115552b385SBrandon } 16125552b385SBrandon if (islite) { 16135552b385SBrandon EGlite_free(fobjs); 16145552b385SBrandon } else { 1615c1cad2e7SMatthew G. Knepley EG_free(fobjs); 16165552b385SBrandon } 1617c1cad2e7SMatthew G. Knepley 1618c1cad2e7SMatthew G. Knepley numFaces += Nf; 1619c1cad2e7SMatthew G. Knepley numEdges += Netemp; 1620c1cad2e7SMatthew G. Knepley numVertices += Nv; 1621c1cad2e7SMatthew G. Knepley edgeCntr += Ne; 1622c1cad2e7SMatthew G. Knepley } 1623c1cad2e7SMatthew G. Knepley 1624c1cad2e7SMatthew G. Knepley // Set up basic DMPlex parameters 162535cb6cd3SPierre Jolivet dim = 2; // Assumes 3D Models :: Need to handle 2D models in the future 162635cb6cd3SPierre Jolivet cdim = 3; // Assumes 3D Models :: Need to update to handle 2D models in future 1627c1cad2e7SMatthew G. Knepley numCorners = 3; // Split Faces into triangles 1628c1cad2e7SMatthew G. Knepley numPoints = numVertices + numEdges + numFaces; // total number of coordinate points 1629c1cad2e7SMatthew G. Knepley 16309566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPoints * cdim, &coords, numCells * numCorners, &cells)); 1631c1cad2e7SMatthew G. Knepley 1632c1cad2e7SMatthew G. Knepley // Get Vertex Coordinates and Set up Cells 1633c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 1634c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 1635c1cad2e7SMatthew G. Knepley int Nf, Ne, Nv; 1636c1cad2e7SMatthew G. Knepley PetscInt bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart; 1637c1cad2e7SMatthew G. Knepley PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter; 1638c1cad2e7SMatthew G. Knepley PetscBool BVfound, BEfound, BEGfound, BFfound, EMfound; 1639c1cad2e7SMatthew G. Knepley 1640c1cad2e7SMatthew G. Knepley // Vertices on Current Body 16415552b385SBrandon if (islite) { 16425552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 16435552b385SBrandon } else { 16449566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 16455552b385SBrandon } 1646c1cad2e7SMatthew G. Knepley 16479566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 16485552b385SBrandon PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyVertexMap", b); 16499566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart)); 1650c1cad2e7SMatthew G. Knepley 1651c1cad2e7SMatthew G. Knepley for (int v = 0; v < Nv; ++v) { 1652c1cad2e7SMatthew G. Knepley ego vertex = nobjs[v]; 1653c1cad2e7SMatthew G. Knepley double limits[4]; 1654c1cad2e7SMatthew G. Knepley int id, dummy; 1655c1cad2e7SMatthew G. Knepley 16565552b385SBrandon if (islite) { 16575552b385SBrandon PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 16585552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 16595552b385SBrandon } else { 16609566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 16615f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, vertex); 16625552b385SBrandon } 1663c1cad2e7SMatthew G. Knepley 1664c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 0] = limits[0]; 1665c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 1] = limits[1]; 1666c1cad2e7SMatthew G. Knepley coords[(bodyVertexIndexStart + id - 1) * cdim + 2] = limits[2]; 1667c1cad2e7SMatthew G. Knepley } 16685552b385SBrandon if (islite) { 16695552b385SBrandon EGlite_free(nobjs); 16705552b385SBrandon } else { 1671c1cad2e7SMatthew G. Knepley EG_free(nobjs); 16725552b385SBrandon } 1673c1cad2e7SMatthew G. Knepley 1674c1cad2e7SMatthew G. Knepley // Edge Midpoint Vertices on Current Body 16755552b385SBrandon if (islite) { 16765552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 16775552b385SBrandon } else { 16789566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 16795552b385SBrandon } 1680c1cad2e7SMatthew G. Knepley 16819566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 16825552b385SBrandon PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyEdgeMap", b); 16839566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart)); 1684c1cad2e7SMatthew G. Knepley 16859566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 16865552b385SBrandon PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyEdgeGlobalMap", b); 16879566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart)); 1688c1cad2e7SMatthew G. Knepley 1689c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 1690c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 1691c1cad2e7SMatthew G. Knepley double range[2], avgt[1], cntrPnt[9]; 1692c1cad2e7SMatthew G. Knepley int eid, eOffset; 1693c1cad2e7SMatthew G. Knepley int periodic; 1694c1cad2e7SMatthew G. Knepley 16955552b385SBrandon if (islite) { 16965552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 16975552b385SBrandon } else { 16989566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 16995552b385SBrandon } 1700ad540459SPierre Jolivet if (mtype == DEGENERATE) continue; 1701c1cad2e7SMatthew G. Knepley 17025552b385SBrandon if (islite) { 17035552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 17045552b385SBrandon } else { 17055f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 17065552b385SBrandon } 1707c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector 17089566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 17095552b385SBrandon PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %" PetscInt_FMT " not found in edgeMap", bodyEdgeGlobalIndexStart + eid - 1); 17109566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 1711c1cad2e7SMatthew G. Knepley 17125552b385SBrandon if (islite) { 17135552b385SBrandon PetscCall(EGlite_getRange(edge, range, &periodic)); 17145552b385SBrandon } else { 17159566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, &periodic)); 17165552b385SBrandon } 1717c1cad2e7SMatthew G. Knepley avgt[0] = (range[0] + range[1]) / 2.; 1718c1cad2e7SMatthew G. Knepley 17195552b385SBrandon if (islite) { 17205552b385SBrandon PetscCall(EGlite_evaluate(edge, avgt, cntrPnt)); 17215552b385SBrandon } else { 17229566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, avgt, cntrPnt)); 17235552b385SBrandon } 1724c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 0] = cntrPnt[0]; 1725c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 1] = cntrPnt[1]; 1726c1cad2e7SMatthew G. Knepley coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 2] = cntrPnt[2]; 1727c1cad2e7SMatthew G. Knepley } 17285552b385SBrandon if (islite) { 17295552b385SBrandon EGlite_free(eobjs); 17305552b385SBrandon } else { 1731c1cad2e7SMatthew G. Knepley EG_free(eobjs); 17325552b385SBrandon } 1733c1cad2e7SMatthew G. Knepley // Face Midpoint Vertices on Current Body 17345552b385SBrandon if (islite) { 17355552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 17365552b385SBrandon } else { 17379566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 17385552b385SBrandon } 17399566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 174028b400f6SJacob Faibussowitsch PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b); 17419566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart)); 1742c1cad2e7SMatthew G. Knepley 1743c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 1744c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 1745c1cad2e7SMatthew G. Knepley double range[4], avgUV[2], cntrPnt[18]; 1746c1cad2e7SMatthew G. Knepley int peri, id; 1747c1cad2e7SMatthew G. Knepley 17485552b385SBrandon if (islite) { 17495552b385SBrandon id = EGlite_indexBodyTopo(body, face); 17505552b385SBrandon PetscCall(EGlite_getRange(face, range, &peri)); 17515552b385SBrandon } else { 1752c1cad2e7SMatthew G. Knepley id = EG_indexBodyTopo(body, face); 17539566063dSJacob Faibussowitsch PetscCall(EG_getRange(face, range, &peri)); 17545552b385SBrandon } 1755c1cad2e7SMatthew G. Knepley 1756c1cad2e7SMatthew G. Knepley avgUV[0] = (range[0] + range[1]) / 2.; 1757c1cad2e7SMatthew G. Knepley avgUV[1] = (range[2] + range[3]) / 2.; 17585552b385SBrandon 17595552b385SBrandon if (islite) { 17605552b385SBrandon PetscCall(EGlite_evaluate(face, avgUV, cntrPnt)); 17615552b385SBrandon } else { 17629566063dSJacob Faibussowitsch PetscCall(EG_evaluate(face, avgUV, cntrPnt)); 17635552b385SBrandon } 1764c1cad2e7SMatthew G. Knepley 1765c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 0] = cntrPnt[0]; 1766c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 1] = cntrPnt[1]; 1767c1cad2e7SMatthew G. Knepley coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 2] = cntrPnt[2]; 1768c1cad2e7SMatthew G. Knepley } 17695552b385SBrandon if (islite) { 17705552b385SBrandon EGlite_free(fobjs); 17715552b385SBrandon } else { 1772c1cad2e7SMatthew G. Knepley EG_free(fobjs); 17735552b385SBrandon } 1774c1cad2e7SMatthew G. Knepley 1775c1cad2e7SMatthew G. Knepley // Define Cells :: Note - This could be incorporated in the Face Midpoint Vertices Loop but was kept separate for clarity 17765552b385SBrandon if (islite) { 17775552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 17785552b385SBrandon } else { 17799566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 17805552b385SBrandon } 1781c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 1782c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 1783c1cad2e7SMatthew G. Knepley int fID, midFaceID, midPntID, startID, endID, Nl; 1784c1cad2e7SMatthew G. Knepley 17855552b385SBrandon if (islite) { 17865552b385SBrandon fID = EGlite_indexBodyTopo(body, face); 17875552b385SBrandon } else { 17885f80ce2aSJacob Faibussowitsch fID = EG_indexBodyTopo(body, face); 17895552b385SBrandon } 17905552b385SBrandon 1791c1cad2e7SMatthew G. Knepley midFaceID = numVertices + numEdges + bodyFaceIndexStart + fID - 1; 1792c1cad2e7SMatthew G. Knepley // Must Traverse Loop to ensure we have all necessary information like the sense (+/- 1) of the edges. 1793c1cad2e7SMatthew G. Knepley // TODO :: Only handles single loop faces (No holes). The choices for handling multiloop faces are: 17945552b385SBrandon // 1) Use the DMPlexCreateGeomFromFile() with the -dm_plex_geom_with_tess = 1 option. 1795c1cad2e7SMatthew G. Knepley // This will use a default EGADS tessellation as an initial surface mesh. 1796d5b43468SJose E. Roman // 2) Create the initial surface mesh via a 2D mesher :: Currently not available (?future?) 1797c1cad2e7SMatthew G. Knepley // May I suggest the XXXX as a starting point? 1798c1cad2e7SMatthew G. Knepley 17995552b385SBrandon if (islite) { 18005552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses)); 18015552b385SBrandon } else { 18029566063dSJacob Faibussowitsch PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses)); 18035552b385SBrandon } 1804c1cad2e7SMatthew G. Knepley 18055552b385SBrandon PetscCheck(Nl == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face has %" PetscInt_FMT " Loops. Can only handle Faces with 1 Loop. Please use --dm_plex_geom_with_tess = 1 Option", Nl); 1806c1cad2e7SMatthew G. Knepley for (int l = 0; l < Nl; ++l) { 1807c1cad2e7SMatthew G. Knepley ego loop = lobjs[l]; 1808c1cad2e7SMatthew G. Knepley 18095552b385SBrandon if (islite) { 18105552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 18115552b385SBrandon } else { 18129566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 18135552b385SBrandon } 18145552b385SBrandon 1815c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 1816c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 1817c1cad2e7SMatthew G. Knepley int eid, eOffset; 1818c1cad2e7SMatthew G. Knepley 18195552b385SBrandon if (islite) { 18205552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 18215552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 18225552b385SBrandon } else { 18239566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1824c1cad2e7SMatthew G. Knepley eid = EG_indexBodyTopo(body, edge); 18255552b385SBrandon } 1826ad540459SPierre Jolivet if (mtype == DEGENERATE) continue; 1827c1cad2e7SMatthew G. Knepley 1828c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector 18299566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 18305552b385SBrandon PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %" PetscInt_FMT " of Body %" PetscInt_FMT " not found in edgeMap. Global Edge ID :: %" PetscInt_FMT, eid, b, bodyEdgeGlobalIndexStart + eid - 1); 18319566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 1832c1cad2e7SMatthew G. Knepley 1833c1cad2e7SMatthew G. Knepley midPntID = numVertices + bodyEdgeIndexStart + eOffset - 1; 1834c1cad2e7SMatthew G. Knepley 18355552b385SBrandon if (islite) { 18365552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 18375552b385SBrandon } else { 18389566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 18395552b385SBrandon } 1840c1cad2e7SMatthew G. Knepley 18419371c9d4SSatish Balay if (eSenses[e] > 0) { 18425552b385SBrandon if (islite) { 18435552b385SBrandon startID = EGlite_indexBodyTopo(body, nobjs[0]); 18445552b385SBrandon endID = EGlite_indexBodyTopo(body, nobjs[1]); 18455552b385SBrandon } else { 18469371c9d4SSatish Balay startID = EG_indexBodyTopo(body, nobjs[0]); 18479371c9d4SSatish Balay endID = EG_indexBodyTopo(body, nobjs[1]); 18485552b385SBrandon } 18495552b385SBrandon } else { 18505552b385SBrandon if (islite) { 18515552b385SBrandon startID = EGlite_indexBodyTopo(body, nobjs[1]); 18525552b385SBrandon endID = EGlite_indexBodyTopo(body, nobjs[0]); 18539371c9d4SSatish Balay } else { 18549371c9d4SSatish Balay startID = EG_indexBodyTopo(body, nobjs[1]); 18559371c9d4SSatish Balay endID = EG_indexBodyTopo(body, nobjs[0]); 18569371c9d4SSatish Balay } 18575552b385SBrandon } 1858c1cad2e7SMatthew G. Knepley 1859c1cad2e7SMatthew G. Knepley // Define 2 Cells per Edge with correct orientation 1860c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 0] = midFaceID; 1861c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 1] = bodyVertexIndexStart + startID - 1; 1862c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 2] = midPntID; 1863c1cad2e7SMatthew G. Knepley 1864c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 3] = midFaceID; 1865c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 4] = midPntID; 1866c1cad2e7SMatthew G. Knepley cells[cellCntr * numCorners + 5] = bodyVertexIndexStart + endID - 1; 1867c1cad2e7SMatthew G. Knepley 1868c1cad2e7SMatthew G. Knepley cellCntr = cellCntr + 2; 1869c1cad2e7SMatthew G. Knepley } 1870c1cad2e7SMatthew G. Knepley } 1871c1cad2e7SMatthew G. Knepley } 18725552b385SBrandon if (islite) { 18735552b385SBrandon EGlite_free(fobjs); 18745552b385SBrandon } else { 1875c1cad2e7SMatthew G. Knepley EG_free(fobjs); 1876c1cad2e7SMatthew G. Knepley } 1877c1cad2e7SMatthew G. Knepley } 18785552b385SBrandon } 1879c1cad2e7SMatthew G. Knepley 1880c1cad2e7SMatthew G. Knepley // Generate DMPlex 18819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 18829566063dSJacob Faibussowitsch PetscCall(PetscFree2(coords, cells)); 188363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %" PetscInt_FMT " \n", numCells)); 188463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %" PetscInt_FMT " \n", numVertices)); 1885c1cad2e7SMatthew G. Knepley 1886c1cad2e7SMatthew G. Knepley // Embed EGADS model in DM 1887c1cad2e7SMatthew G. Knepley { 1888c1cad2e7SMatthew G. Knepley PetscContainer modelObj, contextObj; 1889c1cad2e7SMatthew G. Knepley 18909566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 18919566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model)); 18925552b385SBrandon if (islite) { 18935552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSliteDestroy_Private)); 18945552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Model", (PetscObject)modelObj)); 18955552b385SBrandon } else { 18965552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSDestroy_Private)); 18979566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 18985552b385SBrandon } 18999566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj)); 1900c1cad2e7SMatthew G. Knepley 19019566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 19029566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context)); 19035552b385SBrandon 19045552b385SBrandon if (islite) { 19055552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSliteClose_Private)); 19065552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Context", (PetscObject)contextObj)); 19075552b385SBrandon } else { 19085552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSClose_Private)); 19099566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 19105552b385SBrandon } 19119566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj)); 1912c1cad2e7SMatthew G. Knepley } 1913c1cad2e7SMatthew G. Knepley // Label points 1914c1cad2e7SMatthew G. Knepley PetscInt nStart, nEnd; 1915c1cad2e7SMatthew G. Knepley 19169566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 19179566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 19189566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 19199566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 19209566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 19219566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 19229566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 19239566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 1924c1cad2e7SMatthew G. Knepley 19259566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd)); 1926c1cad2e7SMatthew G. Knepley 1927c1cad2e7SMatthew G. Knepley cellCntr = 0; 1928c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 1929c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 1930c1cad2e7SMatthew G. Knepley int Nv, Ne, Nf; 1931c1cad2e7SMatthew G. Knepley PetscInt bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart; 1932c1cad2e7SMatthew G. Knepley PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter; 1933c1cad2e7SMatthew G. Knepley PetscBool BVfound, BEfound, BEGfound, BFfound, EMfound; 1934c1cad2e7SMatthew G. Knepley 19359566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 193628b400f6SJacob Faibussowitsch PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyVertexMap", b); 19379566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart)); 1938c1cad2e7SMatthew G. Knepley 19399566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 194028b400f6SJacob Faibussowitsch PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeMap", b); 19419566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart)); 1942c1cad2e7SMatthew G. Knepley 19439566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 194428b400f6SJacob Faibussowitsch PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b); 19459566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart)); 1946c1cad2e7SMatthew G. Knepley 19479566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 194828b400f6SJacob Faibussowitsch PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeGlobalMap", b); 19499566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart)); 1950c1cad2e7SMatthew G. Knepley 19515552b385SBrandon if (islite) { 19525552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 19535552b385SBrandon } else { 19549566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 19555552b385SBrandon } 19565552b385SBrandon 1957c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 1958c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 1959c1cad2e7SMatthew G. Knepley int fID, Nl; 1960c1cad2e7SMatthew G. Knepley 19615552b385SBrandon if (islite) { 19625552b385SBrandon fID = EGlite_indexBodyTopo(body, face); 19635552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, LOOP, &Nl, &lobjs)); 19645552b385SBrandon } else { 19655f80ce2aSJacob Faibussowitsch fID = EG_indexBodyTopo(body, face); 19669566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, face, LOOP, &Nl, &lobjs)); 19675552b385SBrandon } 19685552b385SBrandon 1969c1cad2e7SMatthew G. Knepley for (int l = 0; l < Nl; ++l) { 1970c1cad2e7SMatthew G. Knepley ego loop = lobjs[l]; 1971c1cad2e7SMatthew G. Knepley int lid; 1972c1cad2e7SMatthew G. Knepley 19735552b385SBrandon if (islite) { 19745552b385SBrandon lid = EGlite_indexBodyTopo(body, loop); 19755552b385SBrandon } else { 19765f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 19775552b385SBrandon } 1978c1cad2e7SMatthew G. Knepley 19795552b385SBrandon PetscCheck(Nl == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %" PetscInt_FMT " has %" PetscInt_FMT " > 1 faces, which is not supported", lid, Nf); 19805552b385SBrandon 19815552b385SBrandon if (islite) { 19825552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 19835552b385SBrandon } else { 19849566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 19855552b385SBrandon } 19865552b385SBrandon 1987c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 1988c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 1989c1cad2e7SMatthew G. Knepley int eid, eOffset; 1990c1cad2e7SMatthew G. Knepley 1991c1cad2e7SMatthew G. Knepley // Skip DEGENERATE Edges 19925552b385SBrandon if (islite) { 19935552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 19945552b385SBrandon } else { 19959566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 19965552b385SBrandon } 19975552b385SBrandon 19985552b385SBrandon if (mtype == DEGENERATE) { continue; } 19995552b385SBrandon 20005552b385SBrandon if (islite) { 20015552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 20025552b385SBrandon } else { 20035f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 20045552b385SBrandon } 2005c1cad2e7SMatthew G. Knepley 2006c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector 20079566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 20085552b385SBrandon PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %" PetscInt_FMT " of Body %" PetscInt_FMT " not found in edgeMap. Global Edge ID :: %" PetscInt_FMT, eid, b, bodyEdgeGlobalIndexStart + eid - 1); 20099566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 2010c1cad2e7SMatthew G. Knepley 20115552b385SBrandon if (islite) { 20125552b385SBrandon PetscCall(EGlite_getBodyTopos(body, edge, NODE, &Nv, &nobjs)); 20135552b385SBrandon } else { 20149566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, edge, NODE, &Nv, &nobjs)); 20155552b385SBrandon } 20165552b385SBrandon 2017c1cad2e7SMatthew G. Knepley for (int v = 0; v < Nv; ++v) { 2018c1cad2e7SMatthew G. Knepley ego vertex = nobjs[v]; 2019c1cad2e7SMatthew G. Knepley int vID; 2020c1cad2e7SMatthew G. Knepley 20215552b385SBrandon if (islite) { 20225552b385SBrandon vID = EGlite_indexBodyTopo(body, vertex); 20235552b385SBrandon } else { 20245f80ce2aSJacob Faibussowitsch vID = EG_indexBodyTopo(body, vertex); 20255552b385SBrandon } 20265552b385SBrandon 20279566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + bodyVertexIndexStart + vID - 1, b)); 20289566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(vertexLabel, nStart + bodyVertexIndexStart + vID - 1, vID)); 2029c1cad2e7SMatthew G. Knepley } 20305552b385SBrandon if (islite) { 20315552b385SBrandon EGlite_free(nobjs); 20325552b385SBrandon } else { 2033c1cad2e7SMatthew G. Knepley EG_free(nobjs); 20345552b385SBrandon } 2035c1cad2e7SMatthew G. Knepley 20369566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, b)); 20379566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, eid)); 2038c1cad2e7SMatthew G. Knepley 2039c1cad2e7SMatthew G. Knepley // Define Cell faces 2040c1cad2e7SMatthew G. Knepley for (int jj = 0; jj < 2; ++jj) { 20419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cellCntr, b)); 20429566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cellCntr, fID)); 20439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cellCntr, &cone)); 2044c1cad2e7SMatthew G. Knepley 20459566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[0], b)); 20469566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[0], fID)); 2047c1cad2e7SMatthew G. Knepley 20489566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[1], b)); 20499566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(edgeLabel, cone[1], eid)); 2050c1cad2e7SMatthew G. Knepley 20519566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[2], b)); 20529566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[2], fID)); 2053c1cad2e7SMatthew G. Knepley 2054c1cad2e7SMatthew G. Knepley cellCntr = cellCntr + 1; 2055c1cad2e7SMatthew G. Knepley } 2056c1cad2e7SMatthew G. Knepley } 2057c1cad2e7SMatthew G. Knepley } 20585552b385SBrandon if (islite) { 20595552b385SBrandon EGlite_free(lobjs); 20605552b385SBrandon } else { 2061c1cad2e7SMatthew G. Knepley EG_free(lobjs); 20625552b385SBrandon } 2063c1cad2e7SMatthew G. Knepley 20649566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, b)); 20659566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, fID)); 2066c1cad2e7SMatthew G. Knepley } 20675552b385SBrandon if (islite) { 20685552b385SBrandon EGlite_free(fobjs); 20695552b385SBrandon } else { 2070c1cad2e7SMatthew G. Knepley EG_free(fobjs); 2071c1cad2e7SMatthew G. Knepley } 20725552b385SBrandon } 2073c1cad2e7SMatthew G. Knepley 20749566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&edgeMap)); 20759566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyIndexMap)); 20769566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyVertexMap)); 20779566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyEdgeMap)); 20789566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyEdgeGlobalMap)); 20799566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&bodyFaceMap)); 2080c1cad2e7SMatthew G. Knepley 2081c1cad2e7SMatthew G. Knepley *newdm = dm; 20823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2083c1cad2e7SMatthew G. Knepley } 2084c1cad2e7SMatthew G. Knepley 20855552b385SBrandon PetscErrorCode DMPlexCreateGeom_Tess_Internal(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 2086d71ae5a4SJacob Faibussowitsch { 20875552b385SBrandon /* EGADSlite variables */ 2088c1cad2e7SMatthew G. Knepley ego geom, *bodies, *fobjs; 2089c1cad2e7SMatthew G. Knepley int b, oclass, mtype, nbodies, *senses; 2090c1cad2e7SMatthew G. Knepley int totalNumTris = 0, totalNumPoints = 0; 2091c1cad2e7SMatthew G. Knepley double boundBox[6] = {0., 0., 0., 0., 0., 0.}, tessSize; 2092c1cad2e7SMatthew G. Knepley /* PETSc variables */ 2093c1cad2e7SMatthew G. Knepley DM dm; 20945552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 2095c1cad2e7SMatthew G. Knepley PetscHMapI pointIndexStartMap = NULL, triIndexStartMap = NULL, pTypeLabelMap = NULL, pIndexLabelMap = NULL; 2096c1cad2e7SMatthew G. Knepley PetscHMapI pBodyIndexLabelMap = NULL, triFaceIDLabelMap = NULL, triBodyIDLabelMap = NULL; 2097c1cad2e7SMatthew G. Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, counter = 0; 2098c1cad2e7SMatthew G. Knepley PetscInt *cells = NULL; 2099c1cad2e7SMatthew G. Knepley const PetscInt *cone = NULL; 2100c1cad2e7SMatthew G. Knepley PetscReal *coords = NULL; 2101c1cad2e7SMatthew G. Knepley PetscMPIInt rank; 2102c1cad2e7SMatthew G. Knepley 2103c1cad2e7SMatthew G. Knepley PetscFunctionBeginUser; 21049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2105c5853193SPierre Jolivet if (rank == 0) { 2106c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 2107c1cad2e7SMatthew G. Knepley // Generate Petsc Plex from EGADSlite created Tessellation of geometry 2108c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 2109c1cad2e7SMatthew G. Knepley 2110d5b43468SJose E. Roman // Calculate cell and vertex sizes 21115552b385SBrandon if (islite) { 21125552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 21135552b385SBrandon } else { 21149566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 21155552b385SBrandon } 2116c1cad2e7SMatthew G. Knepley 21179566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pointIndexStartMap)); 21189566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triIndexStartMap)); 21199566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pTypeLabelMap)); 21209566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pIndexLabelMap)); 21219566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&pBodyIndexLabelMap)); 21229566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triFaceIDLabelMap)); 21239566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&triBodyIDLabelMap)); 2124c1cad2e7SMatthew G. Knepley 2125c1cad2e7SMatthew G. Knepley /* Create Tessellation of Bodies */ 21265552b385SBrandon ego *tessArray; 2127c1cad2e7SMatthew G. Knepley 21285552b385SBrandon PetscCall(PetscMalloc1(nbodies, &tessArray)); 2129c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 2130c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 2131c1cad2e7SMatthew G. Knepley double params[3] = {0.0, 0.0, 0.0}; // Parameters for Tessellation 2132c1cad2e7SMatthew G. Knepley int Nf, bodyNumPoints = 0, bodyNumTris = 0; 2133c1cad2e7SMatthew G. Knepley PetscHashIter PISiter, TISiter; 2134c1cad2e7SMatthew G. Knepley PetscBool PISfound, TISfound; 2135c1cad2e7SMatthew G. Knepley 2136c1cad2e7SMatthew G. Knepley /* Store Start Index for each Body's Point and Tris */ 21379566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound)); 21389566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triIndexStartMap, b, &TISiter, &TISfound)); 2139c1cad2e7SMatthew G. Knepley 21409566063dSJacob Faibussowitsch if (!PISfound) PetscCall(PetscHMapISet(pointIndexStartMap, b, totalNumPoints)); 21419566063dSJacob Faibussowitsch if (!TISfound) PetscCall(PetscHMapISet(triIndexStartMap, b, totalNumTris)); 2142c1cad2e7SMatthew G. Knepley 2143c1cad2e7SMatthew G. Knepley /* Calculate Tessellation parameters based on Bounding Box */ 2144c1cad2e7SMatthew G. Knepley /* Get Bounding Box Dimensions of the BODY */ 21455552b385SBrandon if (islite) { 21465552b385SBrandon PetscCall(EGlite_getBoundingBox(body, boundBox)); 21475552b385SBrandon } else { 21489566063dSJacob Faibussowitsch PetscCall(EG_getBoundingBox(body, boundBox)); 21495552b385SBrandon } 21505552b385SBrandon 2151c1cad2e7SMatthew G. Knepley tessSize = boundBox[3] - boundBox[0]; 2152c1cad2e7SMatthew G. Knepley if (tessSize < boundBox[4] - boundBox[1]) tessSize = boundBox[4] - boundBox[1]; 2153c1cad2e7SMatthew G. Knepley if (tessSize < boundBox[5] - boundBox[2]) tessSize = boundBox[5] - boundBox[2]; 2154c1cad2e7SMatthew G. Knepley 2155c1cad2e7SMatthew G. Knepley // TODO :: May want to give users tessellation parameter options // 2156c1cad2e7SMatthew G. Knepley params[0] = 0.0250 * tessSize; 2157c1cad2e7SMatthew G. Knepley params[1] = 0.0075 * tessSize; 2158c1cad2e7SMatthew G. Knepley params[2] = 15.0; 2159c1cad2e7SMatthew G. Knepley 21605552b385SBrandon if (islite) { 21615552b385SBrandon PetscCall(EGlite_makeTessBody(body, params, &tessArray[b])); 21625552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 21635552b385SBrandon } else { 21649566063dSJacob Faibussowitsch PetscCall(EG_makeTessBody(body, params, &tessArray[b])); 21659566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 21665552b385SBrandon } 2167c1cad2e7SMatthew G. Knepley 2168c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 2169c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 2170c1cad2e7SMatthew G. Knepley int len, fID, ntris; 2171c1cad2e7SMatthew G. Knepley const int *ptype, *pindex, *ptris, *ptric; 2172c1cad2e7SMatthew G. Knepley const double *pxyz, *puv; 2173c1cad2e7SMatthew G. Knepley 2174c1cad2e7SMatthew G. Knepley // Get Face ID // 21755552b385SBrandon if (islite) { 21765552b385SBrandon fID = EGlite_indexBodyTopo(body, face); 21775552b385SBrandon } else { 2178c1cad2e7SMatthew G. Knepley fID = EG_indexBodyTopo(body, face); 21795552b385SBrandon } 2180c1cad2e7SMatthew G. Knepley 2181c1cad2e7SMatthew G. Knepley // Checkout the Surface Tessellation // 21825552b385SBrandon if (islite) { 21835552b385SBrandon PetscCall(EGlite_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 21845552b385SBrandon } else { 21859566063dSJacob Faibussowitsch PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 21865552b385SBrandon } 2187c1cad2e7SMatthew G. Knepley 2188c1cad2e7SMatthew G. Knepley // Determine total number of triangle cells in the tessellation // 2189c1cad2e7SMatthew G. Knepley bodyNumTris += (int)ntris; 2190c1cad2e7SMatthew G. Knepley 2191c1cad2e7SMatthew G. Knepley // Check out the point index and coordinate // 2192c1cad2e7SMatthew G. Knepley for (int p = 0; p < len; ++p) { 2193c1cad2e7SMatthew G. Knepley int global; 2194c1cad2e7SMatthew G. Knepley 21955552b385SBrandon if (islite) { 21965552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, p + 1, &global)); 21975552b385SBrandon } else { 21989566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global)); 21995552b385SBrandon } 2200c1cad2e7SMatthew G. Knepley 2201c1cad2e7SMatthew G. Knepley // Determine the total number of points in the tessellation // 2202c1cad2e7SMatthew G. Knepley bodyNumPoints = PetscMax(bodyNumPoints, global); 2203c1cad2e7SMatthew G. Knepley } 2204c1cad2e7SMatthew G. Knepley } 22055552b385SBrandon if (islite) { 22065552b385SBrandon EGlite_free(fobjs); 22075552b385SBrandon } else { 2208c1cad2e7SMatthew G. Knepley EG_free(fobjs); 22095552b385SBrandon } 2210c1cad2e7SMatthew G. Knepley 2211c1cad2e7SMatthew G. Knepley totalNumPoints += bodyNumPoints; 2212c1cad2e7SMatthew G. Knepley totalNumTris += bodyNumTris; 2213c1cad2e7SMatthew G. Knepley } 2214c1cad2e7SMatthew G. Knepley 2215c1cad2e7SMatthew G. Knepley dim = 2; 2216c1cad2e7SMatthew G. Knepley cdim = 3; 2217c1cad2e7SMatthew G. Knepley numCorners = 3; 2218c1cad2e7SMatthew G. Knepley 2219c1cad2e7SMatthew G. Knepley /* NEED TO DEFINE MATRICES/VECTORS TO STORE GEOM REFERENCE DATA */ 2220c1cad2e7SMatthew G. Knepley /* Fill in below and use to define DMLabels after DMPlex creation */ 22219566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(totalNumPoints * cdim, &coords, totalNumTris * numCorners, &cells)); 2222c1cad2e7SMatthew G. Knepley 2223c1cad2e7SMatthew G. Knepley for (b = 0; b < nbodies; ++b) { 2224c1cad2e7SMatthew G. Knepley ego body = bodies[b]; 2225c1cad2e7SMatthew G. Knepley int Nf; 2226c1cad2e7SMatthew G. Knepley PetscInt pointIndexStart; 2227c1cad2e7SMatthew G. Knepley PetscHashIter PISiter; 2228c1cad2e7SMatthew G. Knepley PetscBool PISfound; 2229c1cad2e7SMatthew G. Knepley 22309566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound)); 22315552b385SBrandon PetscCheck(PISfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in pointIndexStartMap", b); 22329566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pointIndexStartMap, b, &pointIndexStart)); 2233c1cad2e7SMatthew G. Knepley 22345552b385SBrandon if (islite) { 22355552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 22365552b385SBrandon } else { 22379566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 22385552b385SBrandon } 2239c1cad2e7SMatthew G. Knepley 2240c1cad2e7SMatthew G. Knepley for (int f = 0; f < Nf; ++f) { 2241c1cad2e7SMatthew G. Knepley /* Get Face Object */ 2242c1cad2e7SMatthew G. Knepley ego face = fobjs[f]; 2243c1cad2e7SMatthew G. Knepley int len, fID, ntris; 2244c1cad2e7SMatthew G. Knepley const int *ptype, *pindex, *ptris, *ptric; 2245c1cad2e7SMatthew G. Knepley const double *pxyz, *puv; 2246c1cad2e7SMatthew G. Knepley 2247c1cad2e7SMatthew G. Knepley /* Get Face ID */ 22485552b385SBrandon if (islite) { 22495552b385SBrandon fID = EGlite_indexBodyTopo(body, face); 22505552b385SBrandon } else { 2251c1cad2e7SMatthew G. Knepley fID = EG_indexBodyTopo(body, face); 22525552b385SBrandon } 2253c1cad2e7SMatthew G. Knepley 2254c1cad2e7SMatthew G. Knepley /* Checkout the Surface Tessellation */ 22555552b385SBrandon if (islite) { 22565552b385SBrandon PetscCall(EGlite_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 22575552b385SBrandon } else { 22589566063dSJacob Faibussowitsch PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 22595552b385SBrandon } 2260c1cad2e7SMatthew G. Knepley 2261c1cad2e7SMatthew G. Knepley /* Check out the point index and coordinate */ 2262c1cad2e7SMatthew G. Knepley for (int p = 0; p < len; ++p) { 2263c1cad2e7SMatthew G. Knepley int global; 2264c1cad2e7SMatthew G. Knepley PetscHashIter PTLiter, PILiter, PBLiter; 2265c1cad2e7SMatthew G. Knepley PetscBool PTLfound, PILfound, PBLfound; 2266c1cad2e7SMatthew G. Knepley 22675552b385SBrandon if (islite) { 22685552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, p + 1, &global)); 22695552b385SBrandon } else { 22709566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global)); 22715552b385SBrandon } 2272c1cad2e7SMatthew G. Knepley 2273c1cad2e7SMatthew G. Knepley /* Set the coordinates array for DAG */ 2274c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 0] = pxyz[(p * 3) + 0]; 2275c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 1] = pxyz[(p * 3) + 1]; 2276c1cad2e7SMatthew G. Knepley coords[((global - 1 + pointIndexStart) * 3) + 2] = pxyz[(p * 3) + 2]; 2277c1cad2e7SMatthew G. Knepley 2278c1cad2e7SMatthew G. Knepley /* Store Geometry Label Information for DMLabel assignment later */ 22799566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pTypeLabelMap, global - 1 + pointIndexStart, &PTLiter, &PTLfound)); 22809566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pIndexLabelMap, global - 1 + pointIndexStart, &PILiter, &PILfound)); 22819566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pBodyIndexLabelMap, global - 1 + pointIndexStart, &PBLiter, &PBLfound)); 2282c1cad2e7SMatthew G. Knepley 22839566063dSJacob Faibussowitsch if (!PTLfound) PetscCall(PetscHMapISet(pTypeLabelMap, global - 1 + pointIndexStart, ptype[p])); 22849566063dSJacob Faibussowitsch if (!PILfound) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, pindex[p])); 22859566063dSJacob Faibussowitsch if (!PBLfound) PetscCall(PetscHMapISet(pBodyIndexLabelMap, global - 1 + pointIndexStart, b)); 2286c1cad2e7SMatthew G. Knepley 22879566063dSJacob Faibussowitsch if (ptype[p] < 0) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, fID)); 2288c1cad2e7SMatthew G. Knepley } 2289c1cad2e7SMatthew G. Knepley 2290c1cad2e7SMatthew G. Knepley for (int t = 0; t < (int)ntris; ++t) { 2291c1cad2e7SMatthew G. Knepley int global, globalA, globalB; 2292c1cad2e7SMatthew G. Knepley PetscHashIter TFLiter, TBLiter; 2293c1cad2e7SMatthew G. Knepley PetscBool TFLfound, TBLfound; 2294c1cad2e7SMatthew G. Knepley 22955552b385SBrandon if (islite) { 22965552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global)); 22975552b385SBrandon } else { 22989566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global)); 22995552b385SBrandon } 2300c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 0] = global - 1 + pointIndexStart; 2301c1cad2e7SMatthew G. Knepley 23025552b385SBrandon if (islite) { 23035552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA)); 23045552b385SBrandon } else { 23059566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA)); 23065552b385SBrandon } 2307c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 1] = globalA - 1 + pointIndexStart; 2308c1cad2e7SMatthew G. Knepley 23095552b385SBrandon if (islite) { 23105552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB)); 23115552b385SBrandon } else { 23129566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB)); 23135552b385SBrandon } 2314c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 2] = globalB - 1 + pointIndexStart; 2315c1cad2e7SMatthew G. Knepley 23169566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triFaceIDLabelMap, counter, &TFLiter, &TFLfound)); 23179566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triBodyIDLabelMap, counter, &TBLiter, &TBLfound)); 2318c1cad2e7SMatthew G. Knepley 23199566063dSJacob Faibussowitsch if (!TFLfound) PetscCall(PetscHMapISet(triFaceIDLabelMap, counter, fID)); 23209566063dSJacob Faibussowitsch if (!TBLfound) PetscCall(PetscHMapISet(triBodyIDLabelMap, counter, b)); 2321c1cad2e7SMatthew G. Knepley 2322c1cad2e7SMatthew G. Knepley counter += 1; 2323c1cad2e7SMatthew G. Knepley } 2324c1cad2e7SMatthew G. Knepley } 23255552b385SBrandon if (islite) { 23265552b385SBrandon EGlite_free(fobjs); 23275552b385SBrandon } else { 2328c1cad2e7SMatthew G. Knepley EG_free(fobjs); 2329c1cad2e7SMatthew G. Knepley } 2330c1cad2e7SMatthew G. Knepley } 23315552b385SBrandon PetscCall(PetscFree(tessArray)); 23325552b385SBrandon } 2333c1cad2e7SMatthew G. Knepley 2334c1cad2e7SMatthew G. Knepley //Build DMPlex 23359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, totalNumTris, totalNumPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 23369566063dSJacob Faibussowitsch PetscCall(PetscFree2(coords, cells)); 2337c1cad2e7SMatthew G. Knepley 2338c1cad2e7SMatthew G. Knepley // Embed EGADS model in DM 2339c1cad2e7SMatthew G. Knepley { 2340c1cad2e7SMatthew G. Knepley PetscContainer modelObj, contextObj; 2341c1cad2e7SMatthew G. Knepley 23429566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 23439566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(modelObj, model)); 23445552b385SBrandon if (islite) { 23455552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSliteDestroy_Private)); 23465552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Model", (PetscObject)modelObj)); 23475552b385SBrandon } else { 23485552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSDestroy_Private)); 23499566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 23505552b385SBrandon } 23519566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj)); 2352c1cad2e7SMatthew G. Knepley 23539566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 23549566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context)); 23555552b385SBrandon 23565552b385SBrandon if (islite) { 23575552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSliteClose_Private)); 23585552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Context", (PetscObject)contextObj)); 23595552b385SBrandon } else { 23605552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSClose_Private)); 23619566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 23625552b385SBrandon } 23639566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&contextObj)); 2364c1cad2e7SMatthew G. Knepley } 2365c1cad2e7SMatthew G. Knepley 2366c1cad2e7SMatthew G. Knepley // Label Points 23679566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 23689566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 23699566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 23709566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 23719566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 23729566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 23739566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 23749566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 2375c1cad2e7SMatthew G. Knepley 2376c1cad2e7SMatthew G. Knepley /* Get Number of DAG Nodes at each level */ 2377c1cad2e7SMatthew G. Knepley int fStart, fEnd, eStart, eEnd, nStart, nEnd; 2378c1cad2e7SMatthew G. Knepley 23799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &fStart, &fEnd)); 23809566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &eStart, &eEnd)); 23819566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd)); 2382c1cad2e7SMatthew G. Knepley 2383c1cad2e7SMatthew G. Knepley /* Set DMLabels for NODES */ 2384c1cad2e7SMatthew G. Knepley for (int n = nStart; n < nEnd; ++n) { 2385c1cad2e7SMatthew G. Knepley int pTypeVal, pIndexVal, pBodyVal; 2386c1cad2e7SMatthew G. Knepley PetscHashIter PTLiter, PILiter, PBLiter; 2387c1cad2e7SMatthew G. Knepley PetscBool PTLfound, PILfound, PBLfound; 2388c1cad2e7SMatthew G. Knepley 2389c1cad2e7SMatthew G. Knepley //Converted to Hash Tables 23909566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pTypeLabelMap, n - nStart, &PTLiter, &PTLfound)); 23915552b385SBrandon PetscCheck(PTLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pTypeLabelMap", n); 23929566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pTypeLabelMap, n - nStart, &pTypeVal)); 2393c1cad2e7SMatthew G. Knepley 23949566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pIndexLabelMap, n - nStart, &PILiter, &PILfound)); 23955552b385SBrandon PetscCheck(PILfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pIndexLabelMap", n); 23969566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pIndexLabelMap, n - nStart, &pIndexVal)); 2397c1cad2e7SMatthew G. Knepley 23989566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(pBodyIndexLabelMap, n - nStart, &PBLiter, &PBLfound)); 23995552b385SBrandon PetscCheck(PBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pBodyLabelMap", n); 24009566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(pBodyIndexLabelMap, n - nStart, &pBodyVal)); 2401c1cad2e7SMatthew G. Knepley 24029566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, n, pBodyVal)); 24039566063dSJacob Faibussowitsch if (pTypeVal == 0) PetscCall(DMLabelSetValue(vertexLabel, n, pIndexVal)); 24049566063dSJacob Faibussowitsch if (pTypeVal > 0) PetscCall(DMLabelSetValue(edgeLabel, n, pIndexVal)); 24059566063dSJacob Faibussowitsch if (pTypeVal < 0) PetscCall(DMLabelSetValue(faceLabel, n, pIndexVal)); 2406c1cad2e7SMatthew G. Knepley } 2407c1cad2e7SMatthew G. Knepley 2408c1cad2e7SMatthew G. Knepley /* Set DMLabels for Edges - Based on the DMLabels of the EDGE's NODES */ 2409c1cad2e7SMatthew G. Knepley for (int e = eStart; e < eEnd; ++e) { 2410c1cad2e7SMatthew G. Knepley int bodyID_0, vertexID_0, vertexID_1, edgeID_0, edgeID_1, faceID_0, faceID_1; 2411c1cad2e7SMatthew G. Knepley 24129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 24139566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, cone[0], &bodyID_0)); // Do I need to check the other end? 24149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, cone[0], &vertexID_0)); 24159566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, cone[1], &vertexID_1)); 24169566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[0], &edgeID_0)); 24179566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[1], &edgeID_1)); 24189566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, cone[0], &faceID_0)); 24199566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, cone[1], &faceID_1)); 2420c1cad2e7SMatthew G. Knepley 24219566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, e, bodyID_0)); 2422c1cad2e7SMatthew G. Knepley 24239566063dSJacob Faibussowitsch if (edgeID_0 == edgeID_1) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0)); 24249566063dSJacob Faibussowitsch else if (vertexID_0 > 0 && edgeID_1 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_1)); 24259566063dSJacob Faibussowitsch else if (vertexID_1 > 0 && edgeID_0 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0)); 2426c1cad2e7SMatthew G. Knepley else { /* Do Nothing */ } 2427c1cad2e7SMatthew G. Knepley } 2428c1cad2e7SMatthew G. Knepley 2429c1cad2e7SMatthew G. Knepley /* Set DMLabels for Cells */ 2430c1cad2e7SMatthew G. Knepley for (int f = fStart; f < fEnd; ++f) { 2431c1cad2e7SMatthew G. Knepley int edgeID_0; 2432c1cad2e7SMatthew G. Knepley PetscInt triBodyVal, triFaceVal; 2433c1cad2e7SMatthew G. Knepley PetscHashIter TFLiter, TBLiter; 2434c1cad2e7SMatthew G. Knepley PetscBool TFLfound, TBLfound; 2435c1cad2e7SMatthew G. Knepley 2436c1cad2e7SMatthew G. Knepley // Convert to Hash Table 24379566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triFaceIDLabelMap, f - fStart, &TFLiter, &TFLfound)); 24385552b385SBrandon PetscCheck(TFLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in triFaceIDLabelMap", f); 24399566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(triFaceIDLabelMap, f - fStart, &triFaceVal)); 2440c1cad2e7SMatthew G. Knepley 24419566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(triBodyIDLabelMap, f - fStart, &TBLiter, &TBLfound)); 24425552b385SBrandon PetscCheck(TBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in triBodyIDLabelMap", f); 24439566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(triBodyIDLabelMap, f - fStart, &triBodyVal)); 2444c1cad2e7SMatthew G. Knepley 24459566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, f, triBodyVal)); 24469566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, f, triFaceVal)); 2447c1cad2e7SMatthew G. Knepley 2448c1cad2e7SMatthew G. Knepley /* Finish Labeling previously unlabeled DMPlex Edges - Assumes Triangular Cell (3 Edges Max) */ 24499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, f, &cone)); 2450c1cad2e7SMatthew G. Knepley 2451c1cad2e7SMatthew G. Knepley for (int jj = 0; jj < 3; ++jj) { 24529566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, cone[jj], &edgeID_0)); 2453c1cad2e7SMatthew G. Knepley 2454c1cad2e7SMatthew G. Knepley if (edgeID_0 < 0) { 24559566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, cone[jj], triBodyVal)); 24569566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(faceLabel, cone[jj], triFaceVal)); 2457c1cad2e7SMatthew G. Knepley } 2458c1cad2e7SMatthew G. Knepley } 2459c1cad2e7SMatthew G. Knepley } 2460c1cad2e7SMatthew G. Knepley 2461c1cad2e7SMatthew G. Knepley *newdm = dm; 24623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2463c1cad2e7SMatthew G. Knepley } 24647bee2925SMatthew Knepley #endif 24657bee2925SMatthew Knepley 24665552b385SBrandon /*@C 24675552b385SBrandon DMPlexInflateToGeomModelUseXYZ - Snaps the vertex coordinates of a `DMPLEX` object representing the mesh to its geometry if some vertices depart from the model. This usually happens with non-conforming refinement. 2468c1cad2e7SMatthew G. Knepley 246920f4b53cSBarry Smith Collective 2470c1cad2e7SMatthew G. Knepley 2471c1cad2e7SMatthew G. Knepley Input Parameter: 2472a1cb98faSBarry Smith . dm - The uninflated `DM` object representing the mesh 2473c1cad2e7SMatthew G. Knepley 2474c1cad2e7SMatthew G. Knepley Level: intermediate 2475c1cad2e7SMatthew G. Knepley 24761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()` 2477c1cad2e7SMatthew G. Knepley @*/ 2478ce78bad3SBarry Smith PetscErrorCode DMPlexInflateToGeomModelUseXYZ(DM dm) PeNS 2479d71ae5a4SJacob Faibussowitsch { 2480ce78bad3SBarry Smith // please don't fucking write code like this with #ifdef all of the place! 2481c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS) 2482c1cad2e7SMatthew G. Knepley /* EGADS Variables */ 24835552b385SBrandon ego model, geom, body, face, edge, vertex; 2484c1cad2e7SMatthew G. Knepley ego *bodies; 2485c1cad2e7SMatthew G. Knepley int Nb, oclass, mtype, *senses; 24865552b385SBrandon double result[4]; 2487c1cad2e7SMatthew G. Knepley /* PETSc Variables */ 2488c1cad2e7SMatthew G. Knepley DM cdm; 2489c1cad2e7SMatthew G. Knepley PetscContainer modelObj; 2490c1cad2e7SMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 2491c1cad2e7SMatthew G. Knepley Vec coordinates; 2492c1cad2e7SMatthew G. Knepley PetscScalar *coords; 2493c1cad2e7SMatthew G. Knepley PetscInt bodyID, faceID, edgeID, vertexID; 2494c1cad2e7SMatthew G. Knepley PetscInt cdim, d, vStart, vEnd, v; 24955552b385SBrandon PetscBool islite = PETSC_FALSE; 2496c1cad2e7SMatthew G. Knepley #endif 2497c1cad2e7SMatthew G. Knepley 2498c1cad2e7SMatthew G. Knepley PetscFunctionBegin; 2499c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS) 25009566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 25015552b385SBrandon if (!modelObj) { 25025552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 25035552b385SBrandon islite = PETSC_TRUE; 25045552b385SBrandon } 25053ba16761SJacob Faibussowitsch if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 25069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 25079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 25089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 25099566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 25109566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 25119566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 25129566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 2513c1cad2e7SMatthew G. Knepley 25149566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 25155552b385SBrandon 25165552b385SBrandon if (islite) { 25175552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 25185552b385SBrandon } else { 25199566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 25205552b385SBrandon } 2521c1cad2e7SMatthew G. Knepley 25229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 25239566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 2524c1cad2e7SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 2525c1cad2e7SMatthew G. Knepley PetscScalar *vcoords; 2526c1cad2e7SMatthew G. Knepley 25279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 25289566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 25299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 25309566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 2531c1cad2e7SMatthew G. Knepley 25325552b385SBrandon PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bodyID, Nb); 25335552b385SBrandon body = bodies[bodyID]; 25345552b385SBrandon 25355552b385SBrandon PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 25365552b385SBrandon if (vertexID > 0) { 25375552b385SBrandon if (islite) { 25385552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 25395552b385SBrandon PetscCall(EGlite_evaluate(vertex, NULL, result)); 25405552b385SBrandon } else { 25415552b385SBrandon PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 25425552b385SBrandon PetscCall(EG_evaluate(vertex, NULL, result)); 25435552b385SBrandon } 25445552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 25455552b385SBrandon } else if (edgeID > 0) { 25465552b385SBrandon /* Snap to EDGE at nearest location */ 25475552b385SBrandon double params[1]; 25485552b385SBrandon if (islite) { 25495552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 25505552b385SBrandon PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 25515552b385SBrandon } // Get (x,y,z) of nearest point on EDGE 25525552b385SBrandon else { 25535552b385SBrandon PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 25545552b385SBrandon PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 25555552b385SBrandon } 25565552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 25575552b385SBrandon } else if (faceID > 0) { 25585552b385SBrandon /* Snap to FACE at nearest location */ 25595552b385SBrandon double params[2]; 25605552b385SBrandon if (islite) { 25615552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 25625552b385SBrandon PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 25635552b385SBrandon } // Get (x,y,z) of nearest point on FACE 25645552b385SBrandon else { 25655552b385SBrandon PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 25665552b385SBrandon PetscCall(EG_invEvaluate(face, vcoords, params, result)); 25675552b385SBrandon } 25685552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 25695552b385SBrandon } 25705552b385SBrandon } 25715552b385SBrandon PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 25725552b385SBrandon /* Clear out global coordinates */ 25735552b385SBrandon PetscCall(VecDestroy(&dm->coordinates[0].x)); 25745552b385SBrandon #endif 25755552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 25765552b385SBrandon } 25775552b385SBrandon 25785552b385SBrandon #if defined(PETSC_HAVE_EGADS) 25795552b385SBrandon // This replaces the model in-place 2580ce78bad3SBarry Smith PetscErrorCode ConvertGeomModelToAllBSplines(PetscBool islite, ego *model) PeNS 25815552b385SBrandon { 25825552b385SBrandon /* EGADS/EGADSlite Variables */ 25835552b385SBrandon ego context = NULL, geom, *bodies, *fobjs; 25845552b385SBrandon int oclass, mtype; 25855552b385SBrandon int *senses; 25865552b385SBrandon int Nb, Nf; 25875552b385SBrandon 25885552b385SBrandon PetscFunctionBegin; 25895552b385SBrandon // Get the number of bodies and body objects in the model 25905552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 25915552b385SBrandon else PetscCallEGADS(EG_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 25925552b385SBrandon 25935552b385SBrandon // Get all Faces on the body <-- Only working with 1 body at the moment. 25945552b385SBrandon ego body = bodies[0]; 25955552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 25965552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 25975552b385SBrandon ego newGeom[Nf]; 25985552b385SBrandon ego newFaces[Nf]; 25995552b385SBrandon 26005552b385SBrandon // Convert the 1st Face to a BSpline Geometry 26015552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 26025552b385SBrandon ego face = fobjs[ii]; 26035552b385SBrandon ego gRef, gPrev, gNext, *lobjs; 26045552b385SBrandon int goclass, gmtype, *gpinfo; 26055552b385SBrandon int Nl, *lsenses; 26065552b385SBrandon double *gprv; 26075552b385SBrandon char *gClass = (char *)"", *gType = (char *)""; 26085552b385SBrandon 26095552b385SBrandon /* Shape Optimization is NOT available for EGADSlite geometry files. */ 26105552b385SBrandon /* Note :: islite options are left below in case future versions of EGADSlite includes this capability */ 26115552b385SBrandon PetscCheck(!islite, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot convert geometric entities to all BSplines for geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep"); 26125552b385SBrandon 26135552b385SBrandon if (islite) { 26145552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_ 26155552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info 26165552b385SBrandon PetscCallEGADS(EGlite_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 26175552b385SBrandon } // Get geometry info 26185552b385SBrandon else { 26195552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_ 26205552b385SBrandon PetscCallEGADS(EG_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info 26215552b385SBrandon PetscCallEGADS(EG_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 26225552b385SBrandon } // Get geometry info 26235552b385SBrandon 26245552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType)); // Decode Geometry integers 26255552b385SBrandon 26265552b385SBrandon // Convert current FACE to a BSpline Surface 26275552b385SBrandon ego bspline; 26285552b385SBrandon ego bRef, bPrev, bNext; 26295552b385SBrandon int boclass, bmtype, *bpinfo; 26305552b385SBrandon double *bprv; 26315552b385SBrandon char *bClass = (char *)"", *bType = (char *)""; 26325552b385SBrandon 26335552b385SBrandon PetscCallEGADS(EG_convertToBSpline, (face, &bspline)); // Does not have an EGlite_ version 26345552b385SBrandon 26355552b385SBrandon if (islite) { 26365552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info 26375552b385SBrandon PetscCallEGADS(EGlite_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 26385552b385SBrandon } // Get geometry info 26395552b385SBrandon else { 26405552b385SBrandon PetscCallEGADS(EG_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info 26415552b385SBrandon PetscCallEGADS(EG_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 26425552b385SBrandon } // Get geometry info 26435552b385SBrandon 26445552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(boclass, bmtype, &bClass, &bType)); // Decode Geometry integers 26455552b385SBrandon 26465552b385SBrandon // Get Context from FACE 26475552b385SBrandon context = NULL; 26485552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version 26495552b385SBrandon 26505552b385SBrandon // Silence WARNING Regarding OPENCASCADE 7.5 26515552b385SBrandon if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 0)); 26525552b385SBrandon else PetscCallEGADS(EG_setOutLevel, (context, 0)); 26535552b385SBrandon 26545552b385SBrandon ego newgeom; 26555552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version 26565552b385SBrandon 26575552b385SBrandon PetscCallEGADS(EG_deleteObject, (bspline)); 26585552b385SBrandon 26595552b385SBrandon // Create new FACE based on new SURFACE geometry 26605552b385SBrandon double data[4]; 26615552b385SBrandon int periodic; 26625552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 26635552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 26645552b385SBrandon 26655552b385SBrandon ego newface; 26665552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version 26675552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newgeom)); 26685552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newface)); 26695552b385SBrandon newFaces[ii] = newface; 26705552b385SBrandon newGeom[ii] = newgeom; 26715552b385SBrandon 26725552b385SBrandon // Reinstate WARNING Regarding OPENCASCADE 7.5 26735552b385SBrandon if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 1)); 26745552b385SBrandon else PetscCallEGADS(EG_setOutLevel, (context, 1)); 26755552b385SBrandon } 26765552b385SBrandon 26775552b385SBrandon // Sew New Faces together to get a new model 26785552b385SBrandon ego newmodel; 26795552b385SBrandon PetscCallEGADS(EG_sewFaces, (Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version 26805552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 26815552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[ii])); 26825552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[ii])); 26835552b385SBrandon } 26845552b385SBrandon PetscCallEGADS(EG_deleteObject, (*model)); 26855552b385SBrandon *model = newmodel; 26865552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 26875552b385SBrandon } 26885552b385SBrandon #endif 26895552b385SBrandon 26905552b385SBrandon /*@C 26915552b385SBrandon DMPlexCreateGeomFromFile - Create a `DMPLEX` mesh from an EGADS, IGES, or STEP file. 26925552b385SBrandon 26935552b385SBrandon Collective 26945552b385SBrandon 26955552b385SBrandon Input Parameters: 26965552b385SBrandon + comm - The MPI communicator 26975552b385SBrandon . filename - The name of the EGADS, IGES, or STEP file 26985552b385SBrandon - islite - Flag for EGADSlite support 26995552b385SBrandon 27005552b385SBrandon Output Parameter: 27015552b385SBrandon . dm - The `DM` object representing the mesh 27025552b385SBrandon 27035552b385SBrandon Level: beginner 27045552b385SBrandon 27055552b385SBrandon .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`, `DMPlexCreateEGADSliteFromFile()` 27065552b385SBrandon @*/ 2707ce78bad3SBarry Smith PetscErrorCode DMPlexCreateGeomFromFile(MPI_Comm comm, const char filename[], DM *dm, PetscBool islite) PeNS 27085552b385SBrandon { 27095552b385SBrandon /* PETSc Variables */ 27105552b385SBrandon PetscMPIInt rank; 27115552b385SBrandon PetscBool printModel = PETSC_FALSE, tessModel = PETSC_FALSE, newModel = PETSC_FALSE; 27125552b385SBrandon PetscBool shapeOpt = PETSC_FALSE; 27135552b385SBrandon 27145552b385SBrandon #if defined(PETSC_HAVE_EGADS) 27155552b385SBrandon ego context = NULL, model = NULL; 27165552b385SBrandon #endif 27175552b385SBrandon 27185552b385SBrandon PetscFunctionBegin; 27195552b385SBrandon PetscAssertPointer(filename, 2); 27205552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_print_model", &printModel, NULL)); 27215552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_tess_model", &tessModel, NULL)); 27225552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_new_model", &newModel, NULL)); 27235552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_shape_opt", &shapeOpt, NULL)); 27245552b385SBrandon PetscCallMPI(MPI_Comm_rank(comm, &rank)); 27255552b385SBrandon #if defined(PETSC_HAVE_EGADS) 27265552b385SBrandon if (rank == 0) { 27275552b385SBrandon /* EGADSlite files cannot be used for Shape Optimization Work. It lacks the ability to make new geometry. */ 27285552b385SBrandon /* Must use EGADS, STEP, IGES or BRep files to perform this work. */ 27295552b385SBrandon if (islite) { 27305552b385SBrandon PetscCallEGADS(EGlite_open, (&context)); 27315552b385SBrandon PetscCallEGADS(EGlite_loadModel, (context, 0, filename, &model)); 27325552b385SBrandon if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model)); 27335552b385SBrandon if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite)); 27345552b385SBrandon } else { 27355552b385SBrandon PetscCallEGADS(EG_open, (&context)); 27365552b385SBrandon PetscCallEGADS(EG_loadModel, (context, 0, filename, &model)); 27375552b385SBrandon if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model)); 27385552b385SBrandon if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite)); 27395552b385SBrandon } 27405552b385SBrandon } 27415552b385SBrandon if (tessModel) PetscCall(DMPlexCreateGeom_Tess_Internal(comm, context, model, dm, islite)); 27425552b385SBrandon else if (newModel) PetscCall(DMPlexCreateGeom_Internal(comm, context, model, dm, islite)); 27435552b385SBrandon else { 27445552b385SBrandon PetscCall(DMPlexCreateGeom(comm, context, model, dm, islite)); 27455552b385SBrandon } 27465552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 27475552b385SBrandon #else 27485552b385SBrandon SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 27495552b385SBrandon #endif 27505552b385SBrandon } 27515552b385SBrandon 27525552b385SBrandon #if defined(PETSC_HAVE_EGADS) 27535552b385SBrandon /*@C 27545552b385SBrandon DMPlex_Surface_Grad - Exposes the Geometry's Control Points and Weights and Calculates the Mesh Topology Boundary Nodes Gradient 27555552b385SBrandon with respect the associated geometry's Control Points and Weights. 27565552b385SBrandon 27575552b385SBrandon // ----- Depreciated ---- See DMPlexGeomDataAndGrads ------ // 27585552b385SBrandon 27595552b385SBrandon Collective 27605552b385SBrandon 27615552b385SBrandon Input Parameters: 27625552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 27635552b385SBrandon 27645552b385SBrandon Output Parameter: 27655552b385SBrandon . dm - The DM object representing the mesh with PetscContainers containing the EGADS geometry model, Array-Hash Table Geometry Control Point Pair, Array-Hash Table Geometry Weights Pair and Matrix-Hash Table Surface Gradient Pair 27665552b385SBrandon 27675552b385SBrandon Level: intermediate 27685552b385SBrandon 27695552b385SBrandon .seealso: 27705552b385SBrandon @*/ 27715552b385SBrandon PetscErrorCode DMPlex_Surface_Grad(DM dm) 27725552b385SBrandon { 27735552b385SBrandon ego model, geom, *bodies, *fobjs; 27745552b385SBrandon PetscContainer modelObj; 27755552b385SBrandon int oclass, mtype, *senses; 27765552b385SBrandon int Nb, Nf; 27775552b385SBrandon PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 27785552b385SBrandon PetscHMapI pointSurfGradRow_Start = NULL; 27795552b385SBrandon Mat pointSurfGrad; 27805552b385SBrandon IS faceLabelValues, edgeLabelValues, vertexLabelValues; 27815552b385SBrandon PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 27825552b385SBrandon PetscBool islite = PETSC_FALSE; 27835552b385SBrandon 27845552b385SBrandon PetscFunctionBegin; 27855552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 27865552b385SBrandon if (!modelObj) { 27875552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 27885552b385SBrandon islite = PETSC_TRUE; 27895552b385SBrandon SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, " Cannot provide geometric data or associated calculated gradients for geometries defined by EGADSlite (.egadslite)! \n Please use another geometry file format STEP, IGES, EGADS or BRep"); 27905552b385SBrandon } 27915552b385SBrandon 27925552b385SBrandon // Get attached EGADS model (pointer) 27935552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 27945552b385SBrandon 27955552b385SBrandon // Get the bodies in the model 27965552b385SBrandon if (islite) { 27975552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 27985552b385SBrandon } else { 27995552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 28005552b385SBrandon } 28015552b385SBrandon 28025552b385SBrandon ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 28035552b385SBrandon 28045552b385SBrandon // Get the total number of FACEs in the model 28055552b385SBrandon if (islite) { 28065552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 28075552b385SBrandon } else { 28085552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 28095552b385SBrandon } 28105552b385SBrandon 28115552b385SBrandon // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 28125552b385SBrandon // This will provide the total number of DMPlex points on the boundary of the geometry 28135552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 28145552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 28155552b385SBrandon 28165552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 28175552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 28185552b385SBrandon 28195552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 28205552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 28215552b385SBrandon 28225552b385SBrandon const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 28235552b385SBrandon PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 28245552b385SBrandon PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 28255552b385SBrandon PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 28265552b385SBrandon 28275552b385SBrandon // Get the points associated with each FACE, EDGE and VERTEX label in the DM 28285552b385SBrandon PetscInt totalNumPoints = 0; 28295552b385SBrandon for (int ii = 0; ii < faceLabelSize; ++ii) { 28305552b385SBrandon // Cycle through FACE labels 28315552b385SBrandon PetscInt size; 28325552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[ii], &size)); 28335552b385SBrandon totalNumPoints += size; 28345552b385SBrandon } 28355552b385SBrandon PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 28365552b385SBrandon PetscCall(ISDestroy(&faceLabelValues)); 28375552b385SBrandon 28385552b385SBrandon for (int ii = 0; ii < edgeLabelSize; ++ii) { 28395552b385SBrandon // Cycle Through EDGE Labels 28405552b385SBrandon PetscInt size; 28415552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[ii], &size)); 28425552b385SBrandon totalNumPoints += size; 28435552b385SBrandon } 28445552b385SBrandon PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 28455552b385SBrandon PetscCall(ISDestroy(&edgeLabelValues)); 28465552b385SBrandon 28475552b385SBrandon for (int ii = 0; ii < vertexLabelSize; ++ii) { 28485552b385SBrandon // Cycle Through VERTEX Labels 28495552b385SBrandon PetscInt size; 28505552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 28515552b385SBrandon totalNumPoints += size; 28525552b385SBrandon } 28535552b385SBrandon PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 28545552b385SBrandon PetscCall(ISDestroy(&vertexLabelValues)); 28555552b385SBrandon 28565552b385SBrandon int maxNumCPs = 0; 28575552b385SBrandon int totalNumCPs = 0; 28585552b385SBrandon ego bRef, bPrev, bNext, fgeom, *lobjs; 28595552b385SBrandon int id, boclass, bmtype, *bpinfo; 28605552b385SBrandon int foclass, fmtype, Nl, *lsenses; 28615552b385SBrandon double *bprv; 28625552b385SBrandon double fdata[4]; 28635552b385SBrandon 28645552b385SBrandon // Create Hash Tables 28655552b385SBrandon PetscInt cntr = 0, wcntr = 0; 28665552b385SBrandon PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 28675552b385SBrandon PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 28685552b385SBrandon 28695552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 28705552b385SBrandon // Need to get the maximum number of Control Points defining the FACEs 28715552b385SBrandon ego face = fobjs[ii]; 28725552b385SBrandon int maxNumCPs_temp; 28735552b385SBrandon 28745552b385SBrandon if (islite) { 28755552b385SBrandon id = EGlite_indexBodyTopo(body, face); 28765552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 28775552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 28785552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 28795552b385SBrandon } else { 28805552b385SBrandon id = EG_indexBodyTopo(body, face); 28815552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 28825552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 28835552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 28845552b385SBrandon } 28855552b385SBrandon 28865552b385SBrandon maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 28875552b385SBrandon totalNumCPs += bpinfo[2] * bpinfo[5]; 28885552b385SBrandon 28895552b385SBrandon if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 28905552b385SBrandon } 28915552b385SBrandon 28925552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 28935552b385SBrandon PetscInt cpCoordDataLength = 3 * totalNumCPs; 28945552b385SBrandon PetscInt wDataLength = totalNumCPs; 28955552b385SBrandon cpCoordDataLengthPtr = &cpCoordDataLength; 28965552b385SBrandon wDataLengthPtr = &wDataLength; 28975552b385SBrandon PetscScalar *cntrlPtCoords, *cntrlPtWeights; 28985552b385SBrandon PetscMalloc1(cpCoordDataLength, &cntrlPtCoords); 28995552b385SBrandon PetscMalloc1(wDataLength, &cntrlPtWeights); 29005552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 29015552b385SBrandon // Need to Populate Control Point Coordinates and Weight Vectors 29025552b385SBrandon ego face = fobjs[ii]; 29035552b385SBrandon PetscHashIter hashKeyIter, wHashKeyIter; 29045552b385SBrandon PetscBool hashKeyFound, wHashKeyFound; 29055552b385SBrandon 29065552b385SBrandon if (islite) { 29075552b385SBrandon id = EGlite_indexBodyTopo(body, face); 29085552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 29095552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 29105552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 29115552b385SBrandon } else { 29125552b385SBrandon id = EG_indexBodyTopo(body, face); 29135552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 29145552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 29155552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 29165552b385SBrandon } 29175552b385SBrandon 29185552b385SBrandon // Store Face ID to 1st Row of Control Point Vector 29195552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 29205552b385SBrandon 29215552b385SBrandon if (!hashKeyFound) { PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); } 29225552b385SBrandon 29235552b385SBrandon int offsetCoord = bpinfo[3] + bpinfo[6]; 29245552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 29255552b385SBrandon cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 29265552b385SBrandon cntr += 1; 29275552b385SBrandon } 29285552b385SBrandon 29295552b385SBrandon // Store Face ID to 1st Row of Control Point Weight Vector 29305552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 29315552b385SBrandon 29325552b385SBrandon if (!wHashKeyFound) { PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); } 29335552b385SBrandon 29345552b385SBrandon int offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 29355552b385SBrandon for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 29365552b385SBrandon cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 29375552b385SBrandon wcntr += 1; 29385552b385SBrandon } 29395552b385SBrandon } 29405552b385SBrandon 29415552b385SBrandon // Attach Control Point and Weight Data to DM 29425552b385SBrandon { 29435552b385SBrandon PetscContainer cpOrgObj, cpCoordObj, cpCoordLengthObj; 29445552b385SBrandon PetscContainer wOrgObj, wValObj, wDataLengthObj; 29455552b385SBrandon 29465552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 29475552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 29485552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 29495552b385SBrandon PetscCall(PetscContainerDestroy(&cpOrgObj)); 29505552b385SBrandon 29515552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordObj)); 29525552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordObj, cntrlPtCoords)); 29535552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cpCoordObj)); 29545552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordObj)); 29555552b385SBrandon 29565552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 29575552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 29585552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 29595552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 29605552b385SBrandon 29615552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 29625552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 29635552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 29645552b385SBrandon PetscCall(PetscContainerDestroy(&wOrgObj)); 29655552b385SBrandon 29665552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wValObj)); 29675552b385SBrandon PetscCall(PetscContainerSetPointer(wValObj, cntrlPtWeights)); 29685552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)wValObj)); 29695552b385SBrandon PetscCall(PetscContainerDestroy(&wValObj)); 29705552b385SBrandon 29715552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 29725552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 29735552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 29745552b385SBrandon PetscCall(PetscContainerDestroy(&wDataLengthObj)); 29755552b385SBrandon } 29765552b385SBrandon 29775552b385SBrandon // Define Matrix to store Surface Gradient information dx_i/dCPj_i 29785552b385SBrandon PetscInt gcntr = 0; 29795552b385SBrandon const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 29805552b385SBrandon const PetscInt colSize = 4 * Nf; 29815552b385SBrandon 29825552b385SBrandon // Create Point Surface Gradient Matrix 29835552b385SBrandon MatCreate(PETSC_COMM_WORLD, &pointSurfGrad); 29845552b385SBrandon MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize); 29855552b385SBrandon MatSetType(pointSurfGrad, MATAIJ); 29865552b385SBrandon MatSetUp(pointSurfGrad); 29875552b385SBrandon 29885552b385SBrandon // Create Hash Table to store Point's stare row in surfaceGrad[][] 29895552b385SBrandon PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 29905552b385SBrandon 29915552b385SBrandon // Get Coordinates for the DMPlex point 29925552b385SBrandon DM cdm; 29935552b385SBrandon PetscInt dE, Nv; 29945552b385SBrandon Vec coordinatesLocal; 29955552b385SBrandon PetscScalar *coords = NULL; 29965552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 29975552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &dE)); 29985552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 29995552b385SBrandon 30005552b385SBrandon // CYCLE THROUGH FACEs 30015552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 30025552b385SBrandon ego face = fobjs[ii]; 30035552b385SBrandon ego *eobjs, *nobjs; 30045552b385SBrandon PetscInt fid, Ne, Nn; 30055552b385SBrandon DMLabel faceLabel, edgeLabel, nodeLabel; 30065552b385SBrandon PetscHMapI currFaceUniquePoints = NULL; 30075552b385SBrandon IS facePoints, edgePoints, nodePoints; 30085552b385SBrandon const PetscInt *fIndices, *eIndices, *nIndices; 30095552b385SBrandon PetscInt fSize, eSize, nSize; 30105552b385SBrandon PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 30115552b385SBrandon PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 30125552b385SBrandon PetscInt cfCntr = 0; 30135552b385SBrandon 30145552b385SBrandon // Get Geometry Object for the Current FACE 30155552b385SBrandon if (islite) { 30165552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 30175552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 30185552b385SBrandon } else { 30195552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 30205552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 30215552b385SBrandon } 30225552b385SBrandon 30235552b385SBrandon // Get all EDGE and NODE objects attached to the current FACE 30245552b385SBrandon if (islite) { 30255552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 30265552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 30275552b385SBrandon } else { 30285552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 30295552b385SBrandon PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 30305552b385SBrandon } 30315552b385SBrandon 30325552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 30335552b385SBrandon if (islite) { 30345552b385SBrandon fid = EGlite_indexBodyTopo(body, face); 30355552b385SBrandon } else { 30365552b385SBrandon fid = EG_indexBodyTopo(body, face); 30375552b385SBrandon } 30385552b385SBrandon 30395552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 30405552b385SBrandon PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 30415552b385SBrandon PetscCall(ISGetIndices(facePoints, &fIndices)); 30425552b385SBrandon PetscCall(ISGetSize(facePoints, &fSize)); 30435552b385SBrandon 30445552b385SBrandon PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 30455552b385SBrandon 30465552b385SBrandon for (int jj = 0; jj < fSize; ++jj) { 30475552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 30485552b385SBrandon 30495552b385SBrandon if (!fHashKeyFound) { 30505552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 30515552b385SBrandon cfCntr += 1; 30525552b385SBrandon } 30535552b385SBrandon 30545552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 30555552b385SBrandon 30565552b385SBrandon if (!pHashKeyFound) { 30575552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 30585552b385SBrandon gcntr += 3 * maxNumCPs; 30595552b385SBrandon } 30605552b385SBrandon } 30615552b385SBrandon PetscCall(ISRestoreIndices(facePoints, &fIndices)); 30625552b385SBrandon PetscCall(ISDestroy(&facePoints)); 30635552b385SBrandon 30645552b385SBrandon // Get all DMPlex Points that have DMLable "EGADS Edge ID" attached to the current FACE and store them in a Hash Table for later use. 30655552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 30665552b385SBrandon ego edge = eobjs[jj]; 30675552b385SBrandon PetscBool containLabelValue; 30685552b385SBrandon 30695552b385SBrandon if (islite) { 30705552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 30715552b385SBrandon } else { 30725552b385SBrandon id = EG_indexBodyTopo(body, edge); 30735552b385SBrandon } 30745552b385SBrandon 30755552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 30765552b385SBrandon PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 30775552b385SBrandon 30785552b385SBrandon if (containLabelValue) { 30795552b385SBrandon PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 30805552b385SBrandon PetscCall(ISGetIndices(edgePoints, &eIndices)); 30815552b385SBrandon PetscCall(ISGetSize(edgePoints, &eSize)); 30825552b385SBrandon 30835552b385SBrandon for (int kk = 0; kk < eSize; ++kk) { 30845552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 30855552b385SBrandon 30865552b385SBrandon if (!eHashKeyFound) { 30875552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 30885552b385SBrandon cfCntr += 1; 30895552b385SBrandon } 30905552b385SBrandon 30915552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 30925552b385SBrandon 30935552b385SBrandon if (!pHashKeyFound) { 30945552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 30955552b385SBrandon gcntr += 3 * maxNumCPs; 30965552b385SBrandon } 30975552b385SBrandon } 30985552b385SBrandon PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 30995552b385SBrandon PetscCall(ISDestroy(&edgePoints)); 31005552b385SBrandon } 31015552b385SBrandon } 31025552b385SBrandon 31035552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Vertex ID" attached to the current FACE and store them in a Hash Table for later use. 31045552b385SBrandon for (int jj = 0; jj < Nn; ++jj) { 31055552b385SBrandon ego node = nobjs[jj]; 31065552b385SBrandon 31075552b385SBrandon if (islite) { 31085552b385SBrandon id = EGlite_indexBodyTopo(body, node); 31095552b385SBrandon } else { 31105552b385SBrandon id = EG_indexBodyTopo(body, node); 31115552b385SBrandon } 31125552b385SBrandon 31135552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 31145552b385SBrandon PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 31155552b385SBrandon PetscCall(ISGetIndices(nodePoints, &nIndices)); 31165552b385SBrandon PetscCall(ISGetSize(nodePoints, &nSize)); 31175552b385SBrandon 31185552b385SBrandon for (int kk = 0; kk < nSize; ++kk) { 31195552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 31205552b385SBrandon 31215552b385SBrandon if (!nHashKeyFound) { 31225552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 31235552b385SBrandon cfCntr += 1; 31245552b385SBrandon } 31255552b385SBrandon 31265552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 31275552b385SBrandon if (!pHashKeyFound) { 31285552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 31295552b385SBrandon gcntr += 3 * maxNumCPs; 31305552b385SBrandon } 31315552b385SBrandon } 31325552b385SBrandon PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 31335552b385SBrandon PetscCall(ISDestroy(&nodePoints)); 31345552b385SBrandon } 31355552b385SBrandon 31365552b385SBrandon // Get the Total Number of entries in the Hash Table 31375552b385SBrandon PetscInt currFaceUPSize; 31385552b385SBrandon PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 31395552b385SBrandon 31405552b385SBrandon // Get Keys 31415552b385SBrandon PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 31425552b385SBrandon PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 31435552b385SBrandon 31445552b385SBrandon // Cycle through all points on the current FACE 31455552b385SBrandon for (int jj = 0; jj < currFaceUPSize; ++jj) { 31465552b385SBrandon PetscInt currPointID = currFaceUPKeys[jj]; 31475552b385SBrandon PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 31485552b385SBrandon 31495552b385SBrandon // Get UV position of FACE 31505552b385SBrandon double params[2], range[4], eval[18]; 31515552b385SBrandon int peri; 31525552b385SBrandon 31535552b385SBrandon if (islite) { 31545552b385SBrandon PetscCall(EGlite_getRange(face, range, &peri)); 31555552b385SBrandon } else { 31565552b385SBrandon PetscCall(EG_getRange(face, range, &peri)); 31575552b385SBrandon } 31585552b385SBrandon 31595552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 31605552b385SBrandon 31615552b385SBrandon if (islite) { 31625552b385SBrandon PetscCall(EGlite_evaluate(face, params, eval)); 31635552b385SBrandon } else { 31645552b385SBrandon PetscCall(EG_evaluate(face, params, eval)); 31655552b385SBrandon } 31665552b385SBrandon 31675552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 31685552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 31695552b385SBrandon double nbprv[prvSize]; 31705552b385SBrandon 31715552b385SBrandon // Cycle through each Control Point 31725552b385SBrandon double deltaCoord = 1.0E-4; 31735552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 31745552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 31755552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 31765552b385SBrandon // Cycle through each direction (x, then y, then z) 31775552b385SBrandon for (int kk = 0; kk < 4; ++kk) { 31785552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 31795552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 31805552b385SBrandon 31815552b385SBrandon if (kk == 0) { //X 31825552b385SBrandon nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 31835552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 31845552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 31855552b385SBrandon } else if (kk == 1) { //Y 31865552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 31875552b385SBrandon nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 31885552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 31895552b385SBrandon } else if (kk == 2) { //Z 31905552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 31915552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 31925552b385SBrandon nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 31935552b385SBrandon } else if (kk == 3) { // Weights 31945552b385SBrandon nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 31955552b385SBrandon } else { 31965552b385SBrandon // currently do nothing 31975552b385SBrandon } 31985552b385SBrandon 31995552b385SBrandon // Create New Surface Based on New Control Points or Weights 32005552b385SBrandon ego newgeom, context; 32015552b385SBrandon if (islite) { 32025552b385SBrandon PetscCall(EGlite_open(&context)); 32035552b385SBrandon PetscCall(EGlite_setOutLevel(context, 0)); 32045552b385SBrandon } else { 32055552b385SBrandon PetscCall(EG_open(&context)); 32065552b385SBrandon PetscCall(EG_setOutLevel(context, 0)); 32075552b385SBrandon } 32085552b385SBrandon 32095552b385SBrandon PetscCall(EG_makeGeometry(context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 32105552b385SBrandon 32115552b385SBrandon if (islite) { 32125552b385SBrandon PetscCall(EGlite_setOutLevel(context, 1)); 32135552b385SBrandon } else { 32145552b385SBrandon PetscCall(EG_setOutLevel(context, 1)); 32155552b385SBrandon } 32165552b385SBrandon 32175552b385SBrandon // Evaluate new (x, y, z) Point Position based on new Surface Definition 32185552b385SBrandon double newCoords[18]; 32195552b385SBrandon if (islite) { 32205552b385SBrandon PetscCall(EGlite_getRange(newgeom, range, &peri)); 32215552b385SBrandon } else { 32225552b385SBrandon PetscCall(EG_getRange(newgeom, range, &peri)); 32235552b385SBrandon } 32245552b385SBrandon 32255552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, newgeom, range, 0, dE, params, islite)); 32265552b385SBrandon 32275552b385SBrandon if (islite) { 32285552b385SBrandon PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 32295552b385SBrandon } else { 32305552b385SBrandon PetscCall(EG_evaluate(newgeom, params, newCoords)); 32315552b385SBrandon } 32325552b385SBrandon 32335552b385SBrandon // Now Calculate the Surface Gradient for the change in x-component Control Point 32345552b385SBrandon PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 32355552b385SBrandon PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 32365552b385SBrandon PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 32375552b385SBrandon 32385552b385SBrandon // Store Gradient Information in surfaceGrad[][] Matrix 32395552b385SBrandon PetscInt startRow; 32405552b385SBrandon PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 32415552b385SBrandon 32425552b385SBrandon // Store Results in Petsc Matrix 32435552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 32445552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 32455552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 32465552b385SBrandon } 32475552b385SBrandon offset += 3; 32485552b385SBrandon } 32495552b385SBrandon PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 32505552b385SBrandon } 32515552b385SBrandon } 32525552b385SBrandon 32535552b385SBrandon // Assemble Point Surface Grad Matrix 32545552b385SBrandon MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY); 32555552b385SBrandon MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY); 32565552b385SBrandon 32575552b385SBrandon // Attach Surface Gradient Hash Table and Matrix to DM 32585552b385SBrandon { 32595552b385SBrandon PetscContainer surfGradOrgObj, surfGradObj; 32605552b385SBrandon 32615552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 32625552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 32635552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 32645552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 32655552b385SBrandon 32665552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradObj)); 32675552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradObj, pointSurfGrad)); 32685552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)surfGradObj)); 32695552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradObj)); 32705552b385SBrandon } 32715552b385SBrandon if (islite) EGlite_free(fobjs); 32725552b385SBrandon else EG_free(fobjs); 32735552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 32745552b385SBrandon } 32755552b385SBrandon 32765552b385SBrandon static PetscErrorCode DestroyHashMap(void **p) 32775552b385SBrandon { 32785552b385SBrandon PetscFunctionBegin; 32795552b385SBrandon PetscCall(PetscHMapIDestroy((PetscHMapI *)p)); 32805552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 32815552b385SBrandon } 32825552b385SBrandon #endif 32835552b385SBrandon 32845552b385SBrandon /*@C 32855552b385SBrandon DMPlexGeomDataAndGrads - Exposes Control Points and Control Point Weights defining the underlying geometry allowing user manipulation of the geometry. 32865552b385SBrandon 32875552b385SBrandon Collective 32885552b385SBrandon 32895552b385SBrandon Input Parameters: 32905552b385SBrandon + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 32915552b385SBrandon - fullGeomGrad - PetscBool flag. Determines how the Surface Area and Volume Gradients wrt to Control Points and Control Point Weights are calculated. 32925552b385SBrandon PETSC_FALSE :: Surface Area Gradient wrt Control Points and Control Point Weights are calculated using the change in the local 32935552b385SBrandon FACE changes (not the entire body). Volume Gradients are not calculated. Faster computations. 32945552b385SBrandon PETSC_TRUE :: Surface Area Gradietn wrt to Control Points and Control Point Weights are calculated using the change observed in 32955552b385SBrandon the entire solid body. Volume Gradients are calculated. Slower computation due to the need to generate a new solid 32965552b385SBrandon body geometry for every Control Point and Control Point Weight change. 32975552b385SBrandon 32985552b385SBrandon Output Parameter: 32995552b385SBrandon . dm - The updated DM object representing the mesh with PetscContainers containing the Control Point, Control Point Weight and Gradient Data. 33005552b385SBrandon 33015552b385SBrandon Level: intermediate 33025552b385SBrandon 33035552b385SBrandon Note: 33045552b385SBrandon Calculates the DM Point location, surface area and volume gradients wrt to Control Point and Control Point Weights using Finite Difference (small perturbation of Control Point coordinates or Control Point Weight value). 33055552b385SBrandon 33065552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexModifyEGADSGeomModel()` 33075552b385SBrandon @*/ 3308ce78bad3SBarry Smith PetscErrorCode DMPlexGeomDataAndGrads(DM dm, PetscBool fullGeomGrad) PeNS 33095552b385SBrandon { 33105552b385SBrandon #if defined(PETSC_HAVE_EGADS) 33115552b385SBrandon /* PETSc Variables */ 33125552b385SBrandon PetscContainer modelObj; 33135552b385SBrandon PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 33145552b385SBrandon PetscHMapI pointSurfGradRow_Start = NULL; 33155552b385SBrandon Mat pointSurfGrad, cpEquiv; 33165552b385SBrandon IS faceLabelValues, edgeLabelValues, vertexLabelValues; 33175552b385SBrandon PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 33185552b385SBrandon PetscBool islite = PETSC_FALSE; 33195552b385SBrandon /* EGADS Variables */ 33205552b385SBrandon ego model, geom, *bodies, *fobjs = NULL; 33215552b385SBrandon int oclass, mtype, *senses; 33225552b385SBrandon int Nb, Nf; 33235552b385SBrandon #endif 33245552b385SBrandon 33255552b385SBrandon PetscFunctionBegin; 33265552b385SBrandon #if defined(PETSC_HAVE_EGADS) 33275552b385SBrandon 33285552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 33295552b385SBrandon if (!modelObj) { 33305552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 33315552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 33325552b385SBrandon islite = PETSC_TRUE; 33335552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot provide geometric data or associated calculated gradients for geometries defined by EGADSlite (.egadslite)!\nPlease use another geometry file format STEP, IGES, EGADS or BRep"); 33345552b385SBrandon } 33355552b385SBrandon 33365552b385SBrandon // Get attached EGADS model (pointer) 33375552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 33385552b385SBrandon 33395552b385SBrandon // Get the bodies in the model 33405552b385SBrandon if (islite) { 33415552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 33425552b385SBrandon } else { 33435552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 33445552b385SBrandon } 33455552b385SBrandon 33465552b385SBrandon ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 33475552b385SBrandon 33485552b385SBrandon // Get the total number of FACEs in the model 33495552b385SBrandon if (islite) { 33505552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 33515552b385SBrandon } else { 33525552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 33535552b385SBrandon } 33545552b385SBrandon 33555552b385SBrandon // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 33565552b385SBrandon // This will provide the total number of DMPlex points on the boundary of the geometry 33575552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 33585552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 33595552b385SBrandon 33605552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 33615552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 33625552b385SBrandon 33635552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 33645552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 33655552b385SBrandon 33665552b385SBrandon const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 33675552b385SBrandon PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 33685552b385SBrandon PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 33695552b385SBrandon PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 33705552b385SBrandon 33715552b385SBrandon // Get the points associated with each FACE, EDGE and VERTEX label in the DM 33725552b385SBrandon PetscInt totalNumPoints = 0; 33735552b385SBrandon for (int f = 0; f < faceLabelSize; ++f) { 33745552b385SBrandon // Cycle through FACE labels 33755552b385SBrandon PetscInt size; 33765552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[f], &size)); 33775552b385SBrandon totalNumPoints += size; 33785552b385SBrandon } 33795552b385SBrandon PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 33805552b385SBrandon PetscCall(ISDestroy(&faceLabelValues)); 33815552b385SBrandon 33825552b385SBrandon for (int e = 0; e < edgeLabelSize; ++e) { 33835552b385SBrandon // Cycle Through EDGE Labels 33845552b385SBrandon PetscInt size; 33855552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[e], &size)); 33865552b385SBrandon totalNumPoints += size; 33875552b385SBrandon } 33885552b385SBrandon PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 33895552b385SBrandon PetscCall(ISDestroy(&edgeLabelValues)); 33905552b385SBrandon 33915552b385SBrandon for (int ii = 0; ii < vertexLabelSize; ++ii) { 33925552b385SBrandon // Cycle Through VERTEX Labels 33935552b385SBrandon PetscInt size; 33945552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 33955552b385SBrandon totalNumPoints += size; 33965552b385SBrandon } 33975552b385SBrandon PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 33985552b385SBrandon PetscCall(ISDestroy(&vertexLabelValues)); 33995552b385SBrandon 34005552b385SBrandon int maxNumCPs = 0; 34015552b385SBrandon int totalNumCPs = 0; 34025552b385SBrandon ego bRef, bPrev, bNext, fgeom, *lobjs; 34035552b385SBrandon int id, boclass, bmtype, *bpinfo; 34045552b385SBrandon int foclass, fmtype, Nl, *lsenses; 34055552b385SBrandon double *bprv; 34065552b385SBrandon double fdata[4]; 34075552b385SBrandon 34085552b385SBrandon // Create Hash Tables 34095552b385SBrandon PetscInt cntr = 0, wcntr = 0, vcntr = 0; 34105552b385SBrandon PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 34115552b385SBrandon PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 34125552b385SBrandon 34135552b385SBrandon for (int f = 0; f < Nf; ++f) { 34145552b385SBrandon // Need to get the maximum number of Control Points defining the FACEs 34155552b385SBrandon ego face = fobjs[f]; 34165552b385SBrandon int maxNumCPs_temp; 34175552b385SBrandon 34185552b385SBrandon if (islite) { 34195552b385SBrandon id = EGlite_indexBodyTopo(body, face); 34205552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 34215552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 34225552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 34235552b385SBrandon } else { 34245552b385SBrandon id = EG_indexBodyTopo(body, face); 34255552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 34265552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 34275552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 34285552b385SBrandon } 34295552b385SBrandon maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 34305552b385SBrandon totalNumCPs += bpinfo[2] * bpinfo[5]; 34315552b385SBrandon 34325552b385SBrandon if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 34335552b385SBrandon } 34345552b385SBrandon 34355552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 34365552b385SBrandon PetscInt cpCoordDataLength = 3 * totalNumCPs; 34375552b385SBrandon PetscInt wDataLength = totalNumCPs; 34385552b385SBrandon cpCoordDataLengthPtr = &cpCoordDataLength; 34395552b385SBrandon wDataLengthPtr = &wDataLength; 34405552b385SBrandon 34415552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 34425552b385SBrandon PetscScalar *cntrlPtCoords, *cntrlPtWeights; 34435552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &cntrlPtCoordsVec)); 34445552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &cntrlPtWeightsVec)); 34455552b385SBrandon 34465552b385SBrandon // For dSA/dCPi 34475552b385SBrandon Vec gradSACPVec, gradSAWVec, gradVCPVec, gradVWVec; 34485552b385SBrandon PetscScalar *gradSACP, *gradSAW, *gradVCP, *gradVW; 34495552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradSACPVec)); 34505552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradSAWVec)); 34515552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradVCPVec)); 34525552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradVWVec)); 34535552b385SBrandon 34545552b385SBrandon // Control Point - Vertex/Edge/Face Relationship 34555552b385SBrandon PetscInt *cp_vertex, *cp_edge, *cp_face; 34565552b385SBrandon PetscInt *w_vertex, *w_edge, *w_face; 34575552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_vertex)); 34585552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_edge)); 34595552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_face)); 34605552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_vertex)); 34615552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_edge)); 34625552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_face)); 34635552b385SBrandon 34645552b385SBrandon for (int f = 0; f < Nf; ++f) { 34655552b385SBrandon // Need to Populate Control Point Coordinates and Weight Vectors 34665552b385SBrandon ego face = fobjs[f]; 34675552b385SBrandon ego *vobjs, *eobjs; 34685552b385SBrandon int offsetCoord, offsetWeight; 34695552b385SBrandon PetscInt Nv, Ne, wRowStart = 0; 34705552b385SBrandon PetscHashIter hashKeyIter, wHashKeyIter; 34715552b385SBrandon PetscBool hashKeyFound, wHashKeyFound; 34725552b385SBrandon 34735552b385SBrandon if (islite) { 34745552b385SBrandon id = EGlite_indexBodyTopo(body, face); 34755552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 34765552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 34775552b385SBrandon PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 34785552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 34795552b385SBrandon } else { 34805552b385SBrandon id = EG_indexBodyTopo(body, face); 34815552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 34825552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 34835552b385SBrandon PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 34845552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 34855552b385SBrandon } 34865552b385SBrandon 34875552b385SBrandon // Store Face ID to 1st Row of Control Point Vector 34885552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 34895552b385SBrandon 34905552b385SBrandon if (!hashKeyFound) PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); 34915552b385SBrandon 34925552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 34935552b385SBrandon offsetCoord = bpinfo[3] + bpinfo[6]; 34945552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 34955552b385SBrandon cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 34965552b385SBrandon cntr += 1; 34975552b385SBrandon } 34985552b385SBrandon 34995552b385SBrandon // Store Face ID to 1st Row of Control Point Weight Vector 35005552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 35015552b385SBrandon 35025552b385SBrandon if (!wHashKeyFound) { 35035552b385SBrandon PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); 35045552b385SBrandon wRowStart = wcntr; 35055552b385SBrandon } 35065552b385SBrandon 35075552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 35085552b385SBrandon offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 35095552b385SBrandon for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 35105552b385SBrandon cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 35115552b385SBrandon cp_face[wcntr] = id; 35125552b385SBrandon w_face[wcntr] = id; 35135552b385SBrandon wcntr += 1; 35145552b385SBrandon } 35155552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 35165552b385SBrandon 3517*bfe80ac4SPierre Jolivet // Associate Control Points with Vertex IDs 35185552b385SBrandon PetscScalar xcp, ycp, zcp; 35195552b385SBrandon offsetCoord = bpinfo[3] + bpinfo[6]; 35205552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; jj += 3) { 35215552b385SBrandon xcp = bprv[offsetCoord + jj + 0]; 35225552b385SBrandon ycp = bprv[offsetCoord + jj + 1]; 35235552b385SBrandon zcp = bprv[offsetCoord + jj + 2]; 35245552b385SBrandon 35255552b385SBrandon //Initialize Control Point and Weight to Vertex ID relationship to -1 35265552b385SBrandon cp_vertex[vcntr] = -1; 35275552b385SBrandon w_vertex[vcntr] = -1; 35285552b385SBrandon cp_edge[vcntr] = -1; 35295552b385SBrandon w_edge[vcntr] = -1; 35305552b385SBrandon 35315552b385SBrandon for (int kk = 0; kk < Nv; ++kk) { 35325552b385SBrandon int vid; 35335552b385SBrandon double vCoords[3]; 35345552b385SBrandon PetscScalar vDelta; 35355552b385SBrandon ego vertex = vobjs[kk]; 35365552b385SBrandon 35375552b385SBrandon if (islite) { 35385552b385SBrandon vid = EGlite_indexBodyTopo(body, vertex); 35395552b385SBrandon PetscCallEGADS(EGlite_evaluate, (vertex, NULL, vCoords)); 35405552b385SBrandon } else { 35415552b385SBrandon vid = EG_indexBodyTopo(body, vertex); 35425552b385SBrandon PetscCallEGADS(EG_evaluate, (vertex, NULL, vCoords)); 35435552b385SBrandon } 35445552b385SBrandon vDelta = PetscSqrtReal(PetscSqr(vCoords[0] - xcp) + PetscSqr(vCoords[1] - ycp) + PetscSqr(vCoords[2] - zcp)); 35455552b385SBrandon 35465552b385SBrandon if (vDelta < 1.0E-15) { 35475552b385SBrandon cp_vertex[vcntr] = vid; 35485552b385SBrandon w_vertex[vcntr] = vid; 35495552b385SBrandon } 35505552b385SBrandon } 35515552b385SBrandon vcntr += 1; 35525552b385SBrandon } 35535552b385SBrandon // These two line could be replaced with DMPlexFreeGeomObject() 35545552b385SBrandon if (islite) EGlite_free(vobjs); 35555552b385SBrandon else EG_free(vobjs); 35565552b385SBrandon 35575552b385SBrandon // Associate Control Points with Edge IDs 35585552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 35595552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 35605552b385SBrandon 35615552b385SBrandon int cpV1, cpV2; 35625552b385SBrandon int minID, maxID; 35635552b385SBrandon 35645552b385SBrandon // Along vmin axis 35655552b385SBrandon minID = wRowStart; 35665552b385SBrandon maxID = wRowStart + (bpinfo[2] - 1); 35675552b385SBrandon cpV1 = cp_vertex[minID]; 35685552b385SBrandon cpV2 = cp_vertex[maxID]; 35695552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 35705552b385SBrandon ego edge = eobjs[jj]; 35715552b385SBrandon ego egeom, *nobjs; 35725552b385SBrandon int eoclass, emtype, Nn, *nsenses; 35735552b385SBrandon int n1ID, n2ID, eid; 35745552b385SBrandon 35755552b385SBrandon if (islite) { 35765552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 35775552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 35785552b385SBrandon } else { 35795552b385SBrandon eid = EG_indexBodyTopo(body, edge); 35805552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 35815552b385SBrandon } 35825552b385SBrandon 35835552b385SBrandon if (emtype != DEGENERATE) { 35845552b385SBrandon // Get IDs for current Edge's End Vertices 35855552b385SBrandon if (islite) { 35865552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 35875552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 35885552b385SBrandon } else { 35895552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 35905552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 35915552b385SBrandon } 35925552b385SBrandon 35935552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 35945552b385SBrandon for (int kk = minID + 1; kk < maxID; ++kk) { 35955552b385SBrandon cp_edge[kk] = eid; 35965552b385SBrandon w_edge[kk] = eid; 35975552b385SBrandon } 35985552b385SBrandon } 35995552b385SBrandon } 36005552b385SBrandon } 36015552b385SBrandon 36025552b385SBrandon // Along vmax axis 36035552b385SBrandon minID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 36045552b385SBrandon maxID = wRowStart + (bpinfo[2] * bpinfo[5] - 1); 36055552b385SBrandon 36065552b385SBrandon cpV1 = cp_vertex[minID]; 36075552b385SBrandon cpV2 = cp_vertex[maxID]; 36085552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 36095552b385SBrandon ego edge = eobjs[jj]; 36105552b385SBrandon ego egeom, *nobjs; 36115552b385SBrandon int eoclass, emtype, Nn, *nsenses; 36125552b385SBrandon int n1ID, n2ID, eid; 36135552b385SBrandon 36145552b385SBrandon if (islite) { 36155552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 36165552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36175552b385SBrandon } else { 36185552b385SBrandon eid = EG_indexBodyTopo(body, edge); 36195552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36205552b385SBrandon } 36215552b385SBrandon 36225552b385SBrandon if (emtype != DEGENERATE) { 36235552b385SBrandon // Get IDs for current Edge's End Vertices 36245552b385SBrandon if (islite) { 36255552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 36265552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 36275552b385SBrandon } else { 36285552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 36295552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 36305552b385SBrandon } 36315552b385SBrandon 36325552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 36335552b385SBrandon for (int kk = minID + 1; kk < maxID - 1; ++kk) { 36345552b385SBrandon cp_edge[kk] = eid; 36355552b385SBrandon w_edge[kk] = eid; 36365552b385SBrandon } 36375552b385SBrandon } 36385552b385SBrandon } 36395552b385SBrandon } 36405552b385SBrandon 36415552b385SBrandon // Along umin axis 36425552b385SBrandon minID = wRowStart; 36435552b385SBrandon maxID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 36445552b385SBrandon 36455552b385SBrandon cpV1 = cp_vertex[minID]; 36465552b385SBrandon cpV2 = cp_vertex[maxID]; 36475552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 36485552b385SBrandon ego edge = eobjs[jj]; 36495552b385SBrandon ego egeom, *nobjs; 36505552b385SBrandon int eoclass, emtype, Nn, *nsenses; 36515552b385SBrandon int n1ID, n2ID, eid; 36525552b385SBrandon 36535552b385SBrandon if (islite) { 36545552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 36555552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36565552b385SBrandon } else { 36575552b385SBrandon eid = EG_indexBodyTopo(body, edge); 36585552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36595552b385SBrandon } 36605552b385SBrandon 36615552b385SBrandon if (emtype != DEGENERATE) { 36625552b385SBrandon // Get IDs for current Edge's End Vertices 36635552b385SBrandon if (islite) { 36645552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 36655552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 36665552b385SBrandon } else { 36675552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 36685552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 36695552b385SBrandon } 36705552b385SBrandon 36715552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 36725552b385SBrandon for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 36735552b385SBrandon cp_edge[kk] = eid; 36745552b385SBrandon w_edge[kk] = eid; 36755552b385SBrandon } 36765552b385SBrandon } 36775552b385SBrandon } 36785552b385SBrandon } 36795552b385SBrandon 36805552b385SBrandon // Along umax axis 36815552b385SBrandon minID = wRowStart + (bpinfo[2] - 1); 36825552b385SBrandon maxID = wRowStart + (bpinfo[2] * bpinfo[5]) - 1; 36835552b385SBrandon cpV1 = cp_vertex[minID]; 36845552b385SBrandon cpV2 = cp_vertex[maxID]; 36855552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 36865552b385SBrandon ego edge = eobjs[jj]; 36875552b385SBrandon ego egeom, *nobjs; 36885552b385SBrandon int eoclass, emtype, Nn, *nsenses; 36895552b385SBrandon int n1ID, n2ID, eid; 36905552b385SBrandon 36915552b385SBrandon if (islite) { 36925552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 36935552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36945552b385SBrandon } else { 36955552b385SBrandon eid = EG_indexBodyTopo(body, edge); 36965552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36975552b385SBrandon } 36985552b385SBrandon 36995552b385SBrandon if (emtype != DEGENERATE) { 37005552b385SBrandon // Get IDs for current Edge's End Vertices 37015552b385SBrandon if (islite) { 37025552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 37035552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 37045552b385SBrandon } else { 37055552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 37065552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 37075552b385SBrandon } 37085552b385SBrandon 37095552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 37105552b385SBrandon for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 37115552b385SBrandon cp_edge[kk] = eid; 37125552b385SBrandon w_edge[kk] = eid; 37135552b385SBrandon } 37145552b385SBrandon } 37155552b385SBrandon } 37165552b385SBrandon } 37175552b385SBrandon // These two lines could be replaced with DMPlexFreeGeomObject() 37185552b385SBrandon if (islite) EGlite_free(eobjs); 37195552b385SBrandon else EG_free(eobjs); 37205552b385SBrandon } 37215552b385SBrandon 3722*bfe80ac4SPierre Jolivet // Determine Control Point Equivalence Matrix relating Control Points between Surfaces 37235552b385SBrandon // Note: The Weights will also be tied together in the same manner 37245552b385SBrandon // Also can use the Weight Hash Table for Row Start ID of each Face 37255552b385SBrandon const PetscInt cpRowSize = totalNumCPs; 37265552b385SBrandon const PetscInt cpColSize = cpRowSize; 37275552b385SBrandon PetscInt *maxNumRelatePtr; 37285552b385SBrandon PetscInt maxNumRelate = 0; 37295552b385SBrandon 37305552b385SBrandon // Create Point Surface Gradient Matrix 37315552b385SBrandon PetscCall(MatCreate(PETSC_COMM_WORLD, &cpEquiv)); 37325552b385SBrandon PetscCall(MatSetSizes(cpEquiv, PETSC_DECIDE, PETSC_DECIDE, cpRowSize, cpColSize)); 37335552b385SBrandon PetscCall(MatSetType(cpEquiv, MATAIJ)); 37345552b385SBrandon PetscCall(MatSetUp(cpEquiv)); 37355552b385SBrandon 37365552b385SBrandon for (int ii = 0; ii < totalNumCPs; ++ii) { 37375552b385SBrandon PetscScalar x1, y1, z1; 37385552b385SBrandon PetscInt maxRelateTemp = 0; 37395552b385SBrandon 37405552b385SBrandon x1 = cntrlPtCoords[(3 * ii) + 0]; 37415552b385SBrandon y1 = cntrlPtCoords[(3 * ii) + 1]; 37425552b385SBrandon z1 = cntrlPtCoords[(3 * ii) + 2]; 37435552b385SBrandon 37445552b385SBrandon for (int jj = 0; jj < totalNumCPs; ++jj) { 37455552b385SBrandon PetscScalar x2, y2, z2; 37465552b385SBrandon PetscScalar cpDelta, eqFactor; 37475552b385SBrandon x2 = cntrlPtCoords[(3 * jj) + 0]; 37485552b385SBrandon y2 = cntrlPtCoords[(3 * jj) + 1]; 37495552b385SBrandon z2 = cntrlPtCoords[(3 * jj) + 2]; 37505552b385SBrandon 37515552b385SBrandon cpDelta = PetscSqrtReal(PetscSqr(x2 - x1) + PetscSqr(y2 - y1) + PetscSqr(z2 - z1)); 37525552b385SBrandon if (cpDelta < 1.0E-15) { 37535552b385SBrandon eqFactor = 1.0; 37545552b385SBrandon maxRelateTemp += 1; 37555552b385SBrandon } else { 37565552b385SBrandon eqFactor = 0.0; 37575552b385SBrandon } 37585552b385SBrandon 37595552b385SBrandon // Store Results in Petsc Matrix 37605552b385SBrandon PetscCall(MatSetValue(cpEquiv, ii, jj, eqFactor, INSERT_VALUES)); 37615552b385SBrandon } 37625552b385SBrandon if (maxRelateTemp > maxNumRelate) maxNumRelate = maxRelateTemp; 37635552b385SBrandon } 37645552b385SBrandon maxNumRelatePtr = &maxNumRelate; 37655552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 37665552b385SBrandon 37675552b385SBrandon // Assemble Point Surface Grad Matrix 37685552b385SBrandon PetscCall(MatAssemblyBegin(cpEquiv, MAT_FINAL_ASSEMBLY)); 37695552b385SBrandon PetscCall(MatAssemblyEnd(cpEquiv, MAT_FINAL_ASSEMBLY)); 37705552b385SBrandon 37715552b385SBrandon // Attach Control Point and Weight Data to DM 37725552b385SBrandon { 37735552b385SBrandon PetscContainer cpOrgObj, cpCoordLengthObj; 37745552b385SBrandon PetscContainer wOrgObj, wDataLengthObj; 37755552b385SBrandon PetscContainer cp_faceObj, cp_edgeObj, cp_vertexObj; 37765552b385SBrandon PetscContainer w_faceObj, w_edgeObj, w_vertexObj; 37775552b385SBrandon PetscContainer maxNumRelateObj; 37785552b385SBrandon 37795552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpOrgObj)); 37805552b385SBrandon if (!cpOrgObj) { 37815552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 37825552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 37835552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 37845552b385SBrandon PetscCall(PetscContainerDestroy(&cpOrgObj)); 37855552b385SBrandon } else { 37865552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 37875552b385SBrandon } 37885552b385SBrandon 37895552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cntrlPtCoordsVec)); 37905552b385SBrandon PetscCall(VecDestroy(&cntrlPtCoordsVec)); 37915552b385SBrandon 37925552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordLengthObj)); 37935552b385SBrandon if (!cpCoordLengthObj) { 37945552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 37955552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 37965552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 37975552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 37985552b385SBrandon } else { 37995552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 38005552b385SBrandon } 38015552b385SBrandon 38025552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wOrgObj)); 38035552b385SBrandon if (!wOrgObj) { 38045552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 38055552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 38065552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 38075552b385SBrandon PetscCall(PetscContainerDestroy(&wOrgObj)); 38085552b385SBrandon } else { 38095552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 38105552b385SBrandon } 38115552b385SBrandon 38125552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)cntrlPtWeightsVec)); 38135552b385SBrandon PetscCall(VecDestroy(&cntrlPtWeightsVec)); 38145552b385SBrandon 38155552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 38165552b385SBrandon if (!wDataLengthObj) { 38175552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 38185552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 38195552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 38205552b385SBrandon PetscCall(PetscContainerDestroy(&wDataLengthObj)); 38215552b385SBrandon } else { 38225552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 38235552b385SBrandon } 38245552b385SBrandon 3825*bfe80ac4SPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Equivalency Matrix", (PetscObject)cpEquiv)); 38265552b385SBrandon 38275552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 38285552b385SBrandon if (!maxNumRelateObj) { 38295552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &maxNumRelateObj)); 38305552b385SBrandon PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 38315552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject)maxNumRelateObj)); 38325552b385SBrandon PetscCall(PetscContainerDestroy(&maxNumRelateObj)); 38335552b385SBrandon } else { 38345552b385SBrandon PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 38355552b385SBrandon } 38365552b385SBrandon 38375552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cp_faceObj)); 38385552b385SBrandon if (!cp_faceObj) { 38395552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_faceObj)); 38405552b385SBrandon PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 38415552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_faceObj, PetscCtxDestroyDefault)); 38425552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Face Map", (PetscObject)cp_faceObj)); 38435552b385SBrandon PetscCall(PetscContainerDestroy(&cp_faceObj)); 38445552b385SBrandon } else { 38455552b385SBrandon void *tmp; 38465552b385SBrandon 38475552b385SBrandon PetscCall(PetscContainerGetPointer(cp_faceObj, &tmp)); 38485552b385SBrandon PetscCall(PetscFree(tmp)); 38495552b385SBrandon PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 38505552b385SBrandon } 38515552b385SBrandon 38525552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&w_faceObj)); 38535552b385SBrandon if (!w_faceObj) { 38545552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_faceObj)); 38555552b385SBrandon PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 38565552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_faceObj, PetscCtxDestroyDefault)); 38575552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject)w_faceObj)); 38585552b385SBrandon PetscCall(PetscContainerDestroy(&w_faceObj)); 38595552b385SBrandon } else { 38605552b385SBrandon void *tmp; 38615552b385SBrandon 38625552b385SBrandon PetscCall(PetscContainerGetPointer(w_faceObj, &tmp)); 38635552b385SBrandon PetscCall(PetscFree(tmp)); 38645552b385SBrandon PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 38655552b385SBrandon } 38665552b385SBrandon 38675552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cp_edgeObj)); 38685552b385SBrandon if (!cp_edgeObj) { 38695552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_edgeObj)); 38705552b385SBrandon PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 38715552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_edgeObj, PetscCtxDestroyDefault)); 38725552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Edge Map", (PetscObject)cp_edgeObj)); 38735552b385SBrandon PetscCall(PetscContainerDestroy(&cp_edgeObj)); 38745552b385SBrandon } else { 38755552b385SBrandon void *tmp; 38765552b385SBrandon 38775552b385SBrandon PetscCall(PetscContainerGetPointer(cp_edgeObj, &tmp)); 38785552b385SBrandon PetscCall(PetscFree(tmp)); 38795552b385SBrandon PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 38805552b385SBrandon } 38815552b385SBrandon 38825552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&w_edgeObj)); 38835552b385SBrandon if (!w_edgeObj) { 38845552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_edgeObj)); 38855552b385SBrandon PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 38865552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_edgeObj, PetscCtxDestroyDefault)); 38875552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject)w_edgeObj)); 38885552b385SBrandon PetscCall(PetscContainerDestroy(&w_edgeObj)); 38895552b385SBrandon } else { 38905552b385SBrandon void *tmp; 38915552b385SBrandon 38925552b385SBrandon PetscCall(PetscContainerGetPointer(w_edgeObj, &tmp)); 38935552b385SBrandon PetscCall(PetscFree(tmp)); 38945552b385SBrandon PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 38955552b385SBrandon } 38965552b385SBrandon 38975552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cp_vertexObj)); 38985552b385SBrandon if (!cp_vertexObj) { 38995552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_vertexObj)); 39005552b385SBrandon PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 39015552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_vertexObj, PetscCtxDestroyDefault)); 39025552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Vertex Map", (PetscObject)cp_vertexObj)); 39035552b385SBrandon PetscCall(PetscContainerDestroy(&cp_vertexObj)); 39045552b385SBrandon } else { 39055552b385SBrandon void *tmp; 39065552b385SBrandon 39075552b385SBrandon PetscCall(PetscContainerGetPointer(cp_vertexObj, &tmp)); 39085552b385SBrandon PetscCall(PetscFree(tmp)); 39095552b385SBrandon PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 39105552b385SBrandon } 39115552b385SBrandon 39125552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&w_vertexObj)); 39135552b385SBrandon if (!w_vertexObj) { 39145552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_vertexObj)); 39155552b385SBrandon PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 39165552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_vertexObj, PetscCtxDestroyDefault)); 39175552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject)w_vertexObj)); 39185552b385SBrandon PetscCall(PetscContainerDestroy(&w_vertexObj)); 39195552b385SBrandon } else { 39205552b385SBrandon void *tmp; 39215552b385SBrandon 39225552b385SBrandon PetscCall(PetscContainerGetPointer(w_vertexObj, &tmp)); 39235552b385SBrandon PetscCall(PetscFree(tmp)); 39245552b385SBrandon PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 39255552b385SBrandon } 39265552b385SBrandon } 39275552b385SBrandon 39285552b385SBrandon // Define Matrix to store Geometry Gradient information dGeom_i/dCPj_i 39295552b385SBrandon PetscInt gcntr = 0; 39305552b385SBrandon const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 39315552b385SBrandon const PetscInt colSize = 4 * Nf; 39325552b385SBrandon 39335552b385SBrandon // Create Point Surface Gradient Matrix 39345552b385SBrandon PetscCall(MatCreate(PETSC_COMM_WORLD, &pointSurfGrad)); 39355552b385SBrandon PetscCall(MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize)); 39365552b385SBrandon PetscCall(MatSetType(pointSurfGrad, MATAIJ)); 39375552b385SBrandon PetscCall(MatSetUp(pointSurfGrad)); 39385552b385SBrandon 39395552b385SBrandon // Create Hash Table to store Point's stare row in surfaceGrad[][] 39405552b385SBrandon PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 39415552b385SBrandon 39425552b385SBrandon // Get Coordinates for the DMPlex point 39435552b385SBrandon DM cdm; 39445552b385SBrandon PetscInt dE, Nv; 39455552b385SBrandon Vec coordinatesLocal; 39465552b385SBrandon PetscScalar *coords = NULL; 39475552b385SBrandon 39485552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 39495552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &dE)); 39505552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 39515552b385SBrandon 39525552b385SBrandon // CYCLE THROUGH FACEs 39535552b385SBrandon PetscScalar maxGrad = 0.; 39545552b385SBrandon PetscCall(VecGetArrayWrite(gradSACPVec, &gradSACP)); 39555552b385SBrandon PetscCall(VecGetArrayWrite(gradSAWVec, &gradSAW)); 39565552b385SBrandon PetscCall(VecGetArrayWrite(gradVCPVec, &gradVCP)); 39575552b385SBrandon PetscCall(VecGetArrayWrite(gradVWVec, &gradVW)); 39585552b385SBrandon for (int f = 0; f < Nf; ++f) { 39595552b385SBrandon ego face = fobjs[f]; 39605552b385SBrandon ego *eobjs, *nobjs; 39615552b385SBrandon PetscInt fid, Ne, Nn; 39625552b385SBrandon DMLabel faceLabel, edgeLabel, nodeLabel; 39635552b385SBrandon PetscHMapI currFaceUniquePoints = NULL; 39645552b385SBrandon IS facePoints, edgePoints, nodePoints; 39655552b385SBrandon const PetscInt *fIndices, *eIndices, *nIndices; 39665552b385SBrandon PetscInt fSize, eSize, nSize; 39675552b385SBrandon PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 39685552b385SBrandon PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 39695552b385SBrandon PetscInt cfCntr = 0; 39705552b385SBrandon 39715552b385SBrandon // Get Geometry Object for the Current FACE 39725552b385SBrandon if (islite) { 39735552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 39745552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 39755552b385SBrandon } else { 39765552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 39775552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 39785552b385SBrandon } 39795552b385SBrandon 39805552b385SBrandon // Get all EDGE and NODE objects attached to the current FACE 39815552b385SBrandon if (islite) { 39825552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 39835552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 39845552b385SBrandon } else { 39855552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 39865552b385SBrandon PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 39875552b385SBrandon } 39885552b385SBrandon 39895552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 39905552b385SBrandon if (islite) { 39915552b385SBrandon fid = EGlite_indexBodyTopo(body, face); 39925552b385SBrandon } else { 39935552b385SBrandon fid = EG_indexBodyTopo(body, face); 39945552b385SBrandon } 39955552b385SBrandon 39965552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 39975552b385SBrandon PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 39985552b385SBrandon PetscCall(ISGetIndices(facePoints, &fIndices)); 39995552b385SBrandon PetscCall(ISGetSize(facePoints, &fSize)); 40005552b385SBrandon 40015552b385SBrandon PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 40025552b385SBrandon 40035552b385SBrandon for (int jj = 0; jj < fSize; ++jj) { 40045552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 40055552b385SBrandon 40065552b385SBrandon if (!fHashKeyFound) { 40075552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 40085552b385SBrandon cfCntr += 1; 40095552b385SBrandon } 40105552b385SBrandon 40115552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 40125552b385SBrandon 40135552b385SBrandon if (!pHashKeyFound) { 40145552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 40155552b385SBrandon gcntr += 3 * maxNumCPs; 40165552b385SBrandon } 40175552b385SBrandon } 40185552b385SBrandon PetscCall(ISRestoreIndices(facePoints, &fIndices)); 40195552b385SBrandon PetscCall(ISDestroy(&facePoints)); 40205552b385SBrandon 40215552b385SBrandon // Get all DMPlex Points that have DMLable "EGADS Edge ID" attached to the current FACE and store them in a Hash Table for later use. 40225552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 40235552b385SBrandon ego edge = eobjs[jj]; 40245552b385SBrandon PetscBool containLabelValue; 40255552b385SBrandon 40265552b385SBrandon if (islite) { 40275552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 40285552b385SBrandon } else { 40295552b385SBrandon id = EG_indexBodyTopo(body, edge); 40305552b385SBrandon } 40315552b385SBrandon 40325552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 40335552b385SBrandon PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 40345552b385SBrandon 40355552b385SBrandon if (containLabelValue) { 40365552b385SBrandon PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 40375552b385SBrandon PetscCall(ISGetIndices(edgePoints, &eIndices)); 40385552b385SBrandon PetscCall(ISGetSize(edgePoints, &eSize)); 40395552b385SBrandon 40405552b385SBrandon for (int kk = 0; kk < eSize; ++kk) { 40415552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 40425552b385SBrandon 40435552b385SBrandon if (!eHashKeyFound) { 40445552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 40455552b385SBrandon cfCntr += 1; 40465552b385SBrandon } 40475552b385SBrandon 40485552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 40495552b385SBrandon 40505552b385SBrandon if (!pHashKeyFound) { 40515552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 40525552b385SBrandon gcntr += 3 * maxNumCPs; 40535552b385SBrandon } 40545552b385SBrandon } 40555552b385SBrandon PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 40565552b385SBrandon PetscCall(ISDestroy(&edgePoints)); 40575552b385SBrandon } 40585552b385SBrandon } 40595552b385SBrandon 40605552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Vertex ID" attached to the current FACE and store them in a Hash Table for later use. 40615552b385SBrandon for (int jj = 0; jj < Nn; ++jj) { 40625552b385SBrandon ego node = nobjs[jj]; 40635552b385SBrandon 40645552b385SBrandon if (islite) { 40655552b385SBrandon id = EGlite_indexBodyTopo(body, node); 40665552b385SBrandon } else { 40675552b385SBrandon id = EG_indexBodyTopo(body, node); 40685552b385SBrandon } 40695552b385SBrandon 40705552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 40715552b385SBrandon PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 40725552b385SBrandon PetscCall(ISGetIndices(nodePoints, &nIndices)); 40735552b385SBrandon PetscCall(ISGetSize(nodePoints, &nSize)); 40745552b385SBrandon 40755552b385SBrandon for (int kk = 0; kk < nSize; ++kk) { 40765552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 40775552b385SBrandon 40785552b385SBrandon if (!nHashKeyFound) { 40795552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 40805552b385SBrandon cfCntr += 1; 40815552b385SBrandon } 40825552b385SBrandon 40835552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 40845552b385SBrandon if (!pHashKeyFound) { 40855552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 40865552b385SBrandon gcntr += 3 * maxNumCPs; 40875552b385SBrandon } 40885552b385SBrandon } 40895552b385SBrandon PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 40905552b385SBrandon PetscCall(ISDestroy(&nodePoints)); 40915552b385SBrandon } 40925552b385SBrandon 40935552b385SBrandon // Get the Total Number of entries in the Hash Table 40945552b385SBrandon PetscInt currFaceUPSize; 40955552b385SBrandon PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 40965552b385SBrandon 40975552b385SBrandon // Get Keys 40985552b385SBrandon PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 40995552b385SBrandon PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 41005552b385SBrandon PetscCall(PetscHMapIDestroy(&currFaceUniquePoints)); 41015552b385SBrandon 41025552b385SBrandon // Get Current Face Surface Area 41035552b385SBrandon PetscScalar fSA, faceData[14]; 41045552b385SBrandon PetscCall(EG_getMassProperties(face, faceData)); // This doesn't have a EGlite version. Will it work for EGADSlite files?? KNOWN_ISSUE 41055552b385SBrandon fSA = faceData[1]; 41065552b385SBrandon 41075552b385SBrandon // Get Start Row in cpEquiv Matrix 41085552b385SBrandon PetscHashIter Witer; 41095552b385SBrandon PetscBool Wfound; 41105552b385SBrandon PetscInt faceWStartRow; 41115552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 41125552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 41135552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 41145552b385SBrandon 41155552b385SBrandon // Cycle through all points on the current FACE 41165552b385SBrandon for (int jj = 0; jj < currFaceUPSize; ++jj) { 41175552b385SBrandon PetscInt currPointID = currFaceUPKeys[jj]; 41185552b385SBrandon PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 41195552b385SBrandon 41205552b385SBrandon // Get UV position of FACE 41215552b385SBrandon double params[2], range[4], eval[18]; 41225552b385SBrandon int peri; 41235552b385SBrandon 41245552b385SBrandon if (islite) PetscCall(EGlite_getRange(face, range, &peri)); 41255552b385SBrandon else PetscCall(EG_getRange(face, range, &peri)); 41265552b385SBrandon 41275552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 41285552b385SBrandon 41295552b385SBrandon if (islite) PetscCall(EGlite_evaluate(face, params, eval)); 41305552b385SBrandon else PetscCall(EG_evaluate(face, params, eval)); 41315552b385SBrandon 41325552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 41335552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 41345552b385SBrandon double nbprv[prvSize]; 41355552b385SBrandon 41365552b385SBrandon // Cycle through each Control Point 41375552b385SBrandon double denomNew, denomOld; 41385552b385SBrandon double deltaCoord = 1.0E-4; 41395552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 41405552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 41415552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 41425552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d", f, jj, ii); 41435552b385SBrandon #if 0 41445552b385SBrandon // Cycle through each direction (x, then y, then z) 41455552b385SBrandon if (jj == 0) { 41465552b385SBrandon // Get the Number Control Points that are the same as the current points 41475552b385SBrandon // We are looking for repeated Control Points 41485552b385SBrandon PetscInt commonCPcntr = 0; 41495552b385SBrandon for (int mm = 0; mm < bpinfo[2]*bpinfo[5]; ++mm) { 41505552b385SBrandon PetscScalar matValue; 41515552b385SBrandon PetscCall(MatGetValue(cpEquiv, faceWStartRow + ii, faceWStartRow + mm, &matValue)); 41525552b385SBrandon 41535552b385SBrandon if (matValue > 0.0) commonCPcntr += 1; 41545552b385SBrandon } 41555552b385SBrandon } 41565552b385SBrandon #endif 41575552b385SBrandon 41585552b385SBrandon for (int kk = 0; kk < 4; ++kk) { 41595552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 41605552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 41615552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 41625552b385SBrandon 41635552b385SBrandon if (kk == 0) { //X 41645552b385SBrandon nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 41655552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 41665552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 41675552b385SBrandon denomNew = nbprv[offset + 0]; 41685552b385SBrandon denomOld = bprv[offset + 0]; 41695552b385SBrandon } else if (kk == 1) { //Y 41705552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 41715552b385SBrandon nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 41725552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 41735552b385SBrandon denomNew = nbprv[offset + 1]; 41745552b385SBrandon denomOld = bprv[offset + 1]; 41755552b385SBrandon } else if (kk == 2) { //Z 41765552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 41775552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 41785552b385SBrandon nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 41795552b385SBrandon denomNew = nbprv[offset + 2]; 41805552b385SBrandon denomOld = bprv[offset + 2]; 41815552b385SBrandon } else if (kk == 3) { // Weights 41825552b385SBrandon nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 41835552b385SBrandon denomNew = nbprv[wOffset + ii]; 41845552b385SBrandon denomOld = bprv[wOffset + ii]; 41855552b385SBrandon } else { 41865552b385SBrandon // currently do nothing 41875552b385SBrandon } 41885552b385SBrandon 41895552b385SBrandon // Create New Surface Based on New Control Points or Weights 41905552b385SBrandon ego newgeom, context; 41915552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // This does not have an EGlite_ version KNOWN_ISSUE 41925552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // This does not have an EGlite_ version KNOWN_ISSUE 41935552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 41945552b385SBrandon 41955552b385SBrandon // Evaluate new (x, y, z) Point Position based on new Surface Definition 41965552b385SBrandon double newCoords[18]; 41975552b385SBrandon if (islite) PetscCall(EGlite_getRange(newgeom, range, &peri)); 41985552b385SBrandon else PetscCall(EG_getRange(newgeom, range, &peri)); 41995552b385SBrandon 42005552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 42015552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 42025552b385SBrandon 42035552b385SBrandon if (islite) PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 42045552b385SBrandon else PetscCall(EG_evaluate(newgeom, params, newCoords)); 42055552b385SBrandon 42065552b385SBrandon // Calculate Surface Area Gradients wrt Control Points and Weights using the local discrete FACE only 42075552b385SBrandon // NOTE 1: Will not provide Volume Gradient wrt to Control Points and Weights. 42085552b385SBrandon // NOTE 2: This is faster than below where an entire new solid geometry is created for each 42095552b385SBrandon // Control Point and Weight gradient 42105552b385SBrandon if (!fullGeomGrad) { 42115552b385SBrandon // Create new FACE based on new SURFACE geometry 42125552b385SBrandon if (jj == 0) { // only for 1st DMPlex Point because we only per CP or Weight 42135552b385SBrandon double newFaceRange[4]; 42145552b385SBrandon int newFacePeri; 42155552b385SBrandon if (islite) PetscCall(EGlite_getRange(newgeom, newFaceRange, &newFacePeri)); 42165552b385SBrandon else PetscCall(EG_getRange(newgeom, newFaceRange, &newFacePeri)); 42175552b385SBrandon 42185552b385SBrandon ego newface; 42195552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have EGlite version KNOWN_ISSUE 42205552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 42215552b385SBrandon 42225552b385SBrandon // Get New Face Surface Area 42235552b385SBrandon PetscScalar newfSA, newFaceData[14]; 42245552b385SBrandon PetscCall(EG_getMassProperties(newface, newFaceData)); // Does not have EGlite version KNOWN_ISSUE 42255552b385SBrandon newfSA = newFaceData[1]; 42265552b385SBrandon PetscCallEGADS(EG_deleteObject, (newface)); 42275552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 42285552b385SBrandon 42295552b385SBrandon // Update Control Points 42305552b385SBrandon PetscHashIter CPiter, Witer; 42315552b385SBrandon PetscBool CPfound, Wfound; 42325552b385SBrandon PetscInt faceCPStartRow, faceWStartRow; 42335552b385SBrandon 42345552b385SBrandon PetscScalar dSAdCPi; 42355552b385SBrandon dSAdCPi = (newfSA - fSA) / (denomNew - denomOld); 42365552b385SBrandon 42375552b385SBrandon if (kk < 3) { 42385552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, fid, &CPiter, &CPfound)); 42395552b385SBrandon PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 42405552b385SBrandon PetscCall(PetscHMapIGet(faceCntrlPtRow_Start, fid, &faceCPStartRow)); 42415552b385SBrandon 42425552b385SBrandon gradSACP[faceCPStartRow + (ii * 3) + kk] = dSAdCPi; 42435552b385SBrandon 42445552b385SBrandon if (PetscAbsReal(dSAdCPi) > maxGrad) maxGrad = PetscAbsReal(dSAdCPi); 42455552b385SBrandon 42465552b385SBrandon } else if (kk == 3) { 42475552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 42485552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 42495552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 42505552b385SBrandon 42515552b385SBrandon gradSAW[faceWStartRow + ii] = dSAdCPi; 42525552b385SBrandon 42535552b385SBrandon } else { 42545552b385SBrandon // Do Nothing 42555552b385SBrandon } 42565552b385SBrandon } 42575552b385SBrandon } 42585552b385SBrandon PetscCallEGADS(EG_deleteObject, (newgeom)); 42595552b385SBrandon 42605552b385SBrandon // Now Calculate the Surface Gradient for the change in x-component Control Point 42615552b385SBrandon PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 42625552b385SBrandon PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 42635552b385SBrandon PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 42645552b385SBrandon 42655552b385SBrandon // Store Gradient Information in surfaceGrad[][] Matrix 42665552b385SBrandon PetscInt startRow; 42675552b385SBrandon PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 42685552b385SBrandon 42695552b385SBrandon // Store Results in Petsc Matrix 42705552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 42715552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 42725552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 42735552b385SBrandon 42745552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newgeom)); 42755552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face is corrupted"); 42765552b385SBrandon } 42775552b385SBrandon offset += 3; 42785552b385SBrandon } 42795552b385SBrandon PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 42805552b385SBrandon } 42815552b385SBrandon } 42825552b385SBrandon 42835552b385SBrandon // Assemble Point Surface Grad Matrix 42845552b385SBrandon PetscCall(MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 42855552b385SBrandon PetscCall(MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 42865552b385SBrandon 42875552b385SBrandon if (fullGeomGrad) { 42885552b385SBrandon // Calculate Surface Area and Volume Control Point and Control Point Weight Gradients 42895552b385SBrandon // Note: This is much slower than above due to a new solid geometry being created for 42905552b385SBrandon // each change in Control Point and Control Point Weight. However, this method 42915552b385SBrandon // will provide the Volume Gradient. 42925552b385SBrandon 42935552b385SBrandon // Get Current Face Surface Area 42945552b385SBrandon PetscScalar bodyVol, bodySA, bodyData[14]; 4295*bfe80ac4SPierre Jolivet PetscCall(EG_getMassProperties(body, bodyData)); // Does not have an EGlite version KNOWN_ISSUE 42965552b385SBrandon bodyVol = bodyData[0]; 42975552b385SBrandon bodySA = bodyData[1]; 42985552b385SBrandon 42995552b385SBrandon // Cycle through Control Points 43005552b385SBrandon for (int ii = 0; ii < totalNumCPs; ++ii) { // ii should also be the row in cpEquiv for the Control Point 43015552b385SBrandon // Cycle through X, Y, Z, W changes 43025552b385SBrandon for (int jj = 0; jj < 4; ++jj) { 43035552b385SBrandon // Cycle Through Faces 43045552b385SBrandon double denomNew = 0.0, denomOld = 0.0; 43055552b385SBrandon double deltaCoord = 1.0E-4; 43065552b385SBrandon ego newGeom[Nf]; 43075552b385SBrandon ego newFaces[Nf]; 43085552b385SBrandon for (int kk = 0; kk < Nf; ++kk) { 43095552b385SBrandon ego face; 43105552b385SBrandon PetscInt currFID = kk + 1; 43115552b385SBrandon 43125552b385SBrandon if (islite) { 43135552b385SBrandon // Get Current FACE 43145552b385SBrandon PetscCallEGADS(EGlite_objectBodyTopo, (body, FACE, currFID, &face)); 43155552b385SBrandon 43165552b385SBrandon // Get Geometry Object for the Current FACE 43175552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 43185552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 43195552b385SBrandon } else { 43205552b385SBrandon // Get Current FACE 43215552b385SBrandon PetscCallEGADS(EG_objectBodyTopo, (body, FACE, currFID, &face)); 43225552b385SBrandon 43235552b385SBrandon // Get Geometry Object for the Current FACE 43245552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 43255552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 43265552b385SBrandon } 43275552b385SBrandon 43285552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 43295552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 43305552b385SBrandon double nbprv[prvSize]; 43315552b385SBrandon 43325552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 43335552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) nbprv[mm] = bprv[mm]; 43345552b385SBrandon 43355552b385SBrandon // Get Control Point Row and Column Start for cpEquiv 43365552b385SBrandon PetscHashIter Witer; 43375552b385SBrandon PetscBool Wfound; 43385552b385SBrandon PetscInt faceWStartRow; 43395552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, currFID, &Witer, &Wfound)); 43405552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 43415552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, currFID, &faceWStartRow)); 43425552b385SBrandon 43435552b385SBrandon // Modify the Current Control Point on this FACE and All Other FACES 43445552b385SBrandon // IMPORTANT!!! If you do not move all identical Control Points on other FACES 43455552b385SBrandon // you will not generate a solid body. You will generate a set of 43465552b385SBrandon // disconnected surfaces that have gap(s) between them. 43475552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 43485552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 43495552b385SBrandon for (int mm = 0; mm < bpinfo[2] * bpinfo[5]; ++mm) { 43505552b385SBrandon PetscScalar matValue; 43515552b385SBrandon PetscCall(MatGetValue(cpEquiv, ii, faceWStartRow + mm, &matValue)); 43525552b385SBrandon 43535552b385SBrandon if (matValue > 0.0) { 43545552b385SBrandon if (jj == 0) { //X 43555552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0] + deltaCoord; 43565552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 43575552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 43585552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 0]; 43595552b385SBrandon denomOld = bprv[offset + (3 * mm) + 0]; 43605552b385SBrandon } else if (jj == 1) { //Y 43615552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 43625552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1] + deltaCoord; 43635552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 43645552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 1]; 43655552b385SBrandon denomOld = bprv[offset + (3 * mm) + 1]; 43665552b385SBrandon } else if (jj == 2) { //Z 43675552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 43685552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 43695552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2] + deltaCoord; 43705552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 2]; 43715552b385SBrandon denomOld = bprv[offset + (3 * mm) + 2]; 43725552b385SBrandon } else if (jj == 3) { // Weights 43735552b385SBrandon nbprv[wOffset + mm] = bprv[wOffset + mm] + deltaCoord; 43745552b385SBrandon denomNew = nbprv[wOffset + mm]; 43755552b385SBrandon denomOld = bprv[wOffset + mm]; 43765552b385SBrandon } else { 43775552b385SBrandon // currently do nothing 43785552b385SBrandon } 43795552b385SBrandon } 43805552b385SBrandon } 43815552b385SBrandon 43825552b385SBrandon // Create New Surface Based on New Control Points or Weights 43835552b385SBrandon ego newgeom, context; 43845552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ versions KNOWN_ISSUE 43855552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 43865552b385SBrandon 43875552b385SBrandon // Create New FACE based on modified geometry 43885552b385SBrandon double newFaceRange[4]; 43895552b385SBrandon int newFacePeri; 43905552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, newFaceRange, &newFacePeri)); 43915552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, newFaceRange, &newFacePeri)); 43925552b385SBrandon 43935552b385SBrandon ego newface; 43945552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 43955552b385SBrandon 43965552b385SBrandon // store new face for later assembly 43975552b385SBrandon newGeom[kk] = newgeom; 43985552b385SBrandon newFaces[kk] = newface; 43995552b385SBrandon } 44005552b385SBrandon 44015552b385SBrandon // X-WANT TO BUILD THE NEW GEOMETRY, X-GET NEW SA AND PERFORM dSA/dCPi CALCS HERE <--- 44025552b385SBrandon // Sew New Faces together to get a new model 44035552b385SBrandon ego newmodel; 44045552b385SBrandon PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 44055552b385SBrandon 44065552b385SBrandon // Get Surface Area and Volume of New/Updated Solid Body 44075552b385SBrandon PetscScalar newData[14]; 44085552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 44095552b385SBrandon else PetscCallEGADS(EG_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 44105552b385SBrandon 44115552b385SBrandon ego nbody = bodies[0]; 44125552b385SBrandon PetscCall(EG_getMassProperties(nbody, newData)); // Does not have an EGlite_ version KNOWN_ISSUE 44135552b385SBrandon 44145552b385SBrandon PetscScalar dSAdCPi, dVdCPi; 44155552b385SBrandon PetscScalar nbodyVol = newData[0], nbodySA = newData[1]; 44165552b385SBrandon 44175552b385SBrandon // Calculate Gradients wrt to Control Points and Control Points Weights depending on jj value 44185552b385SBrandon dSAdCPi = (nbodySA - bodySA) / (denomNew - denomOld); 44195552b385SBrandon dVdCPi = (nbodyVol - bodyVol) / (denomNew - denomOld); 44205552b385SBrandon 44215552b385SBrandon if (jj < 3) { 44225552b385SBrandon // Gradienst wrt to Control Points 44235552b385SBrandon gradSACP[(ii * 3) + jj] = dSAdCPi; 44245552b385SBrandon gradVCP[(ii * 3) + jj] = dVdCPi; 44255552b385SBrandon } else if (jj == 3) { 44265552b385SBrandon // Gradients wrt to Control Point Weights 44275552b385SBrandon gradSAW[ii] = dSAdCPi; 44285552b385SBrandon gradVW[ii] = dVdCPi; 44295552b385SBrandon } else { 44305552b385SBrandon // Do Nothing 44315552b385SBrandon } 44325552b385SBrandon PetscCallEGADS(EG_deleteObject, (newmodel)); 44335552b385SBrandon for (int kk = 0; kk < Nf; ++kk) { 44345552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[kk])); 44355552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[kk])); 44365552b385SBrandon } 44375552b385SBrandon } 44385552b385SBrandon } 44395552b385SBrandon } 44405552b385SBrandon PetscCall(VecRestoreArrayWrite(gradSACPVec, &gradSACP)); 44415552b385SBrandon PetscCall(VecRestoreArrayWrite(gradSAWVec, &gradSAW)); 44425552b385SBrandon PetscCall(VecRestoreArrayWrite(gradVCPVec, &gradVCP)); 44435552b385SBrandon PetscCall(VecRestoreArrayWrite(gradVWVec, &gradVW)); 44445552b385SBrandon PetscCall(MatDestroy(&cpEquiv)); 44455552b385SBrandon 44465552b385SBrandon // Attach Surface Gradient Hash Table and Matrix to DM 44475552b385SBrandon { 44485552b385SBrandon PetscContainer surfGradOrgObj; 44495552b385SBrandon 44505552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&surfGradOrgObj)); 44515552b385SBrandon if (!surfGradOrgObj) { 44525552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 44535552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 44545552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(surfGradOrgObj, DestroyHashMap)); 44555552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 44565552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 44575552b385SBrandon } else { 44585552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 44595552b385SBrandon } 44605552b385SBrandon 44615552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)pointSurfGrad)); 44625552b385SBrandon PetscCall(MatDestroy(&pointSurfGrad)); 44635552b385SBrandon 44645552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject)gradSACPVec)); 44655552b385SBrandon PetscCall(VecDestroy(&gradSACPVec)); 44665552b385SBrandon 44675552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject)gradSAWVec)); 44685552b385SBrandon PetscCall(VecDestroy(&gradSAWVec)); 44695552b385SBrandon 44705552b385SBrandon if (fullGeomGrad) { 44715552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Control Point Gradient", (PetscObject)gradVCPVec)); 44725552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Weights Gradient", (PetscObject)gradVWVec)); 44735552b385SBrandon } 44745552b385SBrandon PetscCall(VecDestroy(&gradVCPVec)); 44755552b385SBrandon PetscCall(VecDestroy(&gradVWVec)); 44765552b385SBrandon } 44775552b385SBrandon 44785552b385SBrandon // Could be replaced with DMPlexFreeGeomObject() 44795552b385SBrandon if (islite) EGlite_free(fobjs); 44805552b385SBrandon else EG_free(fobjs); 44815552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 44825552b385SBrandon #else 44835552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 44845552b385SBrandon #endif 44855552b385SBrandon } 44865552b385SBrandon 44875552b385SBrandon /*@C 44885552b385SBrandon DMPlexModifyGeomModel - Generates a new EGADS geometry model based in user provided Control Points and Control Points Weights. Optionally, the function will inflate the DM to the new geometry and save the new geometry to a file. 44895552b385SBrandon 44905552b385SBrandon Collective 44915552b385SBrandon 44925552b385SBrandon Input Parameters: 44935552b385SBrandon + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 44945552b385SBrandon . comm - MPI_Comm object 44955552b385SBrandon . newCP - C Array of [x, y, z] New/Updated Control Point Coordinates defining the geometry (See DMPlexGeomDataAndGrads() for format) 44965552b385SBrandon . newW - C Array of New/Updated Control Point Weights associated with the Control Points defining the new geometry (See DMPlexGemGrads() for format) 44975552b385SBrandon . autoInflate - PetscBool Flag denoting if the user would like to inflate the DM points to the new geometry. 44985552b385SBrandon . saveGeom - PetscBool Flag denoting if the user would iike to save the new geometry to a file. 44995552b385SBrandon - stpName - Char Array indicating the name of the file to save the new geometry to. Extension must be included and will denote type of file written. 45005552b385SBrandon *.stp or *.step = STEP File 45015552b385SBrandon *.igs or *.iges = IGES File 45025552b385SBrandon *.egads = EGADS File 45035552b385SBrandon *.brep = BRep File (OpenCASCADE File) 45045552b385SBrandon 45055552b385SBrandon Output Parameter: 45065552b385SBrandon . dm - The updated DM object representing the mesh with PetscContainers containing the updated/modified geometry 45075552b385SBrandon 45085552b385SBrandon Level: intermediate 45095552b385SBrandon 45105552b385SBrandon Note: 45115552b385SBrandon Functionality not available for DMPlexes with attached EGADSlite geometry files (.egadslite). 45125552b385SBrandon 45135552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 45145552b385SBrandon @*/ 4515ce78bad3SBarry Smith PetscErrorCode DMPlexModifyGeomModel(DM dm, MPI_Comm comm, PetscScalar newCP[], PetscScalar newW[], PetscBool autoInflate, PetscBool saveGeom, const char *stpName) PeNS 45165552b385SBrandon { 45175552b385SBrandon #if defined(PETSC_HAVE_EGADS) 45185552b385SBrandon /* EGADS/EGADSlite variables */ 45195552b385SBrandon ego context, model, geom, *bodies, *lobjs, *fobjs; 45205552b385SBrandon int oclass, mtype, *senses, *lsenses; 45215552b385SBrandon int Nb, Nf, Nl, id; 45225552b385SBrandon /* PETSc variables */ 45235552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 45245552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj; 45255552b385SBrandon PetscHMapI cpHashTable = NULL, wHashTable = NULL; 45265552b385SBrandon PetscBool islite = PETSC_FALSE; 45275552b385SBrandon #endif 45285552b385SBrandon 45295552b385SBrandon #if defined(PETSC_HAVE_EGADS) 45305552b385SBrandon PetscFunctionBegin; 45315552b385SBrandon // Look to see if DM has a Container with either a EGADS or EGADSlite Model 45325552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 45335552b385SBrandon if (!modelObj) { 45345552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 45355552b385SBrandon islite = PETSC_TRUE; 45365552b385SBrandon } 45375552b385SBrandon PetscCheck(!islite, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot modify geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep"); 45385552b385SBrandon PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have a EGADS Geometry Model attached to it!"); 45395552b385SBrandon 45405552b385SBrandon // Get attached EGADS model (pointer) 45415552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 45425552b385SBrandon 45435552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 45445552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 45455552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 45465552b385SBrandon 45475552b385SBrandon PetscCheck(cpHashTableObj && wHashTableObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have required Geometry Data attached! Please run DMPlexGeomDataAndGrads() Function first."); 45485552b385SBrandon 45495552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 45505552b385SBrandon PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTable)); 45515552b385SBrandon PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTable)); 45525552b385SBrandon 45535552b385SBrandon // Get the number of bodies and body objects in the model 45545552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 45555552b385SBrandon else PetscCallEGADS(EG_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 45565552b385SBrandon 45575552b385SBrandon // Get all Faces on the body 45585552b385SBrandon ego body = bodies[0]; 45595552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 45605552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 45615552b385SBrandon 45625552b385SBrandon ego newGeom[Nf]; 45635552b385SBrandon ego newFaces[Nf]; 45645552b385SBrandon 45655552b385SBrandon // Update Control Point and Weight definitions for each surface 45665552b385SBrandon for (int jj = 0; jj < Nf; ++jj) { 45675552b385SBrandon ego face = fobjs[jj]; 45685552b385SBrandon ego bRef, bPrev, bNext; 45695552b385SBrandon ego fgeom; 45705552b385SBrandon int offset; 45715552b385SBrandon int boclass, bmtype, *bpinfo; 45725552b385SBrandon double *bprv; 45735552b385SBrandon 45745552b385SBrandon // Get FACE ID and other Geometry Data 45755552b385SBrandon if (islite) { 45765552b385SBrandon id = EGlite_indexBodyTopo(body, face); 45775552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 45785552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 45795552b385SBrandon PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 45805552b385SBrandon } else { 45815552b385SBrandon id = EG_indexBodyTopo(body, face); 45825552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 45835552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 45845552b385SBrandon PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 45855552b385SBrandon } 45865552b385SBrandon 45875552b385SBrandon // Update Control Points 45885552b385SBrandon PetscHashIter CPiter, Witer; 45895552b385SBrandon PetscBool CPfound, Wfound; 45905552b385SBrandon PetscInt faceCPStartRow, faceWStartRow; 45915552b385SBrandon 45925552b385SBrandon PetscCall(PetscHMapIFind(cpHashTable, id, &CPiter, &CPfound)); 45935552b385SBrandon PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 45945552b385SBrandon PetscCall(PetscHMapIGet(cpHashTable, id, &faceCPStartRow)); 45955552b385SBrandon 45965552b385SBrandon PetscCall(PetscHMapIFind(wHashTable, id, &Witer, &Wfound)); 45975552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 45985552b385SBrandon PetscCall(PetscHMapIGet(wHashTable, id, &faceWStartRow)); 45995552b385SBrandon 46005552b385SBrandon // UPDATE CONTROL POINTS Locations 46015552b385SBrandon offset = bpinfo[3] + bpinfo[6]; 46025552b385SBrandon for (int ii = 0; ii < 3 * bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newCP[faceCPStartRow + ii]; } 46035552b385SBrandon 46045552b385SBrandon // UPDATE CONTROL POINT WEIGHTS 46055552b385SBrandon offset = bpinfo[3] + bpinfo[6] + 3 * bpinfo[2] * bpinfo[5]; 46065552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newW[faceWStartRow + ii]; } 46075552b385SBrandon 46085552b385SBrandon // Get Context from FACE 46095552b385SBrandon context = NULL; 46105552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version KNOWN_ISSUE 46115552b385SBrandon 46125552b385SBrandon // Create New Surface 46135552b385SBrandon ego newgeom; 46145552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 46155552b385SBrandon 46165552b385SBrandon // Create new FACE based on new SURFACE geometry 46175552b385SBrandon double data[4]; 46185552b385SBrandon int periodic; 46195552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 46205552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 46215552b385SBrandon 46225552b385SBrandon ego newface; 46235552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 46245552b385SBrandon newGeom[jj] = newgeom; 46255552b385SBrandon newFaces[jj] = newface; 46265552b385SBrandon } 46275552b385SBrandon // Could be replaced by DMPlexFreeGeomObject 46285552b385SBrandon if (islite) EGlite_free(fobjs); 46295552b385SBrandon else EG_free(fobjs); 46305552b385SBrandon 46315552b385SBrandon // Sew New Faces together to get a new model 46325552b385SBrandon ego newmodel; 46335552b385SBrandon PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 46345552b385SBrandon for (PetscInt f = 0; f < Nf; ++f) { 46355552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[f])); 46365552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[f])); 46375552b385SBrandon } 46385552b385SBrandon 46395552b385SBrandon // Get the total number of NODEs on the original geometry. (This will be the same for the new geometry) 46405552b385SBrandon int totalNumNode; 46415552b385SBrandon ego *nobjTotal; 46425552b385SBrandon if (islite) { 46435552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 46445552b385SBrandon EGlite_free(nobjTotal); 46455552b385SBrandon } else { 46465552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 46475552b385SBrandon EG_free(nobjTotal); 46485552b385SBrandon } // Could be replaced with DMPlexFreeGeomObject 46495552b385SBrandon 46505552b385SBrandon // Initialize vector to store equivalent NODE indices between the 2 geometries 46515552b385SBrandon // FORMAT :: vector index is the Original Geometry's NODE ID, the vector Value is the New Geometry's NODE ID 46525552b385SBrandon int nodeIDEquiv[totalNumNode + 1]; 46535552b385SBrandon 46545552b385SBrandon // Now we need to Map the NODE and EDGE IDs from each Model 46555552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 46565552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 46575552b385SBrandon 46585552b385SBrandon // New CAD 46595552b385SBrandon ego *newbodies, newgeomtest, *nfobjs; 46605552b385SBrandon int nNf, newNb, newoclass, newmtype, *newsenses; 46615552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 46625552b385SBrandon else PetscCallEGADS(EG_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 46635552b385SBrandon 46645552b385SBrandon ego newbody = newbodies[0]; 46655552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 46665552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 46675552b385SBrandon 46685552b385SBrandon PetscCheck(newNb == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ERROR :: newNb > 1 || newNb = %d", newNb); 46695552b385SBrandon 46705552b385SBrandon // Find Equivalent Nodes 46715552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 46725552b385SBrandon double fdata[4]; 46735552b385SBrandon int peri; 46745552b385SBrandon 46755552b385SBrandon // Get Current FACE [u, v] Ranges 46765552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (fobjs[ii], fdata, &peri)); 46775552b385SBrandon else PetscCallEGADS(EG_getRange, (fobjs[ii], fdata, &peri)); 46785552b385SBrandon 46795552b385SBrandon // Equate NODE IDs between 2 FACEs by working through (u, v) limits of FACE 46805552b385SBrandon for (int jj = 0; jj < 2; ++jj) { 46815552b385SBrandon for (int kk = 2; kk < 4; ++kk) { 46825552b385SBrandon double params[2] = {fdata[jj], fdata[kk]}; 46835552b385SBrandon double eval[18]; 46845552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (fobjs[ii], params, eval)); 46855552b385SBrandon else PetscCallEGADS(EG_evaluate, (fobjs[ii], params, eval)); 46865552b385SBrandon 46875552b385SBrandon // Original Body 46885552b385SBrandon ego *nobjsOrigFace; 46895552b385SBrandon int origNn; 46905552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 46915552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 46925552b385SBrandon 46935552b385SBrandon double minVal = 1.0E10; 46945552b385SBrandon double evalCheck[18]; 46955552b385SBrandon int equivOrigNodeID = -1; 46965552b385SBrandon for (int mm = 0; mm < origNn; ++mm) { 46975552b385SBrandon double delta = 1.0E10; 46985552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 46995552b385SBrandon else PetscCallEGADS(EG_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 47005552b385SBrandon 47015552b385SBrandon delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 47025552b385SBrandon 47035552b385SBrandon if (delta < minVal) { 47045552b385SBrandon if (islite) equivOrigNodeID = EGlite_indexBodyTopo(body, nobjsOrigFace[mm]); 47055552b385SBrandon else equivOrigNodeID = EG_indexBodyTopo(body, nobjsOrigFace[mm]); 47065552b385SBrandon 47075552b385SBrandon minVal = delta; 47085552b385SBrandon } 47095552b385SBrandon } 47105552b385SBrandon // Could be replaced with DMPlexFreeGeomObject 47115552b385SBrandon if (islite) EGlite_free(nobjsOrigFace); 47125552b385SBrandon else EG_free(nobjsOrigFace); 47135552b385SBrandon 47145552b385SBrandon // New Body 47155552b385SBrandon ego *nobjsNewFace; 47165552b385SBrandon int newNn; 47175552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 47185552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 47195552b385SBrandon 47205552b385SBrandon minVal = 1.0E10; 47215552b385SBrandon int equivNewNodeID = -1; 47225552b385SBrandon for (int mm = 0; mm < newNn; ++mm) { 47235552b385SBrandon double delta = 1.0E10; 47245552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 47255552b385SBrandon else PetscCallEGADS(EG_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 47265552b385SBrandon 47275552b385SBrandon delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 47285552b385SBrandon 47295552b385SBrandon if (delta < minVal) { 47305552b385SBrandon if (islite) equivNewNodeID = EGlite_indexBodyTopo(newbody, nobjsNewFace[mm]); 47315552b385SBrandon else equivNewNodeID = EG_indexBodyTopo(newbody, nobjsNewFace[mm]); 47325552b385SBrandon 47335552b385SBrandon minVal = delta; 47345552b385SBrandon } 47355552b385SBrandon } 47365552b385SBrandon if (islite) EGlite_free(nobjsNewFace); 47375552b385SBrandon else EG_free(nobjsNewFace); 47385552b385SBrandon 47395552b385SBrandon // Store equivalent NODE IDs 47405552b385SBrandon nodeIDEquiv[equivOrigNodeID] = equivNewNodeID; 47415552b385SBrandon } 47425552b385SBrandon } 47435552b385SBrandon } 47445552b385SBrandon 47455552b385SBrandon // Find Equivalent EDGEs 47465552b385SBrandon // Get total number of EDGEs on Original Geometry 47475552b385SBrandon int totalNumEdge; 47485552b385SBrandon ego *eobjsOrig; 47495552b385SBrandon if (islite) { 47505552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 47515552b385SBrandon EGlite_free(eobjsOrig); 47525552b385SBrandon } else { 47535552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 47545552b385SBrandon EG_free(eobjsOrig); 47555552b385SBrandon } 47565552b385SBrandon 47575552b385SBrandon // Get total number of EDGEs on New Geometry 47585552b385SBrandon int totalNumEdgeNew; 47595552b385SBrandon ego *eobjsNew; 47605552b385SBrandon if (islite) { 47615552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 47625552b385SBrandon EGlite_free(eobjsNew); 47635552b385SBrandon } else { 47645552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 47655552b385SBrandon EG_free(eobjsNew); 47665552b385SBrandon } 47675552b385SBrandon 47685552b385SBrandon // Initialize EDGE ID equivalent vector 47695552b385SBrandon // FORMAT :: vector index is the Original Geometry's EDGE ID, the vector Value is the New Geometry's EDGE ID 47705552b385SBrandon int edgeIDEquiv[totalNumEdge + 1]; 47715552b385SBrandon 47725552b385SBrandon // Find Equivalent EDGEs 47735552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 47745552b385SBrandon // Get Original Geometry EDGE's NODEs 47755552b385SBrandon int numOrigEdge, numNewEdge; 47765552b385SBrandon if (islite) { 47775552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 47785552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 47795552b385SBrandon } else { 47805552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 47815552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 47825552b385SBrandon } 47835552b385SBrandon 47845552b385SBrandon // new loop below 47855552b385SBrandon for (int nn = 0; nn < numOrigEdge; ++nn) { 47865552b385SBrandon ego origEdge = eobjsOrig[nn]; 47875552b385SBrandon ego geomEdgeOrig, *nobjsOrig; 47885552b385SBrandon int oclassEdgeOrig, mtypeEdgeOrig; 47895552b385SBrandon int NnOrig, *nsensesEdgeOrig; 47905552b385SBrandon 47915552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 47925552b385SBrandon else PetscCallEGADS(EG_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 47935552b385SBrandon 47945552b385SBrandon PetscBool isSame = PETSC_FALSE; 47955552b385SBrandon for (int jj = 0; jj < numNewEdge; ++jj) { 47965552b385SBrandon ego newEdge = eobjsNew[jj]; 47975552b385SBrandon ego geomEdgeNew, *nobjsNew; 47985552b385SBrandon int oclassEdgeNew, mtypeEdgeNew; 47995552b385SBrandon int NnNew, *nsensesEdgeNew; 48005552b385SBrandon 48015552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 48025552b385SBrandon else PetscCallEGADS(EG_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 48035552b385SBrandon 48045552b385SBrandon if (mtypeEdgeOrig == mtypeEdgeNew) { 48055552b385SBrandon // Only operate if the EDGE types are the same 48065552b385SBrandon for (int kk = 0; kk < NnNew; ++kk) { 48075552b385SBrandon int nodeIDOrigGeom, nodeIDNewGeom; 48085552b385SBrandon if (islite) { 48095552b385SBrandon nodeIDOrigGeom = EGlite_indexBodyTopo(body, nobjsOrig[kk]); 48105552b385SBrandon nodeIDNewGeom = EGlite_indexBodyTopo(newbody, nobjsNew[kk]); 48115552b385SBrandon } else { 48125552b385SBrandon nodeIDOrigGeom = EG_indexBodyTopo(body, nobjsOrig[kk]); 48135552b385SBrandon nodeIDNewGeom = EG_indexBodyTopo(newbody, nobjsNew[kk]); 48145552b385SBrandon } 48155552b385SBrandon 48165552b385SBrandon if (nodeIDNewGeom == nodeIDEquiv[nodeIDOrigGeom]) { 48175552b385SBrandon isSame = PETSC_TRUE; 48185552b385SBrandon } else { 48195552b385SBrandon isSame = PETSC_FALSE; 48205552b385SBrandon kk = NnNew; // skip ahead because first NODE failed test and order is important 48215552b385SBrandon } 48225552b385SBrandon } 48235552b385SBrandon 48245552b385SBrandon if (isSame == PETSC_TRUE) { 48255552b385SBrandon int edgeIDOrig, edgeIDNew; 48265552b385SBrandon if (islite) { 48275552b385SBrandon edgeIDOrig = EGlite_indexBodyTopo(body, origEdge); 48285552b385SBrandon edgeIDNew = EGlite_indexBodyTopo(newbody, newEdge); 48295552b385SBrandon } else { 48305552b385SBrandon edgeIDOrig = EG_indexBodyTopo(body, origEdge); 48315552b385SBrandon edgeIDNew = EG_indexBodyTopo(newbody, newEdge); 48325552b385SBrandon } 48335552b385SBrandon 48345552b385SBrandon edgeIDEquiv[edgeIDOrig] = edgeIDNew; 48355552b385SBrandon jj = numNewEdge; 48365552b385SBrandon } 48375552b385SBrandon } 48385552b385SBrandon } 48395552b385SBrandon } 48405552b385SBrandon if (islite) { 48415552b385SBrandon EGlite_free(eobjsOrig); 48425552b385SBrandon EGlite_free(eobjsNew); 48435552b385SBrandon } else { 48445552b385SBrandon EG_free(eobjsOrig); 48455552b385SBrandon EG_free(eobjsNew); 48465552b385SBrandon } 48475552b385SBrandon } 48485552b385SBrandon if (islite) { 48495552b385SBrandon EGlite_free(fobjs); 48505552b385SBrandon EGlite_free(nfobjs); 48515552b385SBrandon } else { 48525552b385SBrandon EG_free(fobjs); 48535552b385SBrandon EG_free(nfobjs); 48545552b385SBrandon } 48555552b385SBrandon 48565552b385SBrandon // Modify labels to point to the IDs on the new Geometry 48575552b385SBrandon IS isNodeID, isEdgeID; 48585552b385SBrandon 48595552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 48605552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 48615552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 48625552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 48635552b385SBrandon 48645552b385SBrandon PetscCall(ISCreateGeneral(comm, totalNumNode + 1, nodeIDEquiv, PETSC_COPY_VALUES, &isNodeID)); 48655552b385SBrandon PetscCall(ISCreateGeneral(comm, totalNumEdge + 1, edgeIDEquiv, PETSC_COPY_VALUES, &isEdgeID)); 48665552b385SBrandon /* Do not perform check. Np may != Nv due to Degenerate Geometry which is not stored in labels. */ 48675552b385SBrandon /* We do not know in advance which IDs have been omitted. This may also change due to geometry modifications. */ 48685552b385SBrandon PetscCall(DMLabelRewriteValues(vertexLabel, isNodeID)); 48695552b385SBrandon PetscCall(DMLabelRewriteValues(edgeLabel, isEdgeID)); 48705552b385SBrandon PetscCall(ISDestroy(&isNodeID)); 48715552b385SBrandon PetscCall(ISDestroy(&isEdgeID)); 48725552b385SBrandon 48735552b385SBrandon // Attempt to point to the new geometry 48745552b385SBrandon PetscCallEGADS(EG_deleteObject, (model)); 48755552b385SBrandon PetscCall(PetscContainerSetPointer(modelObj, newmodel)); 48765552b385SBrandon 48775552b385SBrandon // save updated model to file 48785552b385SBrandon if (saveGeom == PETSC_TRUE && stpName != NULL) PetscCall(EG_saveModel(newmodel, stpName)); 48795552b385SBrandon 48805552b385SBrandon // Inflate Mesh to EGADS Model 48815552b385SBrandon if (autoInflate == PETSC_TRUE) PetscCall(DMPlexInflateToGeomModel(dm, PETSC_TRUE)); 48825552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 48835552b385SBrandon #else 48845552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 48855552b385SBrandon #endif 48865552b385SBrandon } 48875552b385SBrandon 48885552b385SBrandon /*@C 48895552b385SBrandon DMPlexGetGeomModelTUV - Gets the [t] (EDGES) and [u, v] (FACES) geometry parameters of DM points that are associated geometry relationships. Requires a DM with a EGADS model attached. 48905552b385SBrandon 48915552b385SBrandon Collective 48925552b385SBrandon 48935552b385SBrandon Input Parameter: 48945552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 48955552b385SBrandon 48965552b385SBrandon Level: intermediate 48975552b385SBrandon 48985552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 48995552b385SBrandon @*/ 4900ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelTUV(DM dm) PeNS 49015552b385SBrandon { 49025552b385SBrandon #if defined(PETSC_HAVE_EGADS) 49035552b385SBrandon /* EGADS Variables */ 49045552b385SBrandon ego model, geom, body, face, edge; 49055552b385SBrandon ego *bodies; 49065552b385SBrandon int Nb, oclass, mtype, *senses; 49075552b385SBrandon double result[4]; 49085552b385SBrandon /* PETSc Variables */ 49095552b385SBrandon DM cdm; 49105552b385SBrandon PetscContainer modelObj; 49115552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 49125552b385SBrandon Vec coordinates; 49135552b385SBrandon PetscScalar *coords; 49145552b385SBrandon PetscInt bodyID, faceID, edgeID, vertexID; 49155552b385SBrandon PetscInt cdim, vStart, vEnd, v; 49165552b385SBrandon PetscBool islite = PETSC_FALSE; 49175552b385SBrandon #endif 49185552b385SBrandon 49195552b385SBrandon PetscFunctionBegin; 49205552b385SBrandon #if defined(PETSC_HAVE_EGADS) 49215552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 49225552b385SBrandon if (!modelObj) { 49235552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 49245552b385SBrandon islite = PETSC_TRUE; 49255552b385SBrandon } 49265552b385SBrandon if (!modelObj) PetscFunctionReturn(0); 49275552b385SBrandon 49285552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &cdim)); 49295552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 49305552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 49315552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 49325552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 49335552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 49345552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 49355552b385SBrandon 49365552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 49375552b385SBrandon 49385552b385SBrandon if (islite) PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 49395552b385SBrandon else PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 49405552b385SBrandon 49415552b385SBrandon PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 49425552b385SBrandon PetscCall(VecGetArrayWrite(coordinates, &coords)); 49435552b385SBrandon 49445552b385SBrandon // Define t, u, v arrays to be stored in a PetscContainer after populated 49455552b385SBrandon PetscScalar *t_point, *u_point, *v_point; 49465552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &t_point)); 49475552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &u_point)); 49485552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &v_point)); 49495552b385SBrandon 49505552b385SBrandon for (v = vStart; v < vEnd; ++v) { 49515552b385SBrandon PetscScalar *vcoords; 49525552b385SBrandon 49535552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 49545552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 49555552b385SBrandon PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 49565552b385SBrandon PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 49575552b385SBrandon 49585552b385SBrandon // TODO Figure out why this is unknown sometimes 49595552b385SBrandon if (bodyID < 0 && Nb == 1) bodyID = 0; 49605552b385SBrandon PetscCheck(bodyID >= 0 && bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " for vertex %" PetscInt_FMT " is not in [0, %d)", bodyID, v, Nb); 4961c1cad2e7SMatthew G. Knepley body = bodies[bodyID]; 4962c1cad2e7SMatthew G. Knepley 49639566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 4964c1cad2e7SMatthew G. Knepley if (edgeID > 0) { 4965c1cad2e7SMatthew G. Knepley /* Snap to EDGE at nearest location */ 4966c1cad2e7SMatthew G. Knepley double params[1]; 49675552b385SBrandon 49685552b385SBrandon if (islite) { 49695552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 49705552b385SBrandon PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 49715552b385SBrandon } // Get (t) of nearest point on EDGE 49725552b385SBrandon else { 49739566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 49745552b385SBrandon PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 49755552b385SBrandon } // Get (t) of nearest point on EDGE 49765552b385SBrandon 49775552b385SBrandon t_point[v - vStart] = params[0]; 49785552b385SBrandon u_point[v - vStart] = 0.0; 49795552b385SBrandon v_point[v - vStart] = 0.0; 4980c1cad2e7SMatthew G. Knepley } else if (faceID > 0) { 4981c1cad2e7SMatthew G. Knepley /* Snap to FACE at nearest location */ 4982c1cad2e7SMatthew G. Knepley double params[2]; 49835552b385SBrandon 49845552b385SBrandon if (islite) { 49855552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 49865552b385SBrandon PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 49875552b385SBrandon } // Get (x,y,z) of nearest point on FACE 49885552b385SBrandon else { 49899566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 49905552b385SBrandon PetscCall(EG_invEvaluate(face, vcoords, params, result)); 49915552b385SBrandon } // Get (x,y,z) of nearest point on FACE 49925552b385SBrandon 49935552b385SBrandon t_point[v - vStart] = 0.0; 49945552b385SBrandon u_point[v - vStart] = params[0]; 49955552b385SBrandon v_point[v - vStart] = params[1]; 49965552b385SBrandon } else { 49975552b385SBrandon t_point[v - vStart] = 0.0; 49985552b385SBrandon u_point[v - vStart] = 0.0; 49995552b385SBrandon v_point[v - vStart] = 0.0; 50005552b385SBrandon } 50015552b385SBrandon } 50025552b385SBrandon PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 50035552b385SBrandon /* Clear out global coordinates */ 50045552b385SBrandon PetscCall(VecDestroy(&dm->coordinates[0].x)); 50055552b385SBrandon 50065552b385SBrandon /* Store in PetscContainters */ 50075552b385SBrandon { 50085552b385SBrandon PetscContainer t_pointObj, u_pointObj, v_pointObj; 50095552b385SBrandon 50105552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 50115552b385SBrandon if (!t_pointObj) { 50125552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &t_pointObj)); 50135552b385SBrandon PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 50145552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Edge t Parameter", (PetscObject)t_pointObj)); 50155552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(t_pointObj, PetscCtxDestroyDefault)); 50165552b385SBrandon PetscCall(PetscContainerDestroy(&t_pointObj)); 50175552b385SBrandon } else { 50185552b385SBrandon void *old; 50195552b385SBrandon 50205552b385SBrandon PetscCall(PetscContainerGetPointer(t_pointObj, &old)); 50215552b385SBrandon PetscCall(PetscFree(old)); 50225552b385SBrandon PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 50235552b385SBrandon } 50245552b385SBrandon 50255552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 50265552b385SBrandon if (!u_pointObj) { 50275552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &u_pointObj)); 50285552b385SBrandon PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 50295552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face u Parameter", (PetscObject)u_pointObj)); 50305552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(u_pointObj, PetscCtxDestroyDefault)); 50315552b385SBrandon PetscCall(PetscContainerDestroy(&u_pointObj)); 50325552b385SBrandon } else { 50335552b385SBrandon void *old; 50345552b385SBrandon 50355552b385SBrandon PetscCall(PetscContainerGetPointer(u_pointObj, &old)); 50365552b385SBrandon PetscCall(PetscFree(old)); 50375552b385SBrandon PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 50385552b385SBrandon } 50395552b385SBrandon 50405552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 50415552b385SBrandon if (!v_pointObj) { 50425552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &v_pointObj)); 50435552b385SBrandon PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 50445552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face v Parameter", (PetscObject)v_pointObj)); 50455552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(v_pointObj, PetscCtxDestroyDefault)); 50465552b385SBrandon PetscCall(PetscContainerDestroy(&v_pointObj)); 50475552b385SBrandon } else { 50485552b385SBrandon void *old; 50495552b385SBrandon 50505552b385SBrandon PetscCall(PetscContainerGetPointer(v_pointObj, &old)); 50515552b385SBrandon PetscCall(PetscFree(old)); 50525552b385SBrandon PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 50535552b385SBrandon } 50545552b385SBrandon } 50555552b385SBrandon #endif 50565552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 50575552b385SBrandon } 50585552b385SBrandon 50595552b385SBrandon /*@C 50605552b385SBrandon DMPlexInflateToGeomModelUseTUV - Inflates the DM to the associated underlying geometry using the [t] {EDGES) and [u, v] (FACES} associated parameters. Requires a DM with an EGADS model attached and a previous call to DMPlexGetGeomModelTUV(). 50615552b385SBrandon 50625552b385SBrandon Collective 50635552b385SBrandon 50645552b385SBrandon Input Parameter: 50655552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 50665552b385SBrandon 50675552b385SBrandon Level: intermediate 50685552b385SBrandon 50695552b385SBrandon Note: 50705552b385SBrandon The updated DM object inflated to the associated underlying geometry. This updates the [x, y, z] coordinates of DM points associated with geometry. 50715552b385SBrandon 50725552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()`, `DMPlexGetGeomModelTUV()` 50735552b385SBrandon @*/ 5074ce78bad3SBarry Smith PetscErrorCode DMPlexInflateToGeomModelUseTUV(DM dm) PeNS 50755552b385SBrandon { 50765552b385SBrandon #if defined(PETSC_HAVE_EGADS) 50775552b385SBrandon /* EGADS Variables */ 50785552b385SBrandon ego model, geom, body, face, edge, vertex; 50795552b385SBrandon ego *bodies; 50805552b385SBrandon int Nb, oclass, mtype, *senses; 50815552b385SBrandon double result[18], params[2]; 50825552b385SBrandon /* PETSc Variables */ 50835552b385SBrandon DM cdm; 50845552b385SBrandon PetscContainer modelObj; 50855552b385SBrandon PetscContainer t_pointObj, u_pointObj, v_pointObj; 50865552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 50875552b385SBrandon Vec coordinates; 50885552b385SBrandon PetscScalar *coords; 50895552b385SBrandon PetscScalar *t_point, *u_point, *v_point; 50905552b385SBrandon PetscInt bodyID, faceID, edgeID, vertexID; 50915552b385SBrandon PetscInt cdim, d, vStart, vEnd, v; 50925552b385SBrandon PetscBool islite = PETSC_FALSE; 50935552b385SBrandon #endif 50945552b385SBrandon 50955552b385SBrandon PetscFunctionBegin; 50965552b385SBrandon #if defined(PETSC_HAVE_EGADS) 50975552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 50985552b385SBrandon if (!modelObj) { 50995552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 51005552b385SBrandon islite = PETSC_TRUE; 51015552b385SBrandon } 51025552b385SBrandon 51035552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 51045552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 51055552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 51065552b385SBrandon 51075552b385SBrandon if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 51085552b385SBrandon if (!t_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 51095552b385SBrandon if (!u_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 51105552b385SBrandon if (!v_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 51115552b385SBrandon 51125552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &cdim)); 51135552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 51145552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 51155552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 51165552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 51175552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 51185552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 51195552b385SBrandon 51205552b385SBrandon PetscCall(PetscContainerGetPointer(t_pointObj, (void **)&t_point)); 51215552b385SBrandon PetscCall(PetscContainerGetPointer(u_pointObj, (void **)&u_point)); 51225552b385SBrandon PetscCall(PetscContainerGetPointer(v_pointObj, (void **)&v_point)); 51235552b385SBrandon 51245552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 51255552b385SBrandon 51265552b385SBrandon if (islite) { 51275552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 51285552b385SBrandon } else { 51295552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 51305552b385SBrandon } 51315552b385SBrandon 51325552b385SBrandon PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 51335552b385SBrandon PetscCall(VecGetArrayWrite(coordinates, &coords)); 51345552b385SBrandon 51355552b385SBrandon for (v = vStart; v < vEnd; ++v) { 51365552b385SBrandon PetscScalar *vcoords; 51375552b385SBrandon 51385552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 51395552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 51405552b385SBrandon PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 51415552b385SBrandon PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 51425552b385SBrandon 51435552b385SBrandon // TODO Figure out why this is unknown sometimes 51445552b385SBrandon if (bodyID < 0 && Nb == 1) bodyID = 0; 51455552b385SBrandon PetscCheck(bodyID >= 0 && bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " for vertex %" PetscInt_FMT " is not in [0, %d)", bodyID, v, Nb); 51465552b385SBrandon body = bodies[bodyID]; 51475552b385SBrandon 51485552b385SBrandon PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 51495552b385SBrandon if (vertexID > 0) { 51505552b385SBrandon /* Snap to Vertices */ 51515552b385SBrandon if (islite) { 51525552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 51535552b385SBrandon PetscCall(EGlite_evaluate(vertex, NULL, result)); 51545552b385SBrandon } else { 51555552b385SBrandon PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 51565552b385SBrandon PetscCall(EG_evaluate(vertex, NULL, result)); 51575552b385SBrandon } 51585552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 51595552b385SBrandon } else if (edgeID > 0) { 51605552b385SBrandon /* Snap to EDGE */ 51615552b385SBrandon params[0] = t_point[v - vStart]; 51625552b385SBrandon if (islite) { 51635552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 51645552b385SBrandon PetscCall(EGlite_evaluate(edge, params, result)); 51655552b385SBrandon } else { 51665552b385SBrandon PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 51675552b385SBrandon PetscCall(EG_evaluate(edge, params, result)); 51685552b385SBrandon } 51695552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 51705552b385SBrandon } else if (faceID > 0) { 51715552b385SBrandon /* Snap to FACE */ 51725552b385SBrandon params[0] = u_point[v - vStart]; 51735552b385SBrandon params[1] = v_point[v - vStart]; 51745552b385SBrandon if (islite) { 51755552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 51765552b385SBrandon PetscCall(EGlite_evaluate(face, params, result)); 51775552b385SBrandon } else { 51785552b385SBrandon PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 51795552b385SBrandon PetscCall(EG_evaluate(face, params, result)); 51805552b385SBrandon } 5181c1cad2e7SMatthew G. Knepley for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5182c1cad2e7SMatthew G. Knepley } 5183c1cad2e7SMatthew G. Knepley } 51849566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 5185c1cad2e7SMatthew G. Knepley /* Clear out global coordinates */ 51866858538eSMatthew G. Knepley PetscCall(VecDestroy(&dm->coordinates[0].x)); 5187c1cad2e7SMatthew G. Knepley #endif 51883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5189c1cad2e7SMatthew G. Knepley } 5190c1cad2e7SMatthew G. Knepley 5191cc4c1da9SBarry Smith /*@ 51925552b385SBrandon DMPlexInflateToGeomModel - Wrapper function allowing two methods for inflating refined meshes to the underlying geometric domain. 51937bee2925SMatthew Knepley 51947bee2925SMatthew Knepley Collective 51957bee2925SMatthew Knepley 51967bee2925SMatthew Knepley Input Parameters: 51975552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 51985552b385SBrandon - useTUV - PetscBool indicating if the user would like to inflate the DMPlex to the underlying geometry 51995552b385SBrandon using (t) for nodes on EDGEs and (u, v) for nodes on FACEs or using the nodes (x, y, z) coordinates 52005552b385SBrandon and shortest distance routine. 52015552b385SBrandon If useTUV = PETSC_TRUE, use the (t) or (u, v) parameters to inflate the DMPlex to the CAD geometry. 52025552b385SBrandon If useTUV = PETSC_FALSE, use the nodes (x, y, z) coordinates and the shortest disctance routine. 52035552b385SBrandon 52045552b385SBrandon Notes: 52055552b385SBrandon DM with nodal coordinates modified so that they lie on the EDGEs and FACEs of the underlying geometry. 52065552b385SBrandon 52075552b385SBrandon (t) and (u, v) parameters for all DMPlex nodes on EDGEs and FACEs are stored in arrays within PetscContainers attached to the DM. 52085552b385SBrandon The containers have names "Point - Edge t Parameter", "Point - Face u Parameter", and "Point - Face v Parameter". 52095552b385SBrandon The arrays are organized by Point 0-based ID (i.e. [v-vstart] as defined in the DMPlex. 52105552b385SBrandon 52115552b385SBrandon Level: intermediate 52125552b385SBrandon 52135552b385SBrandon .seealso: `DMPlexGetGeomModelTUV()`, `DMPlexInflateToGeomModelUseTUV()`, `DMPlexInflateToGeomModelUseXYZ()` 52145552b385SBrandon @*/ 5215ce78bad3SBarry Smith PetscErrorCode DMPlexInflateToGeomModel(DM dm, PetscBool useTUV) PeNS 52165552b385SBrandon { 52175552b385SBrandon PetscFunctionBeginHot; 52185552b385SBrandon if (useTUV) { 52195552b385SBrandon PetscCall(DMPlexGetGeomModelTUV(dm)); 52205552b385SBrandon PetscCall(DMPlexInflateToGeomModelUseTUV(dm)); 52215552b385SBrandon } else { 52225552b385SBrandon PetscCall(DMPlexInflateToGeomModelUseXYZ(dm)); 52235552b385SBrandon } 52245552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 52255552b385SBrandon } 52265552b385SBrandon 52275552b385SBrandon #ifdef PETSC_HAVE_EGADS 52285552b385SBrandon /*@C 5229*bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodies - Returns an array of `PetscGeom` BODY objects attached to the referenced geometric model entity as well as the number of BODYs. 52305552b385SBrandon 52315552b385SBrandon Collective 52325552b385SBrandon 52335552b385SBrandon Input Parameter: 52345552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 52355552b385SBrandon 52365552b385SBrandon Output Parameters: 52375552b385SBrandon + bodies - Array of PetscGeom BODY objects referenced by the geometric model. 52385552b385SBrandon - numBodies - Number of BODYs referenced by the geometric model. Also the size of **bodies array. 52395552b385SBrandon 52405552b385SBrandon Level: intermediate 52415552b385SBrandon 52425552b385SBrandon .seealso: 52435552b385SBrandon @*/ 5244ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodies(DM dm, PetscGeom **bodies, PetscInt *numBodies) PeNS 52455552b385SBrandon { 52465552b385SBrandon PetscFunctionBeginHot; 52475552b385SBrandon PetscContainer modelObj; 52485552b385SBrandon PetscBool islite = PETSC_FALSE; 52495552b385SBrandon ego model, geom; 52505552b385SBrandon int oclass, mtype; 52515552b385SBrandon int *senses; 52525552b385SBrandon 52535552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 52545552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 52555552b385SBrandon if (!modelObj) { 52565552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 52575552b385SBrandon islite = PETSC_TRUE; 52585552b385SBrandon } 52595552b385SBrandon 52605552b385SBrandon // Get attached EGADS or EGADSlite model (pointer) 52615552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 52625552b385SBrandon 52635552b385SBrandon if (islite) { 52645552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 52655552b385SBrandon } else { 52665552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 52675552b385SBrandon } 52685552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 52695552b385SBrandon } 52705552b385SBrandon 52715552b385SBrandon /*@C 5272*bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyShells - Returns an array of `PetscGeom` SHELL objects attached to the referenced BODY geometric entity as well as the number of SHELLs. 52735552b385SBrandon 52745552b385SBrandon Collective 52755552b385SBrandon 52765552b385SBrandon Input Parameters: 52775552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 52785552b385SBrandon - body - PetscGeom BODY object containing the SHELL objects of interest. 52795552b385SBrandon 52805552b385SBrandon Output Parameters: 52815552b385SBrandon + shells - Array of PetscGeom SHELL objects referenced by the PetscGeom BODY object 52825552b385SBrandon - numShells - Number of SHELLs referenced by the PetscGeom BODY object. Also the size of **shells array. 52835552b385SBrandon 52845552b385SBrandon Level: intermediate 52855552b385SBrandon 52865552b385SBrandon .seealso: 52875552b385SBrandon @*/ 5288ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyShells(DM dm, PetscGeom body, PetscGeom **shells, PetscInt *numShells) PeNS 52895552b385SBrandon { 52905552b385SBrandon PetscFunctionBeginHot; 52915552b385SBrandon #ifdef PETSC_HAVE_EGADS 52925552b385SBrandon PetscContainer modelObj; 52935552b385SBrandon PetscBool islite = PETSC_FALSE; 52945552b385SBrandon 52955552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 52965552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 52975552b385SBrandon if (!modelObj) { 52985552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 52995552b385SBrandon islite = PETSC_TRUE; 53005552b385SBrandon } 53015552b385SBrandon 53025552b385SBrandon if (islite) { 53035552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, numShells, shells)); 53045552b385SBrandon } else { 53055552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, SHELL, numShells, shells)); 53065552b385SBrandon } 53075552b385SBrandon #endif 53085552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 53095552b385SBrandon } 53105552b385SBrandon 53115552b385SBrandon /*@C 5312*bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyFaces - Returns an array of `PetscGeom` FACE objects attached to the referenced BODY geometric entity as well as the number of FACEs. 53135552b385SBrandon 53145552b385SBrandon Collective 53155552b385SBrandon 53165552b385SBrandon Input Parameters: 53175552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 53185552b385SBrandon - body - PetscGeom BODY object containing the FACE objects of interest. 53195552b385SBrandon 53205552b385SBrandon Output Parameters: 53215552b385SBrandon + faces - Array of PetscGeom FACE objects referenced by the PetscGeom BODY object 53225552b385SBrandon - numFaces - Number of FACEs referenced by the PetscGeom BODY object. Also the size of **faces array. 53235552b385SBrandon 53245552b385SBrandon Level: intermediate 53255552b385SBrandon 53265552b385SBrandon .seealso: 53275552b385SBrandon @*/ 5328ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyFaces(DM dm, PetscGeom body, PetscGeom **faces, PetscInt *numFaces) PeNS 53295552b385SBrandon { 53305552b385SBrandon PetscFunctionBeginHot; 53315552b385SBrandon #ifdef PETSC_HAVE_EGADS 53325552b385SBrandon PetscContainer modelObj; 53335552b385SBrandon PetscBool islite = PETSC_FALSE; 53345552b385SBrandon 53355552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 53365552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 53375552b385SBrandon if (!modelObj) { 53385552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 53395552b385SBrandon islite = PETSC_TRUE; 53405552b385SBrandon } 53415552b385SBrandon 53425552b385SBrandon if (islite) { 53435552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, numFaces, faces)); 53445552b385SBrandon } else { 53455552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, numFaces, faces)); 53465552b385SBrandon } 53475552b385SBrandon #endif 53485552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 53495552b385SBrandon } 53505552b385SBrandon 53515552b385SBrandon /*@C 5352*bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyLoops - Returns an array of `PetscGeom` Loop objects attached to the referenced BODY geometric entity as well as the number of LOOPs. 53535552b385SBrandon 53545552b385SBrandon Collective 53555552b385SBrandon 53565552b385SBrandon Input Parameters: 53575552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 53585552b385SBrandon - body - PetscGeom BODY object containing the LOOP objects of interest. 53595552b385SBrandon 53605552b385SBrandon Output Parameters: 53615552b385SBrandon + loops - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 53625552b385SBrandon - numLoops - Number of LOOPs referenced by the PetscGeom BODY object. Also the size of **loops array. 53635552b385SBrandon 53645552b385SBrandon Level: intermediate 53655552b385SBrandon 53665552b385SBrandon .seealso: 53675552b385SBrandon @*/ 5368ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyLoops(DM dm, PetscGeom body, PetscGeom **loops, PetscInt *numLoops) PeNS 53695552b385SBrandon { 53705552b385SBrandon PetscFunctionBeginHot; 53715552b385SBrandon #ifdef PETSC_HAVE_EGADS 53725552b385SBrandon PetscContainer modelObj; 53735552b385SBrandon PetscBool islite = PETSC_FALSE; 53745552b385SBrandon 53755552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 53765552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 53775552b385SBrandon if (!modelObj) { 53785552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 53795552b385SBrandon islite = PETSC_TRUE; 53805552b385SBrandon } 53815552b385SBrandon 53825552b385SBrandon if (islite) { 53835552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 53845552b385SBrandon } else { 53855552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 53865552b385SBrandon } 53875552b385SBrandon #endif 53885552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 53895552b385SBrandon } 53905552b385SBrandon 53915552b385SBrandon /*@C 5392*bfe80ac4SPierre Jolivet DMPlexGetGeomModelShellFaces - Returns an array of `PetscGeom` FACE objects attached to the referenced SHELL geometric entity as well as the number of FACEs. 53935552b385SBrandon 53945552b385SBrandon Collective 53955552b385SBrandon 53965552b385SBrandon Input Parameters: 53975552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 53985552b385SBrandon . body - PetscGeom BODY object containing the FACE objects of interest. 53995552b385SBrandon - shell - PetscGeom SHELL object with FACEs of interest. 54005552b385SBrandon 54015552b385SBrandon Output Parameters: 54025552b385SBrandon + faces - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 54035552b385SBrandon - numFaces - Number of FACEs referenced by the PetscGeom SHELL object. Also the size of **faces array. 54045552b385SBrandon 54055552b385SBrandon Level: intermediate 54065552b385SBrandon 54075552b385SBrandon .seealso: 54085552b385SBrandon @*/ 5409ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelShellFaces(DM dm, PetscGeom body, PetscGeom shell, PetscGeom **faces, PetscInt *numFaces) PeNS 54105552b385SBrandon { 54115552b385SBrandon PetscFunctionBeginHot; 54125552b385SBrandon #ifdef PETSC_HAVE_EGADS 54135552b385SBrandon PetscContainer modelObj; 54145552b385SBrandon PetscBool islite = PETSC_FALSE; 54155552b385SBrandon 54165552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 54175552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 54185552b385SBrandon if (!modelObj) { 54195552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 54205552b385SBrandon islite = PETSC_TRUE; 54215552b385SBrandon } 54225552b385SBrandon 54235552b385SBrandon if (islite) { 54245552b385SBrandon PetscCall(EGlite_getBodyTopos(body, shell, FACE, numFaces, faces)); 54255552b385SBrandon } else { 54265552b385SBrandon PetscCall(EG_getBodyTopos(body, shell, FACE, numFaces, faces)); 54275552b385SBrandon } 54285552b385SBrandon #endif 54295552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 54305552b385SBrandon } 54315552b385SBrandon 54325552b385SBrandon /*@C 5433*bfe80ac4SPierre Jolivet DMPlexGetGeomModelFaceLoops - Returns an array of `PetscGeom` LOOP objects attached to the referenced FACE geometric entity as well as the number of LOOPs. 54345552b385SBrandon 54355552b385SBrandon Collective 54365552b385SBrandon 54375552b385SBrandon Input Parameters: 54385552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 54395552b385SBrandon . body - PetscGeom BODY object containing the LOOP objects of interest. 54405552b385SBrandon - face - PetscGeom FACE object with LOOPs of interest. 54415552b385SBrandon 54425552b385SBrandon Output Parameters: 54435552b385SBrandon + loops - Array of PetscGeom LOOP objects referenced by the PetscGeom FACE object 54445552b385SBrandon - numLoops - Number of LOOPs referenced by the PetscGeom FACE object. Also the size of **loops array. 54455552b385SBrandon 54465552b385SBrandon Level: intermediate 54475552b385SBrandon 54485552b385SBrandon .seealso: 54495552b385SBrandon @*/ 5450ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelFaceLoops(DM dm, PetscGeom body, PetscGeom face, PetscGeom **loops, PetscInt *numLoops) PeNS 54515552b385SBrandon { 54525552b385SBrandon PetscFunctionBeginHot; 54535552b385SBrandon #ifdef PETSC_HAVE_EGADS 54545552b385SBrandon PetscContainer modelObj; 54555552b385SBrandon PetscBool islite = PETSC_FALSE; 54565552b385SBrandon 54575552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 54585552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 54595552b385SBrandon if (!modelObj) { 54605552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 54615552b385SBrandon islite = PETSC_TRUE; 54625552b385SBrandon } 54635552b385SBrandon 54645552b385SBrandon if (islite) { 54655552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, LOOP, numLoops, loops)); 54665552b385SBrandon } else { 54675552b385SBrandon PetscCall(EG_getBodyTopos(body, face, LOOP, numLoops, loops)); 54685552b385SBrandon } 54695552b385SBrandon #endif 54705552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 54715552b385SBrandon } 54725552b385SBrandon 54735552b385SBrandon /*@C 5474*bfe80ac4SPierre Jolivet DMPlexGetGeomModelFaceEdges - Returns an array of `PetscGeom` EDGE objects attached to the referenced FACE geometric entity as well as the number of EDGEs. 54755552b385SBrandon 54765552b385SBrandon Collective 54775552b385SBrandon 54785552b385SBrandon Input Parameters: 54795552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 54805552b385SBrandon . body - PetscGeom Body object containing the EDGE objects of interest. 54815552b385SBrandon - face - PetscGeom FACE object with EDGEs of interest. 54825552b385SBrandon 54835552b385SBrandon Output Parameters: 54845552b385SBrandon + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom FACE object 54855552b385SBrandon - numEdges - Number of EDGEs referenced by the PetscGeom FACE object. Also the size of **edges array. 54865552b385SBrandon 54875552b385SBrandon Level: intermediate 54885552b385SBrandon 54895552b385SBrandon .seealso: 54905552b385SBrandon @*/ 5491ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelFaceEdges(DM dm, PetscGeom body, PetscGeom face, PetscGeom **edges, PetscInt *numEdges) PeNS 54925552b385SBrandon { 54935552b385SBrandon PetscFunctionBeginHot; 54945552b385SBrandon #ifdef PETSC_HAVE_EGADS 54955552b385SBrandon PetscContainer modelObj; 54965552b385SBrandon PetscBool islite = PETSC_FALSE; 54975552b385SBrandon 54985552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 54995552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 55005552b385SBrandon if (!modelObj) { 55015552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 55025552b385SBrandon islite = PETSC_TRUE; 55035552b385SBrandon } 55045552b385SBrandon 55055552b385SBrandon if (islite) { 55065552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, numEdges, edges)); 55075552b385SBrandon } else { 55085552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, numEdges, edges)); 55095552b385SBrandon } 55105552b385SBrandon #endif 55115552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 55125552b385SBrandon } 55135552b385SBrandon 55145552b385SBrandon /*@C 5515*bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyEdges - Returns an array of `PetscGeom` EDGE objects attached to the referenced BODY geometric entity as well as the number of EDGEs. 55165552b385SBrandon 55175552b385SBrandon Collective 55185552b385SBrandon 55195552b385SBrandon Input Parameters: 55205552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 55215552b385SBrandon - body - PetscGeom body object of interest. 55225552b385SBrandon 55235552b385SBrandon Output Parameters: 55245552b385SBrandon + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom BODY object 55255552b385SBrandon - numEdges - Number of EDGEs referenced by the PetscGeom BODY object. Also the size of **edges array. 55265552b385SBrandon 55275552b385SBrandon Level: intermediate 55285552b385SBrandon 55295552b385SBrandon .seealso: 55305552b385SBrandon @*/ 5531ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyEdges(DM dm, PetscGeom body, PetscGeom **edges, PetscInt *numEdges) PeNS 55325552b385SBrandon { 55335552b385SBrandon PetscFunctionBeginHot; 55345552b385SBrandon #ifdef PETSC_HAVE_EGADS 55355552b385SBrandon PetscContainer modelObj; 55365552b385SBrandon PetscBool islite = PETSC_FALSE; 55375552b385SBrandon 55385552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 55395552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 55405552b385SBrandon if (!modelObj) { 55415552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 55425552b385SBrandon islite = PETSC_TRUE; 55435552b385SBrandon } 55445552b385SBrandon 55455552b385SBrandon if (islite) { 55465552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 55475552b385SBrandon } else { 55485552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 55495552b385SBrandon } 55505552b385SBrandon #endif 55515552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 55525552b385SBrandon } 55535552b385SBrandon 55545552b385SBrandon /*@C 5555*bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyNodes - Returns an array of `PetscGeom` NODE objects attached to the referenced BODY geometric entity as well as the number of NODES. 55565552b385SBrandon 55575552b385SBrandon Collective 55585552b385SBrandon 55595552b385SBrandon Input Parameters: 55605552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 55615552b385SBrandon - body - PetscGeom body object of interest. 55625552b385SBrandon 55635552b385SBrandon Output Parameters: 55645552b385SBrandon + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom BODY object 55655552b385SBrandon - numNodes - Number of NODEs referenced by the PetscGeom BODY object. Also the size of **nodes array. 55665552b385SBrandon 55675552b385SBrandon Level: intermediate 55685552b385SBrandon 55695552b385SBrandon .seealso: 55705552b385SBrandon @*/ 5571ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyNodes(DM dm, PetscGeom body, PetscGeom **nodes, PetscInt *numNodes) PeNS 55725552b385SBrandon { 55735552b385SBrandon PetscFunctionBeginHot; 55745552b385SBrandon #ifdef PETSC_HAVE_EGADS 55755552b385SBrandon PetscContainer modelObj; 55765552b385SBrandon PetscBool islite = PETSC_FALSE; 55775552b385SBrandon 55785552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 55795552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 55805552b385SBrandon if (!modelObj) { 55815552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 55825552b385SBrandon islite = PETSC_TRUE; 55835552b385SBrandon } 55845552b385SBrandon 55855552b385SBrandon if (islite) { 55865552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 55875552b385SBrandon } else { 55885552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 55895552b385SBrandon } 55905552b385SBrandon #endif 55915552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 55925552b385SBrandon } 55935552b385SBrandon 55945552b385SBrandon /*@C 5595*bfe80ac4SPierre Jolivet DMPlexGetGeomModelEdgeNodes - Returns an array of `PetscGeom` NODE objects attached to the referenced EDGE geometric entity as well as the number of NODES. 55965552b385SBrandon 55975552b385SBrandon Collective 55985552b385SBrandon 55995552b385SBrandon Input Parameters: 56005552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 56015552b385SBrandon . body - PetscGeom body object containing the EDGE object of interest. 56025552b385SBrandon - edge - PetscGeom EDGE object with NODEs of interest. 56035552b385SBrandon 56045552b385SBrandon Output Parameters: 56055552b385SBrandon + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom EDGE object 56065552b385SBrandon - numNodes - Number of Nodes referenced by the PetscGeom EDGE object. Also the size of **nodes array. 56075552b385SBrandon 56085552b385SBrandon Level: intermediate 56095552b385SBrandon 56105552b385SBrandon .seealso: 56115552b385SBrandon @*/ 5612ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelEdgeNodes(DM dm, PetscGeom body, PetscGeom edge, PetscGeom **nodes, PetscInt *numNodes) PeNS 56135552b385SBrandon { 56145552b385SBrandon PetscFunctionBeginHot; 56155552b385SBrandon #ifdef PETSC_HAVE_EGADS 56165552b385SBrandon PetscContainer modelObj; 56175552b385SBrandon PetscBool islite = PETSC_FALSE; 56185552b385SBrandon 56195552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 56205552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 56215552b385SBrandon if (!modelObj) { 56225552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 56235552b385SBrandon islite = PETSC_TRUE; 56245552b385SBrandon } 56255552b385SBrandon 56265552b385SBrandon if (islite) { 56275552b385SBrandon PetscCall(EGlite_getBodyTopos(body, edge, NODE, numNodes, nodes)); 56285552b385SBrandon } else { 56295552b385SBrandon PetscCall(EG_getBodyTopos(body, edge, NODE, numNodes, nodes)); 56305552b385SBrandon } 56315552b385SBrandon #endif 56325552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 56335552b385SBrandon } 56345552b385SBrandon 56355552b385SBrandon /*@C 56365552b385SBrandon DMPlexGetGeomID - Returns ID number of the entity in the geometric (CAD) model 56375552b385SBrandon 56385552b385SBrandon Collective 56395552b385SBrandon 56405552b385SBrandon Input Parameters: 56415552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 56425552b385SBrandon . body - PetscGeom body object containing the lower level entity the ID number is being requested. 56435552b385SBrandon - topoObj - PetscGeom SHELL, FACE, LOOP, EDGE, or NODE object for which ID number is being requested. 56447bee2925SMatthew Knepley 56457bee2925SMatthew Knepley Output Parameter: 56465552b385SBrandon . id - ID number of the entity 56477bee2925SMatthew Knepley 56485552b385SBrandon Level: intermediate 56497bee2925SMatthew Knepley 56505552b385SBrandon .seealso: 56517bee2925SMatthew Knepley @*/ 5652ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomID(DM dm, PetscGeom body, PetscGeom topoObj, PetscInt *id) PeNS 5653d71ae5a4SJacob Faibussowitsch { 56545552b385SBrandon PetscFunctionBeginHot; 56555552b385SBrandon #ifdef PETSC_HAVE_EGADS 56565552b385SBrandon PetscContainer modelObj; 56575552b385SBrandon PetscBool islite = PETSC_FALSE; 56585552b385SBrandon int topoID; 56595552b385SBrandon 56605552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 56615552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 56625552b385SBrandon if (!modelObj) { 56635552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 56645552b385SBrandon islite = PETSC_TRUE; 56655552b385SBrandon } 56665552b385SBrandon 56675552b385SBrandon // Get Topology Object's ID 56685552b385SBrandon if (islite) { 56695552b385SBrandon topoID = EGlite_indexBodyTopo(body, topoObj); 56705552b385SBrandon } else { 56715552b385SBrandon topoID = EG_indexBodyTopo(body, topoObj); 56725552b385SBrandon } 56735552b385SBrandon 56745552b385SBrandon *id = topoID; 56757bee2925SMatthew Knepley #endif 56765552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 56775552b385SBrandon } 56785552b385SBrandon 56795552b385SBrandon /*@C 56805552b385SBrandon DMPlexGetGeomObject - Returns Geometry Object using the objects ID in the geometric (CAD) model 56815552b385SBrandon 56825552b385SBrandon Collective 56835552b385SBrandon 56845552b385SBrandon Input Parameters: 56855552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 56865552b385SBrandon . body - PetscGeom body object containing the lower level entity the referenced by the ID. 56875552b385SBrandon . geomType - Keyword SHELL, FACE, LOOP, EDGE, or NODE of the geometry type for which ID number is being requested. 56885552b385SBrandon - geomID - ID number of the geometry entity being requested. 56895552b385SBrandon 56905552b385SBrandon Output Parameter: 56915552b385SBrandon . geomObj - Geometry Object referenced by the ID number requested. 56925552b385SBrandon 56935552b385SBrandon Level: intermediate 56945552b385SBrandon 56955552b385SBrandon .seealso: 56965552b385SBrandon @*/ 5697ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomObject(DM dm, PetscGeom body, PetscInt geomType, PetscInt geomID, PetscGeom *geomObj) PeNS 56985552b385SBrandon { 56995552b385SBrandon PetscFunctionBeginHot; 57005552b385SBrandon #ifdef PETSC_HAVE_EGADS 57015552b385SBrandon PetscContainer modelObj; 57025552b385SBrandon PetscBool islite = PETSC_FALSE; 57035552b385SBrandon 57045552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 57055552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 57065552b385SBrandon if (!modelObj) { 57075552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 57085552b385SBrandon islite = PETSC_TRUE; 57095552b385SBrandon } 57105552b385SBrandon 57115552b385SBrandon // Get Topology Object's ID 57125552b385SBrandon if (islite) { 57135552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, geomType, geomID, geomObj)); 57145552b385SBrandon } else { 57155552b385SBrandon PetscCall(EG_objectBodyTopo(body, geomType, geomID, geomObj)); 57165552b385SBrandon } 57175552b385SBrandon #endif 57185552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 57195552b385SBrandon } 57205552b385SBrandon 57215552b385SBrandon /*@C 57225552b385SBrandon DMPlexGetGeomFaceNumOfControlPoints - Returns the total number of Control Points (and associated Weights) defining a FACE of a Geometry 57235552b385SBrandon 57245552b385SBrandon Not collective 57255552b385SBrandon 57265552b385SBrandon Input Parameters: 57275552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 57285552b385SBrandon - face - PetscGeom FACE object 57295552b385SBrandon 57305552b385SBrandon Output Parameter: 57315552b385SBrandon . numCntrlPnts - Number of Control Points (and Weights) defining the FACE 57325552b385SBrandon 57335552b385SBrandon Level: intermediate 57345552b385SBrandon 57355552b385SBrandon .seealso: 57365552b385SBrandon @*/ 5737ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomFaceNumOfControlPoints(DM dm, PetscGeom face, PetscInt *numCntrlPnts) PeNS 57385552b385SBrandon { 57395552b385SBrandon PetscFunctionBeginHot; 57405552b385SBrandon #ifdef PETSC_HAVE_EGADS 57415552b385SBrandon PetscContainer modelObj; 57425552b385SBrandon PetscBool islite = PETSC_FALSE; 57435552b385SBrandon PetscGeom geom, gRef; 57445552b385SBrandon PetscGeom *lobjs; 57455552b385SBrandon int Nl, oclass, mtype, goclass, gmtype; 57465552b385SBrandon int *lsenses, *gpinfo; 57475552b385SBrandon double *gprv; 57485552b385SBrandon 57495552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 57505552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 57515552b385SBrandon if (!modelObj) { 57525552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 57535552b385SBrandon islite = PETSC_TRUE; 57545552b385SBrandon } 57555552b385SBrandon 57565552b385SBrandon // Get Total Number of Control Points on FACE 57575552b385SBrandon if (islite) { 57585552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 57595552b385SBrandon PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 57605552b385SBrandon } else { 57615552b385SBrandon PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 57625552b385SBrandon PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 57635552b385SBrandon } 57645552b385SBrandon 57655552b385SBrandon *numCntrlPnts = gpinfo[2] * gpinfo[5]; 57665552b385SBrandon #endif 57675552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 57685552b385SBrandon } 57695552b385SBrandon 57705552b385SBrandon /*@C 57715552b385SBrandon DMPlexGetGeomBodyMassProperties - Returns the Volume, Surface Area, Center of Gravity, and Inertia about the Body's Center of Gravity 57725552b385SBrandon 57735552b385SBrandon Not collective 57745552b385SBrandon 57755552b385SBrandon Input Parameters: 57765552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 57775552b385SBrandon - body - PetscGeom BODY object 57785552b385SBrandon 57795552b385SBrandon Output Parameters: 57805552b385SBrandon + volume - Volume of the CAD Body attached to the DM Plex 57815552b385SBrandon . surfArea - Surface Area of the CAD Body attached to the DM Plex 57825552b385SBrandon . centerOfGravity - Array with the Center of Gravity coordinates of the CAD Body attached to the DM Plex [x, y, z] 57835552b385SBrandon . COGszie - Size of centerOfGravity[] Array 57845552b385SBrandon . inertiaMatrixCOG - Array containing the Inertia about the Body's Center of Gravity [Ixx, Ixy, Ixz, Iyx, Iyy, Iyz, Izx, Izy, Izz] 57855552b385SBrandon - IMCOGsize - Size of inertiaMatrixCOG[] Array 57865552b385SBrandon 57875552b385SBrandon Level: intermediate 57885552b385SBrandon 57895552b385SBrandon .seealso: 57905552b385SBrandon @*/ 5791ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) PeNS 57925552b385SBrandon { 57935552b385SBrandon PetscFunctionBeginHot; 57945552b385SBrandon #ifdef PETSC_HAVE_EGADS 57955552b385SBrandon PetscContainer modelObj; 57965552b385SBrandon PetscBool islite = PETSC_FALSE; 57975552b385SBrandon PetscScalar geomData[14]; 57985552b385SBrandon 57995552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 58005552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 58015552b385SBrandon if (!modelObj) { 58025552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 58035552b385SBrandon islite = PETSC_TRUE; 58045552b385SBrandon PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot provide geometric mass properties for geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep"); 58055552b385SBrandon } 58065552b385SBrandon 58075552b385SBrandon if (islite) { 58085552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " WARNING!! This functionality is not supported for EGADSlite files. \n")); 58095552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " All returned values are equal to 0 \n")); 58105552b385SBrandon } else { 58115552b385SBrandon PetscCall(EG_getMassProperties(body, geomData)); 58125552b385SBrandon } 58135552b385SBrandon 58145552b385SBrandon PetscCall(PetscMalloc2(3, centerOfGravity, 9, inertiaMatrixCOG)); 58155552b385SBrandon 58165552b385SBrandon if (!islite) { 58175552b385SBrandon *volume = geomData[0]; 58185552b385SBrandon *surfArea = geomData[1]; 58195552b385SBrandon for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = geomData[ii]; } 58205552b385SBrandon *COGsize = 3; 58215552b385SBrandon for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = geomData[ii]; } 58225552b385SBrandon *IMCOGsize = 9; 58235552b385SBrandon } else { 58245552b385SBrandon *volume = 0.; 58255552b385SBrandon *surfArea = 0.; 58265552b385SBrandon for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = 0.; } 58275552b385SBrandon *COGsize = 0; 58285552b385SBrandon for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = 0.; } 58295552b385SBrandon *IMCOGsize = 0; 58305552b385SBrandon } 58315552b385SBrandon #endif 58325552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 58335552b385SBrandon } 58345552b385SBrandon 5835ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) PeNS 58365552b385SBrandon { 58375552b385SBrandon PetscFunctionBegin; 58385552b385SBrandon PetscCall(PetscFree2(*centerOfGravity, *inertiaMatrixCOG)); 58395552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 58405552b385SBrandon } 58415552b385SBrandon 58425552b385SBrandon /*@C 58435552b385SBrandon DMPlexFreeGeomObject - Frees PetscGeom Objects 58445552b385SBrandon 58455552b385SBrandon Not collective 58465552b385SBrandon 58475552b385SBrandon Input Parameters: 58485552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 58495552b385SBrandon - geomObj - PetscGeom object 58505552b385SBrandon 58515552b385SBrandon Level: intermediate 58525552b385SBrandon 58535552b385SBrandon .seealso: 58545552b385SBrandon @*/ 5855ce78bad3SBarry Smith PetscErrorCode DMPlexFreeGeomObject(DM dm, PetscGeom *geomObj) PeNS 58565552b385SBrandon { 58575552b385SBrandon PetscFunctionBeginHot; 58585552b385SBrandon #ifdef PETSC_HAVE_EGADS 58595552b385SBrandon PetscContainer modelObj; 58605552b385SBrandon PetscBool islite = PETSC_FALSE; 58615552b385SBrandon 58625552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 58635552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 58645552b385SBrandon if (!modelObj) { 58655552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 58665552b385SBrandon islite = PETSC_TRUE; 58675552b385SBrandon } 58685552b385SBrandon 58695552b385SBrandon if (islite) { 58705552b385SBrandon EGlite_free(geomObj); 58715552b385SBrandon } else { 58725552b385SBrandon EG_free(geomObj); 58735552b385SBrandon } 58745552b385SBrandon #endif 58755552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 58765552b385SBrandon } 58775552b385SBrandon 58785552b385SBrandon /*@C 58795552b385SBrandon DMPlexGetGeomCntrlPntAndWeightData - Gets Control Point and Associated Weight Data for the Geometry attached to the DMPlex 58805552b385SBrandon 58815552b385SBrandon Not collective 58825552b385SBrandon 58835552b385SBrandon Input Parameter: 58845552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 58855552b385SBrandon 58865552b385SBrandon Output Parameters: 58875552b385SBrandon + cpHashTable - Hash Table containing the relationship between FACE ID and Control Point IDs. 58885552b385SBrandon . cpCoordDataLength - Length of cpCoordData Array. 58895552b385SBrandon . cpCoordData - Array holding the Geometry Control Point Coordinate Data. 58905552b385SBrandon . maxNumEquiv - Maximum Number of Equivalent Control Points (Control Points with the same coordinates but different IDs). 58915552b385SBrandon . cpEquiv - Matrix with a size(Number of Control Points, Number or Control Points) which stores a value of 1.0 in locations where Control Points with different IDS (row or column) have the same coordinates 58925552b385SBrandon . wHashTable - Hash Table containing the relationship between FACE ID and Control Point Weight. 58935552b385SBrandon . wDataLength - Length of wData Array. 58945552b385SBrandon - wData - Array holding the Weight for an associated Geometry Control Point. 58955552b385SBrandon 58965552b385SBrandon Note: 58975552b385SBrandon Must Call DMPLexGeomDataAndGrads() before calling this function. 58985552b385SBrandon 58995552b385SBrandon Level: intermediate 59005552b385SBrandon 59015552b385SBrandon .seealso: 59025552b385SBrandon @*/ 5903ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) PeNS 59045552b385SBrandon { 59055552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj, cpCoordDataLengthObj, wDataLengthObj, maxNumRelateObj; 59065552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 59075552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr, *maxNumEquivPtr; 59085552b385SBrandon PetscHMapI cpHashTableTemp, wHashTableTemp; 59095552b385SBrandon 59105552b385SBrandon PetscFunctionBeginHot; 59115552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 59125552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 59135552b385SBrandon if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 59145552b385SBrandon 59155552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 59165552b385SBrandon 59175552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 59185552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 59195552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 59205552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordDataLengthObj)); 59215552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 59225552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 59235552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 5924*bfe80ac4SPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Equivalency Matrix", (PetscObject *)cpEquiv)); 59255552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 59265552b385SBrandon 59275552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 59285552b385SBrandon PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTableTemp)); 59295552b385SBrandon PetscCall(PetscContainerGetPointer(cpCoordDataLengthObj, (void **)&cpCoordDataLengthPtr)); 59305552b385SBrandon PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTableTemp)); 59315552b385SBrandon PetscCall(PetscContainerGetPointer(wDataLengthObj, (void **)&wDataLengthPtr)); 59325552b385SBrandon PetscCall(PetscContainerGetPointer(maxNumRelateObj, (void **)&maxNumEquivPtr)); 59335552b385SBrandon 59345552b385SBrandon *cpCoordDataLength = *cpCoordDataLengthPtr; 59355552b385SBrandon *wDataLength = *wDataLengthPtr; 59365552b385SBrandon *maxNumEquiv = *maxNumEquivPtr; 59375552b385SBrandon *cpHashTable = cpHashTableTemp; 59385552b385SBrandon *wHashTable = wHashTableTemp; 59395552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, cpCoordData)); 59405552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, wData)); 59415552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 59425552b385SBrandon } 59435552b385SBrandon 59445552b385SBrandon PetscErrorCode DMPlexRestoreGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) 59455552b385SBrandon { 59465552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 59475552b385SBrandon 59485552b385SBrandon PetscFunctionBeginHot; 59495552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 59505552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, cpCoordData)); 59515552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 59525552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, wData)); 59535552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 59545552b385SBrandon } 59555552b385SBrandon 59565552b385SBrandon /*@C 59575552b385SBrandon DMPlexGetGeomGradData - Gets Point, Surface and Volume Gradients with respect to changes in Control Points and their associated Weights for the Geometry attached to the DMPlex . 59585552b385SBrandon 59595552b385SBrandon Not collective 59605552b385SBrandon 59615552b385SBrandon Input Parameter: 59625552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 59635552b385SBrandon 59645552b385SBrandon Output Parameters: 59655552b385SBrandon + cpSurfGradHashTable - Hash Table Relating the Control Point ID to the the Row in the cpSurfGrad Matrix 59665552b385SBrandon . cpSurfGrad - Matrix containing the Surface Gradient with respect to the Control Point Data. Data is ranged where the Row corresponds to Control Point ID and the Columns are associated with the Geometric FACE. 59675552b385SBrandon . cpArraySize - The size of arrays gradSACP and gradVolCP and is equal to 3 * total number of Control Points in the Geometry 59685552b385SBrandon . gradSACP - Array containing the Surface Area Gradient with respect to Control Point Data. Data is arranged by Control Point ID * 3 where 3 is for the coordinate dimension. 5969*bfe80ac4SPierre Jolivet . gradVolCP - Array containing the Volume Gradient with respect to Control Point Data. Data is arranged by Control Point ID * 3 where 3 is for the coordinate dimension. 59705552b385SBrandon . wArraySize - The size of arrayws gradSAW and gradVolW and is equal to the total number of Control Points in the Geometry. 59715552b385SBrandon . gradSAW - Array containing the Surface Area Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 59725552b385SBrandon - gradVolW - Array containing the Volume Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 59735552b385SBrandon 59745552b385SBrandon Notes: 59755552b385SBrandon Must Call DMPLexGeomDataAndGrads() before calling this function. 59765552b385SBrandon 59775552b385SBrandon gradVolCP and gradVolW are only available when DMPlexGeomDataAndGrads() is called with fullGeomGrad = PETSC_TRUE. 59785552b385SBrandon 59795552b385SBrandon Level: intermediate 59805552b385SBrandon 59815552b385SBrandon .seealso: DMPlexGeomDataAndGrads 59825552b385SBrandon @*/ 59835552b385SBrandon PetscErrorCode DMPlexGetGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 59845552b385SBrandon { 59855552b385SBrandon PetscContainer modelObj, cpSurfGradHashTableObj, cpArraySizeObj, wArraySizeObj; 59865552b385SBrandon Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 59875552b385SBrandon PetscInt *cpArraySizePtr, *wArraySizePtr; 59885552b385SBrandon PetscHMapI cpSurfGradHashTableTemp; 59895552b385SBrandon 59905552b385SBrandon PetscFunctionBeginHot; 59915552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 59925552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 59935552b385SBrandon if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 59945552b385SBrandon 59955552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 59965552b385SBrandon 59975552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 59985552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&cpSurfGradHashTableObj)); 59995552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Matrix", (PetscObject *)cpSurfGrad)); 60005552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpArraySizeObj)); 60015552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 60025552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 60035552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wArraySizeObj)); 60045552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 60055552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 60065552b385SBrandon 60075552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 60085552b385SBrandon if (cpSurfGradHashTableObj) { 60095552b385SBrandon PetscCall(PetscContainerGetPointer(cpSurfGradHashTableObj, (void **)&cpSurfGradHashTableTemp)); 60105552b385SBrandon *cpSurfGradHashTable = cpSurfGradHashTableTemp; 60115552b385SBrandon } 60125552b385SBrandon 60135552b385SBrandon if (cpArraySizeObj) { 60145552b385SBrandon PetscCall(PetscContainerGetPointer(cpArraySizeObj, (void **)&cpArraySizePtr)); 60155552b385SBrandon *cpArraySize = *cpArraySizePtr; 60165552b385SBrandon } 60175552b385SBrandon 60185552b385SBrandon if (gradSACPVec) PetscCall(VecGetArrayWrite(gradSACPVec, gradSACP)); 60195552b385SBrandon if (gradVolCPVec) PetscCall(VecGetArrayWrite(gradVolCPVec, gradVolCP)); 60205552b385SBrandon if (gradSAWVec) PetscCall(VecGetArrayWrite(gradSAWVec, gradSAW)); 60215552b385SBrandon if (gradVolWVec) PetscCall(VecGetArrayWrite(gradVolWVec, gradVolW)); 60225552b385SBrandon 60235552b385SBrandon if (wArraySizeObj) { 60245552b385SBrandon PetscCall(PetscContainerGetPointer(wArraySizeObj, (void **)&wArraySizePtr)); 60255552b385SBrandon *wArraySize = *wArraySizePtr; 60265552b385SBrandon } 60275552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 60285552b385SBrandon } 60295552b385SBrandon 60305552b385SBrandon PetscErrorCode DMPlexRestoreGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 60315552b385SBrandon { 60325552b385SBrandon Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 60337bee2925SMatthew Knepley 60347bee2925SMatthew Knepley PetscFunctionBegin; 60355552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 60365552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 60375552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 60385552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 60395552b385SBrandon 60405552b385SBrandon if (gradSACPVec) PetscCall(VecRestoreArrayWrite(gradSACPVec, gradSACP)); 60415552b385SBrandon if (gradVolCPVec) PetscCall(VecRestoreArrayWrite(gradVolCPVec, gradVolCP)); 60425552b385SBrandon if (gradSAWVec) PetscCall(VecRestoreArrayWrite(gradSAWVec, gradSAW)); 60435552b385SBrandon if (gradVolWVec) PetscCall(VecRestoreArrayWrite(gradVolWVec, gradVolW)); 60443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60457bee2925SMatthew Knepley } 60465552b385SBrandon 60475552b385SBrandon /*@C 60485552b385SBrandon DMPlexGetGeomCntrlPntMaps - Gets arrays which maps Control Point IDs to their associated Geometry FACE, EDGE, and VERTEX. 60495552b385SBrandon 60505552b385SBrandon Not collective 60515552b385SBrandon 60525552b385SBrandon Input Parameter: 60535552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 60545552b385SBrandon 60555552b385SBrandon Output Parameters: 60565552b385SBrandon + numCntrlPnts - Number of Control Points defining the Geometry attached to the DMPlex 60575552b385SBrandon . cntrlPntFaceMap - Array containing the FACE ID for the Control Point. Array index corresponds to Control Point ID. 60585552b385SBrandon . cntrlPntWeightFaceMap - Array containing the FACE ID for the Control Point Weight. Array index corresponds to Control Point ID. 60595552b385SBrandon . cntrlPntEdgeMap - Array containing the EDGE ID for the Control Point. Array index corresponds to Control Point ID. 60605552b385SBrandon . cntrlPntWeightEdgeMap - Array containing the EDGE ID for the Control Point Weight. Array index corresponds to Control Point ID. 60615552b385SBrandon . cntrlPntVertexMap - Array containing the VERTEX ID for the Control Point. Array index corresponds to Control Point ID. 60625552b385SBrandon - cntrlPntWeightVertexMap - Array containing the VERTEX ID for the Control Point Weight. Array index corresponds to Control Point ID. 60635552b385SBrandon 60645552b385SBrandon Note: 60655552b385SBrandon Arrays are initialized to -1. Array elements with a -1 value indicates that the Control Point or Control Point Weight not associated with the referenced Geometric entity in the array name. 60665552b385SBrandon 60675552b385SBrandon Level: intermediate 60685552b385SBrandon 60695552b385SBrandon .seealso: DMPlexGeomDataAndGrads 60705552b385SBrandon @*/ 60715552b385SBrandon PetscErrorCode DMPlexGetGeomCntrlPntMaps(DM dm, PetscInt *numCntrlPnts, PetscInt **cntrlPntFaceMap, PetscInt **cntrlPntWeightFaceMap, PetscInt **cntrlPntEdgeMap, PetscInt **cntrlPntWeightEdgeMap, PetscInt **cntrlPntVertexMap, PetscInt **cntrlPntWeightVertexMap) 60725552b385SBrandon { 60735552b385SBrandon PetscFunctionBeginHot; 60745552b385SBrandon #ifdef PETSC_HAVE_EGADS 60755552b385SBrandon PetscContainer modelObj, numCntrlPntsObj, cntrlPntFaceMapObj, cntrlPntWeightFaceMapObj, cntrlPntEdgeMapObj, cntrlPntWeightEdgeMapObj, cntrlPntVertexMapObj, cntrlPntWeightVertexMapObj; 60765552b385SBrandon PetscInt *numCntrlPntsPtr, *cntrlPntFaceMapPtr, *cntrlPntWeightFaceMapPtr, *cntrlPntEdgeMapPtr, *cntrlPntWeightEdgeMapPtr, *cntrlPntVertexMapPtr, *cntrlPntWeightVertexMapPtr; 60775552b385SBrandon 60785552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 60795552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 60805552b385SBrandon if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 60815552b385SBrandon 60825552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 60835552b385SBrandon 60845552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 60855552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&numCntrlPntsObj)); 60865552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cntrlPntFaceMapObj)); 60875552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&cntrlPntWeightFaceMapObj)); 60885552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cntrlPntEdgeMapObj)); 60895552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&cntrlPntWeightEdgeMapObj)); 60905552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cntrlPntVertexMapObj)); 60915552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&cntrlPntWeightVertexMapObj)); 60925552b385SBrandon 60935552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 60945552b385SBrandon if (numCntrlPntsObj) { 60955552b385SBrandon PetscCall(PetscContainerGetPointer(numCntrlPntsObj, (void **)&numCntrlPntsPtr)); 60965552b385SBrandon *numCntrlPnts = *numCntrlPntsPtr; 60975552b385SBrandon } 60985552b385SBrandon 60995552b385SBrandon if (cntrlPntFaceMapObj) { 61005552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntFaceMapObj, (void **)&cntrlPntFaceMapPtr)); 61015552b385SBrandon *cntrlPntFaceMap = cntrlPntFaceMapPtr; 61025552b385SBrandon } 61035552b385SBrandon 61045552b385SBrandon if (cntrlPntWeightFaceMapObj) { 61055552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightFaceMapObj, (void **)&cntrlPntWeightFaceMapPtr)); 61065552b385SBrandon *cntrlPntWeightFaceMap = cntrlPntWeightFaceMapPtr; 61075552b385SBrandon } 61085552b385SBrandon 61095552b385SBrandon if (cntrlPntEdgeMapObj) { 61105552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntEdgeMapObj, (void **)&cntrlPntEdgeMapPtr)); 61115552b385SBrandon *cntrlPntEdgeMap = cntrlPntEdgeMapPtr; 61125552b385SBrandon } 61135552b385SBrandon 61145552b385SBrandon if (cntrlPntWeightEdgeMapObj) { 61155552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightEdgeMapObj, (void **)&cntrlPntWeightEdgeMapPtr)); 61165552b385SBrandon *cntrlPntWeightEdgeMap = cntrlPntWeightEdgeMapPtr; 61175552b385SBrandon } 61185552b385SBrandon 61195552b385SBrandon if (cntrlPntVertexMapObj) { 61205552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntVertexMapObj, (void **)&cntrlPntVertexMapPtr)); 61215552b385SBrandon *cntrlPntVertexMap = cntrlPntVertexMapPtr; 61225552b385SBrandon } 61235552b385SBrandon 61245552b385SBrandon if (cntrlPntWeightVertexMapObj) { 61255552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightVertexMapObj, (void **)&cntrlPntWeightVertexMapPtr)); 61265552b385SBrandon *cntrlPntWeightVertexMap = cntrlPntWeightVertexMapPtr; 61275552b385SBrandon } 61285552b385SBrandon 61295552b385SBrandon #endif 61305552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 61315552b385SBrandon } 61325552b385SBrandon 61335552b385SBrandon #endif 6134