1 #include "petscsys.h" 2 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3 #include <petsc/private/hashmapi.h> 4 5 /* We need to understand how to natively parse STEP files. There seems to be only one open-source implementation of 6 the STEP parser contained in the OpenCASCADE package. It is enough to make a strong man weep: 7 8 https://github.com/tpaviot/oce/tree/master/src/STEPControl 9 10 The STEP, and inner EXPRESS, formats are ISO standards, so they are documented 11 12 https://stackoverflow.com/questions/26774037/documentation-or-specification-for-step-and-stp-files 13 http://stepmod.sourceforge.net/express_model_spec/ 14 15 but again it seems that there has been a deliberate effort at obfuscation, probably to raise the bar for entrants. 16 */ 17 18 #ifdef PETSC_HAVE_EGADS 19 #include <petscdmplexegads.h> 20 21 PETSC_INTERN PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM, PetscInt, ego, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscScalar[], PetscBool); 22 PETSC_INTERN PetscErrorCode DMPlex_Geom_EDGE_XYZtoUV_Internal(const PetscScalar[], ego, const PetscScalar[], const PetscInt, const PetscInt, PetscScalar[], PetscBool); 23 PETSC_INTERN PetscErrorCode DMPlex_Geom_FACE_XYZtoUV_Internal(const PetscScalar[], ego, const PetscScalar[], const PetscInt, const PetscInt, PetscScalar[], PetscBool); 24 25 PetscErrorCode DMPlex_EGADS_GeomDecode_Internal(const PetscInt geomClass, const PetscInt geomType, char **retClass, char **retType) 26 { 27 PetscFunctionBeginHot; 28 /* EGADS Object Type */ 29 if (geomClass == CONTXT) { *retClass = (char *)"CONTEXT"; } 30 if (geomClass == TRANSFORM) { *retClass = (char *)"TRANSFORM"; } 31 if (geomClass == TESSELLATION) { *retClass = (char *)"TESSELLATION"; } 32 if (geomClass == NIL) { *retClass = (char *)"NIL"; } 33 if (geomClass == EMPTY) { *retClass = (char *)"EMPTY"; } 34 if (geomClass == REFERENCE) { *retClass = (char *)"REFERENCE"; } 35 if (geomClass == PCURVE) { *retClass = (char *)"PCURVE"; } 36 if (geomClass == CURVE) { *retClass = (char *)"CURVE"; } 37 if (geomClass == SURFACE) { *retClass = (char *)"SURFACE"; } 38 if (geomClass == NODE) { *retClass = (char *)"NODE"; } 39 if (geomClass == EDGE) { *retClass = (char *)"EDGE"; } 40 if (geomClass == LOOP) { *retClass = (char *)"LOOP"; } 41 if (geomClass == FACE) { *retClass = (char *)"FACE"; } 42 if (geomClass == SHELL) { *retClass = (char *)"SHELL"; } 43 if (geomClass == BODY) { *retClass = (char *)"BODY"; } 44 if (geomClass == MODEL) { *retClass = (char *)"MODEL"; } 45 46 /* PCURVES & CURVES */ 47 if (geomClass == PCURVE || geomClass == CURVE) { 48 if (geomType == LINE) { *retType = (char *)"LINE"; } 49 if (geomType == CIRCLE) { *retType = (char *)"CIRCLE"; } 50 if (geomType == ELLIPSE) { *retType = (char *)"ELLIPSE"; } 51 if (geomType == PARABOLA) { *retType = (char *)"PARABOLA"; } 52 if (geomType == HYPERBOLA) { *retType = (char *)"HYPERBOLA"; } 53 if (geomType == TRIMMED) { *retType = (char *)"TRIMMED"; } 54 if (geomType == BEZIER) { *retType = (char *)"BEZIER"; } 55 if (geomType == BSPLINE) { *retType = (char *)"BSPLINE"; } 56 if (geomType == OFFSET) { *retType = (char *)"OFFSET"; } 57 } 58 59 /* SURFACE */ 60 if (geomClass == SURFACE) { 61 if (geomType == PLANE) { *retType = (char *)"PLANE"; } 62 if (geomType == SPHERICAL) { *retType = (char *)"SPHERICAL"; } 63 if (geomType == CYLINDRICAL) { *retType = (char *)"CYLINDRICAL"; } 64 if (geomType == REVOLUTION) { *retType = (char *)"REVOLUTION"; } 65 if (geomType == TOROIDAL) { *retType = (char *)"TOROIDAL"; } 66 if (geomType == CONICAL) { *retType = (char *)"CONICAL"; } 67 if (geomType == EXTRUSION) { *retType = (char *)"EXTRUSION"; } 68 if (geomType == BEZIER) { *retType = (char *)"BEZIER"; } 69 if (geomType == BSPLINE) { *retType = (char *)"BSPLINE"; } 70 } 71 72 /* TOPOLOGY */ 73 if (geomClass == NODE || geomClass == EDGE || geomClass == LOOP || geomClass == FACE || geomClass == SHELL || geomClass == BODY || geomClass == MODEL) { 74 if (geomType == SREVERSE) { *retType = (char *)"SREVERSE"; } 75 if (geomType == NOMTYPE) { *retType = (char *)"NOMTYPE"; } 76 if (geomType == SFORWARD && geomClass == FACE) { *retType = (char *)"SFORWARD"; } 77 if (geomType == ONENODE && geomClass == EDGE) { *retType = (char *)"ONENODE"; } 78 if (geomType == TWONODE) { *retType = (char *)"TWONODE"; } 79 if (geomType == OPEN) { *retType = (char *)"OPEN"; } 80 if (geomType == CLOSED) { *retType = (char *)"CLOSED"; } 81 if (geomType == DEGENERATE) { *retType = (char *)"DEGENERATE"; } 82 if (geomType == WIREBODY) { *retType = (char *)"WIREBODY"; } 83 if (geomType == FACEBODY) { *retType = (char *)"FACEBODY"; } 84 if (geomType == SHEETBODY) { *retType = (char *)"SHEETBODY"; } 85 if (geomType == SOLIDBODY) { *retType = (char *)"SOLIDBODY"; } 86 } 87 PetscFunctionReturn(PETSC_SUCCESS); 88 } 89 90 PetscErrorCode DMPlex_EGADS_EDGE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[]) 91 { 92 // 93 // 94 // Depreciated. Changed all references to DMPlex_Geom_FACE_XYZtoUV_Internal() 95 // 96 // 97 98 PetscInt loopCntr = 0; 99 PetscScalar dx, dy, dz, lambda, tolr, obj_old, obj_tmp, target; 100 PetscScalar delta, A, b; 101 PetscScalar ts[2], tt[2], eval[18], data[18]; 102 103 PetscFunctionBeginHot; 104 /* Initialize Levenberg-Marquardt parameters */ 105 lambda = 1.0; 106 tolr = 1.0; 107 target = 1.0E-20; 108 ts[0] = (range[0] + range[1]) / 2.; 109 110 while (tolr >= target) { 111 PetscCall(EG_evaluate(obj, ts, eval)); 112 dx = coords[v * dE + 0] - eval[0]; 113 dy = coords[v * dE + 1] - eval[1]; 114 dz = coords[v * dE + 2] - eval[2]; 115 obj_old = dx * dx + dy * dy + dz * dz; 116 117 if (obj_old < target) { 118 tolr = obj_old; 119 break; 120 } 121 122 A = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 123 if (A == 0.0) { 124 PetscCall(PetscPrintf(PETSC_COMM_SELF, "A = 0.0 \n")); 125 break; 126 } 127 b = eval[3] * dx + eval[4] * dy + eval[5] * dz; 128 129 /* Solve A*delta = b */ 130 delta = b / A; 131 132 /* Find a temp (u,v) and associated objective function */ 133 tt[0] = ts[0] + delta; 134 if (tt[0] < range[0]) { 135 tt[0] = range[0]; 136 delta = tt[0] - ts[0]; 137 } 138 if (tt[0] > range[1]) { 139 tt[0] = range[1]; 140 delta = tt[0] - ts[0]; 141 } 142 143 PetscCall(EG_evaluate(obj, tt, data)); 144 145 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 147 /* If step is better, accept it and halve lambda (making it more Newton-like) */ 148 if (obj_tmp < obj_old) { 149 obj_old = obj_tmp; 150 ts[0] = tt[0]; 151 for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 152 lambda /= 2.0; 153 if (lambda < 1.0E-14) lambda = 1.0E-14; 154 if (obj_old < target) { 155 tolr = obj_old; 156 break; 157 } 158 } else { 159 /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 160 lambda *= 2.0; 161 } 162 163 if ((tt[0] == range[0]) || (tt[0] == range[1])) break; 164 if (fabs(delta) < target) { 165 tolr = obj_old; 166 break; 167 } 168 169 tolr = obj_old; 170 171 loopCntr += 1; 172 if (loopCntr > 100) break; 173 } 174 paramsV[v * 3 + 0] = ts[0]; 175 paramsV[v * 3 + 1] = 0.; 176 PetscFunctionReturn(PETSC_SUCCESS); 177 } 178 179 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 { 181 PetscInt loopCntr = 0; 182 PetscScalar dx, dy, dz, lambda, tolr, obj_old, obj_tmp, target; 183 PetscScalar delta, A, b; 184 PetscScalar ts[2], tt[2], eval[18], data[18]; 185 186 PetscFunctionBeginHot; 187 /* Initialize Levenberg-Marquardt parameters */ 188 lambda = 1.0; 189 tolr = 1.0; 190 target = 1.0E-20; 191 ts[0] = (range[0] + range[1]) / 2.; 192 193 while (tolr >= target) { 194 if (islite) { 195 PetscCall(EGlite_evaluate(obj, ts, eval)); 196 } else { 197 PetscCall(EG_evaluate(obj, ts, eval)); 198 } 199 200 dx = coords[v * dE + 0] - eval[0]; 201 dy = coords[v * dE + 1] - eval[1]; 202 dz = coords[v * dE + 2] - eval[2]; 203 obj_old = dx * dx + dy * dy + dz * dz; 204 205 if (obj_old < target) { 206 tolr = obj_old; 207 break; 208 } 209 210 A = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 211 if (A == 0.0) { 212 PetscCall(PetscPrintf(PETSC_COMM_SELF, "A = 0.0 \n")); 213 break; 214 } 215 b = eval[3] * dx + eval[4] * dy + eval[5] * dz; 216 217 /* Solve A*delta = b */ 218 delta = b / A; 219 220 /* Find a temp (u,v) and associated objective function */ 221 tt[0] = ts[0] + delta; 222 if (tt[0] < range[0]) { 223 tt[0] = range[0]; 224 delta = tt[0] - ts[0]; 225 } 226 if (tt[0] > range[1]) { 227 tt[0] = range[1]; 228 delta = tt[0] - ts[0]; 229 } 230 231 if (islite) { 232 PetscCall(EGlite_evaluate(obj, tt, data)); 233 } else { 234 PetscCall(EG_evaluate(obj, tt, data)); 235 } 236 237 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 239 /* If step is better, accept it and halve lambda (making it more Newton-like) */ 240 if (obj_tmp < obj_old) { 241 obj_old = obj_tmp; 242 ts[0] = tt[0]; 243 for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 244 lambda /= 2.0; 245 if (lambda < 1.0E-14) lambda = 1.0E-14; 246 if (obj_old < target) { 247 tolr = obj_old; 248 break; 249 } 250 } else { 251 /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 252 lambda *= 2.0; 253 } 254 255 if ((tt[0] == range[0]) || (tt[0] == range[1])) break; 256 if (fabs(delta) < target) { 257 tolr = obj_old; 258 break; 259 } 260 261 tolr = obj_old; 262 263 loopCntr += 1; 264 if (loopCntr > 100) break; 265 } 266 paramsV[v * 3 + 0] = ts[0]; 267 paramsV[v * 3 + 1] = 0.; 268 PetscFunctionReturn(PETSC_SUCCESS); 269 } 270 271 PetscErrorCode DMPlex_EGADS_FACE_XYZtoUV_Internal(const PetscScalar coords[], ego obj, const PetscScalar range[], const PetscInt v, const PetscInt dE, PetscScalar paramsV[]) 272 { 273 // 274 // 275 // Depreciated. Changed all references to DMPlex_Geom_FACE_XYZtoUV_Internal() 276 // 277 // 278 279 PetscInt loopCntr = 0; 280 PetscScalar dx, dy, dz, lambda, tolr, denom, obj_old, obj_tmp, target; 281 PetscScalar uvs[2], uvt[2], delta[2], A[4], b[2], eval[18], data[18]; 282 283 PetscFunctionBeginHot; 284 /* Initialize Levenberg-Marquardt parameters */ 285 lambda = 1.0; 286 tolr = 1.0; 287 target = 1.0E-20; 288 uvs[0] = (range[0] + range[1]) / 2.; 289 uvs[1] = (range[2] + range[3]) / 2.; 290 291 while (tolr >= target) { 292 PetscCall(EG_evaluate(obj, uvs, eval)); 293 dx = coords[v * dE + 0] - eval[0]; 294 dy = coords[v * dE + 1] - eval[1]; 295 dz = coords[v * dE + 2] - eval[2]; 296 obj_old = dx * dx + dy * dy + dz * dz; 297 298 if (obj_old < target) { 299 tolr = obj_old; 300 break; 301 } 302 303 A[0] = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 304 A[1] = eval[3] * eval[6] + eval[4] * eval[7] + eval[5] * eval[8]; 305 A[2] = A[1]; 306 A[3] = (eval[6] * eval[6] + eval[7] * eval[7] + eval[8] * eval[8]) * (1.0 + lambda); 307 308 b[0] = eval[3] * dx + eval[4] * dy + eval[5] * dz; 309 b[1] = eval[6] * dx + eval[7] * dy + eval[8] * dz; 310 311 /* Solve A*delta = b using Cramer's Rule */ 312 denom = A[0] * A[3] - A[2] * A[1]; 313 if (denom == 0.0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, "denom = 0.0 \n")); } 314 delta[0] = (b[0] * A[3] - b[1] * A[1]) / denom; 315 delta[1] = (A[0] * b[1] - A[2] * b[0]) / denom; 316 317 /* Find a temp (u,v) and associated objective function */ 318 uvt[0] = uvs[0] + delta[0]; 319 uvt[1] = uvs[1] + delta[1]; 320 321 if (uvt[0] < range[0]) { 322 uvt[0] = range[0]; 323 delta[0] = uvt[0] - uvs[0]; 324 } 325 if (uvt[0] > range[1]) { 326 uvt[0] = range[1]; 327 delta[0] = uvt[0] - uvs[0]; 328 } 329 if (uvt[1] < range[2]) { 330 uvt[1] = range[2]; 331 delta[1] = uvt[1] - uvs[1]; 332 } 333 if (uvt[1] > range[3]) { 334 uvt[1] = range[3]; 335 delta[1] = uvt[1] - uvs[1]; 336 } 337 338 PetscCall(EG_evaluate(obj, uvt, data)); 339 340 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 342 /* If step is better, accept it and halve lambda (making it more Newton-like) */ 343 if (obj_tmp < obj_old) { 344 obj_old = obj_tmp; 345 uvs[0] = uvt[0]; 346 uvs[1] = uvt[1]; 347 for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 348 lambda /= 2.0; 349 if (lambda < 1.0E-14) lambda = 1.0E-14; 350 if (obj_old < target) { 351 tolr = obj_old; 352 break; 353 } 354 } else { 355 /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 356 lambda *= 2.0; 357 } 358 359 if (sqrt(delta[0] * delta[0] + delta[1] * delta[1]) < target) { 360 tolr = obj_old; 361 break; 362 } 363 364 tolr = obj_old; 365 366 loopCntr += 1; 367 if (loopCntr > 100) break; 368 } 369 paramsV[v * 3 + 0] = uvs[0]; 370 paramsV[v * 3 + 1] = uvs[1]; 371 PetscFunctionReturn(PETSC_SUCCESS); 372 } 373 374 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 { 376 PetscInt loopCntr = 0; 377 PetscScalar dx, dy, dz, lambda, tolr, denom, obj_old, obj_tmp, target; 378 PetscScalar uvs[2], uvt[2], delta[2], A[4], b[2], eval[18], data[18]; 379 380 PetscFunctionBeginHot; 381 /* Initialize Levenberg-Marquardt parameters */ 382 lambda = 1.0; 383 tolr = 1.0; 384 target = 1.0E-20; 385 uvs[0] = (range[0] + range[1]) / 2.; 386 uvs[1] = (range[2] + range[3]) / 2.; 387 388 while (tolr >= target) { 389 if (islite) { 390 PetscCallEGADS(EGlite_evaluate, (obj, uvs, eval)); 391 } else { 392 PetscCallEGADS(EG_evaluate, (obj, uvs, eval)); 393 } 394 395 dx = coords[v * dE + 0] - eval[0]; 396 dy = coords[v * dE + 1] - eval[1]; 397 dz = coords[v * dE + 2] - eval[2]; 398 obj_old = dx * dx + dy * dy + dz * dz; 399 400 if (obj_old < target) { 401 tolr = obj_old; 402 break; 403 } 404 405 A[0] = (eval[3] * eval[3] + eval[4] * eval[4] + eval[5] * eval[5]) * (1.0 + lambda); 406 A[1] = eval[3] * eval[6] + eval[4] * eval[7] + eval[5] * eval[8]; 407 A[2] = A[1]; 408 A[3] = (eval[6] * eval[6] + eval[7] * eval[7] + eval[8] * eval[8]) * (1.0 + lambda); 409 410 b[0] = eval[3] * dx + eval[4] * dy + eval[5] * dz; 411 b[1] = eval[6] * dx + eval[7] * dy + eval[8] * dz; 412 413 /* Solve A*delta = b using Cramer's Rule */ 414 denom = A[0] * A[3] - A[2] * A[1]; 415 if (denom == 0.0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, "denom = 0.0 \n")); } 416 delta[0] = (b[0] * A[3] - b[1] * A[1]) / denom; 417 delta[1] = (A[0] * b[1] - A[2] * b[0]) / denom; 418 419 /* Find a temp (u,v) and associated objective function */ 420 uvt[0] = uvs[0] + delta[0]; 421 uvt[1] = uvs[1] + delta[1]; 422 423 if (uvt[0] < range[0]) { 424 uvt[0] = range[0]; 425 delta[0] = uvt[0] - uvs[0]; 426 } 427 if (uvt[0] > range[1]) { 428 uvt[0] = range[1]; 429 delta[0] = uvt[0] - uvs[0]; 430 } 431 if (uvt[1] < range[2]) { 432 uvt[1] = range[2]; 433 delta[1] = uvt[1] - uvs[1]; 434 } 435 if (uvt[1] > range[3]) { 436 uvt[1] = range[3]; 437 delta[1] = uvt[1] - uvs[1]; 438 } 439 440 if (islite) { 441 PetscCall(EGlite_evaluate(obj, uvt, data)); 442 } else { 443 PetscCall(EG_evaluate(obj, uvt, data)); 444 } 445 446 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 448 /* If step is better, accept it and halve lambda (making it more Newton-like) */ 449 if (obj_tmp < obj_old) { 450 obj_old = obj_tmp; 451 uvs[0] = uvt[0]; 452 uvs[1] = uvt[1]; 453 for (int jj = 0; jj < 18; ++jj) eval[jj] = data[jj]; 454 lambda /= 2.0; 455 if (lambda < 1.0E-14) lambda = 1.0E-14; 456 if (obj_old < target) { 457 tolr = obj_old; 458 break; 459 } 460 } else { 461 /* Otherwise reject it and double lambda (making it more gradient-descent like) */ 462 lambda *= 2.0; 463 } 464 465 if (sqrt(delta[0] * delta[0] + delta[1] * delta[1]) < target) { 466 tolr = obj_old; 467 break; 468 } 469 470 tolr = obj_old; 471 472 loopCntr += 1; 473 if (loopCntr > 100) break; 474 } 475 paramsV[v * 3 + 0] = uvs[0]; 476 paramsV[v * 3 + 1] = uvs[1]; 477 PetscFunctionReturn(PETSC_SUCCESS); 478 } 479 480 PetscErrorCode DMSnapToGeomModel_EGADS_Internal(DM dm, PetscInt p, ego model, PetscInt bodyID, PetscInt faceID, PetscInt edgeID, const PetscScalar mcoords[], PetscScalar gcoords[], PetscBool islite) 481 { 482 /* PETSc Variables */ 483 DM cdm; 484 ego *bodies; 485 ego geom, body, obj; 486 /* result has to hold derviatives, along with the value */ 487 double params[3], result[18], paramsV[16 * 3], range[4]; 488 int Nb, oclass, mtype, *senses, peri; 489 Vec coordinatesLocal; 490 PetscScalar *coords = NULL; 491 PetscInt Nv, v, Np = 0, pm; 492 PetscInt dE, d; 493 PetscReal pTolr = 1.0e-14; 494 495 PetscFunctionBeginHot; 496 PetscCall(DMGetCoordinateDM(dm, &cdm)); 497 PetscCall(DMGetCoordinateDim(dm, &dE)); 498 PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 499 500 if (islite) { 501 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 502 } else { 503 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 504 } 505 506 PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bodyID, Nb); 507 body = bodies[bodyID]; 508 509 if (edgeID >= 0) { 510 if (islite) { 511 PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &obj)); 512 Np = 1; 513 } else { 514 PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &obj)); 515 Np = 1; 516 } 517 } else if (faceID >= 0) { 518 if (islite) { 519 PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &obj)); 520 Np = 2; 521 } else { 522 PetscCall(EG_objectBodyTopo(body, FACE, faceID, &obj)); 523 Np = 2; 524 } 525 } else { 526 for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 527 PetscFunctionReturn(PETSC_SUCCESS); 528 } 529 530 /* Calculate parameters (t or u,v) for vertices */ 531 PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 532 Nv /= dE; 533 if (Nv == 1) { 534 PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 535 for (d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 PetscCheck(Nv <= 16, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " coordinates associated to point %" PetscInt_FMT, Nv, p); 539 540 /* Correct EGADS/EGADSlite 2pi bug when calculating nearest point on Periodic Surfaces */ 541 if (islite) { 542 PetscCall(EGlite_getRange(obj, range, &peri)); 543 } else { 544 PetscCall(EG_getRange(obj, range, &peri)); 545 } 546 547 for (v = 0; v < Nv; ++v) { 548 if (edgeID > 0) { 549 PetscCall(DMPlex_Geom_EDGE_XYZtoUV_Internal(coords, obj, range, v, dE, paramsV, islite)); 550 } else { 551 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, obj, range, v, dE, paramsV, islite)); 552 } 553 } 554 PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, p, &Nv, &coords)); 555 556 /* Calculate parameters (t or u,v) for new vertex at edge midpoint */ 557 for (pm = 0; pm < Np; ++pm) { 558 params[pm] = 0.; 559 for (v = 0; v < Nv; ++v) params[pm] += paramsV[v * 3 + pm]; 560 params[pm] /= Nv; 561 } 562 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 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 565 /* Put coordinates for new vertex in result[] */ 566 if (islite) { 567 PetscCall(EGlite_evaluate(obj, params, result)); 568 } else { 569 PetscCall(EG_evaluate(obj, params, result)); 570 } 571 572 for (d = 0; d < dE; ++d) gcoords[d] = result[d]; 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 #endif 576 577 PetscErrorCode DMSnapToGeomModel_EGADS(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[]) 578 { 579 PetscFunctionBeginHot; 580 #ifdef PETSC_HAVE_EGADS 581 DMLabel bodyLabel, faceLabel, edgeLabel; 582 PetscInt bodyID, faceID, edgeID; 583 PetscContainer modelObj; 584 ego model; 585 PetscBool islite = PETSC_FALSE; 586 587 // FIXME: Change -dm_plex_refine_without_snap_to_geom to DM to shut off snapping 588 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 589 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 590 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 591 PetscCheck(bodyLabel && faceLabel && edgeLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADS meshes must have body, face, and edge labels defined"); 592 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 593 if (!modelObj) { 594 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 595 islite = PETSC_TRUE; 596 } 597 PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "EGADS mesh missing model object"); 598 599 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 600 PetscCall(DMLabelGetValue(bodyLabel, p, &bodyID)); 601 PetscCall(DMLabelGetValue(faceLabel, p, &faceID)); 602 PetscCall(DMLabelGetValue(edgeLabel, p, &edgeID)); 603 /* Allows for "Connective" Plex Edges present in models with multiple non-touching Entities */ 604 if (bodyID < 0) { 605 for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d]; 606 PetscFunctionReturn(PETSC_SUCCESS); 607 } 608 PetscCall(DMSnapToGeomModel_EGADS_Internal(dm, p, model, bodyID, faceID, edgeID, mcoords, gcoords, islite)); 609 #endif 610 PetscFunctionReturn(PETSC_SUCCESS); 611 } 612 613 #if defined(PETSC_HAVE_EGADS) 614 PetscErrorCode DMPlexGeomPrintModel_Internal(ego model, PetscBool islite) 615 { 616 /* PETSc Variables */ 617 ego geom, *bodies, *nobjs, *mobjs, *lobjs, *shobjs, *fobjs, *eobjs; 618 int oclass, mtype, *senses, *shsenses, *fsenses, *lsenses, *esenses; 619 int Nb, b; 620 621 PetscFunctionBeginUser; 622 /* test bodyTopo functions */ 623 if (islite) { 624 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 625 } else { 626 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 627 } 628 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of BODIES (nbodies): %" PetscInt_FMT " \n", Nb)); 629 630 for (b = 0; b < Nb; ++b) { 631 ego body = bodies[b]; 632 int id, sh, Nsh, f, Nf, l, Nl, e, Ne, v, Nv; 633 634 /* List Topology of Bodies */ 635 PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 636 PetscCall(PetscPrintf(PETSC_COMM_SELF, " BODY %d TOPOLOGY SUMMARY \n", b)); 637 638 /* Output Basic Model Topology */ 639 if (islite) { 640 PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, &Nsh, &shobjs)); 641 } else { 642 PetscCall(EG_getBodyTopos(body, NULL, SHELL, &Nsh, &shobjs)); 643 } 644 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of SHELLS: %d \n", Nsh)); 645 646 if (islite) { 647 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 648 } else { 649 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 650 } 651 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of FACES: %d \n", Nf)); 652 653 if (islite) { 654 PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 655 } else { 656 PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 657 } 658 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of LOOPS: %d \n", Nl)); 659 660 if (islite) { 661 PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 662 } else { 663 PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 664 } 665 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of EDGES: %d \n", Ne)); 666 667 if (islite) { 668 PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 669 } else { 670 PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 671 } 672 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Number of NODES: %d \n", Nv)); 673 674 if (islite) { 675 EGlite_free(shobjs); 676 EGlite_free(fobjs); 677 EGlite_free(lobjs); 678 EGlite_free(eobjs); 679 EGlite_free(nobjs); 680 } else { 681 EG_free(shobjs); 682 EG_free(fobjs); 683 EG_free(lobjs); 684 EG_free(eobjs); 685 EG_free(nobjs); 686 } 687 688 /* List Topology of Bodies */ 689 PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 690 PetscCall(PetscPrintf(PETSC_COMM_SELF, " BODY %d TOPOLOGY DETAILS \n", b)); 691 692 /* Get SHELL info which associated with the current BODY */ 693 if (islite) { 694 PetscCall(EGlite_getTopology(body, &geom, &oclass, &mtype, NULL, &Nsh, &shobjs, &shsenses)); 695 } else { 696 PetscCall(EG_getTopology(body, &geom, &oclass, &mtype, NULL, &Nsh, &shobjs, &shsenses)); 697 } 698 699 for (sh = 0; sh < Nsh; ++sh) { 700 ego shell = shobjs[sh]; 701 int shsense = shsenses[sh]; 702 703 if (islite) { 704 id = EGlite_indexBodyTopo(body, shell); 705 } else { 706 id = EG_indexBodyTopo(body, shell); 707 } 708 PetscCall(PetscPrintf(PETSC_COMM_SELF, " SHELL ID: %d :: sense = %d\n", id, shsense)); 709 710 /* Get FACE infor associated with current SHELL */ 711 if (islite) { 712 PetscCall(EGlite_getTopology(shell, &geom, &oclass, &mtype, NULL, &Nf, &fobjs, &fsenses)); 713 } else { 714 PetscCall(EG_getTopology(shell, &geom, &oclass, &mtype, NULL, &Nf, &fobjs, &fsenses)); 715 } 716 717 for (f = 0; f < Nf; ++f) { 718 ego face = fobjs[f]; 719 ego gRef, gPrev, gNext; 720 int goclass, gmtype, *gpinfo; 721 double *gprv; 722 char *gClass = (char *)"", *gType = (char *)""; 723 double fdata[4]; 724 ego fRef, fPrev, fNext; 725 int foclass, fmtype; 726 727 if (islite) { 728 id = EGlite_indexBodyTopo(body, face); 729 } else { 730 id = EG_indexBodyTopo(body, face); 731 } 732 733 /* Get LOOP info associated with current FACE */ 734 if (islite) { 735 PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, fdata, &Nl, &lobjs, &lsenses)); 736 PetscCall(EGlite_getInfo(face, &foclass, &fmtype, &fRef, &fPrev, &fNext)); 737 PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 738 PetscCall(EGlite_getInfo(geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 739 } else { 740 PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, fdata, &Nl, &lobjs, &lsenses)); 741 PetscCall(EG_getInfo(face, &foclass, &fmtype, &fRef, &fPrev, &fNext)); 742 PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 743 PetscCall(EG_getInfo(geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 744 } 745 746 PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType)); 747 PetscCall(PetscPrintf(PETSC_COMM_SELF, " FACE ID: %d :: sense = %d \n", id, fmtype)); 748 PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY CLASS: %s \n", gClass)); 749 PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY TYPE: %s \n\n", gType)); 750 PetscCall(PetscPrintf(PETSC_COMM_SELF, " RANGE (umin, umax) = (%f, %f) \n", fdata[0], fdata[1])); 751 PetscCall(PetscPrintf(PETSC_COMM_SELF, " (vmin, vmax) = (%f, %f) \n\n", fdata[2], fdata[3])); 752 753 for (l = 0; l < Nl; ++l) { 754 ego loop = lobjs[l]; 755 int lsense = lsenses[l]; 756 757 if (islite) { 758 id = EGlite_indexBodyTopo(body, loop); 759 } else { 760 id = EG_indexBodyTopo(body, loop); 761 } 762 763 PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP ID: %d :: sense = %d\n", id, lsense)); 764 765 /* Get EDGE info associated with the current LOOP */ 766 if (islite) { 767 PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &esenses)); 768 } else { 769 PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &esenses)); 770 } 771 772 for (e = 0; e < Ne; ++e) { 773 ego edge = eobjs[e]; 774 ego topRef, prev, next; 775 int esense = esenses[e]; 776 double range[4] = {0., 0., 0., 0.}; 777 int peri; 778 ego gEref, gEprev, gEnext; 779 int gEoclass, gEmtype; 780 char *gEclass = (char *)"", *gEtype = (char *)""; 781 782 if (islite) { 783 PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 784 if (mtype != DEGENERATE) { PetscCall(EGlite_getInfo(geom, &gEoclass, &gEmtype, &gEref, &gEprev, &gEnext)); } 785 } else { 786 PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 787 PetscCall(EG_getInfo(geom, &gEoclass, &gEmtype, &gEref, &gEprev, &gEnext)); 788 } 789 790 if (mtype != DEGENERATE) { PetscCall(DMPlex_EGADS_GeomDecode_Internal(gEoclass, gEmtype, &gEclass, &gEtype)); } 791 792 if (islite) { 793 id = EGlite_indexBodyTopo(body, edge); 794 PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 795 } else { 796 id = EG_indexBodyTopo(body, edge); 797 PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 798 } 799 800 PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE ID: %d :: sense = %d\n", id, esense)); 801 if (mtype != DEGENERATE) { 802 PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY CLASS: %s \n", gEclass)); 803 PetscCall(PetscPrintf(PETSC_COMM_SELF, " GEOMETRY TYPE: %s \n", gEtype)); 804 } 805 806 if (mtype == DEGENERATE) { PetscCall(PetscPrintf(PETSC_COMM_SELF, " EDGE %d is DEGENERATE \n", id)); } 807 808 if (islite) { 809 PetscCall(EGlite_getRange(edge, range, &peri)); 810 } else { 811 PetscCall(EG_getRange(edge, range, &peri)); 812 } 813 814 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Peri = %d :: Range = %lf, %lf, %lf, %lf \n", peri, range[0], range[1], range[2], range[3])); 815 816 /* Get NODE info associated with the current EDGE */ 817 if (islite) { 818 PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 819 } else { 820 PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 821 } 822 823 for (v = 0; v < Nv; ++v) { 824 ego vertex = nobjs[v]; 825 double limits[4]; 826 int dummy; 827 828 if (islite) { 829 PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 830 id = EGlite_indexBodyTopo(body, vertex); 831 } else { 832 PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 833 id = EG_indexBodyTopo(body, vertex); 834 } 835 PetscCall(PetscPrintf(PETSC_COMM_SELF, " NODE ID: %d \n", id)); 836 PetscCall(PetscPrintf(PETSC_COMM_SELF, " (x, y, z) = (%lf, %lf, %lf) \n", limits[0], limits[1], limits[2])); 837 } 838 } 839 } 840 } 841 } 842 } 843 PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n\n")); 844 PetscFunctionReturn(PETSC_SUCCESS); 845 } 846 847 static PetscErrorCode DMPlexEGADSDestroy_Private(void **context) 848 { 849 if (*context) EG_deleteObject((ego)*context); 850 return (PETSC_SUCCESS); 851 } 852 853 static PetscErrorCode DMPlexEGADSClose_Private(void **context) 854 { 855 if (*context) EG_close((ego)*context); 856 return (PETSC_SUCCESS); 857 } 858 859 PetscErrorCode DMPlexEGADSliteDestroy_Private(void **context) 860 { 861 if (*context) EGlite_deleteObject((ego)*context); 862 return 0; 863 } 864 865 PetscErrorCode DMPlexEGADSliteClose_Private(void **context) 866 { 867 if (*context) EGlite_close((ego)*context); 868 return 0; 869 } 870 871 PetscErrorCode DMPlexCreateGeom_Internal(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 872 { 873 /* EGADS variables */ 874 ego geom, *bodies, *objs, *nobjs, *mobjs, *lobjs; 875 int oclass, mtype, nbodies, *senses; 876 int b; 877 /* PETSc variables */ 878 DM dm; 879 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 880 PetscHMapI edgeMap = NULL; 881 PetscInt cStart, cEnd, c; 882 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; 883 PetscInt *cells = NULL, *cone = NULL; 884 PetscReal *coords = NULL; 885 PetscMPIInt rank; 886 887 PetscFunctionBegin; 888 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 889 if (rank == 0) { 890 const PetscInt debug = 0; 891 892 /* --------------------------------------------------------------------------------------------------- 893 Generate Petsc Plex 894 Get all Nodes in model, record coordinates in a correctly formatted array 895 Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array 896 We need to uniformly refine the initial geometry to guarantee a valid mesh 897 */ 898 899 /* Calculate cell and vertex sizes */ 900 if (islite) { 901 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 902 } else { 903 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 904 } 905 906 PetscCall(PetscHMapICreate(&edgeMap)); 907 numEdges = 0; 908 for (b = 0; b < nbodies; ++b) { 909 ego body = bodies[b]; 910 int id, Nl, l, Nv, v; 911 912 if (islite) { 913 PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 914 } else { 915 PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 916 } 917 918 for (l = 0; l < Nl; ++l) { 919 ego loop = lobjs[l]; 920 int Ner = 0, Ne, e, Nc; 921 922 if (islite) { 923 PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 924 } else { 925 PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 926 } 927 928 for (e = 0; e < Ne; ++e) { 929 ego edge = objs[e]; 930 int Nv, id; 931 PetscHashIter iter; 932 PetscBool found; 933 934 if (islite) { 935 PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 936 } else { 937 PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 938 } 939 940 if (mtype == DEGENERATE) continue; 941 942 if (islite) { 943 id = EGlite_indexBodyTopo(body, edge); 944 } else { 945 id = EG_indexBodyTopo(body, edge); 946 } 947 948 PetscCall(PetscHMapIFind(edgeMap, id - 1, &iter, &found)); 949 if (!found) { PetscCall(PetscHMapISet(edgeMap, id - 1, numEdges++)); } 950 ++Ner; 951 } 952 if (Ner == 2) { 953 Nc = 2; 954 } else if (Ner == 3) { 955 Nc = 4; 956 } else if (Ner == 4) { 957 Nc = 8; 958 ++numQuads; 959 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot support loop with %d edges", Ner); 960 numCells += Nc; 961 newCells += Nc - 1; 962 maxCorners = PetscMax(Ner * 2 + 1, maxCorners); 963 } 964 if (islite) { 965 PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 966 } else { 967 PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 968 } 969 970 for (v = 0; v < Nv; ++v) { 971 ego vertex = nobjs[v]; 972 973 if (islite) { 974 id = EGlite_indexBodyTopo(body, vertex); 975 } else { 976 id = EG_indexBodyTopo(body, vertex); 977 } 978 /* TODO: Instead of assuming contiguous ids, we could use a hash table */ 979 numVertices = PetscMax(id, numVertices); 980 } 981 if (islite) { 982 EGlite_free(lobjs); 983 EGlite_free(nobjs); 984 } else { 985 EG_free(lobjs); 986 EG_free(nobjs); 987 } 988 } 989 PetscCall(PetscHMapIGetSize(edgeMap, &numEdges)); 990 newVertices = numEdges + numQuads; 991 numVertices += newVertices; 992 993 dim = 2; /* Assume 3D Models :: Need to update to handle 2D Models in the future */ 994 cdim = 3; /* Assume 3D Models :: Need to update to handle 2D Models in the future */ 995 numCorners = 3; /* Split cells into triangles */ 996 PetscCall(PetscMalloc3(numVertices * cdim, &coords, numCells * numCorners, &cells, maxCorners, &cone)); 997 998 /* Get vertex coordinates */ 999 for (b = 0; b < nbodies; ++b) { 1000 ego body = bodies[b]; 1001 int id, Nv, v; 1002 1003 if (islite) { 1004 PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1005 } else { 1006 PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1007 } 1008 1009 for (v = 0; v < Nv; ++v) { 1010 ego vertex = nobjs[v]; 1011 double limits[4]; 1012 int dummy; 1013 1014 if (islite) { 1015 PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 1016 id = EGlite_indexBodyTopo(body, vertex); 1017 } else { 1018 PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 1019 id = EG_indexBodyTopo(body, vertex); 1020 } 1021 1022 coords[(id - 1) * cdim + 0] = limits[0]; 1023 coords[(id - 1) * cdim + 1] = limits[1]; 1024 coords[(id - 1) * cdim + 2] = limits[2]; 1025 } 1026 if (islite) { 1027 EGlite_free(nobjs); 1028 } else { 1029 EG_free(nobjs); 1030 } 1031 } 1032 PetscCall(PetscHMapIClear(edgeMap)); 1033 fOff = numVertices - newVertices + numEdges; 1034 numEdges = 0; 1035 numQuads = 0; 1036 for (b = 0; b < nbodies; ++b) { 1037 ego body = bodies[b]; 1038 int Nl, l; 1039 1040 if (islite) { 1041 PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1042 } else { 1043 PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1044 } 1045 1046 for (l = 0; l < Nl; ++l) { 1047 ego loop = lobjs[l]; 1048 int lid, Ner = 0, Ne, e; 1049 1050 if (islite) { 1051 lid = EGlite_indexBodyTopo(body, loop); 1052 PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1053 } else { 1054 lid = EG_indexBodyTopo(body, loop); 1055 PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1056 } 1057 1058 for (e = 0; e < Ne; ++e) { 1059 ego edge = objs[e]; 1060 int eid, Nv; 1061 PetscHashIter iter; 1062 PetscBool found; 1063 1064 if (islite) { 1065 PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1066 } else { 1067 PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1068 } 1069 1070 if (mtype == DEGENERATE) continue; 1071 ++Ner; 1072 1073 if (islite) { 1074 eid = EGlite_indexBodyTopo(body, edge); 1075 } else { 1076 eid = EG_indexBodyTopo(body, edge); 1077 } 1078 1079 PetscCall(PetscHMapIFind(edgeMap, eid - 1, &iter, &found)); 1080 if (!found) { 1081 PetscInt v = numVertices - newVertices + numEdges; 1082 double range[4], params[3] = {0., 0., 0.}, result[18]; 1083 int periodic[2]; 1084 1085 PetscCall(PetscHMapISet(edgeMap, eid - 1, numEdges++)); 1086 1087 if (islite) { 1088 PetscCall(EGlite_getRange(edge, range, periodic)); 1089 } else { 1090 PetscCall(EG_getRange(edge, range, periodic)); 1091 } 1092 1093 params[0] = 0.5 * (range[0] + range[1]); 1094 if (islite) { 1095 PetscCall(EGlite_evaluate(edge, params, result)); 1096 } else { 1097 PetscCall(EG_evaluate(edge, params, result)); 1098 } 1099 coords[v * cdim + 0] = result[0]; 1100 coords[v * cdim + 1] = result[1]; 1101 coords[v * cdim + 2] = result[2]; 1102 } 1103 } 1104 if (Ner == 4) { 1105 PetscInt v = fOff + numQuads++; 1106 ego *fobjs, face; 1107 double range[4], params[3] = {0., 0., 0.}, result[18]; 1108 int Nf, fid, periodic[2]; 1109 1110 if (islite) { 1111 PetscCall(EGlite_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 1112 } else { 1113 PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 1114 } 1115 face = fobjs[0]; 1116 1117 if (islite) { 1118 fid = EGlite_indexBodyTopo(body, face); 1119 } else { 1120 fid = EG_indexBodyTopo(body, face); 1121 } 1122 1123 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 if (islite) { 1125 PetscCall(EGlite_getRange(face, range, periodic)); 1126 } else { 1127 PetscCall(EG_getRange(face, range, periodic)); 1128 } 1129 params[0] = 0.5 * (range[0] + range[1]); 1130 params[1] = 0.5 * (range[2] + range[3]); 1131 if (islite) { 1132 PetscCall(EGlite_evaluate(face, params, result)); 1133 } else { 1134 PetscCall(EG_evaluate(face, params, result)); 1135 } 1136 coords[v * cdim + 0] = result[0]; 1137 coords[v * cdim + 1] = result[1]; 1138 coords[v * cdim + 2] = result[2]; 1139 } 1140 } 1141 } 1142 PetscCheck(numEdges + numQuads == newVertices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of new vertices %d != %d previous count", numEdges + numQuads, newVertices); 1143 1144 /* Get cell vertices by traversing loops */ 1145 numQuads = 0; 1146 cOff = 0; 1147 for (b = 0; b < nbodies; ++b) { 1148 ego body = bodies[b]; 1149 int id, Nl, l; 1150 1151 if (islite) { 1152 PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1153 } else { 1154 PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1155 } 1156 for (l = 0; l < Nl; ++l) { 1157 ego loop = lobjs[l]; 1158 int lid, Ner = 0, Ne, e, nc = 0, c, Nt, t; 1159 1160 if (islite) { 1161 lid = EGlite_indexBodyTopo(body, loop); 1162 PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1163 } else { 1164 lid = EG_indexBodyTopo(body, loop); 1165 PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1166 } 1167 1168 for (e = 0; e < Ne; ++e) { 1169 ego edge = objs[e]; 1170 int points[3]; 1171 int eid, Nv, v, tmp; 1172 1173 if (islite) { 1174 eid = EGlite_indexBodyTopo(body, edge); 1175 PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1176 } else { 1177 eid = EG_indexBodyTopo(body, edge); 1178 PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1179 } 1180 1181 if (mtype == DEGENERATE) continue; 1182 else ++Ner; 1183 PetscCheck(Nv == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Edge %" PetscInt_FMT " has %" PetscInt_FMT " vertices != 2", eid, Nv); 1184 1185 for (v = 0; v < Nv; ++v) { 1186 ego vertex = nobjs[v]; 1187 1188 if (islite) { 1189 id = EGlite_indexBodyTopo(body, vertex); 1190 } else { 1191 id = EG_indexBodyTopo(body, vertex); 1192 } 1193 points[v * 2] = id - 1; 1194 } 1195 { 1196 PetscInt edgeNum; 1197 1198 PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum)); 1199 points[1] = numVertices - newVertices + edgeNum; 1200 } 1201 /* EGADS loops are not oriented, but seem to be in order, so we must piece them together */ 1202 if (!nc) { 1203 for (v = 0; v < Nv + 1; ++v) cone[nc++] = points[v]; 1204 } else { 1205 if (cone[nc - 1] == points[0]) { 1206 cone[nc++] = points[1]; 1207 if (cone[0] != points[2]) cone[nc++] = points[2]; 1208 } else if (cone[nc - 1] == points[2]) { 1209 cone[nc++] = points[1]; 1210 if (cone[0] != points[0]) cone[nc++] = points[0]; 1211 } else if (cone[nc - 3] == points[0]) { 1212 tmp = cone[nc - 3]; 1213 cone[nc - 3] = cone[nc - 1]; 1214 cone[nc - 1] = tmp; 1215 cone[nc++] = points[1]; 1216 if (cone[0] != points[2]) cone[nc++] = points[2]; 1217 } else if (cone[nc - 3] == points[2]) { 1218 tmp = cone[nc - 3]; 1219 cone[nc - 3] = cone[nc - 1]; 1220 cone[nc - 1] = tmp; 1221 cone[nc++] = points[1]; 1222 if (cone[0] != points[0]) cone[nc++] = points[0]; 1223 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %d does not match its predecessor", eid); 1224 } 1225 } 1226 PetscCheck(nc == 2 * Ner, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " != %" PetscInt_FMT, nc, 2 * Ner); 1227 if (Ner == 4) { cone[nc++] = numVertices - newVertices + numEdges + numQuads++; } 1228 PetscCheck(nc <= maxCorners, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of corners %" PetscInt_FMT " > %" PetscInt_FMT " max", nc, maxCorners); 1229 /* Triangulate the loop */ 1230 switch (Ner) { 1231 case 2: /* Bi-Segment -> 2 triangles */ 1232 Nt = 2; 1233 cells[cOff * numCorners + 0] = cone[0]; 1234 cells[cOff * numCorners + 1] = cone[1]; 1235 cells[cOff * numCorners + 2] = cone[2]; 1236 ++cOff; 1237 cells[cOff * numCorners + 0] = cone[0]; 1238 cells[cOff * numCorners + 1] = cone[2]; 1239 cells[cOff * numCorners + 2] = cone[3]; 1240 ++cOff; 1241 break; 1242 case 3: /* Triangle -> 4 triangles */ 1243 Nt = 4; 1244 cells[cOff * numCorners + 0] = cone[0]; 1245 cells[cOff * numCorners + 1] = cone[1]; 1246 cells[cOff * numCorners + 2] = cone[5]; 1247 ++cOff; 1248 cells[cOff * numCorners + 0] = cone[1]; 1249 cells[cOff * numCorners + 1] = cone[2]; 1250 cells[cOff * numCorners + 2] = cone[3]; 1251 ++cOff; 1252 cells[cOff * numCorners + 0] = cone[5]; 1253 cells[cOff * numCorners + 1] = cone[3]; 1254 cells[cOff * numCorners + 2] = cone[4]; 1255 ++cOff; 1256 cells[cOff * numCorners + 0] = cone[1]; 1257 cells[cOff * numCorners + 1] = cone[3]; 1258 cells[cOff * numCorners + 2] = cone[5]; 1259 ++cOff; 1260 break; 1261 case 4: /* Quad -> 8 triangles */ 1262 Nt = 8; 1263 cells[cOff * numCorners + 0] = cone[0]; 1264 cells[cOff * numCorners + 1] = cone[1]; 1265 cells[cOff * numCorners + 2] = cone[7]; 1266 ++cOff; 1267 cells[cOff * numCorners + 0] = cone[1]; 1268 cells[cOff * numCorners + 1] = cone[2]; 1269 cells[cOff * numCorners + 2] = cone[3]; 1270 ++cOff; 1271 cells[cOff * numCorners + 0] = cone[3]; 1272 cells[cOff * numCorners + 1] = cone[4]; 1273 cells[cOff * numCorners + 2] = cone[5]; 1274 ++cOff; 1275 cells[cOff * numCorners + 0] = cone[5]; 1276 cells[cOff * numCorners + 1] = cone[6]; 1277 cells[cOff * numCorners + 2] = cone[7]; 1278 ++cOff; 1279 cells[cOff * numCorners + 0] = cone[8]; 1280 cells[cOff * numCorners + 1] = cone[1]; 1281 cells[cOff * numCorners + 2] = cone[3]; 1282 ++cOff; 1283 cells[cOff * numCorners + 0] = cone[8]; 1284 cells[cOff * numCorners + 1] = cone[3]; 1285 cells[cOff * numCorners + 2] = cone[5]; 1286 ++cOff; 1287 cells[cOff * numCorners + 0] = cone[8]; 1288 cells[cOff * numCorners + 1] = cone[5]; 1289 cells[cOff * numCorners + 2] = cone[7]; 1290 ++cOff; 1291 cells[cOff * numCorners + 0] = cone[8]; 1292 cells[cOff * numCorners + 1] = cone[7]; 1293 cells[cOff * numCorners + 2] = cone[1]; 1294 ++cOff; 1295 break; 1296 default: 1297 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d edges, which we do not support", lid, Ner); 1298 } 1299 if (debug) { 1300 for (t = 0; t < Nt; ++t) { 1301 PetscCall(PetscPrintf(PETSC_COMM_SELF, " LOOP Corner NODEs Triangle %d (", t)); 1302 for (c = 0; c < numCorners; ++c) { 1303 if (c > 0) { PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); } 1304 PetscCall(PetscPrintf(PETSC_COMM_SELF, "%d", cells[(cOff - Nt + t) * numCorners + c])); 1305 } 1306 PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n")); 1307 } 1308 } 1309 } 1310 if (islite) { 1311 EGlite_free(lobjs); 1312 } else { 1313 EG_free(lobjs); 1314 } 1315 } 1316 } 1317 PetscCheck(cOff == numCells, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count of total cells %d != %d previous count", cOff, numCells); 1318 PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numVertices, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 1319 PetscCall(PetscFree3(coords, cells, cone)); 1320 PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %d (%d)\n", numCells, newCells)); 1321 PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %d (%d)\n", numVertices, newVertices)); 1322 /* Embed EGADS model in DM */ 1323 { 1324 PetscContainer modelObj, contextObj; 1325 1326 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 1327 PetscCall(PetscContainerSetPointer(modelObj, model)); 1328 PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSDestroy_Private)); 1329 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 1330 PetscCall(PetscContainerDestroy(&modelObj)); 1331 1332 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 1333 PetscCall(PetscContainerSetPointer(contextObj, context)); 1334 PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSClose_Private)); 1335 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 1336 PetscCall(PetscContainerDestroy(&contextObj)); 1337 } 1338 /* Label points */ 1339 PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 1340 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 1341 PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 1342 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 1343 PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 1344 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 1345 PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 1346 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 1347 cOff = 0; 1348 for (b = 0; b < nbodies; ++b) { 1349 ego body = bodies[b]; 1350 int id, Nl, l; 1351 1352 if (islite) { 1353 PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1354 } else { 1355 PetscCall(EG_getBodyTopos(body, NULL, LOOP, &Nl, &lobjs)); 1356 } 1357 for (l = 0; l < Nl; ++l) { 1358 ego loop = lobjs[l]; 1359 ego *fobjs; 1360 int lid, Nf, fid, Ner = 0, Ne, e, Nt = 0, t; 1361 1362 if (islite) { 1363 lid = EGlite_indexBodyTopo(body, loop); 1364 PetscCall(EGlite_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 1365 } else { 1366 lid = EG_indexBodyTopo(body, loop); 1367 PetscCall(EG_getBodyTopos(body, loop, FACE, &Nf, &fobjs)); 1368 } 1369 1370 PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %d has %d > 1 faces, which is not supported", lid, Nf); 1371 if (islite) { 1372 fid = EGlite_indexBodyTopo(body, fobjs[0]); 1373 EGlite_free(fobjs); 1374 PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1375 } else { 1376 fid = EG_indexBodyTopo(body, fobjs[0]); 1377 EG_free(fobjs); 1378 PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &objs, &senses)); 1379 } 1380 1381 for (e = 0; e < Ne; ++e) { 1382 ego edge = objs[e]; 1383 int eid, Nv, v; 1384 PetscInt points[3], support[2], numEdges, edgeNum; 1385 const PetscInt *edges; 1386 1387 if (islite) { 1388 eid = EGlite_indexBodyTopo(body, edge); 1389 PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1390 } else { 1391 eid = EG_indexBodyTopo(body, edge); 1392 PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1393 } 1394 1395 if (mtype == DEGENERATE) continue; 1396 else ++Ner; 1397 for (v = 0; v < Nv; ++v) { 1398 ego vertex = nobjs[v]; 1399 1400 if (islite) { 1401 id = EGlite_indexBodyTopo(body, vertex); 1402 } else { 1403 id = EG_indexBodyTopo(body, vertex); 1404 } 1405 1406 PetscCall(DMLabelSetValue(edgeLabel, numCells + id - 1, eid)); 1407 points[v * 2] = numCells + id - 1; 1408 } 1409 PetscCall(PetscHMapIGet(edgeMap, eid - 1, &edgeNum)); 1410 points[1] = numCells + numVertices - newVertices + edgeNum; 1411 1412 PetscCall(DMLabelSetValue(edgeLabel, points[1], eid)); 1413 support[0] = points[0]; 1414 support[1] = points[1]; 1415 PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges)); 1416 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); 1417 PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid)); 1418 PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges)); 1419 support[0] = points[1]; 1420 support[1] = points[2]; 1421 PetscCall(DMPlexGetJoin(dm, 2, support, &numEdges, &edges)); 1422 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); 1423 PetscCall(DMLabelSetValue(edgeLabel, edges[0], eid)); 1424 PetscCall(DMPlexRestoreJoin(dm, 2, support, &numEdges, &edges)); 1425 } 1426 switch (Ner) { 1427 case 2: 1428 Nt = 2; 1429 break; 1430 case 3: 1431 Nt = 4; 1432 break; 1433 case 4: 1434 Nt = 8; 1435 break; 1436 default: 1437 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Loop with %d edges is unsupported", Ner); 1438 } 1439 for (t = 0; t < Nt; ++t) { 1440 PetscCall(DMLabelSetValue(bodyLabel, cOff + t, b)); 1441 PetscCall(DMLabelSetValue(faceLabel, cOff + t, fid)); 1442 } 1443 cOff += Nt; 1444 } 1445 if (islite) { 1446 EGlite_free(lobjs); 1447 } else { 1448 EG_free(lobjs); 1449 } 1450 } 1451 PetscCall(PetscHMapIDestroy(&edgeMap)); 1452 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1453 for (c = cStart; c < cEnd; ++c) { 1454 PetscInt *closure = NULL; 1455 PetscInt clSize, cl, bval, fval; 1456 1457 PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 1458 PetscCall(DMLabelGetValue(bodyLabel, c, &bval)); 1459 PetscCall(DMLabelGetValue(faceLabel, c, &fval)); 1460 for (cl = 0; cl < clSize * 2; cl += 2) { 1461 PetscCall(DMLabelSetValue(bodyLabel, closure[cl], bval)); 1462 PetscCall(DMLabelSetValue(faceLabel, closure[cl], fval)); 1463 } 1464 PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 1465 } 1466 *newdm = dm; 1467 PetscFunctionReturn(0); 1468 } 1469 1470 PetscErrorCode DMPlexCreateGeom(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 1471 { 1472 // EGADS variables 1473 ego geom, *bodies, *mobjs, *fobjs, *lobjs, *eobjs, *nobjs; 1474 ego topRef, prev, next; 1475 int oclass, mtype, nbodies, *senses, *lSenses, *eSenses; 1476 int b; 1477 // PETSc variables 1478 DM dm; 1479 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 1480 PetscHMapI edgeMap = NULL, bodyIndexMap = NULL, bodyVertexMap = NULL, bodyEdgeMap = NULL, bodyFaceMap = NULL, bodyEdgeGlobalMap = NULL; 1481 PetscInt dim = -1, cdim = -1, numCorners = 0, numVertices = 0, numEdges = 0, numFaces = 0, numCells = 0, edgeCntr = 0; 1482 PetscInt cellCntr = 0, numPoints = 0; 1483 PetscInt *cells = NULL; 1484 const PetscInt *cone = NULL; 1485 PetscReal *coords = NULL; 1486 PetscMPIInt rank; 1487 1488 PetscFunctionBeginUser; 1489 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1490 if (rank == 0) { 1491 // --------------------------------------------------------------------------------------------------- 1492 // Generate Petsc Plex 1493 // Get all Nodes in model, record coordinates in a correctly formatted array 1494 // Cycle through bodies, cycle through loops, recorde NODE IDs in a correctly formatted array 1495 // We need to uniformly refine the initial geometry to guarantee a valid mesh 1496 1497 // Calculate cell and vertex sizes 1498 if (islite) { 1499 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 1500 } else { 1501 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 1502 } 1503 PetscCall(PetscHMapICreate(&edgeMap)); 1504 PetscCall(PetscHMapICreate(&bodyIndexMap)); 1505 PetscCall(PetscHMapICreate(&bodyVertexMap)); 1506 PetscCall(PetscHMapICreate(&bodyEdgeMap)); 1507 PetscCall(PetscHMapICreate(&bodyEdgeGlobalMap)); 1508 PetscCall(PetscHMapICreate(&bodyFaceMap)); 1509 1510 for (b = 0; b < nbodies; ++b) { 1511 ego body = bodies[b]; 1512 int Nf, Ne, Nv; 1513 PetscHashIter BIiter, BViter, BEiter, BEGiter, BFiter, EMiter; 1514 PetscBool BIfound, BVfound, BEfound, BEGfound, BFfound, EMfound; 1515 1516 PetscCall(PetscHMapIFind(bodyIndexMap, b, &BIiter, &BIfound)); 1517 PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 1518 PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 1519 PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 1520 PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 1521 1522 if (!BIfound) PetscCall(PetscHMapISet(bodyIndexMap, b, numFaces + numEdges + numVertices)); 1523 if (!BVfound) PetscCall(PetscHMapISet(bodyVertexMap, b, numVertices)); 1524 if (!BEfound) PetscCall(PetscHMapISet(bodyEdgeMap, b, numEdges)); 1525 if (!BEGfound) PetscCall(PetscHMapISet(bodyEdgeGlobalMap, b, edgeCntr)); 1526 if (!BFfound) PetscCall(PetscHMapISet(bodyFaceMap, b, numFaces)); 1527 1528 if (islite) { 1529 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1530 PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1531 PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1532 EGlite_free(fobjs); 1533 EGlite_free(eobjs); 1534 EGlite_free(nobjs); 1535 } else { 1536 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1537 PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1538 PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1539 EG_free(fobjs); 1540 EG_free(eobjs); 1541 EG_free(nobjs); 1542 } 1543 1544 // Remove DEGENERATE EDGES from Edge count 1545 if (islite) { 1546 PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1547 } else { 1548 PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1549 } 1550 1551 int Netemp = 0; 1552 for (int e = 0; e < Ne; ++e) { 1553 ego edge = eobjs[e]; 1554 int eid; 1555 1556 if (islite) { 1557 PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1558 eid = EGlite_indexBodyTopo(body, edge); 1559 } else { 1560 PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1561 eid = EG_indexBodyTopo(body, edge); 1562 } 1563 1564 PetscCall(PetscHMapIFind(edgeMap, edgeCntr + eid - 1, &EMiter, &EMfound)); 1565 if (mtype == DEGENERATE) { 1566 if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, -1)); 1567 } else { 1568 ++Netemp; 1569 if (!EMfound) PetscCall(PetscHMapISet(edgeMap, edgeCntr + eid - 1, Netemp)); 1570 } 1571 } 1572 if (islite) { 1573 EGlite_free(eobjs); 1574 } else { 1575 EG_free(eobjs); 1576 } 1577 1578 // Determine Number of Cells 1579 if (islite) { 1580 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1581 } else { 1582 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1583 } 1584 1585 for (int f = 0; f < Nf; ++f) { 1586 ego face = fobjs[f]; 1587 int edgeTemp = 0; 1588 1589 if (islite) { 1590 PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 1591 } else { 1592 PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 1593 } 1594 1595 for (int e = 0; e < Ne; ++e) { 1596 ego edge = eobjs[e]; 1597 1598 if (islite) { 1599 PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1600 } else { 1601 PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1602 } 1603 if (mtype != DEGENERATE) ++edgeTemp; 1604 } 1605 numCells += (2 * edgeTemp); 1606 if (islite) { 1607 EGlite_free(eobjs); 1608 } else { 1609 EG_free(eobjs); 1610 } 1611 } 1612 if (islite) { 1613 EGlite_free(fobjs); 1614 } else { 1615 EG_free(fobjs); 1616 } 1617 1618 numFaces += Nf; 1619 numEdges += Netemp; 1620 numVertices += Nv; 1621 edgeCntr += Ne; 1622 } 1623 1624 // Set up basic DMPlex parameters 1625 dim = 2; // Assumes 3D Models :: Need to handle 2D models in the future 1626 cdim = 3; // Assumes 3D Models :: Need to update to handle 2D models in future 1627 numCorners = 3; // Split Faces into triangles 1628 numPoints = numVertices + numEdges + numFaces; // total number of coordinate points 1629 1630 PetscCall(PetscMalloc2(numPoints * cdim, &coords, numCells * numCorners, &cells)); 1631 1632 // Get Vertex Coordinates and Set up Cells 1633 for (b = 0; b < nbodies; ++b) { 1634 ego body = bodies[b]; 1635 int Nf, Ne, Nv; 1636 PetscInt bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart; 1637 PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter; 1638 PetscBool BVfound, BEfound, BEGfound, BFfound, EMfound; 1639 1640 // Vertices on Current Body 1641 if (islite) { 1642 PetscCall(EGlite_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1643 } else { 1644 PetscCall(EG_getBodyTopos(body, NULL, NODE, &Nv, &nobjs)); 1645 } 1646 1647 PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 1648 PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyVertexMap", b); 1649 PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart)); 1650 1651 for (int v = 0; v < Nv; ++v) { 1652 ego vertex = nobjs[v]; 1653 double limits[4]; 1654 int id, dummy; 1655 1656 if (islite) { 1657 PetscCall(EGlite_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 1658 id = EGlite_indexBodyTopo(body, vertex); 1659 } else { 1660 PetscCall(EG_getTopology(vertex, &geom, &oclass, &mtype, limits, &dummy, &mobjs, &senses)); 1661 id = EG_indexBodyTopo(body, vertex); 1662 } 1663 1664 coords[(bodyVertexIndexStart + id - 1) * cdim + 0] = limits[0]; 1665 coords[(bodyVertexIndexStart + id - 1) * cdim + 1] = limits[1]; 1666 coords[(bodyVertexIndexStart + id - 1) * cdim + 2] = limits[2]; 1667 } 1668 if (islite) { 1669 EGlite_free(nobjs); 1670 } else { 1671 EG_free(nobjs); 1672 } 1673 1674 // Edge Midpoint Vertices on Current Body 1675 if (islite) { 1676 PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1677 } else { 1678 PetscCall(EG_getBodyTopos(body, NULL, EDGE, &Ne, &eobjs)); 1679 } 1680 1681 PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 1682 PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyEdgeMap", b); 1683 PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart)); 1684 1685 PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 1686 PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in bodyEdgeGlobalMap", b); 1687 PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart)); 1688 1689 for (int e = 0; e < Ne; ++e) { 1690 ego edge = eobjs[e]; 1691 double range[2], avgt[1], cntrPnt[9]; 1692 int eid, eOffset; 1693 int periodic; 1694 1695 if (islite) { 1696 PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1697 } else { 1698 PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1699 } 1700 if (mtype == DEGENERATE) continue; 1701 1702 if (islite) { 1703 eid = EGlite_indexBodyTopo(body, edge); 1704 } else { 1705 eid = EG_indexBodyTopo(body, edge); 1706 } 1707 // get relative offset from globalEdgeID Vector 1708 PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 1709 PetscCheck(EMfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Edge %" PetscInt_FMT " not found in edgeMap", bodyEdgeGlobalIndexStart + eid - 1); 1710 PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 1711 1712 if (islite) { 1713 PetscCall(EGlite_getRange(edge, range, &periodic)); 1714 } else { 1715 PetscCall(EG_getRange(edge, range, &periodic)); 1716 } 1717 avgt[0] = (range[0] + range[1]) / 2.; 1718 1719 if (islite) { 1720 PetscCall(EGlite_evaluate(edge, avgt, cntrPnt)); 1721 } else { 1722 PetscCall(EG_evaluate(edge, avgt, cntrPnt)); 1723 } 1724 coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 0] = cntrPnt[0]; 1725 coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 1] = cntrPnt[1]; 1726 coords[(numVertices + bodyEdgeIndexStart + eOffset - 1) * cdim + 2] = cntrPnt[2]; 1727 } 1728 if (islite) { 1729 EGlite_free(eobjs); 1730 } else { 1731 EG_free(eobjs); 1732 } 1733 // Face Midpoint Vertices on Current Body 1734 if (islite) { 1735 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1736 } else { 1737 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1738 } 1739 PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 1740 PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b); 1741 PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart)); 1742 1743 for (int f = 0; f < Nf; ++f) { 1744 ego face = fobjs[f]; 1745 double range[4], avgUV[2], cntrPnt[18]; 1746 int peri, id; 1747 1748 if (islite) { 1749 id = EGlite_indexBodyTopo(body, face); 1750 PetscCall(EGlite_getRange(face, range, &peri)); 1751 } else { 1752 id = EG_indexBodyTopo(body, face); 1753 PetscCall(EG_getRange(face, range, &peri)); 1754 } 1755 1756 avgUV[0] = (range[0] + range[1]) / 2.; 1757 avgUV[1] = (range[2] + range[3]) / 2.; 1758 1759 if (islite) { 1760 PetscCall(EGlite_evaluate(face, avgUV, cntrPnt)); 1761 } else { 1762 PetscCall(EG_evaluate(face, avgUV, cntrPnt)); 1763 } 1764 1765 coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 0] = cntrPnt[0]; 1766 coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 1] = cntrPnt[1]; 1767 coords[(numVertices + numEdges + bodyFaceIndexStart + id - 1) * cdim + 2] = cntrPnt[2]; 1768 } 1769 if (islite) { 1770 EGlite_free(fobjs); 1771 } else { 1772 EG_free(fobjs); 1773 } 1774 1775 // Define Cells :: Note - This could be incorporated in the Face Midpoint Vertices Loop but was kept separate for clarity 1776 if (islite) { 1777 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1778 } else { 1779 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1780 } 1781 for (int f = 0; f < Nf; ++f) { 1782 ego face = fobjs[f]; 1783 int fID, midFaceID, midPntID, startID, endID, Nl; 1784 1785 if (islite) { 1786 fID = EGlite_indexBodyTopo(body, face); 1787 } else { 1788 fID = EG_indexBodyTopo(body, face); 1789 } 1790 1791 midFaceID = numVertices + numEdges + bodyFaceIndexStart + fID - 1; 1792 // Must Traverse Loop to ensure we have all necessary information like the sense (+/- 1) of the edges. 1793 // TODO :: Only handles single loop faces (No holes). The choices for handling multiloop faces are: 1794 // 1) Use the DMPlexCreateGeomFromFile() with the -dm_plex_geom_with_tess = 1 option. 1795 // This will use a default EGADS tessellation as an initial surface mesh. 1796 // 2) Create the initial surface mesh via a 2D mesher :: Currently not available (?future?) 1797 // May I suggest the XXXX as a starting point? 1798 1799 if (islite) { 1800 PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses)); 1801 } else { 1802 PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lSenses)); 1803 } 1804 1805 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); 1806 for (int l = 0; l < Nl; ++l) { 1807 ego loop = lobjs[l]; 1808 1809 if (islite) { 1810 PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1811 } else { 1812 PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1813 } 1814 1815 for (int e = 0; e < Ne; ++e) { 1816 ego edge = eobjs[e]; 1817 int eid, eOffset; 1818 1819 if (islite) { 1820 PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1821 eid = EGlite_indexBodyTopo(body, edge); 1822 } else { 1823 PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1824 eid = EG_indexBodyTopo(body, edge); 1825 } 1826 if (mtype == DEGENERATE) continue; 1827 1828 // get relative offset from globalEdgeID Vector 1829 PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 1830 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); 1831 PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 1832 1833 midPntID = numVertices + bodyEdgeIndexStart + eOffset - 1; 1834 1835 if (islite) { 1836 PetscCall(EGlite_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1837 } else { 1838 PetscCall(EG_getTopology(edge, &geom, &oclass, &mtype, NULL, &Nv, &nobjs, &senses)); 1839 } 1840 1841 if (eSenses[e] > 0) { 1842 if (islite) { 1843 startID = EGlite_indexBodyTopo(body, nobjs[0]); 1844 endID = EGlite_indexBodyTopo(body, nobjs[1]); 1845 } else { 1846 startID = EG_indexBodyTopo(body, nobjs[0]); 1847 endID = EG_indexBodyTopo(body, nobjs[1]); 1848 } 1849 } else { 1850 if (islite) { 1851 startID = EGlite_indexBodyTopo(body, nobjs[1]); 1852 endID = EGlite_indexBodyTopo(body, nobjs[0]); 1853 } else { 1854 startID = EG_indexBodyTopo(body, nobjs[1]); 1855 endID = EG_indexBodyTopo(body, nobjs[0]); 1856 } 1857 } 1858 1859 // Define 2 Cells per Edge with correct orientation 1860 cells[cellCntr * numCorners + 0] = midFaceID; 1861 cells[cellCntr * numCorners + 1] = bodyVertexIndexStart + startID - 1; 1862 cells[cellCntr * numCorners + 2] = midPntID; 1863 1864 cells[cellCntr * numCorners + 3] = midFaceID; 1865 cells[cellCntr * numCorners + 4] = midPntID; 1866 cells[cellCntr * numCorners + 5] = bodyVertexIndexStart + endID - 1; 1867 1868 cellCntr = cellCntr + 2; 1869 } 1870 } 1871 } 1872 if (islite) { 1873 EGlite_free(fobjs); 1874 } else { 1875 EG_free(fobjs); 1876 } 1877 } 1878 } 1879 1880 // Generate DMPlex 1881 PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, numCells, numPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 1882 PetscCall(PetscFree2(coords, cells)); 1883 PetscCall(PetscInfo(dm, " Total Number of Unique Cells = %" PetscInt_FMT " \n", numCells)); 1884 PetscCall(PetscInfo(dm, " Total Number of Unique Vertices = %" PetscInt_FMT " \n", numVertices)); 1885 1886 // Embed EGADS model in DM 1887 { 1888 PetscContainer modelObj, contextObj; 1889 1890 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 1891 PetscCall(PetscContainerSetPointer(modelObj, model)); 1892 if (islite) { 1893 PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSliteDestroy_Private)); 1894 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Model", (PetscObject)modelObj)); 1895 } else { 1896 PetscCall(PetscContainerSetCtxDestroy(modelObj, DMPlexEGADSDestroy_Private)); 1897 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 1898 } 1899 PetscCall(PetscContainerDestroy(&modelObj)); 1900 1901 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 1902 PetscCall(PetscContainerSetPointer(contextObj, context)); 1903 1904 if (islite) { 1905 PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSliteClose_Private)); 1906 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Context", (PetscObject)contextObj)); 1907 } else { 1908 PetscCall(PetscContainerSetCtxDestroy(contextObj, DMPlexEGADSClose_Private)); 1909 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 1910 } 1911 PetscCall(PetscContainerDestroy(&contextObj)); 1912 } 1913 // Label points 1914 PetscInt nStart, nEnd; 1915 1916 PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 1917 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 1918 PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 1919 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 1920 PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 1921 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 1922 PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 1923 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 1924 1925 PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd)); 1926 1927 cellCntr = 0; 1928 for (b = 0; b < nbodies; ++b) { 1929 ego body = bodies[b]; 1930 int Nv, Ne, Nf; 1931 PetscInt bodyVertexIndexStart, bodyEdgeIndexStart, bodyEdgeGlobalIndexStart, bodyFaceIndexStart; 1932 PetscHashIter BViter, BEiter, BEGiter, BFiter, EMiter; 1933 PetscBool BVfound, BEfound, BEGfound, BFfound, EMfound; 1934 1935 PetscCall(PetscHMapIFind(bodyVertexMap, b, &BViter, &BVfound)); 1936 PetscCheck(BVfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyVertexMap", b); 1937 PetscCall(PetscHMapIGet(bodyVertexMap, b, &bodyVertexIndexStart)); 1938 1939 PetscCall(PetscHMapIFind(bodyEdgeMap, b, &BEiter, &BEfound)); 1940 PetscCheck(BEfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeMap", b); 1941 PetscCall(PetscHMapIGet(bodyEdgeMap, b, &bodyEdgeIndexStart)); 1942 1943 PetscCall(PetscHMapIFind(bodyFaceMap, b, &BFiter, &BFfound)); 1944 PetscCheck(BFfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyFaceMap", b); 1945 PetscCall(PetscHMapIGet(bodyFaceMap, b, &bodyFaceIndexStart)); 1946 1947 PetscCall(PetscHMapIFind(bodyEdgeGlobalMap, b, &BEGiter, &BEGfound)); 1948 PetscCheck(BEGfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %d not found in bodyEdgeGlobalMap", b); 1949 PetscCall(PetscHMapIGet(bodyEdgeGlobalMap, b, &bodyEdgeGlobalIndexStart)); 1950 1951 if (islite) { 1952 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1953 } else { 1954 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 1955 } 1956 1957 for (int f = 0; f < Nf; ++f) { 1958 ego face = fobjs[f]; 1959 int fID, Nl; 1960 1961 if (islite) { 1962 fID = EGlite_indexBodyTopo(body, face); 1963 PetscCall(EGlite_getBodyTopos(body, face, LOOP, &Nl, &lobjs)); 1964 } else { 1965 fID = EG_indexBodyTopo(body, face); 1966 PetscCall(EG_getBodyTopos(body, face, LOOP, &Nl, &lobjs)); 1967 } 1968 1969 for (int l = 0; l < Nl; ++l) { 1970 ego loop = lobjs[l]; 1971 int lid; 1972 1973 if (islite) { 1974 lid = EGlite_indexBodyTopo(body, loop); 1975 } else { 1976 lid = EG_indexBodyTopo(body, loop); 1977 } 1978 1979 PetscCheck(Nl == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Loop %" PetscInt_FMT " has %" PetscInt_FMT " > 1 faces, which is not supported", lid, Nf); 1980 1981 if (islite) { 1982 PetscCall(EGlite_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1983 } else { 1984 PetscCall(EG_getTopology(loop, &geom, &oclass, &mtype, NULL, &Ne, &eobjs, &eSenses)); 1985 } 1986 1987 for (int e = 0; e < Ne; ++e) { 1988 ego edge = eobjs[e]; 1989 int eid, eOffset; 1990 1991 // Skip DEGENERATE Edges 1992 if (islite) { 1993 PetscCall(EGlite_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1994 } else { 1995 PetscCall(EG_getInfo(edge, &oclass, &mtype, &topRef, &prev, &next)); 1996 } 1997 1998 if (mtype == DEGENERATE) { continue; } 1999 2000 if (islite) { 2001 eid = EGlite_indexBodyTopo(body, edge); 2002 } else { 2003 eid = EG_indexBodyTopo(body, edge); 2004 } 2005 2006 // get relative offset from globalEdgeID Vector 2007 PetscCall(PetscHMapIFind(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &EMiter, &EMfound)); 2008 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); 2009 PetscCall(PetscHMapIGet(edgeMap, bodyEdgeGlobalIndexStart + eid - 1, &eOffset)); 2010 2011 if (islite) { 2012 PetscCall(EGlite_getBodyTopos(body, edge, NODE, &Nv, &nobjs)); 2013 } else { 2014 PetscCall(EG_getBodyTopos(body, edge, NODE, &Nv, &nobjs)); 2015 } 2016 2017 for (int v = 0; v < Nv; ++v) { 2018 ego vertex = nobjs[v]; 2019 int vID; 2020 2021 if (islite) { 2022 vID = EGlite_indexBodyTopo(body, vertex); 2023 } else { 2024 vID = EG_indexBodyTopo(body, vertex); 2025 } 2026 2027 PetscCall(DMLabelSetValue(bodyLabel, nStart + bodyVertexIndexStart + vID - 1, b)); 2028 PetscCall(DMLabelSetValue(vertexLabel, nStart + bodyVertexIndexStart + vID - 1, vID)); 2029 } 2030 if (islite) { 2031 EGlite_free(nobjs); 2032 } else { 2033 EG_free(nobjs); 2034 } 2035 2036 PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, b)); 2037 PetscCall(DMLabelSetValue(edgeLabel, nStart + numVertices + bodyEdgeIndexStart + eOffset - 1, eid)); 2038 2039 // Define Cell faces 2040 for (int jj = 0; jj < 2; ++jj) { 2041 PetscCall(DMLabelSetValue(bodyLabel, cellCntr, b)); 2042 PetscCall(DMLabelSetValue(faceLabel, cellCntr, fID)); 2043 PetscCall(DMPlexGetCone(dm, cellCntr, &cone)); 2044 2045 PetscCall(DMLabelSetValue(bodyLabel, cone[0], b)); 2046 PetscCall(DMLabelSetValue(faceLabel, cone[0], fID)); 2047 2048 PetscCall(DMLabelSetValue(bodyLabel, cone[1], b)); 2049 PetscCall(DMLabelSetValue(edgeLabel, cone[1], eid)); 2050 2051 PetscCall(DMLabelSetValue(bodyLabel, cone[2], b)); 2052 PetscCall(DMLabelSetValue(faceLabel, cone[2], fID)); 2053 2054 cellCntr = cellCntr + 1; 2055 } 2056 } 2057 } 2058 if (islite) { 2059 EGlite_free(lobjs); 2060 } else { 2061 EG_free(lobjs); 2062 } 2063 2064 PetscCall(DMLabelSetValue(bodyLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, b)); 2065 PetscCall(DMLabelSetValue(faceLabel, nStart + numVertices + numEdges + bodyFaceIndexStart + fID - 1, fID)); 2066 } 2067 if (islite) { 2068 EGlite_free(fobjs); 2069 } else { 2070 EG_free(fobjs); 2071 } 2072 } 2073 2074 PetscCall(PetscHMapIDestroy(&edgeMap)); 2075 PetscCall(PetscHMapIDestroy(&bodyIndexMap)); 2076 PetscCall(PetscHMapIDestroy(&bodyVertexMap)); 2077 PetscCall(PetscHMapIDestroy(&bodyEdgeMap)); 2078 PetscCall(PetscHMapIDestroy(&bodyEdgeGlobalMap)); 2079 PetscCall(PetscHMapIDestroy(&bodyFaceMap)); 2080 2081 *newdm = dm; 2082 PetscFunctionReturn(PETSC_SUCCESS); 2083 } 2084 2085 PetscErrorCode DMPlexCreateGeom_Tess_Internal(MPI_Comm comm, ego context, ego model, DM *newdm, PetscBool islite) 2086 { 2087 /* EGADSlite variables */ 2088 ego geom, *bodies, *fobjs; 2089 int b, oclass, mtype, nbodies, *senses; 2090 int totalNumTris = 0, totalNumPoints = 0; 2091 double boundBox[6] = {0., 0., 0., 0., 0., 0.}, tessSize; 2092 /* PETSc variables */ 2093 DM dm; 2094 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 2095 PetscHMapI pointIndexStartMap = NULL, triIndexStartMap = NULL, pTypeLabelMap = NULL, pIndexLabelMap = NULL; 2096 PetscHMapI pBodyIndexLabelMap = NULL, triFaceIDLabelMap = NULL, triBodyIDLabelMap = NULL; 2097 PetscInt dim = -1, cdim = -1, numCorners = 0, counter = 0; 2098 PetscInt *cells = NULL; 2099 const PetscInt *cone = NULL; 2100 PetscReal *coords = NULL; 2101 PetscMPIInt rank; 2102 2103 PetscFunctionBeginUser; 2104 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2105 if (rank == 0) { 2106 // --------------------------------------------------------------------------------------------------- 2107 // Generate Petsc Plex from EGADSlite created Tessellation of geometry 2108 // --------------------------------------------------------------------------------------------------- 2109 2110 // Calculate cell and vertex sizes 2111 if (islite) { 2112 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 2113 } else { 2114 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &nbodies, &bodies, &senses)); 2115 } 2116 2117 PetscCall(PetscHMapICreate(&pointIndexStartMap)); 2118 PetscCall(PetscHMapICreate(&triIndexStartMap)); 2119 PetscCall(PetscHMapICreate(&pTypeLabelMap)); 2120 PetscCall(PetscHMapICreate(&pIndexLabelMap)); 2121 PetscCall(PetscHMapICreate(&pBodyIndexLabelMap)); 2122 PetscCall(PetscHMapICreate(&triFaceIDLabelMap)); 2123 PetscCall(PetscHMapICreate(&triBodyIDLabelMap)); 2124 2125 /* Create Tessellation of Bodies */ 2126 ego *tessArray; 2127 2128 PetscCall(PetscMalloc1(nbodies, &tessArray)); 2129 for (b = 0; b < nbodies; ++b) { 2130 ego body = bodies[b]; 2131 double params[3] = {0.0, 0.0, 0.0}; // Parameters for Tessellation 2132 int Nf, bodyNumPoints = 0, bodyNumTris = 0; 2133 PetscHashIter PISiter, TISiter; 2134 PetscBool PISfound, TISfound; 2135 2136 /* Store Start Index for each Body's Point and Tris */ 2137 PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound)); 2138 PetscCall(PetscHMapIFind(triIndexStartMap, b, &TISiter, &TISfound)); 2139 2140 if (!PISfound) PetscCall(PetscHMapISet(pointIndexStartMap, b, totalNumPoints)); 2141 if (!TISfound) PetscCall(PetscHMapISet(triIndexStartMap, b, totalNumTris)); 2142 2143 /* Calculate Tessellation parameters based on Bounding Box */ 2144 /* Get Bounding Box Dimensions of the BODY */ 2145 if (islite) { 2146 PetscCall(EGlite_getBoundingBox(body, boundBox)); 2147 } else { 2148 PetscCall(EG_getBoundingBox(body, boundBox)); 2149 } 2150 2151 tessSize = boundBox[3] - boundBox[0]; 2152 if (tessSize < boundBox[4] - boundBox[1]) tessSize = boundBox[4] - boundBox[1]; 2153 if (tessSize < boundBox[5] - boundBox[2]) tessSize = boundBox[5] - boundBox[2]; 2154 2155 // TODO :: May want to give users tessellation parameter options // 2156 params[0] = 0.0250 * tessSize; 2157 params[1] = 0.0075 * tessSize; 2158 params[2] = 15.0; 2159 2160 if (islite) { 2161 PetscCall(EGlite_makeTessBody(body, params, &tessArray[b])); 2162 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2163 } else { 2164 PetscCall(EG_makeTessBody(body, params, &tessArray[b])); 2165 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2166 } 2167 2168 for (int f = 0; f < Nf; ++f) { 2169 ego face = fobjs[f]; 2170 int len, fID, ntris; 2171 const int *ptype, *pindex, *ptris, *ptric; 2172 const double *pxyz, *puv; 2173 2174 // Get Face ID // 2175 if (islite) { 2176 fID = EGlite_indexBodyTopo(body, face); 2177 } else { 2178 fID = EG_indexBodyTopo(body, face); 2179 } 2180 2181 // Checkout the Surface Tessellation // 2182 if (islite) { 2183 PetscCall(EGlite_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 2184 } else { 2185 PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 2186 } 2187 2188 // Determine total number of triangle cells in the tessellation // 2189 bodyNumTris += (int)ntris; 2190 2191 // Check out the point index and coordinate // 2192 for (int p = 0; p < len; ++p) { 2193 int global; 2194 2195 if (islite) { 2196 PetscCall(EGlite_localToGlobal(tessArray[b], fID, p + 1, &global)); 2197 } else { 2198 PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global)); 2199 } 2200 2201 // Determine the total number of points in the tessellation // 2202 bodyNumPoints = PetscMax(bodyNumPoints, global); 2203 } 2204 } 2205 if (islite) { 2206 EGlite_free(fobjs); 2207 } else { 2208 EG_free(fobjs); 2209 } 2210 2211 totalNumPoints += bodyNumPoints; 2212 totalNumTris += bodyNumTris; 2213 } 2214 2215 dim = 2; 2216 cdim = 3; 2217 numCorners = 3; 2218 2219 /* NEED TO DEFINE MATRICES/VECTORS TO STORE GEOM REFERENCE DATA */ 2220 /* Fill in below and use to define DMLabels after DMPlex creation */ 2221 PetscCall(PetscMalloc2(totalNumPoints * cdim, &coords, totalNumTris * numCorners, &cells)); 2222 2223 for (b = 0; b < nbodies; ++b) { 2224 ego body = bodies[b]; 2225 int Nf; 2226 PetscInt pointIndexStart; 2227 PetscHashIter PISiter; 2228 PetscBool PISfound; 2229 2230 PetscCall(PetscHMapIFind(pointIndexStartMap, b, &PISiter, &PISfound)); 2231 PetscCheck(PISfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "Body %" PetscInt_FMT " not found in pointIndexStartMap", b); 2232 PetscCall(PetscHMapIGet(pointIndexStartMap, b, &pointIndexStart)); 2233 2234 if (islite) { 2235 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2236 } else { 2237 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2238 } 2239 2240 for (int f = 0; f < Nf; ++f) { 2241 /* Get Face Object */ 2242 ego face = fobjs[f]; 2243 int len, fID, ntris; 2244 const int *ptype, *pindex, *ptris, *ptric; 2245 const double *pxyz, *puv; 2246 2247 /* Get Face ID */ 2248 if (islite) { 2249 fID = EGlite_indexBodyTopo(body, face); 2250 } else { 2251 fID = EG_indexBodyTopo(body, face); 2252 } 2253 2254 /* Checkout the Surface Tessellation */ 2255 if (islite) { 2256 PetscCall(EGlite_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 2257 } else { 2258 PetscCall(EG_getTessFace(tessArray[b], fID, &len, &pxyz, &puv, &ptype, &pindex, &ntris, &ptris, &ptric)); 2259 } 2260 2261 /* Check out the point index and coordinate */ 2262 for (int p = 0; p < len; ++p) { 2263 int global; 2264 PetscHashIter PTLiter, PILiter, PBLiter; 2265 PetscBool PTLfound, PILfound, PBLfound; 2266 2267 if (islite) { 2268 PetscCall(EGlite_localToGlobal(tessArray[b], fID, p + 1, &global)); 2269 } else { 2270 PetscCall(EG_localToGlobal(tessArray[b], fID, p + 1, &global)); 2271 } 2272 2273 /* Set the coordinates array for DAG */ 2274 coords[((global - 1 + pointIndexStart) * 3) + 0] = pxyz[(p * 3) + 0]; 2275 coords[((global - 1 + pointIndexStart) * 3) + 1] = pxyz[(p * 3) + 1]; 2276 coords[((global - 1 + pointIndexStart) * 3) + 2] = pxyz[(p * 3) + 2]; 2277 2278 /* Store Geometry Label Information for DMLabel assignment later */ 2279 PetscCall(PetscHMapIFind(pTypeLabelMap, global - 1 + pointIndexStart, &PTLiter, &PTLfound)); 2280 PetscCall(PetscHMapIFind(pIndexLabelMap, global - 1 + pointIndexStart, &PILiter, &PILfound)); 2281 PetscCall(PetscHMapIFind(pBodyIndexLabelMap, global - 1 + pointIndexStart, &PBLiter, &PBLfound)); 2282 2283 if (!PTLfound) PetscCall(PetscHMapISet(pTypeLabelMap, global - 1 + pointIndexStart, ptype[p])); 2284 if (!PILfound) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, pindex[p])); 2285 if (!PBLfound) PetscCall(PetscHMapISet(pBodyIndexLabelMap, global - 1 + pointIndexStart, b)); 2286 2287 if (ptype[p] < 0) PetscCall(PetscHMapISet(pIndexLabelMap, global - 1 + pointIndexStart, fID)); 2288 } 2289 2290 for (int t = 0; t < (int)ntris; ++t) { 2291 int global, globalA, globalB; 2292 PetscHashIter TFLiter, TBLiter; 2293 PetscBool TFLfound, TBLfound; 2294 2295 if (islite) { 2296 PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global)); 2297 } else { 2298 PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 0], &global)); 2299 } 2300 cells[(counter * 3) + 0] = global - 1 + pointIndexStart; 2301 2302 if (islite) { 2303 PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA)); 2304 } else { 2305 PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 1], &globalA)); 2306 } 2307 cells[(counter * 3) + 1] = globalA - 1 + pointIndexStart; 2308 2309 if (islite) { 2310 PetscCall(EGlite_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB)); 2311 } else { 2312 PetscCall(EG_localToGlobal(tessArray[b], fID, ptris[(t * 3) + 2], &globalB)); 2313 } 2314 cells[(counter * 3) + 2] = globalB - 1 + pointIndexStart; 2315 2316 PetscCall(PetscHMapIFind(triFaceIDLabelMap, counter, &TFLiter, &TFLfound)); 2317 PetscCall(PetscHMapIFind(triBodyIDLabelMap, counter, &TBLiter, &TBLfound)); 2318 2319 if (!TFLfound) PetscCall(PetscHMapISet(triFaceIDLabelMap, counter, fID)); 2320 if (!TBLfound) PetscCall(PetscHMapISet(triBodyIDLabelMap, counter, b)); 2321 2322 counter += 1; 2323 } 2324 } 2325 if (islite) { 2326 EGlite_free(fobjs); 2327 } else { 2328 EG_free(fobjs); 2329 } 2330 } 2331 PetscCall(PetscFree(tessArray)); 2332 } 2333 2334 //Build DMPlex 2335 PetscCall(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, dim, totalNumTris, totalNumPoints, numCorners, PETSC_TRUE, cells, cdim, coords, &dm)); 2336 PetscCall(PetscFree2(coords, cells)); 2337 2338 // Embed EGADS model in DM 2339 { 2340 PetscContainer modelObj, contextObj; 2341 2342 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &modelObj)); 2343 PetscCall(PetscContainerSetPointer(modelObj, model)); 2344 if (islite) { 2345 PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSliteDestroy_Private)); 2346 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Model", (PetscObject)modelObj)); 2347 } else { 2348 PetscCall(PetscContainerSetCtxDestroy(modelObj, (PetscCtxDestroyFn *)DMPlexEGADSDestroy_Private)); 2349 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Model", (PetscObject)modelObj)); 2350 } 2351 PetscCall(PetscContainerDestroy(&modelObj)); 2352 2353 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &contextObj)); 2354 PetscCall(PetscContainerSetPointer(contextObj, context)); 2355 2356 if (islite) { 2357 PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSliteClose_Private)); 2358 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADSlite Context", (PetscObject)contextObj)); 2359 } else { 2360 PetscCall(PetscContainerSetCtxDestroy(contextObj, (PetscCtxDestroyFn *)DMPlexEGADSClose_Private)); 2361 PetscCall(PetscObjectCompose((PetscObject)dm, "EGADS Context", (PetscObject)contextObj)); 2362 } 2363 PetscCall(PetscContainerDestroy(&contextObj)); 2364 } 2365 2366 // Label Points 2367 PetscCall(DMCreateLabel(dm, "EGADS Body ID")); 2368 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 2369 PetscCall(DMCreateLabel(dm, "EGADS Face ID")); 2370 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 2371 PetscCall(DMCreateLabel(dm, "EGADS Edge ID")); 2372 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 2373 PetscCall(DMCreateLabel(dm, "EGADS Vertex ID")); 2374 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 2375 2376 /* Get Number of DAG Nodes at each level */ 2377 int fStart, fEnd, eStart, eEnd, nStart, nEnd; 2378 2379 PetscCall(DMPlexGetHeightStratum(dm, 0, &fStart, &fEnd)); 2380 PetscCall(DMPlexGetHeightStratum(dm, 1, &eStart, &eEnd)); 2381 PetscCall(DMPlexGetHeightStratum(dm, 2, &nStart, &nEnd)); 2382 2383 /* Set DMLabels for NODES */ 2384 for (int n = nStart; n < nEnd; ++n) { 2385 int pTypeVal, pIndexVal, pBodyVal; 2386 PetscHashIter PTLiter, PILiter, PBLiter; 2387 PetscBool PTLfound, PILfound, PBLfound; 2388 2389 //Converted to Hash Tables 2390 PetscCall(PetscHMapIFind(pTypeLabelMap, n - nStart, &PTLiter, &PTLfound)); 2391 PetscCheck(PTLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pTypeLabelMap", n); 2392 PetscCall(PetscHMapIGet(pTypeLabelMap, n - nStart, &pTypeVal)); 2393 2394 PetscCall(PetscHMapIFind(pIndexLabelMap, n - nStart, &PILiter, &PILfound)); 2395 PetscCheck(PILfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pIndexLabelMap", n); 2396 PetscCall(PetscHMapIGet(pIndexLabelMap, n - nStart, &pIndexVal)); 2397 2398 PetscCall(PetscHMapIFind(pBodyIndexLabelMap, n - nStart, &PBLiter, &PBLfound)); 2399 PetscCheck(PBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in pBodyLabelMap", n); 2400 PetscCall(PetscHMapIGet(pBodyIndexLabelMap, n - nStart, &pBodyVal)); 2401 2402 PetscCall(DMLabelSetValue(bodyLabel, n, pBodyVal)); 2403 if (pTypeVal == 0) PetscCall(DMLabelSetValue(vertexLabel, n, pIndexVal)); 2404 if (pTypeVal > 0) PetscCall(DMLabelSetValue(edgeLabel, n, pIndexVal)); 2405 if (pTypeVal < 0) PetscCall(DMLabelSetValue(faceLabel, n, pIndexVal)); 2406 } 2407 2408 /* Set DMLabels for Edges - Based on the DMLabels of the EDGE's NODES */ 2409 for (int e = eStart; e < eEnd; ++e) { 2410 int bodyID_0, vertexID_0, vertexID_1, edgeID_0, edgeID_1, faceID_0, faceID_1; 2411 2412 PetscCall(DMPlexGetCone(dm, e, &cone)); 2413 PetscCall(DMLabelGetValue(bodyLabel, cone[0], &bodyID_0)); // Do I need to check the other end? 2414 PetscCall(DMLabelGetValue(vertexLabel, cone[0], &vertexID_0)); 2415 PetscCall(DMLabelGetValue(vertexLabel, cone[1], &vertexID_1)); 2416 PetscCall(DMLabelGetValue(edgeLabel, cone[0], &edgeID_0)); 2417 PetscCall(DMLabelGetValue(edgeLabel, cone[1], &edgeID_1)); 2418 PetscCall(DMLabelGetValue(faceLabel, cone[0], &faceID_0)); 2419 PetscCall(DMLabelGetValue(faceLabel, cone[1], &faceID_1)); 2420 2421 PetscCall(DMLabelSetValue(bodyLabel, e, bodyID_0)); 2422 2423 if (edgeID_0 == edgeID_1) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0)); 2424 else if (vertexID_0 > 0 && edgeID_1 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_1)); 2425 else if (vertexID_1 > 0 && edgeID_0 > 0) PetscCall(DMLabelSetValue(edgeLabel, e, edgeID_0)); 2426 else { /* Do Nothing */ } 2427 } 2428 2429 /* Set DMLabels for Cells */ 2430 for (int f = fStart; f < fEnd; ++f) { 2431 int edgeID_0; 2432 PetscInt triBodyVal, triFaceVal; 2433 PetscHashIter TFLiter, TBLiter; 2434 PetscBool TFLfound, TBLfound; 2435 2436 // Convert to Hash Table 2437 PetscCall(PetscHMapIFind(triFaceIDLabelMap, f - fStart, &TFLiter, &TFLfound)); 2438 PetscCheck(TFLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in triFaceIDLabelMap", f); 2439 PetscCall(PetscHMapIGet(triFaceIDLabelMap, f - fStart, &triFaceVal)); 2440 2441 PetscCall(PetscHMapIFind(triBodyIDLabelMap, f - fStart, &TBLiter, &TBLfound)); 2442 PetscCheck(TBLfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "DAG Point %" PetscInt_FMT " not found in triBodyIDLabelMap", f); 2443 PetscCall(PetscHMapIGet(triBodyIDLabelMap, f - fStart, &triBodyVal)); 2444 2445 PetscCall(DMLabelSetValue(bodyLabel, f, triBodyVal)); 2446 PetscCall(DMLabelSetValue(faceLabel, f, triFaceVal)); 2447 2448 /* Finish Labeling previously unlabeled DMPlex Edges - Assumes Triangular Cell (3 Edges Max) */ 2449 PetscCall(DMPlexGetCone(dm, f, &cone)); 2450 2451 for (int jj = 0; jj < 3; ++jj) { 2452 PetscCall(DMLabelGetValue(edgeLabel, cone[jj], &edgeID_0)); 2453 2454 if (edgeID_0 < 0) { 2455 PetscCall(DMLabelSetValue(bodyLabel, cone[jj], triBodyVal)); 2456 PetscCall(DMLabelSetValue(faceLabel, cone[jj], triFaceVal)); 2457 } 2458 } 2459 } 2460 2461 *newdm = dm; 2462 PetscFunctionReturn(PETSC_SUCCESS); 2463 } 2464 #endif 2465 2466 /*@C 2467 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. 2468 2469 Collective 2470 2471 Input Parameter: 2472 . dm - The uninflated `DM` object representing the mesh 2473 2474 Level: intermediate 2475 2476 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()` 2477 @*/ 2478 PetscErrorCode DMPlexInflateToGeomModelUseXYZ(DM dm) PeNS 2479 { 2480 // please don't fucking write code like this with #ifdef all of the place! 2481 #if defined(PETSC_HAVE_EGADS) 2482 /* EGADS Variables */ 2483 ego model, geom, body, face, edge, vertex; 2484 ego *bodies; 2485 int Nb, oclass, mtype, *senses; 2486 double result[4]; 2487 /* PETSc Variables */ 2488 DM cdm; 2489 PetscContainer modelObj; 2490 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 2491 Vec coordinates; 2492 PetscScalar *coords; 2493 PetscInt bodyID, faceID, edgeID, vertexID; 2494 PetscInt cdim, d, vStart, vEnd, v; 2495 PetscBool islite = PETSC_FALSE; 2496 #endif 2497 2498 PetscFunctionBegin; 2499 #if defined(PETSC_HAVE_EGADS) 2500 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 2501 if (!modelObj) { 2502 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 2503 islite = PETSC_TRUE; 2504 } 2505 if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 2506 PetscCall(DMGetCoordinateDim(dm, &cdim)); 2507 PetscCall(DMGetCoordinateDM(dm, &cdm)); 2508 PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2509 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 2510 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 2511 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 2512 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 2513 2514 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 2515 2516 if (islite) { 2517 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2518 } else { 2519 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2520 } 2521 2522 PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2523 PetscCall(VecGetArrayWrite(coordinates, &coords)); 2524 for (v = vStart; v < vEnd; ++v) { 2525 PetscScalar *vcoords; 2526 2527 PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 2528 PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 2529 PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 2530 PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 2531 2532 PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bodyID, Nb); 2533 body = bodies[bodyID]; 2534 2535 PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 2536 if (vertexID > 0) { 2537 if (islite) { 2538 PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 2539 PetscCall(EGlite_evaluate(vertex, NULL, result)); 2540 } else { 2541 PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 2542 PetscCall(EG_evaluate(vertex, NULL, result)); 2543 } 2544 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2545 } else if (edgeID > 0) { 2546 /* Snap to EDGE at nearest location */ 2547 double params[1]; 2548 if (islite) { 2549 PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 2550 PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 2551 } // Get (x,y,z) of nearest point on EDGE 2552 else { 2553 PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 2554 PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 2555 } 2556 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2557 } else if (faceID > 0) { 2558 /* Snap to FACE at nearest location */ 2559 double params[2]; 2560 if (islite) { 2561 PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 2562 PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 2563 } // Get (x,y,z) of nearest point on FACE 2564 else { 2565 PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 2566 PetscCall(EG_invEvaluate(face, vcoords, params, result)); 2567 } 2568 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2569 } 2570 } 2571 PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 2572 /* Clear out global coordinates */ 2573 PetscCall(VecDestroy(&dm->coordinates[0].x)); 2574 #endif 2575 PetscFunctionReturn(PETSC_SUCCESS); 2576 } 2577 2578 #if defined(PETSC_HAVE_EGADS) 2579 // This replaces the model in-place 2580 PetscErrorCode ConvertGeomModelToAllBSplines(PetscBool islite, ego *model) PeNS 2581 { 2582 /* EGADS/EGADSlite Variables */ 2583 ego context = NULL, geom, *bodies, *fobjs; 2584 int oclass, mtype; 2585 int *senses; 2586 int Nb, Nf; 2587 2588 PetscFunctionBegin; 2589 // Get the number of bodies and body objects in the model 2590 if (islite) PetscCallEGADS(EGlite_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2591 else PetscCallEGADS(EG_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2592 2593 // Get all Faces on the body <-- Only working with 1 body at the moment. 2594 ego body = bodies[0]; 2595 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 2596 else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 2597 ego newGeom[Nf]; 2598 ego newFaces[Nf]; 2599 2600 // Convert the 1st Face to a BSpline Geometry 2601 for (int ii = 0; ii < Nf; ++ii) { 2602 ego face = fobjs[ii]; 2603 ego gRef, gPrev, gNext, *lobjs; 2604 int goclass, gmtype, *gpinfo; 2605 int Nl, *lsenses; 2606 double *gprv; 2607 char *gClass = (char *)"", *gType = (char *)""; 2608 2609 /* Shape Optimization is NOT available for EGADSlite geometry files. */ 2610 /* Note :: islite options are left below in case future versions of EGADSlite includes this capability */ 2611 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"); 2612 2613 if (islite) { 2614 PetscCallEGADS(EGlite_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_ 2615 PetscCallEGADS(EGlite_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info 2616 PetscCallEGADS(EGlite_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 2617 } // Get geometry info 2618 else { 2619 PetscCallEGADS(EG_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_ 2620 PetscCallEGADS(EG_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info 2621 PetscCallEGADS(EG_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 2622 } // Get geometry info 2623 2624 PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType)); // Decode Geometry integers 2625 2626 // Convert current FACE to a BSpline Surface 2627 ego bspline; 2628 ego bRef, bPrev, bNext; 2629 int boclass, bmtype, *bpinfo; 2630 double *bprv; 2631 char *bClass = (char *)"", *bType = (char *)""; 2632 2633 PetscCallEGADS(EG_convertToBSpline, (face, &bspline)); // Does not have an EGlite_ version 2634 2635 if (islite) { 2636 PetscCallEGADS(EGlite_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info 2637 PetscCallEGADS(EGlite_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2638 } // Get geometry info 2639 else { 2640 PetscCallEGADS(EG_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info 2641 PetscCallEGADS(EG_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2642 } // Get geometry info 2643 2644 PetscCall(DMPlex_EGADS_GeomDecode_Internal(boclass, bmtype, &bClass, &bType)); // Decode Geometry integers 2645 2646 // Get Context from FACE 2647 context = NULL; 2648 PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version 2649 2650 // Silence WARNING Regarding OPENCASCADE 7.5 2651 if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 0)); 2652 else PetscCallEGADS(EG_setOutLevel, (context, 0)); 2653 2654 ego newgeom; 2655 PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version 2656 2657 PetscCallEGADS(EG_deleteObject, (bspline)); 2658 2659 // Create new FACE based on new SURFACE geometry 2660 double data[4]; 2661 int periodic; 2662 if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 2663 else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 2664 2665 ego newface; 2666 PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version 2667 //PetscCallEGADS(EG_deleteObject, (newgeom)); 2668 //PetscCallEGADS(EG_deleteObject, (newface)); 2669 newFaces[ii] = newface; 2670 newGeom[ii] = newgeom; 2671 2672 // Reinstate WARNING Regarding OPENCASCADE 7.5 2673 if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 1)); 2674 else PetscCallEGADS(EG_setOutLevel, (context, 1)); 2675 } 2676 2677 // Sew New Faces together to get a new model 2678 ego newmodel; 2679 PetscCallEGADS(EG_sewFaces, (Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version 2680 for (int ii = 0; ii < Nf; ++ii) { 2681 PetscCallEGADS(EG_deleteObject, (newFaces[ii])); 2682 PetscCallEGADS(EG_deleteObject, (newGeom[ii])); 2683 } 2684 PetscCallEGADS(EG_deleteObject, (*model)); 2685 *model = newmodel; 2686 PetscFunctionReturn(PETSC_SUCCESS); 2687 } 2688 #endif 2689 2690 /*@C 2691 DMPlexCreateGeomFromFile - Create a `DMPLEX` mesh from an EGADS, IGES, or STEP file. 2692 2693 Collective 2694 2695 Input Parameters: 2696 + comm - The MPI communicator 2697 . filename - The name of the EGADS, IGES, or STEP file 2698 - islite - Flag for EGADSlite support 2699 2700 Output Parameter: 2701 . dm - The `DM` object representing the mesh 2702 2703 Level: beginner 2704 2705 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`, `DMPlexCreateEGADSliteFromFile()` 2706 @*/ 2707 PetscErrorCode DMPlexCreateGeomFromFile(MPI_Comm comm, const char filename[], DM *dm, PetscBool islite) PeNS 2708 { 2709 /* PETSc Variables */ 2710 PetscMPIInt rank; 2711 PetscBool printModel = PETSC_FALSE, tessModel = PETSC_FALSE, newModel = PETSC_FALSE; 2712 PetscBool shapeOpt = PETSC_FALSE; 2713 2714 #if defined(PETSC_HAVE_EGADS) 2715 ego context = NULL, model = NULL; 2716 #endif 2717 2718 PetscFunctionBegin; 2719 PetscAssertPointer(filename, 2); 2720 PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_print_model", &printModel, NULL)); 2721 PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_tess_model", &tessModel, NULL)); 2722 PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_new_model", &newModel, NULL)); 2723 PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_shape_opt", &shapeOpt, NULL)); 2724 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2725 #if defined(PETSC_HAVE_EGADS) 2726 if (rank == 0) { 2727 /* EGADSlite files cannot be used for Shape Optimization Work. It lacks the ability to make new geometry. */ 2728 /* Must use EGADS, STEP, IGES or BRep files to perform this work. */ 2729 if (islite) { 2730 PetscCallEGADS(EGlite_open, (&context)); 2731 PetscCallEGADS(EGlite_loadModel, (context, 0, filename, &model)); 2732 if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model)); 2733 if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite)); 2734 } else { 2735 PetscCallEGADS(EG_open, (&context)); 2736 PetscCallEGADS(EG_loadModel, (context, 0, filename, &model)); 2737 if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model)); 2738 if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite)); 2739 } 2740 } 2741 if (tessModel) PetscCall(DMPlexCreateGeom_Tess_Internal(comm, context, model, dm, islite)); 2742 else if (newModel) PetscCall(DMPlexCreateGeom_Internal(comm, context, model, dm, islite)); 2743 else { 2744 PetscCall(DMPlexCreateGeom(comm, context, model, dm, islite)); 2745 } 2746 PetscFunctionReturn(PETSC_SUCCESS); 2747 #else 2748 SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 2749 #endif 2750 } 2751 2752 #if defined(PETSC_HAVE_EGADS) 2753 /*@C 2754 DMPlex_Surface_Grad - Exposes the Geometry's Control Points and Weights and Calculates the Mesh Topology Boundary Nodes Gradient 2755 with respect the associated geometry's Control Points and Weights. 2756 2757 // ----- Depreciated ---- See DMPlexGeomDataAndGrads ------ // 2758 2759 Collective 2760 2761 Input Parameters: 2762 . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 2763 2764 Output Parameter: 2765 . 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 2766 2767 Level: intermediate 2768 2769 .seealso: 2770 @*/ 2771 PetscErrorCode DMPlex_Surface_Grad(DM dm) 2772 { 2773 ego model, geom, *bodies, *fobjs; 2774 PetscContainer modelObj; 2775 int oclass, mtype, *senses; 2776 int Nb, Nf; 2777 PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 2778 PetscHMapI pointSurfGradRow_Start = NULL; 2779 Mat pointSurfGrad; 2780 IS faceLabelValues, edgeLabelValues, vertexLabelValues; 2781 PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 2782 PetscBool islite = PETSC_FALSE; 2783 2784 PetscFunctionBegin; 2785 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 2786 if (!modelObj) { 2787 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 2788 islite = PETSC_TRUE; 2789 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"); 2790 } 2791 2792 // Get attached EGADS model (pointer) 2793 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 2794 2795 // Get the bodies in the model 2796 if (islite) { 2797 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2798 } else { 2799 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2800 } 2801 2802 ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 2803 2804 // Get the total number of FACEs in the model 2805 if (islite) { 2806 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2807 } else { 2808 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2809 } 2810 2811 // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 2812 // This will provide the total number of DMPlex points on the boundary of the geometry 2813 PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 2814 PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 2815 2816 PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 2817 PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 2818 2819 PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 2820 PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 2821 2822 const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 2823 PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 2824 PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 2825 PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 2826 2827 // Get the points associated with each FACE, EDGE and VERTEX label in the DM 2828 PetscInt totalNumPoints = 0; 2829 for (int ii = 0; ii < faceLabelSize; ++ii) { 2830 // Cycle through FACE labels 2831 PetscInt size; 2832 PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[ii], &size)); 2833 totalNumPoints += size; 2834 } 2835 PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 2836 PetscCall(ISDestroy(&faceLabelValues)); 2837 2838 for (int ii = 0; ii < edgeLabelSize; ++ii) { 2839 // Cycle Through EDGE Labels 2840 PetscInt size; 2841 PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[ii], &size)); 2842 totalNumPoints += size; 2843 } 2844 PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 2845 PetscCall(ISDestroy(&edgeLabelValues)); 2846 2847 for (int ii = 0; ii < vertexLabelSize; ++ii) { 2848 // Cycle Through VERTEX Labels 2849 PetscInt size; 2850 PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 2851 totalNumPoints += size; 2852 } 2853 PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 2854 PetscCall(ISDestroy(&vertexLabelValues)); 2855 2856 int maxNumCPs = 0; 2857 int totalNumCPs = 0; 2858 ego bRef, bPrev, bNext, fgeom, *lobjs; 2859 int id, boclass, bmtype, *bpinfo; 2860 int foclass, fmtype, Nl, *lsenses; 2861 double *bprv; 2862 double fdata[4]; 2863 2864 // Create Hash Tables 2865 PetscInt cntr = 0, wcntr = 0; 2866 PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 2867 PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 2868 2869 for (int ii = 0; ii < Nf; ++ii) { 2870 // Need to get the maximum number of Control Points defining the FACEs 2871 ego face = fobjs[ii]; 2872 int maxNumCPs_temp; 2873 2874 if (islite) { 2875 id = EGlite_indexBodyTopo(body, face); 2876 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2877 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2878 PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2879 } else { 2880 id = EG_indexBodyTopo(body, face); 2881 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2882 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2883 PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2884 } 2885 2886 maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 2887 totalNumCPs += bpinfo[2] * bpinfo[5]; 2888 2889 if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 2890 } 2891 2892 PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 2893 PetscInt cpCoordDataLength = 3 * totalNumCPs; 2894 PetscInt wDataLength = totalNumCPs; 2895 cpCoordDataLengthPtr = &cpCoordDataLength; 2896 wDataLengthPtr = &wDataLength; 2897 PetscScalar *cntrlPtCoords, *cntrlPtWeights; 2898 PetscMalloc1(cpCoordDataLength, &cntrlPtCoords); 2899 PetscMalloc1(wDataLength, &cntrlPtWeights); 2900 for (int ii = 0; ii < Nf; ++ii) { 2901 // Need to Populate Control Point Coordinates and Weight Vectors 2902 ego face = fobjs[ii]; 2903 PetscHashIter hashKeyIter, wHashKeyIter; 2904 PetscBool hashKeyFound, wHashKeyFound; 2905 2906 if (islite) { 2907 id = EGlite_indexBodyTopo(body, face); 2908 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2909 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2910 PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2911 } else { 2912 id = EG_indexBodyTopo(body, face); 2913 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2914 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2915 PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2916 } 2917 2918 // Store Face ID to 1st Row of Control Point Vector 2919 PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 2920 2921 if (!hashKeyFound) { PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); } 2922 2923 int offsetCoord = bpinfo[3] + bpinfo[6]; 2924 for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 2925 cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 2926 cntr += 1; 2927 } 2928 2929 // Store Face ID to 1st Row of Control Point Weight Vector 2930 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 2931 2932 if (!wHashKeyFound) { PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); } 2933 2934 int offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 2935 for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 2936 cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 2937 wcntr += 1; 2938 } 2939 } 2940 2941 // Attach Control Point and Weight Data to DM 2942 { 2943 PetscContainer cpOrgObj, cpCoordObj, cpCoordLengthObj; 2944 PetscContainer wOrgObj, wValObj, wDataLengthObj; 2945 2946 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 2947 PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 2948 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 2949 PetscCall(PetscContainerDestroy(&cpOrgObj)); 2950 2951 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordObj)); 2952 PetscCall(PetscContainerSetPointer(cpCoordObj, cntrlPtCoords)); 2953 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cpCoordObj)); 2954 PetscCall(PetscContainerDestroy(&cpCoordObj)); 2955 2956 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 2957 PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 2958 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 2959 PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 2960 2961 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 2962 PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 2963 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 2964 PetscCall(PetscContainerDestroy(&wOrgObj)); 2965 2966 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wValObj)); 2967 PetscCall(PetscContainerSetPointer(wValObj, cntrlPtWeights)); 2968 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)wValObj)); 2969 PetscCall(PetscContainerDestroy(&wValObj)); 2970 2971 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 2972 PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 2973 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 2974 PetscCall(PetscContainerDestroy(&wDataLengthObj)); 2975 } 2976 2977 // Define Matrix to store Surface Gradient information dx_i/dCPj_i 2978 PetscInt gcntr = 0; 2979 const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 2980 const PetscInt colSize = 4 * Nf; 2981 2982 // Create Point Surface Gradient Matrix 2983 MatCreate(PETSC_COMM_WORLD, &pointSurfGrad); 2984 MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize); 2985 MatSetType(pointSurfGrad, MATAIJ); 2986 MatSetUp(pointSurfGrad); 2987 2988 // Create Hash Table to store Point's stare row in surfaceGrad[][] 2989 PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 2990 2991 // Get Coordinates for the DMPlex point 2992 DM cdm; 2993 PetscInt dE, Nv; 2994 Vec coordinatesLocal; 2995 PetscScalar *coords = NULL; 2996 PetscCall(DMGetCoordinateDM(dm, &cdm)); 2997 PetscCall(DMGetCoordinateDim(dm, &dE)); 2998 PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 2999 3000 // CYCLE THROUGH FACEs 3001 for (int ii = 0; ii < Nf; ++ii) { 3002 ego face = fobjs[ii]; 3003 ego *eobjs, *nobjs; 3004 PetscInt fid, Ne, Nn; 3005 DMLabel faceLabel, edgeLabel, nodeLabel; 3006 PetscHMapI currFaceUniquePoints = NULL; 3007 IS facePoints, edgePoints, nodePoints; 3008 const PetscInt *fIndices, *eIndices, *nIndices; 3009 PetscInt fSize, eSize, nSize; 3010 PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 3011 PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 3012 PetscInt cfCntr = 0; 3013 3014 // Get Geometry Object for the Current FACE 3015 if (islite) { 3016 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3017 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3018 } else { 3019 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3020 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3021 } 3022 3023 // Get all EDGE and NODE objects attached to the current FACE 3024 if (islite) { 3025 PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3026 PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3027 } else { 3028 PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3029 PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3030 } 3031 3032 // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 3033 if (islite) { 3034 fid = EGlite_indexBodyTopo(body, face); 3035 } else { 3036 fid = EG_indexBodyTopo(body, face); 3037 } 3038 3039 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 3040 PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 3041 PetscCall(ISGetIndices(facePoints, &fIndices)); 3042 PetscCall(ISGetSize(facePoints, &fSize)); 3043 3044 PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 3045 3046 for (int jj = 0; jj < fSize; ++jj) { 3047 PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 3048 3049 if (!fHashKeyFound) { 3050 PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 3051 cfCntr += 1; 3052 } 3053 3054 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 3055 3056 if (!pHashKeyFound) { 3057 PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 3058 gcntr += 3 * maxNumCPs; 3059 } 3060 } 3061 PetscCall(ISRestoreIndices(facePoints, &fIndices)); 3062 PetscCall(ISDestroy(&facePoints)); 3063 3064 // 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. 3065 for (int jj = 0; jj < Ne; ++jj) { 3066 ego edge = eobjs[jj]; 3067 PetscBool containLabelValue; 3068 3069 if (islite) { 3070 id = EGlite_indexBodyTopo(body, edge); 3071 } else { 3072 id = EG_indexBodyTopo(body, edge); 3073 } 3074 3075 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 3076 PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 3077 3078 if (containLabelValue) { 3079 PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 3080 PetscCall(ISGetIndices(edgePoints, &eIndices)); 3081 PetscCall(ISGetSize(edgePoints, &eSize)); 3082 3083 for (int kk = 0; kk < eSize; ++kk) { 3084 PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 3085 3086 if (!eHashKeyFound) { 3087 PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 3088 cfCntr += 1; 3089 } 3090 3091 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 3092 3093 if (!pHashKeyFound) { 3094 PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 3095 gcntr += 3 * maxNumCPs; 3096 } 3097 } 3098 PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 3099 PetscCall(ISDestroy(&edgePoints)); 3100 } 3101 } 3102 3103 // 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. 3104 for (int jj = 0; jj < Nn; ++jj) { 3105 ego node = nobjs[jj]; 3106 3107 if (islite) { 3108 id = EGlite_indexBodyTopo(body, node); 3109 } else { 3110 id = EG_indexBodyTopo(body, node); 3111 } 3112 3113 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 3114 PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 3115 PetscCall(ISGetIndices(nodePoints, &nIndices)); 3116 PetscCall(ISGetSize(nodePoints, &nSize)); 3117 3118 for (int kk = 0; kk < nSize; ++kk) { 3119 PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 3120 3121 if (!nHashKeyFound) { 3122 PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 3123 cfCntr += 1; 3124 } 3125 3126 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 3127 if (!pHashKeyFound) { 3128 PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 3129 gcntr += 3 * maxNumCPs; 3130 } 3131 } 3132 PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 3133 PetscCall(ISDestroy(&nodePoints)); 3134 } 3135 3136 // Get the Total Number of entries in the Hash Table 3137 PetscInt currFaceUPSize; 3138 PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 3139 3140 // Get Keys 3141 PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 3142 PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 3143 3144 // Cycle through all points on the current FACE 3145 for (int jj = 0; jj < currFaceUPSize; ++jj) { 3146 PetscInt currPointID = currFaceUPKeys[jj]; 3147 PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 3148 3149 // Get UV position of FACE 3150 double params[2], range[4], eval[18]; 3151 int peri; 3152 3153 if (islite) { 3154 PetscCall(EGlite_getRange(face, range, &peri)); 3155 } else { 3156 PetscCall(EG_getRange(face, range, &peri)); 3157 } 3158 3159 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 3160 3161 if (islite) { 3162 PetscCall(EGlite_evaluate(face, params, eval)); 3163 } else { 3164 PetscCall(EG_evaluate(face, params, eval)); 3165 } 3166 3167 // Make a new SURFACE Geometry by changing the location of the Control Points 3168 int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 3169 double nbprv[prvSize]; 3170 3171 // Cycle through each Control Point 3172 double deltaCoord = 1.0E-4; 3173 int offset = bpinfo[3] + bpinfo[6]; 3174 int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 3175 for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 3176 // Cycle through each direction (x, then y, then z) 3177 for (int kk = 0; kk < 4; ++kk) { 3178 // Reinitialize nbprv[] values because we only want to change one value at a time 3179 for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 3180 3181 if (kk == 0) { //X 3182 nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 3183 nbprv[offset + 1] = bprv[offset + 1]; 3184 nbprv[offset + 2] = bprv[offset + 2]; 3185 } else if (kk == 1) { //Y 3186 nbprv[offset + 0] = bprv[offset + 0]; 3187 nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 3188 nbprv[offset + 2] = bprv[offset + 2]; 3189 } else if (kk == 2) { //Z 3190 nbprv[offset + 0] = bprv[offset + 0]; 3191 nbprv[offset + 1] = bprv[offset + 1]; 3192 nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 3193 } else if (kk == 3) { // Weights 3194 nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 3195 } else { 3196 // currently do nothing 3197 } 3198 3199 // Create New Surface Based on New Control Points or Weights 3200 ego newgeom, context; 3201 if (islite) { 3202 PetscCall(EGlite_open(&context)); 3203 PetscCall(EGlite_setOutLevel(context, 0)); 3204 } else { 3205 PetscCall(EG_open(&context)); 3206 PetscCall(EG_setOutLevel(context, 0)); 3207 } 3208 3209 PetscCall(EG_makeGeometry(context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 3210 3211 if (islite) { 3212 PetscCall(EGlite_setOutLevel(context, 1)); 3213 } else { 3214 PetscCall(EG_setOutLevel(context, 1)); 3215 } 3216 3217 // Evaluate new (x, y, z) Point Position based on new Surface Definition 3218 double newCoords[18]; 3219 if (islite) { 3220 PetscCall(EGlite_getRange(newgeom, range, &peri)); 3221 } else { 3222 PetscCall(EG_getRange(newgeom, range, &peri)); 3223 } 3224 3225 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, newgeom, range, 0, dE, params, islite)); 3226 3227 if (islite) { 3228 PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 3229 } else { 3230 PetscCall(EG_evaluate(newgeom, params, newCoords)); 3231 } 3232 3233 // Now Calculate the Surface Gradient for the change in x-component Control Point 3234 PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 3235 PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 3236 PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 3237 3238 // Store Gradient Information in surfaceGrad[][] Matrix 3239 PetscInt startRow; 3240 PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 3241 3242 // Store Results in Petsc Matrix 3243 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 3244 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 3245 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 3246 } 3247 offset += 3; 3248 } 3249 PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 3250 } 3251 } 3252 3253 // Assemble Point Surface Grad Matrix 3254 MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY); 3255 MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY); 3256 3257 // Attach Surface Gradient Hash Table and Matrix to DM 3258 { 3259 PetscContainer surfGradOrgObj, surfGradObj; 3260 3261 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 3262 PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 3263 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 3264 PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 3265 3266 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradObj)); 3267 PetscCall(PetscContainerSetPointer(surfGradObj, pointSurfGrad)); 3268 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)surfGradObj)); 3269 PetscCall(PetscContainerDestroy(&surfGradObj)); 3270 } 3271 if (islite) EGlite_free(fobjs); 3272 else EG_free(fobjs); 3273 PetscFunctionReturn(PETSC_SUCCESS); 3274 } 3275 3276 static PetscErrorCode DestroyHashMap(void **p) 3277 { 3278 PetscFunctionBegin; 3279 PetscCall(PetscHMapIDestroy((PetscHMapI *)p)); 3280 PetscFunctionReturn(PETSC_SUCCESS); 3281 } 3282 #endif 3283 3284 /*@C 3285 DMPlexGeomDataAndGrads - Exposes Control Points and Control Point Weights defining the underlying geometry allowing user manipulation of the geometry. 3286 3287 Collective 3288 3289 Input Parameters: 3290 + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 3291 - fullGeomGrad - PetscBool flag. Determines how the Surface Area and Volume Gradients wrt to Control Points and Control Point Weights are calculated. 3292 PETSC_FALSE :: Surface Area Gradient wrt Control Points and Control Point Weights are calculated using the change in the local 3293 FACE changes (not the entire body). Volume Gradients are not calculated. Faster computations. 3294 PETSC_TRUE :: Surface Area Gradietn wrt to Control Points and Control Point Weights are calculated using the change observed in 3295 the entire solid body. Volume Gradients are calculated. Slower computation due to the need to generate a new solid 3296 body geometry for every Control Point and Control Point Weight change. 3297 3298 Output Parameter: 3299 . dm - The updated DM object representing the mesh with PetscContainers containing the Control Point, Control Point Weight and Gradient Data. 3300 3301 Level: intermediate 3302 3303 Note: 3304 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). 3305 3306 .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexModifyEGADSGeomModel()` 3307 @*/ 3308 PetscErrorCode DMPlexGeomDataAndGrads(DM dm, PetscBool fullGeomGrad) PeNS 3309 { 3310 #if defined(PETSC_HAVE_EGADS) 3311 /* PETSc Variables */ 3312 PetscContainer modelObj; 3313 PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 3314 PetscHMapI pointSurfGradRow_Start = NULL; 3315 Mat pointSurfGrad, cpEquiv; 3316 IS faceLabelValues, edgeLabelValues, vertexLabelValues; 3317 PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 3318 PetscBool islite = PETSC_FALSE; 3319 /* EGADS Variables */ 3320 ego model, geom, *bodies, *fobjs = NULL; 3321 int oclass, mtype, *senses; 3322 int Nb, Nf; 3323 #endif 3324 3325 PetscFunctionBegin; 3326 #if defined(PETSC_HAVE_EGADS) 3327 3328 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 3329 if (!modelObj) { 3330 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 3331 PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 3332 islite = PETSC_TRUE; 3333 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"); 3334 } 3335 3336 // Get attached EGADS model (pointer) 3337 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 3338 3339 // Get the bodies in the model 3340 if (islite) { 3341 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 3342 } else { 3343 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 3344 } 3345 3346 ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 3347 3348 // Get the total number of FACEs in the model 3349 if (islite) { 3350 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 3351 } else { 3352 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 3353 } 3354 3355 // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 3356 // This will provide the total number of DMPlex points on the boundary of the geometry 3357 PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 3358 PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 3359 3360 PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 3361 PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 3362 3363 PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 3364 PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 3365 3366 const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 3367 PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 3368 PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 3369 PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 3370 3371 // Get the points associated with each FACE, EDGE and VERTEX label in the DM 3372 PetscInt totalNumPoints = 0; 3373 for (int f = 0; f < faceLabelSize; ++f) { 3374 // Cycle through FACE labels 3375 PetscInt size; 3376 PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[f], &size)); 3377 totalNumPoints += size; 3378 } 3379 PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 3380 PetscCall(ISDestroy(&faceLabelValues)); 3381 3382 for (int e = 0; e < edgeLabelSize; ++e) { 3383 // Cycle Through EDGE Labels 3384 PetscInt size; 3385 PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[e], &size)); 3386 totalNumPoints += size; 3387 } 3388 PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 3389 PetscCall(ISDestroy(&edgeLabelValues)); 3390 3391 for (int ii = 0; ii < vertexLabelSize; ++ii) { 3392 // Cycle Through VERTEX Labels 3393 PetscInt size; 3394 PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 3395 totalNumPoints += size; 3396 } 3397 PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 3398 PetscCall(ISDestroy(&vertexLabelValues)); 3399 3400 int maxNumCPs = 0; 3401 int totalNumCPs = 0; 3402 ego bRef, bPrev, bNext, fgeom, *lobjs; 3403 int id, boclass, bmtype, *bpinfo; 3404 int foclass, fmtype, Nl, *lsenses; 3405 double *bprv; 3406 double fdata[4]; 3407 3408 // Create Hash Tables 3409 PetscInt cntr = 0, wcntr = 0, vcntr = 0; 3410 PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 3411 PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 3412 3413 for (int f = 0; f < Nf; ++f) { 3414 // Need to get the maximum number of Control Points defining the FACEs 3415 ego face = fobjs[f]; 3416 int maxNumCPs_temp; 3417 3418 if (islite) { 3419 id = EGlite_indexBodyTopo(body, face); 3420 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3421 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3422 PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3423 } else { 3424 id = EG_indexBodyTopo(body, face); 3425 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3426 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3427 PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3428 } 3429 maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 3430 totalNumCPs += bpinfo[2] * bpinfo[5]; 3431 3432 if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 3433 } 3434 3435 PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 3436 PetscInt cpCoordDataLength = 3 * totalNumCPs; 3437 PetscInt wDataLength = totalNumCPs; 3438 cpCoordDataLengthPtr = &cpCoordDataLength; 3439 wDataLengthPtr = &wDataLength; 3440 3441 Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 3442 PetscScalar *cntrlPtCoords, *cntrlPtWeights; 3443 PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &cntrlPtCoordsVec)); 3444 PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &cntrlPtWeightsVec)); 3445 3446 // For dSA/dCPi 3447 Vec gradSACPVec, gradSAWVec, gradVCPVec, gradVWVec; 3448 PetscScalar *gradSACP, *gradSAW, *gradVCP, *gradVW; 3449 PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradSACPVec)); 3450 PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradSAWVec)); 3451 PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradVCPVec)); 3452 PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradVWVec)); 3453 3454 // Control Point - Vertex/Edge/Face Relationship 3455 PetscInt *cp_vertex, *cp_edge, *cp_face; 3456 PetscInt *w_vertex, *w_edge, *w_face; 3457 PetscCall(PetscMalloc1(totalNumCPs, &cp_vertex)); 3458 PetscCall(PetscMalloc1(totalNumCPs, &cp_edge)); 3459 PetscCall(PetscMalloc1(totalNumCPs, &cp_face)); 3460 PetscCall(PetscMalloc1(wDataLength, &w_vertex)); 3461 PetscCall(PetscMalloc1(wDataLength, &w_edge)); 3462 PetscCall(PetscMalloc1(wDataLength, &w_face)); 3463 3464 for (int f = 0; f < Nf; ++f) { 3465 // Need to Populate Control Point Coordinates and Weight Vectors 3466 ego face = fobjs[f]; 3467 ego *vobjs, *eobjs; 3468 int offsetCoord, offsetWeight; 3469 PetscInt Nv, Ne, wRowStart = 0; 3470 PetscHashIter hashKeyIter, wHashKeyIter; 3471 PetscBool hashKeyFound, wHashKeyFound; 3472 3473 if (islite) { 3474 id = EGlite_indexBodyTopo(body, face); 3475 PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3476 PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3477 PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3478 PetscCallEGADS(EGlite_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 3479 } else { 3480 id = EG_indexBodyTopo(body, face); 3481 PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3482 PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3483 PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3484 PetscCallEGADS(EG_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 3485 } 3486 3487 // Store Face ID to 1st Row of Control Point Vector 3488 PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 3489 3490 if (!hashKeyFound) PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); 3491 3492 PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 3493 offsetCoord = bpinfo[3] + bpinfo[6]; 3494 for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 3495 cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 3496 cntr += 1; 3497 } 3498 3499 // Store Face ID to 1st Row of Control Point Weight Vector 3500 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 3501 3502 if (!wHashKeyFound) { 3503 PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); 3504 wRowStart = wcntr; 3505 } 3506 3507 PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 3508 offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 3509 for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 3510 cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 3511 cp_face[wcntr] = id; 3512 w_face[wcntr] = id; 3513 wcntr += 1; 3514 } 3515 PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 3516 3517 // Associate Control Points with Vertix IDs 3518 PetscScalar xcp, ycp, zcp; 3519 offsetCoord = bpinfo[3] + bpinfo[6]; 3520 for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; jj += 3) { 3521 xcp = bprv[offsetCoord + jj + 0]; 3522 ycp = bprv[offsetCoord + jj + 1]; 3523 zcp = bprv[offsetCoord + jj + 2]; 3524 3525 //Initialize Control Point and Weight to Vertex ID relationship to -1 3526 cp_vertex[vcntr] = -1; 3527 w_vertex[vcntr] = -1; 3528 cp_edge[vcntr] = -1; 3529 w_edge[vcntr] = -1; 3530 3531 for (int kk = 0; kk < Nv; ++kk) { 3532 int vid; 3533 double vCoords[3]; 3534 PetscScalar vDelta; 3535 ego vertex = vobjs[kk]; 3536 3537 if (islite) { 3538 vid = EGlite_indexBodyTopo(body, vertex); 3539 PetscCallEGADS(EGlite_evaluate, (vertex, NULL, vCoords)); 3540 } else { 3541 vid = EG_indexBodyTopo(body, vertex); 3542 PetscCallEGADS(EG_evaluate, (vertex, NULL, vCoords)); 3543 } 3544 vDelta = PetscSqrtReal(PetscSqr(vCoords[0] - xcp) + PetscSqr(vCoords[1] - ycp) + PetscSqr(vCoords[2] - zcp)); 3545 3546 if (vDelta < 1.0E-15) { 3547 cp_vertex[vcntr] = vid; 3548 w_vertex[vcntr] = vid; 3549 } 3550 } 3551 vcntr += 1; 3552 } 3553 // These two line could be replaced with DMPlexFreeGeomObject() 3554 if (islite) EGlite_free(vobjs); 3555 else EG_free(vobjs); 3556 3557 // Associate Control Points with Edge IDs 3558 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 3559 else PetscCallEGADS(EG_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 3560 3561 int cpV1, cpV2; 3562 int minID, maxID; 3563 3564 // Along vmin axis 3565 minID = wRowStart; 3566 maxID = wRowStart + (bpinfo[2] - 1); 3567 cpV1 = cp_vertex[minID]; 3568 cpV2 = cp_vertex[maxID]; 3569 for (int jj = 0; jj < Ne; ++jj) { 3570 ego edge = eobjs[jj]; 3571 ego egeom, *nobjs; 3572 int eoclass, emtype, Nn, *nsenses; 3573 int n1ID, n2ID, eid; 3574 3575 if (islite) { 3576 eid = EGlite_indexBodyTopo(body, edge); 3577 PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3578 } else { 3579 eid = EG_indexBodyTopo(body, edge); 3580 PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3581 } 3582 3583 if (emtype != DEGENERATE) { 3584 // Get IDs for current Edge's End Vertices 3585 if (islite) { 3586 n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3587 n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3588 } else { 3589 n1ID = EG_indexBodyTopo(body, nobjs[0]); 3590 n2ID = EG_indexBodyTopo(body, nobjs[1]); 3591 } 3592 3593 if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3594 for (int kk = minID + 1; kk < maxID; ++kk) { 3595 cp_edge[kk] = eid; 3596 w_edge[kk] = eid; 3597 } 3598 } 3599 } 3600 } 3601 3602 // Along vmax axis 3603 minID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 3604 maxID = wRowStart + (bpinfo[2] * bpinfo[5] - 1); 3605 3606 cpV1 = cp_vertex[minID]; 3607 cpV2 = cp_vertex[maxID]; 3608 for (int jj = 0; jj < Ne; ++jj) { 3609 ego edge = eobjs[jj]; 3610 ego egeom, *nobjs; 3611 int eoclass, emtype, Nn, *nsenses; 3612 int n1ID, n2ID, eid; 3613 3614 if (islite) { 3615 eid = EGlite_indexBodyTopo(body, edge); 3616 PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3617 } else { 3618 eid = EG_indexBodyTopo(body, edge); 3619 PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3620 } 3621 3622 if (emtype != DEGENERATE) { 3623 // Get IDs for current Edge's End Vertices 3624 if (islite) { 3625 n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3626 n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3627 } else { 3628 n1ID = EG_indexBodyTopo(body, nobjs[0]); 3629 n2ID = EG_indexBodyTopo(body, nobjs[1]); 3630 } 3631 3632 if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3633 for (int kk = minID + 1; kk < maxID - 1; ++kk) { 3634 cp_edge[kk] = eid; 3635 w_edge[kk] = eid; 3636 } 3637 } 3638 } 3639 } 3640 3641 // Along umin axis 3642 minID = wRowStart; 3643 maxID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 3644 3645 cpV1 = cp_vertex[minID]; 3646 cpV2 = cp_vertex[maxID]; 3647 for (int jj = 0; jj < Ne; ++jj) { 3648 ego edge = eobjs[jj]; 3649 ego egeom, *nobjs; 3650 int eoclass, emtype, Nn, *nsenses; 3651 int n1ID, n2ID, eid; 3652 3653 if (islite) { 3654 eid = EGlite_indexBodyTopo(body, edge); 3655 PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3656 } else { 3657 eid = EG_indexBodyTopo(body, edge); 3658 PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3659 } 3660 3661 if (emtype != DEGENERATE) { 3662 // Get IDs for current Edge's End Vertices 3663 if (islite) { 3664 n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3665 n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3666 } else { 3667 n1ID = EG_indexBodyTopo(body, nobjs[0]); 3668 n2ID = EG_indexBodyTopo(body, nobjs[1]); 3669 } 3670 3671 if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3672 for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 3673 cp_edge[kk] = eid; 3674 w_edge[kk] = eid; 3675 } 3676 } 3677 } 3678 } 3679 3680 // Along umax axis 3681 minID = wRowStart + (bpinfo[2] - 1); 3682 maxID = wRowStart + (bpinfo[2] * bpinfo[5]) - 1; 3683 cpV1 = cp_vertex[minID]; 3684 cpV2 = cp_vertex[maxID]; 3685 for (int jj = 0; jj < Ne; ++jj) { 3686 ego edge = eobjs[jj]; 3687 ego egeom, *nobjs; 3688 int eoclass, emtype, Nn, *nsenses; 3689 int n1ID, n2ID, eid; 3690 3691 if (islite) { 3692 eid = EGlite_indexBodyTopo(body, edge); 3693 PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3694 } else { 3695 eid = EG_indexBodyTopo(body, edge); 3696 PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3697 } 3698 3699 if (emtype != DEGENERATE) { 3700 // Get IDs for current Edge's End Vertices 3701 if (islite) { 3702 n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3703 n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3704 } else { 3705 n1ID = EG_indexBodyTopo(body, nobjs[0]); 3706 n2ID = EG_indexBodyTopo(body, nobjs[1]); 3707 } 3708 3709 if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3710 for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 3711 cp_edge[kk] = eid; 3712 w_edge[kk] = eid; 3713 } 3714 } 3715 } 3716 } 3717 // These two lines could be replaced with DMPlexFreeGeomObject() 3718 if (islite) EGlite_free(eobjs); 3719 else EG_free(eobjs); 3720 } 3721 3722 // Determine Control Point Equivalance Matrix relating Control Points between Surfaces 3723 // Note: The Weights will also be tied together in the same manner 3724 // Also can use the Weight Hash Table for Row Start ID of each Face 3725 const PetscInt cpRowSize = totalNumCPs; 3726 const PetscInt cpColSize = cpRowSize; 3727 PetscInt *maxNumRelatePtr; 3728 PetscInt maxNumRelate = 0; 3729 3730 // Create Point Surface Gradient Matrix 3731 PetscCall(MatCreate(PETSC_COMM_WORLD, &cpEquiv)); 3732 PetscCall(MatSetSizes(cpEquiv, PETSC_DECIDE, PETSC_DECIDE, cpRowSize, cpColSize)); 3733 PetscCall(MatSetType(cpEquiv, MATAIJ)); 3734 PetscCall(MatSetUp(cpEquiv)); 3735 3736 for (int ii = 0; ii < totalNumCPs; ++ii) { 3737 PetscScalar x1, y1, z1; 3738 PetscInt maxRelateTemp = 0; 3739 3740 x1 = cntrlPtCoords[(3 * ii) + 0]; 3741 y1 = cntrlPtCoords[(3 * ii) + 1]; 3742 z1 = cntrlPtCoords[(3 * ii) + 2]; 3743 3744 for (int jj = 0; jj < totalNumCPs; ++jj) { 3745 PetscScalar x2, y2, z2; 3746 PetscScalar cpDelta, eqFactor; 3747 x2 = cntrlPtCoords[(3 * jj) + 0]; 3748 y2 = cntrlPtCoords[(3 * jj) + 1]; 3749 z2 = cntrlPtCoords[(3 * jj) + 2]; 3750 3751 cpDelta = PetscSqrtReal(PetscSqr(x2 - x1) + PetscSqr(y2 - y1) + PetscSqr(z2 - z1)); 3752 if (cpDelta < 1.0E-15) { 3753 eqFactor = 1.0; 3754 maxRelateTemp += 1; 3755 } else { 3756 eqFactor = 0.0; 3757 } 3758 3759 // Store Results in Petsc Matrix 3760 PetscCall(MatSetValue(cpEquiv, ii, jj, eqFactor, INSERT_VALUES)); 3761 } 3762 if (maxRelateTemp > maxNumRelate) maxNumRelate = maxRelateTemp; 3763 } 3764 maxNumRelatePtr = &maxNumRelate; 3765 PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 3766 3767 // Assemble Point Surface Grad Matrix 3768 PetscCall(MatAssemblyBegin(cpEquiv, MAT_FINAL_ASSEMBLY)); 3769 PetscCall(MatAssemblyEnd(cpEquiv, MAT_FINAL_ASSEMBLY)); 3770 3771 // Attach Control Point and Weight Data to DM 3772 { 3773 PetscContainer cpOrgObj, cpCoordLengthObj; 3774 PetscContainer wOrgObj, wDataLengthObj; 3775 PetscContainer cp_faceObj, cp_edgeObj, cp_vertexObj; 3776 PetscContainer w_faceObj, w_edgeObj, w_vertexObj; 3777 PetscContainer maxNumRelateObj; 3778 3779 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpOrgObj)); 3780 if (!cpOrgObj) { 3781 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 3782 PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 3783 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 3784 PetscCall(PetscContainerDestroy(&cpOrgObj)); 3785 } else { 3786 PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 3787 } 3788 3789 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cntrlPtCoordsVec)); 3790 PetscCall(VecDestroy(&cntrlPtCoordsVec)); 3791 3792 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordLengthObj)); 3793 if (!cpCoordLengthObj) { 3794 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 3795 PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 3796 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 3797 PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 3798 } else { 3799 PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 3800 } 3801 3802 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wOrgObj)); 3803 if (!wOrgObj) { 3804 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 3805 PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 3806 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 3807 PetscCall(PetscContainerDestroy(&wOrgObj)); 3808 } else { 3809 PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 3810 } 3811 3812 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)cntrlPtWeightsVec)); 3813 PetscCall(VecDestroy(&cntrlPtWeightsVec)); 3814 3815 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 3816 if (!wDataLengthObj) { 3817 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 3818 PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 3819 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 3820 PetscCall(PetscContainerDestroy(&wDataLengthObj)); 3821 } else { 3822 PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 3823 } 3824 3825 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Equivalancy Matrix", (PetscObject)cpEquiv)); 3826 3827 PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 3828 if (!maxNumRelateObj) { 3829 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &maxNumRelateObj)); 3830 PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 3831 PetscCall(PetscObjectCompose((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject)maxNumRelateObj)); 3832 PetscCall(PetscContainerDestroy(&maxNumRelateObj)); 3833 } else { 3834 PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 3835 } 3836 3837 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cp_faceObj)); 3838 if (!cp_faceObj) { 3839 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_faceObj)); 3840 PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 3841 PetscCall(PetscContainerSetCtxDestroy(cp_faceObj, PetscCtxDestroyDefault)); 3842 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Face Map", (PetscObject)cp_faceObj)); 3843 PetscCall(PetscContainerDestroy(&cp_faceObj)); 3844 } else { 3845 void *tmp; 3846 3847 PetscCall(PetscContainerGetPointer(cp_faceObj, &tmp)); 3848 PetscCall(PetscFree(tmp)); 3849 PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 3850 } 3851 3852 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&w_faceObj)); 3853 if (!w_faceObj) { 3854 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_faceObj)); 3855 PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 3856 PetscCall(PetscContainerSetCtxDestroy(w_faceObj, PetscCtxDestroyDefault)); 3857 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject)w_faceObj)); 3858 PetscCall(PetscContainerDestroy(&w_faceObj)); 3859 } else { 3860 void *tmp; 3861 3862 PetscCall(PetscContainerGetPointer(w_faceObj, &tmp)); 3863 PetscCall(PetscFree(tmp)); 3864 PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 3865 } 3866 3867 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cp_edgeObj)); 3868 if (!cp_edgeObj) { 3869 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_edgeObj)); 3870 PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 3871 PetscCall(PetscContainerSetCtxDestroy(cp_edgeObj, PetscCtxDestroyDefault)); 3872 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Edge Map", (PetscObject)cp_edgeObj)); 3873 PetscCall(PetscContainerDestroy(&cp_edgeObj)); 3874 } else { 3875 void *tmp; 3876 3877 PetscCall(PetscContainerGetPointer(cp_edgeObj, &tmp)); 3878 PetscCall(PetscFree(tmp)); 3879 PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 3880 } 3881 3882 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&w_edgeObj)); 3883 if (!w_edgeObj) { 3884 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_edgeObj)); 3885 PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 3886 PetscCall(PetscContainerSetCtxDestroy(w_edgeObj, PetscCtxDestroyDefault)); 3887 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject)w_edgeObj)); 3888 PetscCall(PetscContainerDestroy(&w_edgeObj)); 3889 } else { 3890 void *tmp; 3891 3892 PetscCall(PetscContainerGetPointer(w_edgeObj, &tmp)); 3893 PetscCall(PetscFree(tmp)); 3894 PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 3895 } 3896 3897 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cp_vertexObj)); 3898 if (!cp_vertexObj) { 3899 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_vertexObj)); 3900 PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 3901 PetscCall(PetscContainerSetCtxDestroy(cp_vertexObj, PetscCtxDestroyDefault)); 3902 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Vertex Map", (PetscObject)cp_vertexObj)); 3903 PetscCall(PetscContainerDestroy(&cp_vertexObj)); 3904 } else { 3905 void *tmp; 3906 3907 PetscCall(PetscContainerGetPointer(cp_vertexObj, &tmp)); 3908 PetscCall(PetscFree(tmp)); 3909 PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 3910 } 3911 3912 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&w_vertexObj)); 3913 if (!w_vertexObj) { 3914 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_vertexObj)); 3915 PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 3916 PetscCall(PetscContainerSetCtxDestroy(w_vertexObj, PetscCtxDestroyDefault)); 3917 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject)w_vertexObj)); 3918 PetscCall(PetscContainerDestroy(&w_vertexObj)); 3919 } else { 3920 void *tmp; 3921 3922 PetscCall(PetscContainerGetPointer(w_vertexObj, &tmp)); 3923 PetscCall(PetscFree(tmp)); 3924 PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 3925 } 3926 } 3927 3928 // Define Matrix to store Geometry Gradient information dGeom_i/dCPj_i 3929 PetscInt gcntr = 0; 3930 const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 3931 const PetscInt colSize = 4 * Nf; 3932 3933 // Create Point Surface Gradient Matrix 3934 PetscCall(MatCreate(PETSC_COMM_WORLD, &pointSurfGrad)); 3935 PetscCall(MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize)); 3936 PetscCall(MatSetType(pointSurfGrad, MATAIJ)); 3937 PetscCall(MatSetUp(pointSurfGrad)); 3938 3939 // Create Hash Table to store Point's stare row in surfaceGrad[][] 3940 PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 3941 3942 // Get Coordinates for the DMPlex point 3943 DM cdm; 3944 PetscInt dE, Nv; 3945 Vec coordinatesLocal; 3946 PetscScalar *coords = NULL; 3947 3948 PetscCall(DMGetCoordinateDM(dm, &cdm)); 3949 PetscCall(DMGetCoordinateDim(dm, &dE)); 3950 PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 3951 3952 // CYCLE THROUGH FACEs 3953 PetscScalar maxGrad = 0.; 3954 PetscCall(VecGetArrayWrite(gradSACPVec, &gradSACP)); 3955 PetscCall(VecGetArrayWrite(gradSAWVec, &gradSAW)); 3956 PetscCall(VecGetArrayWrite(gradVCPVec, &gradVCP)); 3957 PetscCall(VecGetArrayWrite(gradVWVec, &gradVW)); 3958 for (int f = 0; f < Nf; ++f) { 3959 ego face = fobjs[f]; 3960 ego *eobjs, *nobjs; 3961 PetscInt fid, Ne, Nn; 3962 DMLabel faceLabel, edgeLabel, nodeLabel; 3963 PetscHMapI currFaceUniquePoints = NULL; 3964 IS facePoints, edgePoints, nodePoints; 3965 const PetscInt *fIndices, *eIndices, *nIndices; 3966 PetscInt fSize, eSize, nSize; 3967 PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 3968 PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 3969 PetscInt cfCntr = 0; 3970 3971 // Get Geometry Object for the Current FACE 3972 if (islite) { 3973 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3974 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3975 } else { 3976 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3977 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3978 } 3979 3980 // Get all EDGE and NODE objects attached to the current FACE 3981 if (islite) { 3982 PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3983 PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3984 } else { 3985 PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3986 PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3987 } 3988 3989 // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 3990 if (islite) { 3991 fid = EGlite_indexBodyTopo(body, face); 3992 } else { 3993 fid = EG_indexBodyTopo(body, face); 3994 } 3995 3996 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 3997 PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 3998 PetscCall(ISGetIndices(facePoints, &fIndices)); 3999 PetscCall(ISGetSize(facePoints, &fSize)); 4000 4001 PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 4002 4003 for (int jj = 0; jj < fSize; ++jj) { 4004 PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 4005 4006 if (!fHashKeyFound) { 4007 PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 4008 cfCntr += 1; 4009 } 4010 4011 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 4012 4013 if (!pHashKeyFound) { 4014 PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 4015 gcntr += 3 * maxNumCPs; 4016 } 4017 } 4018 PetscCall(ISRestoreIndices(facePoints, &fIndices)); 4019 PetscCall(ISDestroy(&facePoints)); 4020 4021 // 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. 4022 for (int jj = 0; jj < Ne; ++jj) { 4023 ego edge = eobjs[jj]; 4024 PetscBool containLabelValue; 4025 4026 if (islite) { 4027 id = EGlite_indexBodyTopo(body, edge); 4028 } else { 4029 id = EG_indexBodyTopo(body, edge); 4030 } 4031 4032 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4033 PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 4034 4035 if (containLabelValue) { 4036 PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 4037 PetscCall(ISGetIndices(edgePoints, &eIndices)); 4038 PetscCall(ISGetSize(edgePoints, &eSize)); 4039 4040 for (int kk = 0; kk < eSize; ++kk) { 4041 PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 4042 4043 if (!eHashKeyFound) { 4044 PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 4045 cfCntr += 1; 4046 } 4047 4048 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 4049 4050 if (!pHashKeyFound) { 4051 PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 4052 gcntr += 3 * maxNumCPs; 4053 } 4054 } 4055 PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 4056 PetscCall(ISDestroy(&edgePoints)); 4057 } 4058 } 4059 4060 // 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. 4061 for (int jj = 0; jj < Nn; ++jj) { 4062 ego node = nobjs[jj]; 4063 4064 if (islite) { 4065 id = EGlite_indexBodyTopo(body, node); 4066 } else { 4067 id = EG_indexBodyTopo(body, node); 4068 } 4069 4070 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 4071 PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 4072 PetscCall(ISGetIndices(nodePoints, &nIndices)); 4073 PetscCall(ISGetSize(nodePoints, &nSize)); 4074 4075 for (int kk = 0; kk < nSize; ++kk) { 4076 PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 4077 4078 if (!nHashKeyFound) { 4079 PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 4080 cfCntr += 1; 4081 } 4082 4083 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 4084 if (!pHashKeyFound) { 4085 PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 4086 gcntr += 3 * maxNumCPs; 4087 } 4088 } 4089 PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 4090 PetscCall(ISDestroy(&nodePoints)); 4091 } 4092 4093 // Get the Total Number of entries in the Hash Table 4094 PetscInt currFaceUPSize; 4095 PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 4096 4097 // Get Keys 4098 PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 4099 PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 4100 PetscCall(PetscHMapIDestroy(&currFaceUniquePoints)); 4101 4102 // Get Current Face Surface Area 4103 PetscScalar fSA, faceData[14]; 4104 PetscCall(EG_getMassProperties(face, faceData)); // This doesn't have a EGlite version. Will it work for EGADSlite files?? KNOWN_ISSUE 4105 fSA = faceData[1]; 4106 4107 // Get Start Row in cpEquiv Matrix 4108 PetscHashIter Witer; 4109 PetscBool Wfound; 4110 PetscInt faceWStartRow; 4111 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 4112 PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4113 PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 4114 4115 // Cycle through all points on the current FACE 4116 for (int jj = 0; jj < currFaceUPSize; ++jj) { 4117 PetscInt currPointID = currFaceUPKeys[jj]; 4118 PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 4119 4120 // Get UV position of FACE 4121 double params[2], range[4], eval[18]; 4122 int peri; 4123 4124 if (islite) PetscCall(EGlite_getRange(face, range, &peri)); 4125 else PetscCall(EG_getRange(face, range, &peri)); 4126 4127 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 4128 4129 if (islite) PetscCall(EGlite_evaluate(face, params, eval)); 4130 else PetscCall(EG_evaluate(face, params, eval)); 4131 4132 // Make a new SURFACE Geometry by changing the location of the Control Points 4133 int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 4134 double nbprv[prvSize]; 4135 4136 // Cycle through each Control Point 4137 double denomNew, denomOld; 4138 double deltaCoord = 1.0E-4; 4139 int offset = bpinfo[3] + bpinfo[6]; 4140 int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 4141 for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 4142 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d", f, jj, ii); 4143 #if 0 4144 // Cycle through each direction (x, then y, then z) 4145 if (jj == 0) { 4146 // Get the Number Control Points that are the same as the current points 4147 // We are looking for repeated Control Points 4148 PetscInt commonCPcntr = 0; 4149 for (int mm = 0; mm < bpinfo[2]*bpinfo[5]; ++mm) { 4150 PetscScalar matValue; 4151 PetscCall(MatGetValue(cpEquiv, faceWStartRow + ii, faceWStartRow + mm, &matValue)); 4152 4153 if (matValue > 0.0) commonCPcntr += 1; 4154 } 4155 } 4156 #endif 4157 4158 for (int kk = 0; kk < 4; ++kk) { 4159 // Reinitialize nbprv[] values because we only want to change one value at a time 4160 for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 4161 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4162 4163 if (kk == 0) { //X 4164 nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 4165 nbprv[offset + 1] = bprv[offset + 1]; 4166 nbprv[offset + 2] = bprv[offset + 2]; 4167 denomNew = nbprv[offset + 0]; 4168 denomOld = bprv[offset + 0]; 4169 } else if (kk == 1) { //Y 4170 nbprv[offset + 0] = bprv[offset + 0]; 4171 nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 4172 nbprv[offset + 2] = bprv[offset + 2]; 4173 denomNew = nbprv[offset + 1]; 4174 denomOld = bprv[offset + 1]; 4175 } else if (kk == 2) { //Z 4176 nbprv[offset + 0] = bprv[offset + 0]; 4177 nbprv[offset + 1] = bprv[offset + 1]; 4178 nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 4179 denomNew = nbprv[offset + 2]; 4180 denomOld = bprv[offset + 2]; 4181 } else if (kk == 3) { // Weights 4182 nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 4183 denomNew = nbprv[wOffset + ii]; 4184 denomOld = bprv[wOffset + ii]; 4185 } else { 4186 // currently do nothing 4187 } 4188 4189 // Create New Surface Based on New Control Points or Weights 4190 ego newgeom, context; 4191 PetscCallEGADS(EG_getContext, (face, &context)); // This does not have an EGlite_ version KNOWN_ISSUE 4192 PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // This does not have an EGlite_ version KNOWN_ISSUE 4193 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4194 4195 // Evaluate new (x, y, z) Point Position based on new Surface Definition 4196 double newCoords[18]; 4197 if (islite) PetscCall(EGlite_getRange(newgeom, range, &peri)); 4198 else PetscCall(EG_getRange(newgeom, range, &peri)); 4199 4200 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 4201 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4202 4203 if (islite) PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 4204 else PetscCall(EG_evaluate(newgeom, params, newCoords)); 4205 4206 // Calculate Surface Area Gradients wrt Control Points and Weights using the local discrete FACE only 4207 // NOTE 1: Will not provide Volume Gradient wrt to Control Points and Weights. 4208 // NOTE 2: This is faster than below where an entire new solid geometry is created for each 4209 // Control Point and Weight gradient 4210 if (!fullGeomGrad) { 4211 // Create new FACE based on new SURFACE geometry 4212 if (jj == 0) { // only for 1st DMPlex Point because we only per CP or Weight 4213 double newFaceRange[4]; 4214 int newFacePeri; 4215 if (islite) PetscCall(EGlite_getRange(newgeom, newFaceRange, &newFacePeri)); 4216 else PetscCall(EG_getRange(newgeom, newFaceRange, &newFacePeri)); 4217 4218 ego newface; 4219 PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have EGlite version KNOWN_ISSUE 4220 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4221 4222 // Get New Face Surface Area 4223 PetscScalar newfSA, newFaceData[14]; 4224 PetscCall(EG_getMassProperties(newface, newFaceData)); // Does not have EGlite version KNOWN_ISSUE 4225 newfSA = newFaceData[1]; 4226 PetscCallEGADS(EG_deleteObject, (newface)); 4227 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4228 4229 // Update Control Points 4230 PetscHashIter CPiter, Witer; 4231 PetscBool CPfound, Wfound; 4232 PetscInt faceCPStartRow, faceWStartRow; 4233 4234 PetscScalar dSAdCPi; 4235 dSAdCPi = (newfSA - fSA) / (denomNew - denomOld); 4236 4237 if (kk < 3) { 4238 PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, fid, &CPiter, &CPfound)); 4239 PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4240 PetscCall(PetscHMapIGet(faceCntrlPtRow_Start, fid, &faceCPStartRow)); 4241 4242 gradSACP[faceCPStartRow + (ii * 3) + kk] = dSAdCPi; 4243 4244 if (PetscAbsReal(dSAdCPi) > maxGrad) maxGrad = PetscAbsReal(dSAdCPi); 4245 4246 } else if (kk == 3) { 4247 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 4248 PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4249 PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 4250 4251 gradSAW[faceWStartRow + ii] = dSAdCPi; 4252 4253 } else { 4254 // Do Nothing 4255 } 4256 } 4257 } 4258 PetscCallEGADS(EG_deleteObject, (newgeom)); 4259 4260 // Now Calculate the Surface Gradient for the change in x-component Control Point 4261 PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 4262 PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 4263 PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 4264 4265 // Store Gradient Information in surfaceGrad[][] Matrix 4266 PetscInt startRow; 4267 PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 4268 4269 // Store Results in Petsc Matrix 4270 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 4271 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 4272 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 4273 4274 //PetscCallEGADS(EG_deleteObject, (newgeom)); 4275 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face is corrupted"); 4276 } 4277 offset += 3; 4278 } 4279 PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 4280 } 4281 } 4282 4283 // Assemble Point Surface Grad Matrix 4284 PetscCall(MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 4285 PetscCall(MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 4286 4287 if (fullGeomGrad) { 4288 // Calculate Surface Area and Volume Control Point and Control Point Weight Gradients 4289 // Note: This is much slower than above due to a new solid geometry being created for 4290 // each change in Control Point and Control Point Weight. However, this method 4291 // will provide the Volume Gradient. 4292 4293 // Get Current Face Surface Area 4294 PetscScalar bodyVol, bodySA, bodyData[14]; 4295 PetscCall(EG_getMassProperties(body, bodyData)); // Does not have an EGlite versin KNOWN_ISSUE 4296 bodyVol = bodyData[0]; 4297 bodySA = bodyData[1]; 4298 4299 // Cycle through Control Points 4300 for (int ii = 0; ii < totalNumCPs; ++ii) { // ii should also be the row in cpEquiv for the Control Point 4301 // Cycle through X, Y, Z, W changes 4302 for (int jj = 0; jj < 4; ++jj) { 4303 // Cycle Through Faces 4304 double denomNew = 0.0, denomOld = 0.0; 4305 double deltaCoord = 1.0E-4; 4306 ego newGeom[Nf]; 4307 ego newFaces[Nf]; 4308 for (int kk = 0; kk < Nf; ++kk) { 4309 ego face; 4310 PetscInt currFID = kk + 1; 4311 4312 if (islite) { 4313 // Get Current FACE 4314 PetscCallEGADS(EGlite_objectBodyTopo, (body, FACE, currFID, &face)); 4315 4316 // Get Geometry Object for the Current FACE 4317 PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 4318 PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4319 } else { 4320 // Get Current FACE 4321 PetscCallEGADS(EG_objectBodyTopo, (body, FACE, currFID, &face)); 4322 4323 // Get Geometry Object for the Current FACE 4324 PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 4325 PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4326 } 4327 4328 // Make a new SURFACE Geometry by changing the location of the Control Points 4329 int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 4330 double nbprv[prvSize]; 4331 4332 // Reinitialize nbprv[] values because we only want to change one value at a time 4333 for (int mm = 0; mm < prvSize; ++mm) nbprv[mm] = bprv[mm]; 4334 4335 // Get Control Point Row and Column Start for cpEquiv 4336 PetscHashIter Witer; 4337 PetscBool Wfound; 4338 PetscInt faceWStartRow; 4339 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, currFID, &Witer, &Wfound)); 4340 PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4341 PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, currFID, &faceWStartRow)); 4342 4343 // Modify the Current Control Point on this FACE and All Other FACES 4344 // IMPORTANT!!! If you do not move all identical Control Points on other FACES 4345 // you will not generate a solid body. You will generate a set of 4346 // disconnected surfaces that have gap(s) between them. 4347 int offset = bpinfo[3] + bpinfo[6]; 4348 int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 4349 for (int mm = 0; mm < bpinfo[2] * bpinfo[5]; ++mm) { 4350 PetscScalar matValue; 4351 PetscCall(MatGetValue(cpEquiv, ii, faceWStartRow + mm, &matValue)); 4352 4353 if (matValue > 0.0) { 4354 if (jj == 0) { //X 4355 nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0] + deltaCoord; 4356 nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 4357 nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 4358 denomNew = nbprv[offset + (3 * mm) + 0]; 4359 denomOld = bprv[offset + (3 * mm) + 0]; 4360 } else if (jj == 1) { //Y 4361 nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 4362 nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1] + deltaCoord; 4363 nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 4364 denomNew = nbprv[offset + (3 * mm) + 1]; 4365 denomOld = bprv[offset + (3 * mm) + 1]; 4366 } else if (jj == 2) { //Z 4367 nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 4368 nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 4369 nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2] + deltaCoord; 4370 denomNew = nbprv[offset + (3 * mm) + 2]; 4371 denomOld = bprv[offset + (3 * mm) + 2]; 4372 } else if (jj == 3) { // Weights 4373 nbprv[wOffset + mm] = bprv[wOffset + mm] + deltaCoord; 4374 denomNew = nbprv[wOffset + mm]; 4375 denomOld = bprv[wOffset + mm]; 4376 } else { 4377 // currently do nothing 4378 } 4379 } 4380 } 4381 4382 // Create New Surface Based on New Control Points or Weights 4383 ego newgeom, context; 4384 PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ versions KNOWN_ISSUE 4385 PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 4386 4387 // Create New FACE based on modified geometry 4388 double newFaceRange[4]; 4389 int newFacePeri; 4390 if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, newFaceRange, &newFacePeri)); 4391 else PetscCallEGADS(EG_getRange, (newgeom, newFaceRange, &newFacePeri)); 4392 4393 ego newface; 4394 PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 4395 4396 // store new face for later assembly 4397 newGeom[kk] = newgeom; 4398 newFaces[kk] = newface; 4399 } 4400 4401 // X-WANT TO BUILD THE NEW GEOMETRY, X-GET NEW SA AND PERFORM dSA/dCPi CALCS HERE <--- 4402 // Sew New Faces together to get a new model 4403 ego newmodel; 4404 PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 4405 4406 // Get Surface Area and Volume of New/Updated Solid Body 4407 PetscScalar newData[14]; 4408 if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4409 else PetscCallEGADS(EG_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4410 4411 ego nbody = bodies[0]; 4412 PetscCall(EG_getMassProperties(nbody, newData)); // Does not have an EGlite_ version KNOWN_ISSUE 4413 4414 PetscScalar dSAdCPi, dVdCPi; 4415 PetscScalar nbodyVol = newData[0], nbodySA = newData[1]; 4416 4417 // Calculate Gradients wrt to Control Points and Control Points Weights depending on jj value 4418 dSAdCPi = (nbodySA - bodySA) / (denomNew - denomOld); 4419 dVdCPi = (nbodyVol - bodyVol) / (denomNew - denomOld); 4420 4421 if (jj < 3) { 4422 // Gradienst wrt to Control Points 4423 gradSACP[(ii * 3) + jj] = dSAdCPi; 4424 gradVCP[(ii * 3) + jj] = dVdCPi; 4425 } else if (jj == 3) { 4426 // Gradients wrt to Control Point Weights 4427 gradSAW[ii] = dSAdCPi; 4428 gradVW[ii] = dVdCPi; 4429 } else { 4430 // Do Nothing 4431 } 4432 PetscCallEGADS(EG_deleteObject, (newmodel)); 4433 for (int kk = 0; kk < Nf; ++kk) { 4434 PetscCallEGADS(EG_deleteObject, (newFaces[kk])); 4435 PetscCallEGADS(EG_deleteObject, (newGeom[kk])); 4436 } 4437 } 4438 } 4439 } 4440 PetscCall(VecRestoreArrayWrite(gradSACPVec, &gradSACP)); 4441 PetscCall(VecRestoreArrayWrite(gradSAWVec, &gradSAW)); 4442 PetscCall(VecRestoreArrayWrite(gradVCPVec, &gradVCP)); 4443 PetscCall(VecRestoreArrayWrite(gradVWVec, &gradVW)); 4444 PetscCall(MatDestroy(&cpEquiv)); 4445 4446 // Attach Surface Gradient Hash Table and Matrix to DM 4447 { 4448 PetscContainer surfGradOrgObj; 4449 4450 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&surfGradOrgObj)); 4451 if (!surfGradOrgObj) { 4452 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 4453 PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 4454 PetscCall(PetscContainerSetCtxDestroy(surfGradOrgObj, DestroyHashMap)); 4455 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 4456 PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 4457 } else { 4458 PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 4459 } 4460 4461 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)pointSurfGrad)); 4462 PetscCall(MatDestroy(&pointSurfGrad)); 4463 4464 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject)gradSACPVec)); 4465 PetscCall(VecDestroy(&gradSACPVec)); 4466 4467 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject)gradSAWVec)); 4468 PetscCall(VecDestroy(&gradSAWVec)); 4469 4470 if (fullGeomGrad) { 4471 PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Control Point Gradient", (PetscObject)gradVCPVec)); 4472 PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Weights Gradient", (PetscObject)gradVWVec)); 4473 } 4474 PetscCall(VecDestroy(&gradVCPVec)); 4475 PetscCall(VecDestroy(&gradVWVec)); 4476 } 4477 4478 // Could be replaced with DMPlexFreeGeomObject() 4479 if (islite) EGlite_free(fobjs); 4480 else EG_free(fobjs); 4481 PetscFunctionReturn(PETSC_SUCCESS); 4482 #else 4483 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 4484 #endif 4485 } 4486 4487 /*@C 4488 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. 4489 4490 Collective 4491 4492 Input Parameters: 4493 + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 4494 . comm - MPI_Comm object 4495 . newCP - C Array of [x, y, z] New/Updated Control Point Coordinates defining the geometry (See DMPlexGeomDataAndGrads() for format) 4496 . newW - C Array of New/Updated Control Point Weights associated with the Control Points defining the new geometry (See DMPlexGemGrads() for format) 4497 . autoInflate - PetscBool Flag denoting if the user would like to inflate the DM points to the new geometry. 4498 . saveGeom - PetscBool Flag denoting if the user would iike to save the new geometry to a file. 4499 - 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. 4500 *.stp or *.step = STEP File 4501 *.igs or *.iges = IGES File 4502 *.egads = EGADS File 4503 *.brep = BRep File (OpenCASCADE File) 4504 4505 Output Parameter: 4506 . dm - The updated DM object representing the mesh with PetscContainers containing the updated/modified geometry 4507 4508 Level: intermediate 4509 4510 Note: 4511 Functionality not available for DMPlexes with attached EGADSlite geometry files (.egadslite). 4512 4513 .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 4514 @*/ 4515 PetscErrorCode DMPlexModifyGeomModel(DM dm, MPI_Comm comm, PetscScalar newCP[], PetscScalar newW[], PetscBool autoInflate, PetscBool saveGeom, const char *stpName) PeNS 4516 { 4517 #if defined(PETSC_HAVE_EGADS) 4518 /* EGADS/EGADSlite variables */ 4519 ego context, model, geom, *bodies, *lobjs, *fobjs; 4520 int oclass, mtype, *senses, *lsenses; 4521 int Nb, Nf, Nl, id; 4522 /* PETSc variables */ 4523 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 4524 PetscContainer modelObj, cpHashTableObj, wHashTableObj; 4525 PetscHMapI cpHashTable = NULL, wHashTable = NULL; 4526 PetscBool islite = PETSC_FALSE; 4527 #endif 4528 4529 #if defined(PETSC_HAVE_EGADS) 4530 PetscFunctionBegin; 4531 // Look to see if DM has a Container with either a EGADS or EGADSlite Model 4532 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 4533 if (!modelObj) { 4534 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 4535 islite = PETSC_TRUE; 4536 } 4537 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"); 4538 PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have a EGADS Geometry Model attached to it!"); 4539 4540 // Get attached EGADS model (pointer) 4541 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 4542 4543 // Look to see if DM has Container for Geometry Control Point Data 4544 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 4545 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 4546 4547 PetscCheck(cpHashTableObj && wHashTableObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have required Geometry Data attached! Please run DMPlexGeomDataAndGrads() Function first."); 4548 4549 // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 4550 PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTable)); 4551 PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTable)); 4552 4553 // Get the number of bodies and body objects in the model 4554 if (islite) PetscCallEGADS(EGlite_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4555 else PetscCallEGADS(EG_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4556 4557 // Get all Faces on the body 4558 ego body = bodies[0]; 4559 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4560 else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4561 4562 ego newGeom[Nf]; 4563 ego newFaces[Nf]; 4564 4565 // Update Control Point and Weight definitions for each surface 4566 for (int jj = 0; jj < Nf; ++jj) { 4567 ego face = fobjs[jj]; 4568 ego bRef, bPrev, bNext; 4569 ego fgeom; 4570 int offset; 4571 int boclass, bmtype, *bpinfo; 4572 double *bprv; 4573 4574 // Get FACE ID and other Geometry Data 4575 if (islite) { 4576 id = EGlite_indexBodyTopo(body, face); 4577 PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 4578 PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4579 PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 4580 } else { 4581 id = EG_indexBodyTopo(body, face); 4582 PetscCallEGADS(EG_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 4583 PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4584 PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 4585 } 4586 4587 // Update Control Points 4588 PetscHashIter CPiter, Witer; 4589 PetscBool CPfound, Wfound; 4590 PetscInt faceCPStartRow, faceWStartRow; 4591 4592 PetscCall(PetscHMapIFind(cpHashTable, id, &CPiter, &CPfound)); 4593 PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4594 PetscCall(PetscHMapIGet(cpHashTable, id, &faceCPStartRow)); 4595 4596 PetscCall(PetscHMapIFind(wHashTable, id, &Witer, &Wfound)); 4597 PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4598 PetscCall(PetscHMapIGet(wHashTable, id, &faceWStartRow)); 4599 4600 // UPDATE CONTROL POINTS Locations 4601 offset = bpinfo[3] + bpinfo[6]; 4602 for (int ii = 0; ii < 3 * bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newCP[faceCPStartRow + ii]; } 4603 4604 // UPDATE CONTROL POINT WEIGHTS 4605 offset = bpinfo[3] + bpinfo[6] + 3 * bpinfo[2] * bpinfo[5]; 4606 for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newW[faceWStartRow + ii]; } 4607 4608 // Get Context from FACE 4609 context = NULL; 4610 PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version KNOWN_ISSUE 4611 4612 // Create New Surface 4613 ego newgeom; 4614 PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 4615 4616 // Create new FACE based on new SURFACE geometry 4617 double data[4]; 4618 int periodic; 4619 if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 4620 else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 4621 4622 ego newface; 4623 PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 4624 newGeom[jj] = newgeom; 4625 newFaces[jj] = newface; 4626 } 4627 // Could be replaced by DMPlexFreeGeomObject 4628 if (islite) EGlite_free(fobjs); 4629 else EG_free(fobjs); 4630 4631 // Sew New Faces together to get a new model 4632 ego newmodel; 4633 PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 4634 for (PetscInt f = 0; f < Nf; ++f) { 4635 PetscCallEGADS(EG_deleteObject, (newFaces[f])); 4636 PetscCallEGADS(EG_deleteObject, (newGeom[f])); 4637 } 4638 4639 // Get the total number of NODEs on the original geometry. (This will be the same for the new geometry) 4640 int totalNumNode; 4641 ego *nobjTotal; 4642 if (islite) { 4643 PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 4644 EGlite_free(nobjTotal); 4645 } else { 4646 PetscCallEGADS(EG_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 4647 EG_free(nobjTotal); 4648 } // Could be replaced with DMPlexFreeGeomObject 4649 4650 // Initialize vector to store equivalent NODE indices between the 2 geometries 4651 // FORMAT :: vector index is the Original Geometry's NODE ID, the vector Value is the New Geometry's NODE ID 4652 int nodeIDEquiv[totalNumNode + 1]; 4653 4654 // Now we need to Map the NODE and EDGE IDs from each Model 4655 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4656 else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4657 4658 // New CAD 4659 ego *newbodies, newgeomtest, *nfobjs; 4660 int nNf, newNb, newoclass, newmtype, *newsenses; 4661 if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 4662 else PetscCallEGADS(EG_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 4663 4664 ego newbody = newbodies[0]; 4665 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 4666 else PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 4667 4668 PetscCheck(newNb == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ERROR :: newNb > 1 || newNb = %d", newNb); 4669 4670 // Find Equivalent Nodes 4671 for (int ii = 0; ii < Nf; ++ii) { 4672 double fdata[4]; 4673 int peri; 4674 4675 // Get Current FACE [u, v] Ranges 4676 if (islite) PetscCallEGADS(EGlite_getRange, (fobjs[ii], fdata, &peri)); 4677 else PetscCallEGADS(EG_getRange, (fobjs[ii], fdata, &peri)); 4678 4679 // Equate NODE IDs between 2 FACEs by working through (u, v) limits of FACE 4680 for (int jj = 0; jj < 2; ++jj) { 4681 for (int kk = 2; kk < 4; ++kk) { 4682 double params[2] = {fdata[jj], fdata[kk]}; 4683 double eval[18]; 4684 if (islite) PetscCallEGADS(EGlite_evaluate, (fobjs[ii], params, eval)); 4685 else PetscCallEGADS(EG_evaluate, (fobjs[ii], params, eval)); 4686 4687 // Original Body 4688 ego *nobjsOrigFace; 4689 int origNn; 4690 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 4691 else PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 4692 4693 double minVal = 1.0E10; 4694 double evalCheck[18]; 4695 int equivOrigNodeID = -1; 4696 for (int mm = 0; mm < origNn; ++mm) { 4697 double delta = 1.0E10; 4698 if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 4699 else PetscCallEGADS(EG_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 4700 4701 delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 4702 4703 if (delta < minVal) { 4704 if (islite) equivOrigNodeID = EGlite_indexBodyTopo(body, nobjsOrigFace[mm]); 4705 else equivOrigNodeID = EG_indexBodyTopo(body, nobjsOrigFace[mm]); 4706 4707 minVal = delta; 4708 } 4709 } 4710 // Could be replaced with DMPlexFreeGeomObject 4711 if (islite) EGlite_free(nobjsOrigFace); 4712 else EG_free(nobjsOrigFace); 4713 4714 // New Body 4715 ego *nobjsNewFace; 4716 int newNn; 4717 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 4718 else PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 4719 4720 minVal = 1.0E10; 4721 int equivNewNodeID = -1; 4722 for (int mm = 0; mm < newNn; ++mm) { 4723 double delta = 1.0E10; 4724 if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 4725 else PetscCallEGADS(EG_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 4726 4727 delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 4728 4729 if (delta < minVal) { 4730 if (islite) equivNewNodeID = EGlite_indexBodyTopo(newbody, nobjsNewFace[mm]); 4731 else equivNewNodeID = EG_indexBodyTopo(newbody, nobjsNewFace[mm]); 4732 4733 minVal = delta; 4734 } 4735 } 4736 if (islite) EGlite_free(nobjsNewFace); 4737 else EG_free(nobjsNewFace); 4738 4739 // Store equivalent NODE IDs 4740 nodeIDEquiv[equivOrigNodeID] = equivNewNodeID; 4741 } 4742 } 4743 } 4744 4745 // Find Equivalent EDGEs 4746 // Get total number of EDGEs on Original Geometry 4747 int totalNumEdge; 4748 ego *eobjsOrig; 4749 if (islite) { 4750 PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 4751 EGlite_free(eobjsOrig); 4752 } else { 4753 PetscCallEGADS(EG_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 4754 EG_free(eobjsOrig); 4755 } 4756 4757 // Get total number of EDGEs on New Geometry 4758 int totalNumEdgeNew; 4759 ego *eobjsNew; 4760 if (islite) { 4761 PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 4762 EGlite_free(eobjsNew); 4763 } else { 4764 PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 4765 EG_free(eobjsNew); 4766 } 4767 4768 // Initialize EDGE ID equivalent vector 4769 // FORMAT :: vector index is the Original Geometry's EDGE ID, the vector Value is the New Geometry's EDGE ID 4770 int edgeIDEquiv[totalNumEdge + 1]; 4771 4772 // Find Equivalent EDGEs 4773 for (int ii = 0; ii < Nf; ++ii) { 4774 // Get Original Geometry EDGE's NODEs 4775 int numOrigEdge, numNewEdge; 4776 if (islite) { 4777 PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 4778 PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 4779 } else { 4780 PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 4781 PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 4782 } 4783 4784 // new loop below 4785 for (int nn = 0; nn < numOrigEdge; ++nn) { 4786 ego origEdge = eobjsOrig[nn]; 4787 ego geomEdgeOrig, *nobjsOrig; 4788 int oclassEdgeOrig, mtypeEdgeOrig; 4789 int NnOrig, *nsensesEdgeOrig; 4790 4791 if (islite) PetscCallEGADS(EGlite_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 4792 else PetscCallEGADS(EG_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 4793 4794 PetscBool isSame = PETSC_FALSE; 4795 for (int jj = 0; jj < numNewEdge; ++jj) { 4796 ego newEdge = eobjsNew[jj]; 4797 ego geomEdgeNew, *nobjsNew; 4798 int oclassEdgeNew, mtypeEdgeNew; 4799 int NnNew, *nsensesEdgeNew; 4800 4801 if (islite) PetscCallEGADS(EGlite_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 4802 else PetscCallEGADS(EG_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 4803 4804 if (mtypeEdgeOrig == mtypeEdgeNew) { 4805 // Only operate if the EDGE types are the same 4806 for (int kk = 0; kk < NnNew; ++kk) { 4807 int nodeIDOrigGeom, nodeIDNewGeom; 4808 if (islite) { 4809 nodeIDOrigGeom = EGlite_indexBodyTopo(body, nobjsOrig[kk]); 4810 nodeIDNewGeom = EGlite_indexBodyTopo(newbody, nobjsNew[kk]); 4811 } else { 4812 nodeIDOrigGeom = EG_indexBodyTopo(body, nobjsOrig[kk]); 4813 nodeIDNewGeom = EG_indexBodyTopo(newbody, nobjsNew[kk]); 4814 } 4815 4816 if (nodeIDNewGeom == nodeIDEquiv[nodeIDOrigGeom]) { 4817 isSame = PETSC_TRUE; 4818 } else { 4819 isSame = PETSC_FALSE; 4820 kk = NnNew; // skip ahead because first NODE failed test and order is important 4821 } 4822 } 4823 4824 if (isSame == PETSC_TRUE) { 4825 int edgeIDOrig, edgeIDNew; 4826 if (islite) { 4827 edgeIDOrig = EGlite_indexBodyTopo(body, origEdge); 4828 edgeIDNew = EGlite_indexBodyTopo(newbody, newEdge); 4829 } else { 4830 edgeIDOrig = EG_indexBodyTopo(body, origEdge); 4831 edgeIDNew = EG_indexBodyTopo(newbody, newEdge); 4832 } 4833 4834 edgeIDEquiv[edgeIDOrig] = edgeIDNew; 4835 jj = numNewEdge; 4836 } 4837 } 4838 } 4839 } 4840 if (islite) { 4841 EGlite_free(eobjsOrig); 4842 EGlite_free(eobjsNew); 4843 } else { 4844 EG_free(eobjsOrig); 4845 EG_free(eobjsNew); 4846 } 4847 } 4848 if (islite) { 4849 EGlite_free(fobjs); 4850 EGlite_free(nfobjs); 4851 } else { 4852 EG_free(fobjs); 4853 EG_free(nfobjs); 4854 } 4855 4856 // Modify labels to point to the IDs on the new Geometry 4857 IS isNodeID, isEdgeID; 4858 4859 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 4860 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 4861 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4862 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 4863 4864 PetscCall(ISCreateGeneral(comm, totalNumNode + 1, nodeIDEquiv, PETSC_COPY_VALUES, &isNodeID)); 4865 PetscCall(ISCreateGeneral(comm, totalNumEdge + 1, edgeIDEquiv, PETSC_COPY_VALUES, &isEdgeID)); 4866 /* Do not perform check. Np may != Nv due to Degenerate Geometry which is not stored in labels. */ 4867 /* We do not know in advance which IDs have been omitted. This may also change due to geometry modifications. */ 4868 PetscCall(DMLabelRewriteValues(vertexLabel, isNodeID)); 4869 PetscCall(DMLabelRewriteValues(edgeLabel, isEdgeID)); 4870 PetscCall(ISDestroy(&isNodeID)); 4871 PetscCall(ISDestroy(&isEdgeID)); 4872 4873 // Attempt to point to the new geometry 4874 PetscCallEGADS(EG_deleteObject, (model)); 4875 PetscCall(PetscContainerSetPointer(modelObj, newmodel)); 4876 4877 // save updated model to file 4878 if (saveGeom == PETSC_TRUE && stpName != NULL) PetscCall(EG_saveModel(newmodel, stpName)); 4879 4880 // Inflate Mesh to EGADS Model 4881 if (autoInflate == PETSC_TRUE) PetscCall(DMPlexInflateToGeomModel(dm, PETSC_TRUE)); 4882 PetscFunctionReturn(PETSC_SUCCESS); 4883 #else 4884 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 4885 #endif 4886 } 4887 4888 /*@C 4889 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. 4890 4891 Collective 4892 4893 Input Parameter: 4894 . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 4895 4896 Level: intermediate 4897 4898 .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 4899 @*/ 4900 PetscErrorCode DMPlexGetGeomModelTUV(DM dm) PeNS 4901 { 4902 #if defined(PETSC_HAVE_EGADS) 4903 /* EGADS Variables */ 4904 ego model, geom, body, face, edge; 4905 ego *bodies; 4906 int Nb, oclass, mtype, *senses; 4907 double result[4]; 4908 /* PETSc Variables */ 4909 DM cdm; 4910 PetscContainer modelObj; 4911 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 4912 Vec coordinates; 4913 PetscScalar *coords; 4914 PetscInt bodyID, faceID, edgeID, vertexID; 4915 PetscInt cdim, vStart, vEnd, v; 4916 PetscBool islite = PETSC_FALSE; 4917 #endif 4918 4919 PetscFunctionBegin; 4920 #if defined(PETSC_HAVE_EGADS) 4921 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 4922 if (!modelObj) { 4923 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 4924 islite = PETSC_TRUE; 4925 } 4926 if (!modelObj) PetscFunctionReturn(0); 4927 4928 PetscCall(DMGetCoordinateDim(dm, &cdim)); 4929 PetscCall(DMGetCoordinateDM(dm, &cdm)); 4930 PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 4931 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 4932 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 4933 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4934 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 4935 4936 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 4937 4938 if (islite) PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4939 else PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4940 4941 PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 4942 PetscCall(VecGetArrayWrite(coordinates, &coords)); 4943 4944 // Define t, u, v arrays to be stored in a PetscContainer after populated 4945 PetscScalar *t_point, *u_point, *v_point; 4946 PetscCall(PetscMalloc1(vEnd - vStart, &t_point)); 4947 PetscCall(PetscMalloc1(vEnd - vStart, &u_point)); 4948 PetscCall(PetscMalloc1(vEnd - vStart, &v_point)); 4949 4950 for (v = vStart; v < vEnd; ++v) { 4951 PetscScalar *vcoords; 4952 4953 PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 4954 PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 4955 PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 4956 PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 4957 4958 // TODO Figure out why this is unknown sometimes 4959 if (bodyID < 0 && Nb == 1) bodyID = 0; 4960 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); 4961 body = bodies[bodyID]; 4962 4963 PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 4964 if (edgeID > 0) { 4965 /* Snap to EDGE at nearest location */ 4966 double params[1]; 4967 4968 if (islite) { 4969 PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 4970 PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 4971 } // Get (t) of nearest point on EDGE 4972 else { 4973 PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 4974 PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 4975 } // Get (t) of nearest point on EDGE 4976 4977 t_point[v - vStart] = params[0]; 4978 u_point[v - vStart] = 0.0; 4979 v_point[v - vStart] = 0.0; 4980 } else if (faceID > 0) { 4981 /* Snap to FACE at nearest location */ 4982 double params[2]; 4983 4984 if (islite) { 4985 PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 4986 PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 4987 } // Get (x,y,z) of nearest point on FACE 4988 else { 4989 PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 4990 PetscCall(EG_invEvaluate(face, vcoords, params, result)); 4991 } // Get (x,y,z) of nearest point on FACE 4992 4993 t_point[v - vStart] = 0.0; 4994 u_point[v - vStart] = params[0]; 4995 v_point[v - vStart] = params[1]; 4996 } else { 4997 t_point[v - vStart] = 0.0; 4998 u_point[v - vStart] = 0.0; 4999 v_point[v - vStart] = 0.0; 5000 } 5001 } 5002 PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 5003 /* Clear out global coordinates */ 5004 PetscCall(VecDestroy(&dm->coordinates[0].x)); 5005 5006 /* Store in PetscContainters */ 5007 { 5008 PetscContainer t_pointObj, u_pointObj, v_pointObj; 5009 5010 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 5011 if (!t_pointObj) { 5012 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &t_pointObj)); 5013 PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 5014 PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Edge t Parameter", (PetscObject)t_pointObj)); 5015 PetscCall(PetscContainerSetCtxDestroy(t_pointObj, PetscCtxDestroyDefault)); 5016 PetscCall(PetscContainerDestroy(&t_pointObj)); 5017 } else { 5018 void *old; 5019 5020 PetscCall(PetscContainerGetPointer(t_pointObj, &old)); 5021 PetscCall(PetscFree(old)); 5022 PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 5023 } 5024 5025 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 5026 if (!u_pointObj) { 5027 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &u_pointObj)); 5028 PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 5029 PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face u Parameter", (PetscObject)u_pointObj)); 5030 PetscCall(PetscContainerSetCtxDestroy(u_pointObj, PetscCtxDestroyDefault)); 5031 PetscCall(PetscContainerDestroy(&u_pointObj)); 5032 } else { 5033 void *old; 5034 5035 PetscCall(PetscContainerGetPointer(u_pointObj, &old)); 5036 PetscCall(PetscFree(old)); 5037 PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 5038 } 5039 5040 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 5041 if (!v_pointObj) { 5042 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &v_pointObj)); 5043 PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 5044 PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face v Parameter", (PetscObject)v_pointObj)); 5045 PetscCall(PetscContainerSetCtxDestroy(v_pointObj, PetscCtxDestroyDefault)); 5046 PetscCall(PetscContainerDestroy(&v_pointObj)); 5047 } else { 5048 void *old; 5049 5050 PetscCall(PetscContainerGetPointer(v_pointObj, &old)); 5051 PetscCall(PetscFree(old)); 5052 PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 5053 } 5054 } 5055 #endif 5056 PetscFunctionReturn(PETSC_SUCCESS); 5057 } 5058 5059 /*@C 5060 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(). 5061 5062 Collective 5063 5064 Input Parameter: 5065 . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 5066 5067 Level: intermediate 5068 5069 Note: 5070 The updated DM object inflated to the associated underlying geometry. This updates the [x, y, z] coordinates of DM points associated with geometry. 5071 5072 .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()`, `DMPlexGetGeomModelTUV()` 5073 @*/ 5074 PetscErrorCode DMPlexInflateToGeomModelUseTUV(DM dm) PeNS 5075 { 5076 #if defined(PETSC_HAVE_EGADS) 5077 /* EGADS Variables */ 5078 ego model, geom, body, face, edge, vertex; 5079 ego *bodies; 5080 int Nb, oclass, mtype, *senses; 5081 double result[18], params[2]; 5082 /* PETSc Variables */ 5083 DM cdm; 5084 PetscContainer modelObj; 5085 PetscContainer t_pointObj, u_pointObj, v_pointObj; 5086 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 5087 Vec coordinates; 5088 PetscScalar *coords; 5089 PetscScalar *t_point, *u_point, *v_point; 5090 PetscInt bodyID, faceID, edgeID, vertexID; 5091 PetscInt cdim, d, vStart, vEnd, v; 5092 PetscBool islite = PETSC_FALSE; 5093 #endif 5094 5095 PetscFunctionBegin; 5096 #if defined(PETSC_HAVE_EGADS) 5097 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5098 if (!modelObj) { 5099 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5100 islite = PETSC_TRUE; 5101 } 5102 5103 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 5104 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 5105 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 5106 5107 if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 5108 if (!t_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5109 if (!u_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5110 if (!v_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5111 5112 PetscCall(DMGetCoordinateDim(dm, &cdim)); 5113 PetscCall(DMGetCoordinateDM(dm, &cdm)); 5114 PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 5115 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 5116 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 5117 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 5118 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 5119 5120 PetscCall(PetscContainerGetPointer(t_pointObj, (void **)&t_point)); 5121 PetscCall(PetscContainerGetPointer(u_pointObj, (void **)&u_point)); 5122 PetscCall(PetscContainerGetPointer(v_pointObj, (void **)&v_point)); 5123 5124 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 5125 5126 if (islite) { 5127 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 5128 } else { 5129 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 5130 } 5131 5132 PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 5133 PetscCall(VecGetArrayWrite(coordinates, &coords)); 5134 5135 for (v = vStart; v < vEnd; ++v) { 5136 PetscScalar *vcoords; 5137 5138 PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 5139 PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 5140 PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 5141 PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 5142 5143 // TODO Figure out why this is unknown sometimes 5144 if (bodyID < 0 && Nb == 1) bodyID = 0; 5145 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); 5146 body = bodies[bodyID]; 5147 5148 PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 5149 if (vertexID > 0) { 5150 /* Snap to Vertices */ 5151 if (islite) { 5152 PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 5153 PetscCall(EGlite_evaluate(vertex, NULL, result)); 5154 } else { 5155 PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 5156 PetscCall(EG_evaluate(vertex, NULL, result)); 5157 } 5158 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5159 } else if (edgeID > 0) { 5160 /* Snap to EDGE */ 5161 params[0] = t_point[v - vStart]; 5162 if (islite) { 5163 PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 5164 PetscCall(EGlite_evaluate(edge, params, result)); 5165 } else { 5166 PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 5167 PetscCall(EG_evaluate(edge, params, result)); 5168 } 5169 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5170 } else if (faceID > 0) { 5171 /* Snap to FACE */ 5172 params[0] = u_point[v - vStart]; 5173 params[1] = v_point[v - vStart]; 5174 if (islite) { 5175 PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 5176 PetscCall(EGlite_evaluate(face, params, result)); 5177 } else { 5178 PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 5179 PetscCall(EG_evaluate(face, params, result)); 5180 } 5181 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5182 } 5183 } 5184 PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 5185 /* Clear out global coordinates */ 5186 PetscCall(VecDestroy(&dm->coordinates[0].x)); 5187 #endif 5188 PetscFunctionReturn(PETSC_SUCCESS); 5189 } 5190 5191 /*@ 5192 DMPlexInflateToGeomModel - Wrapper function allowing two methods for inflating refined meshes to the underlying geometric domain. 5193 5194 Collective 5195 5196 Input Parameters: 5197 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5198 - useTUV - PetscBool indicating if the user would like to inflate the DMPlex to the underlying geometry 5199 using (t) for nodes on EDGEs and (u, v) for nodes on FACEs or using the nodes (x, y, z) coordinates 5200 and shortest distance routine. 5201 If useTUV = PETSC_TRUE, use the (t) or (u, v) parameters to inflate the DMPlex to the CAD geometry. 5202 If useTUV = PETSC_FALSE, use the nodes (x, y, z) coordinates and the shortest disctance routine. 5203 5204 Notes: 5205 DM with nodal coordinates modified so that they lie on the EDGEs and FACEs of the underlying geometry. 5206 5207 (t) and (u, v) parameters for all DMPlex nodes on EDGEs and FACEs are stored in arrays within PetscContainers attached to the DM. 5208 The containers have names "Point - Edge t Parameter", "Point - Face u Parameter", and "Point - Face v Parameter". 5209 The arrays are organized by Point 0-based ID (i.e. [v-vstart] as defined in the DMPlex. 5210 5211 Level: intermediate 5212 5213 .seealso: `DMPlexGetGeomModelTUV()`, `DMPlexInflateToGeomModelUseTUV()`, `DMPlexInflateToGeomModelUseXYZ()` 5214 @*/ 5215 PetscErrorCode DMPlexInflateToGeomModel(DM dm, PetscBool useTUV) PeNS 5216 { 5217 PetscFunctionBeginHot; 5218 if (useTUV) { 5219 PetscCall(DMPlexGetGeomModelTUV(dm)); 5220 PetscCall(DMPlexInflateToGeomModelUseTUV(dm)); 5221 } else { 5222 PetscCall(DMPlexInflateToGeomModelUseXYZ(dm)); 5223 } 5224 PetscFunctionReturn(PETSC_SUCCESS); 5225 } 5226 5227 #ifdef PETSC_HAVE_EGADS 5228 /*@C 5229 DMPlexGetGeomModelBodies - Returns an array of PetscGeom BODY objects attached to the referenced geomtric model entity as well as the number of BODYs. 5230 5231 Collective 5232 5233 Input Parameter: 5234 . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5235 5236 Output Parameters: 5237 + bodies - Array of PetscGeom BODY objects referenced by the geometric model. 5238 - numBodies - Number of BODYs referenced by the geometric model. Also the size of **bodies array. 5239 5240 Level: intermediate 5241 5242 .seealso: 5243 @*/ 5244 PetscErrorCode DMPlexGetGeomModelBodies(DM dm, PetscGeom **bodies, PetscInt *numBodies) PeNS 5245 { 5246 PetscFunctionBeginHot; 5247 PetscContainer modelObj; 5248 PetscBool islite = PETSC_FALSE; 5249 ego model, geom; 5250 int oclass, mtype; 5251 int *senses; 5252 5253 /* Determine which type of EGADS model is attached to the DM */ 5254 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5255 if (!modelObj) { 5256 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5257 islite = PETSC_TRUE; 5258 } 5259 5260 // Get attached EGADS or EGADSlite model (pointer) 5261 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 5262 5263 if (islite) { 5264 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 5265 } else { 5266 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 5267 } 5268 PetscFunctionReturn(PETSC_SUCCESS); 5269 } 5270 5271 /*@C 5272 DMPlexGetGeomModelBodyShells - Returns an array of PetscGeom SHELL objects attached to the referenced BODY geomtric entity as well as the number of SHELLs. 5273 5274 Collective 5275 5276 Input Parameters: 5277 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5278 - body - PetscGeom BODY object containing the SHELL objects of interest. 5279 5280 Output Parameters: 5281 + shells - Array of PetscGeom SHELL objects referenced by the PetscGeom BODY object 5282 - numShells - Number of SHELLs referenced by the PetscGeom BODY object. Also the size of **shells array. 5283 5284 Level: intermediate 5285 5286 .seealso: 5287 @*/ 5288 PetscErrorCode DMPlexGetGeomModelBodyShells(DM dm, PetscGeom body, PetscGeom **shells, PetscInt *numShells) PeNS 5289 { 5290 PetscFunctionBeginHot; 5291 #ifdef PETSC_HAVE_EGADS 5292 PetscContainer modelObj; 5293 PetscBool islite = PETSC_FALSE; 5294 5295 /* Determine which type of EGADS model is attached to the DM */ 5296 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5297 if (!modelObj) { 5298 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5299 islite = PETSC_TRUE; 5300 } 5301 5302 if (islite) { 5303 PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, numShells, shells)); 5304 } else { 5305 PetscCall(EG_getBodyTopos(body, NULL, SHELL, numShells, shells)); 5306 } 5307 #endif 5308 PetscFunctionReturn(PETSC_SUCCESS); 5309 } 5310 5311 /*@C 5312 DMPlexGetGeomModelBodyFaces - Returns an array of PetscGeom FACE objects attached to the referenced BODY geomtric entity as well as the number of FACEs. 5313 5314 Collective 5315 5316 Input Parameters: 5317 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5318 - body - PetscGeom BODY object containing the FACE objects of interest. 5319 5320 Output Parameters: 5321 + faces - Array of PetscGeom FACE objects referenced by the PetscGeom BODY object 5322 - numFaces - Number of FACEs referenced by the PetscGeom BODY object. Also the size of **faces array. 5323 5324 Level: intermediate 5325 5326 .seealso: 5327 @*/ 5328 PetscErrorCode DMPlexGetGeomModelBodyFaces(DM dm, PetscGeom body, PetscGeom **faces, PetscInt *numFaces) PeNS 5329 { 5330 PetscFunctionBeginHot; 5331 #ifdef PETSC_HAVE_EGADS 5332 PetscContainer modelObj; 5333 PetscBool islite = PETSC_FALSE; 5334 5335 /* Determine which type of EGADS model is attached to the DM */ 5336 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5337 if (!modelObj) { 5338 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5339 islite = PETSC_TRUE; 5340 } 5341 5342 if (islite) { 5343 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, numFaces, faces)); 5344 } else { 5345 PetscCall(EG_getBodyTopos(body, NULL, FACE, numFaces, faces)); 5346 } 5347 #endif 5348 PetscFunctionReturn(PETSC_SUCCESS); 5349 } 5350 5351 /*@C 5352 DMPlexGetGeomModelBodyLoops - Returns an array of PetscGeom Loop objects attached to the referenced BODY geomtric entity as well as the number of LOOPs. 5353 5354 Collective 5355 5356 Input Parameters: 5357 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5358 - body - PetscGeom BODY object containing the LOOP objects of interest. 5359 5360 Output Parameters: 5361 + loops - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 5362 - numLoops - Number of LOOPs referenced by the PetscGeom BODY object. Also the size of **loops array. 5363 5364 Level: intermediate 5365 5366 .seealso: 5367 @*/ 5368 PetscErrorCode DMPlexGetGeomModelBodyLoops(DM dm, PetscGeom body, PetscGeom **loops, PetscInt *numLoops) PeNS 5369 { 5370 PetscFunctionBeginHot; 5371 #ifdef PETSC_HAVE_EGADS 5372 PetscContainer modelObj; 5373 PetscBool islite = PETSC_FALSE; 5374 5375 /* Determine which type of EGADS model is attached to the DM */ 5376 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5377 if (!modelObj) { 5378 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5379 islite = PETSC_TRUE; 5380 } 5381 5382 if (islite) { 5383 PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 5384 } else { 5385 PetscCall(EG_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 5386 } 5387 #endif 5388 PetscFunctionReturn(PETSC_SUCCESS); 5389 } 5390 5391 /*@C 5392 DMPlexGetGeomModelShellFaces - Returns an array of PetscGeom FACE objects attached to the referenced SHELL geomtric entity as well as the number of FACEs. 5393 5394 Collective 5395 5396 Input Parameters: 5397 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5398 . body - PetscGeom BODY object containing the FACE objects of interest. 5399 - shell - PetscGeom SHELL object with FACEs of interest. 5400 5401 Output Parameters: 5402 + faces - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 5403 - numFaces - Number of FACEs referenced by the PetscGeom SHELL object. Also the size of **faces array. 5404 5405 Level: intermediate 5406 5407 .seealso: 5408 @*/ 5409 PetscErrorCode DMPlexGetGeomModelShellFaces(DM dm, PetscGeom body, PetscGeom shell, PetscGeom **faces, PetscInt *numFaces) PeNS 5410 { 5411 PetscFunctionBeginHot; 5412 #ifdef PETSC_HAVE_EGADS 5413 PetscContainer modelObj; 5414 PetscBool islite = PETSC_FALSE; 5415 5416 /* Determine which type of EGADS model is attached to the DM */ 5417 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5418 if (!modelObj) { 5419 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5420 islite = PETSC_TRUE; 5421 } 5422 5423 if (islite) { 5424 PetscCall(EGlite_getBodyTopos(body, shell, FACE, numFaces, faces)); 5425 } else { 5426 PetscCall(EG_getBodyTopos(body, shell, FACE, numFaces, faces)); 5427 } 5428 #endif 5429 PetscFunctionReturn(PETSC_SUCCESS); 5430 } 5431 5432 /*@C 5433 DMPlexGetGeomModelFaceLoops - Returns an array of PetscGeom LOOP objects attached to the referenced FACE geomtric entity as well as the number of LOOPs. 5434 5435 Collective 5436 5437 Input Parameters: 5438 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5439 . body - PetscGeom BODY object containing the LOOP objects of interest. 5440 - face - PetscGeom FACE object with LOOPs of interest. 5441 5442 Output Parameters: 5443 + loops - Array of PetscGeom LOOP objects referenced by the PetscGeom FACE object 5444 - numLoops - Number of LOOPs referenced by the PetscGeom FACE object. Also the size of **loops array. 5445 5446 Level: intermediate 5447 5448 .seealso: 5449 @*/ 5450 PetscErrorCode DMPlexGetGeomModelFaceLoops(DM dm, PetscGeom body, PetscGeom face, PetscGeom **loops, PetscInt *numLoops) PeNS 5451 { 5452 PetscFunctionBeginHot; 5453 #ifdef PETSC_HAVE_EGADS 5454 PetscContainer modelObj; 5455 PetscBool islite = PETSC_FALSE; 5456 5457 /* Determine which type of EGADS model is attached to the DM */ 5458 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5459 if (!modelObj) { 5460 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5461 islite = PETSC_TRUE; 5462 } 5463 5464 if (islite) { 5465 PetscCall(EGlite_getBodyTopos(body, face, LOOP, numLoops, loops)); 5466 } else { 5467 PetscCall(EG_getBodyTopos(body, face, LOOP, numLoops, loops)); 5468 } 5469 #endif 5470 PetscFunctionReturn(PETSC_SUCCESS); 5471 } 5472 5473 /*@C 5474 DMPlexGetGeomModelFaceEdges - Returns an array of PetscGeom EDGE objects attached to the referenced FACE geomtric entity as well as the number of EDGEs. 5475 5476 Collective 5477 5478 Input Parameters: 5479 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5480 . body - PetscGeom Body object containing the EDGE objects of interest. 5481 - face - PetscGeom FACE object with EDGEs of interest. 5482 5483 Output Parameters: 5484 + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom FACE object 5485 - numEdges - Number of EDGEs referenced by the PetscGeom FACE object. Also the size of **edges array. 5486 5487 Level: intermediate 5488 5489 .seealso: 5490 @*/ 5491 PetscErrorCode DMPlexGetGeomModelFaceEdges(DM dm, PetscGeom body, PetscGeom face, PetscGeom **edges, PetscInt *numEdges) PeNS 5492 { 5493 PetscFunctionBeginHot; 5494 #ifdef PETSC_HAVE_EGADS 5495 PetscContainer modelObj; 5496 PetscBool islite = PETSC_FALSE; 5497 5498 /* Determine which type of EGADS model is attached to the DM */ 5499 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5500 if (!modelObj) { 5501 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5502 islite = PETSC_TRUE; 5503 } 5504 5505 if (islite) { 5506 PetscCall(EGlite_getBodyTopos(body, face, EDGE, numEdges, edges)); 5507 } else { 5508 PetscCall(EG_getBodyTopos(body, face, EDGE, numEdges, edges)); 5509 } 5510 #endif 5511 PetscFunctionReturn(PETSC_SUCCESS); 5512 } 5513 5514 /*@C 5515 DMPlexGetGeomModelBodyEdges - Returns an array of PetscGeom EDGE objects attached to the referenced BODY geomtric entity as well as the number of EDGEs. 5516 5517 Collective 5518 5519 Input Parameters: 5520 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5521 - body - PetscGeom body object of interest. 5522 5523 Output Parameters: 5524 + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom BODY object 5525 - numEdges - Number of EDGEs referenced by the PetscGeom BODY object. Also the size of **edges array. 5526 5527 Level: intermediate 5528 5529 .seealso: 5530 @*/ 5531 PetscErrorCode DMPlexGetGeomModelBodyEdges(DM dm, PetscGeom body, PetscGeom **edges, PetscInt *numEdges) PeNS 5532 { 5533 PetscFunctionBeginHot; 5534 #ifdef PETSC_HAVE_EGADS 5535 PetscContainer modelObj; 5536 PetscBool islite = PETSC_FALSE; 5537 5538 /* Determine which type of EGADS model is attached to the DM */ 5539 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5540 if (!modelObj) { 5541 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5542 islite = PETSC_TRUE; 5543 } 5544 5545 if (islite) { 5546 PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 5547 } else { 5548 PetscCall(EG_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 5549 } 5550 #endif 5551 PetscFunctionReturn(PETSC_SUCCESS); 5552 } 5553 5554 /*@C 5555 DMPlexGetGeomModelBodyNodes - Returns an array of PetscGeom NODE objects attached to the referenced BODY geomtric entity as well as the number of NODES. 5556 5557 Collective 5558 5559 Input Parameters: 5560 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5561 - body - PetscGeom body object of interest. 5562 5563 Output Parameters: 5564 + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom BODY object 5565 - numNodes - Number of NODEs referenced by the PetscGeom BODY object. Also the size of **nodes array. 5566 5567 Level: intermediate 5568 5569 .seealso: 5570 @*/ 5571 PetscErrorCode DMPlexGetGeomModelBodyNodes(DM dm, PetscGeom body, PetscGeom **nodes, PetscInt *numNodes) PeNS 5572 { 5573 PetscFunctionBeginHot; 5574 #ifdef PETSC_HAVE_EGADS 5575 PetscContainer modelObj; 5576 PetscBool islite = PETSC_FALSE; 5577 5578 /* Determine which type of EGADS model is attached to the DM */ 5579 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5580 if (!modelObj) { 5581 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5582 islite = PETSC_TRUE; 5583 } 5584 5585 if (islite) { 5586 PetscCall(EGlite_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 5587 } else { 5588 PetscCall(EG_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 5589 } 5590 #endif 5591 PetscFunctionReturn(PETSC_SUCCESS); 5592 } 5593 5594 /*@C 5595 DMPlexGetGeomModelEdgeNodes - Returns an array of PetscGeom NODE objects attached to the referenced EDGE geomtric entity as well as the number of NODES. 5596 5597 Collective 5598 5599 Input Parameters: 5600 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5601 . body - PetscGeom body object containing the EDGE object of interest. 5602 - edge - PetscGeom EDGE object with NODEs of interest. 5603 5604 Output Parameters: 5605 + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom EDGE object 5606 - numNodes - Number of Nodes referenced by the PetscGeom EDGE object. Also the size of **nodes array. 5607 5608 Level: intermediate 5609 5610 .seealso: 5611 @*/ 5612 PetscErrorCode DMPlexGetGeomModelEdgeNodes(DM dm, PetscGeom body, PetscGeom edge, PetscGeom **nodes, PetscInt *numNodes) PeNS 5613 { 5614 PetscFunctionBeginHot; 5615 #ifdef PETSC_HAVE_EGADS 5616 PetscContainer modelObj; 5617 PetscBool islite = PETSC_FALSE; 5618 5619 /* Determine which type of EGADS model is attached to the DM */ 5620 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5621 if (!modelObj) { 5622 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5623 islite = PETSC_TRUE; 5624 } 5625 5626 if (islite) { 5627 PetscCall(EGlite_getBodyTopos(body, edge, NODE, numNodes, nodes)); 5628 } else { 5629 PetscCall(EG_getBodyTopos(body, edge, NODE, numNodes, nodes)); 5630 } 5631 #endif 5632 PetscFunctionReturn(PETSC_SUCCESS); 5633 } 5634 5635 /*@C 5636 DMPlexGetGeomID - Returns ID number of the entity in the geometric (CAD) model 5637 5638 Collective 5639 5640 Input Parameters: 5641 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5642 . body - PetscGeom body object containing the lower level entity the ID number is being requested. 5643 - topoObj - PetscGeom SHELL, FACE, LOOP, EDGE, or NODE object for which ID number is being requested. 5644 5645 Output Parameter: 5646 . id - ID number of the entity 5647 5648 Level: intermediate 5649 5650 .seealso: 5651 @*/ 5652 PetscErrorCode DMPlexGetGeomID(DM dm, PetscGeom body, PetscGeom topoObj, PetscInt *id) PeNS 5653 { 5654 PetscFunctionBeginHot; 5655 #ifdef PETSC_HAVE_EGADS 5656 PetscContainer modelObj; 5657 PetscBool islite = PETSC_FALSE; 5658 int topoID; 5659 5660 /* Determine which type of EGADS model is attached to the DM */ 5661 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5662 if (!modelObj) { 5663 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5664 islite = PETSC_TRUE; 5665 } 5666 5667 // Get Topology Object's ID 5668 if (islite) { 5669 topoID = EGlite_indexBodyTopo(body, topoObj); 5670 } else { 5671 topoID = EG_indexBodyTopo(body, topoObj); 5672 } 5673 5674 *id = topoID; 5675 #endif 5676 PetscFunctionReturn(PETSC_SUCCESS); 5677 } 5678 5679 /*@C 5680 DMPlexGetGeomObject - Returns Geometry Object using the objects ID in the geometric (CAD) model 5681 5682 Collective 5683 5684 Input Parameters: 5685 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5686 . body - PetscGeom body object containing the lower level entity the referenced by the ID. 5687 . geomType - Keyword SHELL, FACE, LOOP, EDGE, or NODE of the geometry type for which ID number is being requested. 5688 - geomID - ID number of the geometry entity being requested. 5689 5690 Output Parameter: 5691 . geomObj - Geometry Object referenced by the ID number requested. 5692 5693 Level: intermediate 5694 5695 .seealso: 5696 @*/ 5697 PetscErrorCode DMPlexGetGeomObject(DM dm, PetscGeom body, PetscInt geomType, PetscInt geomID, PetscGeom *geomObj) PeNS 5698 { 5699 PetscFunctionBeginHot; 5700 #ifdef PETSC_HAVE_EGADS 5701 PetscContainer modelObj; 5702 PetscBool islite = PETSC_FALSE; 5703 5704 /* Determine which type of EGADS model is attached to the DM */ 5705 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5706 if (!modelObj) { 5707 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5708 islite = PETSC_TRUE; 5709 } 5710 5711 // Get Topology Object's ID 5712 if (islite) { 5713 PetscCall(EGlite_objectBodyTopo(body, geomType, geomID, geomObj)); 5714 } else { 5715 PetscCall(EG_objectBodyTopo(body, geomType, geomID, geomObj)); 5716 } 5717 #endif 5718 PetscFunctionReturn(PETSC_SUCCESS); 5719 } 5720 5721 /*@C 5722 DMPlexGetGeomFaceNumOfControlPoints - Returns the total number of Control Points (and associated Weights) defining a FACE of a Geometry 5723 5724 Not collective 5725 5726 Input Parameters: 5727 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5728 - face - PetscGeom FACE object 5729 5730 Output Parameter: 5731 . numCntrlPnts - Number of Control Points (and Weights) defining the FACE 5732 5733 Level: intermediate 5734 5735 .seealso: 5736 @*/ 5737 PetscErrorCode DMPlexGetGeomFaceNumOfControlPoints(DM dm, PetscGeom face, PetscInt *numCntrlPnts) PeNS 5738 { 5739 PetscFunctionBeginHot; 5740 #ifdef PETSC_HAVE_EGADS 5741 PetscContainer modelObj; 5742 PetscBool islite = PETSC_FALSE; 5743 PetscGeom geom, gRef; 5744 PetscGeom *lobjs; 5745 int Nl, oclass, mtype, goclass, gmtype; 5746 int *lsenses, *gpinfo; 5747 double *gprv; 5748 5749 /* Determine which type of EGADS model is attached to the DM */ 5750 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5751 if (!modelObj) { 5752 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5753 islite = PETSC_TRUE; 5754 } 5755 5756 // Get Total Number of Control Points on FACE 5757 if (islite) { 5758 PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 5759 PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 5760 } else { 5761 PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 5762 PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 5763 } 5764 5765 *numCntrlPnts = gpinfo[2] * gpinfo[5]; 5766 #endif 5767 PetscFunctionReturn(PETSC_SUCCESS); 5768 } 5769 5770 /*@C 5771 DMPlexGetGeomBodyMassProperties - Returns the Volume, Surface Area, Center of Gravity, and Inertia about the Body's Center of Gravity 5772 5773 Not collective 5774 5775 Input Parameters: 5776 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5777 - body - PetscGeom BODY object 5778 5779 Output Parameters: 5780 + volume - Volume of the CAD Body attached to the DM Plex 5781 . surfArea - Surface Area of the CAD Body attached to the DM Plex 5782 . centerOfGravity - Array with the Center of Gravity coordinates of the CAD Body attached to the DM Plex [x, y, z] 5783 . COGszie - Size of centerOfGravity[] Array 5784 . inertiaMatrixCOG - Array containing the Inertia about the Body's Center of Gravity [Ixx, Ixy, Ixz, Iyx, Iyy, Iyz, Izx, Izy, Izz] 5785 - IMCOGsize - Size of inertiaMatrixCOG[] Array 5786 5787 Level: intermediate 5788 5789 .seealso: 5790 @*/ 5791 PetscErrorCode DMPlexGetGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) PeNS 5792 { 5793 PetscFunctionBeginHot; 5794 #ifdef PETSC_HAVE_EGADS 5795 PetscContainer modelObj; 5796 PetscBool islite = PETSC_FALSE; 5797 PetscScalar geomData[14]; 5798 5799 /* Determine which type of EGADS model is attached to the DM */ 5800 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5801 if (!modelObj) { 5802 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5803 islite = PETSC_TRUE; 5804 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"); 5805 } 5806 5807 if (islite) { 5808 PetscCall(PetscPrintf(PETSC_COMM_SELF, " WARNING!! This functionality is not supported for EGADSlite files. \n")); 5809 PetscCall(PetscPrintf(PETSC_COMM_SELF, " All returned values are equal to 0 \n")); 5810 } else { 5811 PetscCall(EG_getMassProperties(body, geomData)); 5812 } 5813 5814 PetscCall(PetscMalloc2(3, centerOfGravity, 9, inertiaMatrixCOG)); 5815 5816 if (!islite) { 5817 *volume = geomData[0]; 5818 *surfArea = geomData[1]; 5819 for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = geomData[ii]; } 5820 *COGsize = 3; 5821 for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = geomData[ii]; } 5822 *IMCOGsize = 9; 5823 } else { 5824 *volume = 0.; 5825 *surfArea = 0.; 5826 for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = 0.; } 5827 *COGsize = 0; 5828 for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = 0.; } 5829 *IMCOGsize = 0; 5830 } 5831 #endif 5832 PetscFunctionReturn(PETSC_SUCCESS); 5833 } 5834 5835 PetscErrorCode DMPlexRestoreGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) PeNS 5836 { 5837 PetscFunctionBegin; 5838 PetscCall(PetscFree2(*centerOfGravity, *inertiaMatrixCOG)); 5839 PetscFunctionReturn(PETSC_SUCCESS); 5840 } 5841 5842 /*@C 5843 DMPlexFreeGeomObject - Frees PetscGeom Objects 5844 5845 Not collective 5846 5847 Input Parameters: 5848 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5849 - geomObj - PetscGeom object 5850 5851 Level: intermediate 5852 5853 .seealso: 5854 @*/ 5855 PetscErrorCode DMPlexFreeGeomObject(DM dm, PetscGeom *geomObj) PeNS 5856 { 5857 PetscFunctionBeginHot; 5858 #ifdef PETSC_HAVE_EGADS 5859 PetscContainer modelObj; 5860 PetscBool islite = PETSC_FALSE; 5861 5862 /* Determine which type of EGADS model is attached to the DM */ 5863 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5864 if (!modelObj) { 5865 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5866 islite = PETSC_TRUE; 5867 } 5868 5869 if (islite) { 5870 EGlite_free(geomObj); 5871 } else { 5872 EG_free(geomObj); 5873 } 5874 #endif 5875 PetscFunctionReturn(PETSC_SUCCESS); 5876 } 5877 5878 /*@C 5879 DMPlexGetGeomCntrlPntAndWeightData - Gets Control Point and Associated Weight Data for the Geometry attached to the DMPlex 5880 5881 Not collective 5882 5883 Input Parameter: 5884 . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5885 5886 Output Parameters: 5887 + cpHashTable - Hash Table containing the relationship between FACE ID and Control Point IDs. 5888 . cpCoordDataLength - Length of cpCoordData Array. 5889 . cpCoordData - Array holding the Geometry Control Point Coordinate Data. 5890 . maxNumEquiv - Maximum Number of Equivalent Control Points (Control Points with the same coordinates but different IDs). 5891 . 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 5892 . wHashTable - Hash Table containing the relationship between FACE ID and Control Point Weight. 5893 . wDataLength - Length of wData Array. 5894 - wData - Array holding the Weight for an associated Geometry Control Point. 5895 5896 Note: 5897 Must Call DMPLexGeomDataAndGrads() before calling this function. 5898 5899 Level: intermediate 5900 5901 .seealso: 5902 @*/ 5903 PetscErrorCode DMPlexGetGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) PeNS 5904 { 5905 PetscContainer modelObj, cpHashTableObj, wHashTableObj, cpCoordDataLengthObj, wDataLengthObj, maxNumRelateObj; 5906 Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 5907 PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr, *maxNumEquivPtr; 5908 PetscHMapI cpHashTableTemp, wHashTableTemp; 5909 5910 PetscFunctionBeginHot; 5911 /* Determine which type of EGADS model is attached to the DM */ 5912 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5913 if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 5914 5915 if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 5916 5917 // Look to see if DM has Container for Geometry Control Point Data 5918 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 5919 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 5920 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordDataLengthObj)); 5921 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 5922 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 5923 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 5924 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Equivalancy Matrix", (PetscObject *)cpEquiv)); 5925 PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 5926 5927 // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 5928 PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTableTemp)); 5929 PetscCall(PetscContainerGetPointer(cpCoordDataLengthObj, (void **)&cpCoordDataLengthPtr)); 5930 PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTableTemp)); 5931 PetscCall(PetscContainerGetPointer(wDataLengthObj, (void **)&wDataLengthPtr)); 5932 PetscCall(PetscContainerGetPointer(maxNumRelateObj, (void **)&maxNumEquivPtr)); 5933 5934 *cpCoordDataLength = *cpCoordDataLengthPtr; 5935 *wDataLength = *wDataLengthPtr; 5936 *maxNumEquiv = *maxNumEquivPtr; 5937 *cpHashTable = cpHashTableTemp; 5938 *wHashTable = wHashTableTemp; 5939 PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, cpCoordData)); 5940 PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, wData)); 5941 PetscFunctionReturn(PETSC_SUCCESS); 5942 } 5943 5944 PetscErrorCode DMPlexRestoreGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) 5945 { 5946 Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 5947 5948 PetscFunctionBeginHot; 5949 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 5950 PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, cpCoordData)); 5951 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 5952 PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, wData)); 5953 PetscFunctionReturn(PETSC_SUCCESS); 5954 } 5955 5956 /*@C 5957 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 . 5958 5959 Not collective 5960 5961 Input Parameter: 5962 . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5963 5964 Output Parameters: 5965 + cpSurfGradHashTable - Hash Table Relating the Control Point ID to the the Row in the cpSurfGrad Matrix 5966 . 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. 5967 . cpArraySize - The size of arrays gradSACP and gradVolCP and is equal to 3 * total number of Control Points in the Geometry 5968 . gradSACP - Array containing the Surface Area Gradient with respect to Control Point Data. Data is arranged by Control Point ID * 3 where 3 is for the coordinate dimension. 5969 . 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. 5970 . wArraySize - The size of arrayws gradSAW and gradVolW and is equal to the total number of Control Points in the Geometry. 5971 . gradSAW - Array containing the Surface Area Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 5972 - gradVolW - Array containing the Volume Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 5973 5974 Notes: 5975 Must Call DMPLexGeomDataAndGrads() before calling this function. 5976 5977 gradVolCP and gradVolW are only available when DMPlexGeomDataAndGrads() is called with fullGeomGrad = PETSC_TRUE. 5978 5979 Level: intermediate 5980 5981 .seealso: DMPlexGeomDataAndGrads 5982 @*/ 5983 PetscErrorCode DMPlexGetGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 5984 { 5985 PetscContainer modelObj, cpSurfGradHashTableObj, cpArraySizeObj, wArraySizeObj; 5986 Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 5987 PetscInt *cpArraySizePtr, *wArraySizePtr; 5988 PetscHMapI cpSurfGradHashTableTemp; 5989 5990 PetscFunctionBeginHot; 5991 /* Determine which type of EGADS model is attached to the DM */ 5992 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5993 if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 5994 5995 if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 5996 5997 // Look to see if DM has Container for Geometry Control Point Data 5998 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&cpSurfGradHashTableObj)); 5999 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Matrix", (PetscObject *)cpSurfGrad)); 6000 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpArraySizeObj)); 6001 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 6002 PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 6003 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wArraySizeObj)); 6004 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 6005 PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 6006 6007 // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 6008 if (cpSurfGradHashTableObj) { 6009 PetscCall(PetscContainerGetPointer(cpSurfGradHashTableObj, (void **)&cpSurfGradHashTableTemp)); 6010 *cpSurfGradHashTable = cpSurfGradHashTableTemp; 6011 } 6012 6013 if (cpArraySizeObj) { 6014 PetscCall(PetscContainerGetPointer(cpArraySizeObj, (void **)&cpArraySizePtr)); 6015 *cpArraySize = *cpArraySizePtr; 6016 } 6017 6018 if (gradSACPVec) PetscCall(VecGetArrayWrite(gradSACPVec, gradSACP)); 6019 if (gradVolCPVec) PetscCall(VecGetArrayWrite(gradVolCPVec, gradVolCP)); 6020 if (gradSAWVec) PetscCall(VecGetArrayWrite(gradSAWVec, gradSAW)); 6021 if (gradVolWVec) PetscCall(VecGetArrayWrite(gradVolWVec, gradVolW)); 6022 6023 if (wArraySizeObj) { 6024 PetscCall(PetscContainerGetPointer(wArraySizeObj, (void **)&wArraySizePtr)); 6025 *wArraySize = *wArraySizePtr; 6026 } 6027 PetscFunctionReturn(PETSC_SUCCESS); 6028 } 6029 6030 PetscErrorCode DMPlexRestoreGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 6031 { 6032 Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 6033 6034 PetscFunctionBegin; 6035 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 6036 PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 6037 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 6038 PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 6039 6040 if (gradSACPVec) PetscCall(VecRestoreArrayWrite(gradSACPVec, gradSACP)); 6041 if (gradVolCPVec) PetscCall(VecRestoreArrayWrite(gradVolCPVec, gradVolCP)); 6042 if (gradSAWVec) PetscCall(VecRestoreArrayWrite(gradSAWVec, gradSAW)); 6043 if (gradVolWVec) PetscCall(VecRestoreArrayWrite(gradVolWVec, gradVolW)); 6044 PetscFunctionReturn(PETSC_SUCCESS); 6045 } 6046 6047 /*@C 6048 DMPlexGetGeomCntrlPntMaps - Gets arrays which maps Control Point IDs to their associated Geometry FACE, EDGE, and VERTEX. 6049 6050 Not collective 6051 6052 Input Parameter: 6053 . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 6054 6055 Output Parameters: 6056 + numCntrlPnts - Number of Control Points defining the Geometry attached to the DMPlex 6057 . cntrlPntFaceMap - Array containing the FACE ID for the Control Point. Array index corresponds to Control Point ID. 6058 . cntrlPntWeightFaceMap - Array containing the FACE ID for the Control Point Weight. Array index corresponds to Control Point ID. 6059 . cntrlPntEdgeMap - Array containing the EDGE ID for the Control Point. Array index corresponds to Control Point ID. 6060 . cntrlPntWeightEdgeMap - Array containing the EDGE ID for the Control Point Weight. Array index corresponds to Control Point ID. 6061 . cntrlPntVertexMap - Array containing the VERTEX ID for the Control Point. Array index corresponds to Control Point ID. 6062 - cntrlPntWeightVertexMap - Array containing the VERTEX ID for the Control Point Weight. Array index corresponds to Control Point ID. 6063 6064 Note: 6065 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. 6066 6067 Level: intermediate 6068 6069 .seealso: DMPlexGeomDataAndGrads 6070 @*/ 6071 PetscErrorCode DMPlexGetGeomCntrlPntMaps(DM dm, PetscInt *numCntrlPnts, PetscInt **cntrlPntFaceMap, PetscInt **cntrlPntWeightFaceMap, PetscInt **cntrlPntEdgeMap, PetscInt **cntrlPntWeightEdgeMap, PetscInt **cntrlPntVertexMap, PetscInt **cntrlPntWeightVertexMap) 6072 { 6073 PetscFunctionBeginHot; 6074 #ifdef PETSC_HAVE_EGADS 6075 PetscContainer modelObj, numCntrlPntsObj, cntrlPntFaceMapObj, cntrlPntWeightFaceMapObj, cntrlPntEdgeMapObj, cntrlPntWeightEdgeMapObj, cntrlPntVertexMapObj, cntrlPntWeightVertexMapObj; 6076 PetscInt *numCntrlPntsPtr, *cntrlPntFaceMapPtr, *cntrlPntWeightFaceMapPtr, *cntrlPntEdgeMapPtr, *cntrlPntWeightEdgeMapPtr, *cntrlPntVertexMapPtr, *cntrlPntWeightVertexMapPtr; 6077 6078 /* Determine which type of EGADS model is attached to the DM */ 6079 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 6080 if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 6081 6082 if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 6083 6084 // Look to see if DM has Container for Geometry Control Point Data 6085 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&numCntrlPntsObj)); 6086 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cntrlPntFaceMapObj)); 6087 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&cntrlPntWeightFaceMapObj)); 6088 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cntrlPntEdgeMapObj)); 6089 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&cntrlPntWeightEdgeMapObj)); 6090 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cntrlPntVertexMapObj)); 6091 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&cntrlPntWeightVertexMapObj)); 6092 6093 // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 6094 if (numCntrlPntsObj) { 6095 PetscCall(PetscContainerGetPointer(numCntrlPntsObj, (void **)&numCntrlPntsPtr)); 6096 *numCntrlPnts = *numCntrlPntsPtr; 6097 } 6098 6099 if (cntrlPntFaceMapObj) { 6100 PetscCall(PetscContainerGetPointer(cntrlPntFaceMapObj, (void **)&cntrlPntFaceMapPtr)); 6101 *cntrlPntFaceMap = cntrlPntFaceMapPtr; 6102 } 6103 6104 if (cntrlPntWeightFaceMapObj) { 6105 PetscCall(PetscContainerGetPointer(cntrlPntWeightFaceMapObj, (void **)&cntrlPntWeightFaceMapPtr)); 6106 *cntrlPntWeightFaceMap = cntrlPntWeightFaceMapPtr; 6107 } 6108 6109 if (cntrlPntEdgeMapObj) { 6110 PetscCall(PetscContainerGetPointer(cntrlPntEdgeMapObj, (void **)&cntrlPntEdgeMapPtr)); 6111 *cntrlPntEdgeMap = cntrlPntEdgeMapPtr; 6112 } 6113 6114 if (cntrlPntWeightEdgeMapObj) { 6115 PetscCall(PetscContainerGetPointer(cntrlPntWeightEdgeMapObj, (void **)&cntrlPntWeightEdgeMapPtr)); 6116 *cntrlPntWeightEdgeMap = cntrlPntWeightEdgeMapPtr; 6117 } 6118 6119 if (cntrlPntVertexMapObj) { 6120 PetscCall(PetscContainerGetPointer(cntrlPntVertexMapObj, (void **)&cntrlPntVertexMapPtr)); 6121 *cntrlPntVertexMap = cntrlPntVertexMapPtr; 6122 } 6123 6124 if (cntrlPntWeightVertexMapObj) { 6125 PetscCall(PetscContainerGetPointer(cntrlPntWeightVertexMapObj, (void **)&cntrlPntWeightVertexMapPtr)); 6126 *cntrlPntWeightVertexMap = cntrlPntWeightVertexMapPtr; 6127 } 6128 6129 #endif 6130 PetscFunctionReturn(PETSC_SUCCESS); 6131 } 6132 6133 #endif 6134