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) 2479 { 2480 #if defined(PETSC_HAVE_EGADS) 2481 /* EGADS Variables */ 2482 ego model, geom, body, face, edge, vertex; 2483 ego *bodies; 2484 int Nb, oclass, mtype, *senses; 2485 double result[4]; 2486 /* PETSc Variables */ 2487 DM cdm; 2488 PetscContainer modelObj; 2489 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 2490 Vec coordinates; 2491 PetscScalar *coords; 2492 PetscInt bodyID, faceID, edgeID, vertexID; 2493 PetscInt cdim, d, vStart, vEnd, v; 2494 PetscBool islite = PETSC_FALSE; 2495 #endif 2496 2497 PetscFunctionBegin; 2498 #if defined(PETSC_HAVE_EGADS) 2499 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 2500 if (!modelObj) { 2501 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 2502 islite = PETSC_TRUE; 2503 } 2504 if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 2505 PetscCall(DMGetCoordinateDim(dm, &cdim)); 2506 PetscCall(DMGetCoordinateDM(dm, &cdm)); 2507 PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 2508 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 2509 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 2510 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 2511 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 2512 2513 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 2514 2515 if (islite) { 2516 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2517 } else { 2518 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2519 } 2520 2521 PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2522 PetscCall(VecGetArrayWrite(coordinates, &coords)); 2523 for (v = vStart; v < vEnd; ++v) { 2524 PetscScalar *vcoords; 2525 2526 PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 2527 PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 2528 PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 2529 PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 2530 2531 PetscCheck(bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bodyID, Nb); 2532 body = bodies[bodyID]; 2533 2534 PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 2535 if (vertexID > 0) { 2536 if (islite) { 2537 PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 2538 PetscCall(EGlite_evaluate(vertex, NULL, result)); 2539 } else { 2540 PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 2541 PetscCall(EG_evaluate(vertex, NULL, result)); 2542 } 2543 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2544 } else if (edgeID > 0) { 2545 /* Snap to EDGE at nearest location */ 2546 double params[1]; 2547 if (islite) { 2548 PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 2549 PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 2550 } // Get (x,y,z) of nearest point on EDGE 2551 else { 2552 PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 2553 PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 2554 } 2555 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2556 } else if (faceID > 0) { 2557 /* Snap to FACE at nearest location */ 2558 double params[2]; 2559 if (islite) { 2560 PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 2561 PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 2562 } // Get (x,y,z) of nearest point on FACE 2563 else { 2564 PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 2565 PetscCall(EG_invEvaluate(face, vcoords, params, result)); 2566 } 2567 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 2568 } 2569 } 2570 PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 2571 /* Clear out global coordinates */ 2572 PetscCall(VecDestroy(&dm->coordinates[0].x)); 2573 #endif 2574 PetscFunctionReturn(PETSC_SUCCESS); 2575 } 2576 2577 #if defined(PETSC_HAVE_EGADS) 2578 // This replaces the model in-place 2579 PetscErrorCode ConvertGeomModelToAllBSplines(PetscBool islite, ego *model) 2580 { 2581 /* EGADS/EGADSlite Variables */ 2582 ego context = NULL, geom, *bodies, *fobjs; 2583 int oclass, mtype; 2584 int *senses; 2585 int Nb, Nf; 2586 2587 PetscFunctionBegin; 2588 // Get the number of bodies and body objects in the model 2589 if (islite) PetscCallEGADS(EGlite_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2590 else PetscCallEGADS(EG_getTopology, (*model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2591 2592 // Get all Faces on the body <-- Only working with 1 body at the moment. 2593 ego body = bodies[0]; 2594 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 2595 else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 2596 ego newGeom[Nf]; 2597 ego newFaces[Nf]; 2598 2599 // Convert the 1st Face to a BSpline Geometry 2600 for (int ii = 0; ii < Nf; ++ii) { 2601 ego face = fobjs[ii]; 2602 ego gRef, gPrev, gNext, *lobjs; 2603 int goclass, gmtype, *gpinfo; 2604 int Nl, *lsenses; 2605 double *gprv; 2606 char *gClass = (char *)"", *gType = (char *)""; 2607 2608 /* Shape Optimization is NOT available for EGADSlite geometry files. */ 2609 /* Note :: islite options are left below in case future versions of EGADSlite includes this capability */ 2610 PetscCheck(!islite, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot convert geometric entities to all BSplines for geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep"); 2611 2612 if (islite) { 2613 PetscCallEGADS(EGlite_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_ 2614 PetscCallEGADS(EGlite_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info 2615 PetscCallEGADS(EGlite_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 2616 } // Get geometry info 2617 else { 2618 PetscCallEGADS(EG_getTopology, (face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); // Get FACES Geometry object (geom_ 2619 PetscCallEGADS(EG_getGeometry, (geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); // Get geometry object info 2620 PetscCallEGADS(EG_getInfo, (geom, &goclass, &gmtype, &gRef, &gPrev, &gNext)); 2621 } // Get geometry info 2622 2623 PetscCall(DMPlex_EGADS_GeomDecode_Internal(goclass, gmtype, &gClass, &gType)); // Decode Geometry integers 2624 2625 // Convert current FACE to a BSpline Surface 2626 ego bspline; 2627 ego bRef, bPrev, bNext; 2628 int boclass, bmtype, *bpinfo; 2629 double *bprv; 2630 char *bClass = (char *)"", *bType = (char *)""; 2631 2632 PetscCallEGADS(EG_convertToBSpline, (face, &bspline)); // Does not have an EGlite_ version 2633 2634 if (islite) { 2635 PetscCallEGADS(EGlite_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info 2636 PetscCallEGADS(EGlite_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2637 } // Get geometry info 2638 else { 2639 PetscCallEGADS(EG_getGeometry, (bspline, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); // Get geometry object info 2640 PetscCallEGADS(EG_getInfo, (bspline, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2641 } // Get geometry info 2642 2643 PetscCall(DMPlex_EGADS_GeomDecode_Internal(boclass, bmtype, &bClass, &bType)); // Decode Geometry integers 2644 2645 // Get Context from FACE 2646 context = NULL; 2647 PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version 2648 2649 // Silence WARNING Regarding OPENCASCADE 7.5 2650 if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 0)); 2651 else PetscCallEGADS(EG_setOutLevel, (context, 0)); 2652 2653 ego newgeom; 2654 PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version 2655 2656 PetscCallEGADS(EG_deleteObject, (bspline)); 2657 2658 // Create new FACE based on new SURFACE geometry 2659 double data[4]; 2660 int periodic; 2661 if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 2662 else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 2663 2664 ego newface; 2665 PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version 2666 //PetscCallEGADS(EG_deleteObject, (newgeom)); 2667 //PetscCallEGADS(EG_deleteObject, (newface)); 2668 newFaces[ii] = newface; 2669 newGeom[ii] = newgeom; 2670 2671 // Reinstate WARNING Regarding OPENCASCADE 7.5 2672 if (islite) PetscCallEGADS(EGlite_setOutLevel, (context, 1)); 2673 else PetscCallEGADS(EG_setOutLevel, (context, 1)); 2674 } 2675 2676 // Sew New Faces together to get a new model 2677 ego newmodel; 2678 PetscCallEGADS(EG_sewFaces, (Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version 2679 for (int ii = 0; ii < Nf; ++ii) { 2680 PetscCallEGADS(EG_deleteObject, (newFaces[ii])); 2681 PetscCallEGADS(EG_deleteObject, (newGeom[ii])); 2682 } 2683 PetscCallEGADS(EG_deleteObject, (*model)); 2684 *model = newmodel; 2685 PetscFunctionReturn(PETSC_SUCCESS); 2686 } 2687 #endif 2688 2689 /*@C 2690 DMPlexCreateGeomFromFile - Create a `DMPLEX` mesh from an EGADS, IGES, or STEP file. 2691 2692 Collective 2693 2694 Input Parameters: 2695 + comm - The MPI communicator 2696 . filename - The name of the EGADS, IGES, or STEP file 2697 - islite - Flag for EGADSlite support 2698 2699 Output Parameter: 2700 . dm - The `DM` object representing the mesh 2701 2702 Level: beginner 2703 2704 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexCreateEGADS()`, `DMPlexCreateEGADSliteFromFile()` 2705 @*/ 2706 PetscErrorCode DMPlexCreateGeomFromFile(MPI_Comm comm, const char filename[], DM *dm, PetscBool islite) 2707 { 2708 /* PETSc Variables */ 2709 PetscMPIInt rank; 2710 PetscBool printModel = PETSC_FALSE, tessModel = PETSC_FALSE, newModel = PETSC_FALSE; 2711 PetscBool shapeOpt = PETSC_FALSE; 2712 2713 #if defined(PETSC_HAVE_EGADS) 2714 ego context = NULL, model = NULL; 2715 #endif 2716 2717 PetscFunctionBegin; 2718 PetscAssertPointer(filename, 2); 2719 PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_print_model", &printModel, NULL)); 2720 PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_tess_model", &tessModel, NULL)); 2721 PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_new_model", &newModel, NULL)); 2722 PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_geom_shape_opt", &shapeOpt, NULL)); 2723 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2724 #if defined(PETSC_HAVE_EGADS) 2725 if (rank == 0) { 2726 /* EGADSlite files cannot be used for Shape Optimization Work. It lacks the ability to make new geometry. */ 2727 /* Must use EGADS, STEP, IGES or BRep files to perform this work. */ 2728 if (islite) { 2729 PetscCallEGADS(EGlite_open, (&context)); 2730 PetscCallEGADS(EGlite_loadModel, (context, 0, filename, &model)); 2731 if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model)); 2732 if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite)); 2733 } else { 2734 PetscCallEGADS(EG_open, (&context)); 2735 PetscCallEGADS(EG_loadModel, (context, 0, filename, &model)); 2736 if (shapeOpt) PetscCall(ConvertGeomModelToAllBSplines(islite, &model)); 2737 if (printModel) PetscCall(DMPlexGeomPrintModel_Internal(model, islite)); 2738 } 2739 } 2740 if (tessModel) PetscCall(DMPlexCreateGeom_Tess_Internal(comm, context, model, dm, islite)); 2741 else if (newModel) PetscCall(DMPlexCreateGeom_Internal(comm, context, model, dm, islite)); 2742 else { 2743 PetscCall(DMPlexCreateGeom(comm, context, model, dm, islite)); 2744 } 2745 PetscFunctionReturn(PETSC_SUCCESS); 2746 #else 2747 SETERRQ(comm, PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 2748 #endif 2749 } 2750 2751 #if defined(PETSC_HAVE_EGADS) 2752 /*@C 2753 DMPlex_Surface_Grad - Exposes the Geometry's Control Points and Weights and Calculates the Mesh Topology Boundary Nodes Gradient 2754 with respect the associated geometry's Control Points and Weights. 2755 2756 // ----- Depreciated ---- See DMPlexGeomDataAndGrads ------ // 2757 2758 Collective 2759 2760 Input Parameters: 2761 . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 2762 2763 Output Parameter: 2764 . dm - The DM object representing the mesh with PetscContainers containing the EGADS geometry model, Array-Hash Table Geometry Control Point Pair, Array-Hash Table Geometry Weights Pair and Matrix-Hash Table Surface Gradient Pair 2765 2766 Level: intermediate 2767 2768 .seealso: 2769 @*/ 2770 PetscErrorCode DMPlex_Surface_Grad(DM dm) 2771 { 2772 ego model, geom, *bodies, *fobjs; 2773 PetscContainer modelObj; 2774 int oclass, mtype, *senses; 2775 int Nb, Nf; 2776 PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 2777 PetscHMapI pointSurfGradRow_Start = NULL; 2778 Mat pointSurfGrad; 2779 IS faceLabelValues, edgeLabelValues, vertexLabelValues; 2780 PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 2781 PetscBool islite = PETSC_FALSE; 2782 2783 PetscFunctionBegin; 2784 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 2785 if (!modelObj) { 2786 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 2787 islite = PETSC_TRUE; 2788 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, " Cannot provide geometric data or associated calculated gradients for geometries defined by EGADSlite (.egadslite)! \n Please use another geometry file format STEP, IGES, EGADS or BRep"); 2789 } 2790 2791 // Get attached EGADS model (pointer) 2792 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 2793 2794 // Get the bodies in the model 2795 if (islite) { 2796 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2797 } else { 2798 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 2799 } 2800 2801 ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 2802 2803 // Get the total number of FACEs in the model 2804 if (islite) { 2805 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2806 } else { 2807 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 2808 } 2809 2810 // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 2811 // This will provide the total number of DMPlex points on the boundary of the geometry 2812 PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 2813 PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 2814 2815 PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 2816 PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 2817 2818 PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 2819 PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 2820 2821 const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 2822 PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 2823 PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 2824 PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 2825 2826 // Get the points associated with each FACE, EDGE and VERTEX label in the DM 2827 PetscInt totalNumPoints = 0; 2828 for (int ii = 0; ii < faceLabelSize; ++ii) { 2829 // Cycle through FACE labels 2830 PetscInt size; 2831 PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[ii], &size)); 2832 totalNumPoints += size; 2833 } 2834 PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 2835 PetscCall(ISDestroy(&faceLabelValues)); 2836 2837 for (int ii = 0; ii < edgeLabelSize; ++ii) { 2838 // Cycle Through EDGE Labels 2839 PetscInt size; 2840 PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[ii], &size)); 2841 totalNumPoints += size; 2842 } 2843 PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 2844 PetscCall(ISDestroy(&edgeLabelValues)); 2845 2846 for (int ii = 0; ii < vertexLabelSize; ++ii) { 2847 // Cycle Through VERTEX Labels 2848 PetscInt size; 2849 PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 2850 totalNumPoints += size; 2851 } 2852 PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 2853 PetscCall(ISDestroy(&vertexLabelValues)); 2854 2855 int maxNumCPs = 0; 2856 int totalNumCPs = 0; 2857 ego bRef, bPrev, bNext, fgeom, *lobjs; 2858 int id, boclass, bmtype, *bpinfo; 2859 int foclass, fmtype, Nl, *lsenses; 2860 double *bprv; 2861 double fdata[4]; 2862 2863 // Create Hash Tables 2864 PetscInt cntr = 0, wcntr = 0; 2865 PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 2866 PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 2867 2868 for (int ii = 0; ii < Nf; ++ii) { 2869 // Need to get the maximum number of Control Points defining the FACEs 2870 ego face = fobjs[ii]; 2871 int maxNumCPs_temp; 2872 2873 if (islite) { 2874 id = EGlite_indexBodyTopo(body, face); 2875 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2876 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2877 PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2878 } else { 2879 id = EG_indexBodyTopo(body, face); 2880 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2881 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2882 PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2883 } 2884 2885 maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 2886 totalNumCPs += bpinfo[2] * bpinfo[5]; 2887 2888 if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 2889 } 2890 2891 PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 2892 PetscInt cpCoordDataLength = 3 * totalNumCPs; 2893 PetscInt wDataLength = totalNumCPs; 2894 cpCoordDataLengthPtr = &cpCoordDataLength; 2895 wDataLengthPtr = &wDataLength; 2896 PetscScalar *cntrlPtCoords, *cntrlPtWeights; 2897 PetscMalloc1(cpCoordDataLength, &cntrlPtCoords); 2898 PetscMalloc1(wDataLength, &cntrlPtWeights); 2899 for (int ii = 0; ii < Nf; ++ii) { 2900 // Need to Populate Control Point Coordinates and Weight Vectors 2901 ego face = fobjs[ii]; 2902 PetscHashIter hashKeyIter, wHashKeyIter; 2903 PetscBool hashKeyFound, wHashKeyFound; 2904 2905 if (islite) { 2906 id = EGlite_indexBodyTopo(body, face); 2907 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2908 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2909 PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2910 } else { 2911 id = EG_indexBodyTopo(body, face); 2912 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 2913 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 2914 PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 2915 } 2916 2917 // Store Face ID to 1st Row of Control Point Vector 2918 PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 2919 2920 if (!hashKeyFound) { PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); } 2921 2922 int offsetCoord = bpinfo[3] + bpinfo[6]; 2923 for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 2924 cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 2925 cntr += 1; 2926 } 2927 2928 // Store Face ID to 1st Row of Control Point Weight Vector 2929 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 2930 2931 if (!wHashKeyFound) { PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); } 2932 2933 int offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 2934 for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 2935 cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 2936 wcntr += 1; 2937 } 2938 } 2939 2940 // Attach Control Point and Weight Data to DM 2941 { 2942 PetscContainer cpOrgObj, cpCoordObj, cpCoordLengthObj; 2943 PetscContainer wOrgObj, wValObj, wDataLengthObj; 2944 2945 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 2946 PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 2947 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 2948 PetscCall(PetscContainerDestroy(&cpOrgObj)); 2949 2950 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordObj)); 2951 PetscCall(PetscContainerSetPointer(cpCoordObj, cntrlPtCoords)); 2952 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cpCoordObj)); 2953 PetscCall(PetscContainerDestroy(&cpCoordObj)); 2954 2955 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 2956 PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 2957 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 2958 PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 2959 2960 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 2961 PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 2962 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 2963 PetscCall(PetscContainerDestroy(&wOrgObj)); 2964 2965 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wValObj)); 2966 PetscCall(PetscContainerSetPointer(wValObj, cntrlPtWeights)); 2967 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)wValObj)); 2968 PetscCall(PetscContainerDestroy(&wValObj)); 2969 2970 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 2971 PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 2972 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 2973 PetscCall(PetscContainerDestroy(&wDataLengthObj)); 2974 } 2975 2976 // Define Matrix to store Surface Gradient information dx_i/dCPj_i 2977 PetscInt gcntr = 0; 2978 const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 2979 const PetscInt colSize = 4 * Nf; 2980 2981 // Create Point Surface Gradient Matrix 2982 MatCreate(PETSC_COMM_WORLD, &pointSurfGrad); 2983 MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize); 2984 MatSetType(pointSurfGrad, MATAIJ); 2985 MatSetUp(pointSurfGrad); 2986 2987 // Create Hash Table to store Point's stare row in surfaceGrad[][] 2988 PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 2989 2990 // Get Coordinates for the DMPlex point 2991 DM cdm; 2992 PetscInt dE, Nv; 2993 Vec coordinatesLocal; 2994 PetscScalar *coords = NULL; 2995 PetscCall(DMGetCoordinateDM(dm, &cdm)); 2996 PetscCall(DMGetCoordinateDim(dm, &dE)); 2997 PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 2998 2999 // CYCLE THROUGH FACEs 3000 for (int ii = 0; ii < Nf; ++ii) { 3001 ego face = fobjs[ii]; 3002 ego *eobjs, *nobjs; 3003 PetscInt fid, Ne, Nn; 3004 DMLabel faceLabel, edgeLabel, nodeLabel; 3005 PetscHMapI currFaceUniquePoints = NULL; 3006 IS facePoints, edgePoints, nodePoints; 3007 const PetscInt *fIndices, *eIndices, *nIndices; 3008 PetscInt fSize, eSize, nSize; 3009 PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 3010 PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 3011 PetscInt cfCntr = 0; 3012 3013 // Get Geometry Object for the Current FACE 3014 if (islite) { 3015 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3016 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3017 } else { 3018 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3019 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3020 } 3021 3022 // Get all EDGE and NODE objects attached to the current FACE 3023 if (islite) { 3024 PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3025 PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3026 } else { 3027 PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3028 PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3029 } 3030 3031 // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 3032 if (islite) { 3033 fid = EGlite_indexBodyTopo(body, face); 3034 } else { 3035 fid = EG_indexBodyTopo(body, face); 3036 } 3037 3038 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 3039 PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 3040 PetscCall(ISGetIndices(facePoints, &fIndices)); 3041 PetscCall(ISGetSize(facePoints, &fSize)); 3042 3043 PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 3044 3045 for (int jj = 0; jj < fSize; ++jj) { 3046 PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 3047 3048 if (!fHashKeyFound) { 3049 PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 3050 cfCntr += 1; 3051 } 3052 3053 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 3054 3055 if (!pHashKeyFound) { 3056 PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 3057 gcntr += 3 * maxNumCPs; 3058 } 3059 } 3060 PetscCall(ISRestoreIndices(facePoints, &fIndices)); 3061 PetscCall(ISDestroy(&facePoints)); 3062 3063 // Get all DMPlex Points that have DMLable "EGADS Edge ID" attached to the current FACE and store them in a Hash Table for later use. 3064 for (int jj = 0; jj < Ne; ++jj) { 3065 ego edge = eobjs[jj]; 3066 PetscBool containLabelValue; 3067 3068 if (islite) { 3069 id = EGlite_indexBodyTopo(body, edge); 3070 } else { 3071 id = EG_indexBodyTopo(body, edge); 3072 } 3073 3074 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 3075 PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 3076 3077 if (containLabelValue) { 3078 PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 3079 PetscCall(ISGetIndices(edgePoints, &eIndices)); 3080 PetscCall(ISGetSize(edgePoints, &eSize)); 3081 3082 for (int kk = 0; kk < eSize; ++kk) { 3083 PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 3084 3085 if (!eHashKeyFound) { 3086 PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 3087 cfCntr += 1; 3088 } 3089 3090 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 3091 3092 if (!pHashKeyFound) { 3093 PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 3094 gcntr += 3 * maxNumCPs; 3095 } 3096 } 3097 PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 3098 PetscCall(ISDestroy(&edgePoints)); 3099 } 3100 } 3101 3102 // Get all DMPlex Points that have DMLabel "EGADS Vertex ID" attached to the current FACE and store them in a Hash Table for later use. 3103 for (int jj = 0; jj < Nn; ++jj) { 3104 ego node = nobjs[jj]; 3105 3106 if (islite) { 3107 id = EGlite_indexBodyTopo(body, node); 3108 } else { 3109 id = EG_indexBodyTopo(body, node); 3110 } 3111 3112 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 3113 PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 3114 PetscCall(ISGetIndices(nodePoints, &nIndices)); 3115 PetscCall(ISGetSize(nodePoints, &nSize)); 3116 3117 for (int kk = 0; kk < nSize; ++kk) { 3118 PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 3119 3120 if (!nHashKeyFound) { 3121 PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 3122 cfCntr += 1; 3123 } 3124 3125 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 3126 if (!pHashKeyFound) { 3127 PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 3128 gcntr += 3 * maxNumCPs; 3129 } 3130 } 3131 PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 3132 PetscCall(ISDestroy(&nodePoints)); 3133 } 3134 3135 // Get the Total Number of entries in the Hash Table 3136 PetscInt currFaceUPSize; 3137 PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 3138 3139 // Get Keys 3140 PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 3141 PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 3142 3143 // Cycle through all points on the current FACE 3144 for (int jj = 0; jj < currFaceUPSize; ++jj) { 3145 PetscInt currPointID = currFaceUPKeys[jj]; 3146 PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 3147 3148 // Get UV position of FACE 3149 double params[2], range[4], eval[18]; 3150 int peri; 3151 3152 if (islite) { 3153 PetscCall(EGlite_getRange(face, range, &peri)); 3154 } else { 3155 PetscCall(EG_getRange(face, range, &peri)); 3156 } 3157 3158 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 3159 3160 if (islite) { 3161 PetscCall(EGlite_evaluate(face, params, eval)); 3162 } else { 3163 PetscCall(EG_evaluate(face, params, eval)); 3164 } 3165 3166 // Make a new SURFACE Geometry by changing the location of the Control Points 3167 int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 3168 double nbprv[prvSize]; 3169 3170 // Cycle through each Control Point 3171 double deltaCoord = 1.0E-4; 3172 int offset = bpinfo[3] + bpinfo[6]; 3173 int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 3174 for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 3175 // Cycle through each direction (x, then y, then z) 3176 for (int kk = 0; kk < 4; ++kk) { 3177 // Reinitialize nbprv[] values because we only want to change one value at a time 3178 for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 3179 3180 if (kk == 0) { //X 3181 nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 3182 nbprv[offset + 1] = bprv[offset + 1]; 3183 nbprv[offset + 2] = bprv[offset + 2]; 3184 } else if (kk == 1) { //Y 3185 nbprv[offset + 0] = bprv[offset + 0]; 3186 nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 3187 nbprv[offset + 2] = bprv[offset + 2]; 3188 } else if (kk == 2) { //Z 3189 nbprv[offset + 0] = bprv[offset + 0]; 3190 nbprv[offset + 1] = bprv[offset + 1]; 3191 nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 3192 } else if (kk == 3) { // Weights 3193 nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 3194 } else { 3195 // currently do nothing 3196 } 3197 3198 // Create New Surface Based on New Control Points or Weights 3199 ego newgeom, context; 3200 if (islite) { 3201 PetscCall(EGlite_open(&context)); 3202 PetscCall(EGlite_setOutLevel(context, 0)); 3203 } else { 3204 PetscCall(EG_open(&context)); 3205 PetscCall(EG_setOutLevel(context, 0)); 3206 } 3207 3208 PetscCall(EG_makeGeometry(context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 3209 3210 if (islite) { 3211 PetscCall(EGlite_setOutLevel(context, 1)); 3212 } else { 3213 PetscCall(EG_setOutLevel(context, 1)); 3214 } 3215 3216 // Evaluate new (x, y, z) Point Position based on new Surface Definition 3217 double newCoords[18]; 3218 if (islite) { 3219 PetscCall(EGlite_getRange(newgeom, range, &peri)); 3220 } else { 3221 PetscCall(EG_getRange(newgeom, range, &peri)); 3222 } 3223 3224 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, newgeom, range, 0, dE, params, islite)); 3225 3226 if (islite) { 3227 PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 3228 } else { 3229 PetscCall(EG_evaluate(newgeom, params, newCoords)); 3230 } 3231 3232 // Now Calculate the Surface Gradient for the change in x-component Control Point 3233 PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 3234 PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 3235 PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 3236 3237 // Store Gradient Information in surfaceGrad[][] Matrix 3238 PetscInt startRow; 3239 PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 3240 3241 // Store Results in Petsc Matrix 3242 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 3243 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 3244 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 3245 } 3246 offset += 3; 3247 } 3248 PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 3249 } 3250 } 3251 3252 // Assemble Point Surface Grad Matrix 3253 MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY); 3254 MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY); 3255 3256 // Attach Surface Gradient Hash Table and Matrix to DM 3257 { 3258 PetscContainer surfGradOrgObj, surfGradObj; 3259 3260 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 3261 PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 3262 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 3263 PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 3264 3265 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradObj)); 3266 PetscCall(PetscContainerSetPointer(surfGradObj, pointSurfGrad)); 3267 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)surfGradObj)); 3268 PetscCall(PetscContainerDestroy(&surfGradObj)); 3269 } 3270 if (islite) EGlite_free(fobjs); 3271 else EG_free(fobjs); 3272 PetscFunctionReturn(PETSC_SUCCESS); 3273 } 3274 3275 static PetscErrorCode DestroyHashMap(void **p) 3276 { 3277 PetscFunctionBegin; 3278 PetscCall(PetscHMapIDestroy((PetscHMapI *)p)); 3279 PetscFunctionReturn(PETSC_SUCCESS); 3280 } 3281 #endif 3282 3283 /*@C 3284 DMPlexGeomDataAndGrads - Exposes Control Points and Control Point Weights defining the underlying geometry allowing user manipulation of the geometry. 3285 3286 Collective 3287 3288 Input Parameters: 3289 + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 3290 - fullGeomGrad - PetscBool flag. Determines how the Surface Area and Volume Gradients wrt to Control Points and Control Point Weights are calculated. 3291 PETSC_FALSE :: Surface Area Gradient wrt Control Points and Control Point Weights are calculated using the change in the local 3292 FACE changes (not the entire body). Volume Gradients are not calculated. Faster computations. 3293 PETSC_TRUE :: Surface Area Gradietn wrt to Control Points and Control Point Weights are calculated using the change observed in 3294 the entire solid body. Volume Gradients are calculated. Slower computation due to the need to generate a new solid 3295 body geometry for every Control Point and Control Point Weight change. 3296 3297 Output Parameter: 3298 . dm - The updated DM object representing the mesh with PetscContainers containing the Control Point, Control Point Weight and Gradient Data. 3299 3300 Level: intermediate 3301 3302 Note: 3303 Calculates the DM Point location, surface area and volume gradients wrt to Control Point and Control Point Weights using Finite Difference (small perturbation of Control Point coordinates or Control Point Weight value). 3304 3305 .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexModifyEGADSGeomModel()` 3306 @*/ 3307 PetscErrorCode DMPlexGeomDataAndGrads(DM dm, PetscBool fullGeomGrad) 3308 { 3309 #if defined(PETSC_HAVE_EGADS) 3310 /* PETSc Variables */ 3311 PetscContainer modelObj; 3312 PetscHMapI faceCntrlPtRow_Start = NULL, faceCPWeightsRow_Start = NULL; 3313 PetscHMapI pointSurfGradRow_Start = NULL; 3314 Mat pointSurfGrad, cpEquiv; 3315 IS faceLabelValues, edgeLabelValues, vertexLabelValues; 3316 PetscInt faceLabelSize, edgeLabelSize, vertexLabelSize; 3317 PetscBool islite = PETSC_FALSE; 3318 /* EGADS Variables */ 3319 ego model, geom, *bodies, *fobjs = NULL; 3320 int oclass, mtype, *senses; 3321 int Nb, Nf; 3322 #endif 3323 3324 PetscFunctionBegin; 3325 #if defined(PETSC_HAVE_EGADS) 3326 3327 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 3328 if (!modelObj) { 3329 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 3330 PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 3331 islite = PETSC_TRUE; 3332 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot provide geometric data or associated calculated gradients for geometries defined by EGADSlite (.egadslite)!\nPlease use another geometry file format STEP, IGES, EGADS or BRep"); 3333 } 3334 3335 // Get attached EGADS model (pointer) 3336 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 3337 3338 // Get the bodies in the model 3339 if (islite) { 3340 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 3341 } else { 3342 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 3343 } 3344 3345 ego body = bodies[0]; // Only operate on 1st body. Model should only have 1 body. 3346 3347 // Get the total number of FACEs in the model 3348 if (islite) { 3349 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 3350 } else { 3351 PetscCall(EG_getBodyTopos(body, NULL, FACE, &Nf, &fobjs)); 3352 } 3353 3354 // Get the total number of points and IDs in the DMPlex with a "EGADS Face Label" 3355 // This will provide the total number of DMPlex points on the boundary of the geometry 3356 PetscCall(DMGetLabelIdIS(dm, "EGADS Face ID", &faceLabelValues)); 3357 PetscCall(DMGetLabelSize(dm, "EGADS Face ID", &faceLabelSize)); 3358 3359 PetscCall(DMGetLabelIdIS(dm, "EGADS Edge ID", &edgeLabelValues)); 3360 PetscCall(DMGetLabelSize(dm, "EGADS Edge ID", &edgeLabelSize)); 3361 3362 PetscCall(DMGetLabelIdIS(dm, "EGADS Vertex ID", &vertexLabelValues)); 3363 PetscCall(DMGetLabelSize(dm, "EGADS Vertex ID", &vertexLabelSize)); 3364 3365 const PetscInt *faceIndices, *edgeIndices, *vertexIndices; 3366 PetscCall(ISGetIndices(faceLabelValues, &faceIndices)); 3367 PetscCall(ISGetIndices(edgeLabelValues, &edgeIndices)); 3368 PetscCall(ISGetIndices(vertexLabelValues, &vertexIndices)); 3369 3370 // Get the points associated with each FACE, EDGE and VERTEX label in the DM 3371 PetscInt totalNumPoints = 0; 3372 for (int f = 0; f < faceLabelSize; ++f) { 3373 // Cycle through FACE labels 3374 PetscInt size; 3375 PetscCall(DMGetStratumSize(dm, "EGADS Face ID", faceIndices[f], &size)); 3376 totalNumPoints += size; 3377 } 3378 PetscCall(ISRestoreIndices(faceLabelValues, &faceIndices)); 3379 PetscCall(ISDestroy(&faceLabelValues)); 3380 3381 for (int e = 0; e < edgeLabelSize; ++e) { 3382 // Cycle Through EDGE Labels 3383 PetscInt size; 3384 PetscCall(DMGetStratumSize(dm, "EGADS Edge ID", edgeIndices[e], &size)); 3385 totalNumPoints += size; 3386 } 3387 PetscCall(ISRestoreIndices(edgeLabelValues, &edgeIndices)); 3388 PetscCall(ISDestroy(&edgeLabelValues)); 3389 3390 for (int ii = 0; ii < vertexLabelSize; ++ii) { 3391 // Cycle Through VERTEX Labels 3392 PetscInt size; 3393 PetscCall(DMGetStratumSize(dm, "EGADS Vertex ID", vertexIndices[ii], &size)); 3394 totalNumPoints += size; 3395 } 3396 PetscCall(ISRestoreIndices(vertexLabelValues, &vertexIndices)); 3397 PetscCall(ISDestroy(&vertexLabelValues)); 3398 3399 int maxNumCPs = 0; 3400 int totalNumCPs = 0; 3401 ego bRef, bPrev, bNext, fgeom, *lobjs; 3402 int id, boclass, bmtype, *bpinfo; 3403 int foclass, fmtype, Nl, *lsenses; 3404 double *bprv; 3405 double fdata[4]; 3406 3407 // Create Hash Tables 3408 PetscInt cntr = 0, wcntr = 0, vcntr = 0; 3409 PetscCall(PetscHMapICreate(&faceCntrlPtRow_Start)); 3410 PetscCall(PetscHMapICreate(&faceCPWeightsRow_Start)); 3411 3412 for (int f = 0; f < Nf; ++f) { 3413 // Need to get the maximum number of Control Points defining the FACEs 3414 ego face = fobjs[f]; 3415 int maxNumCPs_temp; 3416 3417 if (islite) { 3418 id = EGlite_indexBodyTopo(body, face); 3419 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3420 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3421 PetscCall(EGlite_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3422 } else { 3423 id = EG_indexBodyTopo(body, face); 3424 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3425 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3426 PetscCall(EG_getInfo(fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3427 } 3428 maxNumCPs_temp = bpinfo[2] * bpinfo[5]; 3429 totalNumCPs += bpinfo[2] * bpinfo[5]; 3430 3431 if (maxNumCPs_temp > maxNumCPs) { maxNumCPs = maxNumCPs_temp; } 3432 } 3433 3434 PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 3435 PetscInt cpCoordDataLength = 3 * totalNumCPs; 3436 PetscInt wDataLength = totalNumCPs; 3437 cpCoordDataLengthPtr = &cpCoordDataLength; 3438 wDataLengthPtr = &wDataLength; 3439 3440 Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 3441 PetscScalar *cntrlPtCoords, *cntrlPtWeights; 3442 PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &cntrlPtCoordsVec)); 3443 PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &cntrlPtWeightsVec)); 3444 3445 // For dSA/dCPi 3446 Vec gradSACPVec, gradSAWVec, gradVCPVec, gradVWVec; 3447 PetscScalar *gradSACP, *gradSAW, *gradVCP, *gradVW; 3448 PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradSACPVec)); 3449 PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradSAWVec)); 3450 PetscCall(VecCreateSeq(PETSC_COMM_SELF, cpCoordDataLength, &gradVCPVec)); 3451 PetscCall(VecCreateSeq(PETSC_COMM_SELF, wDataLength, &gradVWVec)); 3452 3453 // Control Point - Vertex/Edge/Face Relationship 3454 PetscInt *cp_vertex, *cp_edge, *cp_face; 3455 PetscInt *w_vertex, *w_edge, *w_face; 3456 PetscCall(PetscMalloc1(totalNumCPs, &cp_vertex)); 3457 PetscCall(PetscMalloc1(totalNumCPs, &cp_edge)); 3458 PetscCall(PetscMalloc1(totalNumCPs, &cp_face)); 3459 PetscCall(PetscMalloc1(wDataLength, &w_vertex)); 3460 PetscCall(PetscMalloc1(wDataLength, &w_edge)); 3461 PetscCall(PetscMalloc1(wDataLength, &w_face)); 3462 3463 for (int f = 0; f < Nf; ++f) { 3464 // Need to Populate Control Point Coordinates and Weight Vectors 3465 ego face = fobjs[f]; 3466 ego *vobjs, *eobjs; 3467 int offsetCoord, offsetWeight; 3468 PetscInt Nv, Ne, wRowStart = 0; 3469 PetscHashIter hashKeyIter, wHashKeyIter; 3470 PetscBool hashKeyFound, wHashKeyFound; 3471 3472 if (islite) { 3473 id = EGlite_indexBodyTopo(body, face); 3474 PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3475 PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3476 PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3477 PetscCallEGADS(EGlite_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 3478 } else { 3479 id = EG_indexBodyTopo(body, face); 3480 PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3481 PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3482 PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 3483 PetscCallEGADS(EG_getBodyTopos, (body, face, NODE, &Nv, &vobjs)); 3484 } 3485 3486 // Store Face ID to 1st Row of Control Point Vector 3487 PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, id, &hashKeyIter, &hashKeyFound)); 3488 3489 if (!hashKeyFound) PetscCall(PetscHMapISet(faceCntrlPtRow_Start, id, cntr)); 3490 3491 PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 3492 offsetCoord = bpinfo[3] + bpinfo[6]; 3493 for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; ++jj) { 3494 cntrlPtCoords[cntr] = bprv[offsetCoord + jj]; 3495 cntr += 1; 3496 } 3497 3498 // Store Face ID to 1st Row of Control Point Weight Vector 3499 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, id, &wHashKeyIter, &wHashKeyFound)); 3500 3501 if (!wHashKeyFound) { 3502 PetscCall(PetscHMapISet(faceCPWeightsRow_Start, id, wcntr)); 3503 wRowStart = wcntr; 3504 } 3505 3506 PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 3507 offsetWeight = bpinfo[3] + bpinfo[6] + (3 * bpinfo[2] * bpinfo[5]); 3508 for (int jj = 0; jj < bpinfo[2] * bpinfo[5]; ++jj) { 3509 cntrlPtWeights[wcntr] = bprv[offsetWeight + jj]; 3510 cp_face[wcntr] = id; 3511 w_face[wcntr] = id; 3512 wcntr += 1; 3513 } 3514 PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, &cntrlPtWeights)); 3515 3516 // Associate Control Points with Vertix IDs 3517 PetscScalar xcp, ycp, zcp; 3518 offsetCoord = bpinfo[3] + bpinfo[6]; 3519 for (int jj = 0; jj < 3 * bpinfo[2] * bpinfo[5]; jj += 3) { 3520 xcp = bprv[offsetCoord + jj + 0]; 3521 ycp = bprv[offsetCoord + jj + 1]; 3522 zcp = bprv[offsetCoord + jj + 2]; 3523 3524 //Initialize Control Point and Weight to Vertex ID relationship to -1 3525 cp_vertex[vcntr] = -1; 3526 w_vertex[vcntr] = -1; 3527 cp_edge[vcntr] = -1; 3528 w_edge[vcntr] = -1; 3529 3530 for (int kk = 0; kk < Nv; ++kk) { 3531 int vid; 3532 double vCoords[3]; 3533 PetscScalar vDelta; 3534 ego vertex = vobjs[kk]; 3535 3536 if (islite) { 3537 vid = EGlite_indexBodyTopo(body, vertex); 3538 PetscCallEGADS(EGlite_evaluate, (vertex, NULL, vCoords)); 3539 } else { 3540 vid = EG_indexBodyTopo(body, vertex); 3541 PetscCallEGADS(EG_evaluate, (vertex, NULL, vCoords)); 3542 } 3543 vDelta = PetscSqrtReal(PetscSqr(vCoords[0] - xcp) + PetscSqr(vCoords[1] - ycp) + PetscSqr(vCoords[2] - zcp)); 3544 3545 if (vDelta < 1.0E-15) { 3546 cp_vertex[vcntr] = vid; 3547 w_vertex[vcntr] = vid; 3548 } 3549 } 3550 vcntr += 1; 3551 } 3552 // These two line could be replaced with DMPlexFreeGeomObject() 3553 if (islite) EGlite_free(vobjs); 3554 else EG_free(vobjs); 3555 3556 // Associate Control Points with Edge IDs 3557 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 3558 else PetscCallEGADS(EG_getBodyTopos, (body, face, EDGE, &Ne, &eobjs)); 3559 3560 int cpV1, cpV2; 3561 int minID, maxID; 3562 3563 // Along vmin axis 3564 minID = wRowStart; 3565 maxID = wRowStart + (bpinfo[2] - 1); 3566 cpV1 = cp_vertex[minID]; 3567 cpV2 = cp_vertex[maxID]; 3568 for (int jj = 0; jj < Ne; ++jj) { 3569 ego edge = eobjs[jj]; 3570 ego egeom, *nobjs; 3571 int eoclass, emtype, Nn, *nsenses; 3572 int n1ID, n2ID, eid; 3573 3574 if (islite) { 3575 eid = EGlite_indexBodyTopo(body, edge); 3576 PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3577 } else { 3578 eid = EG_indexBodyTopo(body, edge); 3579 PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3580 } 3581 3582 if (emtype != DEGENERATE) { 3583 // Get IDs for current Edge's End Vertices 3584 if (islite) { 3585 n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3586 n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3587 } else { 3588 n1ID = EG_indexBodyTopo(body, nobjs[0]); 3589 n2ID = EG_indexBodyTopo(body, nobjs[1]); 3590 } 3591 3592 if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3593 for (int kk = minID + 1; kk < maxID; ++kk) { 3594 cp_edge[kk] = eid; 3595 w_edge[kk] = eid; 3596 } 3597 } 3598 } 3599 } 3600 3601 // Along vmax axis 3602 minID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 3603 maxID = wRowStart + (bpinfo[2] * bpinfo[5] - 1); 3604 3605 cpV1 = cp_vertex[minID]; 3606 cpV2 = cp_vertex[maxID]; 3607 for (int jj = 0; jj < Ne; ++jj) { 3608 ego edge = eobjs[jj]; 3609 ego egeom, *nobjs; 3610 int eoclass, emtype, Nn, *nsenses; 3611 int n1ID, n2ID, eid; 3612 3613 if (islite) { 3614 eid = EGlite_indexBodyTopo(body, edge); 3615 PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3616 } else { 3617 eid = EG_indexBodyTopo(body, edge); 3618 PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3619 } 3620 3621 if (emtype != DEGENERATE) { 3622 // Get IDs for current Edge's End Vertices 3623 if (islite) { 3624 n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3625 n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3626 } else { 3627 n1ID = EG_indexBodyTopo(body, nobjs[0]); 3628 n2ID = EG_indexBodyTopo(body, nobjs[1]); 3629 } 3630 3631 if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3632 for (int kk = minID + 1; kk < maxID - 1; ++kk) { 3633 cp_edge[kk] = eid; 3634 w_edge[kk] = eid; 3635 } 3636 } 3637 } 3638 } 3639 3640 // Along umin axis 3641 minID = wRowStart; 3642 maxID = wRowStart + (bpinfo[2] * (bpinfo[5] - 1)); 3643 3644 cpV1 = cp_vertex[minID]; 3645 cpV2 = cp_vertex[maxID]; 3646 for (int jj = 0; jj < Ne; ++jj) { 3647 ego edge = eobjs[jj]; 3648 ego egeom, *nobjs; 3649 int eoclass, emtype, Nn, *nsenses; 3650 int n1ID, n2ID, eid; 3651 3652 if (islite) { 3653 eid = EGlite_indexBodyTopo(body, edge); 3654 PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3655 } else { 3656 eid = EG_indexBodyTopo(body, edge); 3657 PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3658 } 3659 3660 if (emtype != DEGENERATE) { 3661 // Get IDs for current Edge's End Vertices 3662 if (islite) { 3663 n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3664 n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3665 } else { 3666 n1ID = EG_indexBodyTopo(body, nobjs[0]); 3667 n2ID = EG_indexBodyTopo(body, nobjs[1]); 3668 } 3669 3670 if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3671 for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 3672 cp_edge[kk] = eid; 3673 w_edge[kk] = eid; 3674 } 3675 } 3676 } 3677 } 3678 3679 // Along umax axis 3680 minID = wRowStart + (bpinfo[2] - 1); 3681 maxID = wRowStart + (bpinfo[2] * bpinfo[5]) - 1; 3682 cpV1 = cp_vertex[minID]; 3683 cpV2 = cp_vertex[maxID]; 3684 for (int jj = 0; jj < Ne; ++jj) { 3685 ego edge = eobjs[jj]; 3686 ego egeom, *nobjs; 3687 int eoclass, emtype, Nn, *nsenses; 3688 int n1ID, n2ID, eid; 3689 3690 if (islite) { 3691 eid = EGlite_indexBodyTopo(body, edge); 3692 PetscCallEGADS(EGlite_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3693 } else { 3694 eid = EG_indexBodyTopo(body, edge); 3695 PetscCallEGADS(EG_getTopology, (edge, &egeom, &eoclass, &emtype, NULL, &Nn, &nobjs, &nsenses)); 3696 } 3697 3698 if (emtype != DEGENERATE) { 3699 // Get IDs for current Edge's End Vertices 3700 if (islite) { 3701 n1ID = EGlite_indexBodyTopo(body, nobjs[0]); 3702 n2ID = EGlite_indexBodyTopo(body, nobjs[1]); 3703 } else { 3704 n1ID = EG_indexBodyTopo(body, nobjs[0]); 3705 n2ID = EG_indexBodyTopo(body, nobjs[1]); 3706 } 3707 3708 if ((cpV1 == n1ID || cpV1 == n2ID) && (cpV2 == n1ID || cpV2 == n2ID)) { 3709 for (int kk = minID + bpinfo[2]; kk < maxID; kk += bpinfo[2]) { 3710 cp_edge[kk] = eid; 3711 w_edge[kk] = eid; 3712 } 3713 } 3714 } 3715 } 3716 // These two lines could be replaced with DMPlexFreeGeomObject() 3717 if (islite) EGlite_free(eobjs); 3718 else EG_free(eobjs); 3719 } 3720 3721 // Determine Control Point Equivalance Matrix relating Control Points between Surfaces 3722 // Note: The Weights will also be tied together in the same manner 3723 // Also can use the Weight Hash Table for Row Start ID of each Face 3724 const PetscInt cpRowSize = totalNumCPs; 3725 const PetscInt cpColSize = cpRowSize; 3726 PetscInt *maxNumRelatePtr; 3727 PetscInt maxNumRelate = 0; 3728 3729 // Create Point Surface Gradient Matrix 3730 PetscCall(MatCreate(PETSC_COMM_WORLD, &cpEquiv)); 3731 PetscCall(MatSetSizes(cpEquiv, PETSC_DECIDE, PETSC_DECIDE, cpRowSize, cpColSize)); 3732 PetscCall(MatSetType(cpEquiv, MATAIJ)); 3733 PetscCall(MatSetUp(cpEquiv)); 3734 3735 for (int ii = 0; ii < totalNumCPs; ++ii) { 3736 PetscScalar x1, y1, z1; 3737 PetscInt maxRelateTemp = 0; 3738 3739 x1 = cntrlPtCoords[(3 * ii) + 0]; 3740 y1 = cntrlPtCoords[(3 * ii) + 1]; 3741 z1 = cntrlPtCoords[(3 * ii) + 2]; 3742 3743 for (int jj = 0; jj < totalNumCPs; ++jj) { 3744 PetscScalar x2, y2, z2; 3745 PetscScalar cpDelta, eqFactor; 3746 x2 = cntrlPtCoords[(3 * jj) + 0]; 3747 y2 = cntrlPtCoords[(3 * jj) + 1]; 3748 z2 = cntrlPtCoords[(3 * jj) + 2]; 3749 3750 cpDelta = PetscSqrtReal(PetscSqr(x2 - x1) + PetscSqr(y2 - y1) + PetscSqr(z2 - z1)); 3751 if (cpDelta < 1.0E-15) { 3752 eqFactor = 1.0; 3753 maxRelateTemp += 1; 3754 } else { 3755 eqFactor = 0.0; 3756 } 3757 3758 // Store Results in Petsc Matrix 3759 PetscCall(MatSetValue(cpEquiv, ii, jj, eqFactor, INSERT_VALUES)); 3760 } 3761 if (maxRelateTemp > maxNumRelate) maxNumRelate = maxRelateTemp; 3762 } 3763 maxNumRelatePtr = &maxNumRelate; 3764 PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, &cntrlPtCoords)); 3765 3766 // Assemble Point Surface Grad Matrix 3767 PetscCall(MatAssemblyBegin(cpEquiv, MAT_FINAL_ASSEMBLY)); 3768 PetscCall(MatAssemblyEnd(cpEquiv, MAT_FINAL_ASSEMBLY)); 3769 3770 // Attach Control Point and Weight Data to DM 3771 { 3772 PetscContainer cpOrgObj, cpCoordLengthObj; 3773 PetscContainer wOrgObj, wDataLengthObj; 3774 PetscContainer cp_faceObj, cp_edgeObj, cp_vertexObj; 3775 PetscContainer w_faceObj, w_edgeObj, w_vertexObj; 3776 PetscContainer maxNumRelateObj; 3777 3778 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpOrgObj)); 3779 if (!cpOrgObj) { 3780 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpOrgObj)); 3781 PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 3782 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Hash Table", (PetscObject)cpOrgObj)); 3783 PetscCall(PetscContainerDestroy(&cpOrgObj)); 3784 } else { 3785 PetscCall(PetscContainerSetPointer(cpOrgObj, faceCntrlPtRow_Start)); 3786 } 3787 3788 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinates", (PetscObject)cntrlPtCoordsVec)); 3789 PetscCall(VecDestroy(&cntrlPtCoordsVec)); 3790 3791 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordLengthObj)); 3792 if (!cpCoordLengthObj) { 3793 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cpCoordLengthObj)); 3794 PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 3795 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject)cpCoordLengthObj)); 3796 PetscCall(PetscContainerDestroy(&cpCoordLengthObj)); 3797 } else { 3798 PetscCall(PetscContainerSetPointer(cpCoordLengthObj, cpCoordDataLengthPtr)); 3799 } 3800 3801 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wOrgObj)); 3802 if (!wOrgObj) { 3803 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wOrgObj)); 3804 PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 3805 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject)wOrgObj)); 3806 PetscCall(PetscContainerDestroy(&wOrgObj)); 3807 } else { 3808 PetscCall(PetscContainerSetPointer(wOrgObj, faceCPWeightsRow_Start)); 3809 } 3810 3811 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data", (PetscObject)cntrlPtWeightsVec)); 3812 PetscCall(VecDestroy(&cntrlPtWeightsVec)); 3813 3814 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 3815 if (!wDataLengthObj) { 3816 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &wDataLengthObj)); 3817 PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 3818 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight Data Length", (PetscObject)wDataLengthObj)); 3819 PetscCall(PetscContainerDestroy(&wDataLengthObj)); 3820 } else { 3821 PetscCall(PetscContainerSetPointer(wDataLengthObj, wDataLengthPtr)); 3822 } 3823 3824 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Equivalancy Matrix", (PetscObject)cpEquiv)); 3825 3826 PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 3827 if (!maxNumRelateObj) { 3828 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &maxNumRelateObj)); 3829 PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 3830 PetscCall(PetscObjectCompose((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject)maxNumRelateObj)); 3831 PetscCall(PetscContainerDestroy(&maxNumRelateObj)); 3832 } else { 3833 PetscCall(PetscContainerSetPointer(maxNumRelateObj, maxNumRelatePtr)); 3834 } 3835 3836 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cp_faceObj)); 3837 if (!cp_faceObj) { 3838 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_faceObj)); 3839 PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 3840 PetscCall(PetscContainerSetCtxDestroy(cp_faceObj, PetscCtxDestroyDefault)); 3841 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Face Map", (PetscObject)cp_faceObj)); 3842 PetscCall(PetscContainerDestroy(&cp_faceObj)); 3843 } else { 3844 void *tmp; 3845 3846 PetscCall(PetscContainerGetPointer(cp_faceObj, &tmp)); 3847 PetscCall(PetscFree(tmp)); 3848 PetscCall(PetscContainerSetPointer(cp_faceObj, cp_face)); 3849 } 3850 3851 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&w_faceObj)); 3852 if (!w_faceObj) { 3853 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_faceObj)); 3854 PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 3855 PetscCall(PetscContainerSetCtxDestroy(w_faceObj, PetscCtxDestroyDefault)); 3856 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject)w_faceObj)); 3857 PetscCall(PetscContainerDestroy(&w_faceObj)); 3858 } else { 3859 void *tmp; 3860 3861 PetscCall(PetscContainerGetPointer(w_faceObj, &tmp)); 3862 PetscCall(PetscFree(tmp)); 3863 PetscCall(PetscContainerSetPointer(w_faceObj, w_face)); 3864 } 3865 3866 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cp_edgeObj)); 3867 if (!cp_edgeObj) { 3868 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_edgeObj)); 3869 PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 3870 PetscCall(PetscContainerSetCtxDestroy(cp_edgeObj, PetscCtxDestroyDefault)); 3871 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Edge Map", (PetscObject)cp_edgeObj)); 3872 PetscCall(PetscContainerDestroy(&cp_edgeObj)); 3873 } else { 3874 void *tmp; 3875 3876 PetscCall(PetscContainerGetPointer(cp_edgeObj, &tmp)); 3877 PetscCall(PetscFree(tmp)); 3878 PetscCall(PetscContainerSetPointer(cp_edgeObj, cp_edge)); 3879 } 3880 3881 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&w_edgeObj)); 3882 if (!w_edgeObj) { 3883 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_edgeObj)); 3884 PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 3885 PetscCall(PetscContainerSetCtxDestroy(w_edgeObj, PetscCtxDestroyDefault)); 3886 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject)w_edgeObj)); 3887 PetscCall(PetscContainerDestroy(&w_edgeObj)); 3888 } else { 3889 void *tmp; 3890 3891 PetscCall(PetscContainerGetPointer(w_edgeObj, &tmp)); 3892 PetscCall(PetscFree(tmp)); 3893 PetscCall(PetscContainerSetPointer(w_edgeObj, w_edge)); 3894 } 3895 3896 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cp_vertexObj)); 3897 if (!cp_vertexObj) { 3898 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &cp_vertexObj)); 3899 PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 3900 PetscCall(PetscContainerSetCtxDestroy(cp_vertexObj, PetscCtxDestroyDefault)); 3901 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point - Vertex Map", (PetscObject)cp_vertexObj)); 3902 PetscCall(PetscContainerDestroy(&cp_vertexObj)); 3903 } else { 3904 void *tmp; 3905 3906 PetscCall(PetscContainerGetPointer(cp_vertexObj, &tmp)); 3907 PetscCall(PetscFree(tmp)); 3908 PetscCall(PetscContainerSetPointer(cp_vertexObj, cp_vertex)); 3909 } 3910 3911 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&w_vertexObj)); 3912 if (!w_vertexObj) { 3913 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &w_vertexObj)); 3914 PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 3915 PetscCall(PetscContainerSetCtxDestroy(w_vertexObj, PetscCtxDestroyDefault)); 3916 PetscCall(PetscObjectCompose((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject)w_vertexObj)); 3917 PetscCall(PetscContainerDestroy(&w_vertexObj)); 3918 } else { 3919 void *tmp; 3920 3921 PetscCall(PetscContainerGetPointer(w_vertexObj, &tmp)); 3922 PetscCall(PetscFree(tmp)); 3923 PetscCall(PetscContainerSetPointer(w_vertexObj, w_vertex)); 3924 } 3925 } 3926 3927 // Define Matrix to store Geometry Gradient information dGeom_i/dCPj_i 3928 PetscInt gcntr = 0; 3929 const PetscInt rowSize = 3 * maxNumCPs * totalNumPoints; 3930 const PetscInt colSize = 4 * Nf; 3931 3932 // Create Point Surface Gradient Matrix 3933 PetscCall(MatCreate(PETSC_COMM_WORLD, &pointSurfGrad)); 3934 PetscCall(MatSetSizes(pointSurfGrad, PETSC_DECIDE, PETSC_DECIDE, rowSize, colSize)); 3935 PetscCall(MatSetType(pointSurfGrad, MATAIJ)); 3936 PetscCall(MatSetUp(pointSurfGrad)); 3937 3938 // Create Hash Table to store Point's stare row in surfaceGrad[][] 3939 PetscCall(PetscHMapICreate(&pointSurfGradRow_Start)); 3940 3941 // Get Coordinates for the DMPlex point 3942 DM cdm; 3943 PetscInt dE, Nv; 3944 Vec coordinatesLocal; 3945 PetscScalar *coords = NULL; 3946 3947 PetscCall(DMGetCoordinateDM(dm, &cdm)); 3948 PetscCall(DMGetCoordinateDim(dm, &dE)); 3949 PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 3950 3951 // CYCLE THROUGH FACEs 3952 PetscScalar maxGrad = 0.; 3953 PetscCall(VecGetArrayWrite(gradSACPVec, &gradSACP)); 3954 PetscCall(VecGetArrayWrite(gradSAWVec, &gradSAW)); 3955 PetscCall(VecGetArrayWrite(gradVCPVec, &gradVCP)); 3956 PetscCall(VecGetArrayWrite(gradVWVec, &gradVW)); 3957 for (int f = 0; f < Nf; ++f) { 3958 ego face = fobjs[f]; 3959 ego *eobjs, *nobjs; 3960 PetscInt fid, Ne, Nn; 3961 DMLabel faceLabel, edgeLabel, nodeLabel; 3962 PetscHMapI currFaceUniquePoints = NULL; 3963 IS facePoints, edgePoints, nodePoints; 3964 const PetscInt *fIndices, *eIndices, *nIndices; 3965 PetscInt fSize, eSize, nSize; 3966 PetscHashIter fHashKeyIter, eHashKeyIter, nHashKeyIter, pHashKeyIter; 3967 PetscBool fHashKeyFound, eHashKeyFound, nHashKeyFound, pHashKeyFound; 3968 PetscInt cfCntr = 0; 3969 3970 // Get Geometry Object for the Current FACE 3971 if (islite) { 3972 PetscCall(EGlite_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3973 PetscCall(EGlite_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3974 } else { 3975 PetscCall(EG_getTopology(face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 3976 PetscCall(EG_getGeometry(fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 3977 } 3978 3979 // Get all EDGE and NODE objects attached to the current FACE 3980 if (islite) { 3981 PetscCall(EGlite_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3982 PetscCall(EGlite_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3983 } else { 3984 PetscCall(EG_getBodyTopos(body, face, EDGE, &Ne, &eobjs)); 3985 PetscCall(EG_getBodyTopos(body, face, NODE, &Nn, &nobjs)); 3986 } 3987 3988 // Get all DMPlex Points that have DMLabel "EGADS Face ID" and store them in a Hash Table for later use 3989 if (islite) { 3990 fid = EGlite_indexBodyTopo(body, face); 3991 } else { 3992 fid = EG_indexBodyTopo(body, face); 3993 } 3994 3995 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 3996 PetscCall(DMLabelGetStratumIS(faceLabel, fid, &facePoints)); 3997 PetscCall(ISGetIndices(facePoints, &fIndices)); 3998 PetscCall(ISGetSize(facePoints, &fSize)); 3999 4000 PetscCall(PetscHMapICreate(&currFaceUniquePoints)); 4001 4002 for (int jj = 0; jj < fSize; ++jj) { 4003 PetscCall(PetscHMapIFind(currFaceUniquePoints, fIndices[jj], &fHashKeyIter, &fHashKeyFound)); 4004 4005 if (!fHashKeyFound) { 4006 PetscCall(PetscHMapISet(currFaceUniquePoints, fIndices[jj], cfCntr)); 4007 cfCntr += 1; 4008 } 4009 4010 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, fIndices[jj], &pHashKeyIter, &pHashKeyFound)); 4011 4012 if (!pHashKeyFound) { 4013 PetscCall(PetscHMapISet(pointSurfGradRow_Start, fIndices[jj], gcntr)); 4014 gcntr += 3 * maxNumCPs; 4015 } 4016 } 4017 PetscCall(ISRestoreIndices(facePoints, &fIndices)); 4018 PetscCall(ISDestroy(&facePoints)); 4019 4020 // Get all DMPlex Points that have DMLable "EGADS Edge ID" attached to the current FACE and store them in a Hash Table for later use. 4021 for (int jj = 0; jj < Ne; ++jj) { 4022 ego edge = eobjs[jj]; 4023 PetscBool containLabelValue; 4024 4025 if (islite) { 4026 id = EGlite_indexBodyTopo(body, edge); 4027 } else { 4028 id = EG_indexBodyTopo(body, edge); 4029 } 4030 4031 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4032 PetscCall(DMLabelHasValue(edgeLabel, id, &containLabelValue)); 4033 4034 if (containLabelValue) { 4035 PetscCall(DMLabelGetStratumIS(edgeLabel, id, &edgePoints)); 4036 PetscCall(ISGetIndices(edgePoints, &eIndices)); 4037 PetscCall(ISGetSize(edgePoints, &eSize)); 4038 4039 for (int kk = 0; kk < eSize; ++kk) { 4040 PetscCall(PetscHMapIFind(currFaceUniquePoints, eIndices[kk], &eHashKeyIter, &eHashKeyFound)); 4041 4042 if (!eHashKeyFound) { 4043 PetscCall(PetscHMapISet(currFaceUniquePoints, eIndices[kk], cfCntr)); 4044 cfCntr += 1; 4045 } 4046 4047 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, eIndices[kk], &pHashKeyIter, &pHashKeyFound)); 4048 4049 if (!pHashKeyFound) { 4050 PetscCall(PetscHMapISet(pointSurfGradRow_Start, eIndices[kk], gcntr)); 4051 gcntr += 3 * maxNumCPs; 4052 } 4053 } 4054 PetscCall(ISRestoreIndices(edgePoints, &eIndices)); 4055 PetscCall(ISDestroy(&edgePoints)); 4056 } 4057 } 4058 4059 // Get all DMPlex Points that have DMLabel "EGADS Vertex ID" attached to the current FACE and store them in a Hash Table for later use. 4060 for (int jj = 0; jj < Nn; ++jj) { 4061 ego node = nobjs[jj]; 4062 4063 if (islite) { 4064 id = EGlite_indexBodyTopo(body, node); 4065 } else { 4066 id = EG_indexBodyTopo(body, node); 4067 } 4068 4069 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &nodeLabel)); 4070 PetscCall(DMLabelGetStratumIS(nodeLabel, id, &nodePoints)); 4071 PetscCall(ISGetIndices(nodePoints, &nIndices)); 4072 PetscCall(ISGetSize(nodePoints, &nSize)); 4073 4074 for (int kk = 0; kk < nSize; ++kk) { 4075 PetscCall(PetscHMapIFind(currFaceUniquePoints, nIndices[kk], &nHashKeyIter, &nHashKeyFound)); 4076 4077 if (!nHashKeyFound) { 4078 PetscCall(PetscHMapISet(currFaceUniquePoints, nIndices[kk], cfCntr)); 4079 cfCntr += 1; 4080 } 4081 4082 PetscCall(PetscHMapIFind(pointSurfGradRow_Start, nIndices[kk], &pHashKeyIter, &pHashKeyFound)); 4083 if (!pHashKeyFound) { 4084 PetscCall(PetscHMapISet(pointSurfGradRow_Start, nIndices[kk], gcntr)); 4085 gcntr += 3 * maxNumCPs; 4086 } 4087 } 4088 PetscCall(ISRestoreIndices(nodePoints, &nIndices)); 4089 PetscCall(ISDestroy(&nodePoints)); 4090 } 4091 4092 // Get the Total Number of entries in the Hash Table 4093 PetscInt currFaceUPSize; 4094 PetscCall(PetscHMapIGetSize(currFaceUniquePoints, &currFaceUPSize)); 4095 4096 // Get Keys 4097 PetscInt currFaceUPKeys[currFaceUPSize], off = 0; 4098 PetscCall(PetscHMapIGetKeys(currFaceUniquePoints, &off, currFaceUPKeys)); 4099 PetscCall(PetscHMapIDestroy(&currFaceUniquePoints)); 4100 4101 // Get Current Face Surface Area 4102 PetscScalar fSA, faceData[14]; 4103 PetscCall(EG_getMassProperties(face, faceData)); // This doesn't have a EGlite version. Will it work for EGADSlite files?? KNOWN_ISSUE 4104 fSA = faceData[1]; 4105 4106 // Get Start Row in cpEquiv Matrix 4107 PetscHashIter Witer; 4108 PetscBool Wfound; 4109 PetscInt faceWStartRow; 4110 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 4111 PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4112 PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 4113 4114 // Cycle through all points on the current FACE 4115 for (int jj = 0; jj < currFaceUPSize; ++jj) { 4116 PetscInt currPointID = currFaceUPKeys[jj]; 4117 PetscCall(DMPlexVecGetClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 4118 4119 // Get UV position of FACE 4120 double params[2], range[4], eval[18]; 4121 int peri; 4122 4123 if (islite) PetscCall(EGlite_getRange(face, range, &peri)); 4124 else PetscCall(EG_getRange(face, range, &peri)); 4125 4126 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 4127 4128 if (islite) PetscCall(EGlite_evaluate(face, params, eval)); 4129 else PetscCall(EG_evaluate(face, params, eval)); 4130 4131 // Make a new SURFACE Geometry by changing the location of the Control Points 4132 int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 4133 double nbprv[prvSize]; 4134 4135 // Cycle through each Control Point 4136 double denomNew, denomOld; 4137 double deltaCoord = 1.0E-4; 4138 int offset = bpinfo[3] + bpinfo[6]; 4139 int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 4140 for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { 4141 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d", f, jj, ii); 4142 #if 0 4143 // Cycle through each direction (x, then y, then z) 4144 if (jj == 0) { 4145 // Get the Number Control Points that are the same as the current points 4146 // We are looking for repeated Control Points 4147 PetscInt commonCPcntr = 0; 4148 for (int mm = 0; mm < bpinfo[2]*bpinfo[5]; ++mm) { 4149 PetscScalar matValue; 4150 PetscCall(MatGetValue(cpEquiv, faceWStartRow + ii, faceWStartRow + mm, &matValue)); 4151 4152 if (matValue > 0.0) commonCPcntr += 1; 4153 } 4154 } 4155 #endif 4156 4157 for (int kk = 0; kk < 4; ++kk) { 4158 // Reinitialize nbprv[] values because we only want to change one value at a time 4159 for (int mm = 0; mm < prvSize; ++mm) { nbprv[mm] = bprv[mm]; } 4160 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4161 4162 if (kk == 0) { //X 4163 nbprv[offset + 0] = bprv[offset + 0] + deltaCoord; 4164 nbprv[offset + 1] = bprv[offset + 1]; 4165 nbprv[offset + 2] = bprv[offset + 2]; 4166 denomNew = nbprv[offset + 0]; 4167 denomOld = bprv[offset + 0]; 4168 } else if (kk == 1) { //Y 4169 nbprv[offset + 0] = bprv[offset + 0]; 4170 nbprv[offset + 1] = bprv[offset + 1] + deltaCoord; 4171 nbprv[offset + 2] = bprv[offset + 2]; 4172 denomNew = nbprv[offset + 1]; 4173 denomOld = bprv[offset + 1]; 4174 } else if (kk == 2) { //Z 4175 nbprv[offset + 0] = bprv[offset + 0]; 4176 nbprv[offset + 1] = bprv[offset + 1]; 4177 nbprv[offset + 2] = bprv[offset + 2] + deltaCoord; 4178 denomNew = nbprv[offset + 2]; 4179 denomOld = bprv[offset + 2]; 4180 } else if (kk == 3) { // Weights 4181 nbprv[wOffset + ii] = bprv[wOffset + ii] + deltaCoord; 4182 denomNew = nbprv[wOffset + ii]; 4183 denomOld = bprv[wOffset + ii]; 4184 } else { 4185 // currently do nothing 4186 } 4187 4188 // Create New Surface Based on New Control Points or Weights 4189 ego newgeom, context; 4190 PetscCallEGADS(EG_getContext, (face, &context)); // This does not have an EGlite_ version KNOWN_ISSUE 4191 PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // This does not have an EGlite_ version KNOWN_ISSUE 4192 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4193 4194 // Evaluate new (x, y, z) Point Position based on new Surface Definition 4195 double newCoords[18]; 4196 if (islite) PetscCall(EGlite_getRange(newgeom, range, &peri)); 4197 else PetscCall(EG_getRange(newgeom, range, &peri)); 4198 4199 PetscCall(DMPlex_Geom_FACE_XYZtoUV_Internal(coords, face, range, 0, dE, params, islite)); 4200 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4201 4202 if (islite) PetscCall(EGlite_evaluate(newgeom, params, newCoords)); 4203 else PetscCall(EG_evaluate(newgeom, params, newCoords)); 4204 4205 // Calculate Surface Area Gradients wrt Control Points and Weights using the local discrete FACE only 4206 // NOTE 1: Will not provide Volume Gradient wrt to Control Points and Weights. 4207 // NOTE 2: This is faster than below where an entire new solid geometry is created for each 4208 // Control Point and Weight gradient 4209 if (!fullGeomGrad) { 4210 // Create new FACE based on new SURFACE geometry 4211 if (jj == 0) { // only for 1st DMPlex Point because we only per CP or Weight 4212 double newFaceRange[4]; 4213 int newFacePeri; 4214 if (islite) PetscCall(EGlite_getRange(newgeom, newFaceRange, &newFacePeri)); 4215 else PetscCall(EG_getRange(newgeom, newFaceRange, &newFacePeri)); 4216 4217 ego newface; 4218 PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have EGlite version KNOWN_ISSUE 4219 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4220 4221 // Get New Face Surface Area 4222 PetscScalar newfSA, newFaceData[14]; 4223 PetscCall(EG_getMassProperties(newface, newFaceData)); // Does not have EGlite version KNOWN_ISSUE 4224 newfSA = newFaceData[1]; 4225 PetscCallEGADS(EG_deleteObject, (newface)); 4226 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face %d is corrupted: %d %d %d", f, jj, ii, kk); 4227 4228 // Update Control Points 4229 PetscHashIter CPiter, Witer; 4230 PetscBool CPfound, Wfound; 4231 PetscInt faceCPStartRow, faceWStartRow; 4232 4233 PetscScalar dSAdCPi; 4234 dSAdCPi = (newfSA - fSA) / (denomNew - denomOld); 4235 4236 if (kk < 3) { 4237 PetscCall(PetscHMapIFind(faceCntrlPtRow_Start, fid, &CPiter, &CPfound)); 4238 PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4239 PetscCall(PetscHMapIGet(faceCntrlPtRow_Start, fid, &faceCPStartRow)); 4240 4241 gradSACP[faceCPStartRow + (ii * 3) + kk] = dSAdCPi; 4242 4243 if (PetscAbsReal(dSAdCPi) > maxGrad) maxGrad = PetscAbsReal(dSAdCPi); 4244 4245 } else if (kk == 3) { 4246 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, fid, &Witer, &Wfound)); 4247 PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4248 PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, fid, &faceWStartRow)); 4249 4250 gradSAW[faceWStartRow + ii] = dSAdCPi; 4251 4252 } else { 4253 // Do Nothing 4254 } 4255 } 4256 } 4257 PetscCallEGADS(EG_deleteObject, (newgeom)); 4258 4259 // Now Calculate the Surface Gradient for the change in x-component Control Point 4260 PetscScalar dxdCx = (newCoords[0] - coords[0]) / deltaCoord; 4261 PetscScalar dxdCy = (newCoords[1] - coords[1]) / deltaCoord; 4262 PetscScalar dxdCz = (newCoords[2] - coords[2]) / deltaCoord; 4263 4264 // Store Gradient Information in surfaceGrad[][] Matrix 4265 PetscInt startRow; 4266 PetscCall(PetscHMapIGet(pointSurfGradRow_Start, currPointID, &startRow)); 4267 4268 // Store Results in Petsc Matrix 4269 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 0, ((fid - 1) * 4) + kk, dxdCx, INSERT_VALUES)); 4270 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 1, ((fid - 1) * 4) + kk, dxdCy, INSERT_VALUES)); 4271 PetscCall(MatSetValue(pointSurfGrad, startRow + (ii * 3) + 2, ((fid - 1) * 4) + kk, dxdCz, INSERT_VALUES)); 4272 4273 //PetscCallEGADS(EG_deleteObject, (newgeom)); 4274 PetscCheck(face->blind, PETSC_COMM_SELF, PETSC_ERR_LIB, "Face is corrupted"); 4275 } 4276 offset += 3; 4277 } 4278 PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coordinatesLocal, currPointID, &Nv, &coords)); 4279 } 4280 } 4281 4282 // Assemble Point Surface Grad Matrix 4283 PetscCall(MatAssemblyBegin(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 4284 PetscCall(MatAssemblyEnd(pointSurfGrad, MAT_FINAL_ASSEMBLY)); 4285 4286 if (fullGeomGrad) { 4287 // Calculate Surface Area and Volume Control Point and Control Point Weight Gradients 4288 // Note: This is much slower than above due to a new solid geometry being created for 4289 // each change in Control Point and Control Point Weight. However, this method 4290 // will provide the Volume Gradient. 4291 4292 // Get Current Face Surface Area 4293 PetscScalar bodyVol, bodySA, bodyData[14]; 4294 PetscCall(EG_getMassProperties(body, bodyData)); // Does not have an EGlite versin KNOWN_ISSUE 4295 bodyVol = bodyData[0]; 4296 bodySA = bodyData[1]; 4297 4298 // Cycle through Control Points 4299 for (int ii = 0; ii < totalNumCPs; ++ii) { // ii should also be the row in cpEquiv for the Control Point 4300 // Cycle through X, Y, Z, W changes 4301 for (int jj = 0; jj < 4; ++jj) { 4302 // Cycle Through Faces 4303 double denomNew = 0.0, denomOld = 0.0; 4304 double deltaCoord = 1.0E-4; 4305 ego newGeom[Nf]; 4306 ego newFaces[Nf]; 4307 for (int kk = 0; kk < Nf; ++kk) { 4308 ego face; 4309 PetscInt currFID = kk + 1; 4310 4311 if (islite) { 4312 // Get Current FACE 4313 PetscCallEGADS(EGlite_objectBodyTopo, (body, FACE, currFID, &face)); 4314 4315 // Get Geometry Object for the Current FACE 4316 PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 4317 PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4318 } else { 4319 // Get Current FACE 4320 PetscCallEGADS(EG_objectBodyTopo, (body, FACE, currFID, &face)); 4321 4322 // Get Geometry Object for the Current FACE 4323 PetscCallEGADS(EG_getTopology, (face, &fgeom, &foclass, &fmtype, fdata, &Nl, &lobjs, &lsenses)); 4324 PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4325 } 4326 4327 // Make a new SURFACE Geometry by changing the location of the Control Points 4328 int prvSize = bpinfo[3] + bpinfo[6] + (4 * bpinfo[2] * bpinfo[5]); 4329 double nbprv[prvSize]; 4330 4331 // Reinitialize nbprv[] values because we only want to change one value at a time 4332 for (int mm = 0; mm < prvSize; ++mm) nbprv[mm] = bprv[mm]; 4333 4334 // Get Control Point Row and Column Start for cpEquiv 4335 PetscHashIter Witer; 4336 PetscBool Wfound; 4337 PetscInt faceWStartRow; 4338 PetscCall(PetscHMapIFind(faceCPWeightsRow_Start, currFID, &Witer, &Wfound)); 4339 PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4340 PetscCall(PetscHMapIGet(faceCPWeightsRow_Start, currFID, &faceWStartRow)); 4341 4342 // Modify the Current Control Point on this FACE and All Other FACES 4343 // IMPORTANT!!! If you do not move all identical Control Points on other FACES 4344 // you will not generate a solid body. You will generate a set of 4345 // disconnected surfaces that have gap(s) between them. 4346 int offset = bpinfo[3] + bpinfo[6]; 4347 int wOffset = offset + (3 * bpinfo[2] * bpinfo[5]); 4348 for (int mm = 0; mm < bpinfo[2] * bpinfo[5]; ++mm) { 4349 PetscScalar matValue; 4350 PetscCall(MatGetValue(cpEquiv, ii, faceWStartRow + mm, &matValue)); 4351 4352 if (matValue > 0.0) { 4353 if (jj == 0) { //X 4354 nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0] + deltaCoord; 4355 nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 4356 nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 4357 denomNew = nbprv[offset + (3 * mm) + 0]; 4358 denomOld = bprv[offset + (3 * mm) + 0]; 4359 } else if (jj == 1) { //Y 4360 nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 4361 nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1] + deltaCoord; 4362 nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2]; 4363 denomNew = nbprv[offset + (3 * mm) + 1]; 4364 denomOld = bprv[offset + (3 * mm) + 1]; 4365 } else if (jj == 2) { //Z 4366 nbprv[offset + (3 * mm) + 0] = bprv[offset + (3 * mm) + 0]; 4367 nbprv[offset + (3 * mm) + 1] = bprv[offset + (3 * mm) + 1]; 4368 nbprv[offset + (3 * mm) + 2] = bprv[offset + (3 * mm) + 2] + deltaCoord; 4369 denomNew = nbprv[offset + (3 * mm) + 2]; 4370 denomOld = bprv[offset + (3 * mm) + 2]; 4371 } else if (jj == 3) { // Weights 4372 nbprv[wOffset + mm] = bprv[wOffset + mm] + deltaCoord; 4373 denomNew = nbprv[wOffset + mm]; 4374 denomOld = bprv[wOffset + mm]; 4375 } else { 4376 // currently do nothing 4377 } 4378 } 4379 } 4380 4381 // Create New Surface Based on New Control Points or Weights 4382 ego newgeom, context; 4383 PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ versions KNOWN_ISSUE 4384 PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, nbprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 4385 4386 // Create New FACE based on modified geometry 4387 double newFaceRange[4]; 4388 int newFacePeri; 4389 if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, newFaceRange, &newFacePeri)); 4390 else PetscCallEGADS(EG_getRange, (newgeom, newFaceRange, &newFacePeri)); 4391 4392 ego newface; 4393 PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, newFaceRange, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 4394 4395 // store new face for later assembly 4396 newGeom[kk] = newgeom; 4397 newFaces[kk] = newface; 4398 } 4399 4400 // X-WANT TO BUILD THE NEW GEOMETRY, X-GET NEW SA AND PERFORM dSA/dCPi CALCS HERE <--- 4401 // Sew New Faces together to get a new model 4402 ego newmodel; 4403 PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 4404 4405 // Get Surface Area and Volume of New/Updated Solid Body 4406 PetscScalar newData[14]; 4407 if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4408 else PetscCallEGADS(EG_getTopology, (newmodel, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4409 4410 ego nbody = bodies[0]; 4411 PetscCall(EG_getMassProperties(nbody, newData)); // Does not have an EGlite_ version KNOWN_ISSUE 4412 4413 PetscScalar dSAdCPi, dVdCPi; 4414 PetscScalar nbodyVol = newData[0], nbodySA = newData[1]; 4415 4416 // Calculate Gradients wrt to Control Points and Control Points Weights depending on jj value 4417 dSAdCPi = (nbodySA - bodySA) / (denomNew - denomOld); 4418 dVdCPi = (nbodyVol - bodyVol) / (denomNew - denomOld); 4419 4420 if (jj < 3) { 4421 // Gradienst wrt to Control Points 4422 gradSACP[(ii * 3) + jj] = dSAdCPi; 4423 gradVCP[(ii * 3) + jj] = dVdCPi; 4424 } else if (jj == 3) { 4425 // Gradients wrt to Control Point Weights 4426 gradSAW[ii] = dSAdCPi; 4427 gradVW[ii] = dVdCPi; 4428 } else { 4429 // Do Nothing 4430 } 4431 PetscCallEGADS(EG_deleteObject, (newmodel)); 4432 for (int kk = 0; kk < Nf; ++kk) { 4433 PetscCallEGADS(EG_deleteObject, (newFaces[kk])); 4434 PetscCallEGADS(EG_deleteObject, (newGeom[kk])); 4435 } 4436 } 4437 } 4438 } 4439 PetscCall(VecRestoreArrayWrite(gradSACPVec, &gradSACP)); 4440 PetscCall(VecRestoreArrayWrite(gradSAWVec, &gradSAW)); 4441 PetscCall(VecRestoreArrayWrite(gradVCPVec, &gradVCP)); 4442 PetscCall(VecRestoreArrayWrite(gradVWVec, &gradVW)); 4443 PetscCall(MatDestroy(&cpEquiv)); 4444 4445 // Attach Surface Gradient Hash Table and Matrix to DM 4446 { 4447 PetscContainer surfGradOrgObj; 4448 4449 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&surfGradOrgObj)); 4450 if (!surfGradOrgObj) { 4451 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &surfGradOrgObj)); 4452 PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 4453 PetscCall(PetscContainerSetCtxDestroy(surfGradOrgObj, DestroyHashMap)); 4454 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject)surfGradOrgObj)); 4455 PetscCall(PetscContainerDestroy(&surfGradOrgObj)); 4456 } else { 4457 PetscCall(PetscContainerSetPointer(surfGradOrgObj, pointSurfGradRow_Start)); 4458 } 4459 4460 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Gradient Matrix", (PetscObject)pointSurfGrad)); 4461 PetscCall(MatDestroy(&pointSurfGrad)); 4462 4463 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject)gradSACPVec)); 4464 PetscCall(VecDestroy(&gradSACPVec)); 4465 4466 PetscCall(PetscObjectCompose((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject)gradSAWVec)); 4467 PetscCall(VecDestroy(&gradSAWVec)); 4468 4469 if (fullGeomGrad) { 4470 PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Control Point Gradient", (PetscObject)gradVCPVec)); 4471 PetscCall(PetscObjectCompose((PetscObject)dm, "Volume Weights Gradient", (PetscObject)gradVWVec)); 4472 } 4473 PetscCall(VecDestroy(&gradVCPVec)); 4474 PetscCall(VecDestroy(&gradVWVec)); 4475 } 4476 4477 // Could be replaced with DMPlexFreeGeomObject() 4478 if (islite) EGlite_free(fobjs); 4479 else EG_free(fobjs); 4480 PetscFunctionReturn(PETSC_SUCCESS); 4481 #else 4482 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 4483 #endif 4484 } 4485 4486 /*@C 4487 DMPlexModifyGeomModel - Generates a new EGADS geometry model based in user provided Control Points and Control Points Weights. Optionally, the function will inflate the DM to the new geometry and save the new geometry to a file. 4488 4489 Collective 4490 4491 Input Parameters: 4492 + dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 4493 . comm - MPI_Comm object 4494 . newCP - C Array of [x, y, z] New/Updated Control Point Coordinates defining the geometry (See DMPlexGeomDataAndGrads() for format) 4495 . newW - C Array of New/Updated Control Point Weights associated with the Control Points defining the new geometry (See DMPlexGemGrads() for format) 4496 . autoInflate - PetscBool Flag denoting if the user would like to inflate the DM points to the new geometry. 4497 . saveGeom - PetscBool Flag denoting if the user would iike to save the new geometry to a file. 4498 - stpName - Char Array indicating the name of the file to save the new geometry to. Extension must be included and will denote type of file written. 4499 *.stp or *.step = STEP File 4500 *.igs or *.iges = IGES File 4501 *.egads = EGADS File 4502 *.brep = BRep File (OpenCASCADE File) 4503 4504 Output Parameter: 4505 . dm - The updated DM object representing the mesh with PetscContainers containing the updated/modified geometry 4506 4507 Level: intermediate 4508 4509 Note: 4510 Functionality not available for DMPlexes with attached EGADSlite geometry files (.egadslite). 4511 4512 .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 4513 @*/ 4514 PetscErrorCode DMPlexModifyGeomModel(DM dm, MPI_Comm comm, PetscScalar newCP[], PetscScalar newW[], PetscBool autoInflate, PetscBool saveGeom, const char *stpName) 4515 { 4516 #if defined(PETSC_HAVE_EGADS) 4517 /* EGADS/EGADSlite variables */ 4518 ego context, model, geom, *bodies, *lobjs, *fobjs; 4519 int oclass, mtype, *senses, *lsenses; 4520 int Nb, Nf, Nl, id; 4521 /* PETSc variables */ 4522 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 4523 PetscContainer modelObj, cpHashTableObj, wHashTableObj; 4524 PetscHMapI cpHashTable = NULL, wHashTable = NULL; 4525 PetscBool islite = PETSC_FALSE; 4526 #endif 4527 4528 #if defined(PETSC_HAVE_EGADS) 4529 PetscFunctionBegin; 4530 // Look to see if DM has a Container with either a EGADS or EGADSlite Model 4531 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 4532 if (!modelObj) { 4533 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 4534 islite = PETSC_TRUE; 4535 } 4536 PetscCheck(!islite, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot modify geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep"); 4537 PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have a EGADS Geometry Model attached to it!"); 4538 4539 // Get attached EGADS model (pointer) 4540 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 4541 4542 // Look to see if DM has Container for Geometry Control Point Data 4543 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 4544 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 4545 4546 PetscCheck(cpHashTableObj && wHashTableObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "DM does not have required Geometry Data attached! Please run DMPlexGeomDataAndGrads() Function first."); 4547 4548 // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 4549 PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTable)); 4550 PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTable)); 4551 4552 // Get the number of bodies and body objects in the model 4553 if (islite) PetscCallEGADS(EGlite_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4554 else PetscCallEGADS(EG_getTopology, (model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4555 4556 // Get all Faces on the body 4557 ego body = bodies[0]; 4558 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4559 else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4560 4561 ego newGeom[Nf]; 4562 ego newFaces[Nf]; 4563 4564 // Update Control Point and Weight definitions for each surface 4565 for (int jj = 0; jj < Nf; ++jj) { 4566 ego face = fobjs[jj]; 4567 ego bRef, bPrev, bNext; 4568 ego fgeom; 4569 int offset; 4570 int boclass, bmtype, *bpinfo; 4571 double *bprv; 4572 4573 // Get FACE ID and other Geometry Data 4574 if (islite) { 4575 id = EGlite_indexBodyTopo(body, face); 4576 PetscCallEGADS(EGlite_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 4577 PetscCallEGADS(EGlite_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4578 PetscCallEGADS(EGlite_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 4579 } else { 4580 id = EG_indexBodyTopo(body, face); 4581 PetscCallEGADS(EG_getTopology, (face, &fgeom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 4582 PetscCallEGADS(EG_getGeometry, (fgeom, &boclass, &bmtype, &bRef, &bpinfo, &bprv)); 4583 PetscCallEGADS(EG_getInfo, (fgeom, &boclass, &bmtype, &bRef, &bPrev, &bNext)); 4584 } 4585 4586 // Update Control Points 4587 PetscHashIter CPiter, Witer; 4588 PetscBool CPfound, Wfound; 4589 PetscInt faceCPStartRow, faceWStartRow; 4590 4591 PetscCall(PetscHMapIFind(cpHashTable, id, &CPiter, &CPfound)); 4592 PetscCheck(CPfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 4593 PetscCall(PetscHMapIGet(cpHashTable, id, &faceCPStartRow)); 4594 4595 PetscCall(PetscHMapIFind(wHashTable, id, &Witer, &Wfound)); 4596 PetscCheck(Wfound, PETSC_COMM_SELF, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 4597 PetscCall(PetscHMapIGet(wHashTable, id, &faceWStartRow)); 4598 4599 // UPDATE CONTROL POINTS Locations 4600 offset = bpinfo[3] + bpinfo[6]; 4601 for (int ii = 0; ii < 3 * bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newCP[faceCPStartRow + ii]; } 4602 4603 // UPDATE CONTROL POINT WEIGHTS 4604 offset = bpinfo[3] + bpinfo[6] + 3 * bpinfo[2] * bpinfo[5]; 4605 for (int ii = 0; ii < bpinfo[2] * bpinfo[5]; ++ii) { bprv[offset + ii] = newW[faceWStartRow + ii]; } 4606 4607 // Get Context from FACE 4608 context = NULL; 4609 PetscCallEGADS(EG_getContext, (face, &context)); // Does not have an EGlite_ version KNOWN_ISSUE 4610 4611 // Create New Surface 4612 ego newgeom; 4613 PetscCallEGADS(EG_makeGeometry, (context, SURFACE, BSPLINE, NULL, bpinfo, bprv, &newgeom)); // Does not have an EGlite_ version KNOWN_ISSUE 4614 4615 // Create new FACE based on new SURFACE geometry 4616 double data[4]; 4617 int periodic; 4618 if (islite) PetscCallEGADS(EGlite_getRange, (newgeom, data, &periodic)); 4619 else PetscCallEGADS(EG_getRange, (newgeom, data, &periodic)); 4620 4621 ego newface; 4622 PetscCallEGADS(EG_makeFace, (newgeom, SFORWARD, data, &newface)); // Does not have an EGlite_ version KNOWN_ISSUE 4623 newGeom[jj] = newgeom; 4624 newFaces[jj] = newface; 4625 } 4626 // Could be replaced by DMPlexFreeGeomObject 4627 if (islite) EGlite_free(fobjs); 4628 else EG_free(fobjs); 4629 4630 // Sew New Faces together to get a new model 4631 ego newmodel; 4632 PetscCall(EG_sewFaces(Nf, newFaces, 0.0, 0, &newmodel)); // Does not have an EGlite_ version KNOWN_ISSUE 4633 for (PetscInt f = 0; f < Nf; ++f) { 4634 PetscCallEGADS(EG_deleteObject, (newFaces[f])); 4635 PetscCallEGADS(EG_deleteObject, (newGeom[f])); 4636 } 4637 4638 // Get the total number of NODEs on the original geometry. (This will be the same for the new geometry) 4639 int totalNumNode; 4640 ego *nobjTotal; 4641 if (islite) { 4642 PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 4643 EGlite_free(nobjTotal); 4644 } else { 4645 PetscCallEGADS(EG_getBodyTopos, (body, NULL, NODE, &totalNumNode, &nobjTotal)); 4646 EG_free(nobjTotal); 4647 } // Could be replaced with DMPlexFreeGeomObject 4648 4649 // Initialize vector to store equivalent NODE indices between the 2 geometries 4650 // FORMAT :: vector index is the Original Geometry's NODE ID, the vector Value is the New Geometry's NODE ID 4651 int nodeIDEquiv[totalNumNode + 1]; 4652 4653 // Now we need to Map the NODE and EDGE IDs from each Model 4654 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4655 else PetscCallEGADS(EG_getBodyTopos, (body, NULL, FACE, &Nf, &fobjs)); 4656 4657 // New CAD 4658 ego *newbodies, newgeomtest, *nfobjs; 4659 int nNf, newNb, newoclass, newmtype, *newsenses; 4660 if (islite) PetscCallEGADS(EGlite_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 4661 else PetscCallEGADS(EG_getTopology, (newmodel, &newgeomtest, &newoclass, &newmtype, NULL, &newNb, &newbodies, &newsenses)); 4662 4663 ego newbody = newbodies[0]; 4664 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 4665 else PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, FACE, &nNf, &nfobjs)); 4666 4667 PetscCheck(newNb == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ERROR :: newNb > 1 || newNb = %d", newNb); 4668 4669 // Find Equivalent Nodes 4670 for (int ii = 0; ii < Nf; ++ii) { 4671 double fdata[4]; 4672 int peri; 4673 4674 // Get Current FACE [u, v] Ranges 4675 if (islite) PetscCallEGADS(EGlite_getRange, (fobjs[ii], fdata, &peri)); 4676 else PetscCallEGADS(EG_getRange, (fobjs[ii], fdata, &peri)); 4677 4678 // Equate NODE IDs between 2 FACEs by working through (u, v) limits of FACE 4679 for (int jj = 0; jj < 2; ++jj) { 4680 for (int kk = 2; kk < 4; ++kk) { 4681 double params[2] = {fdata[jj], fdata[kk]}; 4682 double eval[18]; 4683 if (islite) PetscCallEGADS(EGlite_evaluate, (fobjs[ii], params, eval)); 4684 else PetscCallEGADS(EG_evaluate, (fobjs[ii], params, eval)); 4685 4686 // Original Body 4687 ego *nobjsOrigFace; 4688 int origNn; 4689 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 4690 else PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], NODE, &origNn, &nobjsOrigFace)); 4691 4692 double minVal = 1.0E10; 4693 double evalCheck[18]; 4694 int equivOrigNodeID = -1; 4695 for (int mm = 0; mm < origNn; ++mm) { 4696 double delta = 1.0E10; 4697 if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 4698 else PetscCallEGADS(EG_evaluate, (nobjsOrigFace[mm], NULL, evalCheck)); 4699 4700 delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 4701 4702 if (delta < minVal) { 4703 if (islite) equivOrigNodeID = EGlite_indexBodyTopo(body, nobjsOrigFace[mm]); 4704 else equivOrigNodeID = EG_indexBodyTopo(body, nobjsOrigFace[mm]); 4705 4706 minVal = delta; 4707 } 4708 } 4709 // Could be replaced with DMPlexFreeGeomObject 4710 if (islite) EGlite_free(nobjsOrigFace); 4711 else EG_free(nobjsOrigFace); 4712 4713 // New Body 4714 ego *nobjsNewFace; 4715 int newNn; 4716 if (islite) PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 4717 else PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], NODE, &newNn, &nobjsNewFace)); 4718 4719 minVal = 1.0E10; 4720 int equivNewNodeID = -1; 4721 for (int mm = 0; mm < newNn; ++mm) { 4722 double delta = 1.0E10; 4723 if (islite) PetscCallEGADS(EGlite_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 4724 else PetscCallEGADS(EG_evaluate, (nobjsNewFace[mm], NULL, evalCheck)); 4725 4726 delta = PetscSqrtReal(PetscSqr(evalCheck[0] - eval[0]) + PetscSqr(evalCheck[1] - eval[1]) + PetscSqr(evalCheck[2] - eval[2])); 4727 4728 if (delta < minVal) { 4729 if (islite) equivNewNodeID = EGlite_indexBodyTopo(newbody, nobjsNewFace[mm]); 4730 else equivNewNodeID = EG_indexBodyTopo(newbody, nobjsNewFace[mm]); 4731 4732 minVal = delta; 4733 } 4734 } 4735 if (islite) EGlite_free(nobjsNewFace); 4736 else EG_free(nobjsNewFace); 4737 4738 // Store equivalent NODE IDs 4739 nodeIDEquiv[equivOrigNodeID] = equivNewNodeID; 4740 } 4741 } 4742 } 4743 4744 // Find Equivalent EDGEs 4745 // Get total number of EDGEs on Original Geometry 4746 int totalNumEdge; 4747 ego *eobjsOrig; 4748 if (islite) { 4749 PetscCallEGADS(EGlite_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 4750 EGlite_free(eobjsOrig); 4751 } else { 4752 PetscCallEGADS(EG_getBodyTopos, (body, NULL, EDGE, &totalNumEdge, &eobjsOrig)); 4753 EG_free(eobjsOrig); 4754 } 4755 4756 // Get total number of EDGEs on New Geometry 4757 int totalNumEdgeNew; 4758 ego *eobjsNew; 4759 if (islite) { 4760 PetscCallEGADS(EGlite_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 4761 EGlite_free(eobjsNew); 4762 } else { 4763 PetscCallEGADS(EG_getBodyTopos, (newbody, NULL, EDGE, &totalNumEdgeNew, &eobjsNew)); 4764 EG_free(eobjsNew); 4765 } 4766 4767 // Initialize EDGE ID equivalent vector 4768 // FORMAT :: vector index is the Original Geometry's EDGE ID, the vector Value is the New Geometry's EDGE ID 4769 int edgeIDEquiv[totalNumEdge + 1]; 4770 4771 // Find Equivalent EDGEs 4772 for (int ii = 0; ii < Nf; ++ii) { 4773 // Get Original Geometry EDGE's NODEs 4774 int numOrigEdge, numNewEdge; 4775 if (islite) { 4776 PetscCallEGADS(EGlite_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 4777 PetscCallEGADS(EGlite_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 4778 } else { 4779 PetscCallEGADS(EG_getBodyTopos, (body, fobjs[ii], EDGE, &numOrigEdge, &eobjsOrig)); 4780 PetscCallEGADS(EG_getBodyTopos, (newbody, nfobjs[ii], EDGE, &numNewEdge, &eobjsNew)); 4781 } 4782 4783 // new loop below 4784 for (int nn = 0; nn < numOrigEdge; ++nn) { 4785 ego origEdge = eobjsOrig[nn]; 4786 ego geomEdgeOrig, *nobjsOrig; 4787 int oclassEdgeOrig, mtypeEdgeOrig; 4788 int NnOrig, *nsensesEdgeOrig; 4789 4790 if (islite) PetscCallEGADS(EGlite_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 4791 else PetscCallEGADS(EG_getTopology, (origEdge, &geomEdgeOrig, &oclassEdgeOrig, &mtypeEdgeOrig, NULL, &NnOrig, &nobjsOrig, &nsensesEdgeOrig)); 4792 4793 PetscBool isSame = PETSC_FALSE; 4794 for (int jj = 0; jj < numNewEdge; ++jj) { 4795 ego newEdge = eobjsNew[jj]; 4796 ego geomEdgeNew, *nobjsNew; 4797 int oclassEdgeNew, mtypeEdgeNew; 4798 int NnNew, *nsensesEdgeNew; 4799 4800 if (islite) PetscCallEGADS(EGlite_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 4801 else PetscCallEGADS(EG_getTopology, (newEdge, &geomEdgeNew, &oclassEdgeNew, &mtypeEdgeNew, NULL, &NnNew, &nobjsNew, &nsensesEdgeNew)); 4802 4803 if (mtypeEdgeOrig == mtypeEdgeNew) { 4804 // Only operate if the EDGE types are the same 4805 for (int kk = 0; kk < NnNew; ++kk) { 4806 int nodeIDOrigGeom, nodeIDNewGeom; 4807 if (islite) { 4808 nodeIDOrigGeom = EGlite_indexBodyTopo(body, nobjsOrig[kk]); 4809 nodeIDNewGeom = EGlite_indexBodyTopo(newbody, nobjsNew[kk]); 4810 } else { 4811 nodeIDOrigGeom = EG_indexBodyTopo(body, nobjsOrig[kk]); 4812 nodeIDNewGeom = EG_indexBodyTopo(newbody, nobjsNew[kk]); 4813 } 4814 4815 if (nodeIDNewGeom == nodeIDEquiv[nodeIDOrigGeom]) { 4816 isSame = PETSC_TRUE; 4817 } else { 4818 isSame = PETSC_FALSE; 4819 kk = NnNew; // skip ahead because first NODE failed test and order is important 4820 } 4821 } 4822 4823 if (isSame == PETSC_TRUE) { 4824 int edgeIDOrig, edgeIDNew; 4825 if (islite) { 4826 edgeIDOrig = EGlite_indexBodyTopo(body, origEdge); 4827 edgeIDNew = EGlite_indexBodyTopo(newbody, newEdge); 4828 } else { 4829 edgeIDOrig = EG_indexBodyTopo(body, origEdge); 4830 edgeIDNew = EG_indexBodyTopo(newbody, newEdge); 4831 } 4832 4833 edgeIDEquiv[edgeIDOrig] = edgeIDNew; 4834 jj = numNewEdge; 4835 } 4836 } 4837 } 4838 } 4839 if (islite) { 4840 EGlite_free(eobjsOrig); 4841 EGlite_free(eobjsNew); 4842 } else { 4843 EG_free(eobjsOrig); 4844 EG_free(eobjsNew); 4845 } 4846 } 4847 if (islite) { 4848 EGlite_free(fobjs); 4849 EGlite_free(nfobjs); 4850 } else { 4851 EG_free(fobjs); 4852 EG_free(nfobjs); 4853 } 4854 4855 // Modify labels to point to the IDs on the new Geometry 4856 IS isNodeID, isEdgeID; 4857 4858 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 4859 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 4860 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4861 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 4862 4863 PetscCall(ISCreateGeneral(comm, totalNumNode + 1, nodeIDEquiv, PETSC_COPY_VALUES, &isNodeID)); 4864 PetscCall(ISCreateGeneral(comm, totalNumEdge + 1, edgeIDEquiv, PETSC_COPY_VALUES, &isEdgeID)); 4865 /* Do not perform check. Np may != Nv due to Degenerate Geometry which is not stored in labels. */ 4866 /* We do not know in advance which IDs have been omitted. This may also change due to geometry modifications. */ 4867 PetscCall(DMLabelRewriteValues(vertexLabel, isNodeID)); 4868 PetscCall(DMLabelRewriteValues(edgeLabel, isEdgeID)); 4869 PetscCall(ISDestroy(&isNodeID)); 4870 PetscCall(ISDestroy(&isEdgeID)); 4871 4872 // Attempt to point to the new geometry 4873 PetscCallEGADS(EG_deleteObject, (model)); 4874 PetscCall(PetscContainerSetPointer(modelObj, newmodel)); 4875 4876 // save updated model to file 4877 if (saveGeom == PETSC_TRUE && stpName != NULL) PetscCall(EG_saveModel(newmodel, stpName)); 4878 4879 // Inflate Mesh to EGADS Model 4880 if (autoInflate == PETSC_TRUE) PetscCall(DMPlexInflateToGeomModel(dm, PETSC_TRUE)); 4881 PetscFunctionReturn(PETSC_SUCCESS); 4882 #else 4883 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This method requires EGADS support. Reconfigure using --download-egads"); 4884 #endif 4885 } 4886 4887 /*@C 4888 DMPlexGetGeomModelTUV - Gets the [t] (EDGES) and [u, v] (FACES) geometry parameters of DM points that are associated geometry relationships. Requires a DM with a EGADS model attached. 4889 4890 Collective 4891 4892 Input Parameter: 4893 . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 4894 4895 Level: intermediate 4896 4897 .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()` 4898 @*/ 4899 PetscErrorCode DMPlexGetGeomModelTUV(DM dm) 4900 { 4901 #if defined(PETSC_HAVE_EGADS) 4902 /* EGADS Variables */ 4903 ego model, geom, body, face, edge; 4904 ego *bodies; 4905 int Nb, oclass, mtype, *senses; 4906 double result[4]; 4907 /* PETSc Variables */ 4908 DM cdm; 4909 PetscContainer modelObj; 4910 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 4911 Vec coordinates; 4912 PetscScalar *coords; 4913 PetscInt bodyID, faceID, edgeID, vertexID; 4914 PetscInt cdim, vStart, vEnd, v; 4915 PetscBool islite = PETSC_FALSE; 4916 #endif 4917 4918 PetscFunctionBegin; 4919 #if defined(PETSC_HAVE_EGADS) 4920 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 4921 if (!modelObj) { 4922 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 4923 islite = PETSC_TRUE; 4924 } 4925 if (!modelObj) PetscFunctionReturn(0); 4926 4927 PetscCall(DMGetCoordinateDim(dm, &cdim)); 4928 PetscCall(DMGetCoordinateDM(dm, &cdm)); 4929 PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 4930 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 4931 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 4932 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 4933 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 4934 4935 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 4936 4937 if (islite) PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4938 else PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 4939 4940 PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 4941 PetscCall(VecGetArrayWrite(coordinates, &coords)); 4942 4943 // Define t, u, v arrays to be stored in a PetscContainer after populated 4944 PetscScalar *t_point, *u_point, *v_point; 4945 PetscCall(PetscMalloc1(vEnd - vStart, &t_point)); 4946 PetscCall(PetscMalloc1(vEnd - vStart, &u_point)); 4947 PetscCall(PetscMalloc1(vEnd - vStart, &v_point)); 4948 4949 for (v = vStart; v < vEnd; ++v) { 4950 PetscScalar *vcoords; 4951 4952 PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 4953 PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 4954 PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 4955 PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 4956 4957 // TODO Figure out why this is unknown sometimes 4958 if (bodyID < 0 && Nb == 1) bodyID = 0; 4959 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); 4960 body = bodies[bodyID]; 4961 4962 PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 4963 if (edgeID > 0) { 4964 /* Snap to EDGE at nearest location */ 4965 double params[1]; 4966 4967 if (islite) { 4968 PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 4969 PetscCall(EGlite_invEvaluate(edge, vcoords, params, result)); 4970 } // Get (t) of nearest point on EDGE 4971 else { 4972 PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 4973 PetscCall(EG_invEvaluate(edge, vcoords, params, result)); 4974 } // Get (t) of nearest point on EDGE 4975 4976 t_point[v - vStart] = params[0]; 4977 u_point[v - vStart] = 0.0; 4978 v_point[v - vStart] = 0.0; 4979 } else if (faceID > 0) { 4980 /* Snap to FACE at nearest location */ 4981 double params[2]; 4982 4983 if (islite) { 4984 PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 4985 PetscCall(EGlite_invEvaluate(face, vcoords, params, result)); 4986 } // Get (x,y,z) of nearest point on FACE 4987 else { 4988 PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 4989 PetscCall(EG_invEvaluate(face, vcoords, params, result)); 4990 } // Get (x,y,z) of nearest point on FACE 4991 4992 t_point[v - vStart] = 0.0; 4993 u_point[v - vStart] = params[0]; 4994 v_point[v - vStart] = params[1]; 4995 } else { 4996 t_point[v - vStart] = 0.0; 4997 u_point[v - vStart] = 0.0; 4998 v_point[v - vStart] = 0.0; 4999 } 5000 } 5001 PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 5002 /* Clear out global coordinates */ 5003 PetscCall(VecDestroy(&dm->coordinates[0].x)); 5004 5005 /* Store in PetscContainters */ 5006 { 5007 PetscContainer t_pointObj, u_pointObj, v_pointObj; 5008 5009 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 5010 if (!t_pointObj) { 5011 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &t_pointObj)); 5012 PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 5013 PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Edge t Parameter", (PetscObject)t_pointObj)); 5014 PetscCall(PetscContainerSetCtxDestroy(t_pointObj, PetscCtxDestroyDefault)); 5015 PetscCall(PetscContainerDestroy(&t_pointObj)); 5016 } else { 5017 void *old; 5018 5019 PetscCall(PetscContainerGetPointer(t_pointObj, &old)); 5020 PetscCall(PetscFree(old)); 5021 PetscCall(PetscContainerSetPointer(t_pointObj, t_point)); 5022 } 5023 5024 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 5025 if (!u_pointObj) { 5026 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &u_pointObj)); 5027 PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 5028 PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face u Parameter", (PetscObject)u_pointObj)); 5029 PetscCall(PetscContainerSetCtxDestroy(u_pointObj, PetscCtxDestroyDefault)); 5030 PetscCall(PetscContainerDestroy(&u_pointObj)); 5031 } else { 5032 void *old; 5033 5034 PetscCall(PetscContainerGetPointer(u_pointObj, &old)); 5035 PetscCall(PetscFree(old)); 5036 PetscCall(PetscContainerSetPointer(u_pointObj, u_point)); 5037 } 5038 5039 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 5040 if (!v_pointObj) { 5041 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &v_pointObj)); 5042 PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 5043 PetscCall(PetscObjectCompose((PetscObject)dm, "Point - Face v Parameter", (PetscObject)v_pointObj)); 5044 PetscCall(PetscContainerSetCtxDestroy(v_pointObj, PetscCtxDestroyDefault)); 5045 PetscCall(PetscContainerDestroy(&v_pointObj)); 5046 } else { 5047 void *old; 5048 5049 PetscCall(PetscContainerGetPointer(v_pointObj, &old)); 5050 PetscCall(PetscFree(old)); 5051 PetscCall(PetscContainerSetPointer(v_pointObj, v_point)); 5052 } 5053 } 5054 #endif 5055 PetscFunctionReturn(PETSC_SUCCESS); 5056 } 5057 5058 /*@C 5059 DMPlexInflateToGeomModelUseTUV - Inflates the DM to the associated underlying geometry using the [t] {EDGES) and [u, v] (FACES} associated parameters. Requires a DM with an EGADS model attached and a previous call to DMPlexGetGeomModelTUV(). 5060 5061 Collective 5062 5063 Input Parameter: 5064 . dm - The DM object representing the mesh with PetscContainer containing an EGADS geometry model 5065 5066 Level: intermediate 5067 5068 Note: 5069 The updated DM object inflated to the associated underlying geometry. This updates the [x, y, z] coordinates of DM points associated with geometry. 5070 5071 .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateGeom()`, `DMPlexGeomDataAndGrads()`, `DMPlexGetGeomModelTUV()` 5072 @*/ 5073 PetscErrorCode DMPlexInflateToGeomModelUseTUV(DM dm) 5074 { 5075 #if defined(PETSC_HAVE_EGADS) 5076 /* EGADS Variables */ 5077 ego model, geom, body, face, edge, vertex; 5078 ego *bodies; 5079 int Nb, oclass, mtype, *senses; 5080 double result[18], params[2]; 5081 /* PETSc Variables */ 5082 DM cdm; 5083 PetscContainer modelObj; 5084 PetscContainer t_pointObj, u_pointObj, v_pointObj; 5085 DMLabel bodyLabel, faceLabel, edgeLabel, vertexLabel; 5086 Vec coordinates; 5087 PetscScalar *coords; 5088 PetscScalar *t_point, *u_point, *v_point; 5089 PetscInt bodyID, faceID, edgeID, vertexID; 5090 PetscInt cdim, d, vStart, vEnd, v; 5091 PetscBool islite = PETSC_FALSE; 5092 #endif 5093 5094 PetscFunctionBegin; 5095 #if defined(PETSC_HAVE_EGADS) 5096 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5097 if (!modelObj) { 5098 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5099 islite = PETSC_TRUE; 5100 } 5101 5102 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Edge t Parameter", (PetscObject *)&t_pointObj)); 5103 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face u Parameter", (PetscObject *)&u_pointObj)); 5104 PetscCall(PetscObjectQuery((PetscObject)dm, "Point - Face v Parameter", (PetscObject *)&v_pointObj)); 5105 5106 if (!modelObj) PetscFunctionReturn(PETSC_SUCCESS); 5107 if (!t_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5108 if (!u_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5109 if (!v_pointObj) PetscFunctionReturn(PETSC_SUCCESS); 5110 5111 PetscCall(DMGetCoordinateDim(dm, &cdim)); 5112 PetscCall(DMGetCoordinateDM(dm, &cdm)); 5113 PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 5114 PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 5115 PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 5116 PetscCall(DMGetLabel(dm, "EGADS Edge ID", &edgeLabel)); 5117 PetscCall(DMGetLabel(dm, "EGADS Vertex ID", &vertexLabel)); 5118 5119 PetscCall(PetscContainerGetPointer(t_pointObj, (void **)&t_point)); 5120 PetscCall(PetscContainerGetPointer(u_pointObj, (void **)&u_point)); 5121 PetscCall(PetscContainerGetPointer(v_pointObj, (void **)&v_point)); 5122 5123 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 5124 5125 if (islite) { 5126 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 5127 } else { 5128 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, &Nb, &bodies, &senses)); 5129 } 5130 5131 PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 5132 PetscCall(VecGetArrayWrite(coordinates, &coords)); 5133 5134 for (v = vStart; v < vEnd; ++v) { 5135 PetscScalar *vcoords; 5136 5137 PetscCall(DMLabelGetValue(bodyLabel, v, &bodyID)); 5138 PetscCall(DMLabelGetValue(faceLabel, v, &faceID)); 5139 PetscCall(DMLabelGetValue(edgeLabel, v, &edgeID)); 5140 PetscCall(DMLabelGetValue(vertexLabel, v, &vertexID)); 5141 5142 // TODO Figure out why this is unknown sometimes 5143 if (bodyID < 0 && Nb == 1) bodyID = 0; 5144 PetscCheck(bodyID >= 0 && bodyID < Nb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Body %" PetscInt_FMT " for vertex %" PetscInt_FMT " is not in [0, %d)", bodyID, v, Nb); 5145 body = bodies[bodyID]; 5146 5147 PetscCall(DMPlexPointLocalRef(cdm, v, coords, (void *)&vcoords)); 5148 if (vertexID > 0) { 5149 /* Snap to Vertices */ 5150 if (islite) { 5151 PetscCall(EGlite_objectBodyTopo(body, NODE, vertexID, &vertex)); 5152 PetscCall(EGlite_evaluate(vertex, NULL, result)); 5153 } else { 5154 PetscCall(EG_objectBodyTopo(body, NODE, vertexID, &vertex)); 5155 PetscCall(EG_evaluate(vertex, NULL, result)); 5156 } 5157 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5158 } else if (edgeID > 0) { 5159 /* Snap to EDGE */ 5160 params[0] = t_point[v - vStart]; 5161 if (islite) { 5162 PetscCall(EGlite_objectBodyTopo(body, EDGE, edgeID, &edge)); 5163 PetscCall(EGlite_evaluate(edge, params, result)); 5164 } else { 5165 PetscCall(EG_objectBodyTopo(body, EDGE, edgeID, &edge)); 5166 PetscCall(EG_evaluate(edge, params, result)); 5167 } 5168 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5169 } else if (faceID > 0) { 5170 /* Snap to FACE */ 5171 params[0] = u_point[v - vStart]; 5172 params[1] = v_point[v - vStart]; 5173 if (islite) { 5174 PetscCall(EGlite_objectBodyTopo(body, FACE, faceID, &face)); 5175 PetscCall(EGlite_evaluate(face, params, result)); 5176 } else { 5177 PetscCall(EG_objectBodyTopo(body, FACE, faceID, &face)); 5178 PetscCall(EG_evaluate(face, params, result)); 5179 } 5180 for (d = 0; d < cdim; ++d) vcoords[d] = result[d]; 5181 } 5182 } 5183 PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 5184 /* Clear out global coordinates */ 5185 PetscCall(VecDestroy(&dm->coordinates[0].x)); 5186 #endif 5187 PetscFunctionReturn(PETSC_SUCCESS); 5188 } 5189 5190 /*@ 5191 DMPlexInflateToGeomModel - Wrapper function allowing two methods for inflating refined meshes to the underlying geometric domain. 5192 5193 Collective 5194 5195 Input Parameters: 5196 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5197 - useTUV - PetscBool indicating if the user would like to inflate the DMPlex to the underlying geometry 5198 using (t) for nodes on EDGEs and (u, v) for nodes on FACEs or using the nodes (x, y, z) coordinates 5199 and shortest distance routine. 5200 If useTUV = PETSC_TRUE, use the (t) or (u, v) parameters to inflate the DMPlex to the CAD geometry. 5201 If useTUV = PETSC_FALSE, use the nodes (x, y, z) coordinates and the shortest disctance routine. 5202 5203 Notes: 5204 DM with nodal coordinates modified so that they lie on the EDGEs and FACEs of the underlying geometry. 5205 5206 (t) and (u, v) parameters for all DMPlex nodes on EDGEs and FACEs are stored in arrays within PetscContainers attached to the DM. 5207 The containers have names "Point - Edge t Parameter", "Point - Face u Parameter", and "Point - Face v Parameter". 5208 The arrays are organized by Point 0-based ID (i.e. [v-vstart] as defined in the DMPlex. 5209 5210 Level: intermediate 5211 5212 .seealso: `DMPlexGetGeomModelTUV()`, `DMPlexInflateToGeomModelUseTUV()`, `DMPlexInflateToGeomModelUseXYZ()` 5213 @*/ 5214 PetscErrorCode DMPlexInflateToGeomModel(DM dm, PetscBool useTUV) 5215 { 5216 PetscFunctionBeginHot; 5217 if (useTUV) { 5218 PetscCall(DMPlexGetGeomModelTUV(dm)); 5219 PetscCall(DMPlexInflateToGeomModelUseTUV(dm)); 5220 } else { 5221 PetscCall(DMPlexInflateToGeomModelUseXYZ(dm)); 5222 } 5223 PetscFunctionReturn(PETSC_SUCCESS); 5224 } 5225 5226 #ifdef PETSC_HAVE_EGADS 5227 /*@C 5228 DMPlexGetGeomModelBodies - Returns an array of PetscGeom BODY objects attached to the referenced geomtric model entity as well as the number of BODYs. 5229 5230 Collective 5231 5232 Input Parameter: 5233 . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5234 5235 Output Parameters: 5236 + bodies - Array of PetscGeom BODY objects referenced by the geometric model. 5237 - numBodies - Number of BODYs referenced by the geometric model. Also the size of **bodies array. 5238 5239 Level: intermediate 5240 5241 .seealso: 5242 @*/ 5243 PetscErrorCode DMPlexGetGeomModelBodies(DM dm, PetscGeom **bodies, PetscInt *numBodies) 5244 { 5245 PetscFunctionBeginHot; 5246 PetscContainer modelObj; 5247 PetscBool islite = PETSC_FALSE; 5248 ego model, geom; 5249 int oclass, mtype; 5250 int *senses; 5251 5252 /* Determine which type of EGADS model is attached to the DM */ 5253 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5254 if (!modelObj) { 5255 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5256 islite = PETSC_TRUE; 5257 } 5258 5259 // Get attached EGADS or EGADSlite model (pointer) 5260 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 5261 5262 if (islite) { 5263 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 5264 } else { 5265 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, NULL, numBodies, bodies, &senses)); 5266 } 5267 PetscFunctionReturn(PETSC_SUCCESS); 5268 } 5269 5270 /*@C 5271 DMPlexGetGeomModelBodyShells - Returns an array of PetscGeom SHELL objects attached to the referenced BODY geomtric entity as well as the number of SHELLs. 5272 5273 Collective 5274 5275 Input Parameters: 5276 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5277 - body - PetscGeom BODY object containing the SHELL objects of interest. 5278 5279 Output Parameters: 5280 + shells - Array of PetscGeom SHELL objects referenced by the PetscGeom BODY object 5281 - numShells - Number of SHELLs referenced by the PetscGeom BODY object. Also the size of **shells array. 5282 5283 Level: intermediate 5284 5285 .seealso: 5286 @*/ 5287 PetscErrorCode DMPlexGetGeomModelBodyShells(DM dm, PetscGeom body, PetscGeom **shells, PetscInt *numShells) 5288 { 5289 PetscFunctionBeginHot; 5290 #ifdef PETSC_HAVE_EGADS 5291 PetscContainer modelObj; 5292 PetscBool islite = PETSC_FALSE; 5293 5294 /* Determine which type of EGADS model is attached to the DM */ 5295 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5296 if (!modelObj) { 5297 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5298 islite = PETSC_TRUE; 5299 } 5300 5301 if (islite) { 5302 PetscCall(EGlite_getBodyTopos(body, NULL, SHELL, numShells, shells)); 5303 } else { 5304 PetscCall(EG_getBodyTopos(body, NULL, SHELL, numShells, shells)); 5305 } 5306 #endif 5307 PetscFunctionReturn(PETSC_SUCCESS); 5308 } 5309 5310 /*@C 5311 DMPlexGetGeomModelBodyFaces - Returns an array of PetscGeom FACE objects attached to the referenced BODY geomtric entity as well as the number of FACEs. 5312 5313 Collective 5314 5315 Input Parameters: 5316 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5317 - body - PetscGeom BODY object containing the FACE objects of interest. 5318 5319 Output Parameters: 5320 + faces - Array of PetscGeom FACE objects referenced by the PetscGeom BODY object 5321 - numFaces - Number of FACEs referenced by the PetscGeom BODY object. Also the size of **faces array. 5322 5323 Level: intermediate 5324 5325 .seealso: 5326 @*/ 5327 PetscErrorCode DMPlexGetGeomModelBodyFaces(DM dm, PetscGeom body, PetscGeom **faces, PetscInt *numFaces) 5328 { 5329 PetscFunctionBeginHot; 5330 #ifdef PETSC_HAVE_EGADS 5331 PetscContainer modelObj; 5332 PetscBool islite = PETSC_FALSE; 5333 5334 /* Determine which type of EGADS model is attached to the DM */ 5335 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5336 if (!modelObj) { 5337 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5338 islite = PETSC_TRUE; 5339 } 5340 5341 if (islite) { 5342 PetscCall(EGlite_getBodyTopos(body, NULL, FACE, numFaces, faces)); 5343 } else { 5344 PetscCall(EG_getBodyTopos(body, NULL, FACE, numFaces, faces)); 5345 } 5346 #endif 5347 PetscFunctionReturn(PETSC_SUCCESS); 5348 } 5349 5350 /*@C 5351 DMPlexGetGeomModelBodyLoops - Returns an array of PetscGeom Loop objects attached to the referenced BODY geomtric entity as well as the number of LOOPs. 5352 5353 Collective 5354 5355 Input Parameters: 5356 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5357 - body - PetscGeom BODY object containing the LOOP objects of interest. 5358 5359 Output Parameters: 5360 + loops - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 5361 - numLoops - Number of LOOPs referenced by the PetscGeom BODY object. Also the size of **loops array. 5362 5363 Level: intermediate 5364 5365 .seealso: 5366 @*/ 5367 PetscErrorCode DMPlexGetGeomModelBodyLoops(DM dm, PetscGeom body, PetscGeom **loops, PetscInt *numLoops) 5368 { 5369 PetscFunctionBeginHot; 5370 #ifdef PETSC_HAVE_EGADS 5371 PetscContainer modelObj; 5372 PetscBool islite = PETSC_FALSE; 5373 5374 /* Determine which type of EGADS model is attached to the DM */ 5375 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5376 if (!modelObj) { 5377 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5378 islite = PETSC_TRUE; 5379 } 5380 5381 if (islite) { 5382 PetscCall(EGlite_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 5383 } else { 5384 PetscCall(EG_getBodyTopos(body, NULL, LOOP, numLoops, loops)); 5385 } 5386 #endif 5387 PetscFunctionReturn(PETSC_SUCCESS); 5388 } 5389 5390 /*@C 5391 DMPlexGetGeomModelShellFaces - Returns an array of PetscGeom FACE objects attached to the referenced SHELL geomtric entity as well as the number of FACEs. 5392 5393 Collective 5394 5395 Input Parameters: 5396 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5397 . body - PetscGeom BODY object containing the FACE objects of interest. 5398 - shell - PetscGeom SHELL object with FACEs of interest. 5399 5400 Output Parameters: 5401 + faces - Array of PetscGeom FACE objects referenced by the PetscGeom SHELL object 5402 - numFaces - Number of FACEs referenced by the PetscGeom SHELL object. Also the size of **faces array. 5403 5404 Level: intermediate 5405 5406 .seealso: 5407 @*/ 5408 PetscErrorCode DMPlexGetGeomModelShellFaces(DM dm, PetscGeom body, PetscGeom shell, PetscGeom **faces, PetscInt *numFaces) 5409 { 5410 PetscFunctionBeginHot; 5411 #ifdef PETSC_HAVE_EGADS 5412 PetscContainer modelObj; 5413 PetscBool islite = PETSC_FALSE; 5414 5415 /* Determine which type of EGADS model is attached to the DM */ 5416 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5417 if (!modelObj) { 5418 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5419 islite = PETSC_TRUE; 5420 } 5421 5422 if (islite) { 5423 PetscCall(EGlite_getBodyTopos(body, shell, FACE, numFaces, faces)); 5424 } else { 5425 PetscCall(EG_getBodyTopos(body, shell, FACE, numFaces, faces)); 5426 } 5427 #endif 5428 PetscFunctionReturn(PETSC_SUCCESS); 5429 } 5430 5431 /*@C 5432 DMPlexGetGeomModelFaceLoops - Returns an array of PetscGeom LOOP objects attached to the referenced FACE geomtric entity as well as the number of LOOPs. 5433 5434 Collective 5435 5436 Input Parameters: 5437 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5438 . body - PetscGeom BODY object containing the LOOP objects of interest. 5439 - face - PetscGeom FACE object with LOOPs of interest. 5440 5441 Output Parameters: 5442 + loops - Array of PetscGeom LOOP objects referenced by the PetscGeom FACE object 5443 - numLoops - Number of LOOPs referenced by the PetscGeom FACE object. Also the size of **loops array. 5444 5445 Level: intermediate 5446 5447 .seealso: 5448 @*/ 5449 PetscErrorCode DMPlexGetGeomModelFaceLoops(DM dm, PetscGeom body, PetscGeom face, PetscGeom **loops, PetscInt *numLoops) 5450 { 5451 PetscFunctionBeginHot; 5452 #ifdef PETSC_HAVE_EGADS 5453 PetscContainer modelObj; 5454 PetscBool islite = PETSC_FALSE; 5455 5456 /* Determine which type of EGADS model is attached to the DM */ 5457 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5458 if (!modelObj) { 5459 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5460 islite = PETSC_TRUE; 5461 } 5462 5463 if (islite) { 5464 PetscCall(EGlite_getBodyTopos(body, face, LOOP, numLoops, loops)); 5465 } else { 5466 PetscCall(EG_getBodyTopos(body, face, LOOP, numLoops, loops)); 5467 } 5468 #endif 5469 PetscFunctionReturn(PETSC_SUCCESS); 5470 } 5471 5472 /*@C 5473 DMPlexGetGeomModelFaceEdges - Returns an array of PetscGeom EDGE objects attached to the referenced FACE geomtric entity as well as the number of EDGEs. 5474 5475 Collective 5476 5477 Input Parameters: 5478 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5479 . body - PetscGeom Body object containing the EDGE objects of interest. 5480 - face - PetscGeom FACE object with EDGEs of interest. 5481 5482 Output Parameters: 5483 + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom FACE object 5484 - numEdges - Number of EDGEs referenced by the PetscGeom FACE object. Also the size of **edges array. 5485 5486 Level: intermediate 5487 5488 .seealso: 5489 @*/ 5490 PetscErrorCode DMPlexGetGeomModelFaceEdges(DM dm, PetscGeom body, PetscGeom face, PetscGeom **edges, PetscInt *numEdges) 5491 { 5492 PetscFunctionBeginHot; 5493 #ifdef PETSC_HAVE_EGADS 5494 PetscContainer modelObj; 5495 PetscBool islite = PETSC_FALSE; 5496 5497 /* Determine which type of EGADS model is attached to the DM */ 5498 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5499 if (!modelObj) { 5500 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5501 islite = PETSC_TRUE; 5502 } 5503 5504 if (islite) { 5505 PetscCall(EGlite_getBodyTopos(body, face, EDGE, numEdges, edges)); 5506 } else { 5507 PetscCall(EG_getBodyTopos(body, face, EDGE, numEdges, edges)); 5508 } 5509 #endif 5510 PetscFunctionReturn(PETSC_SUCCESS); 5511 } 5512 5513 /*@C 5514 DMPlexGetGeomModelBodyEdges - Returns an array of PetscGeom EDGE objects attached to the referenced BODY geomtric entity as well as the number of EDGEs. 5515 5516 Collective 5517 5518 Input Parameters: 5519 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5520 - body - PetscGeom body object of interest. 5521 5522 Output Parameters: 5523 + edges - Array of PetscGeom EDGE objects referenced by the PetscGeom BODY object 5524 - numEdges - Number of EDGEs referenced by the PetscGeom BODY object. Also the size of **edges array. 5525 5526 Level: intermediate 5527 5528 .seealso: 5529 @*/ 5530 PetscErrorCode DMPlexGetGeomModelBodyEdges(DM dm, PetscGeom body, PetscGeom **edges, PetscInt *numEdges) 5531 { 5532 PetscFunctionBeginHot; 5533 #ifdef PETSC_HAVE_EGADS 5534 PetscContainer modelObj; 5535 PetscBool islite = PETSC_FALSE; 5536 5537 /* Determine which type of EGADS model is attached to the DM */ 5538 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5539 if (!modelObj) { 5540 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5541 islite = PETSC_TRUE; 5542 } 5543 5544 if (islite) { 5545 PetscCall(EGlite_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 5546 } else { 5547 PetscCall(EG_getBodyTopos(body, NULL, EDGE, numEdges, edges)); 5548 } 5549 #endif 5550 PetscFunctionReturn(PETSC_SUCCESS); 5551 } 5552 5553 /*@C 5554 DMPlexGetGeomModelBodyNodes - Returns an array of PetscGeom NODE objects attached to the referenced BODY geomtric entity as well as the number of NODES. 5555 5556 Collective 5557 5558 Input Parameters: 5559 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5560 - body - PetscGeom body object of interest. 5561 5562 Output Parameters: 5563 + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom BODY object 5564 - numNodes - Number of NODEs referenced by the PetscGeom BODY object. Also the size of **nodes array. 5565 5566 Level: intermediate 5567 5568 .seealso: 5569 @*/ 5570 PetscErrorCode DMPlexGetGeomModelBodyNodes(DM dm, PetscGeom body, PetscGeom **nodes, PetscInt *numNodes) 5571 { 5572 PetscFunctionBeginHot; 5573 #ifdef PETSC_HAVE_EGADS 5574 PetscContainer modelObj; 5575 PetscBool islite = PETSC_FALSE; 5576 5577 /* Determine which type of EGADS model is attached to the DM */ 5578 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5579 if (!modelObj) { 5580 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5581 islite = PETSC_TRUE; 5582 } 5583 5584 if (islite) { 5585 PetscCall(EGlite_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 5586 } else { 5587 PetscCall(EG_getBodyTopos(body, NULL, NODE, numNodes, nodes)); 5588 } 5589 #endif 5590 PetscFunctionReturn(PETSC_SUCCESS); 5591 } 5592 5593 /*@C 5594 DMPlexGetGeomModelEdgeNodes - Returns an array of PetscGeom NODE objects attached to the referenced EDGE geomtric entity as well as the number of NODES. 5595 5596 Collective 5597 5598 Input Parameters: 5599 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5600 . body - PetscGeom body object containing the EDGE object of interest. 5601 - edge - PetscGeom EDGE object with NODEs of interest. 5602 5603 Output Parameters: 5604 + nodes - Array of PetscGeom NODE objects referenced by the PetscGeom EDGE object 5605 - numNodes - Number of Nodes referenced by the PetscGeom EDGE object. Also the size of **nodes array. 5606 5607 Level: intermediate 5608 5609 .seealso: 5610 @*/ 5611 PetscErrorCode DMPlexGetGeomModelEdgeNodes(DM dm, PetscGeom body, PetscGeom edge, PetscGeom **nodes, PetscInt *numNodes) 5612 { 5613 PetscFunctionBeginHot; 5614 #ifdef PETSC_HAVE_EGADS 5615 PetscContainer modelObj; 5616 PetscBool islite = PETSC_FALSE; 5617 5618 /* Determine which type of EGADS model is attached to the DM */ 5619 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5620 if (!modelObj) { 5621 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5622 islite = PETSC_TRUE; 5623 } 5624 5625 if (islite) { 5626 PetscCall(EGlite_getBodyTopos(body, edge, NODE, numNodes, nodes)); 5627 } else { 5628 PetscCall(EG_getBodyTopos(body, edge, NODE, numNodes, nodes)); 5629 } 5630 #endif 5631 PetscFunctionReturn(PETSC_SUCCESS); 5632 } 5633 5634 /*@C 5635 DMPlexGetGeomID - Returns ID number of the entity in the geometric (CAD) model 5636 5637 Collective 5638 5639 Input Parameters: 5640 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5641 . body - PetscGeom body object containing the lower level entity the ID number is being requested. 5642 - topoObj - PetscGeom SHELL, FACE, LOOP, EDGE, or NODE object for which ID number is being requested. 5643 5644 Output Parameter: 5645 . id - ID number of the entity 5646 5647 Level: intermediate 5648 5649 .seealso: 5650 @*/ 5651 PetscErrorCode DMPlexGetGeomID(DM dm, PetscGeom body, PetscGeom topoObj, PetscInt *id) 5652 { 5653 PetscFunctionBeginHot; 5654 #ifdef PETSC_HAVE_EGADS 5655 PetscContainer modelObj; 5656 PetscBool islite = PETSC_FALSE; 5657 int topoID; 5658 5659 /* Determine which type of EGADS model is attached to the DM */ 5660 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5661 if (!modelObj) { 5662 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5663 islite = PETSC_TRUE; 5664 } 5665 5666 // Get Topology Object's ID 5667 if (islite) { 5668 topoID = EGlite_indexBodyTopo(body, topoObj); 5669 } else { 5670 topoID = EG_indexBodyTopo(body, topoObj); 5671 } 5672 5673 *id = topoID; 5674 #endif 5675 PetscFunctionReturn(PETSC_SUCCESS); 5676 } 5677 5678 /*@C 5679 DMPlexGetGeomObject - Returns Geometry Object using the objects ID in the geometric (CAD) model 5680 5681 Collective 5682 5683 Input Parameters: 5684 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5685 . body - PetscGeom body object containing the lower level entity the referenced by the ID. 5686 . geomType - Keyword SHELL, FACE, LOOP, EDGE, or NODE of the geometry type for which ID number is being requested. 5687 - geomID - ID number of the geometry entity being requested. 5688 5689 Output Parameter: 5690 . geomObj - Geometry Object referenced by the ID number requested. 5691 5692 Level: intermediate 5693 5694 .seealso: 5695 @*/ 5696 PetscErrorCode DMPlexGetGeomObject(DM dm, PetscGeom body, PetscInt geomType, PetscInt geomID, PetscGeom *geomObj) 5697 { 5698 PetscFunctionBeginHot; 5699 #ifdef PETSC_HAVE_EGADS 5700 PetscContainer modelObj; 5701 PetscBool islite = PETSC_FALSE; 5702 5703 /* Determine which type of EGADS model is attached to the DM */ 5704 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5705 if (!modelObj) { 5706 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5707 islite = PETSC_TRUE; 5708 } 5709 5710 // Get Topology Object's ID 5711 if (islite) { 5712 PetscCall(EGlite_objectBodyTopo(body, geomType, geomID, geomObj)); 5713 } else { 5714 PetscCall(EG_objectBodyTopo(body, geomType, geomID, geomObj)); 5715 } 5716 #endif 5717 PetscFunctionReturn(PETSC_SUCCESS); 5718 } 5719 5720 /*@C 5721 DMPlexGetGeomFaceNumOfControlPoints - Returns the total number of Control Points (and associated Weights) defining a FACE of a Geometry 5722 5723 Not collective 5724 5725 Input Parameters: 5726 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5727 - face - PetscGeom FACE object 5728 5729 Output Parameter: 5730 . numCntrlPnts - Number of Control Points (and Weights) defining the FACE 5731 5732 Level: intermediate 5733 5734 .seealso: 5735 @*/ 5736 PetscErrorCode DMPlexGetGeomFaceNumOfControlPoints(DM dm, PetscGeom face, PetscInt *numCntrlPnts) 5737 { 5738 PetscFunctionBeginHot; 5739 #ifdef PETSC_HAVE_EGADS 5740 PetscContainer modelObj; 5741 PetscBool islite = PETSC_FALSE; 5742 PetscGeom geom, gRef; 5743 PetscGeom *lobjs; 5744 int Nl, oclass, mtype, goclass, gmtype; 5745 int *lsenses, *gpinfo; 5746 double *gprv; 5747 5748 /* Determine which type of EGADS model is attached to the DM */ 5749 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5750 if (!modelObj) { 5751 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5752 islite = PETSC_TRUE; 5753 } 5754 5755 // Get Total Number of Control Points on FACE 5756 if (islite) { 5757 PetscCall(EGlite_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 5758 PetscCall(EGlite_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 5759 } else { 5760 PetscCall(EG_getTopology(face, &geom, &oclass, &mtype, NULL, &Nl, &lobjs, &lsenses)); 5761 PetscCall(EG_getGeometry(geom, &goclass, &gmtype, &gRef, &gpinfo, &gprv)); 5762 } 5763 5764 *numCntrlPnts = gpinfo[2] * gpinfo[5]; 5765 #endif 5766 PetscFunctionReturn(PETSC_SUCCESS); 5767 } 5768 5769 /*@C 5770 DMPlexGetGeomBodyMassProperties - Returns the Volume, Surface Area, Center of Gravity, and Inertia about the Body's Center of Gravity 5771 5772 Not collective 5773 5774 Input Parameters: 5775 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5776 - body - PetscGeom BODY object 5777 5778 Output Parameters: 5779 + volume - Volume of the CAD Body attached to the DM Plex 5780 . surfArea - Surface Area of the CAD Body attached to the DM Plex 5781 . centerOfGravity - Array with the Center of Gravity coordinates of the CAD Body attached to the DM Plex [x, y, z] 5782 . COGszie - Size of centerOfGravity[] Array 5783 . inertiaMatrixCOG - Array containing the Inertia about the Body's Center of Gravity [Ixx, Ixy, Ixz, Iyx, Iyy, Iyz, Izx, Izy, Izz] 5784 - IMCOGsize - Size of inertiaMatrixCOG[] Array 5785 5786 Level: intermediate 5787 5788 .seealso: 5789 @*/ 5790 PetscErrorCode DMPlexGetGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) 5791 { 5792 PetscFunctionBeginHot; 5793 #ifdef PETSC_HAVE_EGADS 5794 PetscContainer modelObj; 5795 PetscBool islite = PETSC_FALSE; 5796 PetscScalar geomData[14]; 5797 5798 /* Determine which type of EGADS model is attached to the DM */ 5799 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5800 if (!modelObj) { 5801 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5802 islite = PETSC_TRUE; 5803 PetscCheck(modelObj, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot provide geometric mass properties for geometries defined by EGADSlite (.egadslite)! Please use another geometry file format STEP, IGES, EGADS or BRep"); 5804 } 5805 5806 if (islite) { 5807 PetscCall(PetscPrintf(PETSC_COMM_SELF, " WARNING!! This functionality is not supported for EGADSlite files. \n")); 5808 PetscCall(PetscPrintf(PETSC_COMM_SELF, " All returned values are equal to 0 \n")); 5809 } else { 5810 PetscCall(EG_getMassProperties(body, geomData)); 5811 } 5812 5813 PetscCall(PetscMalloc2(3, centerOfGravity, 9, inertiaMatrixCOG)); 5814 5815 if (!islite) { 5816 *volume = geomData[0]; 5817 *surfArea = geomData[1]; 5818 for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = geomData[ii]; } 5819 *COGsize = 3; 5820 for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = geomData[ii]; } 5821 *IMCOGsize = 9; 5822 } else { 5823 *volume = 0.; 5824 *surfArea = 0.; 5825 for (int ii = 2; ii < 5; ++ii) { (*centerOfGravity)[ii - 2] = 0.; } 5826 *COGsize = 0; 5827 for (int ii = 5; ii < 14; ++ii) { (*inertiaMatrixCOG)[ii - 5] = 0.; } 5828 *IMCOGsize = 0; 5829 } 5830 #endif 5831 PetscFunctionReturn(PETSC_SUCCESS); 5832 } 5833 5834 PetscErrorCode DMPlexRestoreGeomBodyMassProperties(DM dm, PetscGeom body, PetscScalar *volume, PetscScalar *surfArea, PetscScalar **centerOfGravity, PetscInt *COGsize, PetscScalar **inertiaMatrixCOG, PetscInt *IMCOGsize) 5835 { 5836 PetscFunctionBegin; 5837 PetscCall(PetscFree2(*centerOfGravity, *inertiaMatrixCOG)); 5838 PetscFunctionReturn(PETSC_SUCCESS); 5839 } 5840 5841 /*@C 5842 DMPlexFreeGeomObject - Frees PetscGeom Objects 5843 5844 Not collective 5845 5846 Input Parameters: 5847 + dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5848 - geomObj - PetscGeom object 5849 5850 Level: intermediate 5851 5852 .seealso: 5853 @*/ 5854 PetscErrorCode DMPlexFreeGeomObject(DM dm, PetscGeom *geomObj) 5855 { 5856 PetscFunctionBeginHot; 5857 #ifdef PETSC_HAVE_EGADS 5858 PetscContainer modelObj; 5859 PetscBool islite = PETSC_FALSE; 5860 5861 /* Determine which type of EGADS model is attached to the DM */ 5862 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5863 if (!modelObj) { 5864 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 5865 islite = PETSC_TRUE; 5866 } 5867 5868 if (islite) { 5869 EGlite_free(geomObj); 5870 } else { 5871 EG_free(geomObj); 5872 } 5873 #endif 5874 PetscFunctionReturn(PETSC_SUCCESS); 5875 } 5876 5877 /*@C 5878 DMPlexGetGeomCntrlPntAndWeightData - Gets Control Point and Associated Weight Data for the Geometry attached to the DMPlex 5879 5880 Not collective 5881 5882 Input Parameter: 5883 . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5884 5885 Output Parameters: 5886 + cpHashTable - Hash Table containing the relationship between FACE ID and Control Point IDs. 5887 . cpCoordDataLength - Length of cpCoordData Array. 5888 . cpCoordData - Array holding the Geometry Control Point Coordinate Data. 5889 . maxNumEquiv - Maximum Number of Equivalent Control Points (Control Points with the same coordinates but different IDs). 5890 . cpEquiv - Matrix with a size(Number of Control Points, Number or Control Points) which stores a value of 1.0 in locations where Control Points with different IDS (row or column) have the same coordinates 5891 . wHashTable - Hash Table containing the relationship between FACE ID and Control Point Weight. 5892 . wDataLength - Length of wData Array. 5893 - wData - Array holding the Weight for an associated Geometry Control Point. 5894 5895 Note: 5896 Must Call DMPLexGeomDataAndGrads() before calling this function. 5897 5898 Level: intermediate 5899 5900 .seealso: 5901 @*/ 5902 PetscErrorCode DMPlexGetGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) 5903 { 5904 PetscContainer modelObj, cpHashTableObj, wHashTableObj, cpCoordDataLengthObj, wDataLengthObj, maxNumRelateObj; 5905 Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 5906 PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr, *maxNumEquivPtr; 5907 PetscHMapI cpHashTableTemp, wHashTableTemp; 5908 5909 PetscFunctionBeginHot; 5910 /* Determine which type of EGADS model is attached to the DM */ 5911 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5912 if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 5913 5914 if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 5915 5916 // Look to see if DM has Container for Geometry Control Point Data 5917 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 5918 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 5919 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordDataLengthObj)); 5920 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 5921 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 5922 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 5923 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Equivalancy Matrix", (PetscObject *)cpEquiv)); 5924 PetscCall(PetscObjectQuery((PetscObject)dm, "Maximum Number Control Point Equivalency", (PetscObject *)&maxNumRelateObj)); 5925 5926 // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 5927 PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTableTemp)); 5928 PetscCall(PetscContainerGetPointer(cpCoordDataLengthObj, (void **)&cpCoordDataLengthPtr)); 5929 PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTableTemp)); 5930 PetscCall(PetscContainerGetPointer(wDataLengthObj, (void **)&wDataLengthPtr)); 5931 PetscCall(PetscContainerGetPointer(maxNumRelateObj, (void **)&maxNumEquivPtr)); 5932 5933 *cpCoordDataLength = *cpCoordDataLengthPtr; 5934 *wDataLength = *wDataLengthPtr; 5935 *maxNumEquiv = *maxNumEquivPtr; 5936 *cpHashTable = cpHashTableTemp; 5937 *wHashTable = wHashTableTemp; 5938 PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, cpCoordData)); 5939 PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, wData)); 5940 PetscFunctionReturn(PETSC_SUCCESS); 5941 } 5942 5943 PetscErrorCode DMPlexRestoreGeomCntrlPntAndWeightData(DM dm, PetscHMapI *cpHashTable, PetscInt *cpCoordDataLength, PetscScalar **cpCoordData, PetscInt *maxNumEquiv, Mat *cpEquiv, PetscHMapI *wHashTable, PetscInt *wDataLength, PetscScalar **wData) 5944 { 5945 Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 5946 5947 PetscFunctionBeginHot; 5948 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 5949 PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, cpCoordData)); 5950 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 5951 PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, wData)); 5952 PetscFunctionReturn(PETSC_SUCCESS); 5953 } 5954 5955 /*@C 5956 DMPlexGetGeomGradData - Gets Point, Surface and Volume Gradients with respect to changes in Control Points and their associated Weights for the Geometry attached to the DMPlex . 5957 5958 Not collective 5959 5960 Input Parameter: 5961 . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 5962 5963 Output Parameters: 5964 + cpSurfGradHashTable - Hash Table Relating the Control Point ID to the the Row in the cpSurfGrad Matrix 5965 . cpSurfGrad - Matrix containing the Surface Gradient with respect to the Control Point Data. Data is ranged where the Row corresponds to Control Point ID and the Columns are associated with the Geometric FACE. 5966 . cpArraySize - The size of arrays gradSACP and gradVolCP and is equal to 3 * total number of Control Points in the Geometry 5967 . gradSACP - Array containing the Surface Area Gradient with respect to Control Point Data. Data is arranged by Control Point ID * 3 where 3 is for the coordinate dimension. 5968 . gradVolCP - Array contianing the Volume Gradient with respect to Control Point Data. Data is arranged by Control Point ID * 3 where 3 is for the coordinate dimension. 5969 . wArraySize - The size of arrayws gradSAW and gradVolW and is equal to the total number of Control Points in the Geometry. 5970 . gradSAW - Array containing the Surface Area Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 5971 - gradVolW - Array containing the Volume Gradient with respect to Control Point Weight. Data is arranged by Control Point ID. 5972 5973 Notes: 5974 Must Call DMPLexGeomDataAndGrads() before calling this function. 5975 5976 gradVolCP and gradVolW are only available when DMPlexGeomDataAndGrads() is called with fullGeomGrad = PETSC_TRUE. 5977 5978 Level: intermediate 5979 5980 .seealso: DMPlexGeomDataAndGrads 5981 @*/ 5982 PetscErrorCode DMPlexGetGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 5983 { 5984 PetscContainer modelObj, cpSurfGradHashTableObj, cpArraySizeObj, wArraySizeObj; 5985 Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 5986 PetscInt *cpArraySizePtr, *wArraySizePtr; 5987 PetscHMapI cpSurfGradHashTableTemp; 5988 5989 PetscFunctionBeginHot; 5990 /* Determine which type of EGADS model is attached to the DM */ 5991 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 5992 if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 5993 5994 if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 5995 5996 // Look to see if DM has Container for Geometry Control Point Data 5997 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Hash Table", (PetscObject *)&cpSurfGradHashTableObj)); 5998 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Gradient Matrix", (PetscObject *)cpSurfGrad)); 5999 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpArraySizeObj)); 6000 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 6001 PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 6002 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wArraySizeObj)); 6003 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 6004 PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 6005 6006 // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 6007 if (cpSurfGradHashTableObj) { 6008 PetscCall(PetscContainerGetPointer(cpSurfGradHashTableObj, (void **)&cpSurfGradHashTableTemp)); 6009 *cpSurfGradHashTable = cpSurfGradHashTableTemp; 6010 } 6011 6012 if (cpArraySizeObj) { 6013 PetscCall(PetscContainerGetPointer(cpArraySizeObj, (void **)&cpArraySizePtr)); 6014 *cpArraySize = *cpArraySizePtr; 6015 } 6016 6017 if (gradSACPVec) PetscCall(VecGetArrayWrite(gradSACPVec, gradSACP)); 6018 if (gradVolCPVec) PetscCall(VecGetArrayWrite(gradVolCPVec, gradVolCP)); 6019 if (gradSAWVec) PetscCall(VecGetArrayWrite(gradSAWVec, gradSAW)); 6020 if (gradVolWVec) PetscCall(VecGetArrayWrite(gradVolWVec, gradVolW)); 6021 6022 if (wArraySizeObj) { 6023 PetscCall(PetscContainerGetPointer(wArraySizeObj, (void **)&wArraySizePtr)); 6024 *wArraySize = *wArraySizePtr; 6025 } 6026 PetscFunctionReturn(PETSC_SUCCESS); 6027 } 6028 6029 PetscErrorCode DMPlexRestoreGeomGradData(DM dm, PetscHMapI *cpSurfGradHashTable, Mat *cpSurfGrad, PetscInt *cpArraySize, PetscScalar **gradSACP, PetscScalar **gradVolCP, PetscInt *wArraySize, PetscScalar **gradSAW, PetscScalar **gradVolW) 6030 { 6031 Vec gradSACPVec, gradVolCPVec, gradSAWVec, gradVolWVec; 6032 6033 PetscFunctionBegin; 6034 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Control Point Gradient", (PetscObject *)&gradSACPVec)); 6035 PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Control Point Gradient", (PetscObject *)&gradVolCPVec)); 6036 PetscCall(PetscObjectQuery((PetscObject)dm, "Surface Area Weights Gradient", (PetscObject *)&gradSAWVec)); 6037 PetscCall(PetscObjectQuery((PetscObject)dm, "Volume Weights Gradient", (PetscObject *)&gradVolWVec)); 6038 6039 if (gradSACPVec) PetscCall(VecRestoreArrayWrite(gradSACPVec, gradSACP)); 6040 if (gradVolCPVec) PetscCall(VecRestoreArrayWrite(gradVolCPVec, gradVolCP)); 6041 if (gradSAWVec) PetscCall(VecRestoreArrayWrite(gradSAWVec, gradSAW)); 6042 if (gradVolWVec) PetscCall(VecRestoreArrayWrite(gradVolWVec, gradVolW)); 6043 PetscFunctionReturn(PETSC_SUCCESS); 6044 } 6045 6046 /*@C 6047 DMPlexGetGeomCntrlPntMaps - Gets arrays which maps Control Point IDs to their associated Geometry FACE, EDGE, and VERTEX. 6048 6049 Not collective 6050 6051 Input Parameter: 6052 . dm - The DMPlex object with an attached PetscContainer storing a CAD Geometry object 6053 6054 Output Parameters: 6055 + numCntrlPnts - Number of Control Points defining the Geometry attached to the DMPlex 6056 . cntrlPntFaceMap - Array containing the FACE ID for the Control Point. Array index corresponds to Control Point ID. 6057 . cntrlPntWeightFaceMap - Array containing the FACE ID for the Control Point Weight. Array index corresponds to Control Point ID. 6058 . cntrlPntEdgeMap - Array containing the EDGE ID for the Control Point. Array index corresponds to Control Point ID. 6059 . cntrlPntWeightEdgeMap - Array containing the EDGE ID for the Control Point Weight. Array index corresponds to Control Point ID. 6060 . cntrlPntVertexMap - Array containing the VERTEX ID for the Control Point. Array index corresponds to Control Point ID. 6061 - cntrlPntWeightVertexMap - Array containing the VERTEX ID for the Control Point Weight. Array index corresponds to Control Point ID. 6062 6063 Note: 6064 Arrays are initialized to -1. Array elements with a -1 value indicates that the Control Point or Control Point Weight not associated with the referenced Geometric entity in the array name. 6065 6066 Level: intermediate 6067 6068 .seealso: DMPlexGeomDataAndGrads 6069 @*/ 6070 PetscErrorCode DMPlexGetGeomCntrlPntMaps(DM dm, PetscInt *numCntrlPnts, PetscInt **cntrlPntFaceMap, PetscInt **cntrlPntWeightFaceMap, PetscInt **cntrlPntEdgeMap, PetscInt **cntrlPntWeightEdgeMap, PetscInt **cntrlPntVertexMap, PetscInt **cntrlPntWeightVertexMap) 6071 { 6072 PetscFunctionBeginHot; 6073 #ifdef PETSC_HAVE_EGADS 6074 PetscContainer modelObj, numCntrlPntsObj, cntrlPntFaceMapObj, cntrlPntWeightFaceMapObj, cntrlPntEdgeMapObj, cntrlPntWeightEdgeMapObj, cntrlPntVertexMapObj, cntrlPntWeightVertexMapObj; 6075 PetscInt *numCntrlPntsPtr, *cntrlPntFaceMapPtr, *cntrlPntWeightFaceMapPtr, *cntrlPntEdgeMapPtr, *cntrlPntWeightEdgeMapPtr, *cntrlPntVertexMapPtr, *cntrlPntWeightVertexMapPtr; 6076 6077 /* Determine which type of EGADS model is attached to the DM */ 6078 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 6079 if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); } 6080 6081 if (!modelObj) { PetscFunctionReturn(PETSC_SUCCESS); } 6082 6083 // Look to see if DM has Container for Geometry Control Point Data 6084 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&numCntrlPntsObj)); 6085 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Face Map", (PetscObject *)&cntrlPntFaceMapObj)); 6086 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Face Map", (PetscObject *)&cntrlPntWeightFaceMapObj)); 6087 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Edge Map", (PetscObject *)&cntrlPntEdgeMapObj)); 6088 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Edge Map", (PetscObject *)&cntrlPntWeightEdgeMapObj)); 6089 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point - Vertex Map", (PetscObject *)&cntrlPntVertexMapObj)); 6090 PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight - Vertex Map", (PetscObject *)&cntrlPntWeightVertexMapObj)); 6091 6092 // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 6093 if (numCntrlPntsObj) { 6094 PetscCall(PetscContainerGetPointer(numCntrlPntsObj, (void **)&numCntrlPntsPtr)); 6095 *numCntrlPnts = *numCntrlPntsPtr; 6096 } 6097 6098 if (cntrlPntFaceMapObj) { 6099 PetscCall(PetscContainerGetPointer(cntrlPntFaceMapObj, (void **)&cntrlPntFaceMapPtr)); 6100 *cntrlPntFaceMap = cntrlPntFaceMapPtr; 6101 } 6102 6103 if (cntrlPntWeightFaceMapObj) { 6104 PetscCall(PetscContainerGetPointer(cntrlPntWeightFaceMapObj, (void **)&cntrlPntWeightFaceMapPtr)); 6105 *cntrlPntWeightFaceMap = cntrlPntWeightFaceMapPtr; 6106 } 6107 6108 if (cntrlPntEdgeMapObj) { 6109 PetscCall(PetscContainerGetPointer(cntrlPntEdgeMapObj, (void **)&cntrlPntEdgeMapPtr)); 6110 *cntrlPntEdgeMap = cntrlPntEdgeMapPtr; 6111 } 6112 6113 if (cntrlPntWeightEdgeMapObj) { 6114 PetscCall(PetscContainerGetPointer(cntrlPntWeightEdgeMapObj, (void **)&cntrlPntWeightEdgeMapPtr)); 6115 *cntrlPntWeightEdgeMap = cntrlPntWeightEdgeMapPtr; 6116 } 6117 6118 if (cntrlPntVertexMapObj) { 6119 PetscCall(PetscContainerGetPointer(cntrlPntVertexMapObj, (void **)&cntrlPntVertexMapPtr)); 6120 *cntrlPntVertexMap = cntrlPntVertexMapPtr; 6121 } 6122 6123 if (cntrlPntWeightVertexMapObj) { 6124 PetscCall(PetscContainerGetPointer(cntrlPntWeightVertexMapObj, (void **)&cntrlPntWeightVertexMapPtr)); 6125 *cntrlPntWeightVertexMap = cntrlPntWeightVertexMapPtr; 6126 } 6127 6128 #endif 6129 PetscFunctionReturn(PETSC_SUCCESS); 6130 } 6131 6132 #endif 6133