1*5552b385SBrandon #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 19*5552b385SBrandon #include <petscdmplexegads.h> 20c1cad2e7SMatthew G. Knepley 21*5552b385SBrandon PETSC_INTERN PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM, PetscInt, ego, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscScalar[], PetscBool); 22*5552b385SBrandon PETSC_INTERN PetscErrorCode DMPlex_Geom_EDGE_XYZtoUV_Internal(const PetscScalar[], ego, const PetscScalar[], const PetscInt, const PetscInt, PetscScalar[], PetscBool); 23*5552b385SBrandon PETSC_INTERN PetscErrorCode DMPlex_Geom_FACE_XYZtoUV_Internal(const PetscScalar[], ego, const PetscScalar[], const PetscInt, const PetscInt, PetscScalar[], PetscBool); 24*5552b385SBrandon 25*5552b385SBrandon PetscErrorCode DMPlex_EGADS_GeomDecode_Internal(const PetscInt geomClass, const PetscInt geomType, char **retClass, char **retType) 26d71ae5a4SJacob Faibussowitsch { 27*5552b385SBrandon PetscFunctionBeginHot; 28*5552b385SBrandon /* EGADS Object Type */ 29*5552b385SBrandon if (geomClass == CONTXT) { *retClass = (char *)"CONTEXT"; } 30*5552b385SBrandon if (geomClass == TRANSFORM) { *retClass = (char *)"TRANSFORM"; } 31*5552b385SBrandon if (geomClass == TESSELLATION) { *retClass = (char *)"TESSELLATION"; } 32*5552b385SBrandon if (geomClass == NIL) { *retClass = (char *)"NIL"; } 33*5552b385SBrandon if (geomClass == EMPTY) { *retClass = (char *)"EMPTY"; } 34*5552b385SBrandon if (geomClass == REFERENCE) { *retClass = (char *)"REFERENCE"; } 35*5552b385SBrandon if (geomClass == PCURVE) { *retClass = (char *)"PCURVE"; } 36*5552b385SBrandon if (geomClass == CURVE) { *retClass = (char *)"CURVE"; } 37*5552b385SBrandon if (geomClass == SURFACE) { *retClass = (char *)"SURFACE"; } 38*5552b385SBrandon if (geomClass == NODE) { *retClass = (char *)"NODE"; } 39*5552b385SBrandon if (geomClass == EDGE) { *retClass = (char *)"EDGE"; } 40*5552b385SBrandon if (geomClass == LOOP) { *retClass = (char *)"LOOP"; } 41*5552b385SBrandon if (geomClass == FACE) { *retClass = (char *)"FACE"; } 42*5552b385SBrandon if (geomClass == SHELL) { *retClass = (char *)"SHELL"; } 43*5552b385SBrandon if (geomClass == BODY) { *retClass = (char *)"BODY"; } 44*5552b385SBrandon if (geomClass == MODEL) { *retClass = (char *)"MODEL"; } 45*5552b385SBrandon 46*5552b385SBrandon /* PCURVES & CURVES */ 47*5552b385SBrandon if (geomClass == PCURVE || geomClass == CURVE) { 48*5552b385SBrandon if (geomType == LINE) { *retType = (char *)"LINE"; } 49*5552b385SBrandon if (geomType == CIRCLE) { *retType = (char *)"CIRCLE"; } 50*5552b385SBrandon if (geomType == ELLIPSE) { *retType = (char *)"ELLIPSE"; } 51*5552b385SBrandon if (geomType == PARABOLA) { *retType = (char *)"PARABOLA"; } 52*5552b385SBrandon if (geomType == HYPERBOLA) { *retType = (char *)"HYPERBOLA"; } 53*5552b385SBrandon if (geomType == TRIMMED) { *retType = (char *)"TRIMMED"; } 54*5552b385SBrandon if (geomType == BEZIER) { *retType = (char *)"BEZIER"; } 55*5552b385SBrandon if (geomType == BSPLINE) { *retType = (char *)"BSPLINE"; } 56*5552b385SBrandon if (geomType == OFFSET) { *retType = (char *)"OFFSET"; } 57*5552b385SBrandon } 58*5552b385SBrandon 59*5552b385SBrandon /* SURFACE */ 60*5552b385SBrandon if (geomClass == SURFACE) { 61*5552b385SBrandon if (geomType == PLANE) { *retType = (char *)"PLANE"; } 62*5552b385SBrandon if (geomType == SPHERICAL) { *retType = (char *)"SPHERICAL"; } 63*5552b385SBrandon if (geomType == CYLINDRICAL) { *retType = (char *)"CYLINDRICAL"; } 64*5552b385SBrandon if (geomType == REVOLUTION) { *retType = (char *)"REVOLUTION"; } 65*5552b385SBrandon if (geomType == TOROIDAL) { *retType = (char *)"TOROIDAL"; } 66*5552b385SBrandon if (geomType == CONICAL) { *retType = (char *)"CONICAL"; } 67*5552b385SBrandon if (geomType == EXTRUSION) { *retType = (char *)"EXTRUSION"; } 68*5552b385SBrandon if (geomType == BEZIER) { *retType = (char *)"BEZIER"; } 69*5552b385SBrandon if (geomType == BSPLINE) { *retType = (char *)"BSPLINE"; } 70*5552b385SBrandon } 71*5552b385SBrandon 72*5552b385SBrandon /* TOPOLOGY */ 73*5552b385SBrandon if (geomClass == NODE || geomClass == EDGE || geomClass == LOOP || geomClass == FACE || geomClass == SHELL || geomClass == BODY || geomClass == MODEL) { 74*5552b385SBrandon if (geomType == SREVERSE) { *retType = (char *)"SREVERSE"; } 75*5552b385SBrandon if (geomType == NOMTYPE) { *retType = (char *)"NOMTYPE"; } 76*5552b385SBrandon if (geomType == SFORWARD && geomClass == FACE) { *retType = (char *)"SFORWARD"; } 77*5552b385SBrandon if (geomType == ONENODE && geomClass == EDGE) { *retType = (char *)"ONENODE"; } 78*5552b385SBrandon if (geomType == TWONODE) { *retType = (char *)"TWONODE"; } 79*5552b385SBrandon if (geomType == OPEN) { *retType = (char *)"OPEN"; } 80*5552b385SBrandon if (geomType == CLOSED) { *retType = (char *)"CLOSED"; } 81*5552b385SBrandon if (geomType == DEGENERATE) { *retType = (char *)"DEGENERATE"; } 82*5552b385SBrandon if (geomType == WIREBODY) { *retType = (char *)"WIREBODY"; } 83*5552b385SBrandon if (geomType == FACEBODY) { *retType = (char *)"FACEBODY"; } 84*5552b385SBrandon if (geomType == SHEETBODY) { *retType = (char *)"SHEETBODY"; } 85*5552b385SBrandon if (geomType == SOLIDBODY) { *retType = (char *)"SOLIDBODY"; } 86*5552b385SBrandon } 87*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 88*5552b385SBrandon } 89*5552b385SBrandon 90*5552b385SBrandon PetscErrorCode DMPlex_EGADS_EDGE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[]) 91*5552b385SBrandon { 92*5552b385SBrandon // 93*5552b385SBrandon // 94*5552b385SBrandon // Depreciated. Changed all references to DMPlex_Geom_FACE_XYZtoUV_Internal() 95*5552b385SBrandon // 96*5552b385SBrandon // 97*5552b385SBrandon 98*5552b385SBrandon PetscInt loopCntr = 0; 99*5552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, obj_old, obj_tmp, target; 100*5552b385SBrandon PetscScalar delta, A, b; 101*5552b385SBrandon PetscScalar ts[2], tt[2], eval[18], data[18]; 102*5552b385SBrandon 103*5552b385SBrandon PetscFunctionBeginHot; 104*5552b385SBrandon /* Initialize Levenberg-Marquardt parameters */ 105*5552b385SBrandon lambda = 1.0; 106*5552b385SBrandon tolr = 1.0; 107*5552b385SBrandon target = 1.0E-20; 108*5552b385SBrandon ts[0] = (range[0] + range[1]) / 2.; 109*5552b385SBrandon 110*5552b385SBrandon while (tolr >= target) { 111*5552b385SBrandon PetscCall(EG_evaluate(obj, ts, eval)); 112*5552b385SBrandon dx = coords[v * dE + 0] - eval[0]; 113*5552b385SBrandon dy = coords[v * dE + 1] - eval[1]; 114*5552b385SBrandon dz = coords[v * dE + 2] - eval[2]; 115*5552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz; 116*5552b385SBrandon 117*5552b385SBrandon if (obj_old < target) { 118*5552b385SBrandon tolr = obj_old; 119*5552b385SBrandon break; 120*5552b385SBrandon } 121*5552b385SBrandon 122*5552b385SBrandon A = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 123*5552b385SBrandon if (A == 0.0) { 124*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "A = 0.0 \n")); 125*5552b385SBrandon break; 126*5552b385SBrandon } 127*5552b385SBrandon b = eval[3] * dx + eval[4] * dy + eval[5] * dz; 128*5552b385SBrandon 129*5552b385SBrandon /* Solve A*delta = b */ 130*5552b385SBrandon delta = b / A; 131*5552b385SBrandon 132*5552b385SBrandon /* Find a temp (u,v) and associated objective function */ 133*5552b385SBrandon tt[0] = ts[0] + delta; 134*5552b385SBrandon if (tt[0] < range[0]) { 135*5552b385SBrandon tt[0] = range[0]; 136*5552b385SBrandon delta = tt[0] - ts[0]; 137*5552b385SBrandon } 138*5552b385SBrandon if (tt[0] > range[1]) { 139*5552b385SBrandon tt[0] = range[1]; 140*5552b385SBrandon delta = tt[0] - ts[0]; 141*5552b385SBrandon } 142*5552b385SBrandon 143*5552b385SBrandon PetscCall(EG_evaluate(obj, tt, data)); 144*5552b385SBrandon 145*5552b385SBrandon 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]); 146*5552b385SBrandon 147*5552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */ 148*5552b385SBrandon if (obj_tmp < obj_old) { 149*5552b385SBrandon obj_old = obj_tmp; 150*5552b385SBrandon ts[0] = tt[0]; 151*5552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 152*5552b385SBrandon lambda /= 2.0; 153*5552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14; 154*5552b385SBrandon if (obj_old < target) { 155*5552b385SBrandon tolr = obj_old; 156*5552b385SBrandon break; 157*5552b385SBrandon } 158*5552b385SBrandon } else { 159*5552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 160*5552b385SBrandon lambda *= 2.0; 161*5552b385SBrandon } 162*5552b385SBrandon 163*5552b385SBrandon if ((tt[0] == range[0]) || (tt[0] == range[1])) break; 164*5552b385SBrandon if (fabs(delta) < target) { 165*5552b385SBrandon tolr = obj_old; 166*5552b385SBrandon break; 167*5552b385SBrandon } 168*5552b385SBrandon 169*5552b385SBrandon tolr = obj_old; 170*5552b385SBrandon 171*5552b385SBrandon loopCntr += 1; 172*5552b385SBrandon if (loopCntr > 100) break; 173*5552b385SBrandon } 174*5552b385SBrandon paramsV[v * 3 + 0] = ts[0]; 175*5552b385SBrandon paramsV[v * 3 + 1] = 0.; 176*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 177*5552b385SBrandon } 178*5552b385SBrandon 179*5552b385SBrandon PetscErrorCode DMPlex_Geom_EDGE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[], PetscBool islite) 180*5552b385SBrandon { 181*5552b385SBrandon PetscInt loopCntr = 0; 182*5552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, obj_old, obj_tmp, target; 183*5552b385SBrandon PetscScalar delta, A, b; 184*5552b385SBrandon PetscScalar ts[2], tt[2], eval[18], data[18]; 185*5552b385SBrandon 186*5552b385SBrandon PetscFunctionBeginHot; 187*5552b385SBrandon /* Initialize Levenberg-Marquardt parameters */ 188*5552b385SBrandon lambda = 1.0; 189*5552b385SBrandon tolr = 1.0; 190*5552b385SBrandon target = 1.0E-20; 191*5552b385SBrandon ts[0] = (range[0] + range[1]) / 2.; 192*5552b385SBrandon 193*5552b385SBrandon while (tolr >= target) { 194*5552b385SBrandon if (islite) { 195*5552b385SBrandon PetscCall(EGlite_evaluate(obj, ts, eval)); 196*5552b385SBrandon } else { 197*5552b385SBrandon PetscCall(EG_evaluate(obj, ts, eval)); 198*5552b385SBrandon } 199*5552b385SBrandon 200*5552b385SBrandon dx = coords[v * dE + 0] - eval[0]; 201*5552b385SBrandon dy = coords[v * dE + 1] - eval[1]; 202*5552b385SBrandon dz = coords[v * dE + 2] - eval[2]; 203*5552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz; 204*5552b385SBrandon 205*5552b385SBrandon if (obj_old < target) { 206*5552b385SBrandon tolr = obj_old; 207*5552b385SBrandon break; 208*5552b385SBrandon } 209*5552b385SBrandon 210*5552b385SBrandon A = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 211*5552b385SBrandon if (A == 0.0) { 212*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "A = 0.0 \n")); 213*5552b385SBrandon break; 214*5552b385SBrandon } 215*5552b385SBrandon b = eval[3] * dx + eval[4] * dy + eval[5] * dz; 216*5552b385SBrandon 217*5552b385SBrandon /* Solve A*delta = b */ 218*5552b385SBrandon delta = b / A; 219*5552b385SBrandon 220*5552b385SBrandon /* Find a temp (u,v) and associated objective function */ 221*5552b385SBrandon tt[0] = ts[0] + delta; 222*5552b385SBrandon if (tt[0] < range[0]) { 223*5552b385SBrandon tt[0] = range[0]; 224*5552b385SBrandon delta = tt[0] - ts[0]; 225*5552b385SBrandon } 226*5552b385SBrandon if (tt[0] > range[1]) { 227*5552b385SBrandon tt[0] = range[1]; 228*5552b385SBrandon delta = tt[0] - ts[0]; 229*5552b385SBrandon } 230*5552b385SBrandon 231*5552b385SBrandon if (islite) { 232*5552b385SBrandon PetscCall(EGlite_evaluate(obj, tt, data)); 233*5552b385SBrandon } else { 234*5552b385SBrandon PetscCall(EG_evaluate(obj, tt, data)); 235*5552b385SBrandon } 236*5552b385SBrandon 237*5552b385SBrandon 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]); 238*5552b385SBrandon 239*5552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */ 240*5552b385SBrandon if (obj_tmp < obj_old) { 241*5552b385SBrandon obj_old = obj_tmp; 242*5552b385SBrandon ts[0] = tt[0]; 243*5552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 244*5552b385SBrandon lambda /= 2.0; 245*5552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14; 246*5552b385SBrandon if (obj_old < target) { 247*5552b385SBrandon tolr = obj_old; 248*5552b385SBrandon break; 249*5552b385SBrandon } 250*5552b385SBrandon } else { 251*5552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 252*5552b385SBrandon lambda *= 2.0; 253*5552b385SBrandon } 254*5552b385SBrandon 255*5552b385SBrandon if ((tt[0] == range[0]) || (tt[0] == range[1])) break; 256*5552b385SBrandon if (fabs(delta) < target) { 257*5552b385SBrandon tolr = obj_old; 258*5552b385SBrandon break; 259*5552b385SBrandon } 260*5552b385SBrandon 261*5552b385SBrandon tolr = obj_old; 262*5552b385SBrandon 263*5552b385SBrandon loopCntr += 1; 264*5552b385SBrandon if (loopCntr > 100) break; 265*5552b385SBrandon } 266*5552b385SBrandon paramsV[v * 3 + 0] = ts[0]; 267*5552b385SBrandon paramsV[v * 3 + 1] = 0.; 268*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 269*5552b385SBrandon } 270*5552b385SBrandon 271*5552b385SBrandon PetscErrorCode DMPlex_EGADS_FACE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[]) 272*5552b385SBrandon { 273*5552b385SBrandon // 274*5552b385SBrandon // 275*5552b385SBrandon // Depreciated. Changed all references to DMPlex_Geom_FACE_XYZtoUV_Internal() 276*5552b385SBrandon // 277*5552b385SBrandon // 278*5552b385SBrandon 279*5552b385SBrandon PetscInt loopCntr = 0; 280*5552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, denom, obj_old, obj_tmp, target; 281*5552b385SBrandon PetscScalar uvs[2], uvt[2], delta[2], A[4], b[2], eval[18], data[18]; 282*5552b385SBrandon 283*5552b385SBrandon PetscFunctionBeginHot; 284*5552b385SBrandon /* Initialize Levenberg-Marquardt parameters */ 285*5552b385SBrandon lambda = 1.0; 286*5552b385SBrandon tolr = 1.0; 287*5552b385SBrandon target = 1.0E-20; 288*5552b385SBrandon uvs[0] = (range[0] + range[1]) / 2.; 289*5552b385SBrandon uvs[1] = (range[2] + range[3]) / 2.; 290*5552b385SBrandon 291*5552b385SBrandon while (tolr >= target) { 292*5552b385SBrandon PetscCall(EG_evaluate(obj, uvs, eval)); 293*5552b385SBrandon dx = coords[v * dE + 0] - eval[0]; 294*5552b385SBrandon dy = coords[v * dE + 1] - eval[1]; 295*5552b385SBrandon dz = coords[v * dE + 2] - eval[2]; 296*5552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz; 297*5552b385SBrandon 298*5552b385SBrandon if (obj_old < target) { 299*5552b385SBrandon tolr = obj_old; 300*5552b385SBrandon break; 301*5552b385SBrandon } 302*5552b385SBrandon 303*5552b385SBrandon A[0] = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 304*5552b385SBrandon A[1] = eval[3] * eval[6] + eval[4] * eval[7] + eval[5] * eval[8]; 305*5552b385SBrandon A[2] = A[1]; 306*5552b385SBrandon A[3] = (eval[6] * eval[6] + eval[7] * eval[7] + eval[8] * eval[8]) * (1.0 + lambda); 307*5552b385SBrandon 308*5552b385SBrandon b[0] = eval[3] * dx + eval[4] * dy + eval[5] * dz; 309*5552b385SBrandon b[1] = eval[6] * dx + eval[7] * dy + eval[8] * dz; 310*5552b385SBrandon 311*5552b385SBrandon /* Solve A*delta = b using Cramer's Rule */ 312*5552b385SBrandon denom = A[0] * A[3] - A[2] * A[1]; 313*5552b385SBrandon if (denom == 0.0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, "denom = 0.0 \n")); } 314*5552b385SBrandon delta[0] = (b[0] * A[3] - b[1] * A[1]) / denom; 315*5552b385SBrandon delta[1] = (A[0] * b[1] - A[2] * b[0]) / denom; 316*5552b385SBrandon 317*5552b385SBrandon /* Find a temp (u,v) and associated objective function */ 318*5552b385SBrandon uvt[0] = uvs[0] + delta[0]; 319*5552b385SBrandon uvt[1] = uvs[1] + delta[1]; 320*5552b385SBrandon 321*5552b385SBrandon if (uvt[0] < range[0]) { 322*5552b385SBrandon uvt[0] = range[0]; 323*5552b385SBrandon delta[0] = uvt[0] - uvs[0]; 324*5552b385SBrandon } 325*5552b385SBrandon if (uvt[0] > range[1]) { 326*5552b385SBrandon uvt[0] = range[1]; 327*5552b385SBrandon delta[0] = uvt[0] - uvs[0]; 328*5552b385SBrandon } 329*5552b385SBrandon if (uvt[1] < range[2]) { 330*5552b385SBrandon uvt[1] = range[2]; 331*5552b385SBrandon delta[1] = uvt[1] - uvs[1]; 332*5552b385SBrandon } 333*5552b385SBrandon if (uvt[1] > range[3]) { 334*5552b385SBrandon uvt[1] = range[3]; 335*5552b385SBrandon delta[1] = uvt[1] - uvs[1]; 336*5552b385SBrandon } 337*5552b385SBrandon 338*5552b385SBrandon PetscCall(EG_evaluate(obj, uvt, data)); 339*5552b385SBrandon 340*5552b385SBrandon 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]); 341*5552b385SBrandon 342*5552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */ 343*5552b385SBrandon if (obj_tmp < obj_old) { 344*5552b385SBrandon obj_old = obj_tmp; 345*5552b385SBrandon uvs[0] = uvt[0]; 346*5552b385SBrandon uvs[1] = uvt[1]; 347*5552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 348*5552b385SBrandon lambda /= 2.0; 349*5552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14; 350*5552b385SBrandon if (obj_old < target) { 351*5552b385SBrandon tolr = obj_old; 352*5552b385SBrandon break; 353*5552b385SBrandon } 354*5552b385SBrandon } else { 355*5552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 356*5552b385SBrandon lambda *= 2.0; 357*5552b385SBrandon } 358*5552b385SBrandon 359*5552b385SBrandon if (sqrt(delta[0] * delta[0] + delta[1] * delta[1]) < target) { 360*5552b385SBrandon tolr = obj_old; 361*5552b385SBrandon break; 362*5552b385SBrandon } 363*5552b385SBrandon 364*5552b385SBrandon tolr = obj_old; 365*5552b385SBrandon 366*5552b385SBrandon loopCntr += 1; 367*5552b385SBrandon if (loopCntr > 100) break; 368*5552b385SBrandon } 369*5552b385SBrandon paramsV[v * 3 + 0] = uvs[0]; 370*5552b385SBrandon paramsV[v * 3 + 1] = uvs[1]; 371*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 372*5552b385SBrandon } 373*5552b385SBrandon 374*5552b385SBrandon PetscErrorCode DMPlex_Geom_FACE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[], PetscBool islite) 375*5552b385SBrandon { 376*5552b385SBrandon PetscInt loopCntr = 0; 377*5552b385SBrandon PetscScalar dx, dy, dz, lambda, tolr, denom, obj_old, obj_tmp, target; 378*5552b385SBrandon PetscScalar uvs[2], uvt[2], delta[2], A[4], b[2], eval[18], data[18]; 379*5552b385SBrandon 380*5552b385SBrandon PetscFunctionBeginHot; 381*5552b385SBrandon /* Initialize Levenberg-Marquardt parameters */ 382*5552b385SBrandon lambda = 1.0; 383*5552b385SBrandon tolr = 1.0; 384*5552b385SBrandon target = 1.0E-20; 385*5552b385SBrandon uvs[0] = (range[0] + range[1]) / 2.; 386*5552b385SBrandon uvs[1] = (range[2] + range[3]) / 2.; 387*5552b385SBrandon 388*5552b385SBrandon while (tolr >= target) { 389*5552b385SBrandon if (islite) { 390*5552b385SBrandon PetscCallEGADS(EGlite_evaluate, (obj, uvs, eval)); 391*5552b385SBrandon } else { 392*5552b385SBrandon PetscCallEGADS(EG_evaluate, (obj, uvs, eval)); 393*5552b385SBrandon } 394*5552b385SBrandon 395*5552b385SBrandon dx = coords[v * dE + 0] - eval[0]; 396*5552b385SBrandon dy = coords[v * dE + 1] - eval[1]; 397*5552b385SBrandon dz = coords[v * dE + 2] - eval[2]; 398*5552b385SBrandon obj_old = dx * dx + dy * dy + dz * dz; 399*5552b385SBrandon 400*5552b385SBrandon if (obj_old < target) { 401*5552b385SBrandon tolr = obj_old; 402*5552b385SBrandon break; 403*5552b385SBrandon } 404*5552b385SBrandon 405*5552b385SBrandon A[0] = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 406*5552b385SBrandon A[1] = eval[3] * eval[6] + eval[4] * eval[7] + eval[5] * eval[8]; 407*5552b385SBrandon A[2] = A[1]; 408*5552b385SBrandon A[3] = (eval[6] * eval[6] + eval[7] * eval[7] + eval[8] * eval[8]) * (1.0 + lambda); 409*5552b385SBrandon 410*5552b385SBrandon b[0] = eval[3] * dx + eval[4] * dy + eval[5] * dz; 411*5552b385SBrandon b[1] = eval[6] * dx + eval[7] * dy + eval[8] * dz; 412*5552b385SBrandon 413*5552b385SBrandon /* Solve A*delta = b using Cramer's Rule */ 414*5552b385SBrandon denom = A[0] * A[3] - A[2] * A[1]; 415*5552b385SBrandon if (denom == 0.0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, "denom = 0.0 \n")); } 416*5552b385SBrandon delta[0] = (b[0] * A[3] - b[1] * A[1]) / denom; 417*5552b385SBrandon delta[1] = (A[0] * b[1] - A[2] * b[0]) / denom; 418*5552b385SBrandon 419*5552b385SBrandon /* Find a temp (u,v) and associated objective function */ 420*5552b385SBrandon uvt[0] = uvs[0] + delta[0]; 421*5552b385SBrandon uvt[1] = uvs[1] + delta[1]; 422*5552b385SBrandon 423*5552b385SBrandon if (uvt[0] < range[0]) { 424*5552b385SBrandon uvt[0] = range[0]; 425*5552b385SBrandon delta[0] = uvt[0] - uvs[0]; 426*5552b385SBrandon } 427*5552b385SBrandon if (uvt[0] > range[1]) { 428*5552b385SBrandon uvt[0] = range[1]; 429*5552b385SBrandon delta[0] = uvt[0] - uvs[0]; 430*5552b385SBrandon } 431*5552b385SBrandon if (uvt[1] < range[2]) { 432*5552b385SBrandon uvt[1] = range[2]; 433*5552b385SBrandon delta[1] = uvt[1] - uvs[1]; 434*5552b385SBrandon } 435*5552b385SBrandon if (uvt[1] > range[3]) { 436*5552b385SBrandon uvt[1] = range[3]; 437*5552b385SBrandon delta[1] = uvt[1] - uvs[1]; 438*5552b385SBrandon } 439*5552b385SBrandon 440*5552b385SBrandon if (islite) { 441*5552b385SBrandon PetscCall(EGlite_evaluate(obj, uvt, data)); 442*5552b385SBrandon } else { 443*5552b385SBrandon PetscCall(EG_evaluate(obj, uvt, data)); 444*5552b385SBrandon } 445*5552b385SBrandon 446*5552b385SBrandon 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]); 447*5552b385SBrandon 448*5552b385SBrandon /* If step is better, accept it and halve lambda (making it more Newton-like) */ 449*5552b385SBrandon if (obj_tmp < obj_old) { 450*5552b385SBrandon obj_old = obj_tmp; 451*5552b385SBrandon uvs[0] = uvt[0]; 452*5552b385SBrandon uvs[1] = uvt[1]; 453*5552b385SBrandon for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 454*5552b385SBrandon lambda /= 2.0; 455*5552b385SBrandon if (lambda < 1.0E-14) lambda = 1.0E-14; 456*5552b385SBrandon if (obj_old < target) { 457*5552b385SBrandon tolr = obj_old; 458*5552b385SBrandon break; 459*5552b385SBrandon } 460*5552b385SBrandon } else { 461*5552b385SBrandon /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 462*5552b385SBrandon lambda *= 2.0; 463*5552b385SBrandon } 464*5552b385SBrandon 465*5552b385SBrandon if (sqrt(delta[0] * delta[0] + delta[1] * delta[1]) < target) { 466*5552b385SBrandon tolr = obj_old; 467*5552b385SBrandon break; 468*5552b385SBrandon } 469*5552b385SBrandon 470*5552b385SBrandon tolr = obj_old; 471*5552b385SBrandon 472*5552b385SBrandon loopCntr += 1; 473*5552b385SBrandon if (loopCntr > 100) break; 474*5552b385SBrandon } 475*5552b385SBrandon paramsV[v * 3 + 0] = uvs[0]; 476*5552b385SBrandon paramsV[v * 3 + 1] = uvs[1]; 477*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 478*5552b385SBrandon } 479*5552b385SBrandon 480*5552b385SBrandon PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM dm, PetscInt p, ego model, PetscInt bodyID, PetscInt faceID, PetscInt edgeID, const PetscScalar mcoords[], PetscScalar gcoords[], PetscBool islite) 481*5552b385SBrandon { 482*5552b385SBrandon /* PETSc Variables */ 483c1cad2e7SMatthew G. Knepley DM cdm; 484c1cad2e7SMatthew G. Knepley ego *bodies; 485c1cad2e7SMatthew G. Knepley ego geom, body, obj; 486*5552b385SBrandon /* result has to hold derviatives, along with the value */ 487*5552b385SBrandon 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; 493*5552b385SBrandon 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)); 499*5552b385SBrandon 500*5552b385SBrandon if (islite) { 501*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 502*5552b385SBrandon } else { 5039566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 504*5552b385SBrandon } 505*5552b385SBrandon 506*5552b385SBrandon 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) { 510*5552b385SBrandon if (islite) { 511*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &obj)); 512*5552b385SBrandon Np = 1; 513*5552b385SBrandon } else { 5149371c9d4SSatish Balay PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &obj)); 5159371c9d4SSatish Balay Np = 1; 516*5552b385SBrandon } 5179371c9d4SSatish Balay } else if (faceID >= 0) { 518*5552b385SBrandon if (islite) { 519*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &obj)); 520*5552b385SBrandon Np = 2; 521*5552b385SBrandon } else { 5229371c9d4SSatish Balay PetscCall(EG_objectBodyTopo(body, FACE, faceID, &obj)); 5239371c9d4SSatish Balay Np = 2; 524*5552b385SBrandon } 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 540*5552b385SBrandon /* Correct EGADS/EGADSlite 2pi bug when calculating nearest point on Periodic Surfaces */ 541*5552b385SBrandon if (islite) { 542*5552b385SBrandon PetscCall(EGlite_getRange(obj, range, &peri)); 543*5552b385SBrandon } else { 5449566063dSJacob Faibussowitsch PetscCall(EG_getRange(obj, range, &peri)); 545*5552b385SBrandon } 546*5552b385SBrandon 547c1cad2e7SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 548*5552b385SBrandon if (edgeID > 0) { 549*5552b385SBrandon PetscCall(DMPlex_Geom_EDGE_XYZtoUV_Internal(coords, obj, range, v, dE, paramsV, islite)); 550*5552b385SBrandon } else { 551*5552b385SBrandon 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)); 555*5552b385SBrandon 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 } 562*5552b385SBrandon 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); 563*5552b385SBrandon 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); 564*5552b385SBrandon 565c1cad2e7SMatthew G. Knepley /* Put coordinates for new vertex in result[] */ 566*5552b385SBrandon if (islite) { 567*5552b385SBrandon PetscCall(EGlite_evaluate(obj, params, result)); 568*5552b385SBrandon } else { 5699566063dSJacob Faibussowitsch PetscCall(EG_evaluate(obj, params, result)); 570*5552b385SBrandon } 571*5552b385SBrandon 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; 585*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5867625649eSMatthew G. Knepley 587*5552b385SBrandon // 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)); 593*5552b385SBrandon if (!modelObj) { 594*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 595*5552b385SBrandon islite = PETSC_TRUE; 596*5552b385SBrandon } 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 } 608*5552b385SBrandon 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) 614*5552b385SBrandon PetscErrorCode DMPlexGeomPrintModel_Internal(ego model, PetscBool islite) 615d71ae5a4SJacob Faibussowitsch { 616*5552b385SBrandon /* PETSc Variables */ 617*5552b385SBrandon ego geom, *bodies, *nobjs, *mobjs, *lobjs, *shobjs, *fobjs, *eobjs; 618*5552b385SBrandon int oclass, mtype, *senses, *shsenses, *fsenses, *lsenses, *esenses; 6197bee2925SMatthew Knepley int Nb, b; 6207bee2925SMatthew Knepley 6217bee2925SMatthew Knepley PetscFunctionBeginUser; 6227bee2925SMatthew Knepley /* test bodyTopo functions */ 623*5552b385SBrandon if (islite) { 624*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 625*5552b385SBrandon } else { 6269566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 627*5552b385SBrandon } 628*5552b385SBrandon 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]; 632*5552b385SBrandon int id, sh, Nsh, f, Nf, l, Nl, e, Ne, v, Nv; 633*5552b385SBrandon 634*5552b385SBrandon /* List Topology of Bodies */ 635*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 636*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " BODY %d TOPOLOGY SUMMARY \n", b)); 6377bee2925SMatthew Knepley 6387bee2925SMatthew Knepley /* Output Basic Model Topology */ 639*5552b385SBrandon if (islite) { 640*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, &Nsh, &shobjs)); 641*5552b385SBrandon } else { 642*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, SHELL, &Nsh, &shobjs)); 643*5552b385SBrandon } 6449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of SHELLS: %d \n", Nsh)); 6457bee2925SMatthew Knepley 646*5552b385SBrandon if (islite) { 647*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 648*5552b385SBrandon } else { 649*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 650*5552b385SBrandon } 6519566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of FACES: %d \n", Nf)); 6527bee2925SMatthew Knepley 653*5552b385SBrandon if (islite) { 654*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 655*5552b385SBrandon } else { 6569566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 657*5552b385SBrandon } 6589566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of LOOPS: %d \n", Nl)); 6597bee2925SMatthew Knepley 660*5552b385SBrandon if (islite) { 661*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 662*5552b385SBrandon } else { 663*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 664*5552b385SBrandon } 6659566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of EDGES: %d \n", Ne)); 6667bee2925SMatthew Knepley 667*5552b385SBrandon if (islite) { 668*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 669*5552b385SBrandon } else { 670*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 671*5552b385SBrandon } 6729566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of NODES: %d \n", Nv)); 673*5552b385SBrandon 674*5552b385SBrandon if (islite) { 675*5552b385SBrandon EGlite_free(shobjs); 676*5552b385SBrandon EGlite_free(fobjs); 677*5552b385SBrandon EGlite_free(lobjs); 678*5552b385SBrandon EGlite_free(eobjs); 679*5552b385SBrandon EGlite_free(nobjs); 680*5552b385SBrandon } else { 681*5552b385SBrandon EG_free(shobjs); 682*5552b385SBrandon EG_free(fobjs); 683*5552b385SBrandon EG_free(lobjs); 684*5552b385SBrandon EG_free(eobjs); 685*5552b385SBrandon EG_free(nobjs); 686*5552b385SBrandon } 687*5552b385SBrandon 688*5552b385SBrandon /* List Topology of Bodies */ 689*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 690*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " BODY %d TOPOLOGY DETAILS \n", b)); 691*5552b385SBrandon 692*5552b385SBrandon /* Get SHELL info which associated with the current BODY */ 693*5552b385SBrandon if (islite) { 694*5552b385SBrandon PetscCall(EGlite_getTopology(body, &geom, &oclass, &mtype, NULL, &Nsh, &shobjs, &shsenses)); 695*5552b385SBrandon } else { 696*5552b385SBrandon PetscCall(EG_getTopology(body, &geom, &oclass, &mtype, NULL, &Nsh, &shobjs, &shsenses)); 697*5552b385SBrandon } 698*5552b385SBrandon 699*5552b385SBrandon for (sh = 0; sh < Nsh; ++sh) { 700*5552b385SBrandon ego shell = shobjs[sh]; 701*5552b385SBrandon int shsense = shsenses[sh]; 702*5552b385SBrandon 703*5552b385SBrandon if (islite) { 704*5552b385SBrandon id = EGlite_indexBodyTopo(body, shell); 705*5552b385SBrandon } else { 706*5552b385SBrandon id = EG_indexBodyTopo(body, shell); 707*5552b385SBrandon } 708*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " SHELL ID: %d :: sense = %d\n", id, shsense)); 709*5552b385SBrandon 710*5552b385SBrandon /* Get FACE infor associated with current SHELL */ 711*5552b385SBrandon if (islite) { 712*5552b385SBrandon PetscCall(EGlite_getTopology(shell, &geom, &oclass, &mtype, NULL, &Nf, &fobjs, &fsenses)); 713*5552b385SBrandon } else { 714*5552b385SBrandon PetscCall(EG_getTopology(shell, &geom, &oclass, &mtype, NULL, &Nf, &fobjs, &fsenses)); 715*5552b385SBrandon } 716*5552b385SBrandon 717*5552b385SBrandon for (f = 0; f < Nf; ++f) { 718*5552b385SBrandon ego face = fobjs[f]; 719*5552b385SBrandon ego gRef, gPrev, gNext; 720*5552b385SBrandon int goclass, gmtype, *gpinfo; 721*5552b385SBrandon double *gprv; 722*5552b385SBrandon char *gClass = (char *)"", *gType = (char *)""; 723*5552b385SBrandon double fdata[4]; 724*5552b385SBrandon ego fRef, fPrev, fNext; 725*5552b385SBrandon int foclass, fmtype; 726*5552b385SBrandon 727*5552b385SBrandon if (islite) { 728*5552b385SBrandon id = EGlite_indexBodyTopo(body, face); 729*5552b385SBrandon } else { 730*5552b385SBrandon id = EG_indexBodyTopo(body, face); 731*5552b385SBrandon } 732*5552b385SBrandon 733*5552b385SBrandon /* Get LOOP info associated with current FACE */ 734*5552b385SBrandon if (islite) { 735*5552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, fdata, &Nl, &lobjs, &lsenses)); 736*5552b385SBrandon PetscCall(EGlite_getInfo(face, &foclass, &fmtype, &fRef, &fPrev, &fNext)); 737*5552b385SBrandon PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 738*5552b385SBrandon PetscCall(EGlite_getInfo(geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 739*5552b385SBrandon } else { 740*5552b385SBrandon PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, fdata, &Nl, &lobjs, &lsenses)); 741*5552b385SBrandon PetscCall(EG_getInfo(face, &foclass, &fmtype, &fRef, &fPrev, &fNext)); 742*5552b385SBrandon PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 743*5552b385SBrandon PetscCall(EG_getInfo(geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 744*5552b385SBrandon } 745*5552b385SBrandon 746*5552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType)); 747*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " FACE ID: %d :: sense = %d \n", id, fmtype)); 748*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY CLASS: %s \n", gClass)); 749*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY TYPE: %s \n\n", gType)); 750*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " RANGE (umin, umax) = (%f, %f) \n", fdata[0], fdata[1])); 751*5552b385SBrandon 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]; 755*5552b385SBrandon int lsense = lsenses[l]; 7567bee2925SMatthew Knepley 757*5552b385SBrandon if (islite) { 758*5552b385SBrandon id = EGlite_indexBodyTopo(body, loop); 759*5552b385SBrandon } else { 7607bee2925SMatthew Knepley id = EG_indexBodyTopo(body, loop); 761*5552b385SBrandon } 7627bee2925SMatthew Knepley 763*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP ID: %d :: sense = %d\n", id, lsense)); 764*5552b385SBrandon 765*5552b385SBrandon /* Get EDGE info associated with the current LOOP */ 766*5552b385SBrandon if (islite) { 767*5552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &esenses)); 768*5552b385SBrandon } else { 769*5552b385SBrandon PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &esenses)); 770*5552b385SBrandon } 7717bee2925SMatthew Knepley 7727bee2925SMatthew Knepley for (e = 0; e < Ne; ++e) { 773*5552b385SBrandon ego edge = eobjs[e]; 774*5552b385SBrandon ego topRef, prev, next; 775*5552b385SBrandon int esense = esenses[e]; 7767bee2925SMatthew Knepley double range[4] = {0., 0., 0., 0.}; 7777bee2925SMatthew Knepley int peri; 778*5552b385SBrandon ego gEref, gEprev, gEnext; 779*5552b385SBrandon int gEoclass, gEmtype; 780*5552b385SBrandon char *gEclass = (char *)"", *gEtype = (char *)""; 7817bee2925SMatthew Knepley 782*5552b385SBrandon if (islite) { 783*5552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 784*5552b385SBrandon if (mtype != DEGENERATE) { PetscCall(EGlite_getInfo(geom, &gEoclass, &gEmtype, &gEref, &gEprev, &gEnext)); } 785266cfabeSMatthew G. Knepley } else { 786*5552b385SBrandon PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 787*5552b385SBrandon PetscCall(EG_getInfo(geom, &gEoclass, &gEmtype, &gEref, &gEprev, &gEnext)); 788*5552b385SBrandon } 789*5552b385SBrandon 790*5552b385SBrandon if (mtype != DEGENERATE) { PetscCall(DMPlex_EGADS_GeomDecode_Internal(gEoclass, gEmtype, &gEclass, &gEtype)); } 791*5552b385SBrandon 792*5552b385SBrandon if (islite) { 793*5552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 794*5552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 795*5552b385SBrandon } else { 796*5552b385SBrandon id = EG_indexBodyTopo(body, edge); 797*5552b385SBrandon PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 798*5552b385SBrandon } 799*5552b385SBrandon 800*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE ID: %d :: sense = %d\n", id, esense)); 801*5552b385SBrandon if (mtype != DEGENERATE) { 802*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY CLASS: %s \n", gEclass)); 803*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY TYPE: %s \n", gEtype)); 804*5552b385SBrandon } 805*5552b385SBrandon 806*5552b385SBrandon if (mtype == DEGENERATE) { PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE %d is DEGENERATE \n", id)); } 807*5552b385SBrandon 808*5552b385SBrandon if (islite) { 809*5552b385SBrandon PetscCall(EGlite_getRange(edge, range, &peri)); 810*5552b385SBrandon } else { 811*5552b385SBrandon PetscCall(EG_getRange(edge, range, &peri)); 812*5552b385SBrandon } 813*5552b385SBrandon 814*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " Peri = %d :: Range = %lf, %lf, %lf, %lf \n", peri, range[0], range[1], range[2], range[3])); 815*5552b385SBrandon 816*5552b385SBrandon /* Get NODE info associated with the current EDGE */ 817*5552b385SBrandon if (islite) { 818*5552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 819*5552b385SBrandon } else { 820*5552b385SBrandon 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 828*5552b385SBrandon if (islite) { 829*5552b385SBrandon PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 830*5552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 831*5552b385SBrandon } else { 8329566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 8337bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 834*5552b385SBrandon } 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 } 841*5552b385SBrandon } 842*5552b385SBrandon } 843*5552b385SBrandon 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 { 849*5552b385SBrandon if (*context) EG_deleteObject((ego)*context); 850*5552b385SBrandon return (PETSC_SUCCESS); 851*5552b385SBrandon } 852*5552b385SBrandon 853*5552b385SBrandon static PetscErrorCode DMPlexEGADSClose_Private(void **context) 854*5552b385SBrandon { 855*5552b385SBrandon if (*context) EG_close((ego)*context); 856*5552b385SBrandon return (PETSC_SUCCESS); 857*5552b385SBrandon } 858*5552b385SBrandon 859*5552b385SBrandon PetscErrorCode DMPlexEGADSliteDestroy_Private(void **context) 860*5552b385SBrandon { 861*5552b385SBrandon if (*context) EGlite_deleteObject((ego)*context); 8627bee2925SMatthew Knepley return 0; 8637bee2925SMatthew Knepley } 8647bee2925SMatthew Knepley 865*5552b385SBrandon PetscErrorCode DMPlexEGADSliteClose_Private(void **context) 866d71ae5a4SJacob Faibussowitsch { 867*5552b385SBrandon if (*context) EGlite_close((ego)*context); 868*5552b385SBrandon return 0; 869*5552b385SBrandon } 870*5552b385SBrandon 871*5552b385SBrandon PetscErrorCode DMPlexCreateGeom_Internal(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 872*5552b385SBrandon { 873*5552b385SBrandon /* 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; 879*5552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 8807bee2925SMatthew Knepley PetscHMapI edgeMap = NULL; 881*5552b385SBrandon PetscInt cStart, cEnd, c; 8827bee2925SMatthew Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, maxCorners = 0, numVertices = 0, newVertices = 0, numEdges = 0, numCells = 0, newCells = 0, numQuads = 0, cOff = 0, fOff = 0; 8837bee2925SMatthew Knepley PetscInt *cells = NULL, *cone = NULL; 8847bee2925SMatthew Knepley PetscReal *coords = NULL; 8857bee2925SMatthew Knepley PetscMPIInt rank; 8867bee2925SMatthew Knepley 8877bee2925SMatthew Knepley PetscFunctionBegin; 8889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 889dd400576SPatrick Sanan if (rank == 0) { 890266cfabeSMatthew G. Knepley const PetscInt debug = 0; 891266cfabeSMatthew G. Knepley 8927bee2925SMatthew Knepley /* --------------------------------------------------------------------------------------------------- 8937bee2925SMatthew Knepley Generate Petsc Plex 8947bee2925SMatthew Knepley Get all Nodes in model, record coordinates in a correctly formatted array 8957bee2925SMatthew Knepley Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array 8967bee2925SMatthew Knepley We need to uniformly refine the initial geometry to guarantee a valid mesh 8977bee2925SMatthew Knepley */ 8987bee2925SMatthew Knepley 8997bee2925SMatthew Knepley /* Calculate cell and vertex sizes */ 900*5552b385SBrandon if (islite) { 901*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 902*5552b385SBrandon } else { 9039566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 904*5552b385SBrandon } 905*5552b385SBrandon 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 912*5552b385SBrandon if (islite) { 913*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 914*5552b385SBrandon } else { 9159566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 916*5552b385SBrandon } 917*5552b385SBrandon 9187bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 9197bee2925SMatthew Knepley ego loop = lobjs[l]; 9207bee2925SMatthew Knepley int Ner = 0, Ne, e, Nc; 9217bee2925SMatthew Knepley 922*5552b385SBrandon if (islite) { 923*5552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 924*5552b385SBrandon } else { 9259566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 926*5552b385SBrandon } 927*5552b385SBrandon 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 934*5552b385SBrandon if (islite) { 935*5552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 936*5552b385SBrandon } else { 9379566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 938*5552b385SBrandon } 939*5552b385SBrandon 9407bee2925SMatthew Knepley if (mtype == DEGENERATE) continue; 941*5552b385SBrandon 942*5552b385SBrandon if (islite) { 943*5552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 944*5552b385SBrandon } else { 9455f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, edge); 946*5552b385SBrandon } 947*5552b385SBrandon 9489566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, id - 1, &iter, &found)); 949*5552b385SBrandon 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 } 964*5552b385SBrandon if (islite) { 965*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 966*5552b385SBrandon } else { 9679566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 968*5552b385SBrandon } 969*5552b385SBrandon 9707bee2925SMatthew Knepley for (v = 0; v < Nv; ++v) { 9717bee2925SMatthew Knepley ego vertex = nobjs[v]; 9727bee2925SMatthew Knepley 973*5552b385SBrandon if (islite) { 974*5552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 975*5552b385SBrandon } else { 9767bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 977*5552b385SBrandon } 9787bee2925SMatthew Knepley /* TODO: Instead of assuming contiguous ids, we could use a hash table */ 9797bee2925SMatthew Knepley numVertices = PetscMax(id, numVertices); 9807bee2925SMatthew Knepley } 981*5552b385SBrandon if (islite) { 982*5552b385SBrandon EGlite_free(lobjs); 983*5552b385SBrandon EGlite_free(nobjs); 984*5552b385SBrandon } else { 9857bee2925SMatthew Knepley EG_free(lobjs); 9867bee2925SMatthew Knepley EG_free(nobjs); 9877bee2925SMatthew Knepley } 988*5552b385SBrandon } 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 1003*5552b385SBrandon if (islite) { 1004*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1005*5552b385SBrandon } else { 10069566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1007*5552b385SBrandon } 1008*5552b385SBrandon 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 1014*5552b385SBrandon if (islite) { 1015*5552b385SBrandon PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 1016*5552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 1017*5552b385SBrandon } else { 10189566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 10195f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, vertex); 1020*5552b385SBrandon } 1021*5552b385SBrandon 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 } 1026*5552b385SBrandon if (islite) { 1027*5552b385SBrandon EGlite_free(nobjs); 1028*5552b385SBrandon } else { 10297bee2925SMatthew Knepley EG_free(nobjs); 10307bee2925SMatthew Knepley } 1031*5552b385SBrandon } 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 1040*5552b385SBrandon if (islite) { 1041*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1042*5552b385SBrandon } else { 10439566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1044*5552b385SBrandon } 1045*5552b385SBrandon 10467bee2925SMatthew Knepley for (l = 0; l < Nl; ++l) { 10477bee2925SMatthew Knepley ego loop = lobjs[l]; 10487bee2925SMatthew Knepley int lid, Ner = 0, Ne, e; 10497bee2925SMatthew Knepley 1050*5552b385SBrandon if (islite) { 1051*5552b385SBrandon lid = EGlite_indexBodyTopo(body, loop); 1052*5552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1053*5552b385SBrandon } else { 10545f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 10559566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1056*5552b385SBrandon } 1057*5552b385SBrandon 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 1064*5552b385SBrandon if (islite) { 1065*5552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1066*5552b385SBrandon } else { 10679566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1068*5552b385SBrandon } 1069*5552b385SBrandon 10707bee2925SMatthew Knepley if (mtype == DEGENERATE) continue; 10717bee2925SMatthew Knepley ++Ner; 1072*5552b385SBrandon 1073*5552b385SBrandon if (islite) { 1074*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 1075*5552b385SBrandon } else { 10765f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 1077*5552b385SBrandon } 1078*5552b385SBrandon 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++)); 1086*5552b385SBrandon 1087*5552b385SBrandon if (islite) { 1088*5552b385SBrandon PetscCall(EGlite_getRange(edge, range, periodic)); 1089*5552b385SBrandon } else { 10909566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, periodic)); 1091*5552b385SBrandon } 1092*5552b385SBrandon 10937bee2925SMatthew Knepley params[0] = 0.5 * (range[0] + range[1]); 1094*5552b385SBrandon if (islite) { 1095*5552b385SBrandon PetscCall(EGlite_evaluate(edge, params, result)); 1096*5552b385SBrandon } else { 10979566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, params, result)); 1098*5552b385SBrandon } 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 1110*5552b385SBrandon if (islite) { 1111*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 1112*5552b385SBrandon } else { 11139566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 1114*5552b385SBrandon } 1115266cfabeSMatthew G. Knepley face = fobjs[0]; 1116*5552b385SBrandon 1117*5552b385SBrandon if (islite) { 1118*5552b385SBrandon fid = EGlite_indexBodyTopo(body, face); 1119*5552b385SBrandon } else { 11205f80ce2aSJacob Faibussowitsch fid = EG_indexBodyTopo(body, face); 1121*5552b385SBrandon } 1122*5552b385SBrandon 1123*5552b385SBrandon PetscCheck(Nf != 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Loop %d has %" PetscInt_FMT " faces, instead of 1 (%" PetscInt_FMT ")", lid - 1, Nf, fid); 1124*5552b385SBrandon if (islite) { 1125*5552b385SBrandon PetscCall(EGlite_getRange(face, range, periodic)); 1126*5552b385SBrandon } else { 11279566063dSJacob Faibussowitsch PetscCall(EG_getRange(face, range, periodic)); 1128*5552b385SBrandon } 11297bee2925SMatthew Knepley params[0] = 0.5 * (range[0] + range[1]); 11307bee2925SMatthew Knepley params[1] = 0.5 * (range[2] + range[3]); 1131*5552b385SBrandon if (islite) { 1132*5552b385SBrandon PetscCall(EGlite_evaluate(face, params, result)); 1133*5552b385SBrandon } else { 11349566063dSJacob Faibussowitsch PetscCall(EG_evaluate(face, params, result)); 1135*5552b385SBrandon } 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 } 1142*5552b385SBrandon 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 1151*5552b385SBrandon if (islite) { 1152*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1153*5552b385SBrandon } else { 11549566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1155*5552b385SBrandon } 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 1160*5552b385SBrandon if (islite) { 1161*5552b385SBrandon lid = EGlite_indexBodyTopo(body, loop); 1162*5552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1163*5552b385SBrandon } else { 11645f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 11659566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1166*5552b385SBrandon } 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 1173*5552b385SBrandon if (islite) { 1174*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 1175*5552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1176*5552b385SBrandon } else { 11777bee2925SMatthew Knepley eid = EG_indexBodyTopo(body, edge); 11789566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1179*5552b385SBrandon } 1180*5552b385SBrandon 1181266cfabeSMatthew G. Knepley if (mtype == DEGENERATE) continue; 1182266cfabeSMatthew G. Knepley else ++Ner; 1183*5552b385SBrandon 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 1188*5552b385SBrandon if (islite) { 1189*5552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 1190*5552b385SBrandon } else { 11917bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 1192*5552b385SBrandon } 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); 1227*5552b385SBrandon 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) { 1301*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP Corner NODEs Triangle %d (", t)); 13027bee2925SMatthew Knepley for (c = 0; c < numCorners; ++c) { 1303*5552b385SBrandon if (c > 0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); } 1304*5552b385SBrandon 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 } 1310*5552b385SBrandon if (islite) { 1311*5552b385SBrandon EGlite_free(lobjs); 1312*5552b385SBrandon } else { 13137bee2925SMatthew Knepley EG_free(lobjs); 13147bee2925SMatthew Knepley } 13157bee2925SMatthew Knepley } 1316*5552b385SBrandon } 1317*5552b385SBrandon 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)); 1320*5552b385SBrandon PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %d (%d)\n", numCells, newCells)); 1321*5552b385SBrandon 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)); 1328*5552b385SBrandon 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)); 1334*5552b385SBrandon 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 1352*5552b385SBrandon if (islite) { 1353*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1354*5552b385SBrandon } else { 13559566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1356*5552b385SBrandon } 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 1362*5552b385SBrandon if (islite) { 1363*5552b385SBrandon lid = EGlite_indexBodyTopo(body, loop); 1364*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 1365*5552b385SBrandon } else { 13665f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 13679566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 1368*5552b385SBrandon } 1369*5552b385SBrandon 137008401ef6SPierre Jolivet PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf); 1371*5552b385SBrandon if (islite) { 1372*5552b385SBrandon fid = EGlite_indexBodyTopo(body, fobjs[0]); 1373*5552b385SBrandon EGlite_free(fobjs); 1374*5552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1375*5552b385SBrandon } 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)); 1379*5552b385SBrandon } 1380*5552b385SBrandon 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 1387*5552b385SBrandon if (islite) { 1388*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 1389*5552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1390*5552b385SBrandon } else { 13917bee2925SMatthew Knepley eid = EG_indexBodyTopo(body, edge); 13929566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1393*5552b385SBrandon } 1394*5552b385SBrandon 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 1400*5552b385SBrandon if (islite) { 1401*5552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 1402*5552b385SBrandon } else { 14037bee2925SMatthew Knepley id = EG_indexBodyTopo(body, vertex); 1404*5552b385SBrandon } 1405*5552b385SBrandon 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)); 1416*5552b385SBrandon 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)); 1422*5552b385SBrandon 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 } 1445*5552b385SBrandon if (islite) { 1446*5552b385SBrandon EGlite_free(lobjs); 1447*5552b385SBrandon } else { 14487bee2925SMatthew Knepley EG_free(lobjs); 14497bee2925SMatthew Knepley } 1450*5552b385SBrandon } 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*5552b385SBrandon PetscFunctionReturn(0); 14687bee2925SMatthew Knepley } 1469c1cad2e7SMatthew G. Knepley 1470*5552b385SBrandon PetscErrorCode DMPlexCreateGeom(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 1471d71ae5a4SJacob Faibussowitsch { 1472*5552b385SBrandon // 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; 1479*5552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 1480c1cad2e7SMatthew G. Knepley PetscHMapI edgeMap = NULL, bodyIndexMap = NULL, bodyVertexMap = NULL, bodyEdgeMap = NULL, bodyFaceMap = NULL, bodyEdgeGlobalMap = NULL; 1481c1cad2e7SMatthew G. Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, numVertices = 0, numEdges = 0, numFaces = 0, numCells = 0, edgeCntr = 0; 1482c1cad2e7SMatthew G. Knepley PetscInt cellCntr = 0, numPoints = 0; 1483c1cad2e7SMatthew G. Knepley PetscInt *cells = NULL; 1484c1cad2e7SMatthew G. Knepley const PetscInt *cone = NULL; 1485c1cad2e7SMatthew G. Knepley PetscReal *coords = NULL; 1486c1cad2e7SMatthew G. Knepley PetscMPIInt rank; 1487c1cad2e7SMatthew G. Knepley 1488c1cad2e7SMatthew G. Knepley PetscFunctionBeginUser; 14899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1490c5853193SPierre Jolivet if (rank == 0) { 1491c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 1492c1cad2e7SMatthew G. Knepley // Generate Petsc Plex 1493c1cad2e7SMatthew G. Knepley // Get all Nodes in model, record coordinates in a correctly formatted array 1494c1cad2e7SMatthew G. Knepley // Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array 1495c1cad2e7SMatthew G. Knepley // We need to uniformly refine the initial geometry to guarantee a valid mesh 1496c1cad2e7SMatthew G. Knepley 1497d5b43468SJose E. Roman // Calculate cell and vertex sizes 1498*5552b385SBrandon if (islite) { 1499*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 1500*5552b385SBrandon } else { 15019566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 1502*5552b385SBrandon } 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 1528*5552b385SBrandon if (islite) { 1529*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1530*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1531*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1532*5552b385SBrandon EGlite_free(fobjs); 1533*5552b385SBrandon EGlite_free(eobjs); 1534*5552b385SBrandon EGlite_free(nobjs); 1535*5552b385SBrandon } 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); 1542*5552b385SBrandon } 1543c1cad2e7SMatthew G. Knepley 1544c1cad2e7SMatthew G. Knepley // Remove DEGENERATE EDGES from Edge count 1545*5552b385SBrandon if (islite) { 1546*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1547*5552b385SBrandon } else { 15489566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1549*5552b385SBrandon } 1550*5552b385SBrandon 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 1556*5552b385SBrandon if (islite) { 1557*5552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1558*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 1559*5552b385SBrandon } else { 15609566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 15615f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 1562*5552b385SBrandon } 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 } 1572*5552b385SBrandon if (islite) { 1573*5552b385SBrandon EGlite_free(eobjs); 1574*5552b385SBrandon } else { 1575c1cad2e7SMatthew G. Knepley EG_free(eobjs); 1576*5552b385SBrandon } 1577c1cad2e7SMatthew G. Knepley 1578c1cad2e7SMatthew G. Knepley // Determine Number of Cells 1579*5552b385SBrandon if (islite) { 1580*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1581*5552b385SBrandon } else { 15829566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1583*5552b385SBrandon } 1584*5552b385SBrandon 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 1589*5552b385SBrandon if (islite) { 1590*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 1591*5552b385SBrandon } else { 15929566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 1593*5552b385SBrandon } 1594*5552b385SBrandon 1595c1cad2e7SMatthew G. Knepley for (int e = 0; e < Ne; ++e) { 1596c1cad2e7SMatthew G. Knepley ego edge = eobjs[e]; 1597c1cad2e7SMatthew G. Knepley 1598*5552b385SBrandon if (islite) { 1599*5552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1600*5552b385SBrandon } else { 16019566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1602*5552b385SBrandon } 1603ad540459SPierre Jolivet if (mtype != DEGENERATE) ++edgeTemp; 1604c1cad2e7SMatthew G. Knepley } 1605c1cad2e7SMatthew G. Knepley numCells += (2 * edgeTemp); 1606*5552b385SBrandon if (islite) { 1607*5552b385SBrandon EGlite_free(eobjs); 1608*5552b385SBrandon } else { 1609c1cad2e7SMatthew G. Knepley EG_free(eobjs); 1610c1cad2e7SMatthew G. Knepley } 1611*5552b385SBrandon } 1612*5552b385SBrandon if (islite) { 1613*5552b385SBrandon EGlite_free(fobjs); 1614*5552b385SBrandon } else { 1615c1cad2e7SMatthew G. Knepley EG_free(fobjs); 1616*5552b385SBrandon } 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 1641*5552b385SBrandon if (islite) { 1642*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1643*5552b385SBrandon } else { 16449566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1645*5552b385SBrandon } 1646c1cad2e7SMatthew G. Knepley 16479566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 1648*5552b385SBrandon 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 1656*5552b385SBrandon if (islite) { 1657*5552b385SBrandon PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 1658*5552b385SBrandon id = EGlite_indexBodyTopo(body, vertex); 1659*5552b385SBrandon } else { 16609566063dSJacob Faibussowitsch PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 16615f80ce2aSJacob Faibussowitsch id = EG_indexBodyTopo(body, vertex); 1662*5552b385SBrandon } 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 } 1668*5552b385SBrandon if (islite) { 1669*5552b385SBrandon EGlite_free(nobjs); 1670*5552b385SBrandon } else { 1671c1cad2e7SMatthew G. Knepley EG_free(nobjs); 1672*5552b385SBrandon } 1673c1cad2e7SMatthew G. Knepley 1674c1cad2e7SMatthew G. Knepley // Edge Midpoint Vertices on Current Body 1675*5552b385SBrandon if (islite) { 1676*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1677*5552b385SBrandon } else { 16789566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1679*5552b385SBrandon } 1680c1cad2e7SMatthew G. Knepley 16819566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 1682*5552b385SBrandon 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)); 1686*5552b385SBrandon 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 1695*5552b385SBrandon if (islite) { 1696*5552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1697*5552b385SBrandon } else { 16989566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1699*5552b385SBrandon } 1700ad540459SPierre Jolivet if (mtype == DEGENERATE) continue; 1701c1cad2e7SMatthew G. Knepley 1702*5552b385SBrandon if (islite) { 1703*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 1704*5552b385SBrandon } else { 17055f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 1706*5552b385SBrandon } 1707c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector 17089566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 1709*5552b385SBrandon 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 1712*5552b385SBrandon if (islite) { 1713*5552b385SBrandon PetscCall(EGlite_getRange(edge, range, &periodic)); 1714*5552b385SBrandon } else { 17159566063dSJacob Faibussowitsch PetscCall(EG_getRange(edge, range, &periodic)); 1716*5552b385SBrandon } 1717c1cad2e7SMatthew G. Knepley avgt[0] = (range[0] + range[1]) / 2.; 1718c1cad2e7SMatthew G. Knepley 1719*5552b385SBrandon if (islite) { 1720*5552b385SBrandon PetscCall(EGlite_evaluate(edge, avgt, cntrPnt)); 1721*5552b385SBrandon } else { 17229566063dSJacob Faibussowitsch PetscCall(EG_evaluate(edge, avgt, cntrPnt)); 1723*5552b385SBrandon } 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 } 1728*5552b385SBrandon if (islite) { 1729*5552b385SBrandon EGlite_free(eobjs); 1730*5552b385SBrandon } else { 1731c1cad2e7SMatthew G. Knepley EG_free(eobjs); 1732*5552b385SBrandon } 1733c1cad2e7SMatthew G. Knepley // Face Midpoint Vertices on Current Body 1734*5552b385SBrandon if (islite) { 1735*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1736*5552b385SBrandon } else { 17379566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1738*5552b385SBrandon } 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 1748*5552b385SBrandon if (islite) { 1749*5552b385SBrandon id = EGlite_indexBodyTopo(body, face); 1750*5552b385SBrandon PetscCall(EGlite_getRange(face, range, &peri)); 1751*5552b385SBrandon } else { 1752c1cad2e7SMatthew G. Knepley id = EG_indexBodyTopo(body, face); 17539566063dSJacob Faibussowitsch PetscCall(EG_getRange(face, range, &peri)); 1754*5552b385SBrandon } 1755c1cad2e7SMatthew G. Knepley 1756c1cad2e7SMatthew G. Knepley avgUV[0] = (range[0] + range[1]) / 2.; 1757c1cad2e7SMatthew G. Knepley avgUV[1] = (range[2] + range[3]) / 2.; 1758*5552b385SBrandon 1759*5552b385SBrandon if (islite) { 1760*5552b385SBrandon PetscCall(EGlite_evaluate(face, avgUV, cntrPnt)); 1761*5552b385SBrandon } else { 17629566063dSJacob Faibussowitsch PetscCall(EG_evaluate(face, avgUV, cntrPnt)); 1763*5552b385SBrandon } 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 } 1769*5552b385SBrandon if (islite) { 1770*5552b385SBrandon EGlite_free(fobjs); 1771*5552b385SBrandon } else { 1772c1cad2e7SMatthew G. Knepley EG_free(fobjs); 1773*5552b385SBrandon } 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 1776*5552b385SBrandon if (islite) { 1777*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1778*5552b385SBrandon } else { 17799566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1780*5552b385SBrandon } 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 1785*5552b385SBrandon if (islite) { 1786*5552b385SBrandon fID = EGlite_indexBodyTopo(body, face); 1787*5552b385SBrandon } else { 17885f80ce2aSJacob Faibussowitsch fID = EG_indexBodyTopo(body, face); 1789*5552b385SBrandon } 1790*5552b385SBrandon 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: 1794*5552b385SBrandon // 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 1799*5552b385SBrandon if (islite) { 1800*5552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses)); 1801*5552b385SBrandon } else { 18029566063dSJacob Faibussowitsch PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses)); 1803*5552b385SBrandon } 1804c1cad2e7SMatthew G. Knepley 1805*5552b385SBrandon 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 1809*5552b385SBrandon if (islite) { 1810*5552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1811*5552b385SBrandon } else { 18129566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1813*5552b385SBrandon } 1814*5552b385SBrandon 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 1819*5552b385SBrandon if (islite) { 1820*5552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1821*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 1822*5552b385SBrandon } else { 18239566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1824c1cad2e7SMatthew G. Knepley eid = EG_indexBodyTopo(body, edge); 1825*5552b385SBrandon } 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)); 1830*5552b385SBrandon 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 1835*5552b385SBrandon if (islite) { 1836*5552b385SBrandon PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1837*5552b385SBrandon } else { 18389566063dSJacob Faibussowitsch PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1839*5552b385SBrandon } 1840c1cad2e7SMatthew G. Knepley 18419371c9d4SSatish Balay if (eSenses[e] > 0) { 1842*5552b385SBrandon if (islite) { 1843*5552b385SBrandon startID = EGlite_indexBodyTopo(body, nobjs[0]); 1844*5552b385SBrandon endID = EGlite_indexBodyTopo(body, nobjs[1]); 1845*5552b385SBrandon } else { 18469371c9d4SSatish Balay startID = EG_indexBodyTopo(body, nobjs[0]); 18479371c9d4SSatish Balay endID = EG_indexBodyTopo(body, nobjs[1]); 1848*5552b385SBrandon } 1849*5552b385SBrandon } else { 1850*5552b385SBrandon if (islite) { 1851*5552b385SBrandon startID = EGlite_indexBodyTopo(body, nobjs[1]); 1852*5552b385SBrandon 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 } 1857*5552b385SBrandon } 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 } 1872*5552b385SBrandon if (islite) { 1873*5552b385SBrandon EGlite_free(fobjs); 1874*5552b385SBrandon } else { 1875c1cad2e7SMatthew G. Knepley EG_free(fobjs); 1876c1cad2e7SMatthew G. Knepley } 1877c1cad2e7SMatthew G. Knepley } 1878*5552b385SBrandon } 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)); 1892*5552b385SBrandon if (islite) { 1893*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSliteDestroy_Private)); 1894*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Model", (PetscObject)modelObj)); 1895*5552b385SBrandon } else { 1896*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSDestroy_Private)); 18979566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 1898*5552b385SBrandon } 18999566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj)); 1900c1cad2e7SMatthew G. Knepley 19019566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 19029566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context)); 1903*5552b385SBrandon 1904*5552b385SBrandon if (islite) { 1905*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSliteClose_Private)); 1906*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Context", (PetscObject)contextObj)); 1907*5552b385SBrandon } else { 1908*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSClose_Private)); 19099566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 1910*5552b385SBrandon } 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 1951*5552b385SBrandon if (islite) { 1952*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1953*5552b385SBrandon } else { 19549566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1955*5552b385SBrandon } 1956*5552b385SBrandon 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 1961*5552b385SBrandon if (islite) { 1962*5552b385SBrandon fID = EGlite_indexBodyTopo(body, face); 1963*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, LOOP, &Nl, &lobjs)); 1964*5552b385SBrandon } else { 19655f80ce2aSJacob Faibussowitsch fID = EG_indexBodyTopo(body, face); 19669566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, face, LOOP, &Nl, &lobjs)); 1967*5552b385SBrandon } 1968*5552b385SBrandon 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 1973*5552b385SBrandon if (islite) { 1974*5552b385SBrandon lid = EGlite_indexBodyTopo(body, loop); 1975*5552b385SBrandon } else { 19765f80ce2aSJacob Faibussowitsch lid = EG_indexBodyTopo(body, loop); 1977*5552b385SBrandon } 1978c1cad2e7SMatthew G. Knepley 1979*5552b385SBrandon PetscCheck(Nl == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %" PetscInt_FMT " has %" PetscInt_FMT " > 1 faces, which is not supported", lid, Nf); 1980*5552b385SBrandon 1981*5552b385SBrandon if (islite) { 1982*5552b385SBrandon PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1983*5552b385SBrandon } else { 19849566063dSJacob Faibussowitsch PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1985*5552b385SBrandon } 1986*5552b385SBrandon 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 1992*5552b385SBrandon if (islite) { 1993*5552b385SBrandon PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1994*5552b385SBrandon } else { 19959566063dSJacob Faibussowitsch PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1996*5552b385SBrandon } 1997*5552b385SBrandon 1998*5552b385SBrandon if (mtype == DEGENERATE) { continue; } 1999*5552b385SBrandon 2000*5552b385SBrandon if (islite) { 2001*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 2002*5552b385SBrandon } else { 20035f80ce2aSJacob Faibussowitsch eid = EG_indexBodyTopo(body, edge); 2004*5552b385SBrandon } 2005c1cad2e7SMatthew G. Knepley 2006c1cad2e7SMatthew G. Knepley // get relative offset from globalEdgeID Vector 20079566063dSJacob Faibussowitsch PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 2008*5552b385SBrandon 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 2011*5552b385SBrandon if (islite) { 2012*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, edge, NODE, &Nv, &nobjs)); 2013*5552b385SBrandon } else { 20149566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, edge, NODE, &Nv, &nobjs)); 2015*5552b385SBrandon } 2016*5552b385SBrandon 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 2021*5552b385SBrandon if (islite) { 2022*5552b385SBrandon vID = EGlite_indexBodyTopo(body, vertex); 2023*5552b385SBrandon } else { 20245f80ce2aSJacob Faibussowitsch vID = EG_indexBodyTopo(body, vertex); 2025*5552b385SBrandon } 2026*5552b385SBrandon 20279566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(bodyLabel, nStart + bodyVertexIndexStart + vID - 1, b)); 20289566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(vertexLabel, nStart + bodyVertexIndexStart + vID - 1, vID)); 2029c1cad2e7SMatthew G. Knepley } 2030*5552b385SBrandon if (islite) { 2031*5552b385SBrandon EGlite_free(nobjs); 2032*5552b385SBrandon } else { 2033c1cad2e7SMatthew G. Knepley EG_free(nobjs); 2034*5552b385SBrandon } 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 } 2058*5552b385SBrandon if (islite) { 2059*5552b385SBrandon EGlite_free(lobjs); 2060*5552b385SBrandon } else { 2061c1cad2e7SMatthew G. Knepley EG_free(lobjs); 2062*5552b385SBrandon } 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 } 2067*5552b385SBrandon if (islite) { 2068*5552b385SBrandon EGlite_free(fobjs); 2069*5552b385SBrandon } else { 2070c1cad2e7SMatthew G. Knepley EG_free(fobjs); 2071c1cad2e7SMatthew G. Knepley } 2072*5552b385SBrandon } 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 2085*5552b385SBrandon PetscErrorCode DMPlexCreateGeom_Tess_Internal(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 2086d71ae5a4SJacob Faibussowitsch { 2087*5552b385SBrandon /* 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; 2094*5552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 2095c1cad2e7SMatthew G. Knepley PetscHMapI pointIndexStartMap = NULL, triIndexStartMap = NULL, pTypeLabelMap = NULL, pIndexLabelMap = NULL; 2096c1cad2e7SMatthew G. Knepley PetscHMapI pBodyIndexLabelMap = NULL, triFaceIDLabelMap = NULL, triBodyIDLabelMap = NULL; 2097c1cad2e7SMatthew G. Knepley PetscInt dim = -1, cdim = -1, numCorners = 0, counter = 0; 2098c1cad2e7SMatthew G. Knepley PetscInt *cells = NULL; 2099c1cad2e7SMatthew G. Knepley const PetscInt *cone = NULL; 2100c1cad2e7SMatthew G. Knepley PetscReal *coords = NULL; 2101c1cad2e7SMatthew G. Knepley PetscMPIInt rank; 2102c1cad2e7SMatthew G. Knepley 2103c1cad2e7SMatthew G. Knepley PetscFunctionBeginUser; 21049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2105c5853193SPierre Jolivet if (rank == 0) { 2106c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 2107c1cad2e7SMatthew G. Knepley // Generate Petsc Plex from EGADSlite created Tessellation of geometry 2108c1cad2e7SMatthew G. Knepley // --------------------------------------------------------------------------------------------------- 2109c1cad2e7SMatthew G. Knepley 2110d5b43468SJose E. Roman // Calculate cell and vertex sizes 2111*5552b385SBrandon if (islite) { 2112*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 2113*5552b385SBrandon } else { 21149566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 2115*5552b385SBrandon } 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 */ 2126*5552b385SBrandon ego *tessArray; 2127c1cad2e7SMatthew G. Knepley 2128*5552b385SBrandon 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 */ 2145*5552b385SBrandon if (islite) { 2146*5552b385SBrandon PetscCall(EGlite_getBoundingBox(body, boundBox)); 2147*5552b385SBrandon } else { 21489566063dSJacob Faibussowitsch PetscCall(EG_getBoundingBox(body, boundBox)); 2149*5552b385SBrandon } 2150*5552b385SBrandon 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 2160*5552b385SBrandon if (islite) { 2161*5552b385SBrandon PetscCall(EGlite_makeTessBody(body, params, &tessArray[b])); 2162*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2163*5552b385SBrandon } else { 21649566063dSJacob Faibussowitsch PetscCall(EG_makeTessBody(body, params, &tessArray[b])); 21659566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2166*5552b385SBrandon } 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 // 2175*5552b385SBrandon if (islite) { 2176*5552b385SBrandon fID = EGlite_indexBodyTopo(body, face); 2177*5552b385SBrandon } else { 2178c1cad2e7SMatthew G. Knepley fID = EG_indexBodyTopo(body, face); 2179*5552b385SBrandon } 2180c1cad2e7SMatthew G. Knepley 2181c1cad2e7SMatthew G. Knepley // Checkout the Surface Tessellation // 2182*5552b385SBrandon if (islite) { 2183*5552b385SBrandon PetscCall(EGlite_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 2184*5552b385SBrandon } else { 21859566063dSJacob Faibussowitsch PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 2186*5552b385SBrandon } 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 2195*5552b385SBrandon if (islite) { 2196*5552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, p + 1, &global)); 2197*5552b385SBrandon } else { 21989566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global)); 2199*5552b385SBrandon } 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 } 2205*5552b385SBrandon if (islite) { 2206*5552b385SBrandon EGlite_free(fobjs); 2207*5552b385SBrandon } else { 2208c1cad2e7SMatthew G. Knepley EG_free(fobjs); 2209*5552b385SBrandon } 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)); 2231*5552b385SBrandon 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 2234*5552b385SBrandon if (islite) { 2235*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2236*5552b385SBrandon } else { 22379566063dSJacob Faibussowitsch PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2238*5552b385SBrandon } 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 */ 2248*5552b385SBrandon if (islite) { 2249*5552b385SBrandon fID = EGlite_indexBodyTopo(body, face); 2250*5552b385SBrandon } else { 2251c1cad2e7SMatthew G. Knepley fID = EG_indexBodyTopo(body, face); 2252*5552b385SBrandon } 2253c1cad2e7SMatthew G. Knepley 2254c1cad2e7SMatthew G. Knepley /* Checkout the Surface Tessellation */ 2255*5552b385SBrandon if (islite) { 2256*5552b385SBrandon PetscCall(EGlite_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 2257*5552b385SBrandon } else { 22589566063dSJacob Faibussowitsch PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 2259*5552b385SBrandon } 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 2267*5552b385SBrandon if (islite) { 2268*5552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, p + 1, &global)); 2269*5552b385SBrandon } else { 22709566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global)); 2271*5552b385SBrandon } 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 2295*5552b385SBrandon if (islite) { 2296*5552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global)); 2297*5552b385SBrandon } else { 22989566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global)); 2299*5552b385SBrandon } 2300c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 0] = global - 1 + pointIndexStart; 2301c1cad2e7SMatthew G. Knepley 2302*5552b385SBrandon if (islite) { 2303*5552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA)); 2304*5552b385SBrandon } else { 23059566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA)); 2306*5552b385SBrandon } 2307c1cad2e7SMatthew G. Knepley cells[(counter * 3) + 1] = globalA - 1 + pointIndexStart; 2308c1cad2e7SMatthew G. Knepley 2309*5552b385SBrandon if (islite) { 2310*5552b385SBrandon PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB)); 2311*5552b385SBrandon } else { 23129566063dSJacob Faibussowitsch PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB)); 2313*5552b385SBrandon } 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 } 2325*5552b385SBrandon if (islite) { 2326*5552b385SBrandon EGlite_free(fobjs); 2327*5552b385SBrandon } else { 2328c1cad2e7SMatthew G. Knepley EG_free(fobjs); 2329c1cad2e7SMatthew G. Knepley } 2330c1cad2e7SMatthew G. Knepley } 2331*5552b385SBrandon PetscCall(PetscFree(tessArray)); 2332*5552b385SBrandon } 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)); 2344*5552b385SBrandon if (islite) { 2345*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSliteDestroy_Private)); 2346*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Model", (PetscObject)modelObj)); 2347*5552b385SBrandon } else { 2348*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSDestroy_Private)); 23499566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 2350*5552b385SBrandon } 23519566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&modelObj)); 2352c1cad2e7SMatthew G. Knepley 23539566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 23549566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(contextObj, context)); 2355*5552b385SBrandon 2356*5552b385SBrandon if (islite) { 2357*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSliteClose_Private)); 2358*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Context", (PetscObject)contextObj)); 2359*5552b385SBrandon } else { 2360*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSClose_Private)); 23619566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 2362*5552b385SBrandon } 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)); 2391*5552b385SBrandon 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)); 2395*5552b385SBrandon 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)); 2399*5552b385SBrandon 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)); 2438*5552b385SBrandon 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)); 2442*5552b385SBrandon 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 2466*5552b385SBrandon /*@C 2467*5552b385SBrandon 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 @*/ 2478*5552b385SBrandon PetscErrorCode DMPlexInflateToGeomModelUseXYZ(DM dm) 2479d71ae5a4SJacob Faibussowitsch { 2480c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS) 2481c1cad2e7SMatthew G. Knepley /* EGADS Variables */ 2482*5552b385SBrandon ego model, geom, body, face, edge, vertex; 2483c1cad2e7SMatthew G. Knepley ego *bodies; 2484c1cad2e7SMatthew G. Knepley int Nb, oclass, mtype, *senses; 2485*5552b385SBrandon double result[4]; 2486c1cad2e7SMatthew G. Knepley /* PETSc Variables */ 2487c1cad2e7SMatthew G. Knepley DM cdm; 2488c1cad2e7SMatthew G. Knepley PetscContainer modelObj; 2489c1cad2e7SMatthew G. Knepley DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 2490c1cad2e7SMatthew G. Knepley Vec coordinates; 2491c1cad2e7SMatthew G. Knepley PetscScalar *coords; 2492c1cad2e7SMatthew G. Knepley PetscInt bodyID, faceID, edgeID, vertexID; 2493c1cad2e7SMatthew G. Knepley PetscInt cdim, d, vStart, vEnd, v; 2494*5552b385SBrandon PetscBool islite = PETSC_FALSE; 2495c1cad2e7SMatthew G. Knepley #endif 2496c1cad2e7SMatthew G. Knepley 2497c1cad2e7SMatthew G. Knepley PetscFunctionBegin; 2498c1cad2e7SMatthew G. Knepley #if defined(PETSC_HAVE_EGADS) 24999566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 2500*5552b385SBrandon if (!modelObj) { 2501*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 2502*5552b385SBrandon islite = PETSC_TRUE; 2503*5552b385SBrandon } 25043ba16761SJacob Faibussowitsch if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 25059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 25069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 25079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 25089566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 25099566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 25109566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 25119566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 2512c1cad2e7SMatthew G. Knepley 25139566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 2514*5552b385SBrandon 2515*5552b385SBrandon if (islite) { 2516*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2517*5552b385SBrandon } else { 25189566063dSJacob Faibussowitsch PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2519*5552b385SBrandon } 2520c1cad2e7SMatthew G. Knepley 25219566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 25229566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 2523c1cad2e7SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 2524c1cad2e7SMatthew G. Knepley PetscScalar *vcoords; 2525c1cad2e7SMatthew G. Knepley 25269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 25279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 25289566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 25299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 2530c1cad2e7SMatthew G. Knepley 2531*5552b385SBrandon PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bodyID, Nb); 2532*5552b385SBrandon body = bodies[bodyID]; 2533*5552b385SBrandon 2534*5552b385SBrandon PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 2535*5552b385SBrandon if (vertexID > 0) { 2536*5552b385SBrandon if (islite) { 2537*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 2538*5552b385SBrandon PetscCall(EGlite_evaluate(vertex, NULL, result)); 2539*5552b385SBrandon } else { 2540*5552b385SBrandon PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 2541*5552b385SBrandon PetscCall(EG_evaluate(vertex, NULL, result)); 2542*5552b385SBrandon } 2543*5552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2544*5552b385SBrandon } else if (edgeID > 0) { 2545*5552b385SBrandon /* Snap to EDGE at nearest location */ 2546*5552b385SBrandon double params[1]; 2547*5552b385SBrandon if (islite) { 2548*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 2549*5552b385SBrandon PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 2550*5552b385SBrandon } // Get (x,y,z) of nearest point on EDGE 2551*5552b385SBrandon else { 2552*5552b385SBrandon PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 2553*5552b385SBrandon PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 2554*5552b385SBrandon } 2555*5552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2556*5552b385SBrandon } else if (faceID > 0) { 2557*5552b385SBrandon /* Snap to FACE at nearest location */ 2558*5552b385SBrandon double params[2]; 2559*5552b385SBrandon if (islite) { 2560*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 2561*5552b385SBrandon PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 2562*5552b385SBrandon } // Get (x,y,z) of nearest point on FACE 2563*5552b385SBrandon else { 2564*5552b385SBrandon PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 2565*5552b385SBrandon PetscCall(EG_invEvaluate(face, vcoords, params, result)); 2566*5552b385SBrandon } 2567*5552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2568*5552b385SBrandon } 2569*5552b385SBrandon } 2570*5552b385SBrandon PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 2571*5552b385SBrandon /* Clear out global coordinates */ 2572*5552b385SBrandon PetscCall(VecDestroy(&dm->coordinates[0].x)); 2573*5552b385SBrandon #endif 2574*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 2575*5552b385SBrandon } 2576*5552b385SBrandon 2577*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 2578*5552b385SBrandon // This replaces the model in-place 2579*5552b385SBrandon PetscErrorCode ConvertGeomModelToAllBSplines(PetscBool islite, ego *model) 2580*5552b385SBrandon { 2581*5552b385SBrandon /* EGADS/EGADSlite Variables */ 2582*5552b385SBrandon ego context = NULL, geom, *bodies, *fobjs; 2583*5552b385SBrandon int oclass, mtype; 2584*5552b385SBrandon int *senses; 2585*5552b385SBrandon int Nb, Nf; 2586*5552b385SBrandon 2587*5552b385SBrandon PetscFunctionBegin; 2588*5552b385SBrandon // Get the number of bodies and body objects in the model 2589*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2590*5552b385SBrandon else PetscCallEGADS(EG_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2591*5552b385SBrandon 2592*5552b385SBrandon // Get all Faces on the body <-- Only working with 1 body at the moment. 2593*5552b385SBrandon ego body = bodies[0]; 2594*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 2595*5552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 2596*5552b385SBrandon ego newGeom[Nf]; 2597*5552b385SBrandon ego newFaces[Nf]; 2598*5552b385SBrandon 2599*5552b385SBrandon // Convert the 1st Face to a BSpline Geometry 2600*5552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 2601*5552b385SBrandon ego face = fobjs[ii]; 2602*5552b385SBrandon ego gRef, gPrev, gNext, *lobjs; 2603*5552b385SBrandon int goclass, gmtype, *gpinfo; 2604*5552b385SBrandon int Nl, *lsenses; 2605*5552b385SBrandon double *gprv; 2606*5552b385SBrandon char *gClass = (char *)"", *gType = (char *)""; 2607*5552b385SBrandon 2608*5552b385SBrandon /* Shape Optimization is NOT available for EGADSlite geometry files. */ 2609*5552b385SBrandon /* Note :: islite options are left below in case future versions of EGADSlite includes this capability */ 2610*5552b385SBrandon 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"); 2611*5552b385SBrandon 2612*5552b385SBrandon if (islite) { 2613*5552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_ 2614*5552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info 2615*5552b385SBrandon PetscCallEGADS(EGlite_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 2616*5552b385SBrandon } // Get geometry info 2617*5552b385SBrandon else { 2618*5552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_ 2619*5552b385SBrandon PetscCallEGADS(EG_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info 2620*5552b385SBrandon PetscCallEGADS(EG_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 2621*5552b385SBrandon } // Get geometry info 2622*5552b385SBrandon 2623*5552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType)); // Decode Geometry integers 2624*5552b385SBrandon 2625*5552b385SBrandon // Convert current FACE to a BSpline Surface 2626*5552b385SBrandon ego bspline; 2627*5552b385SBrandon ego bRef, bPrev, bNext; 2628*5552b385SBrandon int boclass, bmtype, *bpinfo; 2629*5552b385SBrandon double *bprv; 2630*5552b385SBrandon char *bClass = (char *)"", *bType = (char *)""; 2631*5552b385SBrandon 2632*5552b385SBrandon PetscCallEGADS(EG_convertToBSpline, (face, &bspline)); // Does not have an EGlite_ version 2633*5552b385SBrandon 2634*5552b385SBrandon if (islite) { 2635*5552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info 2636*5552b385SBrandon PetscCallEGADS(EGlite_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2637*5552b385SBrandon } // Get geometry info 2638*5552b385SBrandon else { 2639*5552b385SBrandon PetscCallEGADS(EG_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info 2640*5552b385SBrandon PetscCallEGADS(EG_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2641*5552b385SBrandon } // Get geometry info 2642*5552b385SBrandon 2643*5552b385SBrandon PetscCall(DMPlex_EGADS_GeomDecode_Internal(boclass, bmtype, &bClass, &bType)); // Decode Geometry integers 2644*5552b385SBrandon 2645*5552b385SBrandon // Get Context from FACE 2646*5552b385SBrandon context = NULL; 2647*5552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version 2648*5552b385SBrandon 2649*5552b385SBrandon // Silence WARNING Regarding OPENCASCADE 7.5 2650*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 0)); 2651*5552b385SBrandon else PetscCallEGADS(EG_setOutLevel, (context, 0)); 2652*5552b385SBrandon 2653*5552b385SBrandon ego newgeom; 2654*5552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version 2655*5552b385SBrandon 2656*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (bspline)); 2657*5552b385SBrandon 2658*5552b385SBrandon // Create new FACE based on new SURFACE geometry 2659*5552b385SBrandon double data[4]; 2660*5552b385SBrandon int periodic; 2661*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 2662*5552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 2663*5552b385SBrandon 2664*5552b385SBrandon ego newface; 2665*5552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version 2666*5552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newgeom)); 2667*5552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newface)); 2668*5552b385SBrandon newFaces[ii] = newface; 2669*5552b385SBrandon newGeom[ii] = newgeom; 2670*5552b385SBrandon 2671*5552b385SBrandon // Reinstate WARNING Regarding OPENCASCADE 7.5 2672*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 1)); 2673*5552b385SBrandon else PetscCallEGADS(EG_setOutLevel, (context, 1)); 2674*5552b385SBrandon } 2675*5552b385SBrandon 2676*5552b385SBrandon // Sew New Faces together to get a new model 2677*5552b385SBrandon ego newmodel; 2678*5552b385SBrandon PetscCallEGADS(EG_sewFaces, (Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version 2679*5552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 2680*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[ii])); 2681*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[ii])); 2682*5552b385SBrandon } 2683*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (*model)); 2684*5552b385SBrandon *model = newmodel; 2685*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 2686*5552b385SBrandon } 2687*5552b385SBrandon #endif 2688*5552b385SBrandon 2689*5552b385SBrandon /*@C 2690*5552b385SBrandon DMPlexCreateGeomFromFile - Create a `DMPLEX` mesh from an EGADS, IGES, or STEP file. 2691*5552b385SBrandon 2692*5552b385SBrandon Collective 2693*5552b385SBrandon 2694*5552b385SBrandon Input Parameters: 2695*5552b385SBrandon + comm - The MPI communicator 2696*5552b385SBrandon . filename - The name of the EGADS, IGES, or STEP file 2697*5552b385SBrandon - islite - Flag for EGADSlite support 2698*5552b385SBrandon 2699*5552b385SBrandon Output Parameter: 2700*5552b385SBrandon . dm - The `DM` object representing the mesh 2701*5552b385SBrandon 2702*5552b385SBrandon Level: beginner 2703*5552b385SBrandon 2704*5552b385SBrandon .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`, `DMPlexCreateEGADSliteFromFile()` 2705*5552b385SBrandon @*/ 2706*5552b385SBrandon PetscErrorCode DMPlexCreateGeomFromFile(MPI_Comm comm, const char filename[], DM *dm, PetscBool islite) 2707*5552b385SBrandon { 2708*5552b385SBrandon /* PETSc Variables */ 2709*5552b385SBrandon PetscMPIInt rank; 2710*5552b385SBrandon PetscBool printModel = PETSC_FALSE, tessModel = PETSC_FALSE, newModel = PETSC_FALSE; 2711*5552b385SBrandon PetscBool shapeOpt = PETSC_FALSE; 2712*5552b385SBrandon 2713*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 2714*5552b385SBrandon ego context = NULL, model = NULL; 2715*5552b385SBrandon #endif 2716*5552b385SBrandon 2717*5552b385SBrandon PetscFunctionBegin; 2718*5552b385SBrandon PetscAssertPointer(filename, 2); 2719*5552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_print_model", &printModel, NULL)); 2720*5552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_tess_model", &tessModel, NULL)); 2721*5552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_new_model", &newModel, NULL)); 2722*5552b385SBrandon PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_shape_opt", &shapeOpt, NULL)); 2723*5552b385SBrandon PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2724*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 2725*5552b385SBrandon if (rank == 0) { 2726*5552b385SBrandon /* EGADSlite files cannot be used for Shape Optimization Work. It lacks the ability to make new geometry. */ 2727*5552b385SBrandon /* Must use EGADS, STEP, IGES or BRep files to perform this work. */ 2728*5552b385SBrandon if (islite) { 2729*5552b385SBrandon PetscCallEGADS(EGlite_open, (&context)); 2730*5552b385SBrandon PetscCallEGADS(EGlite_loadModel, (context, 0, filename, &model)); 2731*5552b385SBrandon if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model)); 2732*5552b385SBrandon if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite)); 2733*5552b385SBrandon } else { 2734*5552b385SBrandon PetscCallEGADS(EG_open, (&context)); 2735*5552b385SBrandon PetscCallEGADS(EG_loadModel, (context, 0, filename, &model)); 2736*5552b385SBrandon if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model)); 2737*5552b385SBrandon if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite)); 2738*5552b385SBrandon } 2739*5552b385SBrandon } 2740*5552b385SBrandon if (tessModel) PetscCall(DMPlexCreateGeom_Tess_Internal(comm, context, model, dm, islite)); 2741*5552b385SBrandon else if (newModel) PetscCall(DMPlexCreateGeom_Internal(comm, context, model, dm, islite)); 2742*5552b385SBrandon else { 2743*5552b385SBrandon PetscCall(DMPlexCreateGeom(comm, context, model, dm, islite)); 2744*5552b385SBrandon } 2745*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 2746*5552b385SBrandon #else 2747*5552b385SBrandon SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 2748*5552b385SBrandon #endif 2749*5552b385SBrandon } 2750*5552b385SBrandon 2751*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 2752*5552b385SBrandon /*@C 2753*5552b385SBrandon DMPlex_Surface_Grad - Exposes the Geometry's Control Points and Weights and Calculates the Mesh Topology Boundary Nodes Gradient 2754*5552b385SBrandon with respect the associated geometry's Control Points and Weights. 2755*5552b385SBrandon 2756*5552b385SBrandon // ----- Depreciated ---- See DMPlexGeomDataAndGrads ------ // 2757*5552b385SBrandon 2758*5552b385SBrandon Collective 2759*5552b385SBrandon 2760*5552b385SBrandon Input Parameters: 2761*5552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 2762*5552b385SBrandon 2763*5552b385SBrandon Output Parameter: 2764*5552b385SBrandon . 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 2765*5552b385SBrandon 2766*5552b385SBrandon Level: intermediate 2767*5552b385SBrandon 2768*5552b385SBrandon .seealso: 2769*5552b385SBrandon @*/ 2770*5552b385SBrandon PetscErrorCode DMPlex_Surface_Grad(DM dm) 2771*5552b385SBrandon { 2772*5552b385SBrandon ego model, geom, *bodies, *fobjs; 2773*5552b385SBrandon PetscContainer modelObj; 2774*5552b385SBrandon int oclass, mtype, *senses; 2775*5552b385SBrandon int Nb, Nf; 2776*5552b385SBrandon PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 2777*5552b385SBrandon PetscHMapI pointSurfGradRow_Start = NULL; 2778*5552b385SBrandon Mat pointSurfGrad; 2779*5552b385SBrandon IS faceLabelValues, edgeLabelValues, vertexLabelValues; 2780*5552b385SBrandon PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 2781*5552b385SBrandon PetscBool islite = PETSC_FALSE; 2782*5552b385SBrandon 2783*5552b385SBrandon PetscFunctionBegin; 2784*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 2785*5552b385SBrandon if (!modelObj) { 2786*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 2787*5552b385SBrandon islite = PETSC_TRUE; 2788*5552b385SBrandon 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"); 2789*5552b385SBrandon } 2790*5552b385SBrandon 2791*5552b385SBrandon // Get attached EGADS model (pointer) 2792*5552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 2793*5552b385SBrandon 2794*5552b385SBrandon // Get the bodies in the model 2795*5552b385SBrandon if (islite) { 2796*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2797*5552b385SBrandon } else { 2798*5552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2799*5552b385SBrandon } 2800*5552b385SBrandon 2801*5552b385SBrandon ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 2802*5552b385SBrandon 2803*5552b385SBrandon // Get the total number of FACEs in the model 2804*5552b385SBrandon if (islite) { 2805*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2806*5552b385SBrandon } else { 2807*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2808*5552b385SBrandon } 2809*5552b385SBrandon 2810*5552b385SBrandon // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 2811*5552b385SBrandon // This will provide the total number of DMPlex points on the boundary of the geometry 2812*5552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 2813*5552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 2814*5552b385SBrandon 2815*5552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 2816*5552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 2817*5552b385SBrandon 2818*5552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 2819*5552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 2820*5552b385SBrandon 2821*5552b385SBrandon const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 2822*5552b385SBrandon PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 2823*5552b385SBrandon PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 2824*5552b385SBrandon PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 2825*5552b385SBrandon 2826*5552b385SBrandon // Get the points associated with each FACE, EDGE and VERTEX label in the DM 2827*5552b385SBrandon PetscInt totalNumPoints = 0; 2828*5552b385SBrandon for (int ii = 0; ii < faceLabelSize; ++ii) { 2829*5552b385SBrandon // Cycle through FACE labels 2830*5552b385SBrandon PetscInt size; 2831*5552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[ii], &size)); 2832*5552b385SBrandon totalNumPoints += size; 2833*5552b385SBrandon } 2834*5552b385SBrandon PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 2835*5552b385SBrandon PetscCall(ISDestroy(&faceLabelValues)); 2836*5552b385SBrandon 2837*5552b385SBrandon for (int ii = 0; ii < edgeLabelSize; ++ii) { 2838*5552b385SBrandon // Cycle Through EDGE Labels 2839*5552b385SBrandon PetscInt size; 2840*5552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[ii], &size)); 2841*5552b385SBrandon totalNumPoints += size; 2842*5552b385SBrandon } 2843*5552b385SBrandon PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 2844*5552b385SBrandon PetscCall(ISDestroy(&edgeLabelValues)); 2845*5552b385SBrandon 2846*5552b385SBrandon for (int ii = 0; ii < vertexLabelSize; ++ii) { 2847*5552b385SBrandon // Cycle Through VERTEX Labels 2848*5552b385SBrandon PetscInt size; 2849*5552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 2850*5552b385SBrandon totalNumPoints += size; 2851*5552b385SBrandon } 2852*5552b385SBrandon PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 2853*5552b385SBrandon PetscCall(ISDestroy(&vertexLabelValues)); 2854*5552b385SBrandon 2855*5552b385SBrandon int maxNumCPs = 0; 2856*5552b385SBrandon int totalNumCPs = 0; 2857*5552b385SBrandon ego bRef, bPrev, bNext, fgeom, *lobjs; 2858*5552b385SBrandon int id, boclass, bmtype, *bpinfo; 2859*5552b385SBrandon int foclass, fmtype, Nl, *lsenses; 2860*5552b385SBrandon double *bprv; 2861*5552b385SBrandon double fdata[4]; 2862*5552b385SBrandon 2863*5552b385SBrandon // Create Hash Tables 2864*5552b385SBrandon PetscInt cntr = 0, wcntr = 0; 2865*5552b385SBrandon PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 2866*5552b385SBrandon PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 2867*5552b385SBrandon 2868*5552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 2869*5552b385SBrandon // Need to get the maximum number of Control Points defining the FACEs 2870*5552b385SBrandon ego face = fobjs[ii]; 2871*5552b385SBrandon int maxNumCPs_temp; 2872*5552b385SBrandon 2873*5552b385SBrandon if (islite) { 2874*5552b385SBrandon id = EGlite_indexBodyTopo(body, face); 2875*5552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2876*5552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2877*5552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2878*5552b385SBrandon } else { 2879*5552b385SBrandon id = EG_indexBodyTopo(body, face); 2880*5552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2881*5552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2882*5552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2883*5552b385SBrandon } 2884*5552b385SBrandon 2885*5552b385SBrandon maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 2886*5552b385SBrandon totalNumCPs += bpinfo[2] * bpinfo[5]; 2887*5552b385SBrandon 2888*5552b385SBrandon if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 2889*5552b385SBrandon } 2890*5552b385SBrandon 2891*5552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 2892*5552b385SBrandon PetscInt cpCoordDataLength = 3 * totalNumCPs; 2893*5552b385SBrandon PetscInt wDataLength = totalNumCPs; 2894*5552b385SBrandon cpCoordDataLengthPtr = &cpCoordDataLength; 2895*5552b385SBrandon wDataLengthPtr = &wDataLength; 2896*5552b385SBrandon PetscScalar *cntrlPtCoords, *cntrlPtWeights; 2897*5552b385SBrandon PetscMalloc1(cpCoordDataLength, &cntrlPtCoords); 2898*5552b385SBrandon PetscMalloc1(wDataLength, &cntrlPtWeights); 2899*5552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 2900*5552b385SBrandon // Need to Populate Control Point Coordinates and Weight Vectors 2901*5552b385SBrandon ego face = fobjs[ii]; 2902*5552b385SBrandon PetscHashIter hashKeyIter, wHashKeyIter; 2903*5552b385SBrandon PetscBool hashKeyFound, wHashKeyFound; 2904*5552b385SBrandon 2905*5552b385SBrandon if (islite) { 2906*5552b385SBrandon id = EGlite_indexBodyTopo(body, face); 2907*5552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2908*5552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2909*5552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2910*5552b385SBrandon } else { 2911*5552b385SBrandon id = EG_indexBodyTopo(body, face); 2912*5552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2913*5552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2914*5552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2915*5552b385SBrandon } 2916*5552b385SBrandon 2917*5552b385SBrandon // Store Face ID to 1st Row of Control Point Vector 2918*5552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 2919*5552b385SBrandon 2920*5552b385SBrandon if (!hashKeyFound) { PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); } 2921*5552b385SBrandon 2922*5552b385SBrandon int offsetCoord = bpinfo[3] + bpinfo[6]; 2923*5552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 2924*5552b385SBrandon cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 2925*5552b385SBrandon cntr += 1; 2926*5552b385SBrandon } 2927*5552b385SBrandon 2928*5552b385SBrandon // Store Face ID to 1st Row of Control Point Weight Vector 2929*5552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 2930*5552b385SBrandon 2931*5552b385SBrandon if (!wHashKeyFound) { PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); } 2932*5552b385SBrandon 2933*5552b385SBrandon int offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 2934*5552b385SBrandon for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 2935*5552b385SBrandon cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 2936*5552b385SBrandon wcntr += 1; 2937*5552b385SBrandon } 2938*5552b385SBrandon } 2939*5552b385SBrandon 2940*5552b385SBrandon // Attach Control Point and Weight Data to DM 2941*5552b385SBrandon { 2942*5552b385SBrandon PetscContainer cpOrgObj, cpCoordObj, cpCoordLengthObj; 2943*5552b385SBrandon PetscContainer wOrgObj, wValObj, wDataLengthObj; 2944*5552b385SBrandon 2945*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 2946*5552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 2947*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 2948*5552b385SBrandon PetscCall(PetscContainerDestroy(&cpOrgObj)); 2949*5552b385SBrandon 2950*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordObj)); 2951*5552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordObj, cntrlPtCoords)); 2952*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cpCoordObj)); 2953*5552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordObj)); 2954*5552b385SBrandon 2955*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 2956*5552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 2957*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 2958*5552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 2959*5552b385SBrandon 2960*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 2961*5552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 2962*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 2963*5552b385SBrandon PetscCall(PetscContainerDestroy(&wOrgObj)); 2964*5552b385SBrandon 2965*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wValObj)); 2966*5552b385SBrandon PetscCall(PetscContainerSetPointer(wValObj, cntrlPtWeights)); 2967*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)wValObj)); 2968*5552b385SBrandon PetscCall(PetscContainerDestroy(&wValObj)); 2969*5552b385SBrandon 2970*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 2971*5552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 2972*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 2973*5552b385SBrandon PetscCall(PetscContainerDestroy(&wDataLengthObj)); 2974*5552b385SBrandon } 2975*5552b385SBrandon 2976*5552b385SBrandon // Define Matrix to store Surface Gradient information dx_i/dCPj_i 2977*5552b385SBrandon PetscInt gcntr = 0; 2978*5552b385SBrandon const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 2979*5552b385SBrandon const PetscInt colSize = 4 * Nf; 2980*5552b385SBrandon 2981*5552b385SBrandon // Create Point Surface Gradient Matrix 2982*5552b385SBrandon MatCreate(PETSC_COMM_WORLD, &pointSurfGrad); 2983*5552b385SBrandon MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize); 2984*5552b385SBrandon MatSetType(pointSurfGrad, MATAIJ); 2985*5552b385SBrandon MatSetUp(pointSurfGrad); 2986*5552b385SBrandon 2987*5552b385SBrandon // Create Hash Table to store Point's stare row in surfaceGrad[][] 2988*5552b385SBrandon PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 2989*5552b385SBrandon 2990*5552b385SBrandon // Get Coordinates for the DMPlex point 2991*5552b385SBrandon DM cdm; 2992*5552b385SBrandon PetscInt dE, Nv; 2993*5552b385SBrandon Vec coordinatesLocal; 2994*5552b385SBrandon PetscScalar *coords = NULL; 2995*5552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 2996*5552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &dE)); 2997*5552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 2998*5552b385SBrandon 2999*5552b385SBrandon // CYCLE THROUGH FACEs 3000*5552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 3001*5552b385SBrandon ego face = fobjs[ii]; 3002*5552b385SBrandon ego *eobjs, *nobjs; 3003*5552b385SBrandon PetscInt fid, Ne, Nn; 3004*5552b385SBrandon DMLabel faceLabel, edgeLabel, nodeLabel; 3005*5552b385SBrandon PetscHMapI currFaceUniquePoints = NULL; 3006*5552b385SBrandon IS facePoints, edgePoints, nodePoints; 3007*5552b385SBrandon const PetscInt *fIndices, *eIndices, *nIndices; 3008*5552b385SBrandon PetscInt fSize, eSize, nSize; 3009*5552b385SBrandon PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 3010*5552b385SBrandon PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 3011*5552b385SBrandon PetscInt cfCntr = 0; 3012*5552b385SBrandon 3013*5552b385SBrandon // Get Geometry Object for the Current FACE 3014*5552b385SBrandon if (islite) { 3015*5552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3016*5552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3017*5552b385SBrandon } else { 3018*5552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3019*5552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3020*5552b385SBrandon } 3021*5552b385SBrandon 3022*5552b385SBrandon // Get all EDGE and NODE objects attached to the current FACE 3023*5552b385SBrandon if (islite) { 3024*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3025*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3026*5552b385SBrandon } else { 3027*5552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3028*5552b385SBrandon PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3029*5552b385SBrandon } 3030*5552b385SBrandon 3031*5552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 3032*5552b385SBrandon if (islite) { 3033*5552b385SBrandon fid = EGlite_indexBodyTopo(body, face); 3034*5552b385SBrandon } else { 3035*5552b385SBrandon fid = EG_indexBodyTopo(body, face); 3036*5552b385SBrandon } 3037*5552b385SBrandon 3038*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 3039*5552b385SBrandon PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 3040*5552b385SBrandon PetscCall(ISGetIndices(facePoints, &fIndices)); 3041*5552b385SBrandon PetscCall(ISGetSize(facePoints, &fSize)); 3042*5552b385SBrandon 3043*5552b385SBrandon PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 3044*5552b385SBrandon 3045*5552b385SBrandon for (int jj = 0; jj < fSize; ++jj) { 3046*5552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 3047*5552b385SBrandon 3048*5552b385SBrandon if (!fHashKeyFound) { 3049*5552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 3050*5552b385SBrandon cfCntr += 1; 3051*5552b385SBrandon } 3052*5552b385SBrandon 3053*5552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 3054*5552b385SBrandon 3055*5552b385SBrandon if (!pHashKeyFound) { 3056*5552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 3057*5552b385SBrandon gcntr += 3 * maxNumCPs; 3058*5552b385SBrandon } 3059*5552b385SBrandon } 3060*5552b385SBrandon PetscCall(ISRestoreIndices(facePoints, &fIndices)); 3061*5552b385SBrandon PetscCall(ISDestroy(&facePoints)); 3062*5552b385SBrandon 3063*5552b385SBrandon // 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. 3064*5552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 3065*5552b385SBrandon ego edge = eobjs[jj]; 3066*5552b385SBrandon PetscBool containLabelValue; 3067*5552b385SBrandon 3068*5552b385SBrandon if (islite) { 3069*5552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 3070*5552b385SBrandon } else { 3071*5552b385SBrandon id = EG_indexBodyTopo(body, edge); 3072*5552b385SBrandon } 3073*5552b385SBrandon 3074*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 3075*5552b385SBrandon PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 3076*5552b385SBrandon 3077*5552b385SBrandon if (containLabelValue) { 3078*5552b385SBrandon PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 3079*5552b385SBrandon PetscCall(ISGetIndices(edgePoints, &eIndices)); 3080*5552b385SBrandon PetscCall(ISGetSize(edgePoints, &eSize)); 3081*5552b385SBrandon 3082*5552b385SBrandon for (int kk = 0; kk < eSize; ++kk) { 3083*5552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 3084*5552b385SBrandon 3085*5552b385SBrandon if (!eHashKeyFound) { 3086*5552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 3087*5552b385SBrandon cfCntr += 1; 3088*5552b385SBrandon } 3089*5552b385SBrandon 3090*5552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 3091*5552b385SBrandon 3092*5552b385SBrandon if (!pHashKeyFound) { 3093*5552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 3094*5552b385SBrandon gcntr += 3 * maxNumCPs; 3095*5552b385SBrandon } 3096*5552b385SBrandon } 3097*5552b385SBrandon PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 3098*5552b385SBrandon PetscCall(ISDestroy(&edgePoints)); 3099*5552b385SBrandon } 3100*5552b385SBrandon } 3101*5552b385SBrandon 3102*5552b385SBrandon // 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. 3103*5552b385SBrandon for (int jj = 0; jj < Nn; ++jj) { 3104*5552b385SBrandon ego node = nobjs[jj]; 3105*5552b385SBrandon 3106*5552b385SBrandon if (islite) { 3107*5552b385SBrandon id = EGlite_indexBodyTopo(body, node); 3108*5552b385SBrandon } else { 3109*5552b385SBrandon id = EG_indexBodyTopo(body, node); 3110*5552b385SBrandon } 3111*5552b385SBrandon 3112*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 3113*5552b385SBrandon PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 3114*5552b385SBrandon PetscCall(ISGetIndices(nodePoints, &nIndices)); 3115*5552b385SBrandon PetscCall(ISGetSize(nodePoints, &nSize)); 3116*5552b385SBrandon 3117*5552b385SBrandon for (int kk = 0; kk < nSize; ++kk) { 3118*5552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 3119*5552b385SBrandon 3120*5552b385SBrandon if (!nHashKeyFound) { 3121*5552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 3122*5552b385SBrandon cfCntr += 1; 3123*5552b385SBrandon } 3124*5552b385SBrandon 3125*5552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 3126*5552b385SBrandon if (!pHashKeyFound) { 3127*5552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 3128*5552b385SBrandon gcntr += 3 * maxNumCPs; 3129*5552b385SBrandon } 3130*5552b385SBrandon } 3131*5552b385SBrandon PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 3132*5552b385SBrandon PetscCall(ISDestroy(&nodePoints)); 3133*5552b385SBrandon } 3134*5552b385SBrandon 3135*5552b385SBrandon // Get the Total Number of entries in the Hash Table 3136*5552b385SBrandon PetscInt currFaceUPSize; 3137*5552b385SBrandon PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 3138*5552b385SBrandon 3139*5552b385SBrandon // Get Keys 3140*5552b385SBrandon PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 3141*5552b385SBrandon PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 3142*5552b385SBrandon 3143*5552b385SBrandon // Cycle through all points on the current FACE 3144*5552b385SBrandon for (int jj = 0; jj < currFaceUPSize; ++jj) { 3145*5552b385SBrandon PetscInt currPointID = currFaceUPKeys[jj]; 3146*5552b385SBrandon PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 3147*5552b385SBrandon 3148*5552b385SBrandon // Get UV position of FACE 3149*5552b385SBrandon double params[2], range[4], eval[18]; 3150*5552b385SBrandon int peri; 3151*5552b385SBrandon 3152*5552b385SBrandon if (islite) { 3153*5552b385SBrandon PetscCall(EGlite_getRange(face, range, &peri)); 3154*5552b385SBrandon } else { 3155*5552b385SBrandon PetscCall(EG_getRange(face, range, &peri)); 3156*5552b385SBrandon } 3157*5552b385SBrandon 3158*5552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 3159*5552b385SBrandon 3160*5552b385SBrandon if (islite) { 3161*5552b385SBrandon PetscCall(EGlite_evaluate(face, params, eval)); 3162*5552b385SBrandon } else { 3163*5552b385SBrandon PetscCall(EG_evaluate(face, params, eval)); 3164*5552b385SBrandon } 3165*5552b385SBrandon 3166*5552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 3167*5552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 3168*5552b385SBrandon double nbprv[prvSize]; 3169*5552b385SBrandon 3170*5552b385SBrandon // Cycle through each Control Point 3171*5552b385SBrandon double deltaCoord = 1.0E-4; 3172*5552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 3173*5552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 3174*5552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 3175*5552b385SBrandon // Cycle through each direction (x, then y, then z) 3176*5552b385SBrandon for (int kk = 0; kk < 4; ++kk) { 3177*5552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 3178*5552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 3179*5552b385SBrandon 3180*5552b385SBrandon if (kk == 0) { //X 3181*5552b385SBrandon nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 3182*5552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 3183*5552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 3184*5552b385SBrandon } else if (kk == 1) { //Y 3185*5552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 3186*5552b385SBrandon nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 3187*5552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 3188*5552b385SBrandon } else if (kk == 2) { //Z 3189*5552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 3190*5552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 3191*5552b385SBrandon nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 3192*5552b385SBrandon } else if (kk == 3) { // Weights 3193*5552b385SBrandon nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 3194*5552b385SBrandon } else { 3195*5552b385SBrandon // currently do nothing 3196*5552b385SBrandon } 3197*5552b385SBrandon 3198*5552b385SBrandon // Create New Surface Based on New Control Points or Weights 3199*5552b385SBrandon ego newgeom, context; 3200*5552b385SBrandon if (islite) { 3201*5552b385SBrandon PetscCall(EGlite_open(&context)); 3202*5552b385SBrandon PetscCall(EGlite_setOutLevel(context, 0)); 3203*5552b385SBrandon } else { 3204*5552b385SBrandon PetscCall(EG_open(&context)); 3205*5552b385SBrandon PetscCall(EG_setOutLevel(context, 0)); 3206*5552b385SBrandon } 3207*5552b385SBrandon 3208*5552b385SBrandon PetscCall(EG_makeGeometry(context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 3209*5552b385SBrandon 3210*5552b385SBrandon if (islite) { 3211*5552b385SBrandon PetscCall(EGlite_setOutLevel(context, 1)); 3212*5552b385SBrandon } else { 3213*5552b385SBrandon PetscCall(EG_setOutLevel(context, 1)); 3214*5552b385SBrandon } 3215*5552b385SBrandon 3216*5552b385SBrandon // Evaluate new (x, y, z) Point Position based on new Surface Definition 3217*5552b385SBrandon double newCoords[18]; 3218*5552b385SBrandon if (islite) { 3219*5552b385SBrandon PetscCall(EGlite_getRange(newgeom, range, &peri)); 3220*5552b385SBrandon } else { 3221*5552b385SBrandon PetscCall(EG_getRange(newgeom, range, &peri)); 3222*5552b385SBrandon } 3223*5552b385SBrandon 3224*5552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, newgeom, range, 0, dE, params, islite)); 3225*5552b385SBrandon 3226*5552b385SBrandon if (islite) { 3227*5552b385SBrandon PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 3228*5552b385SBrandon } else { 3229*5552b385SBrandon PetscCall(EG_evaluate(newgeom, params, newCoords)); 3230*5552b385SBrandon } 3231*5552b385SBrandon 3232*5552b385SBrandon // Now Calculate the Surface Gradient for the change in x-component Control Point 3233*5552b385SBrandon PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 3234*5552b385SBrandon PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 3235*5552b385SBrandon PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 3236*5552b385SBrandon 3237*5552b385SBrandon // Store Gradient Information in surfaceGrad[][] Matrix 3238*5552b385SBrandon PetscInt startRow; 3239*5552b385SBrandon PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 3240*5552b385SBrandon 3241*5552b385SBrandon // Store Results in Petsc Matrix 3242*5552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 3243*5552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 3244*5552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 3245*5552b385SBrandon } 3246*5552b385SBrandon offset += 3; 3247*5552b385SBrandon } 3248*5552b385SBrandon PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 3249*5552b385SBrandon } 3250*5552b385SBrandon } 3251*5552b385SBrandon 3252*5552b385SBrandon // Assemble Point Surface Grad Matrix 3253*5552b385SBrandon MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY); 3254*5552b385SBrandon MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY); 3255*5552b385SBrandon 3256*5552b385SBrandon // Attach Surface Gradient Hash Table and Matrix to DM 3257*5552b385SBrandon { 3258*5552b385SBrandon PetscContainer surfGradOrgObj, surfGradObj; 3259*5552b385SBrandon 3260*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 3261*5552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 3262*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 3263*5552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 3264*5552b385SBrandon 3265*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradObj)); 3266*5552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradObj, pointSurfGrad)); 3267*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)surfGradObj)); 3268*5552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradObj)); 3269*5552b385SBrandon } 3270*5552b385SBrandon if (islite) EGlite_free(fobjs); 3271*5552b385SBrandon else EG_free(fobjs); 3272*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 3273*5552b385SBrandon } 3274*5552b385SBrandon 3275*5552b385SBrandon static PetscErrorCode DestroyHashMap(void **p) 3276*5552b385SBrandon { 3277*5552b385SBrandon PetscFunctionBegin; 3278*5552b385SBrandon PetscCall(PetscHMapIDestroy((PetscHMapI *)p)); 3279*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 3280*5552b385SBrandon } 3281*5552b385SBrandon #endif 3282*5552b385SBrandon 3283*5552b385SBrandon /*@C 3284*5552b385SBrandon DMPlexGeomDataAndGrads - Exposes Control Points and Control Point Weights defining the underlying geometry allowing user manipulation of the geometry. 3285*5552b385SBrandon 3286*5552b385SBrandon Collective 3287*5552b385SBrandon 3288*5552b385SBrandon Input Parameters: 3289*5552b385SBrandon + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 3290*5552b385SBrandon - fullGeomGrad - PetscBool flag. Determines how the Surface Area and Volume Gradients wrt to Control Points and Control Point Weights are calculated. 3291*5552b385SBrandon PETSC_FALSE :: Surface Area Gradient wrt Control Points and Control Point Weights are calculated using the change in the local 3292*5552b385SBrandon FACE changes (not the entire body). Volume Gradients are not calculated. Faster computations. 3293*5552b385SBrandon PETSC_TRUE :: Surface Area Gradietn wrt to Control Points and Control Point Weights are calculated using the change observed in 3294*5552b385SBrandon the entire solid body. Volume Gradients are calculated. Slower computation due to the need to generate a new solid 3295*5552b385SBrandon body geometry for every Control Point and Control Point Weight change. 3296*5552b385SBrandon 3297*5552b385SBrandon Output Parameter: 3298*5552b385SBrandon . dm - The updated DM object representing the mesh with PetscContainers containing the Control Point, Control Point Weight and Gradient Data. 3299*5552b385SBrandon 3300*5552b385SBrandon Level: intermediate 3301*5552b385SBrandon 3302*5552b385SBrandon Note: 3303*5552b385SBrandon 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). 3304*5552b385SBrandon 3305*5552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexModifyEGADSGeomModel()` 3306*5552b385SBrandon @*/ 3307*5552b385SBrandon PetscErrorCode DMPlexGeomDataAndGrads(DM dm, PetscBool fullGeomGrad) 3308*5552b385SBrandon { 3309*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 3310*5552b385SBrandon /* PETSc Variables */ 3311*5552b385SBrandon PetscContainer modelObj; 3312*5552b385SBrandon PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 3313*5552b385SBrandon PetscHMapI pointSurfGradRow_Start = NULL; 3314*5552b385SBrandon Mat pointSurfGrad, cpEquiv; 3315*5552b385SBrandon IS faceLabelValues, edgeLabelValues, vertexLabelValues; 3316*5552b385SBrandon PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 3317*5552b385SBrandon PetscBool islite = PETSC_FALSE; 3318*5552b385SBrandon /* EGADS Variables */ 3319*5552b385SBrandon ego model, geom, *bodies, *fobjs = NULL; 3320*5552b385SBrandon int oclass, mtype, *senses; 3321*5552b385SBrandon int Nb, Nf; 3322*5552b385SBrandon #endif 3323*5552b385SBrandon 3324*5552b385SBrandon PetscFunctionBegin; 3325*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 3326*5552b385SBrandon 3327*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 3328*5552b385SBrandon if (!modelObj) { 3329*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 3330*5552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 3331*5552b385SBrandon islite = PETSC_TRUE; 3332*5552b385SBrandon 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"); 3333*5552b385SBrandon } 3334*5552b385SBrandon 3335*5552b385SBrandon // Get attached EGADS model (pointer) 3336*5552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 3337*5552b385SBrandon 3338*5552b385SBrandon // Get the bodies in the model 3339*5552b385SBrandon if (islite) { 3340*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 3341*5552b385SBrandon } else { 3342*5552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 3343*5552b385SBrandon } 3344*5552b385SBrandon 3345*5552b385SBrandon ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 3346*5552b385SBrandon 3347*5552b385SBrandon // Get the total number of FACEs in the model 3348*5552b385SBrandon if (islite) { 3349*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 3350*5552b385SBrandon } else { 3351*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 3352*5552b385SBrandon } 3353*5552b385SBrandon 3354*5552b385SBrandon // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 3355*5552b385SBrandon // This will provide the total number of DMPlex points on the boundary of the geometry 3356*5552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 3357*5552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 3358*5552b385SBrandon 3359*5552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 3360*5552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 3361*5552b385SBrandon 3362*5552b385SBrandon PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 3363*5552b385SBrandon PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 3364*5552b385SBrandon 3365*5552b385SBrandon const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 3366*5552b385SBrandon PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 3367*5552b385SBrandon PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 3368*5552b385SBrandon PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 3369*5552b385SBrandon 3370*5552b385SBrandon // Get the points associated with each FACE, EDGE and VERTEX label in the DM 3371*5552b385SBrandon PetscInt totalNumPoints = 0; 3372*5552b385SBrandon for (int f = 0; f < faceLabelSize; ++f) { 3373*5552b385SBrandon // Cycle through FACE labels 3374*5552b385SBrandon PetscInt size; 3375*5552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[f], &size)); 3376*5552b385SBrandon totalNumPoints += size; 3377*5552b385SBrandon } 3378*5552b385SBrandon PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 3379*5552b385SBrandon PetscCall(ISDestroy(&faceLabelValues)); 3380*5552b385SBrandon 3381*5552b385SBrandon for (int e = 0; e < edgeLabelSize; ++e) { 3382*5552b385SBrandon // Cycle Through EDGE Labels 3383*5552b385SBrandon PetscInt size; 3384*5552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[e], &size)); 3385*5552b385SBrandon totalNumPoints += size; 3386*5552b385SBrandon } 3387*5552b385SBrandon PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 3388*5552b385SBrandon PetscCall(ISDestroy(&edgeLabelValues)); 3389*5552b385SBrandon 3390*5552b385SBrandon for (int ii = 0; ii < vertexLabelSize; ++ii) { 3391*5552b385SBrandon // Cycle Through VERTEX Labels 3392*5552b385SBrandon PetscInt size; 3393*5552b385SBrandon PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 3394*5552b385SBrandon totalNumPoints += size; 3395*5552b385SBrandon } 3396*5552b385SBrandon PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 3397*5552b385SBrandon PetscCall(ISDestroy(&vertexLabelValues)); 3398*5552b385SBrandon 3399*5552b385SBrandon int maxNumCPs = 0; 3400*5552b385SBrandon int totalNumCPs = 0; 3401*5552b385SBrandon ego bRef, bPrev, bNext, fgeom, *lobjs; 3402*5552b385SBrandon int id, boclass, bmtype, *bpinfo; 3403*5552b385SBrandon int foclass, fmtype, Nl, *lsenses; 3404*5552b385SBrandon double *bprv; 3405*5552b385SBrandon double fdata[4]; 3406*5552b385SBrandon 3407*5552b385SBrandon // Create Hash Tables 3408*5552b385SBrandon PetscInt cntr = 0, wcntr = 0, vcntr = 0; 3409*5552b385SBrandon PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 3410*5552b385SBrandon PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 3411*5552b385SBrandon 3412*5552b385SBrandon for (int f = 0; f < Nf; ++f) { 3413*5552b385SBrandon // Need to get the maximum number of Control Points defining the FACEs 3414*5552b385SBrandon ego face = fobjs[f]; 3415*5552b385SBrandon int maxNumCPs_temp; 3416*5552b385SBrandon 3417*5552b385SBrandon if (islite) { 3418*5552b385SBrandon id = EGlite_indexBodyTopo(body, face); 3419*5552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3420*5552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3421*5552b385SBrandon PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3422*5552b385SBrandon } else { 3423*5552b385SBrandon id = EG_indexBodyTopo(body, face); 3424*5552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3425*5552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3426*5552b385SBrandon PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3427*5552b385SBrandon } 3428*5552b385SBrandon maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 3429*5552b385SBrandon totalNumCPs += bpinfo[2] * bpinfo[5]; 3430*5552b385SBrandon 3431*5552b385SBrandon if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 3432*5552b385SBrandon } 3433*5552b385SBrandon 3434*5552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 3435*5552b385SBrandon PetscInt cpCoordDataLength = 3 * totalNumCPs; 3436*5552b385SBrandon PetscInt wDataLength = totalNumCPs; 3437*5552b385SBrandon cpCoordDataLengthPtr = &cpCoordDataLength; 3438*5552b385SBrandon wDataLengthPtr = &wDataLength; 3439*5552b385SBrandon 3440*5552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 3441*5552b385SBrandon PetscScalar *cntrlPtCoords, *cntrlPtWeights; 3442*5552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &cntrlPtCoordsVec)); 3443*5552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &cntrlPtWeightsVec)); 3444*5552b385SBrandon 3445*5552b385SBrandon // For dSA/dCPi 3446*5552b385SBrandon Vec gradSACPVec, gradSAWVec, gradVCPVec, gradVWVec; 3447*5552b385SBrandon PetscScalar *gradSACP, *gradSAW, *gradVCP, *gradVW; 3448*5552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradSACPVec)); 3449*5552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradSAWVec)); 3450*5552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradVCPVec)); 3451*5552b385SBrandon PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradVWVec)); 3452*5552b385SBrandon 3453*5552b385SBrandon // Control Point - Vertex/Edge/Face Relationship 3454*5552b385SBrandon PetscInt *cp_vertex, *cp_edge, *cp_face; 3455*5552b385SBrandon PetscInt *w_vertex, *w_edge, *w_face; 3456*5552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_vertex)); 3457*5552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_edge)); 3458*5552b385SBrandon PetscCall(PetscMalloc1(totalNumCPs, &cp_face)); 3459*5552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_vertex)); 3460*5552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_edge)); 3461*5552b385SBrandon PetscCall(PetscMalloc1(wDataLength, &w_face)); 3462*5552b385SBrandon 3463*5552b385SBrandon for (int f = 0; f < Nf; ++f) { 3464*5552b385SBrandon // Need to Populate Control Point Coordinates and Weight Vectors 3465*5552b385SBrandon ego face = fobjs[f]; 3466*5552b385SBrandon ego *vobjs, *eobjs; 3467*5552b385SBrandon int offsetCoord, offsetWeight; 3468*5552b385SBrandon PetscInt Nv, Ne, wRowStart = 0; 3469*5552b385SBrandon PetscHashIter hashKeyIter, wHashKeyIter; 3470*5552b385SBrandon PetscBool hashKeyFound, wHashKeyFound; 3471*5552b385SBrandon 3472*5552b385SBrandon if (islite) { 3473*5552b385SBrandon id = EGlite_indexBodyTopo(body, face); 3474*5552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3475*5552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3476*5552b385SBrandon PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3477*5552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 3478*5552b385SBrandon } else { 3479*5552b385SBrandon id = EG_indexBodyTopo(body, face); 3480*5552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3481*5552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3482*5552b385SBrandon PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3483*5552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 3484*5552b385SBrandon } 3485*5552b385SBrandon 3486*5552b385SBrandon // Store Face ID to 1st Row of Control Point Vector 3487*5552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 3488*5552b385SBrandon 3489*5552b385SBrandon if (!hashKeyFound) PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); 3490*5552b385SBrandon 3491*5552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 3492*5552b385SBrandon offsetCoord = bpinfo[3] + bpinfo[6]; 3493*5552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 3494*5552b385SBrandon cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 3495*5552b385SBrandon cntr += 1; 3496*5552b385SBrandon } 3497*5552b385SBrandon 3498*5552b385SBrandon // Store Face ID to 1st Row of Control Point Weight Vector 3499*5552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 3500*5552b385SBrandon 3501*5552b385SBrandon if (!wHashKeyFound) { 3502*5552b385SBrandon PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); 3503*5552b385SBrandon wRowStart = wcntr; 3504*5552b385SBrandon } 3505*5552b385SBrandon 3506*5552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 3507*5552b385SBrandon offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 3508*5552b385SBrandon for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 3509*5552b385SBrandon cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 3510*5552b385SBrandon cp_face[wcntr] = id; 3511*5552b385SBrandon w_face[wcntr] = id; 3512*5552b385SBrandon wcntr += 1; 3513*5552b385SBrandon } 3514*5552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 3515*5552b385SBrandon 3516*5552b385SBrandon // Associate Control Points with Vertix IDs 3517*5552b385SBrandon PetscScalar xcp, ycp, zcp; 3518*5552b385SBrandon offsetCoord = bpinfo[3] + bpinfo[6]; 3519*5552b385SBrandon for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; jj += 3) { 3520*5552b385SBrandon xcp = bprv[offsetCoord + jj + 0]; 3521*5552b385SBrandon ycp = bprv[offsetCoord + jj + 1]; 3522*5552b385SBrandon zcp = bprv[offsetCoord + jj + 2]; 3523*5552b385SBrandon 3524*5552b385SBrandon //Initialize Control Point and Weight to Vertex ID relationship to -1 3525*5552b385SBrandon cp_vertex[vcntr] = -1; 3526*5552b385SBrandon w_vertex[vcntr] = -1; 3527*5552b385SBrandon cp_edge[vcntr] = -1; 3528*5552b385SBrandon w_edge[vcntr] = -1; 3529*5552b385SBrandon 3530*5552b385SBrandon for (int kk = 0; kk < Nv; ++kk) { 3531*5552b385SBrandon int vid; 3532*5552b385SBrandon double vCoords[3]; 3533*5552b385SBrandon PetscScalar vDelta; 3534*5552b385SBrandon ego vertex = vobjs[kk]; 3535*5552b385SBrandon 3536*5552b385SBrandon if (islite) { 3537*5552b385SBrandon vid = EGlite_indexBodyTopo(body, vertex); 3538*5552b385SBrandon PetscCallEGADS(EGlite_evaluate, (vertex, NULL, vCoords)); 3539*5552b385SBrandon } else { 3540*5552b385SBrandon vid = EG_indexBodyTopo(body, vertex); 3541*5552b385SBrandon PetscCallEGADS(EG_evaluate, (vertex, NULL, vCoords)); 3542*5552b385SBrandon } 3543*5552b385SBrandon vDelta = PetscSqrtReal(PetscSqr(vCoords[0] - xcp) + PetscSqr(vCoords[1] - ycp) + PetscSqr(vCoords[2] - zcp)); 3544*5552b385SBrandon 3545*5552b385SBrandon if (vDelta < 1.0E-15) { 3546*5552b385SBrandon cp_vertex[vcntr] = vid; 3547*5552b385SBrandon w_vertex[vcntr] = vid; 3548*5552b385SBrandon } 3549*5552b385SBrandon } 3550*5552b385SBrandon vcntr += 1; 3551*5552b385SBrandon } 3552*5552b385SBrandon // These two line could be replaced with DMPlexFreeGeomObject() 3553*5552b385SBrandon if (islite) EGlite_free(vobjs); 3554*5552b385SBrandon else EG_free(vobjs); 3555*5552b385SBrandon 3556*5552b385SBrandon // Associate Control Points with Edge IDs 3557*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 3558*5552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 3559*5552b385SBrandon 3560*5552b385SBrandon int cpV1, cpV2; 3561*5552b385SBrandon int minID, maxID; 3562*5552b385SBrandon 3563*5552b385SBrandon // Along vmin axis 3564*5552b385SBrandon minID = wRowStart; 3565*5552b385SBrandon maxID = wRowStart + (bpinfo[2] - 1); 3566*5552b385SBrandon cpV1 = cp_vertex[minID]; 3567*5552b385SBrandon cpV2 = cp_vertex[maxID]; 3568*5552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 3569*5552b385SBrandon ego edge = eobjs[jj]; 3570*5552b385SBrandon ego egeom, *nobjs; 3571*5552b385SBrandon int eoclass, emtype, Nn, *nsenses; 3572*5552b385SBrandon int n1ID, n2ID, eid; 3573*5552b385SBrandon 3574*5552b385SBrandon if (islite) { 3575*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 3576*5552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3577*5552b385SBrandon } else { 3578*5552b385SBrandon eid = EG_indexBodyTopo(body, edge); 3579*5552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3580*5552b385SBrandon } 3581*5552b385SBrandon 3582*5552b385SBrandon if (emtype != DEGENERATE) { 3583*5552b385SBrandon // Get IDs for current Edge's End Vertices 3584*5552b385SBrandon if (islite) { 3585*5552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3586*5552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3587*5552b385SBrandon } else { 3588*5552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 3589*5552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 3590*5552b385SBrandon } 3591*5552b385SBrandon 3592*5552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3593*5552b385SBrandon for (int kk = minID + 1; kk < maxID; ++kk) { 3594*5552b385SBrandon cp_edge[kk] = eid; 3595*5552b385SBrandon w_edge[kk] = eid; 3596*5552b385SBrandon } 3597*5552b385SBrandon } 3598*5552b385SBrandon } 3599*5552b385SBrandon } 3600*5552b385SBrandon 3601*5552b385SBrandon // Along vmax axis 3602*5552b385SBrandon minID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 3603*5552b385SBrandon maxID = wRowStart + (bpinfo[2] * bpinfo[5] - 1); 3604*5552b385SBrandon 3605*5552b385SBrandon cpV1 = cp_vertex[minID]; 3606*5552b385SBrandon cpV2 = cp_vertex[maxID]; 3607*5552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 3608*5552b385SBrandon ego edge = eobjs[jj]; 3609*5552b385SBrandon ego egeom, *nobjs; 3610*5552b385SBrandon int eoclass, emtype, Nn, *nsenses; 3611*5552b385SBrandon int n1ID, n2ID, eid; 3612*5552b385SBrandon 3613*5552b385SBrandon if (islite) { 3614*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 3615*5552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3616*5552b385SBrandon } else { 3617*5552b385SBrandon eid = EG_indexBodyTopo(body, edge); 3618*5552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3619*5552b385SBrandon } 3620*5552b385SBrandon 3621*5552b385SBrandon if (emtype != DEGENERATE) { 3622*5552b385SBrandon // Get IDs for current Edge's End Vertices 3623*5552b385SBrandon if (islite) { 3624*5552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3625*5552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3626*5552b385SBrandon } else { 3627*5552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 3628*5552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 3629*5552b385SBrandon } 3630*5552b385SBrandon 3631*5552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3632*5552b385SBrandon for (int kk = minID + 1; kk < maxID - 1; ++kk) { 3633*5552b385SBrandon cp_edge[kk] = eid; 3634*5552b385SBrandon w_edge[kk] = eid; 3635*5552b385SBrandon } 3636*5552b385SBrandon } 3637*5552b385SBrandon } 3638*5552b385SBrandon } 3639*5552b385SBrandon 3640*5552b385SBrandon // Along umin axis 3641*5552b385SBrandon minID = wRowStart; 3642*5552b385SBrandon maxID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 3643*5552b385SBrandon 3644*5552b385SBrandon cpV1 = cp_vertex[minID]; 3645*5552b385SBrandon cpV2 = cp_vertex[maxID]; 3646*5552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 3647*5552b385SBrandon ego edge = eobjs[jj]; 3648*5552b385SBrandon ego egeom, *nobjs; 3649*5552b385SBrandon int eoclass, emtype, Nn, *nsenses; 3650*5552b385SBrandon int n1ID, n2ID, eid; 3651*5552b385SBrandon 3652*5552b385SBrandon if (islite) { 3653*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 3654*5552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3655*5552b385SBrandon } else { 3656*5552b385SBrandon eid = EG_indexBodyTopo(body, edge); 3657*5552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3658*5552b385SBrandon } 3659*5552b385SBrandon 3660*5552b385SBrandon if (emtype != DEGENERATE) { 3661*5552b385SBrandon // Get IDs for current Edge's End Vertices 3662*5552b385SBrandon if (islite) { 3663*5552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3664*5552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3665*5552b385SBrandon } else { 3666*5552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 3667*5552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 3668*5552b385SBrandon } 3669*5552b385SBrandon 3670*5552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3671*5552b385SBrandon for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 3672*5552b385SBrandon cp_edge[kk] = eid; 3673*5552b385SBrandon w_edge[kk] = eid; 3674*5552b385SBrandon } 3675*5552b385SBrandon } 3676*5552b385SBrandon } 3677*5552b385SBrandon } 3678*5552b385SBrandon 3679*5552b385SBrandon // Along umax axis 3680*5552b385SBrandon minID = wRowStart + (bpinfo[2] - 1); 3681*5552b385SBrandon maxID = wRowStart + (bpinfo[2] * bpinfo[5]) - 1; 3682*5552b385SBrandon cpV1 = cp_vertex[minID]; 3683*5552b385SBrandon cpV2 = cp_vertex[maxID]; 3684*5552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 3685*5552b385SBrandon ego edge = eobjs[jj]; 3686*5552b385SBrandon ego egeom, *nobjs; 3687*5552b385SBrandon int eoclass, emtype, Nn, *nsenses; 3688*5552b385SBrandon int n1ID, n2ID, eid; 3689*5552b385SBrandon 3690*5552b385SBrandon if (islite) { 3691*5552b385SBrandon eid = EGlite_indexBodyTopo(body, edge); 3692*5552b385SBrandon PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3693*5552b385SBrandon } else { 3694*5552b385SBrandon eid = EG_indexBodyTopo(body, edge); 3695*5552b385SBrandon PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3696*5552b385SBrandon } 3697*5552b385SBrandon 3698*5552b385SBrandon if (emtype != DEGENERATE) { 3699*5552b385SBrandon // Get IDs for current Edge's End Vertices 3700*5552b385SBrandon if (islite) { 3701*5552b385SBrandon n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3702*5552b385SBrandon n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3703*5552b385SBrandon } else { 3704*5552b385SBrandon n1ID = EG_indexBodyTopo(body, nobjs[0]); 3705*5552b385SBrandon n2ID = EG_indexBodyTopo(body, nobjs[1]); 3706*5552b385SBrandon } 3707*5552b385SBrandon 3708*5552b385SBrandon if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3709*5552b385SBrandon for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 3710*5552b385SBrandon cp_edge[kk] = eid; 3711*5552b385SBrandon w_edge[kk] = eid; 3712*5552b385SBrandon } 3713*5552b385SBrandon } 3714*5552b385SBrandon } 3715*5552b385SBrandon } 3716*5552b385SBrandon // These two lines could be replaced with DMPlexFreeGeomObject() 3717*5552b385SBrandon if (islite) EGlite_free(eobjs); 3718*5552b385SBrandon else EG_free(eobjs); 3719*5552b385SBrandon } 3720*5552b385SBrandon 3721*5552b385SBrandon // Determine Control Point Equivalance Matrix relating Control Points between Surfaces 3722*5552b385SBrandon // Note: The Weights will also be tied together in the same manner 3723*5552b385SBrandon // Also can use the Weight Hash Table for Row Start ID of each Face 3724*5552b385SBrandon const PetscInt cpRowSize = totalNumCPs; 3725*5552b385SBrandon const PetscInt cpColSize = cpRowSize; 3726*5552b385SBrandon PetscInt *maxNumRelatePtr; 3727*5552b385SBrandon PetscInt maxNumRelate = 0; 3728*5552b385SBrandon 3729*5552b385SBrandon // Create Point Surface Gradient Matrix 3730*5552b385SBrandon PetscCall(MatCreate(PETSC_COMM_WORLD, &cpEquiv)); 3731*5552b385SBrandon PetscCall(MatSetSizes(cpEquiv, PETSC_DECIDE, PETSC_DECIDE, cpRowSize, cpColSize)); 3732*5552b385SBrandon PetscCall(MatSetType(cpEquiv, MATAIJ)); 3733*5552b385SBrandon PetscCall(MatSetUp(cpEquiv)); 3734*5552b385SBrandon 3735*5552b385SBrandon for (int ii = 0; ii < totalNumCPs; ++ii) { 3736*5552b385SBrandon PetscScalar x1, y1, z1; 3737*5552b385SBrandon PetscInt maxRelateTemp = 0; 3738*5552b385SBrandon 3739*5552b385SBrandon x1 = cntrlPtCoords[(3 * ii) + 0]; 3740*5552b385SBrandon y1 = cntrlPtCoords[(3 * ii) + 1]; 3741*5552b385SBrandon z1 = cntrlPtCoords[(3 * ii) + 2]; 3742*5552b385SBrandon 3743*5552b385SBrandon for (int jj = 0; jj < totalNumCPs; ++jj) { 3744*5552b385SBrandon PetscScalar x2, y2, z2; 3745*5552b385SBrandon PetscScalar cpDelta, eqFactor; 3746*5552b385SBrandon x2 = cntrlPtCoords[(3 * jj) + 0]; 3747*5552b385SBrandon y2 = cntrlPtCoords[(3 * jj) + 1]; 3748*5552b385SBrandon z2 = cntrlPtCoords[(3 * jj) + 2]; 3749*5552b385SBrandon 3750*5552b385SBrandon cpDelta = PetscSqrtReal(PetscSqr(x2 - x1) + PetscSqr(y2 - y1) + PetscSqr(z2 - z1)); 3751*5552b385SBrandon if (cpDelta < 1.0E-15) { 3752*5552b385SBrandon eqFactor = 1.0; 3753*5552b385SBrandon maxRelateTemp += 1; 3754*5552b385SBrandon } else { 3755*5552b385SBrandon eqFactor = 0.0; 3756*5552b385SBrandon } 3757*5552b385SBrandon 3758*5552b385SBrandon // Store Results in Petsc Matrix 3759*5552b385SBrandon PetscCall(MatSetValue(cpEquiv, ii, jj, eqFactor, INSERT_VALUES)); 3760*5552b385SBrandon } 3761*5552b385SBrandon if (maxRelateTemp > maxNumRelate) maxNumRelate = maxRelateTemp; 3762*5552b385SBrandon } 3763*5552b385SBrandon maxNumRelatePtr = &maxNumRelate; 3764*5552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 3765*5552b385SBrandon 3766*5552b385SBrandon // Assemble Point Surface Grad Matrix 3767*5552b385SBrandon PetscCall(MatAssemblyBegin(cpEquiv, MAT_FINAL_ASSEMBLY)); 3768*5552b385SBrandon PetscCall(MatAssemblyEnd(cpEquiv, MAT_FINAL_ASSEMBLY)); 3769*5552b385SBrandon 3770*5552b385SBrandon // Attach Control Point and Weight Data to DM 3771*5552b385SBrandon { 3772*5552b385SBrandon PetscContainer cpOrgObj, cpCoordLengthObj; 3773*5552b385SBrandon PetscContainer wOrgObj, wDataLengthObj; 3774*5552b385SBrandon PetscContainer cp_faceObj, cp_edgeObj, cp_vertexObj; 3775*5552b385SBrandon PetscContainer w_faceObj, w_edgeObj, w_vertexObj; 3776*5552b385SBrandon PetscContainer maxNumRelateObj; 3777*5552b385SBrandon 3778*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpOrgObj)); 3779*5552b385SBrandon if (!cpOrgObj) { 3780*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 3781*5552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 3782*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 3783*5552b385SBrandon PetscCall(PetscContainerDestroy(&cpOrgObj)); 3784*5552b385SBrandon } else { 3785*5552b385SBrandon PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 3786*5552b385SBrandon } 3787*5552b385SBrandon 3788*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cntrlPtCoordsVec)); 3789*5552b385SBrandon PetscCall(VecDestroy(&cntrlPtCoordsVec)); 3790*5552b385SBrandon 3791*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordLengthObj)); 3792*5552b385SBrandon if (!cpCoordLengthObj) { 3793*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 3794*5552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 3795*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 3796*5552b385SBrandon PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 3797*5552b385SBrandon } else { 3798*5552b385SBrandon PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 3799*5552b385SBrandon } 3800*5552b385SBrandon 3801*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wOrgObj)); 3802*5552b385SBrandon if (!wOrgObj) { 3803*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 3804*5552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 3805*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 3806*5552b385SBrandon PetscCall(PetscContainerDestroy(&wOrgObj)); 3807*5552b385SBrandon } else { 3808*5552b385SBrandon PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 3809*5552b385SBrandon } 3810*5552b385SBrandon 3811*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)cntrlPtWeightsVec)); 3812*5552b385SBrandon PetscCall(VecDestroy(&cntrlPtWeightsVec)); 3813*5552b385SBrandon 3814*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 3815*5552b385SBrandon if (!wDataLengthObj) { 3816*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 3817*5552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 3818*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 3819*5552b385SBrandon PetscCall(PetscContainerDestroy(&wDataLengthObj)); 3820*5552b385SBrandon } else { 3821*5552b385SBrandon PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 3822*5552b385SBrandon } 3823*5552b385SBrandon 3824*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Equivalancy Matrix", (PetscObject)cpEquiv)); 3825*5552b385SBrandon 3826*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 3827*5552b385SBrandon if (!maxNumRelateObj) { 3828*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &maxNumRelateObj)); 3829*5552b385SBrandon PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 3830*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject)maxNumRelateObj)); 3831*5552b385SBrandon PetscCall(PetscContainerDestroy(&maxNumRelateObj)); 3832*5552b385SBrandon } else { 3833*5552b385SBrandon PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 3834*5552b385SBrandon } 3835*5552b385SBrandon 3836*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cp_faceObj)); 3837*5552b385SBrandon if (!cp_faceObj) { 3838*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_faceObj)); 3839*5552b385SBrandon PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 3840*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_faceObj, PetscCtxDestroyDefault)); 3841*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Face Map", (PetscObject)cp_faceObj)); 3842*5552b385SBrandon PetscCall(PetscContainerDestroy(&cp_faceObj)); 3843*5552b385SBrandon } else { 3844*5552b385SBrandon void *tmp; 3845*5552b385SBrandon 3846*5552b385SBrandon PetscCall(PetscContainerGetPointer(cp_faceObj, &tmp)); 3847*5552b385SBrandon PetscCall(PetscFree(tmp)); 3848*5552b385SBrandon PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 3849*5552b385SBrandon } 3850*5552b385SBrandon 3851*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&w_faceObj)); 3852*5552b385SBrandon if (!w_faceObj) { 3853*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_faceObj)); 3854*5552b385SBrandon PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 3855*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_faceObj, PetscCtxDestroyDefault)); 3856*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject)w_faceObj)); 3857*5552b385SBrandon PetscCall(PetscContainerDestroy(&w_faceObj)); 3858*5552b385SBrandon } else { 3859*5552b385SBrandon void *tmp; 3860*5552b385SBrandon 3861*5552b385SBrandon PetscCall(PetscContainerGetPointer(w_faceObj, &tmp)); 3862*5552b385SBrandon PetscCall(PetscFree(tmp)); 3863*5552b385SBrandon PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 3864*5552b385SBrandon } 3865*5552b385SBrandon 3866*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cp_edgeObj)); 3867*5552b385SBrandon if (!cp_edgeObj) { 3868*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_edgeObj)); 3869*5552b385SBrandon PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 3870*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_edgeObj, PetscCtxDestroyDefault)); 3871*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Edge Map", (PetscObject)cp_edgeObj)); 3872*5552b385SBrandon PetscCall(PetscContainerDestroy(&cp_edgeObj)); 3873*5552b385SBrandon } else { 3874*5552b385SBrandon void *tmp; 3875*5552b385SBrandon 3876*5552b385SBrandon PetscCall(PetscContainerGetPointer(cp_edgeObj, &tmp)); 3877*5552b385SBrandon PetscCall(PetscFree(tmp)); 3878*5552b385SBrandon PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 3879*5552b385SBrandon } 3880*5552b385SBrandon 3881*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&w_edgeObj)); 3882*5552b385SBrandon if (!w_edgeObj) { 3883*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_edgeObj)); 3884*5552b385SBrandon PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 3885*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_edgeObj, PetscCtxDestroyDefault)); 3886*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject)w_edgeObj)); 3887*5552b385SBrandon PetscCall(PetscContainerDestroy(&w_edgeObj)); 3888*5552b385SBrandon } else { 3889*5552b385SBrandon void *tmp; 3890*5552b385SBrandon 3891*5552b385SBrandon PetscCall(PetscContainerGetPointer(w_edgeObj, &tmp)); 3892*5552b385SBrandon PetscCall(PetscFree(tmp)); 3893*5552b385SBrandon PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 3894*5552b385SBrandon } 3895*5552b385SBrandon 3896*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cp_vertexObj)); 3897*5552b385SBrandon if (!cp_vertexObj) { 3898*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_vertexObj)); 3899*5552b385SBrandon PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 3900*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(cp_vertexObj, PetscCtxDestroyDefault)); 3901*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Vertex Map", (PetscObject)cp_vertexObj)); 3902*5552b385SBrandon PetscCall(PetscContainerDestroy(&cp_vertexObj)); 3903*5552b385SBrandon } else { 3904*5552b385SBrandon void *tmp; 3905*5552b385SBrandon 3906*5552b385SBrandon PetscCall(PetscContainerGetPointer(cp_vertexObj, &tmp)); 3907*5552b385SBrandon PetscCall(PetscFree(tmp)); 3908*5552b385SBrandon PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 3909*5552b385SBrandon } 3910*5552b385SBrandon 3911*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&w_vertexObj)); 3912*5552b385SBrandon if (!w_vertexObj) { 3913*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_vertexObj)); 3914*5552b385SBrandon PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 3915*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(w_vertexObj, PetscCtxDestroyDefault)); 3916*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject)w_vertexObj)); 3917*5552b385SBrandon PetscCall(PetscContainerDestroy(&w_vertexObj)); 3918*5552b385SBrandon } else { 3919*5552b385SBrandon void *tmp; 3920*5552b385SBrandon 3921*5552b385SBrandon PetscCall(PetscContainerGetPointer(w_vertexObj, &tmp)); 3922*5552b385SBrandon PetscCall(PetscFree(tmp)); 3923*5552b385SBrandon PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 3924*5552b385SBrandon } 3925*5552b385SBrandon } 3926*5552b385SBrandon 3927*5552b385SBrandon // Define Matrix to store Geometry Gradient information dGeom_i/dCPj_i 3928*5552b385SBrandon PetscInt gcntr = 0; 3929*5552b385SBrandon const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 3930*5552b385SBrandon const PetscInt colSize = 4 * Nf; 3931*5552b385SBrandon 3932*5552b385SBrandon // Create Point Surface Gradient Matrix 3933*5552b385SBrandon PetscCall(MatCreate(PETSC_COMM_WORLD, &pointSurfGrad)); 3934*5552b385SBrandon PetscCall(MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize)); 3935*5552b385SBrandon PetscCall(MatSetType(pointSurfGrad, MATAIJ)); 3936*5552b385SBrandon PetscCall(MatSetUp(pointSurfGrad)); 3937*5552b385SBrandon 3938*5552b385SBrandon // Create Hash Table to store Point's stare row in surfaceGrad[][] 3939*5552b385SBrandon PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 3940*5552b385SBrandon 3941*5552b385SBrandon // Get Coordinates for the DMPlex point 3942*5552b385SBrandon DM cdm; 3943*5552b385SBrandon PetscInt dE, Nv; 3944*5552b385SBrandon Vec coordinatesLocal; 3945*5552b385SBrandon PetscScalar *coords = NULL; 3946*5552b385SBrandon 3947*5552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 3948*5552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &dE)); 3949*5552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 3950*5552b385SBrandon 3951*5552b385SBrandon // CYCLE THROUGH FACEs 3952*5552b385SBrandon PetscScalar maxGrad = 0.; 3953*5552b385SBrandon PetscCall(VecGetArrayWrite(gradSACPVec, &gradSACP)); 3954*5552b385SBrandon PetscCall(VecGetArrayWrite(gradSAWVec, &gradSAW)); 3955*5552b385SBrandon PetscCall(VecGetArrayWrite(gradVCPVec, &gradVCP)); 3956*5552b385SBrandon PetscCall(VecGetArrayWrite(gradVWVec, &gradVW)); 3957*5552b385SBrandon for (int f = 0; f < Nf; ++f) { 3958*5552b385SBrandon ego face = fobjs[f]; 3959*5552b385SBrandon ego *eobjs, *nobjs; 3960*5552b385SBrandon PetscInt fid, Ne, Nn; 3961*5552b385SBrandon DMLabel faceLabel, edgeLabel, nodeLabel; 3962*5552b385SBrandon PetscHMapI currFaceUniquePoints = NULL; 3963*5552b385SBrandon IS facePoints, edgePoints, nodePoints; 3964*5552b385SBrandon const PetscInt *fIndices, *eIndices, *nIndices; 3965*5552b385SBrandon PetscInt fSize, eSize, nSize; 3966*5552b385SBrandon PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 3967*5552b385SBrandon PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 3968*5552b385SBrandon PetscInt cfCntr = 0; 3969*5552b385SBrandon 3970*5552b385SBrandon // Get Geometry Object for the Current FACE 3971*5552b385SBrandon if (islite) { 3972*5552b385SBrandon PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3973*5552b385SBrandon PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3974*5552b385SBrandon } else { 3975*5552b385SBrandon PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3976*5552b385SBrandon PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3977*5552b385SBrandon } 3978*5552b385SBrandon 3979*5552b385SBrandon // Get all EDGE and NODE objects attached to the current FACE 3980*5552b385SBrandon if (islite) { 3981*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3982*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3983*5552b385SBrandon } else { 3984*5552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3985*5552b385SBrandon PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3986*5552b385SBrandon } 3987*5552b385SBrandon 3988*5552b385SBrandon // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 3989*5552b385SBrandon if (islite) { 3990*5552b385SBrandon fid = EGlite_indexBodyTopo(body, face); 3991*5552b385SBrandon } else { 3992*5552b385SBrandon fid = EG_indexBodyTopo(body, face); 3993*5552b385SBrandon } 3994*5552b385SBrandon 3995*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 3996*5552b385SBrandon PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 3997*5552b385SBrandon PetscCall(ISGetIndices(facePoints, &fIndices)); 3998*5552b385SBrandon PetscCall(ISGetSize(facePoints, &fSize)); 3999*5552b385SBrandon 4000*5552b385SBrandon PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 4001*5552b385SBrandon 4002*5552b385SBrandon for (int jj = 0; jj < fSize; ++jj) { 4003*5552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 4004*5552b385SBrandon 4005*5552b385SBrandon if (!fHashKeyFound) { 4006*5552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 4007*5552b385SBrandon cfCntr += 1; 4008*5552b385SBrandon } 4009*5552b385SBrandon 4010*5552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 4011*5552b385SBrandon 4012*5552b385SBrandon if (!pHashKeyFound) { 4013*5552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 4014*5552b385SBrandon gcntr += 3 * maxNumCPs; 4015*5552b385SBrandon } 4016*5552b385SBrandon } 4017*5552b385SBrandon PetscCall(ISRestoreIndices(facePoints, &fIndices)); 4018*5552b385SBrandon PetscCall(ISDestroy(&facePoints)); 4019*5552b385SBrandon 4020*5552b385SBrandon // 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. 4021*5552b385SBrandon for (int jj = 0; jj < Ne; ++jj) { 4022*5552b385SBrandon ego edge = eobjs[jj]; 4023*5552b385SBrandon PetscBool containLabelValue; 4024*5552b385SBrandon 4025*5552b385SBrandon if (islite) { 4026*5552b385SBrandon id = EGlite_indexBodyTopo(body, edge); 4027*5552b385SBrandon } else { 4028*5552b385SBrandon id = EG_indexBodyTopo(body, edge); 4029*5552b385SBrandon } 4030*5552b385SBrandon 4031*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4032*5552b385SBrandon PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 4033*5552b385SBrandon 4034*5552b385SBrandon if (containLabelValue) { 4035*5552b385SBrandon PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 4036*5552b385SBrandon PetscCall(ISGetIndices(edgePoints, &eIndices)); 4037*5552b385SBrandon PetscCall(ISGetSize(edgePoints, &eSize)); 4038*5552b385SBrandon 4039*5552b385SBrandon for (int kk = 0; kk < eSize; ++kk) { 4040*5552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 4041*5552b385SBrandon 4042*5552b385SBrandon if (!eHashKeyFound) { 4043*5552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 4044*5552b385SBrandon cfCntr += 1; 4045*5552b385SBrandon } 4046*5552b385SBrandon 4047*5552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 4048*5552b385SBrandon 4049*5552b385SBrandon if (!pHashKeyFound) { 4050*5552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 4051*5552b385SBrandon gcntr += 3 * maxNumCPs; 4052*5552b385SBrandon } 4053*5552b385SBrandon } 4054*5552b385SBrandon PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 4055*5552b385SBrandon PetscCall(ISDestroy(&edgePoints)); 4056*5552b385SBrandon } 4057*5552b385SBrandon } 4058*5552b385SBrandon 4059*5552b385SBrandon // 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. 4060*5552b385SBrandon for (int jj = 0; jj < Nn; ++jj) { 4061*5552b385SBrandon ego node = nobjs[jj]; 4062*5552b385SBrandon 4063*5552b385SBrandon if (islite) { 4064*5552b385SBrandon id = EGlite_indexBodyTopo(body, node); 4065*5552b385SBrandon } else { 4066*5552b385SBrandon id = EG_indexBodyTopo(body, node); 4067*5552b385SBrandon } 4068*5552b385SBrandon 4069*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 4070*5552b385SBrandon PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 4071*5552b385SBrandon PetscCall(ISGetIndices(nodePoints, &nIndices)); 4072*5552b385SBrandon PetscCall(ISGetSize(nodePoints, &nSize)); 4073*5552b385SBrandon 4074*5552b385SBrandon for (int kk = 0; kk < nSize; ++kk) { 4075*5552b385SBrandon PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 4076*5552b385SBrandon 4077*5552b385SBrandon if (!nHashKeyFound) { 4078*5552b385SBrandon PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 4079*5552b385SBrandon cfCntr += 1; 4080*5552b385SBrandon } 4081*5552b385SBrandon 4082*5552b385SBrandon PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 4083*5552b385SBrandon if (!pHashKeyFound) { 4084*5552b385SBrandon PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 4085*5552b385SBrandon gcntr += 3 * maxNumCPs; 4086*5552b385SBrandon } 4087*5552b385SBrandon } 4088*5552b385SBrandon PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 4089*5552b385SBrandon PetscCall(ISDestroy(&nodePoints)); 4090*5552b385SBrandon } 4091*5552b385SBrandon 4092*5552b385SBrandon // Get the Total Number of entries in the Hash Table 4093*5552b385SBrandon PetscInt currFaceUPSize; 4094*5552b385SBrandon PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 4095*5552b385SBrandon 4096*5552b385SBrandon // Get Keys 4097*5552b385SBrandon PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 4098*5552b385SBrandon PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 4099*5552b385SBrandon PetscCall(PetscHMapIDestroy(&currFaceUniquePoints)); 4100*5552b385SBrandon 4101*5552b385SBrandon // Get Current Face Surface Area 4102*5552b385SBrandon PetscScalar fSA, faceData[14]; 4103*5552b385SBrandon PetscCall(EG_getMassProperties(face, faceData)); // This doesn't have a EGlite version. Will it work for EGADSlite files?? KNOWN_ISSUE 4104*5552b385SBrandon fSA = faceData[1]; 4105*5552b385SBrandon 4106*5552b385SBrandon // Get Start Row in cpEquiv Matrix 4107*5552b385SBrandon PetscHashIter Witer; 4108*5552b385SBrandon PetscBool Wfound; 4109*5552b385SBrandon PetscInt faceWStartRow; 4110*5552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 4111*5552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4112*5552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 4113*5552b385SBrandon 4114*5552b385SBrandon // Cycle through all points on the current FACE 4115*5552b385SBrandon for (int jj = 0; jj < currFaceUPSize; ++jj) { 4116*5552b385SBrandon PetscInt currPointID = currFaceUPKeys[jj]; 4117*5552b385SBrandon PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 4118*5552b385SBrandon 4119*5552b385SBrandon // Get UV position of FACE 4120*5552b385SBrandon double params[2], range[4], eval[18]; 4121*5552b385SBrandon int peri; 4122*5552b385SBrandon 4123*5552b385SBrandon if (islite) PetscCall(EGlite_getRange(face, range, &peri)); 4124*5552b385SBrandon else PetscCall(EG_getRange(face, range, &peri)); 4125*5552b385SBrandon 4126*5552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 4127*5552b385SBrandon 4128*5552b385SBrandon if (islite) PetscCall(EGlite_evaluate(face, params, eval)); 4129*5552b385SBrandon else PetscCall(EG_evaluate(face, params, eval)); 4130*5552b385SBrandon 4131*5552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 4132*5552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 4133*5552b385SBrandon double nbprv[prvSize]; 4134*5552b385SBrandon 4135*5552b385SBrandon // Cycle through each Control Point 4136*5552b385SBrandon double denomNew, denomOld; 4137*5552b385SBrandon double deltaCoord = 1.0E-4; 4138*5552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 4139*5552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 4140*5552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 4141*5552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d", f, jj, ii); 4142*5552b385SBrandon #if 0 4143*5552b385SBrandon // Cycle through each direction (x, then y, then z) 4144*5552b385SBrandon if (jj == 0) { 4145*5552b385SBrandon // Get the Number Control Points that are the same as the current points 4146*5552b385SBrandon // We are looking for repeated Control Points 4147*5552b385SBrandon PetscInt commonCPcntr = 0; 4148*5552b385SBrandon for (int mm = 0; mm < bpinfo[2]*bpinfo[5]; ++mm) { 4149*5552b385SBrandon PetscScalar matValue; 4150*5552b385SBrandon PetscCall(MatGetValue(cpEquiv, faceWStartRow + ii, faceWStartRow + mm, &matValue)); 4151*5552b385SBrandon 4152*5552b385SBrandon if (matValue > 0.0) commonCPcntr += 1; 4153*5552b385SBrandon } 4154*5552b385SBrandon } 4155*5552b385SBrandon #endif 4156*5552b385SBrandon 4157*5552b385SBrandon for (int kk = 0; kk < 4; ++kk) { 4158*5552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 4159*5552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 4160*5552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4161*5552b385SBrandon 4162*5552b385SBrandon if (kk == 0) { //X 4163*5552b385SBrandon nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 4164*5552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 4165*5552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 4166*5552b385SBrandon denomNew = nbprv[offset + 0]; 4167*5552b385SBrandon denomOld = bprv[offset + 0]; 4168*5552b385SBrandon } else if (kk == 1) { //Y 4169*5552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 4170*5552b385SBrandon nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 4171*5552b385SBrandon nbprv[offset + 2] = bprv[offset + 2]; 4172*5552b385SBrandon denomNew = nbprv[offset + 1]; 4173*5552b385SBrandon denomOld = bprv[offset + 1]; 4174*5552b385SBrandon } else if (kk == 2) { //Z 4175*5552b385SBrandon nbprv[offset + 0] = bprv[offset + 0]; 4176*5552b385SBrandon nbprv[offset + 1] = bprv[offset + 1]; 4177*5552b385SBrandon nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 4178*5552b385SBrandon denomNew = nbprv[offset + 2]; 4179*5552b385SBrandon denomOld = bprv[offset + 2]; 4180*5552b385SBrandon } else if (kk == 3) { // Weights 4181*5552b385SBrandon nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 4182*5552b385SBrandon denomNew = nbprv[wOffset + ii]; 4183*5552b385SBrandon denomOld = bprv[wOffset + ii]; 4184*5552b385SBrandon } else { 4185*5552b385SBrandon // currently do nothing 4186*5552b385SBrandon } 4187*5552b385SBrandon 4188*5552b385SBrandon // Create New Surface Based on New Control Points or Weights 4189*5552b385SBrandon ego newgeom, context; 4190*5552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // This does not have an EGlite_ version KNOWN_ISSUE 4191*5552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // This does not have an EGlite_ version KNOWN_ISSUE 4192*5552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4193*5552b385SBrandon 4194*5552b385SBrandon // Evaluate new (x, y, z) Point Position based on new Surface Definition 4195*5552b385SBrandon double newCoords[18]; 4196*5552b385SBrandon if (islite) PetscCall(EGlite_getRange(newgeom, range, &peri)); 4197*5552b385SBrandon else PetscCall(EG_getRange(newgeom, range, &peri)); 4198*5552b385SBrandon 4199*5552b385SBrandon PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 4200*5552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4201*5552b385SBrandon 4202*5552b385SBrandon if (islite) PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 4203*5552b385SBrandon else PetscCall(EG_evaluate(newgeom, params, newCoords)); 4204*5552b385SBrandon 4205*5552b385SBrandon // Calculate Surface Area Gradients wrt Control Points and Weights using the local discrete FACE only 4206*5552b385SBrandon // NOTE 1: Will not provide Volume Gradient wrt to Control Points and Weights. 4207*5552b385SBrandon // NOTE 2: This is faster than below where an entire new solid geometry is created for each 4208*5552b385SBrandon // Control Point and Weight gradient 4209*5552b385SBrandon if (!fullGeomGrad) { 4210*5552b385SBrandon // Create new FACE based on new SURFACE geometry 4211*5552b385SBrandon if (jj == 0) { // only for 1st DMPlex Point because we only per CP or Weight 4212*5552b385SBrandon double newFaceRange[4]; 4213*5552b385SBrandon int newFacePeri; 4214*5552b385SBrandon if (islite) PetscCall(EGlite_getRange(newgeom, newFaceRange, &newFacePeri)); 4215*5552b385SBrandon else PetscCall(EG_getRange(newgeom, newFaceRange, &newFacePeri)); 4216*5552b385SBrandon 4217*5552b385SBrandon ego newface; 4218*5552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have EGlite version KNOWN_ISSUE 4219*5552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4220*5552b385SBrandon 4221*5552b385SBrandon // Get New Face Surface Area 4222*5552b385SBrandon PetscScalar newfSA, newFaceData[14]; 4223*5552b385SBrandon PetscCall(EG_getMassProperties(newface, newFaceData)); // Does not have EGlite version KNOWN_ISSUE 4224*5552b385SBrandon newfSA = newFaceData[1]; 4225*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newface)); 4226*5552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4227*5552b385SBrandon 4228*5552b385SBrandon // Update Control Points 4229*5552b385SBrandon PetscHashIter CPiter, Witer; 4230*5552b385SBrandon PetscBool CPfound, Wfound; 4231*5552b385SBrandon PetscInt faceCPStartRow, faceWStartRow; 4232*5552b385SBrandon 4233*5552b385SBrandon PetscScalar dSAdCPi; 4234*5552b385SBrandon dSAdCPi = (newfSA - fSA) / (denomNew - denomOld); 4235*5552b385SBrandon 4236*5552b385SBrandon if (kk < 3) { 4237*5552b385SBrandon PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, fid, &CPiter, &CPfound)); 4238*5552b385SBrandon PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4239*5552b385SBrandon PetscCall(PetscHMapIGet(faceCntrlPtRow_Start, fid, &faceCPStartRow)); 4240*5552b385SBrandon 4241*5552b385SBrandon gradSACP[faceCPStartRow + (ii * 3) + kk] = dSAdCPi; 4242*5552b385SBrandon 4243*5552b385SBrandon if (PetscAbsReal(dSAdCPi) > maxGrad) maxGrad = PetscAbsReal(dSAdCPi); 4244*5552b385SBrandon 4245*5552b385SBrandon } else if (kk == 3) { 4246*5552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 4247*5552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4248*5552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 4249*5552b385SBrandon 4250*5552b385SBrandon gradSAW[faceWStartRow + ii] = dSAdCPi; 4251*5552b385SBrandon 4252*5552b385SBrandon } else { 4253*5552b385SBrandon // Do Nothing 4254*5552b385SBrandon } 4255*5552b385SBrandon } 4256*5552b385SBrandon } 4257*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newgeom)); 4258*5552b385SBrandon 4259*5552b385SBrandon // Now Calculate the Surface Gradient for the change in x-component Control Point 4260*5552b385SBrandon PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 4261*5552b385SBrandon PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 4262*5552b385SBrandon PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 4263*5552b385SBrandon 4264*5552b385SBrandon // Store Gradient Information in surfaceGrad[][] Matrix 4265*5552b385SBrandon PetscInt startRow; 4266*5552b385SBrandon PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 4267*5552b385SBrandon 4268*5552b385SBrandon // Store Results in Petsc Matrix 4269*5552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 4270*5552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 4271*5552b385SBrandon PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 4272*5552b385SBrandon 4273*5552b385SBrandon //PetscCallEGADS(EG_deleteObject, (newgeom)); 4274*5552b385SBrandon PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face is corrupted"); 4275*5552b385SBrandon } 4276*5552b385SBrandon offset += 3; 4277*5552b385SBrandon } 4278*5552b385SBrandon PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 4279*5552b385SBrandon } 4280*5552b385SBrandon } 4281*5552b385SBrandon 4282*5552b385SBrandon // Assemble Point Surface Grad Matrix 4283*5552b385SBrandon PetscCall(MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 4284*5552b385SBrandon PetscCall(MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 4285*5552b385SBrandon 4286*5552b385SBrandon if (fullGeomGrad) { 4287*5552b385SBrandon // Calculate Surface Area and Volume Control Point and Control Point Weight Gradients 4288*5552b385SBrandon // Note: This is much slower than above due to a new solid geometry being created for 4289*5552b385SBrandon // each change in Control Point and Control Point Weight. However, this method 4290*5552b385SBrandon // will provide the Volume Gradient. 4291*5552b385SBrandon 4292*5552b385SBrandon // Get Current Face Surface Area 4293*5552b385SBrandon PetscScalar bodyVol, bodySA, bodyData[14]; 4294*5552b385SBrandon PetscCall(EG_getMassProperties(body, bodyData)); // Does not have an EGlite versin KNOWN_ISSUE 4295*5552b385SBrandon bodyVol = bodyData[0]; 4296*5552b385SBrandon bodySA = bodyData[1]; 4297*5552b385SBrandon 4298*5552b385SBrandon // Cycle through Control Points 4299*5552b385SBrandon for (int ii = 0; ii < totalNumCPs; ++ii) { // ii should also be the row in cpEquiv for the Control Point 4300*5552b385SBrandon // Cycle through X, Y, Z, W changes 4301*5552b385SBrandon for (int jj = 0; jj < 4; ++jj) { 4302*5552b385SBrandon // Cycle Through Faces 4303*5552b385SBrandon double denomNew = 0.0, denomOld = 0.0; 4304*5552b385SBrandon double deltaCoord = 1.0E-4; 4305*5552b385SBrandon ego newGeom[Nf]; 4306*5552b385SBrandon ego newFaces[Nf]; 4307*5552b385SBrandon for (int kk = 0; kk < Nf; ++kk) { 4308*5552b385SBrandon ego face; 4309*5552b385SBrandon PetscInt currFID = kk + 1; 4310*5552b385SBrandon 4311*5552b385SBrandon if (islite) { 4312*5552b385SBrandon // Get Current FACE 4313*5552b385SBrandon PetscCallEGADS(EGlite_objectBodyTopo, (body, FACE, currFID, &face)); 4314*5552b385SBrandon 4315*5552b385SBrandon // Get Geometry Object for the Current FACE 4316*5552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 4317*5552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4318*5552b385SBrandon } else { 4319*5552b385SBrandon // Get Current FACE 4320*5552b385SBrandon PetscCallEGADS(EG_objectBodyTopo, (body, FACE, currFID, &face)); 4321*5552b385SBrandon 4322*5552b385SBrandon // Get Geometry Object for the Current FACE 4323*5552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 4324*5552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4325*5552b385SBrandon } 4326*5552b385SBrandon 4327*5552b385SBrandon // Make a new SURFACE Geometry by changing the location of the Control Points 4328*5552b385SBrandon int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 4329*5552b385SBrandon double nbprv[prvSize]; 4330*5552b385SBrandon 4331*5552b385SBrandon // Reinitialize nbprv[] values because we only want to change one value at a time 4332*5552b385SBrandon for (int mm = 0; mm < prvSize; ++mm) nbprv[mm] = bprv[mm]; 4333*5552b385SBrandon 4334*5552b385SBrandon // Get Control Point Row and Column Start for cpEquiv 4335*5552b385SBrandon PetscHashIter Witer; 4336*5552b385SBrandon PetscBool Wfound; 4337*5552b385SBrandon PetscInt faceWStartRow; 4338*5552b385SBrandon PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, currFID, &Witer, &Wfound)); 4339*5552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4340*5552b385SBrandon PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, currFID, &faceWStartRow)); 4341*5552b385SBrandon 4342*5552b385SBrandon // Modify the Current Control Point on this FACE and All Other FACES 4343*5552b385SBrandon // IMPORTANT!!! If you do not move all identical Control Points on other FACES 4344*5552b385SBrandon // you will not generate a solid body. You will generate a set of 4345*5552b385SBrandon // disconnected surfaces that have gap(s) between them. 4346*5552b385SBrandon int offset = bpinfo[3] + bpinfo[6]; 4347*5552b385SBrandon int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 4348*5552b385SBrandon for (int mm = 0; mm < bpinfo[2] * bpinfo[5]; ++mm) { 4349*5552b385SBrandon PetscScalar matValue; 4350*5552b385SBrandon PetscCall(MatGetValue(cpEquiv, ii, faceWStartRow + mm, &matValue)); 4351*5552b385SBrandon 4352*5552b385SBrandon if (matValue > 0.0) { 4353*5552b385SBrandon if (jj == 0) { //X 4354*5552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0] + deltaCoord; 4355*5552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 4356*5552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 4357*5552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 0]; 4358*5552b385SBrandon denomOld = bprv[offset + (3 * mm) + 0]; 4359*5552b385SBrandon } else if (jj == 1) { //Y 4360*5552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 4361*5552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1] + deltaCoord; 4362*5552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 4363*5552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 1]; 4364*5552b385SBrandon denomOld = bprv[offset + (3 * mm) + 1]; 4365*5552b385SBrandon } else if (jj == 2) { //Z 4366*5552b385SBrandon nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 4367*5552b385SBrandon nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 4368*5552b385SBrandon nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2] + deltaCoord; 4369*5552b385SBrandon denomNew = nbprv[offset + (3 * mm) + 2]; 4370*5552b385SBrandon denomOld = bprv[offset + (3 * mm) + 2]; 4371*5552b385SBrandon } else if (jj == 3) { // Weights 4372*5552b385SBrandon nbprv[wOffset + mm] = bprv[wOffset + mm] + deltaCoord; 4373*5552b385SBrandon denomNew = nbprv[wOffset + mm]; 4374*5552b385SBrandon denomOld = bprv[wOffset + mm]; 4375*5552b385SBrandon } else { 4376*5552b385SBrandon // currently do nothing 4377*5552b385SBrandon } 4378*5552b385SBrandon } 4379*5552b385SBrandon } 4380*5552b385SBrandon 4381*5552b385SBrandon // Create New Surface Based on New Control Points or Weights 4382*5552b385SBrandon ego newgeom, context; 4383*5552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ versions KNOWN_ISSUE 4384*5552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 4385*5552b385SBrandon 4386*5552b385SBrandon // Create New FACE based on modified geometry 4387*5552b385SBrandon double newFaceRange[4]; 4388*5552b385SBrandon int newFacePeri; 4389*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, newFaceRange, &newFacePeri)); 4390*5552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, newFaceRange, &newFacePeri)); 4391*5552b385SBrandon 4392*5552b385SBrandon ego newface; 4393*5552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 4394*5552b385SBrandon 4395*5552b385SBrandon // store new face for later assembly 4396*5552b385SBrandon newGeom[kk] = newgeom; 4397*5552b385SBrandon newFaces[kk] = newface; 4398*5552b385SBrandon } 4399*5552b385SBrandon 4400*5552b385SBrandon // X-WANT TO BUILD THE NEW GEOMETRY, X-GET NEW SA AND PERFORM dSA/dCPi CALCS HERE <--- 4401*5552b385SBrandon // Sew New Faces together to get a new model 4402*5552b385SBrandon ego newmodel; 4403*5552b385SBrandon PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 4404*5552b385SBrandon 4405*5552b385SBrandon // Get Surface Area and Volume of New/Updated Solid Body 4406*5552b385SBrandon PetscScalar newData[14]; 4407*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4408*5552b385SBrandon else PetscCallEGADS(EG_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4409*5552b385SBrandon 4410*5552b385SBrandon ego nbody = bodies[0]; 4411*5552b385SBrandon PetscCall(EG_getMassProperties(nbody, newData)); // Does not have an EGlite_ version KNOWN_ISSUE 4412*5552b385SBrandon 4413*5552b385SBrandon PetscScalar dSAdCPi, dVdCPi; 4414*5552b385SBrandon PetscScalar nbodyVol = newData[0], nbodySA = newData[1]; 4415*5552b385SBrandon 4416*5552b385SBrandon // Calculate Gradients wrt to Control Points and Control Points Weights depending on jj value 4417*5552b385SBrandon dSAdCPi = (nbodySA - bodySA) / (denomNew - denomOld); 4418*5552b385SBrandon dVdCPi = (nbodyVol - bodyVol) / (denomNew - denomOld); 4419*5552b385SBrandon 4420*5552b385SBrandon if (jj < 3) { 4421*5552b385SBrandon // Gradienst wrt to Control Points 4422*5552b385SBrandon gradSACP[(ii * 3) + jj] = dSAdCPi; 4423*5552b385SBrandon gradVCP[(ii * 3) + jj] = dVdCPi; 4424*5552b385SBrandon } else if (jj == 3) { 4425*5552b385SBrandon // Gradients wrt to Control Point Weights 4426*5552b385SBrandon gradSAW[ii] = dSAdCPi; 4427*5552b385SBrandon gradVW[ii] = dVdCPi; 4428*5552b385SBrandon } else { 4429*5552b385SBrandon // Do Nothing 4430*5552b385SBrandon } 4431*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newmodel)); 4432*5552b385SBrandon for (int kk = 0; kk < Nf; ++kk) { 4433*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[kk])); 4434*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[kk])); 4435*5552b385SBrandon } 4436*5552b385SBrandon } 4437*5552b385SBrandon } 4438*5552b385SBrandon } 4439*5552b385SBrandon PetscCall(VecRestoreArrayWrite(gradSACPVec, &gradSACP)); 4440*5552b385SBrandon PetscCall(VecRestoreArrayWrite(gradSAWVec, &gradSAW)); 4441*5552b385SBrandon PetscCall(VecRestoreArrayWrite(gradVCPVec, &gradVCP)); 4442*5552b385SBrandon PetscCall(VecRestoreArrayWrite(gradVWVec, &gradVW)); 4443*5552b385SBrandon PetscCall(MatDestroy(&cpEquiv)); 4444*5552b385SBrandon 4445*5552b385SBrandon // Attach Surface Gradient Hash Table and Matrix to DM 4446*5552b385SBrandon { 4447*5552b385SBrandon PetscContainer surfGradOrgObj; 4448*5552b385SBrandon 4449*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&surfGradOrgObj)); 4450*5552b385SBrandon if (!surfGradOrgObj) { 4451*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 4452*5552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 4453*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(surfGradOrgObj, DestroyHashMap)); 4454*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 4455*5552b385SBrandon PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 4456*5552b385SBrandon } else { 4457*5552b385SBrandon PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 4458*5552b385SBrandon } 4459*5552b385SBrandon 4460*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)pointSurfGrad)); 4461*5552b385SBrandon PetscCall(MatDestroy(&pointSurfGrad)); 4462*5552b385SBrandon 4463*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject)gradSACPVec)); 4464*5552b385SBrandon PetscCall(VecDestroy(&gradSACPVec)); 4465*5552b385SBrandon 4466*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject)gradSAWVec)); 4467*5552b385SBrandon PetscCall(VecDestroy(&gradSAWVec)); 4468*5552b385SBrandon 4469*5552b385SBrandon if (fullGeomGrad) { 4470*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Control Point Gradient", (PetscObject)gradVCPVec)); 4471*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Weights Gradient", (PetscObject)gradVWVec)); 4472*5552b385SBrandon } 4473*5552b385SBrandon PetscCall(VecDestroy(&gradVCPVec)); 4474*5552b385SBrandon PetscCall(VecDestroy(&gradVWVec)); 4475*5552b385SBrandon } 4476*5552b385SBrandon 4477*5552b385SBrandon // Could be replaced with DMPlexFreeGeomObject() 4478*5552b385SBrandon if (islite) EGlite_free(fobjs); 4479*5552b385SBrandon else EG_free(fobjs); 4480*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 4481*5552b385SBrandon #else 4482*5552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 4483*5552b385SBrandon #endif 4484*5552b385SBrandon } 4485*5552b385SBrandon 4486*5552b385SBrandon /*@C 4487*5552b385SBrandon 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. 4488*5552b385SBrandon 4489*5552b385SBrandon Collective 4490*5552b385SBrandon 4491*5552b385SBrandon Input Parameters: 4492*5552b385SBrandon + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 4493*5552b385SBrandon . comm - MPI_Comm object 4494*5552b385SBrandon . newCP - C Array of [x, y, z] New/Updated Control Point Coordinates defining the geometry (See DMPlexGeomDataAndGrads() for format) 4495*5552b385SBrandon . newW - C Array of New/Updated Control Point Weights associated with the Control Points defining the new geometry (See DMPlexGemGrads() for format) 4496*5552b385SBrandon . autoInflate - PetscBool Flag denoting if the user would like to inflate the DM points to the new geometry. 4497*5552b385SBrandon . saveGeom - PetscBool Flag denoting if the user would iike to save the new geometry to a file. 4498*5552b385SBrandon - 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. 4499*5552b385SBrandon *.stp or *.step = STEP File 4500*5552b385SBrandon *.igs or *.iges = IGES File 4501*5552b385SBrandon *.egads = EGADS File 4502*5552b385SBrandon *.brep = BRep File (OpenCASCADE File) 4503*5552b385SBrandon 4504*5552b385SBrandon Output Parameter: 4505*5552b385SBrandon . dm - The updated DM object representing the mesh with PetscContainers containing the updated/modified geometry 4506*5552b385SBrandon 4507*5552b385SBrandon Level: intermediate 4508*5552b385SBrandon 4509*5552b385SBrandon Note: 4510*5552b385SBrandon Functionality not available for DMPlexes with attached EGADSlite geometry files (.egadslite). 4511*5552b385SBrandon 4512*5552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 4513*5552b385SBrandon @*/ 4514*5552b385SBrandon PetscErrorCode DMPlexModifyGeomModel(DM dm, MPI_Comm comm, PetscScalar newCP[], PetscScalar newW[], PetscBool autoInflate, PetscBool saveGeom, const char *stpName) 4515*5552b385SBrandon { 4516*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 4517*5552b385SBrandon /* EGADS/EGADSlite variables */ 4518*5552b385SBrandon ego context, model, geom, *bodies, *lobjs, *fobjs; 4519*5552b385SBrandon int oclass, mtype, *senses, *lsenses; 4520*5552b385SBrandon int Nb, Nf, Nl, id; 4521*5552b385SBrandon /* PETSc variables */ 4522*5552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 4523*5552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj; 4524*5552b385SBrandon PetscHMapI cpHashTable = NULL, wHashTable = NULL; 4525*5552b385SBrandon PetscBool islite = PETSC_FALSE; 4526*5552b385SBrandon #endif 4527*5552b385SBrandon 4528*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 4529*5552b385SBrandon PetscFunctionBegin; 4530*5552b385SBrandon // Look to see if DM has a Container with either a EGADS or EGADSlite Model 4531*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 4532*5552b385SBrandon if (!modelObj) { 4533*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 4534*5552b385SBrandon islite = PETSC_TRUE; 4535*5552b385SBrandon } 4536*5552b385SBrandon 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"); 4537*5552b385SBrandon PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have a EGADS Geometry Model attached to it!"); 4538*5552b385SBrandon 4539*5552b385SBrandon // Get attached EGADS model (pointer) 4540*5552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 4541*5552b385SBrandon 4542*5552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 4543*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 4544*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 4545*5552b385SBrandon 4546*5552b385SBrandon PetscCheck(cpHashTableObj && wHashTableObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have required Geometry Data attached! Please run DMPlexGeomDataAndGrads() Function first."); 4547*5552b385SBrandon 4548*5552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 4549*5552b385SBrandon PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTable)); 4550*5552b385SBrandon PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTable)); 4551*5552b385SBrandon 4552*5552b385SBrandon // Get the number of bodies and body objects in the model 4553*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4554*5552b385SBrandon else PetscCallEGADS(EG_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4555*5552b385SBrandon 4556*5552b385SBrandon // Get all Faces on the body 4557*5552b385SBrandon ego body = bodies[0]; 4558*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4559*5552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4560*5552b385SBrandon 4561*5552b385SBrandon ego newGeom[Nf]; 4562*5552b385SBrandon ego newFaces[Nf]; 4563*5552b385SBrandon 4564*5552b385SBrandon // Update Control Point and Weight definitions for each surface 4565*5552b385SBrandon for (int jj = 0; jj < Nf; ++jj) { 4566*5552b385SBrandon ego face = fobjs[jj]; 4567*5552b385SBrandon ego bRef, bPrev, bNext; 4568*5552b385SBrandon ego fgeom; 4569*5552b385SBrandon int offset; 4570*5552b385SBrandon int boclass, bmtype, *bpinfo; 4571*5552b385SBrandon double *bprv; 4572*5552b385SBrandon 4573*5552b385SBrandon // Get FACE ID and other Geometry Data 4574*5552b385SBrandon if (islite) { 4575*5552b385SBrandon id = EGlite_indexBodyTopo(body, face); 4576*5552b385SBrandon PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 4577*5552b385SBrandon PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4578*5552b385SBrandon PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 4579*5552b385SBrandon } else { 4580*5552b385SBrandon id = EG_indexBodyTopo(body, face); 4581*5552b385SBrandon PetscCallEGADS(EG_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 4582*5552b385SBrandon PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4583*5552b385SBrandon PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 4584*5552b385SBrandon } 4585*5552b385SBrandon 4586*5552b385SBrandon // Update Control Points 4587*5552b385SBrandon PetscHashIter CPiter, Witer; 4588*5552b385SBrandon PetscBool CPfound, Wfound; 4589*5552b385SBrandon PetscInt faceCPStartRow, faceWStartRow; 4590*5552b385SBrandon 4591*5552b385SBrandon PetscCall(PetscHMapIFind(cpHashTable, id, &CPiter, &CPfound)); 4592*5552b385SBrandon PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4593*5552b385SBrandon PetscCall(PetscHMapIGet(cpHashTable, id, &faceCPStartRow)); 4594*5552b385SBrandon 4595*5552b385SBrandon PetscCall(PetscHMapIFind(wHashTable, id, &Witer, &Wfound)); 4596*5552b385SBrandon PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4597*5552b385SBrandon PetscCall(PetscHMapIGet(wHashTable, id, &faceWStartRow)); 4598*5552b385SBrandon 4599*5552b385SBrandon // UPDATE CONTROL POINTS Locations 4600*5552b385SBrandon offset = bpinfo[3] + bpinfo[6]; 4601*5552b385SBrandon for (int ii = 0; ii < 3 * bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newCP[faceCPStartRow + ii]; } 4602*5552b385SBrandon 4603*5552b385SBrandon // UPDATE CONTROL POINT WEIGHTS 4604*5552b385SBrandon offset = bpinfo[3] + bpinfo[6] + 3 * bpinfo[2] * bpinfo[5]; 4605*5552b385SBrandon for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newW[faceWStartRow + ii]; } 4606*5552b385SBrandon 4607*5552b385SBrandon // Get Context from FACE 4608*5552b385SBrandon context = NULL; 4609*5552b385SBrandon PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version KNOWN_ISSUE 4610*5552b385SBrandon 4611*5552b385SBrandon // Create New Surface 4612*5552b385SBrandon ego newgeom; 4613*5552b385SBrandon PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 4614*5552b385SBrandon 4615*5552b385SBrandon // Create new FACE based on new SURFACE geometry 4616*5552b385SBrandon double data[4]; 4617*5552b385SBrandon int periodic; 4618*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 4619*5552b385SBrandon else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 4620*5552b385SBrandon 4621*5552b385SBrandon ego newface; 4622*5552b385SBrandon PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 4623*5552b385SBrandon newGeom[jj] = newgeom; 4624*5552b385SBrandon newFaces[jj] = newface; 4625*5552b385SBrandon } 4626*5552b385SBrandon // Could be replaced by DMPlexFreeGeomObject 4627*5552b385SBrandon if (islite) EGlite_free(fobjs); 4628*5552b385SBrandon else EG_free(fobjs); 4629*5552b385SBrandon 4630*5552b385SBrandon // Sew New Faces together to get a new model 4631*5552b385SBrandon ego newmodel; 4632*5552b385SBrandon PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 4633*5552b385SBrandon for (PetscInt f = 0; f < Nf; ++f) { 4634*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newFaces[f])); 4635*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (newGeom[f])); 4636*5552b385SBrandon } 4637*5552b385SBrandon 4638*5552b385SBrandon // Get the total number of NODEs on the original geometry. (This will be the same for the new geometry) 4639*5552b385SBrandon int totalNumNode; 4640*5552b385SBrandon ego *nobjTotal; 4641*5552b385SBrandon if (islite) { 4642*5552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 4643*5552b385SBrandon EGlite_free(nobjTotal); 4644*5552b385SBrandon } else { 4645*5552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 4646*5552b385SBrandon EG_free(nobjTotal); 4647*5552b385SBrandon } // Could be replaced with DMPlexFreeGeomObject 4648*5552b385SBrandon 4649*5552b385SBrandon // Initialize vector to store equivalent NODE indices between the 2 geometries 4650*5552b385SBrandon // FORMAT :: vector index is the Original Geometry's NODE ID, the vector Value is the New Geometry's NODE ID 4651*5552b385SBrandon int nodeIDEquiv[totalNumNode + 1]; 4652*5552b385SBrandon 4653*5552b385SBrandon // Now we need to Map the NODE and EDGE IDs from each Model 4654*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4655*5552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4656*5552b385SBrandon 4657*5552b385SBrandon // New CAD 4658*5552b385SBrandon ego *newbodies, newgeomtest, *nfobjs; 4659*5552b385SBrandon int nNf, newNb, newoclass, newmtype, *newsenses; 4660*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 4661*5552b385SBrandon else PetscCallEGADS(EG_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 4662*5552b385SBrandon 4663*5552b385SBrandon ego newbody = newbodies[0]; 4664*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 4665*5552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 4666*5552b385SBrandon 4667*5552b385SBrandon PetscCheck(newNb == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ERROR :: newNb > 1 || newNb = %d", newNb); 4668*5552b385SBrandon 4669*5552b385SBrandon // Find Equivalent Nodes 4670*5552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 4671*5552b385SBrandon double fdata[4]; 4672*5552b385SBrandon int peri; 4673*5552b385SBrandon 4674*5552b385SBrandon // Get Current FACE [u, v] Ranges 4675*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getRange, (fobjs[ii], fdata, &peri)); 4676*5552b385SBrandon else PetscCallEGADS(EG_getRange, (fobjs[ii], fdata, &peri)); 4677*5552b385SBrandon 4678*5552b385SBrandon // Equate NODE IDs between 2 FACEs by working through (u, v) limits of FACE 4679*5552b385SBrandon for (int jj = 0; jj < 2; ++jj) { 4680*5552b385SBrandon for (int kk = 2; kk < 4; ++kk) { 4681*5552b385SBrandon double params[2] = {fdata[jj], fdata[kk]}; 4682*5552b385SBrandon double eval[18]; 4683*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (fobjs[ii], params, eval)); 4684*5552b385SBrandon else PetscCallEGADS(EG_evaluate, (fobjs[ii], params, eval)); 4685*5552b385SBrandon 4686*5552b385SBrandon // Original Body 4687*5552b385SBrandon ego *nobjsOrigFace; 4688*5552b385SBrandon int origNn; 4689*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 4690*5552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 4691*5552b385SBrandon 4692*5552b385SBrandon double minVal = 1.0E10; 4693*5552b385SBrandon double evalCheck[18]; 4694*5552b385SBrandon int equivOrigNodeID = -1; 4695*5552b385SBrandon for (int mm = 0; mm < origNn; ++mm) { 4696*5552b385SBrandon double delta = 1.0E10; 4697*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 4698*5552b385SBrandon else PetscCallEGADS(EG_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 4699*5552b385SBrandon 4700*5552b385SBrandon delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 4701*5552b385SBrandon 4702*5552b385SBrandon if (delta < minVal) { 4703*5552b385SBrandon if (islite) equivOrigNodeID = EGlite_indexBodyTopo(body, nobjsOrigFace[mm]); 4704*5552b385SBrandon else equivOrigNodeID = EG_indexBodyTopo(body, nobjsOrigFace[mm]); 4705*5552b385SBrandon 4706*5552b385SBrandon minVal = delta; 4707*5552b385SBrandon } 4708*5552b385SBrandon } 4709*5552b385SBrandon // Could be replaced with DMPlexFreeGeomObject 4710*5552b385SBrandon if (islite) EGlite_free(nobjsOrigFace); 4711*5552b385SBrandon else EG_free(nobjsOrigFace); 4712*5552b385SBrandon 4713*5552b385SBrandon // New Body 4714*5552b385SBrandon ego *nobjsNewFace; 4715*5552b385SBrandon int newNn; 4716*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 4717*5552b385SBrandon else PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 4718*5552b385SBrandon 4719*5552b385SBrandon minVal = 1.0E10; 4720*5552b385SBrandon int equivNewNodeID = -1; 4721*5552b385SBrandon for (int mm = 0; mm < newNn; ++mm) { 4722*5552b385SBrandon double delta = 1.0E10; 4723*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 4724*5552b385SBrandon else PetscCallEGADS(EG_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 4725*5552b385SBrandon 4726*5552b385SBrandon delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 4727*5552b385SBrandon 4728*5552b385SBrandon if (delta < minVal) { 4729*5552b385SBrandon if (islite) equivNewNodeID = EGlite_indexBodyTopo(newbody, nobjsNewFace[mm]); 4730*5552b385SBrandon else equivNewNodeID = EG_indexBodyTopo(newbody, nobjsNewFace[mm]); 4731*5552b385SBrandon 4732*5552b385SBrandon minVal = delta; 4733*5552b385SBrandon } 4734*5552b385SBrandon } 4735*5552b385SBrandon if (islite) EGlite_free(nobjsNewFace); 4736*5552b385SBrandon else EG_free(nobjsNewFace); 4737*5552b385SBrandon 4738*5552b385SBrandon // Store equivalent NODE IDs 4739*5552b385SBrandon nodeIDEquiv[equivOrigNodeID] = equivNewNodeID; 4740*5552b385SBrandon } 4741*5552b385SBrandon } 4742*5552b385SBrandon } 4743*5552b385SBrandon 4744*5552b385SBrandon // Find Equivalent EDGEs 4745*5552b385SBrandon // Get total number of EDGEs on Original Geometry 4746*5552b385SBrandon int totalNumEdge; 4747*5552b385SBrandon ego *eobjsOrig; 4748*5552b385SBrandon if (islite) { 4749*5552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 4750*5552b385SBrandon EGlite_free(eobjsOrig); 4751*5552b385SBrandon } else { 4752*5552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 4753*5552b385SBrandon EG_free(eobjsOrig); 4754*5552b385SBrandon } 4755*5552b385SBrandon 4756*5552b385SBrandon // Get total number of EDGEs on New Geometry 4757*5552b385SBrandon int totalNumEdgeNew; 4758*5552b385SBrandon ego *eobjsNew; 4759*5552b385SBrandon if (islite) { 4760*5552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 4761*5552b385SBrandon EGlite_free(eobjsNew); 4762*5552b385SBrandon } else { 4763*5552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 4764*5552b385SBrandon EG_free(eobjsNew); 4765*5552b385SBrandon } 4766*5552b385SBrandon 4767*5552b385SBrandon // Initialize EDGE ID equivalent vector 4768*5552b385SBrandon // FORMAT :: vector index is the Original Geometry's EDGE ID, the vector Value is the New Geometry's EDGE ID 4769*5552b385SBrandon int edgeIDEquiv[totalNumEdge + 1]; 4770*5552b385SBrandon 4771*5552b385SBrandon // Find Equivalent EDGEs 4772*5552b385SBrandon for (int ii = 0; ii < Nf; ++ii) { 4773*5552b385SBrandon // Get Original Geometry EDGE's NODEs 4774*5552b385SBrandon int numOrigEdge, numNewEdge; 4775*5552b385SBrandon if (islite) { 4776*5552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 4777*5552b385SBrandon PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 4778*5552b385SBrandon } else { 4779*5552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 4780*5552b385SBrandon PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 4781*5552b385SBrandon } 4782*5552b385SBrandon 4783*5552b385SBrandon // new loop below 4784*5552b385SBrandon for (int nn = 0; nn < numOrigEdge; ++nn) { 4785*5552b385SBrandon ego origEdge = eobjsOrig[nn]; 4786*5552b385SBrandon ego geomEdgeOrig, *nobjsOrig; 4787*5552b385SBrandon int oclassEdgeOrig, mtypeEdgeOrig; 4788*5552b385SBrandon int NnOrig, *nsensesEdgeOrig; 4789*5552b385SBrandon 4790*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 4791*5552b385SBrandon else PetscCallEGADS(EG_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 4792*5552b385SBrandon 4793*5552b385SBrandon PetscBool isSame = PETSC_FALSE; 4794*5552b385SBrandon for (int jj = 0; jj < numNewEdge; ++jj) { 4795*5552b385SBrandon ego newEdge = eobjsNew[jj]; 4796*5552b385SBrandon ego geomEdgeNew, *nobjsNew; 4797*5552b385SBrandon int oclassEdgeNew, mtypeEdgeNew; 4798*5552b385SBrandon int NnNew, *nsensesEdgeNew; 4799*5552b385SBrandon 4800*5552b385SBrandon if (islite) PetscCallEGADS(EGlite_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 4801*5552b385SBrandon else PetscCallEGADS(EG_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 4802*5552b385SBrandon 4803*5552b385SBrandon if (mtypeEdgeOrig == mtypeEdgeNew) { 4804*5552b385SBrandon // Only operate if the EDGE types are the same 4805*5552b385SBrandon for (int kk = 0; kk < NnNew; ++kk) { 4806*5552b385SBrandon int nodeIDOrigGeom, nodeIDNewGeom; 4807*5552b385SBrandon if (islite) { 4808*5552b385SBrandon nodeIDOrigGeom = EGlite_indexBodyTopo(body, nobjsOrig[kk]); 4809*5552b385SBrandon nodeIDNewGeom = EGlite_indexBodyTopo(newbody, nobjsNew[kk]); 4810*5552b385SBrandon } else { 4811*5552b385SBrandon nodeIDOrigGeom = EG_indexBodyTopo(body, nobjsOrig[kk]); 4812*5552b385SBrandon nodeIDNewGeom = EG_indexBodyTopo(newbody, nobjsNew[kk]); 4813*5552b385SBrandon } 4814*5552b385SBrandon 4815*5552b385SBrandon if (nodeIDNewGeom == nodeIDEquiv[nodeIDOrigGeom]) { 4816*5552b385SBrandon isSame = PETSC_TRUE; 4817*5552b385SBrandon } else { 4818*5552b385SBrandon isSame = PETSC_FALSE; 4819*5552b385SBrandon kk = NnNew; // skip ahead because first NODE failed test and order is important 4820*5552b385SBrandon } 4821*5552b385SBrandon } 4822*5552b385SBrandon 4823*5552b385SBrandon if (isSame == PETSC_TRUE) { 4824*5552b385SBrandon int edgeIDOrig, edgeIDNew; 4825*5552b385SBrandon if (islite) { 4826*5552b385SBrandon edgeIDOrig = EGlite_indexBodyTopo(body, origEdge); 4827*5552b385SBrandon edgeIDNew = EGlite_indexBodyTopo(newbody, newEdge); 4828*5552b385SBrandon } else { 4829*5552b385SBrandon edgeIDOrig = EG_indexBodyTopo(body, origEdge); 4830*5552b385SBrandon edgeIDNew = EG_indexBodyTopo(newbody, newEdge); 4831*5552b385SBrandon } 4832*5552b385SBrandon 4833*5552b385SBrandon edgeIDEquiv[edgeIDOrig] = edgeIDNew; 4834*5552b385SBrandon jj = numNewEdge; 4835*5552b385SBrandon } 4836*5552b385SBrandon } 4837*5552b385SBrandon } 4838*5552b385SBrandon } 4839*5552b385SBrandon if (islite) { 4840*5552b385SBrandon EGlite_free(eobjsOrig); 4841*5552b385SBrandon EGlite_free(eobjsNew); 4842*5552b385SBrandon } else { 4843*5552b385SBrandon EG_free(eobjsOrig); 4844*5552b385SBrandon EG_free(eobjsNew); 4845*5552b385SBrandon } 4846*5552b385SBrandon } 4847*5552b385SBrandon if (islite) { 4848*5552b385SBrandon EGlite_free(fobjs); 4849*5552b385SBrandon EGlite_free(nfobjs); 4850*5552b385SBrandon } else { 4851*5552b385SBrandon EG_free(fobjs); 4852*5552b385SBrandon EG_free(nfobjs); 4853*5552b385SBrandon } 4854*5552b385SBrandon 4855*5552b385SBrandon // Modify labels to point to the IDs on the new Geometry 4856*5552b385SBrandon IS isNodeID, isEdgeID; 4857*5552b385SBrandon 4858*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 4859*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 4860*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4861*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 4862*5552b385SBrandon 4863*5552b385SBrandon PetscCall(ISCreateGeneral(comm, totalNumNode + 1, nodeIDEquiv, PETSC_COPY_VALUES, &isNodeID)); 4864*5552b385SBrandon PetscCall(ISCreateGeneral(comm, totalNumEdge + 1, edgeIDEquiv, PETSC_COPY_VALUES, &isEdgeID)); 4865*5552b385SBrandon /* Do not perform check. Np may != Nv due to Degenerate Geometry which is not stored in labels. */ 4866*5552b385SBrandon /* We do not know in advance which IDs have been omitted. This may also change due to geometry modifications. */ 4867*5552b385SBrandon PetscCall(DMLabelRewriteValues(vertexLabel, isNodeID)); 4868*5552b385SBrandon PetscCall(DMLabelRewriteValues(edgeLabel, isEdgeID)); 4869*5552b385SBrandon PetscCall(ISDestroy(&isNodeID)); 4870*5552b385SBrandon PetscCall(ISDestroy(&isEdgeID)); 4871*5552b385SBrandon 4872*5552b385SBrandon // Attempt to point to the new geometry 4873*5552b385SBrandon PetscCallEGADS(EG_deleteObject, (model)); 4874*5552b385SBrandon PetscCall(PetscContainerSetPointer(modelObj, newmodel)); 4875*5552b385SBrandon 4876*5552b385SBrandon // save updated model to file 4877*5552b385SBrandon if (saveGeom == PETSC_TRUE && stpName != NULL) PetscCall(EG_saveModel(newmodel, stpName)); 4878*5552b385SBrandon 4879*5552b385SBrandon // Inflate Mesh to EGADS Model 4880*5552b385SBrandon if (autoInflate == PETSC_TRUE) PetscCall(DMPlexInflateToGeomModel(dm, PETSC_TRUE)); 4881*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 4882*5552b385SBrandon #else 4883*5552b385SBrandon SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 4884*5552b385SBrandon #endif 4885*5552b385SBrandon } 4886*5552b385SBrandon 4887*5552b385SBrandon /*@C 4888*5552b385SBrandon 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. 4889*5552b385SBrandon 4890*5552b385SBrandon Collective 4891*5552b385SBrandon 4892*5552b385SBrandon Input Parameter: 4893*5552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 4894*5552b385SBrandon 4895*5552b385SBrandon Level: intermediate 4896*5552b385SBrandon 4897*5552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 4898*5552b385SBrandon @*/ 4899*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelTUV(DM dm) 4900*5552b385SBrandon { 4901*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 4902*5552b385SBrandon /* EGADS Variables */ 4903*5552b385SBrandon ego model, geom, body, face, edge; 4904*5552b385SBrandon ego *bodies; 4905*5552b385SBrandon int Nb, oclass, mtype, *senses; 4906*5552b385SBrandon double result[4]; 4907*5552b385SBrandon /* PETSc Variables */ 4908*5552b385SBrandon DM cdm; 4909*5552b385SBrandon PetscContainer modelObj; 4910*5552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 4911*5552b385SBrandon Vec coordinates; 4912*5552b385SBrandon PetscScalar *coords; 4913*5552b385SBrandon PetscInt bodyID, faceID, edgeID, vertexID; 4914*5552b385SBrandon PetscInt cdim, vStart, vEnd, v; 4915*5552b385SBrandon PetscBool islite = PETSC_FALSE; 4916*5552b385SBrandon #endif 4917*5552b385SBrandon 4918*5552b385SBrandon PetscFunctionBegin; 4919*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 4920*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 4921*5552b385SBrandon if (!modelObj) { 4922*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 4923*5552b385SBrandon islite = PETSC_TRUE; 4924*5552b385SBrandon } 4925*5552b385SBrandon if (!modelObj) PetscFunctionReturn(0); 4926*5552b385SBrandon 4927*5552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &cdim)); 4928*5552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 4929*5552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 4930*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 4931*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 4932*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4933*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 4934*5552b385SBrandon 4935*5552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 4936*5552b385SBrandon 4937*5552b385SBrandon if (islite) PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4938*5552b385SBrandon else PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4939*5552b385SBrandon 4940*5552b385SBrandon PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 4941*5552b385SBrandon PetscCall(VecGetArrayWrite(coordinates, &coords)); 4942*5552b385SBrandon 4943*5552b385SBrandon // Define t, u, v arrays to be stored in a PetscContainer after populated 4944*5552b385SBrandon PetscScalar *t_point, *u_point, *v_point; 4945*5552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &t_point)); 4946*5552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &u_point)); 4947*5552b385SBrandon PetscCall(PetscMalloc1(vEnd - vStart, &v_point)); 4948*5552b385SBrandon 4949*5552b385SBrandon for (v = vStart; v < vEnd; ++v) { 4950*5552b385SBrandon PetscScalar *vcoords; 4951*5552b385SBrandon 4952*5552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 4953*5552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 4954*5552b385SBrandon PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 4955*5552b385SBrandon PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 4956*5552b385SBrandon 4957*5552b385SBrandon // TODO Figure out why this is unknown sometimes 4958*5552b385SBrandon if (bodyID < 0 && Nb == 1) bodyID = 0; 4959*5552b385SBrandon 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); 4960c1cad2e7SMatthew G. Knepley body = bodies[bodyID]; 4961c1cad2e7SMatthew G. Knepley 49629566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 4963c1cad2e7SMatthew G. Knepley if (edgeID > 0) { 4964c1cad2e7SMatthew G. Knepley /* Snap to EDGE at nearest location */ 4965c1cad2e7SMatthew G. Knepley double params[1]; 4966*5552b385SBrandon 4967*5552b385SBrandon if (islite) { 4968*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 4969*5552b385SBrandon PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 4970*5552b385SBrandon } // Get (t) of nearest point on EDGE 4971*5552b385SBrandon else { 49729566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 4973*5552b385SBrandon PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 4974*5552b385SBrandon } // Get (t) of nearest point on EDGE 4975*5552b385SBrandon 4976*5552b385SBrandon t_point[v - vStart] = params[0]; 4977*5552b385SBrandon u_point[v - vStart] = 0.0; 4978*5552b385SBrandon v_point[v - vStart] = 0.0; 4979c1cad2e7SMatthew G. Knepley } else if (faceID > 0) { 4980c1cad2e7SMatthew G. Knepley /* Snap to FACE at nearest location */ 4981c1cad2e7SMatthew G. Knepley double params[2]; 4982*5552b385SBrandon 4983*5552b385SBrandon if (islite) { 4984*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 4985*5552b385SBrandon PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 4986*5552b385SBrandon } // Get (x,y,z) of nearest point on FACE 4987*5552b385SBrandon else { 49889566063dSJacob Faibussowitsch PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 4989*5552b385SBrandon PetscCall(EG_invEvaluate(face, vcoords, params, result)); 4990*5552b385SBrandon } // Get (x,y,z) of nearest point on FACE 4991*5552b385SBrandon 4992*5552b385SBrandon t_point[v - vStart] = 0.0; 4993*5552b385SBrandon u_point[v - vStart] = params[0]; 4994*5552b385SBrandon v_point[v - vStart] = params[1]; 4995*5552b385SBrandon } else { 4996*5552b385SBrandon t_point[v - vStart] = 0.0; 4997*5552b385SBrandon u_point[v - vStart] = 0.0; 4998*5552b385SBrandon v_point[v - vStart] = 0.0; 4999*5552b385SBrandon } 5000*5552b385SBrandon } 5001*5552b385SBrandon PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 5002*5552b385SBrandon /* Clear out global coordinates */ 5003*5552b385SBrandon PetscCall(VecDestroy(&dm->coordinates[0].x)); 5004*5552b385SBrandon 5005*5552b385SBrandon /* Store in PetscContainters */ 5006*5552b385SBrandon { 5007*5552b385SBrandon PetscContainer t_pointObj, u_pointObj, v_pointObj; 5008*5552b385SBrandon 5009*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 5010*5552b385SBrandon if (!t_pointObj) { 5011*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &t_pointObj)); 5012*5552b385SBrandon PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 5013*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Edge t Parameter", (PetscObject)t_pointObj)); 5014*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(t_pointObj, PetscCtxDestroyDefault)); 5015*5552b385SBrandon PetscCall(PetscContainerDestroy(&t_pointObj)); 5016*5552b385SBrandon } else { 5017*5552b385SBrandon void *old; 5018*5552b385SBrandon 5019*5552b385SBrandon PetscCall(PetscContainerGetPointer(t_pointObj, &old)); 5020*5552b385SBrandon PetscCall(PetscFree(old)); 5021*5552b385SBrandon PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 5022*5552b385SBrandon } 5023*5552b385SBrandon 5024*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 5025*5552b385SBrandon if (!u_pointObj) { 5026*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &u_pointObj)); 5027*5552b385SBrandon PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 5028*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face u Parameter", (PetscObject)u_pointObj)); 5029*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(u_pointObj, PetscCtxDestroyDefault)); 5030*5552b385SBrandon PetscCall(PetscContainerDestroy(&u_pointObj)); 5031*5552b385SBrandon } else { 5032*5552b385SBrandon void *old; 5033*5552b385SBrandon 5034*5552b385SBrandon PetscCall(PetscContainerGetPointer(u_pointObj, &old)); 5035*5552b385SBrandon PetscCall(PetscFree(old)); 5036*5552b385SBrandon PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 5037*5552b385SBrandon } 5038*5552b385SBrandon 5039*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 5040*5552b385SBrandon if (!v_pointObj) { 5041*5552b385SBrandon PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &v_pointObj)); 5042*5552b385SBrandon PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 5043*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face v Parameter", (PetscObject)v_pointObj)); 5044*5552b385SBrandon PetscCall(PetscContainerSetCtxDestroy(v_pointObj, PetscCtxDestroyDefault)); 5045*5552b385SBrandon PetscCall(PetscContainerDestroy(&v_pointObj)); 5046*5552b385SBrandon } else { 5047*5552b385SBrandon void *old; 5048*5552b385SBrandon 5049*5552b385SBrandon PetscCall(PetscContainerGetPointer(v_pointObj, &old)); 5050*5552b385SBrandon PetscCall(PetscFree(old)); 5051*5552b385SBrandon PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 5052*5552b385SBrandon } 5053*5552b385SBrandon } 5054*5552b385SBrandon #endif 5055*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5056*5552b385SBrandon } 5057*5552b385SBrandon 5058*5552b385SBrandon /*@C 5059*5552b385SBrandon 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(). 5060*5552b385SBrandon 5061*5552b385SBrandon Collective 5062*5552b385SBrandon 5063*5552b385SBrandon Input Parameter: 5064*5552b385SBrandon . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 5065*5552b385SBrandon 5066*5552b385SBrandon Level: intermediate 5067*5552b385SBrandon 5068*5552b385SBrandon Note: 5069*5552b385SBrandon The updated DM object inflated to the associated underlying geometry. This updates the [x, y, z] coordinates of DM points associated with geometry. 5070*5552b385SBrandon 5071*5552b385SBrandon .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()`, `DMPlexGetGeomModelTUV()` 5072*5552b385SBrandon @*/ 5073*5552b385SBrandon PetscErrorCode DMPlexInflateToGeomModelUseTUV(DM dm) 5074*5552b385SBrandon { 5075*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 5076*5552b385SBrandon /* EGADS Variables */ 5077*5552b385SBrandon ego model, geom, body, face, edge, vertex; 5078*5552b385SBrandon ego *bodies; 5079*5552b385SBrandon int Nb, oclass, mtype, *senses; 5080*5552b385SBrandon double result[18], params[2]; 5081*5552b385SBrandon /* PETSc Variables */ 5082*5552b385SBrandon DM cdm; 5083*5552b385SBrandon PetscContainer modelObj; 5084*5552b385SBrandon PetscContainer t_pointObj, u_pointObj, v_pointObj; 5085*5552b385SBrandon DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 5086*5552b385SBrandon Vec coordinates; 5087*5552b385SBrandon PetscScalar *coords; 5088*5552b385SBrandon PetscScalar *t_point, *u_point, *v_point; 5089*5552b385SBrandon PetscInt bodyID, faceID, edgeID, vertexID; 5090*5552b385SBrandon PetscInt cdim, d, vStart, vEnd, v; 5091*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5092*5552b385SBrandon #endif 5093*5552b385SBrandon 5094*5552b385SBrandon PetscFunctionBegin; 5095*5552b385SBrandon #if defined(PETSC_HAVE_EGADS) 5096*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5097*5552b385SBrandon if (!modelObj) { 5098*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5099*5552b385SBrandon islite = PETSC_TRUE; 5100*5552b385SBrandon } 5101*5552b385SBrandon 5102*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 5103*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 5104*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 5105*5552b385SBrandon 5106*5552b385SBrandon if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 5107*5552b385SBrandon if (!t_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5108*5552b385SBrandon if (!u_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5109*5552b385SBrandon if (!v_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5110*5552b385SBrandon 5111*5552b385SBrandon PetscCall(DMGetCoordinateDim(dm, &cdim)); 5112*5552b385SBrandon PetscCall(DMGetCoordinateDM(dm, &cdm)); 5113*5552b385SBrandon PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 5114*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 5115*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 5116*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 5117*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 5118*5552b385SBrandon 5119*5552b385SBrandon PetscCall(PetscContainerGetPointer(t_pointObj, (void **)&t_point)); 5120*5552b385SBrandon PetscCall(PetscContainerGetPointer(u_pointObj, (void **)&u_point)); 5121*5552b385SBrandon PetscCall(PetscContainerGetPointer(v_pointObj, (void **)&v_point)); 5122*5552b385SBrandon 5123*5552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 5124*5552b385SBrandon 5125*5552b385SBrandon if (islite) { 5126*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 5127*5552b385SBrandon } else { 5128*5552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 5129*5552b385SBrandon } 5130*5552b385SBrandon 5131*5552b385SBrandon PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 5132*5552b385SBrandon PetscCall(VecGetArrayWrite(coordinates, &coords)); 5133*5552b385SBrandon 5134*5552b385SBrandon for (v = vStart; v < vEnd; ++v) { 5135*5552b385SBrandon PetscScalar *vcoords; 5136*5552b385SBrandon 5137*5552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 5138*5552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 5139*5552b385SBrandon PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 5140*5552b385SBrandon PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 5141*5552b385SBrandon 5142*5552b385SBrandon // TODO Figure out why this is unknown sometimes 5143*5552b385SBrandon if (bodyID < 0 && Nb == 1) bodyID = 0; 5144*5552b385SBrandon 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); 5145*5552b385SBrandon body = bodies[bodyID]; 5146*5552b385SBrandon 5147*5552b385SBrandon PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 5148*5552b385SBrandon if (vertexID > 0) { 5149*5552b385SBrandon /* Snap to Vertices */ 5150*5552b385SBrandon if (islite) { 5151*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 5152*5552b385SBrandon PetscCall(EGlite_evaluate(vertex, NULL, result)); 5153*5552b385SBrandon } else { 5154*5552b385SBrandon PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 5155*5552b385SBrandon PetscCall(EG_evaluate(vertex, NULL, result)); 5156*5552b385SBrandon } 5157*5552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5158*5552b385SBrandon } else if (edgeID > 0) { 5159*5552b385SBrandon /* Snap to EDGE */ 5160*5552b385SBrandon params[0] = t_point[v - vStart]; 5161*5552b385SBrandon if (islite) { 5162*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 5163*5552b385SBrandon PetscCall(EGlite_evaluate(edge, params, result)); 5164*5552b385SBrandon } else { 5165*5552b385SBrandon PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 5166*5552b385SBrandon PetscCall(EG_evaluate(edge, params, result)); 5167*5552b385SBrandon } 5168*5552b385SBrandon for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5169*5552b385SBrandon } else if (faceID > 0) { 5170*5552b385SBrandon /* Snap to FACE */ 5171*5552b385SBrandon params[0] = u_point[v - vStart]; 5172*5552b385SBrandon params[1] = v_point[v - vStart]; 5173*5552b385SBrandon if (islite) { 5174*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 5175*5552b385SBrandon PetscCall(EGlite_evaluate(face, params, result)); 5176*5552b385SBrandon } else { 5177*5552b385SBrandon PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 5178*5552b385SBrandon PetscCall(EG_evaluate(face, params, result)); 5179*5552b385SBrandon } 5180c1cad2e7SMatthew G. Knepley for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5181c1cad2e7SMatthew G. Knepley } 5182c1cad2e7SMatthew G. Knepley } 51839566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 5184c1cad2e7SMatthew G. Knepley /* Clear out global coordinates */ 51856858538eSMatthew G. Knepley PetscCall(VecDestroy(&dm->coordinates[0].x)); 5186c1cad2e7SMatthew G. Knepley #endif 51873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5188c1cad2e7SMatthew G. Knepley } 5189c1cad2e7SMatthew G. Knepley 5190cc4c1da9SBarry Smith /*@ 5191*5552b385SBrandon DMPlexInflateToGeomModel - Wrapper function allowing two methods for inflating refined meshes to the underlying geometric domain. 51927bee2925SMatthew Knepley 51937bee2925SMatthew Knepley Collective 51947bee2925SMatthew Knepley 51957bee2925SMatthew Knepley Input Parameters: 5196*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5197*5552b385SBrandon - useTUV - PetscBool indicating if the user would like to inflate the DMPlex to the underlying geometry 5198*5552b385SBrandon using (t) for nodes on EDGEs and (u, v) for nodes on FACEs or using the nodes (x, y, z) coordinates 5199*5552b385SBrandon and shortest distance routine. 5200*5552b385SBrandon If useTUV = PETSC_TRUE, use the (t) or (u, v) parameters to inflate the DMPlex to the CAD geometry. 5201*5552b385SBrandon If useTUV = PETSC_FALSE, use the nodes (x, y, z) coordinates and the shortest disctance routine. 5202*5552b385SBrandon 5203*5552b385SBrandon Notes: 5204*5552b385SBrandon DM with nodal coordinates modified so that they lie on the EDGEs and FACEs of the underlying geometry. 5205*5552b385SBrandon 5206*5552b385SBrandon (t) and (u, v) parameters for all DMPlex nodes on EDGEs and FACEs are stored in arrays within PetscContainers attached to the DM. 5207*5552b385SBrandon The containers have names "Point - Edge t Parameter", "Point - Face u Parameter", and "Point - Face v Parameter". 5208*5552b385SBrandon The arrays are organized by Point 0-based ID (i.e. [v-vstart] as defined in the DMPlex. 5209*5552b385SBrandon 5210*5552b385SBrandon Level: intermediate 5211*5552b385SBrandon 5212*5552b385SBrandon .seealso: `DMPlexGetGeomModelTUV()`, `DMPlexInflateToGeomModelUseTUV()`, `DMPlexInflateToGeomModelUseXYZ()` 5213*5552b385SBrandon @*/ 5214*5552b385SBrandon PetscErrorCode DMPlexInflateToGeomModel(DM dm, PetscBool useTUV) 5215*5552b385SBrandon { 5216*5552b385SBrandon PetscFunctionBeginHot; 5217*5552b385SBrandon if (useTUV) { 5218*5552b385SBrandon PetscCall(DMPlexGetGeomModelTUV(dm)); 5219*5552b385SBrandon PetscCall(DMPlexInflateToGeomModelUseTUV(dm)); 5220*5552b385SBrandon } else { 5221*5552b385SBrandon PetscCall(DMPlexInflateToGeomModelUseXYZ(dm)); 5222*5552b385SBrandon } 5223*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5224*5552b385SBrandon } 5225*5552b385SBrandon 5226*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5227*5552b385SBrandon /*@C 5228*5552b385SBrandon DMPlexGetGeomModelBodies - Returns an array of PetscGeom BODY objects attached to the referenced geomtric model entity as well as the number of BODYs. 5229*5552b385SBrandon 5230*5552b385SBrandon Collective 5231*5552b385SBrandon 5232*5552b385SBrandon Input Parameter: 5233*5552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5234*5552b385SBrandon 5235*5552b385SBrandon Output Parameters: 5236*5552b385SBrandon + bodies - Array of PetscGeom BODY objects referenced by the geometric model. 5237*5552b385SBrandon - numBodies - Number of BODYs referenced by the geometric model. Also the size of **bodies array. 5238*5552b385SBrandon 5239*5552b385SBrandon Level: intermediate 5240*5552b385SBrandon 5241*5552b385SBrandon .seealso: 5242*5552b385SBrandon @*/ 5243*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelBodies(DM dm, PetscGeom **bodies, PetscInt *numBodies) 5244*5552b385SBrandon { 5245*5552b385SBrandon PetscFunctionBeginHot; 5246*5552b385SBrandon PetscContainer modelObj; 5247*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5248*5552b385SBrandon ego model, geom; 5249*5552b385SBrandon int oclass, mtype; 5250*5552b385SBrandon int *senses; 5251*5552b385SBrandon 5252*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5253*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5254*5552b385SBrandon if (!modelObj) { 5255*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5256*5552b385SBrandon islite = PETSC_TRUE; 5257*5552b385SBrandon } 5258*5552b385SBrandon 5259*5552b385SBrandon // Get attached EGADS or EGADSlite model (pointer) 5260*5552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 5261*5552b385SBrandon 5262*5552b385SBrandon if (islite) { 5263*5552b385SBrandon PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 5264*5552b385SBrandon } else { 5265*5552b385SBrandon PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 5266*5552b385SBrandon } 5267*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5268*5552b385SBrandon } 5269*5552b385SBrandon 5270*5552b385SBrandon /*@C 5271*5552b385SBrandon DMPlexGetGeomModelBodyShells - Returns an array of PetscGeom SHELL objects attached to the referenced BODY geomtric entity as well as the number of SHELLs. 5272*5552b385SBrandon 5273*5552b385SBrandon Collective 5274*5552b385SBrandon 5275*5552b385SBrandon Input Parameters: 5276*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5277*5552b385SBrandon - body - PetscGeom BODY object containing the SHELL objects of interest. 5278*5552b385SBrandon 5279*5552b385SBrandon Output Parameters: 5280*5552b385SBrandon + shells - Array of PetscGeom SHELL objects referenced by the PetscGeom BODY object 5281*5552b385SBrandon - numShells - Number of SHELLs referenced by the PetscGeom BODY object. Also the size of **shells array. 5282*5552b385SBrandon 5283*5552b385SBrandon Level: intermediate 5284*5552b385SBrandon 5285*5552b385SBrandon .seealso: 5286*5552b385SBrandon @*/ 5287*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelBodyShells(DM dm, PetscGeom body, PetscGeom **shells, PetscInt *numShells) 5288*5552b385SBrandon { 5289*5552b385SBrandon PetscFunctionBeginHot; 5290*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5291*5552b385SBrandon PetscContainer modelObj; 5292*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5293*5552b385SBrandon 5294*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5295*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5296*5552b385SBrandon if (!modelObj) { 5297*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5298*5552b385SBrandon islite = PETSC_TRUE; 5299*5552b385SBrandon } 5300*5552b385SBrandon 5301*5552b385SBrandon if (islite) { 5302*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, numShells, shells)); 5303*5552b385SBrandon } else { 5304*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, SHELL, numShells, shells)); 5305*5552b385SBrandon } 5306*5552b385SBrandon #endif 5307*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5308*5552b385SBrandon } 5309*5552b385SBrandon 5310*5552b385SBrandon /*@C 5311*5552b385SBrandon DMPlexGetGeomModelBodyFaces - Returns an array of PetscGeom FACE objects attached to the referenced BODY geomtric entity as well as the number of FACEs. 5312*5552b385SBrandon 5313*5552b385SBrandon Collective 5314*5552b385SBrandon 5315*5552b385SBrandon Input Parameters: 5316*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5317*5552b385SBrandon - body - PetscGeom BODY object containing the FACE objects of interest. 5318*5552b385SBrandon 5319*5552b385SBrandon Output Parameters: 5320*5552b385SBrandon + faces - Array of PetscGeom FACE objects referenced by the PetscGeom BODY object 5321*5552b385SBrandon - numFaces - Number of FACEs referenced by the PetscGeom BODY object. Also the size of **faces array. 5322*5552b385SBrandon 5323*5552b385SBrandon Level: intermediate 5324*5552b385SBrandon 5325*5552b385SBrandon .seealso: 5326*5552b385SBrandon @*/ 5327*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelBodyFaces(DM dm, PetscGeom body, PetscGeom **faces, PetscInt *numFaces) 5328*5552b385SBrandon { 5329*5552b385SBrandon PetscFunctionBeginHot; 5330*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5331*5552b385SBrandon PetscContainer modelObj; 5332*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5333*5552b385SBrandon 5334*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5335*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5336*5552b385SBrandon if (!modelObj) { 5337*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5338*5552b385SBrandon islite = PETSC_TRUE; 5339*5552b385SBrandon } 5340*5552b385SBrandon 5341*5552b385SBrandon if (islite) { 5342*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, FACE, numFaces, faces)); 5343*5552b385SBrandon } else { 5344*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, FACE, numFaces, faces)); 5345*5552b385SBrandon } 5346*5552b385SBrandon #endif 5347*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5348*5552b385SBrandon } 5349*5552b385SBrandon 5350*5552b385SBrandon /*@C 5351*5552b385SBrandon DMPlexGetGeomModelBodyLoops - Returns an array of PetscGeom Loop objects attached to the referenced BODY geomtric entity as well as the number of LOOPs. 5352*5552b385SBrandon 5353*5552b385SBrandon Collective 5354*5552b385SBrandon 5355*5552b385SBrandon Input Parameters: 5356*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5357*5552b385SBrandon - body - PetscGeom BODY object containing the LOOP objects of interest. 5358*5552b385SBrandon 5359*5552b385SBrandon Output Parameters: 5360*5552b385SBrandon + loops - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 5361*5552b385SBrandon - numLoops - Number of LOOPs referenced by the PetscGeom BODY object. Also the size of **loops array. 5362*5552b385SBrandon 5363*5552b385SBrandon Level: intermediate 5364*5552b385SBrandon 5365*5552b385SBrandon .seealso: 5366*5552b385SBrandon @*/ 5367*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelBodyLoops(DM dm, PetscGeom body, PetscGeom **loops, PetscInt *numLoops) 5368*5552b385SBrandon { 5369*5552b385SBrandon PetscFunctionBeginHot; 5370*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5371*5552b385SBrandon PetscContainer modelObj; 5372*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5373*5552b385SBrandon 5374*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5375*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5376*5552b385SBrandon if (!modelObj) { 5377*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5378*5552b385SBrandon islite = PETSC_TRUE; 5379*5552b385SBrandon } 5380*5552b385SBrandon 5381*5552b385SBrandon if (islite) { 5382*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 5383*5552b385SBrandon } else { 5384*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 5385*5552b385SBrandon } 5386*5552b385SBrandon #endif 5387*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5388*5552b385SBrandon } 5389*5552b385SBrandon 5390*5552b385SBrandon /*@C 5391*5552b385SBrandon DMPlexGetGeomModelShellFaces - Returns an array of PetscGeom FACE objects attached to the referenced SHELL geomtric entity as well as the number of FACEs. 5392*5552b385SBrandon 5393*5552b385SBrandon Collective 5394*5552b385SBrandon 5395*5552b385SBrandon Input Parameters: 5396*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5397*5552b385SBrandon . body - PetscGeom BODY object containing the FACE objects of interest. 5398*5552b385SBrandon - shell - PetscGeom SHELL object with FACEs of interest. 5399*5552b385SBrandon 5400*5552b385SBrandon Output Parameters: 5401*5552b385SBrandon + faces - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 5402*5552b385SBrandon - numFaces - Number of FACEs referenced by the PetscGeom SHELL object. Also the size of **faces array. 5403*5552b385SBrandon 5404*5552b385SBrandon Level: intermediate 5405*5552b385SBrandon 5406*5552b385SBrandon .seealso: 5407*5552b385SBrandon @*/ 5408*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelShellFaces(DM dm, PetscGeom body, PetscGeom shell, PetscGeom **faces, PetscInt *numFaces) 5409*5552b385SBrandon { 5410*5552b385SBrandon PetscFunctionBeginHot; 5411*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5412*5552b385SBrandon PetscContainer modelObj; 5413*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5414*5552b385SBrandon 5415*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5416*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5417*5552b385SBrandon if (!modelObj) { 5418*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5419*5552b385SBrandon islite = PETSC_TRUE; 5420*5552b385SBrandon } 5421*5552b385SBrandon 5422*5552b385SBrandon if (islite) { 5423*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, shell, FACE, numFaces, faces)); 5424*5552b385SBrandon } else { 5425*5552b385SBrandon PetscCall(EG_getBodyTopos(body, shell, FACE, numFaces, faces)); 5426*5552b385SBrandon } 5427*5552b385SBrandon #endif 5428*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5429*5552b385SBrandon } 5430*5552b385SBrandon 5431*5552b385SBrandon /*@C 5432*5552b385SBrandon DMPlexGetGeomModelFaceLoops - Returns an array of PetscGeom LOOP objects attached to the referenced FACE geomtric entity as well as the number of LOOPs. 5433*5552b385SBrandon 5434*5552b385SBrandon Collective 5435*5552b385SBrandon 5436*5552b385SBrandon Input Parameters: 5437*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5438*5552b385SBrandon . body - PetscGeom BODY object containing the LOOP objects of interest. 5439*5552b385SBrandon - face - PetscGeom FACE object with LOOPs of interest. 5440*5552b385SBrandon 5441*5552b385SBrandon Output Parameters: 5442*5552b385SBrandon + loops - Array of PetscGeom LOOP objects referenced by the PetscGeom FACE object 5443*5552b385SBrandon - numLoops - Number of LOOPs referenced by the PetscGeom FACE object. Also the size of **loops array. 5444*5552b385SBrandon 5445*5552b385SBrandon Level: intermediate 5446*5552b385SBrandon 5447*5552b385SBrandon .seealso: 5448*5552b385SBrandon @*/ 5449*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelFaceLoops(DM dm, PetscGeom body, PetscGeom face, PetscGeom **loops, PetscInt *numLoops) 5450*5552b385SBrandon { 5451*5552b385SBrandon PetscFunctionBeginHot; 5452*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5453*5552b385SBrandon PetscContainer modelObj; 5454*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5455*5552b385SBrandon 5456*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5457*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5458*5552b385SBrandon if (!modelObj) { 5459*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5460*5552b385SBrandon islite = PETSC_TRUE; 5461*5552b385SBrandon } 5462*5552b385SBrandon 5463*5552b385SBrandon if (islite) { 5464*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, LOOP, numLoops, loops)); 5465*5552b385SBrandon } else { 5466*5552b385SBrandon PetscCall(EG_getBodyTopos(body, face, LOOP, numLoops, loops)); 5467*5552b385SBrandon } 5468*5552b385SBrandon #endif 5469*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5470*5552b385SBrandon } 5471*5552b385SBrandon 5472*5552b385SBrandon /*@C 5473*5552b385SBrandon DMPlexGetGeomModelFaceEdges - Returns an array of PetscGeom EDGE objects attached to the referenced FACE geomtric entity as well as the number of EDGEs. 5474*5552b385SBrandon 5475*5552b385SBrandon Collective 5476*5552b385SBrandon 5477*5552b385SBrandon Input Parameters: 5478*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5479*5552b385SBrandon . body - PetscGeom Body object containing the EDGE objects of interest. 5480*5552b385SBrandon - face - PetscGeom FACE object with EDGEs of interest. 5481*5552b385SBrandon 5482*5552b385SBrandon Output Parameters: 5483*5552b385SBrandon + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom FACE object 5484*5552b385SBrandon - numEdges - Number of EDGEs referenced by the PetscGeom FACE object. Also the size of **edges array. 5485*5552b385SBrandon 5486*5552b385SBrandon Level: intermediate 5487*5552b385SBrandon 5488*5552b385SBrandon .seealso: 5489*5552b385SBrandon @*/ 5490*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelFaceEdges(DM dm, PetscGeom body, PetscGeom face, PetscGeom **edges, PetscInt *numEdges) 5491*5552b385SBrandon { 5492*5552b385SBrandon PetscFunctionBeginHot; 5493*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5494*5552b385SBrandon PetscContainer modelObj; 5495*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5496*5552b385SBrandon 5497*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5498*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5499*5552b385SBrandon if (!modelObj) { 5500*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5501*5552b385SBrandon islite = PETSC_TRUE; 5502*5552b385SBrandon } 5503*5552b385SBrandon 5504*5552b385SBrandon if (islite) { 5505*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, face, EDGE, numEdges, edges)); 5506*5552b385SBrandon } else { 5507*5552b385SBrandon PetscCall(EG_getBodyTopos(body, face, EDGE, numEdges, edges)); 5508*5552b385SBrandon } 5509*5552b385SBrandon #endif 5510*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5511*5552b385SBrandon } 5512*5552b385SBrandon 5513*5552b385SBrandon /*@C 5514*5552b385SBrandon DMPlexGetGeomModelBodyEdges - Returns an array of PetscGeom EDGE objects attached to the referenced BODY geomtric entity as well as the number of EDGEs. 5515*5552b385SBrandon 5516*5552b385SBrandon Collective 5517*5552b385SBrandon 5518*5552b385SBrandon Input Parameters: 5519*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5520*5552b385SBrandon - body - PetscGeom body object of interest. 5521*5552b385SBrandon 5522*5552b385SBrandon Output Parameters: 5523*5552b385SBrandon + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom BODY object 5524*5552b385SBrandon - numEdges - Number of EDGEs referenced by the PetscGeom BODY object. Also the size of **edges array. 5525*5552b385SBrandon 5526*5552b385SBrandon Level: intermediate 5527*5552b385SBrandon 5528*5552b385SBrandon .seealso: 5529*5552b385SBrandon @*/ 5530*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelBodyEdges(DM dm, PetscGeom body, PetscGeom **edges, PetscInt *numEdges) 5531*5552b385SBrandon { 5532*5552b385SBrandon PetscFunctionBeginHot; 5533*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5534*5552b385SBrandon PetscContainer modelObj; 5535*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5536*5552b385SBrandon 5537*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5538*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5539*5552b385SBrandon if (!modelObj) { 5540*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5541*5552b385SBrandon islite = PETSC_TRUE; 5542*5552b385SBrandon } 5543*5552b385SBrandon 5544*5552b385SBrandon if (islite) { 5545*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 5546*5552b385SBrandon } else { 5547*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 5548*5552b385SBrandon } 5549*5552b385SBrandon #endif 5550*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5551*5552b385SBrandon } 5552*5552b385SBrandon 5553*5552b385SBrandon /*@C 5554*5552b385SBrandon DMPlexGetGeomModelBodyNodes - Returns an array of PetscGeom NODE objects attached to the referenced BODY geomtric entity as well as the number of NODES. 5555*5552b385SBrandon 5556*5552b385SBrandon Collective 5557*5552b385SBrandon 5558*5552b385SBrandon Input Parameters: 5559*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5560*5552b385SBrandon - body - PetscGeom body object of interest. 5561*5552b385SBrandon 5562*5552b385SBrandon Output Parameters: 5563*5552b385SBrandon + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom BODY object 5564*5552b385SBrandon - numNodes - Number of NODEs referenced by the PetscGeom BODY object. Also the size of **nodes array. 5565*5552b385SBrandon 5566*5552b385SBrandon Level: intermediate 5567*5552b385SBrandon 5568*5552b385SBrandon .seealso: 5569*5552b385SBrandon @*/ 5570*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelBodyNodes(DM dm, PetscGeom body, PetscGeom **nodes, PetscInt *numNodes) 5571*5552b385SBrandon { 5572*5552b385SBrandon PetscFunctionBeginHot; 5573*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5574*5552b385SBrandon PetscContainer modelObj; 5575*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5576*5552b385SBrandon 5577*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5578*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5579*5552b385SBrandon if (!modelObj) { 5580*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5581*5552b385SBrandon islite = PETSC_TRUE; 5582*5552b385SBrandon } 5583*5552b385SBrandon 5584*5552b385SBrandon if (islite) { 5585*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 5586*5552b385SBrandon } else { 5587*5552b385SBrandon PetscCall(EG_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 5588*5552b385SBrandon } 5589*5552b385SBrandon #endif 5590*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5591*5552b385SBrandon } 5592*5552b385SBrandon 5593*5552b385SBrandon /*@C 5594*5552b385SBrandon DMPlexGetGeomModelEdgeNodes - Returns an array of PetscGeom NODE objects attached to the referenced EDGE geomtric entity as well as the number of NODES. 5595*5552b385SBrandon 5596*5552b385SBrandon Collective 5597*5552b385SBrandon 5598*5552b385SBrandon Input Parameters: 5599*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5600*5552b385SBrandon . body - PetscGeom body object containing the EDGE object of interest. 5601*5552b385SBrandon - edge - PetscGeom EDGE object with NODEs of interest. 5602*5552b385SBrandon 5603*5552b385SBrandon Output Parameters: 5604*5552b385SBrandon + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom EDGE object 5605*5552b385SBrandon - numNodes - Number of Nodes referenced by the PetscGeom EDGE object. Also the size of **nodes array. 5606*5552b385SBrandon 5607*5552b385SBrandon Level: intermediate 5608*5552b385SBrandon 5609*5552b385SBrandon .seealso: 5610*5552b385SBrandon @*/ 5611*5552b385SBrandon PetscErrorCode DMPlexGetGeomModelEdgeNodes(DM dm, PetscGeom body, PetscGeom edge, PetscGeom **nodes, PetscInt *numNodes) 5612*5552b385SBrandon { 5613*5552b385SBrandon PetscFunctionBeginHot; 5614*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5615*5552b385SBrandon PetscContainer modelObj; 5616*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5617*5552b385SBrandon 5618*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5619*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5620*5552b385SBrandon if (!modelObj) { 5621*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5622*5552b385SBrandon islite = PETSC_TRUE; 5623*5552b385SBrandon } 5624*5552b385SBrandon 5625*5552b385SBrandon if (islite) { 5626*5552b385SBrandon PetscCall(EGlite_getBodyTopos(body, edge, NODE, numNodes, nodes)); 5627*5552b385SBrandon } else { 5628*5552b385SBrandon PetscCall(EG_getBodyTopos(body, edge, NODE, numNodes, nodes)); 5629*5552b385SBrandon } 5630*5552b385SBrandon #endif 5631*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5632*5552b385SBrandon } 5633*5552b385SBrandon 5634*5552b385SBrandon /*@C 5635*5552b385SBrandon DMPlexGetGeomID - Returns ID number of the entity in the geometric (CAD) model 5636*5552b385SBrandon 5637*5552b385SBrandon Collective 5638*5552b385SBrandon 5639*5552b385SBrandon Input Parameters: 5640*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5641*5552b385SBrandon . body - PetscGeom body object containing the lower level entity the ID number is being requested. 5642*5552b385SBrandon - topoObj - PetscGeom SHELL, FACE, LOOP, EDGE, or NODE object for which ID number is being requested. 56437bee2925SMatthew Knepley 56447bee2925SMatthew Knepley Output Parameter: 5645*5552b385SBrandon . id - ID number of the entity 56467bee2925SMatthew Knepley 5647*5552b385SBrandon Level: intermediate 56487bee2925SMatthew Knepley 5649*5552b385SBrandon .seealso: 56507bee2925SMatthew Knepley @*/ 5651*5552b385SBrandon PetscErrorCode DMPlexGetGeomID(DM dm, PetscGeom body, PetscGeom topoObj, PetscInt *id) 5652d71ae5a4SJacob Faibussowitsch { 5653*5552b385SBrandon PetscFunctionBeginHot; 5654*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5655*5552b385SBrandon PetscContainer modelObj; 5656*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5657*5552b385SBrandon int topoID; 5658*5552b385SBrandon 5659*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5660*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5661*5552b385SBrandon if (!modelObj) { 5662*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5663*5552b385SBrandon islite = PETSC_TRUE; 5664*5552b385SBrandon } 5665*5552b385SBrandon 5666*5552b385SBrandon // Get Topology Object's ID 5667*5552b385SBrandon if (islite) { 5668*5552b385SBrandon topoID = EGlite_indexBodyTopo(body, topoObj); 5669*5552b385SBrandon } else { 5670*5552b385SBrandon topoID = EG_indexBodyTopo(body, topoObj); 5671*5552b385SBrandon } 5672*5552b385SBrandon 5673*5552b385SBrandon *id = topoID; 56747bee2925SMatthew Knepley #endif 5675*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5676*5552b385SBrandon } 5677*5552b385SBrandon 5678*5552b385SBrandon /*@C 5679*5552b385SBrandon DMPlexGetGeomObject - Returns Geometry Object using the objects ID in the geometric (CAD) model 5680*5552b385SBrandon 5681*5552b385SBrandon Collective 5682*5552b385SBrandon 5683*5552b385SBrandon Input Parameters: 5684*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5685*5552b385SBrandon . body - PetscGeom body object containing the lower level entity the referenced by the ID. 5686*5552b385SBrandon . geomType - Keyword SHELL, FACE, LOOP, EDGE, or NODE of the geometry type for which ID number is being requested. 5687*5552b385SBrandon - geomID - ID number of the geometry entity being requested. 5688*5552b385SBrandon 5689*5552b385SBrandon Output Parameter: 5690*5552b385SBrandon . geomObj - Geometry Object referenced by the ID number requested. 5691*5552b385SBrandon 5692*5552b385SBrandon Level: intermediate 5693*5552b385SBrandon 5694*5552b385SBrandon .seealso: 5695*5552b385SBrandon @*/ 5696*5552b385SBrandon PetscErrorCode DMPlexGetGeomObject(DM dm, PetscGeom body, PetscInt geomType, PetscInt geomID, PetscGeom *geomObj) 5697*5552b385SBrandon { 5698*5552b385SBrandon PetscFunctionBeginHot; 5699*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5700*5552b385SBrandon PetscContainer modelObj; 5701*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5702*5552b385SBrandon 5703*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5704*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5705*5552b385SBrandon if (!modelObj) { 5706*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5707*5552b385SBrandon islite = PETSC_TRUE; 5708*5552b385SBrandon } 5709*5552b385SBrandon 5710*5552b385SBrandon // Get Topology Object's ID 5711*5552b385SBrandon if (islite) { 5712*5552b385SBrandon PetscCall(EGlite_objectBodyTopo(body, geomType, geomID, geomObj)); 5713*5552b385SBrandon } else { 5714*5552b385SBrandon PetscCall(EG_objectBodyTopo(body, geomType, geomID, geomObj)); 5715*5552b385SBrandon } 5716*5552b385SBrandon #endif 5717*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5718*5552b385SBrandon } 5719*5552b385SBrandon 5720*5552b385SBrandon /*@C 5721*5552b385SBrandon DMPlexGetGeomFaceNumOfControlPoints - Returns the total number of Control Points (and associated Weights) defining a FACE of a Geometry 5722*5552b385SBrandon 5723*5552b385SBrandon Not collective 5724*5552b385SBrandon 5725*5552b385SBrandon Input Parameters: 5726*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5727*5552b385SBrandon - face - PetscGeom FACE object 5728*5552b385SBrandon 5729*5552b385SBrandon Output Parameter: 5730*5552b385SBrandon . numCntrlPnts - Number of Control Points (and Weights) defining the FACE 5731*5552b385SBrandon 5732*5552b385SBrandon Level: intermediate 5733*5552b385SBrandon 5734*5552b385SBrandon .seealso: 5735*5552b385SBrandon @*/ 5736*5552b385SBrandon PetscErrorCode DMPlexGetGeomFaceNumOfControlPoints(DM dm, PetscGeom face, PetscInt *numCntrlPnts) 5737*5552b385SBrandon { 5738*5552b385SBrandon PetscFunctionBeginHot; 5739*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5740*5552b385SBrandon PetscContainer modelObj; 5741*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5742*5552b385SBrandon PetscGeom geom, gRef; 5743*5552b385SBrandon PetscGeom *lobjs; 5744*5552b385SBrandon int Nl, oclass, mtype, goclass, gmtype; 5745*5552b385SBrandon int *lsenses, *gpinfo; 5746*5552b385SBrandon double *gprv; 5747*5552b385SBrandon 5748*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5749*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5750*5552b385SBrandon if (!modelObj) { 5751*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5752*5552b385SBrandon islite = PETSC_TRUE; 5753*5552b385SBrandon } 5754*5552b385SBrandon 5755*5552b385SBrandon // Get Total Number of Control Points on FACE 5756*5552b385SBrandon if (islite) { 5757*5552b385SBrandon PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 5758*5552b385SBrandon PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 5759*5552b385SBrandon } else { 5760*5552b385SBrandon PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 5761*5552b385SBrandon PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 5762*5552b385SBrandon } 5763*5552b385SBrandon 5764*5552b385SBrandon *numCntrlPnts = gpinfo[2] * gpinfo[5]; 5765*5552b385SBrandon #endif 5766*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5767*5552b385SBrandon } 5768*5552b385SBrandon 5769*5552b385SBrandon /*@C 5770*5552b385SBrandon DMPlexGetGeomBodyMassProperties - Returns the Volume, Surface Area, Center of Gravity, and Inertia about the Body's Center of Gravity 5771*5552b385SBrandon 5772*5552b385SBrandon Not collective 5773*5552b385SBrandon 5774*5552b385SBrandon Input Parameters: 5775*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5776*5552b385SBrandon - body - PetscGeom BODY object 5777*5552b385SBrandon 5778*5552b385SBrandon Output Parameters: 5779*5552b385SBrandon + volume - Volume of the CAD Body attached to the DM Plex 5780*5552b385SBrandon . surfArea - Surface Area of the CAD Body attached to the DM Plex 5781*5552b385SBrandon . centerOfGravity - Array with the Center of Gravity coordinates of the CAD Body attached to the DM Plex [x, y, z] 5782*5552b385SBrandon . COGszie - Size of centerOfGravity[] Array 5783*5552b385SBrandon . inertiaMatrixCOG - Array containing the Inertia about the Body's Center of Gravity [Ixx, Ixy, Ixz, Iyx, Iyy, Iyz, Izx, Izy, Izz] 5784*5552b385SBrandon - IMCOGsize - Size of inertiaMatrixCOG[] Array 5785*5552b385SBrandon 5786*5552b385SBrandon Level: intermediate 5787*5552b385SBrandon 5788*5552b385SBrandon .seealso: 5789*5552b385SBrandon @*/ 5790*5552b385SBrandon PetscErrorCode DMPlexGetGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) 5791*5552b385SBrandon { 5792*5552b385SBrandon PetscFunctionBeginHot; 5793*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5794*5552b385SBrandon PetscContainer modelObj; 5795*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5796*5552b385SBrandon PetscScalar geomData[14]; 5797*5552b385SBrandon 5798*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5799*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5800*5552b385SBrandon if (!modelObj) { 5801*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5802*5552b385SBrandon islite = PETSC_TRUE; 5803*5552b385SBrandon 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"); 5804*5552b385SBrandon } 5805*5552b385SBrandon 5806*5552b385SBrandon if (islite) { 5807*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " WARNING!! This functionality is not supported for EGADSlite files. \n")); 5808*5552b385SBrandon PetscCall(PetscPrintf(PETSC_COMM_SELF, " All returned values are equal to 0 \n")); 5809*5552b385SBrandon } else { 5810*5552b385SBrandon PetscCall(EG_getMassProperties(body, geomData)); 5811*5552b385SBrandon } 5812*5552b385SBrandon 5813*5552b385SBrandon PetscCall(PetscMalloc2(3, centerOfGravity, 9, inertiaMatrixCOG)); 5814*5552b385SBrandon 5815*5552b385SBrandon if (!islite) { 5816*5552b385SBrandon *volume = geomData[0]; 5817*5552b385SBrandon *surfArea = geomData[1]; 5818*5552b385SBrandon for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = geomData[ii]; } 5819*5552b385SBrandon *COGsize = 3; 5820*5552b385SBrandon for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = geomData[ii]; } 5821*5552b385SBrandon *IMCOGsize = 9; 5822*5552b385SBrandon } else { 5823*5552b385SBrandon *volume = 0.; 5824*5552b385SBrandon *surfArea = 0.; 5825*5552b385SBrandon for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = 0.; } 5826*5552b385SBrandon *COGsize = 0; 5827*5552b385SBrandon for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = 0.; } 5828*5552b385SBrandon *IMCOGsize = 0; 5829*5552b385SBrandon } 5830*5552b385SBrandon #endif 5831*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5832*5552b385SBrandon } 5833*5552b385SBrandon 5834*5552b385SBrandon PetscErrorCode DMPlexRestoreGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) 5835*5552b385SBrandon { 5836*5552b385SBrandon PetscFunctionBegin; 5837*5552b385SBrandon PetscCall(PetscFree2(*centerOfGravity, *inertiaMatrixCOG)); 5838*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5839*5552b385SBrandon } 5840*5552b385SBrandon 5841*5552b385SBrandon /*@C 5842*5552b385SBrandon DMPlexFreeGeomObject - Frees PetscGeom Objects 5843*5552b385SBrandon 5844*5552b385SBrandon Not collective 5845*5552b385SBrandon 5846*5552b385SBrandon Input Parameters: 5847*5552b385SBrandon + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5848*5552b385SBrandon - geomObj - PetscGeom object 5849*5552b385SBrandon 5850*5552b385SBrandon Level: intermediate 5851*5552b385SBrandon 5852*5552b385SBrandon .seealso: 5853*5552b385SBrandon @*/ 5854*5552b385SBrandon PetscErrorCode DMPlexFreeGeomObject(DM dm, PetscGeom *geomObj) 5855*5552b385SBrandon { 5856*5552b385SBrandon PetscFunctionBeginHot; 5857*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 5858*5552b385SBrandon PetscContainer modelObj; 5859*5552b385SBrandon PetscBool islite = PETSC_FALSE; 5860*5552b385SBrandon 5861*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5862*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5863*5552b385SBrandon if (!modelObj) { 5864*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5865*5552b385SBrandon islite = PETSC_TRUE; 5866*5552b385SBrandon } 5867*5552b385SBrandon 5868*5552b385SBrandon if (islite) { 5869*5552b385SBrandon EGlite_free(geomObj); 5870*5552b385SBrandon } else { 5871*5552b385SBrandon EG_free(geomObj); 5872*5552b385SBrandon } 5873*5552b385SBrandon #endif 5874*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5875*5552b385SBrandon } 5876*5552b385SBrandon 5877*5552b385SBrandon /*@C 5878*5552b385SBrandon DMPlexGetGeomCntrlPntAndWeightData - Gets Control Point and Associated Weight Data for the Geometry attached to the DMPlex 5879*5552b385SBrandon 5880*5552b385SBrandon Not collective 5881*5552b385SBrandon 5882*5552b385SBrandon Input Parameter: 5883*5552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5884*5552b385SBrandon 5885*5552b385SBrandon Output Parameters: 5886*5552b385SBrandon + cpHashTable - Hash Table containing the relationship between FACE ID and Control Point IDs. 5887*5552b385SBrandon . cpCoordDataLength - Length of cpCoordData Array. 5888*5552b385SBrandon . cpCoordData - Array holding the Geometry Control Point Coordinate Data. 5889*5552b385SBrandon . maxNumEquiv - Maximum Number of Equivalent Control Points (Control Points with the same coordinates but different IDs). 5890*5552b385SBrandon . 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 5891*5552b385SBrandon . wHashTable - Hash Table containing the relationship between FACE ID and Control Point Weight. 5892*5552b385SBrandon . wDataLength - Length of wData Array. 5893*5552b385SBrandon - wData - Array holding the Weight for an associated Geometry Control Point. 5894*5552b385SBrandon 5895*5552b385SBrandon Note: 5896*5552b385SBrandon Must Call DMPLexGeomDataAndGrads() before calling this function. 5897*5552b385SBrandon 5898*5552b385SBrandon Level: intermediate 5899*5552b385SBrandon 5900*5552b385SBrandon .seealso: 5901*5552b385SBrandon @*/ 5902*5552b385SBrandon PetscErrorCode DMPlexGetGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) 5903*5552b385SBrandon { 5904*5552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj, cpCoordDataLengthObj, wDataLengthObj, maxNumRelateObj; 5905*5552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 5906*5552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr, *maxNumEquivPtr; 5907*5552b385SBrandon PetscHMapI cpHashTableTemp, wHashTableTemp; 5908*5552b385SBrandon 5909*5552b385SBrandon PetscFunctionBeginHot; 5910*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5911*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5912*5552b385SBrandon if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 5913*5552b385SBrandon 5914*5552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 5915*5552b385SBrandon 5916*5552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 5917*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 5918*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 5919*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordDataLengthObj)); 5920*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 5921*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 5922*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 5923*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Equivalancy Matrix", (PetscObject *)cpEquiv)); 5924*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 5925*5552b385SBrandon 5926*5552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 5927*5552b385SBrandon PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTableTemp)); 5928*5552b385SBrandon PetscCall(PetscContainerGetPointer(cpCoordDataLengthObj, (void **)&cpCoordDataLengthPtr)); 5929*5552b385SBrandon PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTableTemp)); 5930*5552b385SBrandon PetscCall(PetscContainerGetPointer(wDataLengthObj, (void **)&wDataLengthPtr)); 5931*5552b385SBrandon PetscCall(PetscContainerGetPointer(maxNumRelateObj, (void **)&maxNumEquivPtr)); 5932*5552b385SBrandon 5933*5552b385SBrandon *cpCoordDataLength = *cpCoordDataLengthPtr; 5934*5552b385SBrandon *wDataLength = *wDataLengthPtr; 5935*5552b385SBrandon *maxNumEquiv = *maxNumEquivPtr; 5936*5552b385SBrandon *cpHashTable = cpHashTableTemp; 5937*5552b385SBrandon *wHashTable = wHashTableTemp; 5938*5552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, cpCoordData)); 5939*5552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, wData)); 5940*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5941*5552b385SBrandon } 5942*5552b385SBrandon 5943*5552b385SBrandon PetscErrorCode DMPlexRestoreGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) 5944*5552b385SBrandon { 5945*5552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 5946*5552b385SBrandon 5947*5552b385SBrandon PetscFunctionBeginHot; 5948*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 5949*5552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, cpCoordData)); 5950*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 5951*5552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, wData)); 5952*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 5953*5552b385SBrandon } 5954*5552b385SBrandon 5955*5552b385SBrandon /*@C 5956*5552b385SBrandon 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 . 5957*5552b385SBrandon 5958*5552b385SBrandon Not collective 5959*5552b385SBrandon 5960*5552b385SBrandon Input Parameter: 5961*5552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5962*5552b385SBrandon 5963*5552b385SBrandon Output Parameters: 5964*5552b385SBrandon + cpSurfGradHashTable - Hash Table Relating the Control Point ID to the the Row in the cpSurfGrad Matrix 5965*5552b385SBrandon . 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. 5966*5552b385SBrandon . cpArraySize - The size of arrays gradSACP and gradVolCP and is equal to 3 * total number of Control Points in the Geometry 5967*5552b385SBrandon . 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. 5968*5552b385SBrandon . gradVolCP - Array contianing the Volume Gradient with respect to Control Point Data. Data is arranged by Control Point ID * 3 where 3 is for the coordinate dimension. 5969*5552b385SBrandon . wArraySize - The size of arrayws gradSAW and gradVolW and is equal to the total number of Control Points in the Geometry. 5970*5552b385SBrandon . gradSAW - Array containing the Surface Area Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 5971*5552b385SBrandon - gradVolW - Array containing the Volume Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 5972*5552b385SBrandon 5973*5552b385SBrandon Notes: 5974*5552b385SBrandon Must Call DMPLexGeomDataAndGrads() before calling this function. 5975*5552b385SBrandon 5976*5552b385SBrandon gradVolCP and gradVolW are only available when DMPlexGeomDataAndGrads() is called with fullGeomGrad = PETSC_TRUE. 5977*5552b385SBrandon 5978*5552b385SBrandon Level: intermediate 5979*5552b385SBrandon 5980*5552b385SBrandon .seealso: DMPlexGeomDataAndGrads 5981*5552b385SBrandon @*/ 5982*5552b385SBrandon PetscErrorCode DMPlexGetGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 5983*5552b385SBrandon { 5984*5552b385SBrandon PetscContainer modelObj, cpSurfGradHashTableObj, cpArraySizeObj, wArraySizeObj; 5985*5552b385SBrandon Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 5986*5552b385SBrandon PetscInt *cpArraySizePtr, *wArraySizePtr; 5987*5552b385SBrandon PetscHMapI cpSurfGradHashTableTemp; 5988*5552b385SBrandon 5989*5552b385SBrandon PetscFunctionBeginHot; 5990*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 5991*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5992*5552b385SBrandon if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 5993*5552b385SBrandon 5994*5552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 5995*5552b385SBrandon 5996*5552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 5997*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&cpSurfGradHashTableObj)); 5998*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Matrix", (PetscObject *)cpSurfGrad)); 5999*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpArraySizeObj)); 6000*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 6001*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 6002*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wArraySizeObj)); 6003*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 6004*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 6005*5552b385SBrandon 6006*5552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 6007*5552b385SBrandon if (cpSurfGradHashTableObj) { 6008*5552b385SBrandon PetscCall(PetscContainerGetPointer(cpSurfGradHashTableObj, (void **)&cpSurfGradHashTableTemp)); 6009*5552b385SBrandon *cpSurfGradHashTable = cpSurfGradHashTableTemp; 6010*5552b385SBrandon } 6011*5552b385SBrandon 6012*5552b385SBrandon if (cpArraySizeObj) { 6013*5552b385SBrandon PetscCall(PetscContainerGetPointer(cpArraySizeObj, (void **)&cpArraySizePtr)); 6014*5552b385SBrandon *cpArraySize = *cpArraySizePtr; 6015*5552b385SBrandon } 6016*5552b385SBrandon 6017*5552b385SBrandon if (gradSACPVec) PetscCall(VecGetArrayWrite(gradSACPVec, gradSACP)); 6018*5552b385SBrandon if (gradVolCPVec) PetscCall(VecGetArrayWrite(gradVolCPVec, gradVolCP)); 6019*5552b385SBrandon if (gradSAWVec) PetscCall(VecGetArrayWrite(gradSAWVec, gradSAW)); 6020*5552b385SBrandon if (gradVolWVec) PetscCall(VecGetArrayWrite(gradVolWVec, gradVolW)); 6021*5552b385SBrandon 6022*5552b385SBrandon if (wArraySizeObj) { 6023*5552b385SBrandon PetscCall(PetscContainerGetPointer(wArraySizeObj, (void **)&wArraySizePtr)); 6024*5552b385SBrandon *wArraySize = *wArraySizePtr; 6025*5552b385SBrandon } 6026*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 6027*5552b385SBrandon } 6028*5552b385SBrandon 6029*5552b385SBrandon PetscErrorCode DMPlexRestoreGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 6030*5552b385SBrandon { 6031*5552b385SBrandon Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 60327bee2925SMatthew Knepley 60337bee2925SMatthew Knepley PetscFunctionBegin; 6034*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 6035*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 6036*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 6037*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 6038*5552b385SBrandon 6039*5552b385SBrandon if (gradSACPVec) PetscCall(VecRestoreArrayWrite(gradSACPVec, gradSACP)); 6040*5552b385SBrandon if (gradVolCPVec) PetscCall(VecRestoreArrayWrite(gradVolCPVec, gradVolCP)); 6041*5552b385SBrandon if (gradSAWVec) PetscCall(VecRestoreArrayWrite(gradSAWVec, gradSAW)); 6042*5552b385SBrandon if (gradVolWVec) PetscCall(VecRestoreArrayWrite(gradVolWVec, gradVolW)); 60433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60447bee2925SMatthew Knepley } 6045*5552b385SBrandon 6046*5552b385SBrandon /*@C 6047*5552b385SBrandon DMPlexGetGeomCntrlPntMaps - Gets arrays which maps Control Point IDs to their associated Geometry FACE, EDGE, and VERTEX. 6048*5552b385SBrandon 6049*5552b385SBrandon Not collective 6050*5552b385SBrandon 6051*5552b385SBrandon Input Parameter: 6052*5552b385SBrandon . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 6053*5552b385SBrandon 6054*5552b385SBrandon Output Parameters: 6055*5552b385SBrandon + numCntrlPnts - Number of Control Points defining the Geometry attached to the DMPlex 6056*5552b385SBrandon . cntrlPntFaceMap - Array containing the FACE ID for the Control Point. Array index corresponds to Control Point ID. 6057*5552b385SBrandon . cntrlPntWeightFaceMap - Array containing the FACE ID for the Control Point Weight. Array index corresponds to Control Point ID. 6058*5552b385SBrandon . cntrlPntEdgeMap - Array containing the EDGE ID for the Control Point. Array index corresponds to Control Point ID. 6059*5552b385SBrandon . cntrlPntWeightEdgeMap - Array containing the EDGE ID for the Control Point Weight. Array index corresponds to Control Point ID. 6060*5552b385SBrandon . cntrlPntVertexMap - Array containing the VERTEX ID for the Control Point. Array index corresponds to Control Point ID. 6061*5552b385SBrandon - cntrlPntWeightVertexMap - Array containing the VERTEX ID for the Control Point Weight. Array index corresponds to Control Point ID. 6062*5552b385SBrandon 6063*5552b385SBrandon Note: 6064*5552b385SBrandon 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. 6065*5552b385SBrandon 6066*5552b385SBrandon Level: intermediate 6067*5552b385SBrandon 6068*5552b385SBrandon .seealso: DMPlexGeomDataAndGrads 6069*5552b385SBrandon @*/ 6070*5552b385SBrandon PetscErrorCode DMPlexGetGeomCntrlPntMaps(DM dm, PetscInt *numCntrlPnts, PetscInt **cntrlPntFaceMap, PetscInt **cntrlPntWeightFaceMap, PetscInt **cntrlPntEdgeMap, PetscInt **cntrlPntWeightEdgeMap, PetscInt **cntrlPntVertexMap, PetscInt **cntrlPntWeightVertexMap) 6071*5552b385SBrandon { 6072*5552b385SBrandon PetscFunctionBeginHot; 6073*5552b385SBrandon #ifdef PETSC_HAVE_EGADS 6074*5552b385SBrandon PetscContainer modelObj, numCntrlPntsObj, cntrlPntFaceMapObj, cntrlPntWeightFaceMapObj, cntrlPntEdgeMapObj, cntrlPntWeightEdgeMapObj, cntrlPntVertexMapObj, cntrlPntWeightVertexMapObj; 6075*5552b385SBrandon PetscInt *numCntrlPntsPtr, *cntrlPntFaceMapPtr, *cntrlPntWeightFaceMapPtr, *cntrlPntEdgeMapPtr, *cntrlPntWeightEdgeMapPtr, *cntrlPntVertexMapPtr, *cntrlPntWeightVertexMapPtr; 6076*5552b385SBrandon 6077*5552b385SBrandon /* Determine which type of EGADS model is attached to the DM */ 6078*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 6079*5552b385SBrandon if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 6080*5552b385SBrandon 6081*5552b385SBrandon if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 6082*5552b385SBrandon 6083*5552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 6084*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&numCntrlPntsObj)); 6085*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cntrlPntFaceMapObj)); 6086*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&cntrlPntWeightFaceMapObj)); 6087*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cntrlPntEdgeMapObj)); 6088*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&cntrlPntWeightEdgeMapObj)); 6089*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cntrlPntVertexMapObj)); 6090*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&cntrlPntWeightVertexMapObj)); 6091*5552b385SBrandon 6092*5552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 6093*5552b385SBrandon if (numCntrlPntsObj) { 6094*5552b385SBrandon PetscCall(PetscContainerGetPointer(numCntrlPntsObj, (void **)&numCntrlPntsPtr)); 6095*5552b385SBrandon *numCntrlPnts = *numCntrlPntsPtr; 6096*5552b385SBrandon } 6097*5552b385SBrandon 6098*5552b385SBrandon if (cntrlPntFaceMapObj) { 6099*5552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntFaceMapObj, (void **)&cntrlPntFaceMapPtr)); 6100*5552b385SBrandon *cntrlPntFaceMap = cntrlPntFaceMapPtr; 6101*5552b385SBrandon } 6102*5552b385SBrandon 6103*5552b385SBrandon if (cntrlPntWeightFaceMapObj) { 6104*5552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightFaceMapObj, (void **)&cntrlPntWeightFaceMapPtr)); 6105*5552b385SBrandon *cntrlPntWeightFaceMap = cntrlPntWeightFaceMapPtr; 6106*5552b385SBrandon } 6107*5552b385SBrandon 6108*5552b385SBrandon if (cntrlPntEdgeMapObj) { 6109*5552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntEdgeMapObj, (void **)&cntrlPntEdgeMapPtr)); 6110*5552b385SBrandon *cntrlPntEdgeMap = cntrlPntEdgeMapPtr; 6111*5552b385SBrandon } 6112*5552b385SBrandon 6113*5552b385SBrandon if (cntrlPntWeightEdgeMapObj) { 6114*5552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightEdgeMapObj, (void **)&cntrlPntWeightEdgeMapPtr)); 6115*5552b385SBrandon *cntrlPntWeightEdgeMap = cntrlPntWeightEdgeMapPtr; 6116*5552b385SBrandon } 6117*5552b385SBrandon 6118*5552b385SBrandon if (cntrlPntVertexMapObj) { 6119*5552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntVertexMapObj, (void **)&cntrlPntVertexMapPtr)); 6120*5552b385SBrandon *cntrlPntVertexMap = cntrlPntVertexMapPtr; 6121*5552b385SBrandon } 6122*5552b385SBrandon 6123*5552b385SBrandon if (cntrlPntWeightVertexMapObj) { 6124*5552b385SBrandon PetscCall(PetscContainerGetPointer(cntrlPntWeightVertexMapObj, (void **)&cntrlPntWeightVertexMapPtr)); 6125*5552b385SBrandon *cntrlPntWeightVertexMap = cntrlPntWeightVertexMapPtr; 6126*5552b385SBrandon } 6127*5552b385SBrandon 6128*5552b385SBrandon #endif 6129*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 6130*5552b385SBrandon } 6131*5552b385SBrandon 6132*5552b385SBrandon #endif 6133