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]; 3133a7d0413SPierre Jolivet 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]; 4153a7d0413SPierre Jolivet 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; 486bfe80ac4SPierre 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 710bfe80ac4SPierre 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)); 7843a7d0413SPierre Jolivet 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 7903a7d0413SPierre Jolivet 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 8063a7d0413SPierre Jolivet 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); 850*b6555650SPierre Jolivet return PETSC_SUCCESS; 8515552b385SBrandon } 8525552b385SBrandon 8535552b385SBrandon static PetscErrorCode DMPlexEGADSClose_Private(void **context) 8545552b385SBrandon { 8555552b385SBrandon if (*context) EG_close((ego)*context); 856*b6555650SPierre Jolivet return PETSC_SUCCESS; 8575552b385SBrandon } 8585552b385SBrandon 8595552b385SBrandon PetscErrorCode DMPlexEGADSliteDestroy_Private(void **context) 8605552b385SBrandon { 8615552b385SBrandon if (*context) EGlite_deleteObject((ego)*context); 862*b6555650SPierre Jolivet return PETSC_SUCCESS; 8637bee2925SMatthew Knepley } 8647bee2925SMatthew Knepley 8655552b385SBrandon PetscErrorCode DMPlexEGADSliteClose_Private(void **context) 866d71ae5a4SJacob Faibussowitsch { 8675552b385SBrandon if (*context) EGlite_close((ego)*context); 868*b6555650SPierre Jolivet return PETSC_SUCCESS; 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 /* --------------------------------------------------------------------------------------------------- 893f0b74427SPierre Jolivet Generate PETSc DMPlex 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)); 9493a7d0413SPierre Jolivet 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) { 13033a7d0413SPierre Jolivet 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; 1467*b6555650SPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 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 // --------------------------------------------------------------------------------------------------- 1492f0b74427SPierre Jolivet // Generate PETSc DMPlex 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 // --------------------------------------------------------------------------------------------------- 2107f0b74427SPierre Jolivet // Generate PETSc DMPlex 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)); 27433a7d0413SPierre Jolivet else PetscCall(DMPlexCreateGeom(comm, context, model, dm, islite)); 27445552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 27455552b385SBrandon #else 27465552b385SBrandon SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 27475552b385SBrandon #endif 27485552b385SBrandon } 27495552b385SBrandon 27505552b385SBrandon #if defined(PETSC_HAVE_EGADS) 27515552b385SBrandon /*@C 27525552b385SBrandon DMPlex_Surface_Grad - Exposes the Geometry's Control Points and Weights and Calculates the Mesh Topology Boundary Nodes Gradient 27535552b385SBrandon with respect the associated geometry's Control Points and Weights. 27545552b385SBrandon 27555552b385SBrandon // ----- Depreciated ---- See DMPlexGeomDataAndGrads ------ // 27565552b385SBrandon 27575552b385SBrandon Collective 27585552b385SBrandon 27595552b385SBrandon Input Parameters: 27605552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 27615552b385SBrandon 27625552b385SBrandon Output Parameter: 27635552b385SBrandon . 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 27645552b385SBrandon 27655552b385SBrandon Level: intermediate 27665552b385SBrandon 27675552b385SBrandon .seealso: 27685552b385SBrandon @*/ 27695552b385SBrandon PetscErrorCode DMPlex_Surface_Grad(DM dm) 27705552b385SBrandon { 27715552b385SBrandon ego model, geom, *bodies, *fobjs; 27725552b385SBrandon PetscContainer modelObj; 27735552b385SBrandon int oclass, mtype, *senses; 27745552b385SBrandon int Nb, Nf; 27755552b385SBrandon PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 27765552b385SBrandon PetscHMapI pointSurfGradRow_Start = NULL; 27775552b385SBrandon Mat pointSurfGrad; 27785552b385SBrandon IS faceLabelValues, edgeLabelValues, vertexLabelValues; 27795552b385SBrandon PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 27805552b385SBrandon PetscBool islite = PETSC_FALSE; 27815552b385SBrandon 27825552b385SBrandon PetscFunctionBegin; 27835552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 27845552b385SBrandon if (!modelObj) { 27855552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 27865552b385SBrandon islite = PETSC_TRUE; 27875552b385SBrandon 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"); 27885552b385SBrandon } 27895552b385SBrandon 27905552b385SBrandon // Get attached EGADS model (pointer) 27915552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 27925552b385SBrandon 27935552b385SBrandon // Get the bodies in the model 27945552b385SBrandon if (islite) { 27955552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 27965552b385SBrandon } else { 27975552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 27985552b385SBrandon } 27995552b385SBrandon 28005552b385SBrandon ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 28015552b385SBrandon 28025552b385SBrandon // Get the total number of FACEs in the model 28035552b385SBrandon if (islite) { 28045552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 28055552b385SBrandon } else { 28065552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 28075552b385SBrandon } 28085552b385SBrandon 28095552b385SBrandon // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 28105552b385SBrandon // This will provide the total number of DMPlex points on the boundary of the geometry 28115552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 28125552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 28135552b385SBrandon 28145552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 28155552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 28165552b385SBrandon 28175552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 28185552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 28195552b385SBrandon 28205552b385SBrandon const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 28215552b385SBrandon PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 28225552b385SBrandon PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 28235552b385SBrandon PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 28245552b385SBrandon 28255552b385SBrandon // Get the points associated with each FACE, EDGE and VERTEX label in the DM 28265552b385SBrandon PetscInt totalNumPoints = 0; 28275552b385SBrandon for (int ii = 0; ii < faceLabelSize; ++ii) { 28285552b385SBrandon // Cycle through FACE labels 28295552b385SBrandon PetscInt size; 28305552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[ii], &size)); 28315552b385SBrandon totalNumPoints += size; 28325552b385SBrandon } 28335552b385SBrandon PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 28345552b385SBrandon PetscCall(ISDestroy(&faceLabelValues)); 28355552b385SBrandon 28365552b385SBrandon for (int ii = 0; ii < edgeLabelSize; ++ii) { 28375552b385SBrandon // Cycle Through EDGE Labels 28385552b385SBrandon PetscInt size; 28395552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[ii], &size)); 28405552b385SBrandon totalNumPoints += size; 28415552b385SBrandon } 28425552b385SBrandon PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 28435552b385SBrandon PetscCall(ISDestroy(&edgeLabelValues)); 28445552b385SBrandon 28455552b385SBrandon for (int ii = 0; ii < vertexLabelSize; ++ii) { 28465552b385SBrandon // Cycle Through VERTEX Labels 28475552b385SBrandon PetscInt size; 28485552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 28495552b385SBrandon totalNumPoints += size; 28505552b385SBrandon } 28515552b385SBrandon PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 28525552b385SBrandon PetscCall(ISDestroy(&vertexLabelValues)); 28535552b385SBrandon 28545552b385SBrandon int maxNumCPs = 0; 28555552b385SBrandon int totalNumCPs = 0; 28565552b385SBrandon ego bRef, bPrev, bNext, fgeom, *lobjs; 28575552b385SBrandon int id, boclass, bmtype, *bpinfo; 28585552b385SBrandon int foclass, fmtype, Nl, *lsenses; 28595552b385SBrandon double *bprv; 28605552b385SBrandon double fdata[4]; 28615552b385SBrandon 28625552b385SBrandon // Create Hash Tables 28635552b385SBrandon PetscInt cntr = 0, wcntr = 0; 28645552b385SBrandon PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 28655552b385SBrandon PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 28665552b385SBrandon 28675552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 28685552b385SBrandon // Need to get the maximum number of Control Points defining the FACEs 28695552b385SBrandon ego face = fobjs[ii]; 28705552b385SBrandon int maxNumCPs_temp; 28715552b385SBrandon 28725552b385SBrandon if (islite) { 28735552b385SBrandon id = EGlite_indexBodyTopo(body, face); 28745552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 28755552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 28765552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 28775552b385SBrandon } else { 28785552b385SBrandon id = EG_indexBodyTopo(body, face); 28795552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 28805552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 28815552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 28825552b385SBrandon } 28835552b385SBrandon 28845552b385SBrandon maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 28855552b385SBrandon totalNumCPs += bpinfo[2] * bpinfo[5]; 28865552b385SBrandon 28875552b385SBrandon if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 28885552b385SBrandon } 28895552b385SBrandon 28905552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 28915552b385SBrandon PetscInt cpCoordDataLength = 3 * totalNumCPs; 28925552b385SBrandon PetscInt wDataLength = totalNumCPs; 28935552b385SBrandon cpCoordDataLengthPtr = &cpCoordDataLength; 28945552b385SBrandon wDataLengthPtr = &wDataLength; 28955552b385SBrandon PetscScalar *cntrlPtCoords, *cntrlPtWeights; 28965552b385SBrandon PetscMalloc1(cpCoordDataLength, &cntrlPtCoords); 28975552b385SBrandon PetscMalloc1(wDataLength, &cntrlPtWeights); 28985552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 28995552b385SBrandon // Need to Populate Control Point Coordinates and Weight Vectors 29005552b385SBrandon ego face = fobjs[ii]; 29015552b385SBrandon PetscHashIter hashKeyIter, wHashKeyIter; 29025552b385SBrandon PetscBool hashKeyFound, wHashKeyFound; 29035552b385SBrandon 29045552b385SBrandon if (islite) { 29055552b385SBrandon id = EGlite_indexBodyTopo(body, face); 29065552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 29075552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 29085552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 29095552b385SBrandon } else { 29105552b385SBrandon id = EG_indexBodyTopo(body, face); 29115552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 29125552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 29135552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 29145552b385SBrandon } 29155552b385SBrandon 29165552b385SBrandon // Store Face ID to 1st Row of Control Point Vector 29175552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 29185552b385SBrandon 29193a7d0413SPierre Jolivet if (!hashKeyFound) PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); 29205552b385SBrandon 29215552b385SBrandon int offsetCoord = bpinfo[3] + bpinfo[6]; 29225552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 29235552b385SBrandon cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 29245552b385SBrandon cntr += 1; 29255552b385SBrandon } 29265552b385SBrandon 29275552b385SBrandon // Store Face ID to 1st Row of Control Point Weight Vector 29285552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 29295552b385SBrandon 29303a7d0413SPierre Jolivet if (!wHashKeyFound) PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); 29315552b385SBrandon 29325552b385SBrandon int offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 29335552b385SBrandon for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 29345552b385SBrandon cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 29355552b385SBrandon wcntr += 1; 29365552b385SBrandon } 29375552b385SBrandon } 29385552b385SBrandon 29395552b385SBrandon // Attach Control Point and Weight Data to DM 29405552b385SBrandon { 29415552b385SBrandon PetscContainer cpOrgObj, cpCoordObj, cpCoordLengthObj; 29425552b385SBrandon PetscContainer wOrgObj, wValObj, wDataLengthObj; 29435552b385SBrandon 29445552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 29455552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 29465552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 29475552b385SBrandon PetscCall(PetscContainerDestroy(&cpOrgObj)); 29485552b385SBrandon 29495552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordObj)); 29505552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordObj, cntrlPtCoords)); 29515552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cpCoordObj)); 29525552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordObj)); 29535552b385SBrandon 29545552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 29555552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 29565552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 29575552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 29585552b385SBrandon 29595552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 29605552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 29615552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 29625552b385SBrandon PetscCall(PetscContainerDestroy(&wOrgObj)); 29635552b385SBrandon 29645552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wValObj)); 29655552b385SBrandon PetscCall(PetscContainerSetPointer(wValObj, cntrlPtWeights)); 29665552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)wValObj)); 29675552b385SBrandon PetscCall(PetscContainerDestroy(&wValObj)); 29685552b385SBrandon 29695552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 29705552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 29715552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 29725552b385SBrandon PetscCall(PetscContainerDestroy(&wDataLengthObj)); 29735552b385SBrandon } 29745552b385SBrandon 29755552b385SBrandon // Define Matrix to store Surface Gradient information dx_i/dCPj_i 29765552b385SBrandon PetscInt gcntr = 0; 29775552b385SBrandon const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 29785552b385SBrandon const PetscInt colSize = 4 * Nf; 29795552b385SBrandon 29805552b385SBrandon // Create Point Surface Gradient Matrix 29815552b385SBrandon MatCreate(PETSC_COMM_WORLD, &pointSurfGrad); 29825552b385SBrandon MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize); 29835552b385SBrandon MatSetType(pointSurfGrad, MATAIJ); 29845552b385SBrandon MatSetUp(pointSurfGrad); 29855552b385SBrandon 29865552b385SBrandon // Create Hash Table to store Point's stare row in surfaceGrad[][] 29875552b385SBrandon PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 29885552b385SBrandon 29895552b385SBrandon // Get Coordinates for the DMPlex point 29905552b385SBrandon DM cdm; 29915552b385SBrandon PetscInt dE, Nv; 29925552b385SBrandon Vec coordinatesLocal; 29935552b385SBrandon PetscScalar *coords = NULL; 29945552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 29955552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &dE)); 29965552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 29975552b385SBrandon 29985552b385SBrandon // CYCLE THROUGH FACEs 29995552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 30005552b385SBrandon ego face = fobjs[ii]; 30015552b385SBrandon ego *eobjs, *nobjs; 30025552b385SBrandon PetscInt fid, Ne, Nn; 30035552b385SBrandon DMLabel faceLabel, edgeLabel, nodeLabel; 30045552b385SBrandon PetscHMapI currFaceUniquePoints = NULL; 30055552b385SBrandon IS facePoints, edgePoints, nodePoints; 30065552b385SBrandon const PetscInt *fIndices, *eIndices, *nIndices; 30075552b385SBrandon PetscInt fSize, eSize, nSize; 30085552b385SBrandon PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 30095552b385SBrandon PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 30105552b385SBrandon PetscInt cfCntr = 0; 30115552b385SBrandon 30125552b385SBrandon // Get Geometry Object for the Current FACE 30135552b385SBrandon if (islite) { 30145552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 30155552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 30165552b385SBrandon } else { 30175552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 30185552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 30195552b385SBrandon } 30205552b385SBrandon 30215552b385SBrandon // Get all EDGE and NODE objects attached to the current FACE 30225552b385SBrandon if (islite) { 30235552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 30245552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 30255552b385SBrandon } else { 30265552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 30275552b385SBrandon PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 30285552b385SBrandon } 30295552b385SBrandon 30305552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 30315552b385SBrandon if (islite) { 30325552b385SBrandon fid = EGlite_indexBodyTopo(body, face); 30335552b385SBrandon } else { 30345552b385SBrandon fid = EG_indexBodyTopo(body, face); 30355552b385SBrandon } 30365552b385SBrandon 30375552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 30385552b385SBrandon PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 30395552b385SBrandon PetscCall(ISGetIndices(facePoints, &fIndices)); 30405552b385SBrandon PetscCall(ISGetSize(facePoints, &fSize)); 30415552b385SBrandon 30425552b385SBrandon PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 30435552b385SBrandon 30445552b385SBrandon for (int jj = 0; jj < fSize; ++jj) { 30455552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 30465552b385SBrandon 30475552b385SBrandon if (!fHashKeyFound) { 30485552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 30495552b385SBrandon cfCntr += 1; 30505552b385SBrandon } 30515552b385SBrandon 30525552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 30535552b385SBrandon 30545552b385SBrandon if (!pHashKeyFound) { 30555552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 30565552b385SBrandon gcntr += 3 * maxNumCPs; 30575552b385SBrandon } 30585552b385SBrandon } 30595552b385SBrandon PetscCall(ISRestoreIndices(facePoints, &fIndices)); 30605552b385SBrandon PetscCall(ISDestroy(&facePoints)); 30615552b385SBrandon 30625552b385SBrandon // 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. 30635552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 30645552b385SBrandon ego edge = eobjs[jj]; 30655552b385SBrandon PetscBool containLabelValue; 30665552b385SBrandon 30675552b385SBrandon if (islite) { 30685552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 30695552b385SBrandon } else { 30705552b385SBrandon id = EG_indexBodyTopo(body, edge); 30715552b385SBrandon } 30725552b385SBrandon 30735552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 30745552b385SBrandon PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 30755552b385SBrandon 30765552b385SBrandon if (containLabelValue) { 30775552b385SBrandon PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 30785552b385SBrandon PetscCall(ISGetIndices(edgePoints, &eIndices)); 30795552b385SBrandon PetscCall(ISGetSize(edgePoints, &eSize)); 30805552b385SBrandon 30815552b385SBrandon for (int kk = 0; kk < eSize; ++kk) { 30825552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 30835552b385SBrandon 30845552b385SBrandon if (!eHashKeyFound) { 30855552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 30865552b385SBrandon cfCntr += 1; 30875552b385SBrandon } 30885552b385SBrandon 30895552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 30905552b385SBrandon 30915552b385SBrandon if (!pHashKeyFound) { 30925552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 30935552b385SBrandon gcntr += 3 * maxNumCPs; 30945552b385SBrandon } 30955552b385SBrandon } 30965552b385SBrandon PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 30975552b385SBrandon PetscCall(ISDestroy(&edgePoints)); 30985552b385SBrandon } 30995552b385SBrandon } 31005552b385SBrandon 31015552b385SBrandon // 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. 31025552b385SBrandon for (int jj = 0; jj < Nn; ++jj) { 31035552b385SBrandon ego node = nobjs[jj]; 31045552b385SBrandon 31055552b385SBrandon if (islite) { 31065552b385SBrandon id = EGlite_indexBodyTopo(body, node); 31075552b385SBrandon } else { 31085552b385SBrandon id = EG_indexBodyTopo(body, node); 31095552b385SBrandon } 31105552b385SBrandon 31115552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 31125552b385SBrandon PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 31135552b385SBrandon PetscCall(ISGetIndices(nodePoints, &nIndices)); 31145552b385SBrandon PetscCall(ISGetSize(nodePoints, &nSize)); 31155552b385SBrandon 31165552b385SBrandon for (int kk = 0; kk < nSize; ++kk) { 31175552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 31185552b385SBrandon 31195552b385SBrandon if (!nHashKeyFound) { 31205552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 31215552b385SBrandon cfCntr += 1; 31225552b385SBrandon } 31235552b385SBrandon 31245552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 31255552b385SBrandon if (!pHashKeyFound) { 31265552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 31275552b385SBrandon gcntr += 3 * maxNumCPs; 31285552b385SBrandon } 31295552b385SBrandon } 31305552b385SBrandon PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 31315552b385SBrandon PetscCall(ISDestroy(&nodePoints)); 31325552b385SBrandon } 31335552b385SBrandon 31345552b385SBrandon // Get the Total Number of entries in the Hash Table 31355552b385SBrandon PetscInt currFaceUPSize; 31365552b385SBrandon PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 31375552b385SBrandon 31385552b385SBrandon // Get Keys 31395552b385SBrandon PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 31405552b385SBrandon PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 31415552b385SBrandon 31425552b385SBrandon // Cycle through all points on the current FACE 31435552b385SBrandon for (int jj = 0; jj < currFaceUPSize; ++jj) { 31445552b385SBrandon PetscInt currPointID = currFaceUPKeys[jj]; 31455552b385SBrandon PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 31465552b385SBrandon 31475552b385SBrandon // Get UV position of FACE 31485552b385SBrandon double params[2], range[4], eval[18]; 31495552b385SBrandon int peri; 31505552b385SBrandon 31515552b385SBrandon if (islite) { 31525552b385SBrandon PetscCall(EGlite_getRange(face, range, &peri)); 31535552b385SBrandon } else { 31545552b385SBrandon PetscCall(EG_getRange(face, range, &peri)); 31555552b385SBrandon } 31565552b385SBrandon 31575552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 31585552b385SBrandon 31595552b385SBrandon if (islite) { 31605552b385SBrandon PetscCall(EGlite_evaluate(face, params, eval)); 31615552b385SBrandon } else { 31625552b385SBrandon PetscCall(EG_evaluate(face, params, eval)); 31635552b385SBrandon } 31645552b385SBrandon 31655552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 31665552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 31675552b385SBrandon double nbprv[prvSize]; 31685552b385SBrandon 31695552b385SBrandon // Cycle through each Control Point 31705552b385SBrandon double deltaCoord = 1.0E-4; 31715552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 31725552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 31735552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 31745552b385SBrandon // Cycle through each direction (x, then y, then z) 31755552b385SBrandon for (int kk = 0; kk < 4; ++kk) { 31765552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 31775552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 31785552b385SBrandon 31795552b385SBrandon if (kk == 0) { //X 31805552b385SBrandon nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 31815552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 31825552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 31835552b385SBrandon } else if (kk == 1) { //Y 31845552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 31855552b385SBrandon nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 31865552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 31875552b385SBrandon } else if (kk == 2) { //Z 31885552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 31895552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 31905552b385SBrandon nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 31915552b385SBrandon } else if (kk == 3) { // Weights 31925552b385SBrandon nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 31935552b385SBrandon } else { 31945552b385SBrandon // currently do nothing 31955552b385SBrandon } 31965552b385SBrandon 31975552b385SBrandon // Create New Surface Based on New Control Points or Weights 31985552b385SBrandon ego newgeom, context; 31995552b385SBrandon if (islite) { 32005552b385SBrandon PetscCall(EGlite_open(&context)); 32015552b385SBrandon PetscCall(EGlite_setOutLevel(context, 0)); 32025552b385SBrandon } else { 32035552b385SBrandon PetscCall(EG_open(&context)); 32045552b385SBrandon PetscCall(EG_setOutLevel(context, 0)); 32055552b385SBrandon } 32065552b385SBrandon 32075552b385SBrandon PetscCall(EG_makeGeometry(context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 32085552b385SBrandon 32095552b385SBrandon if (islite) { 32105552b385SBrandon PetscCall(EGlite_setOutLevel(context, 1)); 32115552b385SBrandon } else { 32125552b385SBrandon PetscCall(EG_setOutLevel(context, 1)); 32135552b385SBrandon } 32145552b385SBrandon 32155552b385SBrandon // Evaluate new (x, y, z) Point Position based on new Surface Definition 32165552b385SBrandon double newCoords[18]; 32175552b385SBrandon if (islite) { 32185552b385SBrandon PetscCall(EGlite_getRange(newgeom, range, &peri)); 32195552b385SBrandon } else { 32205552b385SBrandon PetscCall(EG_getRange(newgeom, range, &peri)); 32215552b385SBrandon } 32225552b385SBrandon 32235552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, newgeom, range, 0, dE, params, islite)); 32245552b385SBrandon 32255552b385SBrandon if (islite) { 32265552b385SBrandon PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 32275552b385SBrandon } else { 32285552b385SBrandon PetscCall(EG_evaluate(newgeom, params, newCoords)); 32295552b385SBrandon } 32305552b385SBrandon 32315552b385SBrandon // Now Calculate the Surface Gradient for the change in x-component Control Point 32325552b385SBrandon PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 32335552b385SBrandon PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 32345552b385SBrandon PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 32355552b385SBrandon 32365552b385SBrandon // Store Gradient Information in surfaceGrad[][] Matrix 32375552b385SBrandon PetscInt startRow; 32385552b385SBrandon PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 32395552b385SBrandon 3240f0b74427SPierre Jolivet // Store Results in PETSc Mat 32415552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 32425552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 32435552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 32445552b385SBrandon } 32455552b385SBrandon offset += 3; 32465552b385SBrandon } 32475552b385SBrandon PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 32485552b385SBrandon } 32495552b385SBrandon } 32505552b385SBrandon 32515552b385SBrandon // Assemble Point Surface Grad Matrix 32525552b385SBrandon MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY); 32535552b385SBrandon MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY); 32545552b385SBrandon 32555552b385SBrandon // Attach Surface Gradient Hash Table and Matrix to DM 32565552b385SBrandon { 32575552b385SBrandon PetscContainer surfGradOrgObj, surfGradObj; 32585552b385SBrandon 32595552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 32605552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 32615552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 32625552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 32635552b385SBrandon 32645552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradObj)); 32655552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradObj, pointSurfGrad)); 32665552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)surfGradObj)); 32675552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradObj)); 32685552b385SBrandon } 32695552b385SBrandon if (islite) EGlite_free(fobjs); 32705552b385SBrandon else EG_free(fobjs); 32715552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 32725552b385SBrandon } 32735552b385SBrandon 32745552b385SBrandon static PetscErrorCode DestroyHashMap(void **p) 32755552b385SBrandon { 32765552b385SBrandon PetscFunctionBegin; 32775552b385SBrandon PetscCall(PetscHMapIDestroy((PetscHMapI *)p)); 32785552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 32795552b385SBrandon } 32805552b385SBrandon #endif 32815552b385SBrandon 32825552b385SBrandon /*@C 32835552b385SBrandon DMPlexGeomDataAndGrads - Exposes Control Points and Control Point Weights defining the underlying geometry allowing user manipulation of the geometry. 32845552b385SBrandon 32855552b385SBrandon Collective 32865552b385SBrandon 32875552b385SBrandon Input Parameters: 32885552b385SBrandon + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 32895552b385SBrandon - fullGeomGrad - PetscBool flag. Determines how the Surface Area and Volume Gradients wrt to Control Points and Control Point Weights are calculated. 32905552b385SBrandon PETSC_FALSE :: Surface Area Gradient wrt Control Points and Control Point Weights are calculated using the change in the local 32915552b385SBrandon FACE changes (not the entire body). Volume Gradients are not calculated. Faster computations. 32925552b385SBrandon PETSC_TRUE :: Surface Area Gradietn wrt to Control Points and Control Point Weights are calculated using the change observed in 32935552b385SBrandon the entire solid body. Volume Gradients are calculated. Slower computation due to the need to generate a new solid 32945552b385SBrandon body geometry for every Control Point and Control Point Weight change. 32955552b385SBrandon 32965552b385SBrandon Output Parameter: 32975552b385SBrandon . dm - The updated DM object representing the mesh with PetscContainers containing the Control Point, Control Point Weight and Gradient Data. 32985552b385SBrandon 32995552b385SBrandon Level: intermediate 33005552b385SBrandon 33015552b385SBrandon Note: 33025552b385SBrandon 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). 33035552b385SBrandon 33045552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexModifyEGADSGeomModel()` 33055552b385SBrandon @*/ 3306ce78bad3SBarry Smith PetscErrorCode DMPlexGeomDataAndGrads(DM dm, PetscBool fullGeomGrad) PeNS 33075552b385SBrandon { 33085552b385SBrandon #if defined(PETSC_HAVE_EGADS) 33095552b385SBrandon /* PETSc Variables */ 33105552b385SBrandon PetscContainer modelObj; 33115552b385SBrandon PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 33125552b385SBrandon PetscHMapI pointSurfGradRow_Start = NULL; 33135552b385SBrandon Mat pointSurfGrad, cpEquiv; 33145552b385SBrandon IS faceLabelValues, edgeLabelValues, vertexLabelValues; 33155552b385SBrandon PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 33165552b385SBrandon PetscBool islite = PETSC_FALSE; 33175552b385SBrandon /* EGADS Variables */ 33185552b385SBrandon ego model, geom, *bodies, *fobjs = NULL; 33195552b385SBrandon int oclass, mtype, *senses; 33205552b385SBrandon int Nb, Nf; 33215552b385SBrandon #endif 33225552b385SBrandon 33235552b385SBrandon PetscFunctionBegin; 33245552b385SBrandon #if defined(PETSC_HAVE_EGADS) 33255552b385SBrandon 33265552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 33275552b385SBrandon if (!modelObj) { 33285552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 33295552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 33305552b385SBrandon islite = PETSC_TRUE; 33315552b385SBrandon 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"); 33325552b385SBrandon } 33335552b385SBrandon 33345552b385SBrandon // Get attached EGADS model (pointer) 33355552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 33365552b385SBrandon 33375552b385SBrandon // Get the bodies in the model 33385552b385SBrandon if (islite) { 33395552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 33405552b385SBrandon } else { 33415552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 33425552b385SBrandon } 33435552b385SBrandon 33445552b385SBrandon ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 33455552b385SBrandon 33465552b385SBrandon // Get the total number of FACEs in the model 33475552b385SBrandon if (islite) { 33485552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 33495552b385SBrandon } else { 33505552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 33515552b385SBrandon } 33525552b385SBrandon 33535552b385SBrandon // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 33545552b385SBrandon // This will provide the total number of DMPlex points on the boundary of the geometry 33555552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 33565552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 33575552b385SBrandon 33585552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 33595552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 33605552b385SBrandon 33615552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 33625552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 33635552b385SBrandon 33645552b385SBrandon const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 33655552b385SBrandon PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 33665552b385SBrandon PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 33675552b385SBrandon PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 33685552b385SBrandon 33695552b385SBrandon // Get the points associated with each FACE, EDGE and VERTEX label in the DM 33705552b385SBrandon PetscInt totalNumPoints = 0; 33715552b385SBrandon for (int f = 0; f < faceLabelSize; ++f) { 33725552b385SBrandon // Cycle through FACE labels 33735552b385SBrandon PetscInt size; 33745552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[f], &size)); 33755552b385SBrandon totalNumPoints += size; 33765552b385SBrandon } 33775552b385SBrandon PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 33785552b385SBrandon PetscCall(ISDestroy(&faceLabelValues)); 33795552b385SBrandon 33805552b385SBrandon for (int e = 0; e < edgeLabelSize; ++e) { 33815552b385SBrandon // Cycle Through EDGE Labels 33825552b385SBrandon PetscInt size; 33835552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[e], &size)); 33845552b385SBrandon totalNumPoints += size; 33855552b385SBrandon } 33865552b385SBrandon PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 33875552b385SBrandon PetscCall(ISDestroy(&edgeLabelValues)); 33885552b385SBrandon 33895552b385SBrandon for (int ii = 0; ii < vertexLabelSize; ++ii) { 33905552b385SBrandon // Cycle Through VERTEX Labels 33915552b385SBrandon PetscInt size; 33925552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 33935552b385SBrandon totalNumPoints += size; 33945552b385SBrandon } 33955552b385SBrandon PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 33965552b385SBrandon PetscCall(ISDestroy(&vertexLabelValues)); 33975552b385SBrandon 33985552b385SBrandon int maxNumCPs = 0; 33995552b385SBrandon int totalNumCPs = 0; 34005552b385SBrandon ego bRef, bPrev, bNext, fgeom, *lobjs; 34015552b385SBrandon int id, boclass, bmtype, *bpinfo; 34025552b385SBrandon int foclass, fmtype, Nl, *lsenses; 34035552b385SBrandon double *bprv; 34045552b385SBrandon double fdata[4]; 34055552b385SBrandon 34065552b385SBrandon // Create Hash Tables 34075552b385SBrandon PetscInt cntr = 0, wcntr = 0, vcntr = 0; 34085552b385SBrandon PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 34095552b385SBrandon PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 34105552b385SBrandon 34115552b385SBrandon for (int f = 0; f < Nf; ++f) { 34125552b385SBrandon // Need to get the maximum number of Control Points defining the FACEs 34135552b385SBrandon ego face = fobjs[f]; 34145552b385SBrandon int maxNumCPs_temp; 34155552b385SBrandon 34165552b385SBrandon if (islite) { 34175552b385SBrandon id = EGlite_indexBodyTopo(body, face); 34185552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 34195552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 34205552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 34215552b385SBrandon } else { 34225552b385SBrandon id = EG_indexBodyTopo(body, face); 34235552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 34245552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 34255552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 34265552b385SBrandon } 34275552b385SBrandon maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 34285552b385SBrandon totalNumCPs += bpinfo[2] * bpinfo[5]; 34295552b385SBrandon 34305552b385SBrandon if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 34315552b385SBrandon } 34325552b385SBrandon 34335552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 34345552b385SBrandon PetscInt cpCoordDataLength = 3 * totalNumCPs; 34355552b385SBrandon PetscInt wDataLength = totalNumCPs; 34365552b385SBrandon cpCoordDataLengthPtr = &cpCoordDataLength; 34375552b385SBrandon wDataLengthPtr = &wDataLength; 34385552b385SBrandon 34395552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 34405552b385SBrandon PetscScalar *cntrlPtCoords, *cntrlPtWeights; 34415552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &cntrlPtCoordsVec)); 34425552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &cntrlPtWeightsVec)); 34435552b385SBrandon 34445552b385SBrandon // For dSA/dCPi 34455552b385SBrandon Vec gradSACPVec, gradSAWVec, gradVCPVec, gradVWVec; 34465552b385SBrandon PetscScalar *gradSACP, *gradSAW, *gradVCP, *gradVW; 34475552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradSACPVec)); 34485552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradSAWVec)); 34495552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradVCPVec)); 34505552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradVWVec)); 34515552b385SBrandon 34525552b385SBrandon // Control Point - Vertex/Edge/Face Relationship 34535552b385SBrandon PetscInt *cp_vertex, *cp_edge, *cp_face; 34545552b385SBrandon PetscInt *w_vertex, *w_edge, *w_face; 34555552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_vertex)); 34565552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_edge)); 34575552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_face)); 34585552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_vertex)); 34595552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_edge)); 34605552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_face)); 34615552b385SBrandon 34625552b385SBrandon for (int f = 0; f < Nf; ++f) { 34635552b385SBrandon // Need to Populate Control Point Coordinates and Weight Vectors 34645552b385SBrandon ego face = fobjs[f]; 34655552b385SBrandon ego *vobjs, *eobjs; 34665552b385SBrandon int offsetCoord, offsetWeight; 34675552b385SBrandon PetscInt Nv, Ne, wRowStart = 0; 34685552b385SBrandon PetscHashIter hashKeyIter, wHashKeyIter; 34695552b385SBrandon PetscBool hashKeyFound, wHashKeyFound; 34705552b385SBrandon 34715552b385SBrandon if (islite) { 34725552b385SBrandon id = EGlite_indexBodyTopo(body, face); 34735552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 34745552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 34755552b385SBrandon PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 34765552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 34775552b385SBrandon } else { 34785552b385SBrandon id = EG_indexBodyTopo(body, face); 34795552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 34805552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 34815552b385SBrandon PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 34825552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 34835552b385SBrandon } 34845552b385SBrandon 34855552b385SBrandon // Store Face ID to 1st Row of Control Point Vector 34865552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 34875552b385SBrandon 34885552b385SBrandon if (!hashKeyFound) PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); 34895552b385SBrandon 34905552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 34915552b385SBrandon offsetCoord = bpinfo[3] + bpinfo[6]; 34925552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 34935552b385SBrandon cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 34945552b385SBrandon cntr += 1; 34955552b385SBrandon } 34965552b385SBrandon 34975552b385SBrandon // Store Face ID to 1st Row of Control Point Weight Vector 34985552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 34995552b385SBrandon 35005552b385SBrandon if (!wHashKeyFound) { 35015552b385SBrandon PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); 35025552b385SBrandon wRowStart = wcntr; 35035552b385SBrandon } 35045552b385SBrandon 35055552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 35065552b385SBrandon offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 35075552b385SBrandon for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 35085552b385SBrandon cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 35095552b385SBrandon cp_face[wcntr] = id; 35105552b385SBrandon w_face[wcntr] = id; 35115552b385SBrandon wcntr += 1; 35125552b385SBrandon } 35135552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 35145552b385SBrandon 3515bfe80ac4SPierre Jolivet // Associate Control Points with Vertex IDs 35165552b385SBrandon PetscScalar xcp, ycp, zcp; 35175552b385SBrandon offsetCoord = bpinfo[3] + bpinfo[6]; 35185552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; jj += 3) { 35195552b385SBrandon xcp = bprv[offsetCoord + jj + 0]; 35205552b385SBrandon ycp = bprv[offsetCoord + jj + 1]; 35215552b385SBrandon zcp = bprv[offsetCoord + jj + 2]; 35225552b385SBrandon 35235552b385SBrandon //Initialize Control Point and Weight to Vertex ID relationship to -1 35245552b385SBrandon cp_vertex[vcntr] = -1; 35255552b385SBrandon w_vertex[vcntr] = -1; 35265552b385SBrandon cp_edge[vcntr] = -1; 35275552b385SBrandon w_edge[vcntr] = -1; 35285552b385SBrandon 35295552b385SBrandon for (int kk = 0; kk < Nv; ++kk) { 35305552b385SBrandon int vid; 35315552b385SBrandon double vCoords[3]; 35325552b385SBrandon PetscScalar vDelta; 35335552b385SBrandon ego vertex = vobjs[kk]; 35345552b385SBrandon 35355552b385SBrandon if (islite) { 35365552b385SBrandon vid = EGlite_indexBodyTopo(body, vertex); 35375552b385SBrandon PetscCallEGADS(EGlite_evaluate, (vertex, NULL, vCoords)); 35385552b385SBrandon } else { 35395552b385SBrandon vid = EG_indexBodyTopo(body, vertex); 35405552b385SBrandon PetscCallEGADS(EG_evaluate, (vertex, NULL, vCoords)); 35415552b385SBrandon } 35425552b385SBrandon vDelta = PetscSqrtReal(PetscSqr(vCoords[0] - xcp) + PetscSqr(vCoords[1] - ycp) + PetscSqr(vCoords[2] - zcp)); 35435552b385SBrandon 35445552b385SBrandon if (vDelta < 1.0E-15) { 35455552b385SBrandon cp_vertex[vcntr] = vid; 35465552b385SBrandon w_vertex[vcntr] = vid; 35475552b385SBrandon } 35485552b385SBrandon } 35495552b385SBrandon vcntr += 1; 35505552b385SBrandon } 35515552b385SBrandon // These two line could be replaced with DMPlexFreeGeomObject() 35525552b385SBrandon if (islite) EGlite_free(vobjs); 35535552b385SBrandon else EG_free(vobjs); 35545552b385SBrandon 35555552b385SBrandon // Associate Control Points with Edge IDs 35565552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 35575552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 35585552b385SBrandon 35595552b385SBrandon int cpV1, cpV2; 35605552b385SBrandon int minID, maxID; 35615552b385SBrandon 35625552b385SBrandon // Along vmin axis 35635552b385SBrandon minID = wRowStart; 35645552b385SBrandon maxID = wRowStart + (bpinfo[2] - 1); 35655552b385SBrandon cpV1 = cp_vertex[minID]; 35665552b385SBrandon cpV2 = cp_vertex[maxID]; 35675552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 35685552b385SBrandon ego edge = eobjs[jj]; 35695552b385SBrandon ego egeom, *nobjs; 35705552b385SBrandon int eoclass, emtype, Nn, *nsenses; 35715552b385SBrandon int n1ID, n2ID, eid; 35725552b385SBrandon 35735552b385SBrandon if (islite) { 35745552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 35755552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 35765552b385SBrandon } else { 35775552b385SBrandon eid = EG_indexBodyTopo(body, edge); 35785552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 35795552b385SBrandon } 35805552b385SBrandon 35815552b385SBrandon if (emtype != DEGENERATE) { 35825552b385SBrandon // Get IDs for current Edge's End Vertices 35835552b385SBrandon if (islite) { 35845552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 35855552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 35865552b385SBrandon } else { 35875552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 35885552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 35895552b385SBrandon } 35905552b385SBrandon 35915552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 35925552b385SBrandon for (int kk = minID + 1; kk < maxID; ++kk) { 35935552b385SBrandon cp_edge[kk] = eid; 35945552b385SBrandon w_edge[kk] = eid; 35955552b385SBrandon } 35965552b385SBrandon } 35975552b385SBrandon } 35985552b385SBrandon } 35995552b385SBrandon 36005552b385SBrandon // Along vmax axis 36015552b385SBrandon minID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 36025552b385SBrandon maxID = wRowStart + (bpinfo[2] * bpinfo[5] - 1); 36035552b385SBrandon 36045552b385SBrandon cpV1 = cp_vertex[minID]; 36055552b385SBrandon cpV2 = cp_vertex[maxID]; 36065552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 36075552b385SBrandon ego edge = eobjs[jj]; 36085552b385SBrandon ego egeom, *nobjs; 36095552b385SBrandon int eoclass, emtype, Nn, *nsenses; 36105552b385SBrandon int n1ID, n2ID, eid; 36115552b385SBrandon 36125552b385SBrandon if (islite) { 36135552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 36145552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36155552b385SBrandon } else { 36165552b385SBrandon eid = EG_indexBodyTopo(body, edge); 36175552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36185552b385SBrandon } 36195552b385SBrandon 36205552b385SBrandon if (emtype != DEGENERATE) { 36215552b385SBrandon // Get IDs for current Edge's End Vertices 36225552b385SBrandon if (islite) { 36235552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 36245552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 36255552b385SBrandon } else { 36265552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 36275552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 36285552b385SBrandon } 36295552b385SBrandon 36305552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 36315552b385SBrandon for (int kk = minID + 1; kk < maxID - 1; ++kk) { 36325552b385SBrandon cp_edge[kk] = eid; 36335552b385SBrandon w_edge[kk] = eid; 36345552b385SBrandon } 36355552b385SBrandon } 36365552b385SBrandon } 36375552b385SBrandon } 36385552b385SBrandon 36395552b385SBrandon // Along umin axis 36405552b385SBrandon minID = wRowStart; 36415552b385SBrandon maxID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 36425552b385SBrandon 36435552b385SBrandon cpV1 = cp_vertex[minID]; 36445552b385SBrandon cpV2 = cp_vertex[maxID]; 36455552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 36465552b385SBrandon ego edge = eobjs[jj]; 36475552b385SBrandon ego egeom, *nobjs; 36485552b385SBrandon int eoclass, emtype, Nn, *nsenses; 36495552b385SBrandon int n1ID, n2ID, eid; 36505552b385SBrandon 36515552b385SBrandon if (islite) { 36525552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 36535552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36545552b385SBrandon } else { 36555552b385SBrandon eid = EG_indexBodyTopo(body, edge); 36565552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36575552b385SBrandon } 36585552b385SBrandon 36595552b385SBrandon if (emtype != DEGENERATE) { 36605552b385SBrandon // Get IDs for current Edge's End Vertices 36615552b385SBrandon if (islite) { 36625552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 36635552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 36645552b385SBrandon } else { 36655552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 36665552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 36675552b385SBrandon } 36685552b385SBrandon 36695552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 36705552b385SBrandon for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 36715552b385SBrandon cp_edge[kk] = eid; 36725552b385SBrandon w_edge[kk] = eid; 36735552b385SBrandon } 36745552b385SBrandon } 36755552b385SBrandon } 36765552b385SBrandon } 36775552b385SBrandon 36785552b385SBrandon // Along umax axis 36795552b385SBrandon minID = wRowStart + (bpinfo[2] - 1); 36805552b385SBrandon maxID = wRowStart + (bpinfo[2] * bpinfo[5]) - 1; 36815552b385SBrandon cpV1 = cp_vertex[minID]; 36825552b385SBrandon cpV2 = cp_vertex[maxID]; 36835552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 36845552b385SBrandon ego edge = eobjs[jj]; 36855552b385SBrandon ego egeom, *nobjs; 36865552b385SBrandon int eoclass, emtype, Nn, *nsenses; 36875552b385SBrandon int n1ID, n2ID, eid; 36885552b385SBrandon 36895552b385SBrandon if (islite) { 36905552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 36915552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36925552b385SBrandon } else { 36935552b385SBrandon eid = EG_indexBodyTopo(body, edge); 36945552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 36955552b385SBrandon } 36965552b385SBrandon 36975552b385SBrandon if (emtype != DEGENERATE) { 36985552b385SBrandon // Get IDs for current Edge's End Vertices 36995552b385SBrandon if (islite) { 37005552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 37015552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 37025552b385SBrandon } else { 37035552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 37045552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 37055552b385SBrandon } 37065552b385SBrandon 37075552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 37085552b385SBrandon for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 37095552b385SBrandon cp_edge[kk] = eid; 37105552b385SBrandon w_edge[kk] = eid; 37115552b385SBrandon } 37125552b385SBrandon } 37135552b385SBrandon } 37145552b385SBrandon } 37155552b385SBrandon // These two lines could be replaced with DMPlexFreeGeomObject() 37165552b385SBrandon if (islite) EGlite_free(eobjs); 37175552b385SBrandon else EG_free(eobjs); 37185552b385SBrandon } 37195552b385SBrandon 3720bfe80ac4SPierre Jolivet // Determine Control Point Equivalence Matrix relating Control Points between Surfaces 37215552b385SBrandon // Note: The Weights will also be tied together in the same manner 37225552b385SBrandon // Also can use the Weight Hash Table for Row Start ID of each Face 37235552b385SBrandon const PetscInt cpRowSize = totalNumCPs; 37245552b385SBrandon const PetscInt cpColSize = cpRowSize; 37255552b385SBrandon PetscInt *maxNumRelatePtr; 37265552b385SBrandon PetscInt maxNumRelate = 0; 37275552b385SBrandon 37285552b385SBrandon // Create Point Surface Gradient Matrix 37295552b385SBrandon PetscCall(MatCreate(PETSC_COMM_WORLD, &cpEquiv)); 37305552b385SBrandon PetscCall(MatSetSizes(cpEquiv, PETSC_DECIDE, PETSC_DECIDE, cpRowSize, cpColSize)); 37315552b385SBrandon PetscCall(MatSetType(cpEquiv, MATAIJ)); 37325552b385SBrandon PetscCall(MatSetUp(cpEquiv)); 37335552b385SBrandon 37345552b385SBrandon for (int ii = 0; ii < totalNumCPs; ++ii) { 37355552b385SBrandon PetscScalar x1, y1, z1; 37365552b385SBrandon PetscInt maxRelateTemp = 0; 37375552b385SBrandon 37385552b385SBrandon x1 = cntrlPtCoords[(3 * ii) + 0]; 37395552b385SBrandon y1 = cntrlPtCoords[(3 * ii) + 1]; 37405552b385SBrandon z1 = cntrlPtCoords[(3 * ii) + 2]; 37415552b385SBrandon 37425552b385SBrandon for (int jj = 0; jj < totalNumCPs; ++jj) { 37435552b385SBrandon PetscScalar x2, y2, z2; 37445552b385SBrandon PetscScalar cpDelta, eqFactor; 37455552b385SBrandon x2 = cntrlPtCoords[(3 * jj) + 0]; 37465552b385SBrandon y2 = cntrlPtCoords[(3 * jj) + 1]; 37475552b385SBrandon z2 = cntrlPtCoords[(3 * jj) + 2]; 37485552b385SBrandon 37495552b385SBrandon cpDelta = PetscSqrtReal(PetscSqr(x2 - x1) + PetscSqr(y2 - y1) + PetscSqr(z2 - z1)); 37505552b385SBrandon if (cpDelta < 1.0E-15) { 37515552b385SBrandon eqFactor = 1.0; 37525552b385SBrandon maxRelateTemp += 1; 37535552b385SBrandon } else { 37545552b385SBrandon eqFactor = 0.0; 37555552b385SBrandon } 37565552b385SBrandon 3757f0b74427SPierre Jolivet // Store Results in PETSc Mat 37585552b385SBrandon PetscCall(MatSetValue(cpEquiv, ii, jj, eqFactor, INSERT_VALUES)); 37595552b385SBrandon } 37605552b385SBrandon if (maxRelateTemp > maxNumRelate) maxNumRelate = maxRelateTemp; 37615552b385SBrandon } 37625552b385SBrandon maxNumRelatePtr = &maxNumRelate; 37635552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 37645552b385SBrandon 37655552b385SBrandon // Assemble Point Surface Grad Matrix 37665552b385SBrandon PetscCall(MatAssemblyBegin(cpEquiv, MAT_FINAL_ASSEMBLY)); 37675552b385SBrandon PetscCall(MatAssemblyEnd(cpEquiv, MAT_FINAL_ASSEMBLY)); 37685552b385SBrandon 37695552b385SBrandon // Attach Control Point and Weight Data to DM 37705552b385SBrandon { 37715552b385SBrandon PetscContainer cpOrgObj, cpCoordLengthObj; 37725552b385SBrandon PetscContainer wOrgObj, wDataLengthObj; 37735552b385SBrandon PetscContainer cp_faceObj, cp_edgeObj, cp_vertexObj; 37745552b385SBrandon PetscContainer w_faceObj, w_edgeObj, w_vertexObj; 37755552b385SBrandon PetscContainer maxNumRelateObj; 37765552b385SBrandon 37775552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpOrgObj)); 37785552b385SBrandon if (!cpOrgObj) { 37795552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 37805552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 37815552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 37825552b385SBrandon PetscCall(PetscContainerDestroy(&cpOrgObj)); 37835552b385SBrandon } else { 37845552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 37855552b385SBrandon } 37865552b385SBrandon 37875552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cntrlPtCoordsVec)); 37885552b385SBrandon PetscCall(VecDestroy(&cntrlPtCoordsVec)); 37895552b385SBrandon 37905552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordLengthObj)); 37915552b385SBrandon if (!cpCoordLengthObj) { 37925552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 37935552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 37945552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 37955552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 37965552b385SBrandon } else { 37975552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 37985552b385SBrandon } 37995552b385SBrandon 38005552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wOrgObj)); 38015552b385SBrandon if (!wOrgObj) { 38025552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 38035552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 38045552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 38055552b385SBrandon PetscCall(PetscContainerDestroy(&wOrgObj)); 38065552b385SBrandon } else { 38075552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 38085552b385SBrandon } 38095552b385SBrandon 38105552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)cntrlPtWeightsVec)); 38115552b385SBrandon PetscCall(VecDestroy(&cntrlPtWeightsVec)); 38125552b385SBrandon 38135552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 38145552b385SBrandon if (!wDataLengthObj) { 38155552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 38165552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 38175552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 38185552b385SBrandon PetscCall(PetscContainerDestroy(&wDataLengthObj)); 38195552b385SBrandon } else { 38205552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 38215552b385SBrandon } 38225552b385SBrandon 3823bfe80ac4SPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Equivalency Matrix", (PetscObject)cpEquiv)); 38245552b385SBrandon 38255552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 38265552b385SBrandon if (!maxNumRelateObj) { 38275552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &maxNumRelateObj)); 38285552b385SBrandon PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 38295552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject)maxNumRelateObj)); 38305552b385SBrandon PetscCall(PetscContainerDestroy(&maxNumRelateObj)); 38315552b385SBrandon } else { 38325552b385SBrandon PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 38335552b385SBrandon } 38345552b385SBrandon 38355552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cp_faceObj)); 38365552b385SBrandon if (!cp_faceObj) { 38375552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_faceObj)); 38385552b385SBrandon PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 38395552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_faceObj, PetscCtxDestroyDefault)); 38405552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Face Map", (PetscObject)cp_faceObj)); 38415552b385SBrandon PetscCall(PetscContainerDestroy(&cp_faceObj)); 38425552b385SBrandon } else { 38435552b385SBrandon void *tmp; 38445552b385SBrandon 38455552b385SBrandon PetscCall(PetscContainerGetPointer(cp_faceObj, &tmp)); 38465552b385SBrandon PetscCall(PetscFree(tmp)); 38475552b385SBrandon PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 38485552b385SBrandon } 38495552b385SBrandon 38505552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&w_faceObj)); 38515552b385SBrandon if (!w_faceObj) { 38525552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_faceObj)); 38535552b385SBrandon PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 38545552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_faceObj, PetscCtxDestroyDefault)); 38555552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject)w_faceObj)); 38565552b385SBrandon PetscCall(PetscContainerDestroy(&w_faceObj)); 38575552b385SBrandon } else { 38585552b385SBrandon void *tmp; 38595552b385SBrandon 38605552b385SBrandon PetscCall(PetscContainerGetPointer(w_faceObj, &tmp)); 38615552b385SBrandon PetscCall(PetscFree(tmp)); 38625552b385SBrandon PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 38635552b385SBrandon } 38645552b385SBrandon 38655552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cp_edgeObj)); 38665552b385SBrandon if (!cp_edgeObj) { 38675552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_edgeObj)); 38685552b385SBrandon PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 38695552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_edgeObj, PetscCtxDestroyDefault)); 38705552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Edge Map", (PetscObject)cp_edgeObj)); 38715552b385SBrandon PetscCall(PetscContainerDestroy(&cp_edgeObj)); 38725552b385SBrandon } else { 38735552b385SBrandon void *tmp; 38745552b385SBrandon 38755552b385SBrandon PetscCall(PetscContainerGetPointer(cp_edgeObj, &tmp)); 38765552b385SBrandon PetscCall(PetscFree(tmp)); 38775552b385SBrandon PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 38785552b385SBrandon } 38795552b385SBrandon 38805552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&w_edgeObj)); 38815552b385SBrandon if (!w_edgeObj) { 38825552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_edgeObj)); 38835552b385SBrandon PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 38845552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_edgeObj, PetscCtxDestroyDefault)); 38855552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject)w_edgeObj)); 38865552b385SBrandon PetscCall(PetscContainerDestroy(&w_edgeObj)); 38875552b385SBrandon } else { 38885552b385SBrandon void *tmp; 38895552b385SBrandon 38905552b385SBrandon PetscCall(PetscContainerGetPointer(w_edgeObj, &tmp)); 38915552b385SBrandon PetscCall(PetscFree(tmp)); 38925552b385SBrandon PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 38935552b385SBrandon } 38945552b385SBrandon 38955552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cp_vertexObj)); 38965552b385SBrandon if (!cp_vertexObj) { 38975552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_vertexObj)); 38985552b385SBrandon PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 38995552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_vertexObj, PetscCtxDestroyDefault)); 39005552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Vertex Map", (PetscObject)cp_vertexObj)); 39015552b385SBrandon PetscCall(PetscContainerDestroy(&cp_vertexObj)); 39025552b385SBrandon } else { 39035552b385SBrandon void *tmp; 39045552b385SBrandon 39055552b385SBrandon PetscCall(PetscContainerGetPointer(cp_vertexObj, &tmp)); 39065552b385SBrandon PetscCall(PetscFree(tmp)); 39075552b385SBrandon PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 39085552b385SBrandon } 39095552b385SBrandon 39105552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&w_vertexObj)); 39115552b385SBrandon if (!w_vertexObj) { 39125552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_vertexObj)); 39135552b385SBrandon PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 39145552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_vertexObj, PetscCtxDestroyDefault)); 39155552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject)w_vertexObj)); 39165552b385SBrandon PetscCall(PetscContainerDestroy(&w_vertexObj)); 39175552b385SBrandon } else { 39185552b385SBrandon void *tmp; 39195552b385SBrandon 39205552b385SBrandon PetscCall(PetscContainerGetPointer(w_vertexObj, &tmp)); 39215552b385SBrandon PetscCall(PetscFree(tmp)); 39225552b385SBrandon PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 39235552b385SBrandon } 39245552b385SBrandon } 39255552b385SBrandon 39265552b385SBrandon // Define Matrix to store Geometry Gradient information dGeom_i/dCPj_i 39275552b385SBrandon PetscInt gcntr = 0; 39285552b385SBrandon const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 39295552b385SBrandon const PetscInt colSize = 4 * Nf; 39305552b385SBrandon 39315552b385SBrandon // Create Point Surface Gradient Matrix 39325552b385SBrandon PetscCall(MatCreate(PETSC_COMM_WORLD, &pointSurfGrad)); 39335552b385SBrandon PetscCall(MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize)); 39345552b385SBrandon PetscCall(MatSetType(pointSurfGrad, MATAIJ)); 39355552b385SBrandon PetscCall(MatSetUp(pointSurfGrad)); 39365552b385SBrandon 39375552b385SBrandon // Create Hash Table to store Point's stare row in surfaceGrad[][] 39385552b385SBrandon PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 39395552b385SBrandon 39405552b385SBrandon // Get Coordinates for the DMPlex point 39415552b385SBrandon DM cdm; 39425552b385SBrandon PetscInt dE, Nv; 39435552b385SBrandon Vec coordinatesLocal; 39445552b385SBrandon PetscScalar *coords = NULL; 39455552b385SBrandon 39465552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 39475552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &dE)); 39485552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 39495552b385SBrandon 39505552b385SBrandon // CYCLE THROUGH FACEs 39515552b385SBrandon PetscScalar maxGrad = 0.; 39525552b385SBrandon PetscCall(VecGetArrayWrite(gradSACPVec, &gradSACP)); 39535552b385SBrandon PetscCall(VecGetArrayWrite(gradSAWVec, &gradSAW)); 39545552b385SBrandon PetscCall(VecGetArrayWrite(gradVCPVec, &gradVCP)); 39555552b385SBrandon PetscCall(VecGetArrayWrite(gradVWVec, &gradVW)); 39565552b385SBrandon for (int f = 0; f < Nf; ++f) { 39575552b385SBrandon ego face = fobjs[f]; 39585552b385SBrandon ego *eobjs, *nobjs; 39595552b385SBrandon PetscInt fid, Ne, Nn; 39605552b385SBrandon DMLabel faceLabel, edgeLabel, nodeLabel; 39615552b385SBrandon PetscHMapI currFaceUniquePoints = NULL; 39625552b385SBrandon IS facePoints, edgePoints, nodePoints; 39635552b385SBrandon const PetscInt *fIndices, *eIndices, *nIndices; 39645552b385SBrandon PetscInt fSize, eSize, nSize; 39655552b385SBrandon PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 39665552b385SBrandon PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 39675552b385SBrandon PetscInt cfCntr = 0; 39685552b385SBrandon 39695552b385SBrandon // Get Geometry Object for the Current FACE 39705552b385SBrandon if (islite) { 39715552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 39725552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 39735552b385SBrandon } else { 39745552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 39755552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 39765552b385SBrandon } 39775552b385SBrandon 39785552b385SBrandon // Get all EDGE and NODE objects attached to the current FACE 39795552b385SBrandon if (islite) { 39805552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 39815552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 39825552b385SBrandon } else { 39835552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 39845552b385SBrandon PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 39855552b385SBrandon } 39865552b385SBrandon 39875552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 39885552b385SBrandon if (islite) { 39895552b385SBrandon fid = EGlite_indexBodyTopo(body, face); 39905552b385SBrandon } else { 39915552b385SBrandon fid = EG_indexBodyTopo(body, face); 39925552b385SBrandon } 39935552b385SBrandon 39945552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 39955552b385SBrandon PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 39965552b385SBrandon PetscCall(ISGetIndices(facePoints, &fIndices)); 39975552b385SBrandon PetscCall(ISGetSize(facePoints, &fSize)); 39985552b385SBrandon 39995552b385SBrandon PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 40005552b385SBrandon 40015552b385SBrandon for (int jj = 0; jj < fSize; ++jj) { 40025552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 40035552b385SBrandon 40045552b385SBrandon if (!fHashKeyFound) { 40055552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 40065552b385SBrandon cfCntr += 1; 40075552b385SBrandon } 40085552b385SBrandon 40095552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 40105552b385SBrandon 40115552b385SBrandon if (!pHashKeyFound) { 40125552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 40135552b385SBrandon gcntr += 3 * maxNumCPs; 40145552b385SBrandon } 40155552b385SBrandon } 40165552b385SBrandon PetscCall(ISRestoreIndices(facePoints, &fIndices)); 40175552b385SBrandon PetscCall(ISDestroy(&facePoints)); 40185552b385SBrandon 40195552b385SBrandon // 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. 40205552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 40215552b385SBrandon ego edge = eobjs[jj]; 40225552b385SBrandon PetscBool containLabelValue; 40235552b385SBrandon 40245552b385SBrandon if (islite) { 40255552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 40265552b385SBrandon } else { 40275552b385SBrandon id = EG_indexBodyTopo(body, edge); 40285552b385SBrandon } 40295552b385SBrandon 40305552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 40315552b385SBrandon PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 40325552b385SBrandon 40335552b385SBrandon if (containLabelValue) { 40345552b385SBrandon PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 40355552b385SBrandon PetscCall(ISGetIndices(edgePoints, &eIndices)); 40365552b385SBrandon PetscCall(ISGetSize(edgePoints, &eSize)); 40375552b385SBrandon 40385552b385SBrandon for (int kk = 0; kk < eSize; ++kk) { 40395552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 40405552b385SBrandon 40415552b385SBrandon if (!eHashKeyFound) { 40425552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 40435552b385SBrandon cfCntr += 1; 40445552b385SBrandon } 40455552b385SBrandon 40465552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 40475552b385SBrandon 40485552b385SBrandon if (!pHashKeyFound) { 40495552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 40505552b385SBrandon gcntr += 3 * maxNumCPs; 40515552b385SBrandon } 40525552b385SBrandon } 40535552b385SBrandon PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 40545552b385SBrandon PetscCall(ISDestroy(&edgePoints)); 40555552b385SBrandon } 40565552b385SBrandon } 40575552b385SBrandon 40585552b385SBrandon // 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. 40595552b385SBrandon for (int jj = 0; jj < Nn; ++jj) { 40605552b385SBrandon ego node = nobjs[jj]; 40615552b385SBrandon 40625552b385SBrandon if (islite) { 40635552b385SBrandon id = EGlite_indexBodyTopo(body, node); 40645552b385SBrandon } else { 40655552b385SBrandon id = EG_indexBodyTopo(body, node); 40665552b385SBrandon } 40675552b385SBrandon 40685552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 40695552b385SBrandon PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 40705552b385SBrandon PetscCall(ISGetIndices(nodePoints, &nIndices)); 40715552b385SBrandon PetscCall(ISGetSize(nodePoints, &nSize)); 40725552b385SBrandon 40735552b385SBrandon for (int kk = 0; kk < nSize; ++kk) { 40745552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 40755552b385SBrandon 40765552b385SBrandon if (!nHashKeyFound) { 40775552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 40785552b385SBrandon cfCntr += 1; 40795552b385SBrandon } 40805552b385SBrandon 40815552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 40825552b385SBrandon if (!pHashKeyFound) { 40835552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 40845552b385SBrandon gcntr += 3 * maxNumCPs; 40855552b385SBrandon } 40865552b385SBrandon } 40875552b385SBrandon PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 40885552b385SBrandon PetscCall(ISDestroy(&nodePoints)); 40895552b385SBrandon } 40905552b385SBrandon 40915552b385SBrandon // Get the Total Number of entries in the Hash Table 40925552b385SBrandon PetscInt currFaceUPSize; 40935552b385SBrandon PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 40945552b385SBrandon 40955552b385SBrandon // Get Keys 40965552b385SBrandon PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 40975552b385SBrandon PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 40985552b385SBrandon PetscCall(PetscHMapIDestroy(&currFaceUniquePoints)); 40995552b385SBrandon 41005552b385SBrandon // Get Current Face Surface Area 41015552b385SBrandon PetscScalar fSA, faceData[14]; 41025552b385SBrandon PetscCall(EG_getMassProperties(face, faceData)); // This doesn't have a EGlite version. Will it work for EGADSlite files?? KNOWN_ISSUE 41035552b385SBrandon fSA = faceData[1]; 41045552b385SBrandon 41055552b385SBrandon // Get Start Row in cpEquiv Matrix 41065552b385SBrandon PetscHashIter Witer; 41075552b385SBrandon PetscBool Wfound; 41085552b385SBrandon PetscInt faceWStartRow; 41095552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 41105552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 41115552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 41125552b385SBrandon 41135552b385SBrandon // Cycle through all points on the current FACE 41145552b385SBrandon for (int jj = 0; jj < currFaceUPSize; ++jj) { 41155552b385SBrandon PetscInt currPointID = currFaceUPKeys[jj]; 41165552b385SBrandon PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 41175552b385SBrandon 41185552b385SBrandon // Get UV position of FACE 41195552b385SBrandon double params[2], range[4], eval[18]; 41205552b385SBrandon int peri; 41215552b385SBrandon 41225552b385SBrandon if (islite) PetscCall(EGlite_getRange(face, range, &peri)); 41235552b385SBrandon else PetscCall(EG_getRange(face, range, &peri)); 41245552b385SBrandon 41255552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 41265552b385SBrandon 41275552b385SBrandon if (islite) PetscCall(EGlite_evaluate(face, params, eval)); 41285552b385SBrandon else PetscCall(EG_evaluate(face, params, eval)); 41295552b385SBrandon 41305552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 41315552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 41325552b385SBrandon double nbprv[prvSize]; 41335552b385SBrandon 41345552b385SBrandon // Cycle through each Control Point 41355552b385SBrandon double denomNew, denomOld; 41365552b385SBrandon double deltaCoord = 1.0E-4; 41375552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 41385552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 41395552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 41405552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d", f, jj, ii); 41415552b385SBrandon #if 0 41425552b385SBrandon // Cycle through each direction (x, then y, then z) 41435552b385SBrandon if (jj == 0) { 41445552b385SBrandon // Get the Number Control Points that are the same as the current points 41455552b385SBrandon // We are looking for repeated Control Points 41465552b385SBrandon PetscInt commonCPcntr = 0; 41475552b385SBrandon for (int mm = 0; mm < bpinfo[2]*bpinfo[5]; ++mm) { 41485552b385SBrandon PetscScalar matValue; 41495552b385SBrandon PetscCall(MatGetValue(cpEquiv, faceWStartRow + ii, faceWStartRow + mm, &matValue)); 41505552b385SBrandon 41515552b385SBrandon if (matValue > 0.0) commonCPcntr += 1; 41525552b385SBrandon } 41535552b385SBrandon } 41545552b385SBrandon #endif 41555552b385SBrandon 41565552b385SBrandon for (int kk = 0; kk < 4; ++kk) { 41575552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 41585552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 41595552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 41605552b385SBrandon 41615552b385SBrandon if (kk == 0) { //X 41625552b385SBrandon nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 41635552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 41645552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 41655552b385SBrandon denomNew = nbprv[offset + 0]; 41665552b385SBrandon denomOld = bprv[offset + 0]; 41675552b385SBrandon } else if (kk == 1) { //Y 41685552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 41695552b385SBrandon nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 41705552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 41715552b385SBrandon denomNew = nbprv[offset + 1]; 41725552b385SBrandon denomOld = bprv[offset + 1]; 41735552b385SBrandon } else if (kk == 2) { //Z 41745552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 41755552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 41765552b385SBrandon nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 41775552b385SBrandon denomNew = nbprv[offset + 2]; 41785552b385SBrandon denomOld = bprv[offset + 2]; 41795552b385SBrandon } else if (kk == 3) { // Weights 41805552b385SBrandon nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 41815552b385SBrandon denomNew = nbprv[wOffset + ii]; 41825552b385SBrandon denomOld = bprv[wOffset + ii]; 41835552b385SBrandon } else { 41845552b385SBrandon // currently do nothing 41855552b385SBrandon } 41865552b385SBrandon 41875552b385SBrandon // Create New Surface Based on New Control Points or Weights 41885552b385SBrandon ego newgeom, context; 41895552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // This does not have an EGlite_ version KNOWN_ISSUE 41905552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // This does not have an EGlite_ version KNOWN_ISSUE 41915552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 41925552b385SBrandon 41935552b385SBrandon // Evaluate new (x, y, z) Point Position based on new Surface Definition 41945552b385SBrandon double newCoords[18]; 41955552b385SBrandon if (islite) PetscCall(EGlite_getRange(newgeom, range, &peri)); 41965552b385SBrandon else PetscCall(EG_getRange(newgeom, range, &peri)); 41975552b385SBrandon 41985552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 41995552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 42005552b385SBrandon 42015552b385SBrandon if (islite) PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 42025552b385SBrandon else PetscCall(EG_evaluate(newgeom, params, newCoords)); 42035552b385SBrandon 42045552b385SBrandon // Calculate Surface Area Gradients wrt Control Points and Weights using the local discrete FACE only 42055552b385SBrandon // NOTE 1: Will not provide Volume Gradient wrt to Control Points and Weights. 42065552b385SBrandon // NOTE 2: This is faster than below where an entire new solid geometry is created for each 42075552b385SBrandon // Control Point and Weight gradient 42085552b385SBrandon if (!fullGeomGrad) { 42095552b385SBrandon // Create new FACE based on new SURFACE geometry 42105552b385SBrandon if (jj == 0) { // only for 1st DMPlex Point because we only per CP or Weight 42115552b385SBrandon double newFaceRange[4]; 42125552b385SBrandon int newFacePeri; 42135552b385SBrandon if (islite) PetscCall(EGlite_getRange(newgeom, newFaceRange, &newFacePeri)); 42145552b385SBrandon else PetscCall(EG_getRange(newgeom, newFaceRange, &newFacePeri)); 42155552b385SBrandon 42165552b385SBrandon ego newface; 42175552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have EGlite version KNOWN_ISSUE 42185552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 42195552b385SBrandon 42205552b385SBrandon // Get New Face Surface Area 42215552b385SBrandon PetscScalar newfSA, newFaceData[14]; 42225552b385SBrandon PetscCall(EG_getMassProperties(newface, newFaceData)); // Does not have EGlite version KNOWN_ISSUE 42235552b385SBrandon newfSA = newFaceData[1]; 42245552b385SBrandon PetscCallEGADS(EG_deleteObject, (newface)); 42255552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 42265552b385SBrandon 42275552b385SBrandon // Update Control Points 42285552b385SBrandon PetscHashIter CPiter, Witer; 42295552b385SBrandon PetscBool CPfound, Wfound; 42305552b385SBrandon PetscInt faceCPStartRow, faceWStartRow; 42315552b385SBrandon 42325552b385SBrandon PetscScalar dSAdCPi; 42335552b385SBrandon dSAdCPi = (newfSA - fSA) / (denomNew - denomOld); 42345552b385SBrandon 42355552b385SBrandon if (kk < 3) { 42365552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, fid, &CPiter, &CPfound)); 42375552b385SBrandon PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 42385552b385SBrandon PetscCall(PetscHMapIGet(faceCntrlPtRow_Start, fid, &faceCPStartRow)); 42395552b385SBrandon 42405552b385SBrandon gradSACP[faceCPStartRow + (ii * 3) + kk] = dSAdCPi; 42415552b385SBrandon 42425552b385SBrandon if (PetscAbsReal(dSAdCPi) > maxGrad) maxGrad = PetscAbsReal(dSAdCPi); 42435552b385SBrandon 42445552b385SBrandon } else if (kk == 3) { 42455552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 42465552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 42475552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 42485552b385SBrandon 42495552b385SBrandon gradSAW[faceWStartRow + ii] = dSAdCPi; 42505552b385SBrandon 42515552b385SBrandon } else { 42525552b385SBrandon // Do Nothing 42535552b385SBrandon } 42545552b385SBrandon } 42555552b385SBrandon } 42565552b385SBrandon PetscCallEGADS(EG_deleteObject, (newgeom)); 42575552b385SBrandon 42585552b385SBrandon // Now Calculate the Surface Gradient for the change in x-component Control Point 42595552b385SBrandon PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 42605552b385SBrandon PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 42615552b385SBrandon PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 42625552b385SBrandon 42635552b385SBrandon // Store Gradient Information in surfaceGrad[][] Matrix 42645552b385SBrandon PetscInt startRow; 42655552b385SBrandon PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 42665552b385SBrandon 4267f0b74427SPierre Jolivet // Store Results in PETSc Mat 42685552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 42695552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 42705552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 42715552b385SBrandon 42725552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newgeom)); 42735552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face is corrupted"); 42745552b385SBrandon } 42755552b385SBrandon offset += 3; 42765552b385SBrandon } 42775552b385SBrandon PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 42785552b385SBrandon } 42795552b385SBrandon } 42805552b385SBrandon 42815552b385SBrandon // Assemble Point Surface Grad Matrix 42825552b385SBrandon PetscCall(MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 42835552b385SBrandon PetscCall(MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 42845552b385SBrandon 42855552b385SBrandon if (fullGeomGrad) { 42865552b385SBrandon // Calculate Surface Area and Volume Control Point and Control Point Weight Gradients 42875552b385SBrandon // Note: This is much slower than above due to a new solid geometry being created for 42885552b385SBrandon // each change in Control Point and Control Point Weight. However, this method 42895552b385SBrandon // will provide the Volume Gradient. 42905552b385SBrandon 42915552b385SBrandon // Get Current Face Surface Area 42925552b385SBrandon PetscScalar bodyVol, bodySA, bodyData[14]; 4293bfe80ac4SPierre Jolivet PetscCall(EG_getMassProperties(body, bodyData)); // Does not have an EGlite version KNOWN_ISSUE 42945552b385SBrandon bodyVol = bodyData[0]; 42955552b385SBrandon bodySA = bodyData[1]; 42965552b385SBrandon 42975552b385SBrandon // Cycle through Control Points 42985552b385SBrandon for (int ii = 0; ii < totalNumCPs; ++ii) { // ii should also be the row in cpEquiv for the Control Point 42995552b385SBrandon // Cycle through X, Y, Z, W changes 43005552b385SBrandon for (int jj = 0; jj < 4; ++jj) { 43015552b385SBrandon // Cycle Through Faces 43025552b385SBrandon double denomNew = 0.0, denomOld = 0.0; 43035552b385SBrandon double deltaCoord = 1.0E-4; 43045552b385SBrandon ego newGeom[Nf]; 43055552b385SBrandon ego newFaces[Nf]; 43065552b385SBrandon for (int kk = 0; kk < Nf; ++kk) { 43075552b385SBrandon ego face; 43085552b385SBrandon PetscInt currFID = kk + 1; 43095552b385SBrandon 43105552b385SBrandon if (islite) { 43115552b385SBrandon // Get Current FACE 43125552b385SBrandon PetscCallEGADS(EGlite_objectBodyTopo, (body, FACE, currFID, &face)); 43135552b385SBrandon 43145552b385SBrandon // Get Geometry Object for the Current FACE 43155552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 43165552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 43175552b385SBrandon } else { 43185552b385SBrandon // Get Current FACE 43195552b385SBrandon PetscCallEGADS(EG_objectBodyTopo, (body, FACE, currFID, &face)); 43205552b385SBrandon 43215552b385SBrandon // Get Geometry Object for the Current FACE 43225552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 43235552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 43245552b385SBrandon } 43255552b385SBrandon 43265552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 43275552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 43285552b385SBrandon double nbprv[prvSize]; 43295552b385SBrandon 43305552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 43315552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) nbprv[mm] = bprv[mm]; 43325552b385SBrandon 43335552b385SBrandon // Get Control Point Row and Column Start for cpEquiv 43345552b385SBrandon PetscHashIter Witer; 43355552b385SBrandon PetscBool Wfound; 43365552b385SBrandon PetscInt faceWStartRow; 43375552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, currFID, &Witer, &Wfound)); 43385552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 43395552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, currFID, &faceWStartRow)); 43405552b385SBrandon 43415552b385SBrandon // Modify the Current Control Point on this FACE and All Other FACES 43425552b385SBrandon // IMPORTANT!!! If you do not move all identical Control Points on other FACES 43435552b385SBrandon // you will not generate a solid body. You will generate a set of 43445552b385SBrandon // disconnected surfaces that have gap(s) between them. 43455552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 43465552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 43475552b385SBrandon for (int mm = 0; mm < bpinfo[2] * bpinfo[5]; ++mm) { 43485552b385SBrandon PetscScalar matValue; 43495552b385SBrandon PetscCall(MatGetValue(cpEquiv, ii, faceWStartRow + mm, &matValue)); 43505552b385SBrandon 43515552b385SBrandon if (matValue > 0.0) { 43525552b385SBrandon if (jj == 0) { //X 43535552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0] + deltaCoord; 43545552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 43555552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 43565552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 0]; 43575552b385SBrandon denomOld = bprv[offset + (3 * mm) + 0]; 43585552b385SBrandon } else if (jj == 1) { //Y 43595552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 43605552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1] + deltaCoord; 43615552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 43625552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 1]; 43635552b385SBrandon denomOld = bprv[offset + (3 * mm) + 1]; 43645552b385SBrandon } else if (jj == 2) { //Z 43655552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 43665552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 43675552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2] + deltaCoord; 43685552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 2]; 43695552b385SBrandon denomOld = bprv[offset + (3 * mm) + 2]; 43705552b385SBrandon } else if (jj == 3) { // Weights 43715552b385SBrandon nbprv[wOffset + mm] = bprv[wOffset + mm] + deltaCoord; 43725552b385SBrandon denomNew = nbprv[wOffset + mm]; 43735552b385SBrandon denomOld = bprv[wOffset + mm]; 43745552b385SBrandon } else { 43755552b385SBrandon // currently do nothing 43765552b385SBrandon } 43775552b385SBrandon } 43785552b385SBrandon } 43795552b385SBrandon 43805552b385SBrandon // Create New Surface Based on New Control Points or Weights 43815552b385SBrandon ego newgeom, context; 43825552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ versions KNOWN_ISSUE 43835552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 43845552b385SBrandon 43855552b385SBrandon // Create New FACE based on modified geometry 43865552b385SBrandon double newFaceRange[4]; 43875552b385SBrandon int newFacePeri; 43885552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, newFaceRange, &newFacePeri)); 43895552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, newFaceRange, &newFacePeri)); 43905552b385SBrandon 43915552b385SBrandon ego newface; 43925552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 43935552b385SBrandon 43945552b385SBrandon // store new face for later assembly 43955552b385SBrandon newGeom[kk] = newgeom; 43965552b385SBrandon newFaces[kk] = newface; 43975552b385SBrandon } 43985552b385SBrandon 43995552b385SBrandon // X-WANT TO BUILD THE NEW GEOMETRY, X-GET NEW SA AND PERFORM dSA/dCPi CALCS HERE <--- 44005552b385SBrandon // Sew New Faces together to get a new model 44015552b385SBrandon ego newmodel; 44025552b385SBrandon PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 44035552b385SBrandon 44045552b385SBrandon // Get Surface Area and Volume of New/Updated Solid Body 44055552b385SBrandon PetscScalar newData[14]; 44065552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 44075552b385SBrandon else PetscCallEGADS(EG_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 44085552b385SBrandon 44095552b385SBrandon ego nbody = bodies[0]; 44105552b385SBrandon PetscCall(EG_getMassProperties(nbody, newData)); // Does not have an EGlite_ version KNOWN_ISSUE 44115552b385SBrandon 44125552b385SBrandon PetscScalar dSAdCPi, dVdCPi; 44135552b385SBrandon PetscScalar nbodyVol = newData[0], nbodySA = newData[1]; 44145552b385SBrandon 44155552b385SBrandon // Calculate Gradients wrt to Control Points and Control Points Weights depending on jj value 44165552b385SBrandon dSAdCPi = (nbodySA - bodySA) / (denomNew - denomOld); 44175552b385SBrandon dVdCPi = (nbodyVol - bodyVol) / (denomNew - denomOld); 44185552b385SBrandon 44195552b385SBrandon if (jj < 3) { 44205552b385SBrandon // Gradienst wrt to Control Points 44215552b385SBrandon gradSACP[(ii * 3) + jj] = dSAdCPi; 44225552b385SBrandon gradVCP[(ii * 3) + jj] = dVdCPi; 44235552b385SBrandon } else if (jj == 3) { 44245552b385SBrandon // Gradients wrt to Control Point Weights 44255552b385SBrandon gradSAW[ii] = dSAdCPi; 44265552b385SBrandon gradVW[ii] = dVdCPi; 44275552b385SBrandon } else { 44285552b385SBrandon // Do Nothing 44295552b385SBrandon } 44305552b385SBrandon PetscCallEGADS(EG_deleteObject, (newmodel)); 44315552b385SBrandon for (int kk = 0; kk < Nf; ++kk) { 44325552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[kk])); 44335552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[kk])); 44345552b385SBrandon } 44355552b385SBrandon } 44365552b385SBrandon } 44375552b385SBrandon } 44385552b385SBrandon PetscCall(VecRestoreArrayWrite(gradSACPVec, &gradSACP)); 44395552b385SBrandon PetscCall(VecRestoreArrayWrite(gradSAWVec, &gradSAW)); 44405552b385SBrandon PetscCall(VecRestoreArrayWrite(gradVCPVec, &gradVCP)); 44415552b385SBrandon PetscCall(VecRestoreArrayWrite(gradVWVec, &gradVW)); 44425552b385SBrandon PetscCall(MatDestroy(&cpEquiv)); 44435552b385SBrandon 44445552b385SBrandon // Attach Surface Gradient Hash Table and Matrix to DM 44455552b385SBrandon { 44465552b385SBrandon PetscContainer surfGradOrgObj; 44475552b385SBrandon 44485552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&surfGradOrgObj)); 44495552b385SBrandon if (!surfGradOrgObj) { 44505552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 44515552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 44525552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(surfGradOrgObj, DestroyHashMap)); 44535552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 44545552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 44555552b385SBrandon } else { 44565552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 44575552b385SBrandon } 44585552b385SBrandon 44595552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)pointSurfGrad)); 44605552b385SBrandon PetscCall(MatDestroy(&pointSurfGrad)); 44615552b385SBrandon 44625552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject)gradSACPVec)); 44635552b385SBrandon PetscCall(VecDestroy(&gradSACPVec)); 44645552b385SBrandon 44655552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject)gradSAWVec)); 44665552b385SBrandon PetscCall(VecDestroy(&gradSAWVec)); 44675552b385SBrandon 44685552b385SBrandon if (fullGeomGrad) { 44695552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Control Point Gradient", (PetscObject)gradVCPVec)); 44705552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Weights Gradient", (PetscObject)gradVWVec)); 44715552b385SBrandon } 44725552b385SBrandon PetscCall(VecDestroy(&gradVCPVec)); 44735552b385SBrandon PetscCall(VecDestroy(&gradVWVec)); 44745552b385SBrandon } 44755552b385SBrandon 44765552b385SBrandon // Could be replaced with DMPlexFreeGeomObject() 44775552b385SBrandon if (islite) EGlite_free(fobjs); 44785552b385SBrandon else EG_free(fobjs); 44795552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 44805552b385SBrandon #else 44815552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 44825552b385SBrandon #endif 44835552b385SBrandon } 44845552b385SBrandon 44855552b385SBrandon /*@C 44865552b385SBrandon 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. 44875552b385SBrandon 44885552b385SBrandon Collective 44895552b385SBrandon 44905552b385SBrandon Input Parameters: 44915552b385SBrandon + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 44925552b385SBrandon . comm - MPI_Comm object 44935552b385SBrandon . newCP - C Array of [x, y, z] New/Updated Control Point Coordinates defining the geometry (See DMPlexGeomDataAndGrads() for format) 44945552b385SBrandon . newW - C Array of New/Updated Control Point Weights associated with the Control Points defining the new geometry (See DMPlexGemGrads() for format) 44955552b385SBrandon . autoInflate - PetscBool Flag denoting if the user would like to inflate the DM points to the new geometry. 44965552b385SBrandon . saveGeom - PetscBool Flag denoting if the user would iike to save the new geometry to a file. 44975552b385SBrandon - 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. 44985552b385SBrandon *.stp or *.step = STEP File 44995552b385SBrandon *.igs or *.iges = IGES File 45005552b385SBrandon *.egads = EGADS File 45015552b385SBrandon *.brep = BRep File (OpenCASCADE File) 45025552b385SBrandon 45035552b385SBrandon Output Parameter: 45045552b385SBrandon . dm - The updated DM object representing the mesh with PetscContainers containing the updated/modified geometry 45055552b385SBrandon 45065552b385SBrandon Level: intermediate 45075552b385SBrandon 45085552b385SBrandon Note: 45095552b385SBrandon Functionality not available for DMPlexes with attached EGADSlite geometry files (.egadslite). 45105552b385SBrandon 45115552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 45125552b385SBrandon @*/ 4513ce78bad3SBarry Smith PetscErrorCode DMPlexModifyGeomModel(DM dm, MPI_Comm comm, PetscScalar newCP[], PetscScalar newW[], PetscBool autoInflate, PetscBool saveGeom, const char *stpName) PeNS 45145552b385SBrandon { 45155552b385SBrandon #if defined(PETSC_HAVE_EGADS) 45165552b385SBrandon /* EGADS/EGADSlite variables */ 45175552b385SBrandon ego context, model, geom, *bodies, *lobjs, *fobjs; 45185552b385SBrandon int oclass, mtype, *senses, *lsenses; 45195552b385SBrandon int Nb, Nf, Nl, id; 45205552b385SBrandon /* PETSc variables */ 45215552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 45225552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj; 45235552b385SBrandon PetscHMapI cpHashTable = NULL, wHashTable = NULL; 45245552b385SBrandon PetscBool islite = PETSC_FALSE; 45255552b385SBrandon #endif 45265552b385SBrandon 45275552b385SBrandon #if defined(PETSC_HAVE_EGADS) 45285552b385SBrandon PetscFunctionBegin; 45295552b385SBrandon // Look to see if DM has a Container with either a EGADS or EGADSlite Model 45305552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 45315552b385SBrandon if (!modelObj) { 45325552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 45335552b385SBrandon islite = PETSC_TRUE; 45345552b385SBrandon } 45355552b385SBrandon 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"); 45365552b385SBrandon PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have a EGADS Geometry Model attached to it!"); 45375552b385SBrandon 45385552b385SBrandon // Get attached EGADS model (pointer) 45395552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 45405552b385SBrandon 45415552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 45425552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 45435552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 45445552b385SBrandon 45455552b385SBrandon PetscCheck(cpHashTableObj && wHashTableObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have required Geometry Data attached! Please run DMPlexGeomDataAndGrads() Function first."); 45465552b385SBrandon 45475552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 45485552b385SBrandon PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTable)); 45495552b385SBrandon PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTable)); 45505552b385SBrandon 45515552b385SBrandon // Get the number of bodies and body objects in the model 45525552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 45535552b385SBrandon else PetscCallEGADS(EG_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 45545552b385SBrandon 45555552b385SBrandon // Get all Faces on the body 45565552b385SBrandon ego body = bodies[0]; 45575552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 45585552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 45595552b385SBrandon 45605552b385SBrandon ego newGeom[Nf]; 45615552b385SBrandon ego newFaces[Nf]; 45625552b385SBrandon 45635552b385SBrandon // Update Control Point and Weight definitions for each surface 45645552b385SBrandon for (int jj = 0; jj < Nf; ++jj) { 45655552b385SBrandon ego face = fobjs[jj]; 45665552b385SBrandon ego bRef, bPrev, bNext; 45675552b385SBrandon ego fgeom; 45685552b385SBrandon int offset; 45695552b385SBrandon int boclass, bmtype, *bpinfo; 45705552b385SBrandon double *bprv; 45715552b385SBrandon 45725552b385SBrandon // Get FACE ID and other Geometry Data 45735552b385SBrandon if (islite) { 45745552b385SBrandon id = EGlite_indexBodyTopo(body, face); 45755552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 45765552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 45775552b385SBrandon PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 45785552b385SBrandon } else { 45795552b385SBrandon id = EG_indexBodyTopo(body, face); 45805552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 45815552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 45825552b385SBrandon PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 45835552b385SBrandon } 45845552b385SBrandon 45855552b385SBrandon // Update Control Points 45865552b385SBrandon PetscHashIter CPiter, Witer; 45875552b385SBrandon PetscBool CPfound, Wfound; 45885552b385SBrandon PetscInt faceCPStartRow, faceWStartRow; 45895552b385SBrandon 45905552b385SBrandon PetscCall(PetscHMapIFind(cpHashTable, id, &CPiter, &CPfound)); 45915552b385SBrandon PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 45925552b385SBrandon PetscCall(PetscHMapIGet(cpHashTable, id, &faceCPStartRow)); 45935552b385SBrandon 45945552b385SBrandon PetscCall(PetscHMapIFind(wHashTable, id, &Witer, &Wfound)); 45955552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 45965552b385SBrandon PetscCall(PetscHMapIGet(wHashTable, id, &faceWStartRow)); 45975552b385SBrandon 45985552b385SBrandon // UPDATE CONTROL POINTS Locations 45995552b385SBrandon offset = bpinfo[3] + bpinfo[6]; 46005552b385SBrandon for (int ii = 0; ii < 3 * bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newCP[faceCPStartRow + ii]; } 46015552b385SBrandon 46025552b385SBrandon // UPDATE CONTROL POINT WEIGHTS 46035552b385SBrandon offset = bpinfo[3] + bpinfo[6] + 3 * bpinfo[2] * bpinfo[5]; 46045552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newW[faceWStartRow + ii]; } 46055552b385SBrandon 46065552b385SBrandon // Get Context from FACE 46075552b385SBrandon context = NULL; 46085552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version KNOWN_ISSUE 46095552b385SBrandon 46105552b385SBrandon // Create New Surface 46115552b385SBrandon ego newgeom; 46125552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 46135552b385SBrandon 46145552b385SBrandon // Create new FACE based on new SURFACE geometry 46155552b385SBrandon double data[4]; 46165552b385SBrandon int periodic; 46175552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 46185552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 46195552b385SBrandon 46205552b385SBrandon ego newface; 46215552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 46225552b385SBrandon newGeom[jj] = newgeom; 46235552b385SBrandon newFaces[jj] = newface; 46245552b385SBrandon } 46255552b385SBrandon // Could be replaced by DMPlexFreeGeomObject 46265552b385SBrandon if (islite) EGlite_free(fobjs); 46275552b385SBrandon else EG_free(fobjs); 46285552b385SBrandon 46295552b385SBrandon // Sew New Faces together to get a new model 46305552b385SBrandon ego newmodel; 46315552b385SBrandon PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 46325552b385SBrandon for (PetscInt f = 0; f < Nf; ++f) { 46335552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[f])); 46345552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[f])); 46355552b385SBrandon } 46365552b385SBrandon 46375552b385SBrandon // Get the total number of NODEs on the original geometry. (This will be the same for the new geometry) 46385552b385SBrandon int totalNumNode; 46395552b385SBrandon ego *nobjTotal; 46405552b385SBrandon if (islite) { 46415552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 46425552b385SBrandon EGlite_free(nobjTotal); 46435552b385SBrandon } else { 46445552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 46455552b385SBrandon EG_free(nobjTotal); 46465552b385SBrandon } // Could be replaced with DMPlexFreeGeomObject 46475552b385SBrandon 46485552b385SBrandon // Initialize vector to store equivalent NODE indices between the 2 geometries 46495552b385SBrandon // FORMAT :: vector index is the Original Geometry's NODE ID, the vector Value is the New Geometry's NODE ID 46505552b385SBrandon int nodeIDEquiv[totalNumNode + 1]; 46515552b385SBrandon 46525552b385SBrandon // Now we need to Map the NODE and EDGE IDs from each Model 46535552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 46545552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 46555552b385SBrandon 46565552b385SBrandon // New CAD 46575552b385SBrandon ego *newbodies, newgeomtest, *nfobjs; 46585552b385SBrandon int nNf, newNb, newoclass, newmtype, *newsenses; 46595552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 46605552b385SBrandon else PetscCallEGADS(EG_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 46615552b385SBrandon 46625552b385SBrandon ego newbody = newbodies[0]; 46635552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 46645552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 46655552b385SBrandon 46665552b385SBrandon PetscCheck(newNb == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ERROR :: newNb > 1 || newNb = %d", newNb); 46675552b385SBrandon 46685552b385SBrandon // Find Equivalent Nodes 46695552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 46705552b385SBrandon double fdata[4]; 46715552b385SBrandon int peri; 46725552b385SBrandon 46735552b385SBrandon // Get Current FACE [u, v] Ranges 46745552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (fobjs[ii], fdata, &peri)); 46755552b385SBrandon else PetscCallEGADS(EG_getRange, (fobjs[ii], fdata, &peri)); 46765552b385SBrandon 46775552b385SBrandon // Equate NODE IDs between 2 FACEs by working through (u, v) limits of FACE 46785552b385SBrandon for (int jj = 0; jj < 2; ++jj) { 46795552b385SBrandon for (int kk = 2; kk < 4; ++kk) { 46805552b385SBrandon double params[2] = {fdata[jj], fdata[kk]}; 46815552b385SBrandon double eval[18]; 46825552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (fobjs[ii], params, eval)); 46835552b385SBrandon else PetscCallEGADS(EG_evaluate, (fobjs[ii], params, eval)); 46845552b385SBrandon 46855552b385SBrandon // Original Body 46865552b385SBrandon ego *nobjsOrigFace; 46875552b385SBrandon int origNn; 46885552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 46895552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 46905552b385SBrandon 46915552b385SBrandon double minVal = 1.0E10; 46925552b385SBrandon double evalCheck[18]; 46935552b385SBrandon int equivOrigNodeID = -1; 46945552b385SBrandon for (int mm = 0; mm < origNn; ++mm) { 46955552b385SBrandon double delta = 1.0E10; 46965552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 46975552b385SBrandon else PetscCallEGADS(EG_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 46985552b385SBrandon 46995552b385SBrandon delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 47005552b385SBrandon 47015552b385SBrandon if (delta < minVal) { 47025552b385SBrandon if (islite) equivOrigNodeID = EGlite_indexBodyTopo(body, nobjsOrigFace[mm]); 47035552b385SBrandon else equivOrigNodeID = EG_indexBodyTopo(body, nobjsOrigFace[mm]); 47045552b385SBrandon 47055552b385SBrandon minVal = delta; 47065552b385SBrandon } 47075552b385SBrandon } 47085552b385SBrandon // Could be replaced with DMPlexFreeGeomObject 47095552b385SBrandon if (islite) EGlite_free(nobjsOrigFace); 47105552b385SBrandon else EG_free(nobjsOrigFace); 47115552b385SBrandon 47125552b385SBrandon // New Body 47135552b385SBrandon ego *nobjsNewFace; 47145552b385SBrandon int newNn; 47155552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 47165552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 47175552b385SBrandon 47185552b385SBrandon minVal = 1.0E10; 47195552b385SBrandon int equivNewNodeID = -1; 47205552b385SBrandon for (int mm = 0; mm < newNn; ++mm) { 47215552b385SBrandon double delta = 1.0E10; 47225552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 47235552b385SBrandon else PetscCallEGADS(EG_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 47245552b385SBrandon 47255552b385SBrandon delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 47265552b385SBrandon 47275552b385SBrandon if (delta < minVal) { 47285552b385SBrandon if (islite) equivNewNodeID = EGlite_indexBodyTopo(newbody, nobjsNewFace[mm]); 47295552b385SBrandon else equivNewNodeID = EG_indexBodyTopo(newbody, nobjsNewFace[mm]); 47305552b385SBrandon 47315552b385SBrandon minVal = delta; 47325552b385SBrandon } 47335552b385SBrandon } 47345552b385SBrandon if (islite) EGlite_free(nobjsNewFace); 47355552b385SBrandon else EG_free(nobjsNewFace); 47365552b385SBrandon 47375552b385SBrandon // Store equivalent NODE IDs 47385552b385SBrandon nodeIDEquiv[equivOrigNodeID] = equivNewNodeID; 47395552b385SBrandon } 47405552b385SBrandon } 47415552b385SBrandon } 47425552b385SBrandon 47435552b385SBrandon // Find Equivalent EDGEs 47445552b385SBrandon // Get total number of EDGEs on Original Geometry 47455552b385SBrandon int totalNumEdge; 47465552b385SBrandon ego *eobjsOrig; 47475552b385SBrandon if (islite) { 47485552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 47495552b385SBrandon EGlite_free(eobjsOrig); 47505552b385SBrandon } else { 47515552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 47525552b385SBrandon EG_free(eobjsOrig); 47535552b385SBrandon } 47545552b385SBrandon 47555552b385SBrandon // Get total number of EDGEs on New Geometry 47565552b385SBrandon int totalNumEdgeNew; 47575552b385SBrandon ego *eobjsNew; 47585552b385SBrandon if (islite) { 47595552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 47605552b385SBrandon EGlite_free(eobjsNew); 47615552b385SBrandon } else { 47625552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 47635552b385SBrandon EG_free(eobjsNew); 47645552b385SBrandon } 47655552b385SBrandon 47665552b385SBrandon // Initialize EDGE ID equivalent vector 47675552b385SBrandon // FORMAT :: vector index is the Original Geometry's EDGE ID, the vector Value is the New Geometry's EDGE ID 47685552b385SBrandon int edgeIDEquiv[totalNumEdge + 1]; 47695552b385SBrandon 47705552b385SBrandon // Find Equivalent EDGEs 47715552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 47725552b385SBrandon // Get Original Geometry EDGE's NODEs 47735552b385SBrandon int numOrigEdge, numNewEdge; 47745552b385SBrandon if (islite) { 47755552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 47765552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 47775552b385SBrandon } else { 47785552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 47795552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 47805552b385SBrandon } 47815552b385SBrandon 47825552b385SBrandon // new loop below 47835552b385SBrandon for (int nn = 0; nn < numOrigEdge; ++nn) { 47845552b385SBrandon ego origEdge = eobjsOrig[nn]; 47855552b385SBrandon ego geomEdgeOrig, *nobjsOrig; 47865552b385SBrandon int oclassEdgeOrig, mtypeEdgeOrig; 47875552b385SBrandon int NnOrig, *nsensesEdgeOrig; 47885552b385SBrandon 47895552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 47905552b385SBrandon else PetscCallEGADS(EG_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 47915552b385SBrandon 47925552b385SBrandon PetscBool isSame = PETSC_FALSE; 47935552b385SBrandon for (int jj = 0; jj < numNewEdge; ++jj) { 47945552b385SBrandon ego newEdge = eobjsNew[jj]; 47955552b385SBrandon ego geomEdgeNew, *nobjsNew; 47965552b385SBrandon int oclassEdgeNew, mtypeEdgeNew; 47975552b385SBrandon int NnNew, *nsensesEdgeNew; 47985552b385SBrandon 47995552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 48005552b385SBrandon else PetscCallEGADS(EG_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 48015552b385SBrandon 48025552b385SBrandon if (mtypeEdgeOrig == mtypeEdgeNew) { 48035552b385SBrandon // Only operate if the EDGE types are the same 48045552b385SBrandon for (int kk = 0; kk < NnNew; ++kk) { 48055552b385SBrandon int nodeIDOrigGeom, nodeIDNewGeom; 48065552b385SBrandon if (islite) { 48075552b385SBrandon nodeIDOrigGeom = EGlite_indexBodyTopo(body, nobjsOrig[kk]); 48085552b385SBrandon nodeIDNewGeom = EGlite_indexBodyTopo(newbody, nobjsNew[kk]); 48095552b385SBrandon } else { 48105552b385SBrandon nodeIDOrigGeom = EG_indexBodyTopo(body, nobjsOrig[kk]); 48115552b385SBrandon nodeIDNewGeom = EG_indexBodyTopo(newbody, nobjsNew[kk]); 48125552b385SBrandon } 48135552b385SBrandon 48145552b385SBrandon if (nodeIDNewGeom == nodeIDEquiv[nodeIDOrigGeom]) { 48155552b385SBrandon isSame = PETSC_TRUE; 48165552b385SBrandon } else { 48175552b385SBrandon isSame = PETSC_FALSE; 48185552b385SBrandon kk = NnNew; // skip ahead because first NODE failed test and order is important 48195552b385SBrandon } 48205552b385SBrandon } 48215552b385SBrandon 48225552b385SBrandon if (isSame == PETSC_TRUE) { 48235552b385SBrandon int edgeIDOrig, edgeIDNew; 48245552b385SBrandon if (islite) { 48255552b385SBrandon edgeIDOrig = EGlite_indexBodyTopo(body, origEdge); 48265552b385SBrandon edgeIDNew = EGlite_indexBodyTopo(newbody, newEdge); 48275552b385SBrandon } else { 48285552b385SBrandon edgeIDOrig = EG_indexBodyTopo(body, origEdge); 48295552b385SBrandon edgeIDNew = EG_indexBodyTopo(newbody, newEdge); 48305552b385SBrandon } 48315552b385SBrandon 48325552b385SBrandon edgeIDEquiv[edgeIDOrig] = edgeIDNew; 48335552b385SBrandon jj = numNewEdge; 48345552b385SBrandon } 48355552b385SBrandon } 48365552b385SBrandon } 48375552b385SBrandon } 48385552b385SBrandon if (islite) { 48395552b385SBrandon EGlite_free(eobjsOrig); 48405552b385SBrandon EGlite_free(eobjsNew); 48415552b385SBrandon } else { 48425552b385SBrandon EG_free(eobjsOrig); 48435552b385SBrandon EG_free(eobjsNew); 48445552b385SBrandon } 48455552b385SBrandon } 48465552b385SBrandon if (islite) { 48475552b385SBrandon EGlite_free(fobjs); 48485552b385SBrandon EGlite_free(nfobjs); 48495552b385SBrandon } else { 48505552b385SBrandon EG_free(fobjs); 48515552b385SBrandon EG_free(nfobjs); 48525552b385SBrandon } 48535552b385SBrandon 48545552b385SBrandon // Modify labels to point to the IDs on the new Geometry 48555552b385SBrandon IS isNodeID, isEdgeID; 48565552b385SBrandon 48575552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 48585552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 48595552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 48605552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 48615552b385SBrandon 48625552b385SBrandon PetscCall(ISCreateGeneral(comm, totalNumNode + 1, nodeIDEquiv, PETSC_COPY_VALUES, &isNodeID)); 48635552b385SBrandon PetscCall(ISCreateGeneral(comm, totalNumEdge + 1, edgeIDEquiv, PETSC_COPY_VALUES, &isEdgeID)); 48645552b385SBrandon /* Do not perform check. Np may != Nv due to Degenerate Geometry which is not stored in labels. */ 48655552b385SBrandon /* We do not know in advance which IDs have been omitted. This may also change due to geometry modifications. */ 48665552b385SBrandon PetscCall(DMLabelRewriteValues(vertexLabel, isNodeID)); 48675552b385SBrandon PetscCall(DMLabelRewriteValues(edgeLabel, isEdgeID)); 48685552b385SBrandon PetscCall(ISDestroy(&isNodeID)); 48695552b385SBrandon PetscCall(ISDestroy(&isEdgeID)); 48705552b385SBrandon 48715552b385SBrandon // Attempt to point to the new geometry 48725552b385SBrandon PetscCallEGADS(EG_deleteObject, (model)); 48735552b385SBrandon PetscCall(PetscContainerSetPointer(modelObj, newmodel)); 48745552b385SBrandon 48755552b385SBrandon // save updated model to file 48765552b385SBrandon if (saveGeom == PETSC_TRUE && stpName != NULL) PetscCall(EG_saveModel(newmodel, stpName)); 48775552b385SBrandon 48785552b385SBrandon // Inflate Mesh to EGADS Model 48795552b385SBrandon if (autoInflate == PETSC_TRUE) PetscCall(DMPlexInflateToGeomModel(dm, PETSC_TRUE)); 48805552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 48815552b385SBrandon #else 48825552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 48835552b385SBrandon #endif 48845552b385SBrandon } 48855552b385SBrandon 48865552b385SBrandon /*@C 48875552b385SBrandon 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. 48885552b385SBrandon 48895552b385SBrandon Collective 48905552b385SBrandon 48915552b385SBrandon Input Parameter: 48925552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 48935552b385SBrandon 48945552b385SBrandon Level: intermediate 48955552b385SBrandon 48965552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 48975552b385SBrandon @*/ 4898ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelTUV(DM dm) PeNS 48995552b385SBrandon { 49005552b385SBrandon #if defined(PETSC_HAVE_EGADS) 49015552b385SBrandon /* EGADS Variables */ 49025552b385SBrandon ego model, geom, body, face, edge; 49035552b385SBrandon ego *bodies; 49045552b385SBrandon int Nb, oclass, mtype, *senses; 49055552b385SBrandon double result[4]; 49065552b385SBrandon /* PETSc Variables */ 49075552b385SBrandon DM cdm; 49085552b385SBrandon PetscContainer modelObj; 49095552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 49105552b385SBrandon Vec coordinates; 49115552b385SBrandon PetscScalar *coords; 49125552b385SBrandon PetscInt bodyID, faceID, edgeID, vertexID; 49135552b385SBrandon PetscInt cdim, vStart, vEnd, v; 49145552b385SBrandon PetscBool islite = PETSC_FALSE; 49155552b385SBrandon #endif 49165552b385SBrandon 49175552b385SBrandon PetscFunctionBegin; 49185552b385SBrandon #if defined(PETSC_HAVE_EGADS) 49195552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 49205552b385SBrandon if (!modelObj) { 49215552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 49225552b385SBrandon islite = PETSC_TRUE; 49235552b385SBrandon } 4924*b6555650SPierre Jolivet if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 49255552b385SBrandon 49265552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &cdim)); 49275552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 49285552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 49295552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 49305552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 49315552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 49325552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 49335552b385SBrandon 49345552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 49355552b385SBrandon 49365552b385SBrandon if (islite) PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 49375552b385SBrandon else PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 49385552b385SBrandon 49395552b385SBrandon PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 49405552b385SBrandon PetscCall(VecGetArrayWrite(coordinates, &coords)); 49415552b385SBrandon 49425552b385SBrandon // Define t, u, v arrays to be stored in a PetscContainer after populated 49435552b385SBrandon PetscScalar *t_point, *u_point, *v_point; 49445552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &t_point)); 49455552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &u_point)); 49465552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &v_point)); 49475552b385SBrandon 49485552b385SBrandon for (v = vStart; v < vEnd; ++v) { 49495552b385SBrandon PetscScalar *vcoords; 49505552b385SBrandon 49515552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 49525552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 49535552b385SBrandon PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 49545552b385SBrandon PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 49555552b385SBrandon 49565552b385SBrandon // TODO Figure out why this is unknown sometimes 49575552b385SBrandon if (bodyID < 0 && Nb == 1) bodyID = 0; 49585552b385SBrandon 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); 4959c1cad2e7SMatthew G. Knepley body = bodies[bodyID]; 4960c1cad2e7SMatthew G. Knepley 49619566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 4962c1cad2e7SMatthew G. Knepley if (edgeID > 0) { 4963c1cad2e7SMatthew G. Knepley /* Snap to EDGE at nearest location */ 4964c1cad2e7SMatthew G. Knepley double params[1]; 49655552b385SBrandon 49665552b385SBrandon if (islite) { 49675552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 49685552b385SBrandon PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 49695552b385SBrandon } // Get (t) of nearest point on EDGE 49705552b385SBrandon else { 49719566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 49725552b385SBrandon PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 49735552b385SBrandon } // Get (t) of nearest point on EDGE 49745552b385SBrandon 49755552b385SBrandon t_point[v - vStart] = params[0]; 49765552b385SBrandon u_point[v - vStart] = 0.0; 49775552b385SBrandon v_point[v - vStart] = 0.0; 4978c1cad2e7SMatthew G. Knepley } else if (faceID > 0) { 4979c1cad2e7SMatthew G. Knepley /* Snap to FACE at nearest location */ 4980c1cad2e7SMatthew G. Knepley double params[2]; 49815552b385SBrandon 49825552b385SBrandon if (islite) { 49835552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 49845552b385SBrandon PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 49855552b385SBrandon } // Get (x,y,z) of nearest point on FACE 49865552b385SBrandon else { 49879566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 49885552b385SBrandon PetscCall(EG_invEvaluate(face, vcoords, params, result)); 49895552b385SBrandon } // Get (x,y,z) of nearest point on FACE 49905552b385SBrandon 49915552b385SBrandon t_point[v - vStart] = 0.0; 49925552b385SBrandon u_point[v - vStart] = params[0]; 49935552b385SBrandon v_point[v - vStart] = params[1]; 49945552b385SBrandon } else { 49955552b385SBrandon t_point[v - vStart] = 0.0; 49965552b385SBrandon u_point[v - vStart] = 0.0; 49975552b385SBrandon v_point[v - vStart] = 0.0; 49985552b385SBrandon } 49995552b385SBrandon } 50005552b385SBrandon PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 50015552b385SBrandon /* Clear out global coordinates */ 50025552b385SBrandon PetscCall(VecDestroy(&dm->coordinates[0].x)); 50035552b385SBrandon 50045552b385SBrandon /* Store in PetscContainters */ 50055552b385SBrandon { 50065552b385SBrandon PetscContainer t_pointObj, u_pointObj, v_pointObj; 50075552b385SBrandon 50085552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 50095552b385SBrandon if (!t_pointObj) { 50105552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &t_pointObj)); 50115552b385SBrandon PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 50125552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Edge t Parameter", (PetscObject)t_pointObj)); 50135552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(t_pointObj, PetscCtxDestroyDefault)); 50145552b385SBrandon PetscCall(PetscContainerDestroy(&t_pointObj)); 50155552b385SBrandon } else { 50165552b385SBrandon void *old; 50175552b385SBrandon 50185552b385SBrandon PetscCall(PetscContainerGetPointer(t_pointObj, &old)); 50195552b385SBrandon PetscCall(PetscFree(old)); 50205552b385SBrandon PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 50215552b385SBrandon } 50225552b385SBrandon 50235552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 50245552b385SBrandon if (!u_pointObj) { 50255552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &u_pointObj)); 50265552b385SBrandon PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 50275552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face u Parameter", (PetscObject)u_pointObj)); 50285552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(u_pointObj, PetscCtxDestroyDefault)); 50295552b385SBrandon PetscCall(PetscContainerDestroy(&u_pointObj)); 50305552b385SBrandon } else { 50315552b385SBrandon void *old; 50325552b385SBrandon 50335552b385SBrandon PetscCall(PetscContainerGetPointer(u_pointObj, &old)); 50345552b385SBrandon PetscCall(PetscFree(old)); 50355552b385SBrandon PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 50365552b385SBrandon } 50375552b385SBrandon 50385552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 50395552b385SBrandon if (!v_pointObj) { 50405552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &v_pointObj)); 50415552b385SBrandon PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 50425552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face v Parameter", (PetscObject)v_pointObj)); 50435552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(v_pointObj, PetscCtxDestroyDefault)); 50445552b385SBrandon PetscCall(PetscContainerDestroy(&v_pointObj)); 50455552b385SBrandon } else { 50465552b385SBrandon void *old; 50475552b385SBrandon 50485552b385SBrandon PetscCall(PetscContainerGetPointer(v_pointObj, &old)); 50495552b385SBrandon PetscCall(PetscFree(old)); 50505552b385SBrandon PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 50515552b385SBrandon } 50525552b385SBrandon } 50535552b385SBrandon #endif 50545552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 50555552b385SBrandon } 50565552b385SBrandon 50575552b385SBrandon /*@C 50585552b385SBrandon 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(). 50595552b385SBrandon 50605552b385SBrandon Collective 50615552b385SBrandon 50625552b385SBrandon Input Parameter: 50635552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 50645552b385SBrandon 50655552b385SBrandon Level: intermediate 50665552b385SBrandon 50675552b385SBrandon Note: 50685552b385SBrandon The updated DM object inflated to the associated underlying geometry. This updates the [x, y, z] coordinates of DM points associated with geometry. 50695552b385SBrandon 50705552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()`, `DMPlexGetGeomModelTUV()` 50715552b385SBrandon @*/ 5072ce78bad3SBarry Smith PetscErrorCode DMPlexInflateToGeomModelUseTUV(DM dm) PeNS 50735552b385SBrandon { 50745552b385SBrandon #if defined(PETSC_HAVE_EGADS) 50755552b385SBrandon /* EGADS Variables */ 50765552b385SBrandon ego model, geom, body, face, edge, vertex; 50775552b385SBrandon ego *bodies; 50785552b385SBrandon int Nb, oclass, mtype, *senses; 50795552b385SBrandon double result[18], params[2]; 50805552b385SBrandon /* PETSc Variables */ 50815552b385SBrandon DM cdm; 50825552b385SBrandon PetscContainer modelObj; 50835552b385SBrandon PetscContainer t_pointObj, u_pointObj, v_pointObj; 50845552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 50855552b385SBrandon Vec coordinates; 50865552b385SBrandon PetscScalar *coords; 50875552b385SBrandon PetscScalar *t_point, *u_point, *v_point; 50885552b385SBrandon PetscInt bodyID, faceID, edgeID, vertexID; 50895552b385SBrandon PetscInt cdim, d, vStart, vEnd, v; 50905552b385SBrandon PetscBool islite = PETSC_FALSE; 50915552b385SBrandon #endif 50925552b385SBrandon 50935552b385SBrandon PetscFunctionBegin; 50945552b385SBrandon #if defined(PETSC_HAVE_EGADS) 50955552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 50965552b385SBrandon if (!modelObj) { 50975552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 50985552b385SBrandon islite = PETSC_TRUE; 50995552b385SBrandon } 51005552b385SBrandon 51015552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 51025552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 51035552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 51045552b385SBrandon 51055552b385SBrandon if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 51065552b385SBrandon if (!t_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 51075552b385SBrandon if (!u_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 51085552b385SBrandon if (!v_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 51095552b385SBrandon 51105552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &cdim)); 51115552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 51125552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 51135552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 51145552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 51155552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 51165552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 51175552b385SBrandon 51185552b385SBrandon PetscCall(PetscContainerGetPointer(t_pointObj, (void **)&t_point)); 51195552b385SBrandon PetscCall(PetscContainerGetPointer(u_pointObj, (void **)&u_point)); 51205552b385SBrandon PetscCall(PetscContainerGetPointer(v_pointObj, (void **)&v_point)); 51215552b385SBrandon 51225552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 51235552b385SBrandon 51245552b385SBrandon if (islite) { 51255552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 51265552b385SBrandon } else { 51275552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 51285552b385SBrandon } 51295552b385SBrandon 51305552b385SBrandon PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 51315552b385SBrandon PetscCall(VecGetArrayWrite(coordinates, &coords)); 51325552b385SBrandon 51335552b385SBrandon for (v = vStart; v < vEnd; ++v) { 51345552b385SBrandon PetscScalar *vcoords; 51355552b385SBrandon 51365552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 51375552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 51385552b385SBrandon PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 51395552b385SBrandon PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 51405552b385SBrandon 51415552b385SBrandon // TODO Figure out why this is unknown sometimes 51425552b385SBrandon if (bodyID < 0 && Nb == 1) bodyID = 0; 51435552b385SBrandon 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); 51445552b385SBrandon body = bodies[bodyID]; 51455552b385SBrandon 51465552b385SBrandon PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 51475552b385SBrandon if (vertexID > 0) { 51485552b385SBrandon /* Snap to Vertices */ 51495552b385SBrandon if (islite) { 51505552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 51515552b385SBrandon PetscCall(EGlite_evaluate(vertex, NULL, result)); 51525552b385SBrandon } else { 51535552b385SBrandon PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 51545552b385SBrandon PetscCall(EG_evaluate(vertex, NULL, result)); 51555552b385SBrandon } 51565552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 51575552b385SBrandon } else if (edgeID > 0) { 51585552b385SBrandon /* Snap to EDGE */ 51595552b385SBrandon params[0] = t_point[v - vStart]; 51605552b385SBrandon if (islite) { 51615552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 51625552b385SBrandon PetscCall(EGlite_evaluate(edge, params, result)); 51635552b385SBrandon } else { 51645552b385SBrandon PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 51655552b385SBrandon PetscCall(EG_evaluate(edge, params, result)); 51665552b385SBrandon } 51675552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 51685552b385SBrandon } else if (faceID > 0) { 51695552b385SBrandon /* Snap to FACE */ 51705552b385SBrandon params[0] = u_point[v - vStart]; 51715552b385SBrandon params[1] = v_point[v - vStart]; 51725552b385SBrandon if (islite) { 51735552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 51745552b385SBrandon PetscCall(EGlite_evaluate(face, params, result)); 51755552b385SBrandon } else { 51765552b385SBrandon PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 51775552b385SBrandon PetscCall(EG_evaluate(face, params, result)); 51785552b385SBrandon } 5179c1cad2e7SMatthew G. Knepley for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5180c1cad2e7SMatthew G. Knepley } 5181c1cad2e7SMatthew G. Knepley } 51829566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 5183c1cad2e7SMatthew G. Knepley /* Clear out global coordinates */ 51846858538eSMatthew G. Knepley PetscCall(VecDestroy(&dm->coordinates[0].x)); 5185c1cad2e7SMatthew G. Knepley #endif 51863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5187c1cad2e7SMatthew G. Knepley } 5188c1cad2e7SMatthew G. Knepley 5189cc4c1da9SBarry Smith /*@ 51905552b385SBrandon DMPlexInflateToGeomModel - Wrapper function allowing two methods for inflating refined meshes to the underlying geometric domain. 51917bee2925SMatthew Knepley 51927bee2925SMatthew Knepley Collective 51937bee2925SMatthew Knepley 51947bee2925SMatthew Knepley Input Parameters: 51955552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 51965552b385SBrandon - useTUV - PetscBool indicating if the user would like to inflate the DMPlex to the underlying geometry 51975552b385SBrandon using (t) for nodes on EDGEs and (u, v) for nodes on FACEs or using the nodes (x, y, z) coordinates 51985552b385SBrandon and shortest distance routine. 51995552b385SBrandon If useTUV = PETSC_TRUE, use the (t) or (u, v) parameters to inflate the DMPlex to the CAD geometry. 52005552b385SBrandon If useTUV = PETSC_FALSE, use the nodes (x, y, z) coordinates and the shortest disctance routine. 52015552b385SBrandon 52025552b385SBrandon Notes: 52035552b385SBrandon DM with nodal coordinates modified so that they lie on the EDGEs and FACEs of the underlying geometry. 52045552b385SBrandon 52055552b385SBrandon (t) and (u, v) parameters for all DMPlex nodes on EDGEs and FACEs are stored in arrays within PetscContainers attached to the DM. 52065552b385SBrandon The containers have names "Point - Edge t Parameter", "Point - Face u Parameter", and "Point - Face v Parameter". 52075552b385SBrandon The arrays are organized by Point 0-based ID (i.e. [v-vstart] as defined in the DMPlex. 52085552b385SBrandon 52095552b385SBrandon Level: intermediate 52105552b385SBrandon 52115552b385SBrandon .seealso: `DMPlexGetGeomModelTUV()`, `DMPlexInflateToGeomModelUseTUV()`, `DMPlexInflateToGeomModelUseXYZ()` 52125552b385SBrandon @*/ 5213ce78bad3SBarry Smith PetscErrorCode DMPlexInflateToGeomModel(DM dm, PetscBool useTUV) PeNS 52145552b385SBrandon { 52155552b385SBrandon PetscFunctionBeginHot; 52165552b385SBrandon if (useTUV) { 52175552b385SBrandon PetscCall(DMPlexGetGeomModelTUV(dm)); 52185552b385SBrandon PetscCall(DMPlexInflateToGeomModelUseTUV(dm)); 52195552b385SBrandon } else { 52205552b385SBrandon PetscCall(DMPlexInflateToGeomModelUseXYZ(dm)); 52215552b385SBrandon } 52225552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 52235552b385SBrandon } 52245552b385SBrandon 52255552b385SBrandon #ifdef PETSC_HAVE_EGADS 52265552b385SBrandon /*@C 5227bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodies - Returns an array of `PetscGeom` BODY objects attached to the referenced geometric model entity as well as the number of BODYs. 52285552b385SBrandon 52295552b385SBrandon Collective 52305552b385SBrandon 52315552b385SBrandon Input Parameter: 52325552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 52335552b385SBrandon 52345552b385SBrandon Output Parameters: 52355552b385SBrandon + bodies - Array of PetscGeom BODY objects referenced by the geometric model. 52365552b385SBrandon - numBodies - Number of BODYs referenced by the geometric model. Also the size of **bodies array. 52375552b385SBrandon 52385552b385SBrandon Level: intermediate 52395552b385SBrandon 52405552b385SBrandon .seealso: 52415552b385SBrandon @*/ 5242ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodies(DM dm, PetscGeom **bodies, PetscInt *numBodies) PeNS 52435552b385SBrandon { 52445552b385SBrandon PetscFunctionBeginHot; 52455552b385SBrandon PetscContainer modelObj; 52465552b385SBrandon PetscBool islite = PETSC_FALSE; 52475552b385SBrandon ego model, geom; 52485552b385SBrandon int oclass, mtype; 52495552b385SBrandon int *senses; 52505552b385SBrandon 52515552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 52525552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 52535552b385SBrandon if (!modelObj) { 52545552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 52555552b385SBrandon islite = PETSC_TRUE; 52565552b385SBrandon } 52575552b385SBrandon 52585552b385SBrandon // Get attached EGADS or EGADSlite model (pointer) 52595552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 52605552b385SBrandon 52615552b385SBrandon if (islite) { 52625552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 52635552b385SBrandon } else { 52645552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 52655552b385SBrandon } 52665552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 52675552b385SBrandon } 52685552b385SBrandon 52695552b385SBrandon /*@C 5270bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyShells - Returns an array of `PetscGeom` SHELL objects attached to the referenced BODY geometric entity as well as the number of SHELLs. 52715552b385SBrandon 52725552b385SBrandon Collective 52735552b385SBrandon 52745552b385SBrandon Input Parameters: 52755552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 52765552b385SBrandon - body - PetscGeom BODY object containing the SHELL objects of interest. 52775552b385SBrandon 52785552b385SBrandon Output Parameters: 52795552b385SBrandon + shells - Array of PetscGeom SHELL objects referenced by the PetscGeom BODY object 52805552b385SBrandon - numShells - Number of SHELLs referenced by the PetscGeom BODY object. Also the size of **shells array. 52815552b385SBrandon 52825552b385SBrandon Level: intermediate 52835552b385SBrandon 52845552b385SBrandon .seealso: 52855552b385SBrandon @*/ 5286ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyShells(DM dm, PetscGeom body, PetscGeom **shells, PetscInt *numShells) PeNS 52875552b385SBrandon { 52885552b385SBrandon PetscFunctionBeginHot; 52895552b385SBrandon #ifdef PETSC_HAVE_EGADS 52905552b385SBrandon PetscContainer modelObj; 52915552b385SBrandon PetscBool islite = PETSC_FALSE; 52925552b385SBrandon 52935552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 52945552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 52955552b385SBrandon if (!modelObj) { 52965552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 52975552b385SBrandon islite = PETSC_TRUE; 52985552b385SBrandon } 52995552b385SBrandon 53005552b385SBrandon if (islite) { 53015552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, numShells, shells)); 53025552b385SBrandon } else { 53035552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, SHELL, numShells, shells)); 53045552b385SBrandon } 53055552b385SBrandon #endif 53065552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 53075552b385SBrandon } 53085552b385SBrandon 53095552b385SBrandon /*@C 5310bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyFaces - Returns an array of `PetscGeom` FACE objects attached to the referenced BODY geometric entity as well as the number of FACEs. 53115552b385SBrandon 53125552b385SBrandon Collective 53135552b385SBrandon 53145552b385SBrandon Input Parameters: 53155552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 53165552b385SBrandon - body - PetscGeom BODY object containing the FACE objects of interest. 53175552b385SBrandon 53185552b385SBrandon Output Parameters: 53195552b385SBrandon + faces - Array of PetscGeom FACE objects referenced by the PetscGeom BODY object 53205552b385SBrandon - numFaces - Number of FACEs referenced by the PetscGeom BODY object. Also the size of **faces array. 53215552b385SBrandon 53225552b385SBrandon Level: intermediate 53235552b385SBrandon 53245552b385SBrandon .seealso: 53255552b385SBrandon @*/ 5326ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyFaces(DM dm, PetscGeom body, PetscGeom **faces, PetscInt *numFaces) PeNS 53275552b385SBrandon { 53285552b385SBrandon PetscFunctionBeginHot; 53295552b385SBrandon #ifdef PETSC_HAVE_EGADS 53305552b385SBrandon PetscContainer modelObj; 53315552b385SBrandon PetscBool islite = PETSC_FALSE; 53325552b385SBrandon 53335552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 53345552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 53355552b385SBrandon if (!modelObj) { 53365552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 53375552b385SBrandon islite = PETSC_TRUE; 53385552b385SBrandon } 53395552b385SBrandon 53405552b385SBrandon if (islite) { 53415552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, numFaces, faces)); 53425552b385SBrandon } else { 53435552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, numFaces, faces)); 53445552b385SBrandon } 53455552b385SBrandon #endif 53465552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 53475552b385SBrandon } 53485552b385SBrandon 53495552b385SBrandon /*@C 5350bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyLoops - Returns an array of `PetscGeom` Loop objects attached to the referenced BODY geometric entity as well as the number of LOOPs. 53515552b385SBrandon 53525552b385SBrandon Collective 53535552b385SBrandon 53545552b385SBrandon Input Parameters: 53555552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 53565552b385SBrandon - body - PetscGeom BODY object containing the LOOP objects of interest. 53575552b385SBrandon 53585552b385SBrandon Output Parameters: 53595552b385SBrandon + loops - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 53605552b385SBrandon - numLoops - Number of LOOPs referenced by the PetscGeom BODY object. Also the size of **loops array. 53615552b385SBrandon 53625552b385SBrandon Level: intermediate 53635552b385SBrandon 53645552b385SBrandon .seealso: 53655552b385SBrandon @*/ 5366ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyLoops(DM dm, PetscGeom body, PetscGeom **loops, PetscInt *numLoops) PeNS 53675552b385SBrandon { 53685552b385SBrandon PetscFunctionBeginHot; 53695552b385SBrandon #ifdef PETSC_HAVE_EGADS 53705552b385SBrandon PetscContainer modelObj; 53715552b385SBrandon PetscBool islite = PETSC_FALSE; 53725552b385SBrandon 53735552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 53745552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 53755552b385SBrandon if (!modelObj) { 53765552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 53775552b385SBrandon islite = PETSC_TRUE; 53785552b385SBrandon } 53795552b385SBrandon 53805552b385SBrandon if (islite) { 53815552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 53825552b385SBrandon } else { 53835552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 53845552b385SBrandon } 53855552b385SBrandon #endif 53865552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 53875552b385SBrandon } 53885552b385SBrandon 53895552b385SBrandon /*@C 5390bfe80ac4SPierre Jolivet DMPlexGetGeomModelShellFaces - Returns an array of `PetscGeom` FACE objects attached to the referenced SHELL geometric entity as well as the number of FACEs. 53915552b385SBrandon 53925552b385SBrandon Collective 53935552b385SBrandon 53945552b385SBrandon Input Parameters: 53955552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 53965552b385SBrandon . body - PetscGeom BODY object containing the FACE objects of interest. 53975552b385SBrandon - shell - PetscGeom SHELL object with FACEs of interest. 53985552b385SBrandon 53995552b385SBrandon Output Parameters: 54005552b385SBrandon + faces - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 54015552b385SBrandon - numFaces - Number of FACEs referenced by the PetscGeom SHELL object. Also the size of **faces array. 54025552b385SBrandon 54035552b385SBrandon Level: intermediate 54045552b385SBrandon 54055552b385SBrandon .seealso: 54065552b385SBrandon @*/ 5407ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelShellFaces(DM dm, PetscGeom body, PetscGeom shell, PetscGeom **faces, PetscInt *numFaces) PeNS 54085552b385SBrandon { 54095552b385SBrandon PetscFunctionBeginHot; 54105552b385SBrandon #ifdef PETSC_HAVE_EGADS 54115552b385SBrandon PetscContainer modelObj; 54125552b385SBrandon PetscBool islite = PETSC_FALSE; 54135552b385SBrandon 54145552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 54155552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 54165552b385SBrandon if (!modelObj) { 54175552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 54185552b385SBrandon islite = PETSC_TRUE; 54195552b385SBrandon } 54205552b385SBrandon 54215552b385SBrandon if (islite) { 54225552b385SBrandon PetscCall(EGlite_getBodyTopos(body, shell, FACE, numFaces, faces)); 54235552b385SBrandon } else { 54245552b385SBrandon PetscCall(EG_getBodyTopos(body, shell, FACE, numFaces, faces)); 54255552b385SBrandon } 54265552b385SBrandon #endif 54275552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 54285552b385SBrandon } 54295552b385SBrandon 54305552b385SBrandon /*@C 5431bfe80ac4SPierre Jolivet DMPlexGetGeomModelFaceLoops - Returns an array of `PetscGeom` LOOP objects attached to the referenced FACE geometric entity as well as the number of LOOPs. 54325552b385SBrandon 54335552b385SBrandon Collective 54345552b385SBrandon 54355552b385SBrandon Input Parameters: 54365552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 54375552b385SBrandon . body - PetscGeom BODY object containing the LOOP objects of interest. 54385552b385SBrandon - face - PetscGeom FACE object with LOOPs of interest. 54395552b385SBrandon 54405552b385SBrandon Output Parameters: 54415552b385SBrandon + loops - Array of PetscGeom LOOP objects referenced by the PetscGeom FACE object 54425552b385SBrandon - numLoops - Number of LOOPs referenced by the PetscGeom FACE object. Also the size of **loops array. 54435552b385SBrandon 54445552b385SBrandon Level: intermediate 54455552b385SBrandon 54465552b385SBrandon .seealso: 54475552b385SBrandon @*/ 5448ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelFaceLoops(DM dm, PetscGeom body, PetscGeom face, PetscGeom **loops, PetscInt *numLoops) PeNS 54495552b385SBrandon { 54505552b385SBrandon PetscFunctionBeginHot; 54515552b385SBrandon #ifdef PETSC_HAVE_EGADS 54525552b385SBrandon PetscContainer modelObj; 54535552b385SBrandon PetscBool islite = PETSC_FALSE; 54545552b385SBrandon 54555552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 54565552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 54575552b385SBrandon if (!modelObj) { 54585552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 54595552b385SBrandon islite = PETSC_TRUE; 54605552b385SBrandon } 54615552b385SBrandon 54625552b385SBrandon if (islite) { 54635552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, LOOP, numLoops, loops)); 54645552b385SBrandon } else { 54655552b385SBrandon PetscCall(EG_getBodyTopos(body, face, LOOP, numLoops, loops)); 54665552b385SBrandon } 54675552b385SBrandon #endif 54685552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 54695552b385SBrandon } 54705552b385SBrandon 54715552b385SBrandon /*@C 5472bfe80ac4SPierre Jolivet DMPlexGetGeomModelFaceEdges - Returns an array of `PetscGeom` EDGE objects attached to the referenced FACE geometric entity as well as the number of EDGEs. 54735552b385SBrandon 54745552b385SBrandon Collective 54755552b385SBrandon 54765552b385SBrandon Input Parameters: 54775552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 54785552b385SBrandon . body - PetscGeom Body object containing the EDGE objects of interest. 54795552b385SBrandon - face - PetscGeom FACE object with EDGEs of interest. 54805552b385SBrandon 54815552b385SBrandon Output Parameters: 54825552b385SBrandon + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom FACE object 54835552b385SBrandon - numEdges - Number of EDGEs referenced by the PetscGeom FACE object. Also the size of **edges array. 54845552b385SBrandon 54855552b385SBrandon Level: intermediate 54865552b385SBrandon 54875552b385SBrandon .seealso: 54885552b385SBrandon @*/ 5489ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelFaceEdges(DM dm, PetscGeom body, PetscGeom face, PetscGeom **edges, PetscInt *numEdges) PeNS 54905552b385SBrandon { 54915552b385SBrandon PetscFunctionBeginHot; 54925552b385SBrandon #ifdef PETSC_HAVE_EGADS 54935552b385SBrandon PetscContainer modelObj; 54945552b385SBrandon PetscBool islite = PETSC_FALSE; 54955552b385SBrandon 54965552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 54975552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 54985552b385SBrandon if (!modelObj) { 54995552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 55005552b385SBrandon islite = PETSC_TRUE; 55015552b385SBrandon } 55025552b385SBrandon 55035552b385SBrandon if (islite) { 55045552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, numEdges, edges)); 55055552b385SBrandon } else { 55065552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, numEdges, edges)); 55075552b385SBrandon } 55085552b385SBrandon #endif 55095552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 55105552b385SBrandon } 55115552b385SBrandon 55125552b385SBrandon /*@C 5513bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyEdges - Returns an array of `PetscGeom` EDGE objects attached to the referenced BODY geometric entity as well as the number of EDGEs. 55145552b385SBrandon 55155552b385SBrandon Collective 55165552b385SBrandon 55175552b385SBrandon Input Parameters: 55185552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 55195552b385SBrandon - body - PetscGeom body object of interest. 55205552b385SBrandon 55215552b385SBrandon Output Parameters: 55225552b385SBrandon + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom BODY object 55235552b385SBrandon - numEdges - Number of EDGEs referenced by the PetscGeom BODY object. Also the size of **edges array. 55245552b385SBrandon 55255552b385SBrandon Level: intermediate 55265552b385SBrandon 55275552b385SBrandon .seealso: 55285552b385SBrandon @*/ 5529ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyEdges(DM dm, PetscGeom body, PetscGeom **edges, PetscInt *numEdges) PeNS 55305552b385SBrandon { 55315552b385SBrandon PetscFunctionBeginHot; 55325552b385SBrandon #ifdef PETSC_HAVE_EGADS 55335552b385SBrandon PetscContainer modelObj; 55345552b385SBrandon PetscBool islite = PETSC_FALSE; 55355552b385SBrandon 55365552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 55375552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 55385552b385SBrandon if (!modelObj) { 55395552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 55405552b385SBrandon islite = PETSC_TRUE; 55415552b385SBrandon } 55425552b385SBrandon 55435552b385SBrandon if (islite) { 55445552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 55455552b385SBrandon } else { 55465552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 55475552b385SBrandon } 55485552b385SBrandon #endif 55495552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 55505552b385SBrandon } 55515552b385SBrandon 55525552b385SBrandon /*@C 5553bfe80ac4SPierre Jolivet DMPlexGetGeomModelBodyNodes - Returns an array of `PetscGeom` NODE objects attached to the referenced BODY geometric entity as well as the number of NODES. 55545552b385SBrandon 55555552b385SBrandon Collective 55565552b385SBrandon 55575552b385SBrandon Input Parameters: 55585552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 55595552b385SBrandon - body - PetscGeom body object of interest. 55605552b385SBrandon 55615552b385SBrandon Output Parameters: 55625552b385SBrandon + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom BODY object 55635552b385SBrandon - numNodes - Number of NODEs referenced by the PetscGeom BODY object. Also the size of **nodes array. 55645552b385SBrandon 55655552b385SBrandon Level: intermediate 55665552b385SBrandon 55675552b385SBrandon .seealso: 55685552b385SBrandon @*/ 5569ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelBodyNodes(DM dm, PetscGeom body, PetscGeom **nodes, PetscInt *numNodes) PeNS 55705552b385SBrandon { 55715552b385SBrandon PetscFunctionBeginHot; 55725552b385SBrandon #ifdef PETSC_HAVE_EGADS 55735552b385SBrandon PetscContainer modelObj; 55745552b385SBrandon PetscBool islite = PETSC_FALSE; 55755552b385SBrandon 55765552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 55775552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 55785552b385SBrandon if (!modelObj) { 55795552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 55805552b385SBrandon islite = PETSC_TRUE; 55815552b385SBrandon } 55825552b385SBrandon 55835552b385SBrandon if (islite) { 55845552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 55855552b385SBrandon } else { 55865552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 55875552b385SBrandon } 55885552b385SBrandon #endif 55895552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 55905552b385SBrandon } 55915552b385SBrandon 55925552b385SBrandon /*@C 5593bfe80ac4SPierre Jolivet DMPlexGetGeomModelEdgeNodes - Returns an array of `PetscGeom` NODE objects attached to the referenced EDGE geometric entity as well as the number of NODES. 55945552b385SBrandon 55955552b385SBrandon Collective 55965552b385SBrandon 55975552b385SBrandon Input Parameters: 55985552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 55995552b385SBrandon . body - PetscGeom body object containing the EDGE object of interest. 56005552b385SBrandon - edge - PetscGeom EDGE object with NODEs of interest. 56015552b385SBrandon 56025552b385SBrandon Output Parameters: 56035552b385SBrandon + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom EDGE object 56045552b385SBrandon - numNodes - Number of Nodes referenced by the PetscGeom EDGE object. Also the size of **nodes array. 56055552b385SBrandon 56065552b385SBrandon Level: intermediate 56075552b385SBrandon 56085552b385SBrandon .seealso: 56095552b385SBrandon @*/ 5610ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomModelEdgeNodes(DM dm, PetscGeom body, PetscGeom edge, PetscGeom **nodes, PetscInt *numNodes) PeNS 56115552b385SBrandon { 56125552b385SBrandon PetscFunctionBeginHot; 56135552b385SBrandon #ifdef PETSC_HAVE_EGADS 56145552b385SBrandon PetscContainer modelObj; 56155552b385SBrandon PetscBool islite = PETSC_FALSE; 56165552b385SBrandon 56175552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 56185552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 56195552b385SBrandon if (!modelObj) { 56205552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 56215552b385SBrandon islite = PETSC_TRUE; 56225552b385SBrandon } 56235552b385SBrandon 56245552b385SBrandon if (islite) { 56255552b385SBrandon PetscCall(EGlite_getBodyTopos(body, edge, NODE, numNodes, nodes)); 56265552b385SBrandon } else { 56275552b385SBrandon PetscCall(EG_getBodyTopos(body, edge, NODE, numNodes, nodes)); 56285552b385SBrandon } 56295552b385SBrandon #endif 56305552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 56315552b385SBrandon } 56325552b385SBrandon 56335552b385SBrandon /*@C 56345552b385SBrandon DMPlexGetGeomID - Returns ID number of the entity in the geometric (CAD) model 56355552b385SBrandon 56365552b385SBrandon Collective 56375552b385SBrandon 56385552b385SBrandon Input Parameters: 56395552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 56405552b385SBrandon . body - PetscGeom body object containing the lower level entity the ID number is being requested. 56415552b385SBrandon - topoObj - PetscGeom SHELL, FACE, LOOP, EDGE, or NODE object for which ID number is being requested. 56427bee2925SMatthew Knepley 56437bee2925SMatthew Knepley Output Parameter: 56445552b385SBrandon . id - ID number of the entity 56457bee2925SMatthew Knepley 56465552b385SBrandon Level: intermediate 56477bee2925SMatthew Knepley 56485552b385SBrandon .seealso: 56497bee2925SMatthew Knepley @*/ 5650ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomID(DM dm, PetscGeom body, PetscGeom topoObj, PetscInt *id) PeNS 5651d71ae5a4SJacob Faibussowitsch { 56525552b385SBrandon PetscFunctionBeginHot; 56535552b385SBrandon #ifdef PETSC_HAVE_EGADS 56545552b385SBrandon PetscContainer modelObj; 56555552b385SBrandon PetscBool islite = PETSC_FALSE; 56565552b385SBrandon int topoID; 56575552b385SBrandon 56585552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 56595552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 56605552b385SBrandon if (!modelObj) { 56615552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 56625552b385SBrandon islite = PETSC_TRUE; 56635552b385SBrandon } 56645552b385SBrandon 56655552b385SBrandon // Get Topology Object's ID 56665552b385SBrandon if (islite) { 56675552b385SBrandon topoID = EGlite_indexBodyTopo(body, topoObj); 56685552b385SBrandon } else { 56695552b385SBrandon topoID = EG_indexBodyTopo(body, topoObj); 56705552b385SBrandon } 56715552b385SBrandon 56725552b385SBrandon *id = topoID; 56737bee2925SMatthew Knepley #endif 56745552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 56755552b385SBrandon } 56765552b385SBrandon 56775552b385SBrandon /*@C 56785552b385SBrandon DMPlexGetGeomObject - Returns Geometry Object using the objects ID in the geometric (CAD) model 56795552b385SBrandon 56805552b385SBrandon Collective 56815552b385SBrandon 56825552b385SBrandon Input Parameters: 56835552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 56845552b385SBrandon . body - PetscGeom body object containing the lower level entity the referenced by the ID. 56855552b385SBrandon . geomType - Keyword SHELL, FACE, LOOP, EDGE, or NODE of the geometry type for which ID number is being requested. 56865552b385SBrandon - geomID - ID number of the geometry entity being requested. 56875552b385SBrandon 56885552b385SBrandon Output Parameter: 56895552b385SBrandon . geomObj - Geometry Object referenced by the ID number requested. 56905552b385SBrandon 56915552b385SBrandon Level: intermediate 56925552b385SBrandon 56935552b385SBrandon .seealso: 56945552b385SBrandon @*/ 5695ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomObject(DM dm, PetscGeom body, PetscInt geomType, PetscInt geomID, PetscGeom *geomObj) PeNS 56965552b385SBrandon { 56975552b385SBrandon PetscFunctionBeginHot; 56985552b385SBrandon #ifdef PETSC_HAVE_EGADS 56995552b385SBrandon PetscContainer modelObj; 57005552b385SBrandon PetscBool islite = PETSC_FALSE; 57015552b385SBrandon 57025552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 57035552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 57045552b385SBrandon if (!modelObj) { 57055552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 57065552b385SBrandon islite = PETSC_TRUE; 57075552b385SBrandon } 57085552b385SBrandon 57095552b385SBrandon // Get Topology Object's ID 57105552b385SBrandon if (islite) { 57115552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, geomType, geomID, geomObj)); 57125552b385SBrandon } else { 57135552b385SBrandon PetscCall(EG_objectBodyTopo(body, geomType, geomID, geomObj)); 57145552b385SBrandon } 57155552b385SBrandon #endif 57165552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 57175552b385SBrandon } 57185552b385SBrandon 57195552b385SBrandon /*@C 57205552b385SBrandon DMPlexGetGeomFaceNumOfControlPoints - Returns the total number of Control Points (and associated Weights) defining a FACE of a Geometry 57215552b385SBrandon 57225552b385SBrandon Not collective 57235552b385SBrandon 57245552b385SBrandon Input Parameters: 57255552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 57265552b385SBrandon - face - PetscGeom FACE object 57275552b385SBrandon 57285552b385SBrandon Output Parameter: 57295552b385SBrandon . numCntrlPnts - Number of Control Points (and Weights) defining the FACE 57305552b385SBrandon 57315552b385SBrandon Level: intermediate 57325552b385SBrandon 57335552b385SBrandon .seealso: 57345552b385SBrandon @*/ 5735ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomFaceNumOfControlPoints(DM dm, PetscGeom face, PetscInt *numCntrlPnts) PeNS 57365552b385SBrandon { 57375552b385SBrandon PetscFunctionBeginHot; 57385552b385SBrandon #ifdef PETSC_HAVE_EGADS 57395552b385SBrandon PetscContainer modelObj; 57405552b385SBrandon PetscBool islite = PETSC_FALSE; 57415552b385SBrandon PetscGeom geom, gRef; 57425552b385SBrandon PetscGeom *lobjs; 57435552b385SBrandon int Nl, oclass, mtype, goclass, gmtype; 57445552b385SBrandon int *lsenses, *gpinfo; 57455552b385SBrandon double *gprv; 57465552b385SBrandon 57475552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 57485552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 57495552b385SBrandon if (!modelObj) { 57505552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 57515552b385SBrandon islite = PETSC_TRUE; 57525552b385SBrandon } 57535552b385SBrandon 57545552b385SBrandon // Get Total Number of Control Points on FACE 57555552b385SBrandon if (islite) { 57565552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 57575552b385SBrandon PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 57585552b385SBrandon } else { 57595552b385SBrandon PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 57605552b385SBrandon PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 57615552b385SBrandon } 57625552b385SBrandon 57635552b385SBrandon *numCntrlPnts = gpinfo[2] * gpinfo[5]; 57645552b385SBrandon #endif 57655552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 57665552b385SBrandon } 57675552b385SBrandon 57685552b385SBrandon /*@C 57695552b385SBrandon DMPlexGetGeomBodyMassProperties - Returns the Volume, Surface Area, Center of Gravity, and Inertia about the Body's Center of Gravity 57705552b385SBrandon 57715552b385SBrandon Not collective 57725552b385SBrandon 57735552b385SBrandon Input Parameters: 57745552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 57755552b385SBrandon - body - PetscGeom BODY object 57765552b385SBrandon 57775552b385SBrandon Output Parameters: 57785552b385SBrandon + volume - Volume of the CAD Body attached to the DM Plex 57795552b385SBrandon . surfArea - Surface Area of the CAD Body attached to the DM Plex 57805552b385SBrandon . centerOfGravity - Array with the Center of Gravity coordinates of the CAD Body attached to the DM Plex [x, y, z] 57815552b385SBrandon . COGszie - Size of centerOfGravity[] Array 57825552b385SBrandon . inertiaMatrixCOG - Array containing the Inertia about the Body's Center of Gravity [Ixx, Ixy, Ixz, Iyx, Iyy, Iyz, Izx, Izy, Izz] 57835552b385SBrandon - IMCOGsize - Size of inertiaMatrixCOG[] Array 57845552b385SBrandon 57855552b385SBrandon Level: intermediate 57865552b385SBrandon 57875552b385SBrandon .seealso: 57885552b385SBrandon @*/ 5789ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) PeNS 57905552b385SBrandon { 57915552b385SBrandon PetscFunctionBeginHot; 57925552b385SBrandon #ifdef PETSC_HAVE_EGADS 57935552b385SBrandon PetscContainer modelObj; 57945552b385SBrandon PetscBool islite = PETSC_FALSE; 57955552b385SBrandon PetscScalar geomData[14]; 57965552b385SBrandon 57975552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 57985552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 57995552b385SBrandon if (!modelObj) { 58005552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 58015552b385SBrandon islite = PETSC_TRUE; 58025552b385SBrandon 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"); 58035552b385SBrandon } 58045552b385SBrandon 58055552b385SBrandon if (islite) { 58065552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " WARNING!! This functionality is not supported for EGADSlite files. \n")); 58075552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " All returned values are equal to 0 \n")); 58085552b385SBrandon } else { 58095552b385SBrandon PetscCall(EG_getMassProperties(body, geomData)); 58105552b385SBrandon } 58115552b385SBrandon 58125552b385SBrandon PetscCall(PetscMalloc2(3, centerOfGravity, 9, inertiaMatrixCOG)); 58135552b385SBrandon 58145552b385SBrandon if (!islite) { 58155552b385SBrandon *volume = geomData[0]; 58165552b385SBrandon *surfArea = geomData[1]; 58175552b385SBrandon for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = geomData[ii]; } 58185552b385SBrandon *COGsize = 3; 58195552b385SBrandon for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = geomData[ii]; } 58205552b385SBrandon *IMCOGsize = 9; 58215552b385SBrandon } else { 58225552b385SBrandon *volume = 0.; 58235552b385SBrandon *surfArea = 0.; 58245552b385SBrandon for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = 0.; } 58255552b385SBrandon *COGsize = 0; 58265552b385SBrandon for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = 0.; } 58275552b385SBrandon *IMCOGsize = 0; 58285552b385SBrandon } 58295552b385SBrandon #endif 58305552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 58315552b385SBrandon } 58325552b385SBrandon 5833ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) PeNS 58345552b385SBrandon { 58355552b385SBrandon PetscFunctionBegin; 58365552b385SBrandon PetscCall(PetscFree2(*centerOfGravity, *inertiaMatrixCOG)); 58375552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 58385552b385SBrandon } 58395552b385SBrandon 58405552b385SBrandon /*@C 58415552b385SBrandon DMPlexFreeGeomObject - Frees PetscGeom Objects 58425552b385SBrandon 58435552b385SBrandon Not collective 58445552b385SBrandon 58455552b385SBrandon Input Parameters: 58465552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 58475552b385SBrandon - geomObj - PetscGeom object 58485552b385SBrandon 58495552b385SBrandon Level: intermediate 58505552b385SBrandon 58515552b385SBrandon .seealso: 58525552b385SBrandon @*/ 5853ce78bad3SBarry Smith PetscErrorCode DMPlexFreeGeomObject(DM dm, PetscGeom *geomObj) PeNS 58545552b385SBrandon { 58555552b385SBrandon PetscFunctionBeginHot; 58565552b385SBrandon #ifdef PETSC_HAVE_EGADS 58575552b385SBrandon PetscContainer modelObj; 58585552b385SBrandon PetscBool islite = PETSC_FALSE; 58595552b385SBrandon 58605552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 58615552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 58625552b385SBrandon if (!modelObj) { 58635552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 58645552b385SBrandon islite = PETSC_TRUE; 58655552b385SBrandon } 58665552b385SBrandon 58675552b385SBrandon if (islite) { 58685552b385SBrandon EGlite_free(geomObj); 58695552b385SBrandon } else { 58705552b385SBrandon EG_free(geomObj); 58715552b385SBrandon } 58725552b385SBrandon #endif 58735552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 58745552b385SBrandon } 58755552b385SBrandon 58765552b385SBrandon /*@C 58775552b385SBrandon DMPlexGetGeomCntrlPntAndWeightData - Gets Control Point and Associated Weight Data for the Geometry attached to the DMPlex 58785552b385SBrandon 58795552b385SBrandon Not collective 58805552b385SBrandon 58815552b385SBrandon Input Parameter: 58825552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 58835552b385SBrandon 58845552b385SBrandon Output Parameters: 58855552b385SBrandon + cpHashTable - Hash Table containing the relationship between FACE ID and Control Point IDs. 58865552b385SBrandon . cpCoordDataLength - Length of cpCoordData Array. 58875552b385SBrandon . cpCoordData - Array holding the Geometry Control Point Coordinate Data. 58885552b385SBrandon . maxNumEquiv - Maximum Number of Equivalent Control Points (Control Points with the same coordinates but different IDs). 58895552b385SBrandon . 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 58905552b385SBrandon . wHashTable - Hash Table containing the relationship between FACE ID and Control Point Weight. 58915552b385SBrandon . wDataLength - Length of wData Array. 58925552b385SBrandon - wData - Array holding the Weight for an associated Geometry Control Point. 58935552b385SBrandon 58945552b385SBrandon Note: 58955552b385SBrandon Must Call DMPLexGeomDataAndGrads() before calling this function. 58965552b385SBrandon 58975552b385SBrandon Level: intermediate 58985552b385SBrandon 58995552b385SBrandon .seealso: 59005552b385SBrandon @*/ 5901ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) PeNS 59025552b385SBrandon { 59035552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj, cpCoordDataLengthObj, wDataLengthObj, maxNumRelateObj; 59045552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 59055552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr, *maxNumEquivPtr; 59065552b385SBrandon PetscHMapI cpHashTableTemp, wHashTableTemp; 59075552b385SBrandon 59085552b385SBrandon PetscFunctionBeginHot; 59095552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 59105552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 59113a7d0413SPierre Jolivet if (!modelObj) PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 59125552b385SBrandon 59135552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 59145552b385SBrandon 59155552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 59165552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 59175552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 59185552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordDataLengthObj)); 59195552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 59205552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 59215552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 5922bfe80ac4SPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Equivalency Matrix", (PetscObject *)cpEquiv)); 59235552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 59245552b385SBrandon 59255552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 59265552b385SBrandon PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTableTemp)); 59275552b385SBrandon PetscCall(PetscContainerGetPointer(cpCoordDataLengthObj, (void **)&cpCoordDataLengthPtr)); 59285552b385SBrandon PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTableTemp)); 59295552b385SBrandon PetscCall(PetscContainerGetPointer(wDataLengthObj, (void **)&wDataLengthPtr)); 59305552b385SBrandon PetscCall(PetscContainerGetPointer(maxNumRelateObj, (void **)&maxNumEquivPtr)); 59315552b385SBrandon 59325552b385SBrandon *cpCoordDataLength = *cpCoordDataLengthPtr; 59335552b385SBrandon *wDataLength = *wDataLengthPtr; 59345552b385SBrandon *maxNumEquiv = *maxNumEquivPtr; 59355552b385SBrandon *cpHashTable = cpHashTableTemp; 59365552b385SBrandon *wHashTable = wHashTableTemp; 59375552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, cpCoordData)); 59385552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, wData)); 59395552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 59405552b385SBrandon } 59415552b385SBrandon 59425552b385SBrandon PetscErrorCode DMPlexRestoreGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) 59435552b385SBrandon { 59445552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 59455552b385SBrandon 59465552b385SBrandon PetscFunctionBeginHot; 59475552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 59485552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, cpCoordData)); 59495552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 59505552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, wData)); 59515552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 59525552b385SBrandon } 59535552b385SBrandon 59545552b385SBrandon /*@C 59555552b385SBrandon 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 . 59565552b385SBrandon 59575552b385SBrandon Not collective 59585552b385SBrandon 59595552b385SBrandon Input Parameter: 59605552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 59615552b385SBrandon 59625552b385SBrandon Output Parameters: 59635552b385SBrandon + cpSurfGradHashTable - Hash Table Relating the Control Point ID to the the Row in the cpSurfGrad Matrix 59645552b385SBrandon . 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. 59655552b385SBrandon . cpArraySize - The size of arrays gradSACP and gradVolCP and is equal to 3 * total number of Control Points in the Geometry 59665552b385SBrandon . 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. 5967bfe80ac4SPierre 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. 59685552b385SBrandon . wArraySize - The size of arrayws gradSAW and gradVolW and is equal to the total number of Control Points in the Geometry. 59695552b385SBrandon . gradSAW - Array containing the Surface Area Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 59705552b385SBrandon - gradVolW - Array containing the Volume Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 59715552b385SBrandon 59725552b385SBrandon Notes: 59735552b385SBrandon Must Call DMPLexGeomDataAndGrads() before calling this function. 59745552b385SBrandon 59755552b385SBrandon gradVolCP and gradVolW are only available when DMPlexGeomDataAndGrads() is called with fullGeomGrad = PETSC_TRUE. 59765552b385SBrandon 59775552b385SBrandon Level: intermediate 59785552b385SBrandon 59795552b385SBrandon .seealso: DMPlexGeomDataAndGrads 59805552b385SBrandon @*/ 59815552b385SBrandon PetscErrorCode DMPlexGetGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 59825552b385SBrandon { 59835552b385SBrandon PetscContainer modelObj, cpSurfGradHashTableObj, cpArraySizeObj, wArraySizeObj; 59845552b385SBrandon Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 59855552b385SBrandon PetscInt *cpArraySizePtr, *wArraySizePtr; 59865552b385SBrandon PetscHMapI cpSurfGradHashTableTemp; 59875552b385SBrandon 59885552b385SBrandon PetscFunctionBeginHot; 59895552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 59905552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 59913a7d0413SPierre Jolivet if (!modelObj) PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 59925552b385SBrandon 59935552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 59945552b385SBrandon 59955552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 59965552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&cpSurfGradHashTableObj)); 59975552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Matrix", (PetscObject *)cpSurfGrad)); 59985552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpArraySizeObj)); 59995552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 60005552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 60015552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wArraySizeObj)); 60025552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 60035552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 60045552b385SBrandon 60055552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 60065552b385SBrandon if (cpSurfGradHashTableObj) { 60075552b385SBrandon PetscCall(PetscContainerGetPointer(cpSurfGradHashTableObj, (void **)&cpSurfGradHashTableTemp)); 60085552b385SBrandon *cpSurfGradHashTable = cpSurfGradHashTableTemp; 60095552b385SBrandon } 60105552b385SBrandon 60115552b385SBrandon if (cpArraySizeObj) { 60125552b385SBrandon PetscCall(PetscContainerGetPointer(cpArraySizeObj, (void **)&cpArraySizePtr)); 60135552b385SBrandon *cpArraySize = *cpArraySizePtr; 60145552b385SBrandon } 60155552b385SBrandon 60165552b385SBrandon if (gradSACPVec) PetscCall(VecGetArrayWrite(gradSACPVec, gradSACP)); 60175552b385SBrandon if (gradVolCPVec) PetscCall(VecGetArrayWrite(gradVolCPVec, gradVolCP)); 60185552b385SBrandon if (gradSAWVec) PetscCall(VecGetArrayWrite(gradSAWVec, gradSAW)); 60195552b385SBrandon if (gradVolWVec) PetscCall(VecGetArrayWrite(gradVolWVec, gradVolW)); 60205552b385SBrandon 60215552b385SBrandon if (wArraySizeObj) { 60225552b385SBrandon PetscCall(PetscContainerGetPointer(wArraySizeObj, (void **)&wArraySizePtr)); 60235552b385SBrandon *wArraySize = *wArraySizePtr; 60245552b385SBrandon } 60255552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 60265552b385SBrandon } 60275552b385SBrandon 60285552b385SBrandon PetscErrorCode DMPlexRestoreGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 60295552b385SBrandon { 60305552b385SBrandon Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 60317bee2925SMatthew Knepley 60327bee2925SMatthew Knepley PetscFunctionBegin; 60335552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 60345552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 60355552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 60365552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 60375552b385SBrandon 60385552b385SBrandon if (gradSACPVec) PetscCall(VecRestoreArrayWrite(gradSACPVec, gradSACP)); 60395552b385SBrandon if (gradVolCPVec) PetscCall(VecRestoreArrayWrite(gradVolCPVec, gradVolCP)); 60405552b385SBrandon if (gradSAWVec) PetscCall(VecRestoreArrayWrite(gradSAWVec, gradSAW)); 60415552b385SBrandon if (gradVolWVec) PetscCall(VecRestoreArrayWrite(gradVolWVec, gradVolW)); 60423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60437bee2925SMatthew Knepley } 60445552b385SBrandon 60455552b385SBrandon /*@C 60465552b385SBrandon DMPlexGetGeomCntrlPntMaps - Gets arrays which maps Control Point IDs to their associated Geometry FACE, EDGE, and VERTEX. 60475552b385SBrandon 60485552b385SBrandon Not collective 60495552b385SBrandon 60505552b385SBrandon Input Parameter: 60515552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 60525552b385SBrandon 60535552b385SBrandon Output Parameters: 60545552b385SBrandon + numCntrlPnts - Number of Control Points defining the Geometry attached to the DMPlex 60555552b385SBrandon . cntrlPntFaceMap - Array containing the FACE ID for the Control Point. Array index corresponds to Control Point ID. 60565552b385SBrandon . cntrlPntWeightFaceMap - Array containing the FACE ID for the Control Point Weight. Array index corresponds to Control Point ID. 60575552b385SBrandon . cntrlPntEdgeMap - Array containing the EDGE ID for the Control Point. Array index corresponds to Control Point ID. 60585552b385SBrandon . cntrlPntWeightEdgeMap - Array containing the EDGE ID for the Control Point Weight. Array index corresponds to Control Point ID. 60595552b385SBrandon . cntrlPntVertexMap - Array containing the VERTEX ID for the Control Point. Array index corresponds to Control Point ID. 60605552b385SBrandon - cntrlPntWeightVertexMap - Array containing the VERTEX ID for the Control Point Weight. Array index corresponds to Control Point ID. 60615552b385SBrandon 60625552b385SBrandon Note: 60635552b385SBrandon 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. 60645552b385SBrandon 60655552b385SBrandon Level: intermediate 60665552b385SBrandon 60675552b385SBrandon .seealso: DMPlexGeomDataAndGrads 60685552b385SBrandon @*/ 60695552b385SBrandon PetscErrorCode DMPlexGetGeomCntrlPntMaps(DM dm, PetscInt *numCntrlPnts, PetscInt **cntrlPntFaceMap, PetscInt **cntrlPntWeightFaceMap, PetscInt **cntrlPntEdgeMap, PetscInt **cntrlPntWeightEdgeMap, PetscInt **cntrlPntVertexMap, PetscInt **cntrlPntWeightVertexMap) 60705552b385SBrandon { 60715552b385SBrandon PetscFunctionBeginHot; 60725552b385SBrandon #ifdef PETSC_HAVE_EGADS 60735552b385SBrandon PetscContainer modelObj, numCntrlPntsObj, cntrlPntFaceMapObj, cntrlPntWeightFaceMapObj, cntrlPntEdgeMapObj, cntrlPntWeightEdgeMapObj, cntrlPntVertexMapObj, cntrlPntWeightVertexMapObj; 60745552b385SBrandon PetscInt *numCntrlPntsPtr, *cntrlPntFaceMapPtr, *cntrlPntWeightFaceMapPtr, *cntrlPntEdgeMapPtr, *cntrlPntWeightEdgeMapPtr, *cntrlPntVertexMapPtr, *cntrlPntWeightVertexMapPtr; 60755552b385SBrandon 60765552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 60775552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 60783a7d0413SPierre Jolivet if (!modelObj) PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 60795552b385SBrandon 60805552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 60815552b385SBrandon 60825552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 60835552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&numCntrlPntsObj)); 60845552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cntrlPntFaceMapObj)); 60855552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&cntrlPntWeightFaceMapObj)); 60865552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cntrlPntEdgeMapObj)); 60875552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&cntrlPntWeightEdgeMapObj)); 60885552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cntrlPntVertexMapObj)); 60895552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&cntrlPntWeightVertexMapObj)); 60905552b385SBrandon 60915552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 60925552b385SBrandon if (numCntrlPntsObj) { 60935552b385SBrandon PetscCall(PetscContainerGetPointer(numCntrlPntsObj, (void **)&numCntrlPntsPtr)); 60945552b385SBrandon *numCntrlPnts = *numCntrlPntsPtr; 60955552b385SBrandon } 60965552b385SBrandon 60975552b385SBrandon if (cntrlPntFaceMapObj) { 60985552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntFaceMapObj, (void **)&cntrlPntFaceMapPtr)); 60995552b385SBrandon *cntrlPntFaceMap = cntrlPntFaceMapPtr; 61005552b385SBrandon } 61015552b385SBrandon 61025552b385SBrandon if (cntrlPntWeightFaceMapObj) { 61035552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightFaceMapObj, (void **)&cntrlPntWeightFaceMapPtr)); 61045552b385SBrandon *cntrlPntWeightFaceMap = cntrlPntWeightFaceMapPtr; 61055552b385SBrandon } 61065552b385SBrandon 61075552b385SBrandon if (cntrlPntEdgeMapObj) { 61085552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntEdgeMapObj, (void **)&cntrlPntEdgeMapPtr)); 61095552b385SBrandon *cntrlPntEdgeMap = cntrlPntEdgeMapPtr; 61105552b385SBrandon } 61115552b385SBrandon 61125552b385SBrandon if (cntrlPntWeightEdgeMapObj) { 61135552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightEdgeMapObj, (void **)&cntrlPntWeightEdgeMapPtr)); 61145552b385SBrandon *cntrlPntWeightEdgeMap = cntrlPntWeightEdgeMapPtr; 61155552b385SBrandon } 61165552b385SBrandon 61175552b385SBrandon if (cntrlPntVertexMapObj) { 61185552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntVertexMapObj, (void **)&cntrlPntVertexMapPtr)); 61195552b385SBrandon *cntrlPntVertexMap = cntrlPntVertexMapPtr; 61205552b385SBrandon } 61215552b385SBrandon 61225552b385SBrandon if (cntrlPntWeightVertexMapObj) { 61235552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightVertexMapObj, (void **)&cntrlPntWeightVertexMapPtr)); 61245552b385SBrandon *cntrlPntWeightVertexMap = cntrlPntWeightVertexMapPtr; 61255552b385SBrandon } 61265552b385SBrandon 61275552b385SBrandon #endif 61285552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 61295552b385SBrandon } 61305552b385SBrandon 61315552b385SBrandon #endif 6132