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