1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 2 3 #include <petscdmplex.h> /* For DMProjectCoordinates() */ 4 #include <petscsf.h> /* For DMLocatePoints() */ 5 6 PetscErrorCode DMRestrictHook_Coordinates(DM dm, DM dmc, void *ctx) 7 { 8 DM dm_coord, dmc_coord; 9 Vec coords, ccoords; 10 Mat inject; 11 PetscFunctionBegin; 12 PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 13 PetscCall(DMGetCoordinateDM(dmc, &dmc_coord)); 14 PetscCall(DMGetCoordinates(dm, &coords)); 15 PetscCall(DMGetCoordinates(dmc, &ccoords)); 16 if (coords && !ccoords) { 17 PetscCall(DMCreateGlobalVector(dmc_coord, &ccoords)); 18 PetscCall(PetscObjectSetName((PetscObject)ccoords, "coordinates")); 19 PetscCall(DMCreateInjection(dmc_coord, dm_coord, &inject)); 20 PetscCall(MatRestrict(inject, coords, ccoords)); 21 PetscCall(MatDestroy(&inject)); 22 PetscCall(DMSetCoordinates(dmc, ccoords)); 23 PetscCall(VecDestroy(&ccoords)); 24 } 25 PetscFunctionReturn(PETSC_SUCCESS); 26 } 27 28 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm, DM subdm, void *ctx) 29 { 30 DM dm_coord, subdm_coord; 31 Vec coords, ccoords, clcoords; 32 VecScatter *scat_i, *scat_g; 33 PetscFunctionBegin; 34 PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 35 PetscCall(DMGetCoordinateDM(subdm, &subdm_coord)); 36 PetscCall(DMGetCoordinates(dm, &coords)); 37 PetscCall(DMGetCoordinates(subdm, &ccoords)); 38 if (coords && !ccoords) { 39 PetscCall(DMCreateGlobalVector(subdm_coord, &ccoords)); 40 PetscCall(PetscObjectSetName((PetscObject)ccoords, "coordinates")); 41 PetscCall(DMCreateLocalVector(subdm_coord, &clcoords)); 42 PetscCall(PetscObjectSetName((PetscObject)clcoords, "coordinates")); 43 PetscCall(DMCreateDomainDecompositionScatters(dm_coord, 1, &subdm_coord, NULL, &scat_i, &scat_g)); 44 PetscCall(VecScatterBegin(scat_i[0], coords, ccoords, INSERT_VALUES, SCATTER_FORWARD)); 45 PetscCall(VecScatterEnd(scat_i[0], coords, ccoords, INSERT_VALUES, SCATTER_FORWARD)); 46 PetscCall(VecScatterBegin(scat_g[0], coords, clcoords, INSERT_VALUES, SCATTER_FORWARD)); 47 PetscCall(VecScatterEnd(scat_g[0], coords, clcoords, INSERT_VALUES, SCATTER_FORWARD)); 48 PetscCall(DMSetCoordinates(subdm, ccoords)); 49 PetscCall(DMSetCoordinatesLocal(subdm, clcoords)); 50 PetscCall(VecScatterDestroy(&scat_i[0])); 51 PetscCall(VecScatterDestroy(&scat_g[0])); 52 PetscCall(VecDestroy(&ccoords)); 53 PetscCall(VecDestroy(&clcoords)); 54 PetscCall(PetscFree(scat_i)); 55 PetscCall(PetscFree(scat_g)); 56 } 57 PetscFunctionReturn(PETSC_SUCCESS); 58 } 59 60 /*@ 61 DMGetCoordinateDM - Gets the `DM` that prescribes coordinate layout and scatters between global and local coordinates 62 63 Collective 64 65 Input Parameter: 66 . dm - the `DM` 67 68 Output Parameter: 69 . cdm - coordinate `DM` 70 71 Level: intermediate 72 73 .seealso: `DM`, `DMSetCoordinateDM()`, `DMSetCoordinates()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGSetCellCoordinateDM()`, 74 `DMGSetCellCoordinateDM()` 75 @*/ 76 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 77 { 78 PetscFunctionBegin; 79 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80 PetscValidPointer(cdm, 2); 81 if (!dm->coordinates[0].dm) { 82 DM cdm; 83 84 PetscUseTypeMethod(dm, createcoordinatedm, &cdm); 85 PetscCall(PetscObjectSetName((PetscObject)cdm, "coordinateDM")); 86 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 87 * until the call to CreateCoordinateDM) */ 88 PetscCall(DMDestroy(&dm->coordinates[0].dm)); 89 dm->coordinates[0].dm = cdm; 90 } 91 *cdm = dm->coordinates[0].dm; 92 PetscFunctionReturn(PETSC_SUCCESS); 93 } 94 95 /*@ 96 DMSetCoordinateDM - Sets the `DM` that prescribes coordinate layout and scatters between global and local coordinates 97 98 Logically Collective 99 100 Input Parameters: 101 + dm - the `DM` 102 - cdm - coordinate `DM` 103 104 Level: intermediate 105 106 .seealso: `DM`, `DMGetCoordinateDM()`, `DMSetCoordinates()`, `DMGetCellCoordinateDM()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, 107 `DMGSetCellCoordinateDM()` 108 @*/ 109 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 110 { 111 PetscFunctionBegin; 112 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 113 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 114 PetscCall(PetscObjectReference((PetscObject)cdm)); 115 PetscCall(DMDestroy(&dm->coordinates[0].dm)); 116 dm->coordinates[0].dm = cdm; 117 PetscFunctionReturn(PETSC_SUCCESS); 118 } 119 120 /*@ 121 DMGetCellCoordinateDM - Gets the `DM` that prescribes cellwise coordinate layout and scatters between global and local cellwise coordinates 122 123 Collective 124 125 Input Parameter: 126 . dm - the `DM` 127 128 Output Parameter: 129 . cdm - cellwise coordinate `DM`, or NULL if they are not defined 130 131 Level: intermediate 132 133 Note: 134 Call `DMLocalizeCoordinates()` to automatically create cellwise coordinates for periodic geometries. 135 136 .seealso: `DM`, `DMSetCellCoordinateDM()`, `DMSetCellCoordinates()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMGetCellCoordinatesLocal()`, 137 `DMLocalizeCoordinates()`, `DMSetCoordinateDM()`, `DMGetCoordinateDM()` 138 @*/ 139 PetscErrorCode DMGetCellCoordinateDM(DM dm, DM *cdm) 140 { 141 PetscFunctionBegin; 142 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 143 PetscValidPointer(cdm, 2); 144 *cdm = dm->coordinates[1].dm; 145 PetscFunctionReturn(PETSC_SUCCESS); 146 } 147 148 /*@ 149 DMSetCellCoordinateDM - Sets the `DM` that prescribes cellwise coordinate layout and scatters between global and local cellwise coordinates 150 151 Logically Collective 152 153 Input Parameters: 154 + dm - the `DM` 155 - cdm - cellwise coordinate `DM` 156 157 Level: intermediate 158 159 Note: 160 As opposed to `DMSetCoordinateDM()` these coordinates are useful for discontinuous Galerkin methods since they support coordinate fields that are discontinuous at cell boundaries. 161 162 .seealso: `DMGetCellCoordinateDM()`, `DMSetCellCoordinates()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMGetCellCoordinatesLocal()`, 163 `DMSetCoordinateDM()`, `DMGetCoordinateDM()` 164 @*/ 165 PetscErrorCode DMSetCellCoordinateDM(DM dm, DM cdm) 166 { 167 PetscInt dim; 168 169 PetscFunctionBegin; 170 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 171 if (cdm) { 172 PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 173 PetscCall(DMGetCoordinateDim(dm, &dim)); 174 dm->coordinates[1].dim = dim; 175 } 176 PetscCall(PetscObjectReference((PetscObject)cdm)); 177 PetscCall(DMDestroy(&dm->coordinates[1].dm)); 178 dm->coordinates[1].dm = cdm; 179 PetscFunctionReturn(PETSC_SUCCESS); 180 } 181 182 /*@ 183 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. For example a mesh on the surface of a sphere would have a 3 dimensional embedding space 184 185 Not Collective 186 187 Input Parameter: 188 . dm - The `DM` object 189 190 Output Parameter: 191 . dim - The embedding dimension 192 193 Level: intermediate 194 195 .seealso: `DM`, `DMSetCoordinateDim()`, `DMGetCoordinateSection()`, `DMGetCoordinateDM()`, `DMGetLocalSection()`, `DMSetLocalSection()` 196 @*/ 197 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 198 { 199 PetscFunctionBegin; 200 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 201 PetscValidIntPointer(dim, 2); 202 if (dm->coordinates[0].dim == PETSC_DEFAULT) dm->coordinates[0].dim = dm->dim; 203 *dim = dm->coordinates[0].dim; 204 PetscFunctionReturn(PETSC_SUCCESS); 205 } 206 207 /*@ 208 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 209 210 Not Collective 211 212 Input Parameters: 213 + dm - The `DM` object 214 - dim - The embedding dimension 215 216 Level: intermediate 217 218 .seealso: `DM`, `DMGetCoordinateDim()`, `DMSetCoordinateSection()`, `DMGetCoordinateSection()`, `DMGetLocalSection()`, `DMSetLocalSection()` 219 @*/ 220 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 221 { 222 PetscDS ds; 223 PetscInt Nds, n; 224 225 PetscFunctionBegin; 226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 227 dm->coordinates[0].dim = dim; 228 if (dm->dim >= 0) { 229 PetscCall(DMGetNumDS(dm, &Nds)); 230 for (n = 0; n < Nds; ++n) { 231 PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds)); 232 PetscCall(PetscDSSetCoordinateDimension(ds, dim)); 233 } 234 } 235 PetscFunctionReturn(PETSC_SUCCESS); 236 } 237 238 /*@ 239 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 240 241 Collective 242 243 Input Parameter: 244 . dm - The `DM` object 245 246 Output Parameter: 247 . section - The `PetscSection` object 248 249 Level: intermediate 250 251 Note: 252 This just retrieves the local section from the coordinate `DM`. In other words, 253 .vb 254 DMGetCoordinateDM(dm, &cdm); 255 DMGetLocalSection(cdm, §ion); 256 .ve 257 258 .seealso: `DMGetCoordinateDM()`, `DMGetLocalSection()`, `DMSetLocalSection()` 259 @*/ 260 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 261 { 262 DM cdm; 263 264 PetscFunctionBegin; 265 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 266 PetscValidPointer(section, 2); 267 PetscCall(DMGetCoordinateDM(dm, &cdm)); 268 PetscCall(DMGetLocalSection(cdm, section)); 269 PetscFunctionReturn(PETSC_SUCCESS); 270 } 271 272 /*@ 273 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 274 275 Not Collective 276 277 Input Parameters: 278 + dm - The `DM` object 279 . dim - The embedding dimension, or `PETSC_DETERMINE` 280 - section - The `PetscSection` object 281 282 Level: intermediate 283 284 .seealso: `DM`, `DMGetCoordinateDim()`, `DMGetCoordinateSection()`, `DMGetLocalSection()`, `DMSetLocalSection()` 285 @*/ 286 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 287 { 288 DM cdm; 289 290 PetscFunctionBegin; 291 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 292 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 3); 293 PetscCall(DMGetCoordinateDM(dm, &cdm)); 294 PetscCall(DMSetLocalSection(cdm, section)); 295 if (dim == PETSC_DETERMINE) { 296 PetscInt d = PETSC_DEFAULT; 297 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 298 299 PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 300 PetscCall(DMGetDimPoints(dm, 0, &vStart, &vEnd)); 301 pStart = PetscMax(vStart, pStart); 302 pEnd = PetscMin(vEnd, pEnd); 303 for (v = pStart; v < pEnd; ++v) { 304 PetscCall(PetscSectionGetDof(section, v, &dd)); 305 if (dd) { 306 d = dd; 307 break; 308 } 309 } 310 if (d >= 0) PetscCall(DMSetCoordinateDim(dm, d)); 311 } 312 PetscFunctionReturn(PETSC_SUCCESS); 313 } 314 315 /*@ 316 DMGetCellCoordinateSection - Retrieve the layout of cellwise coordinate values over the mesh. 317 318 Collective 319 320 Input Parameter: 321 . dm - The `DM` object 322 323 Output Parameter: 324 . section - The `PetscSection` object, or `NULL` if no cellwise coordinates are defined 325 326 Level: intermediate 327 328 Note: 329 This just retrieves the local section from the cell coordinate `DM`. In other words, 330 .vb 331 DMGetCellCoordinateDM(dm, &cdm); 332 DMGetLocalSection(cdm, §ion); 333 .ve 334 335 .seealso: `DM`, `DMGetCoordinateSection()`, `DMSetCellCoordinateSection()`, `DMGetCellCoordinateDM()`, `DMGetCoordinateDM()`, `DMGetLocalSection()`, `DMSetLocalSection()` 336 @*/ 337 PetscErrorCode DMGetCellCoordinateSection(DM dm, PetscSection *section) 338 { 339 DM cdm; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 343 PetscValidPointer(section, 2); 344 *section = NULL; 345 PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 346 if (cdm) PetscCall(DMGetLocalSection(cdm, section)); 347 PetscFunctionReturn(PETSC_SUCCESS); 348 } 349 350 /*@ 351 DMSetCellCoordinateSection - Set the layout of cellwise coordinate values over the mesh. 352 353 Not Collective 354 355 Input Parameters: 356 + dm - The `DM` object 357 . dim - The embedding dimension, or `PETSC_DETERMINE` 358 - section - The `PetscSection` object for a cellwise layout 359 360 Level: intermediate 361 362 .seealso: `DM`, `DMGetCoordinateDim()`, `DMSetCoordinateSection()`, `DMGetCellCoordinateSection()`, `DMGetCoordinateSection()`, `DMGetCellCoordinateDM()`, `DMGetLocalSection()`, `DMSetLocalSection()` 363 @*/ 364 PetscErrorCode DMSetCellCoordinateSection(DM dm, PetscInt dim, PetscSection section) 365 { 366 DM cdm; 367 368 PetscFunctionBegin; 369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 370 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 3); 371 PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 372 PetscCheck(cdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "No DM defined for cellwise coordinates"); 373 PetscCall(DMSetLocalSection(cdm, section)); 374 if (dim == PETSC_DETERMINE) { 375 PetscInt d = PETSC_DEFAULT; 376 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 377 378 PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 379 PetscCall(DMGetDimPoints(dm, 0, &vStart, &vEnd)); 380 pStart = PetscMax(vStart, pStart); 381 pEnd = PetscMin(vEnd, pEnd); 382 for (v = pStart; v < pEnd; ++v) { 383 PetscCall(PetscSectionGetDof(section, v, &dd)); 384 if (dd) { 385 d = dd; 386 break; 387 } 388 } 389 if (d >= 0) PetscCall(DMSetCoordinateDim(dm, d)); 390 } 391 PetscFunctionReturn(PETSC_SUCCESS); 392 } 393 394 /*@ 395 DMGetCoordinates - Gets a global vector with the coordinates associated with the `DM`. 396 397 Collective 398 399 Input Parameter: 400 . dm - the `DM` 401 402 Output Parameter: 403 . c - global coordinate vector 404 405 Level: intermediate 406 407 Notes: 408 This is a borrowed reference, so the user should NOT destroy this vector. When the `DM` is 409 destroyed the array will no longer be valid. 410 411 Each process has only the locally-owned portion of the global coordinates (does NOT have the ghost coordinates). 412 413 For `DMDA`, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 414 and (x_0,y_0,z_0,x_1,y_1,z_1...) 415 416 .seealso: `DM`, `DMDA`, `DMSetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMDASetUniformCoordinates()` 417 @*/ 418 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 419 { 420 PetscFunctionBegin; 421 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 422 PetscValidPointer(c, 2); 423 if (!dm->coordinates[0].x && dm->coordinates[0].xl) { 424 DM cdm = NULL; 425 426 PetscCall(DMGetCoordinateDM(dm, &cdm)); 427 PetscCall(DMCreateGlobalVector(cdm, &dm->coordinates[0].x)); 428 PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[0].x, "coordinates")); 429 PetscCall(DMLocalToGlobalBegin(cdm, dm->coordinates[0].xl, INSERT_VALUES, dm->coordinates[0].x)); 430 PetscCall(DMLocalToGlobalEnd(cdm, dm->coordinates[0].xl, INSERT_VALUES, dm->coordinates[0].x)); 431 } 432 *c = dm->coordinates[0].x; 433 PetscFunctionReturn(PETSC_SUCCESS); 434 } 435 436 /*@ 437 DMSetCoordinates - Sets into the `DM` a global vector that holds the coordinates 438 439 Collective 440 441 Input Parameters: 442 + dm - the `DM` 443 - c - coordinate vector 444 445 Level: intermediate 446 447 Notes: 448 The coordinates do not include those for ghost points, which are in the local vector. 449 450 The vector `c` can be destroyed after the call 451 452 .seealso: `DM`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMDASetUniformCoordinates()` 453 @*/ 454 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 455 { 456 PetscFunctionBegin; 457 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 458 if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2); 459 PetscCall(PetscObjectReference((PetscObject)c)); 460 PetscCall(VecDestroy(&dm->coordinates[0].x)); 461 dm->coordinates[0].x = c; 462 PetscCall(VecDestroy(&dm->coordinates[0].xl)); 463 PetscCall(DMCoarsenHookAdd(dm, DMRestrictHook_Coordinates, NULL, NULL)); 464 PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_Coordinates, NULL, NULL)); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 DMGetCellCoordinates - Gets a global vector with the cellwise coordinates associated with the `DM`. 470 471 Collective 472 473 Input Parameter: 474 . dm - the `DM` 475 476 Output Parameter: 477 . c - global coordinate vector 478 479 Level: intermediate 480 481 Notes: 482 This is a borrowed reference, so the user should NOT destroy this vector. When the `DM` is 483 destroyed the array will no longer be valid. 484 485 Each process has only the locally-owned portion of the global coordinates (does NOT have the ghost coordinates). 486 487 .seealso: `DM`, `DMGetCoordinates()`, `DMSetCellCoordinates()`, `DMGetCellCoordinatesLocal()`, `DMGetCellCoordinateDM()` 488 @*/ 489 PetscErrorCode DMGetCellCoordinates(DM dm, Vec *c) 490 { 491 PetscFunctionBegin; 492 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 493 PetscValidPointer(c, 2); 494 if (!dm->coordinates[1].x && dm->coordinates[1].xl) { 495 DM cdm = NULL; 496 497 PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 498 PetscCall(DMCreateGlobalVector(cdm, &dm->coordinates[1].x)); 499 PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[1].x, "DG coordinates")); 500 PetscCall(DMLocalToGlobalBegin(cdm, dm->coordinates[1].xl, INSERT_VALUES, dm->coordinates[1].x)); 501 PetscCall(DMLocalToGlobalEnd(cdm, dm->coordinates[1].xl, INSERT_VALUES, dm->coordinates[1].x)); 502 } 503 *c = dm->coordinates[1].x; 504 PetscFunctionReturn(PETSC_SUCCESS); 505 } 506 507 /*@ 508 DMSetCellCoordinates - Sets into the `DM` a global vector that holds the cellwise coordinates 509 510 Collective 511 512 Input Parameters: 513 + dm - the `DM` 514 - c - cellwise coordinate vector 515 516 Level: intermediate 517 518 Notes: 519 The coordinates do not include those for ghost points, which are in the local vector. 520 521 The vector `c` should be destroyed by the caller. 522 523 .seealso: `DM`, `DMGetCoordinates()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMGetCellCoordinatesLocal()`, `DMGetCellCoordinateDM()` 524 @*/ 525 PetscErrorCode DMSetCellCoordinates(DM dm, Vec c) 526 { 527 PetscFunctionBegin; 528 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 529 if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2); 530 PetscCall(PetscObjectReference((PetscObject)c)); 531 PetscCall(VecDestroy(&dm->coordinates[1].x)); 532 dm->coordinates[1].x = c; 533 PetscCall(VecDestroy(&dm->coordinates[1].xl)); 534 PetscFunctionReturn(PETSC_SUCCESS); 535 } 536 537 /*@ 538 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that `DMGetCoordinatesLocalNoncollective()` can be used as non-collective afterwards. 539 540 Collective 541 542 Input Parameter: 543 . dm - the `DM` 544 545 Level: advanced 546 547 .seealso: `DM`, `DMSetCoordinates()`, `DMGetCoordinatesLocalNoncollective()` 548 @*/ 549 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 550 { 551 PetscFunctionBegin; 552 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 553 if (!dm->coordinates[0].xl && dm->coordinates[0].x) { 554 DM cdm = NULL; 555 PetscInt bs; 556 557 PetscCall(DMGetCoordinateDM(dm, &cdm)); 558 PetscCall(DMCreateLocalVector(cdm, &dm->coordinates[0].xl)); 559 // If the size of the vector is 0, it will not get the right block size 560 PetscCall(VecGetBlockSize(dm->coordinates[0].x, &bs)); 561 PetscCall(VecSetBlockSize(dm->coordinates[0].xl, bs)); 562 PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[0].xl, "coordinates")); 563 PetscCall(DMGlobalToLocalBegin(cdm, dm->coordinates[0].x, INSERT_VALUES, dm->coordinates[0].xl)); 564 PetscCall(DMGlobalToLocalEnd(cdm, dm->coordinates[0].x, INSERT_VALUES, dm->coordinates[0].xl)); 565 } 566 PetscFunctionReturn(PETSC_SUCCESS); 567 } 568 569 /*@ 570 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the `DM`. 571 572 Collective the first time it is called 573 574 Input Parameter: 575 . dm - the `DM` 576 577 Output Parameter: 578 . c - coordinate vector 579 580 Level: intermediate 581 582 Notes: 583 This is a borrowed reference, so the user should NOT destroy this vector 584 585 Each process has the local and ghost coordinates 586 587 For `DMDA`, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 588 and (x_0,y_0,z_0,x_1,y_1,z_1...) 589 590 .seealso: `DM`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()`, `DMGetCoordinatesLocalNoncollective()` 591 @*/ 592 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 593 { 594 PetscFunctionBegin; 595 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 596 PetscValidPointer(c, 2); 597 PetscCall(DMGetCoordinatesLocalSetUp(dm)); 598 *c = dm->coordinates[0].xl; 599 PetscFunctionReturn(PETSC_SUCCESS); 600 } 601 602 /*@ 603 DMGetCoordinatesLocalNoncollective - Non-collective version of `DMGetCoordinatesLocal()`. Fails if global coordinates have been set and `DMGetCoordinatesLocalSetUp()` not called. 604 605 Not Collective 606 607 Input Parameter: 608 . dm - the `DM` 609 610 Output Parameter: 611 . c - coordinate vector 612 613 Level: advanced 614 615 Note: 616 A previous call to `DMGetCoordinatesLocal()` or `DMGetCoordinatesLocalSetUp()` ensures that a call to this function will not error. 617 618 .seealso: `DM`, `DMGetCoordinatesLocalSetUp()`, `DMGetCoordinatesLocal()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()` 619 @*/ 620 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 621 { 622 PetscFunctionBegin; 623 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 624 PetscValidPointer(c, 2); 625 PetscCheck(dm->coordinates[0].xl || !dm->coordinates[0].x, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 626 *c = dm->coordinates[0].xl; 627 PetscFunctionReturn(PETSC_SUCCESS); 628 } 629 630 /*@ 631 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and the section describing its layout. 632 633 Not Collective 634 635 Input Parameters: 636 + dm - the `DM` 637 - p - the `IS` of points whose coordinates will be returned 638 639 Output Parameters: 640 + pCoordSection - the `PetscSection` describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 641 - pCoord - the `Vec` with coordinates of points in p 642 643 Level: advanced 644 645 Notes: 646 `DMGetCoordinatesLocalSetUp()` must be called first. This function employs `DMGetCoordinatesLocalNoncollective()` so it is not collective. 647 648 This creates a new vector, so the user SHOULD destroy this vector 649 650 Each process has the local and ghost coordinates 651 652 For `DMDA`, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 653 and (x_0,y_0,z_0,x_1,y_1,z_1...) 654 655 .seealso: `DM`, `DMDA`, `DMSetCoordinatesLocal()`, `DMGetCoordinatesLocal()`, `DMGetCoordinatesLocalNoncollective()`, `DMGetCoordinatesLocalSetUp()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()` 656 @*/ 657 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 658 { 659 DM cdm; 660 PetscSection cs, newcs; 661 Vec coords; 662 const PetscScalar *arr; 663 PetscScalar *newarr = NULL; 664 PetscInt n; 665 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 668 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 669 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 670 if (pCoord) PetscValidPointer(pCoord, 4); 671 PetscCall(DMGetCoordinateDM(dm, &cdm)); 672 PetscCall(DMGetLocalSection(cdm, &cs)); 673 PetscCall(DMGetCoordinatesLocal(dm, &coords)); 674 PetscCheck(coords, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 675 PetscCheck(cdm && cs, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 676 PetscCall(VecGetArrayRead(coords, &arr)); 677 PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void **)&newarr) : NULL)); 678 PetscCall(VecRestoreArrayRead(coords, &arr)); 679 if (pCoord) { 680 PetscCall(PetscSectionGetStorageSize(newcs, &n)); 681 /* set array in two steps to mimic PETSC_OWN_POINTER */ 682 PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord)); 683 PetscCall(VecReplaceArray(*pCoord, newarr)); 684 } else { 685 PetscCall(PetscFree(newarr)); 686 } 687 if (pCoordSection) { 688 *pCoordSection = newcs; 689 } else PetscCall(PetscSectionDestroy(&newcs)); 690 PetscFunctionReturn(PETSC_SUCCESS); 691 } 692 693 /*@ 694 DMSetCoordinatesLocal - Sets into the `DM` a local vector, including ghost points, that holds the coordinates 695 696 Not Collective 697 698 Input Parameters: 699 + dm - the `DM` 700 - c - coordinate vector 701 702 Level: intermediate 703 704 Notes: 705 The coordinates of ghost points can be set using `DMSetCoordinates()` 706 followed by `DMGetCoordinatesLocal()`. This is intended to enable the 707 setting of ghost coordinates outside of the domain. 708 709 The vector c should be destroyed by the caller. 710 711 .seealso: `DM`, `DMGetCoordinatesLocal()`, `DMSetCoordinates()`, `DMGetCoordinates()`, `DMGetCoordinateDM()` 712 @*/ 713 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 714 { 715 PetscFunctionBegin; 716 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 717 if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2); 718 PetscCall(PetscObjectReference((PetscObject)c)); 719 PetscCall(VecDestroy(&dm->coordinates[0].xl)); 720 dm->coordinates[0].xl = c; 721 PetscCall(VecDestroy(&dm->coordinates[0].x)); 722 PetscFunctionReturn(PETSC_SUCCESS); 723 } 724 725 /*@ 726 DMGetCellCoordinatesLocalSetUp - Prepares a local vector of cellwise coordinates, so that `DMGetCellCoordinatesLocalNoncollective()` can be used as non-collective afterwards. 727 728 Collective 729 730 Input Parameter: 731 . dm - the `DM` 732 733 Level: advanced 734 735 .seealso: `DM`, `DMGetCellCoordinatesLocalNoncollective()` 736 @*/ 737 PetscErrorCode DMGetCellCoordinatesLocalSetUp(DM dm) 738 { 739 PetscFunctionBegin; 740 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 741 if (!dm->coordinates[1].xl && dm->coordinates[1].x) { 742 DM cdm = NULL; 743 744 PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 745 PetscCall(DMCreateLocalVector(cdm, &dm->coordinates[1].xl)); 746 PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[1].xl, "DG coordinates")); 747 PetscCall(DMGlobalToLocalBegin(cdm, dm->coordinates[1].x, INSERT_VALUES, dm->coordinates[1].xl)); 748 PetscCall(DMGlobalToLocalEnd(cdm, dm->coordinates[1].x, INSERT_VALUES, dm->coordinates[1].xl)); 749 } 750 PetscFunctionReturn(PETSC_SUCCESS); 751 } 752 753 /*@ 754 DMGetCellCoordinatesLocal - Gets a local vector with the cellwise coordinates associated with the `DM`. 755 756 Collective 757 758 Input Parameter: 759 . dm - the `DM` 760 761 Output Parameter: 762 . c - coordinate vector 763 764 Level: intermediate 765 766 Notes: 767 This is a borrowed reference, so the user should NOT destroy this vector 768 769 Each process has the local and ghost coordinates 770 771 .seealso: `DM`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMSetCellCoordinates()`, `DMGetCellCoordinateDM()`, `DMGetCellCoordinatesLocalNoncollective()` 772 @*/ 773 PetscErrorCode DMGetCellCoordinatesLocal(DM dm, Vec *c) 774 { 775 PetscFunctionBegin; 776 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 777 PetscValidPointer(c, 2); 778 PetscCall(DMGetCellCoordinatesLocalSetUp(dm)); 779 *c = dm->coordinates[1].xl; 780 PetscFunctionReturn(PETSC_SUCCESS); 781 } 782 783 /*@ 784 DMGetCellCoordinatesLocalNoncollective - Non-collective version of `DMGetCellCoordinatesLocal()`. Fails if global cellwise coordinates have been set and `DMGetCellCoordinatesLocalSetUp()` not called. 785 786 Not Collective 787 788 Input Parameter: 789 . dm - the `DM` 790 791 Output Parameter: 792 . c - cellwise coordinate vector 793 794 Level: advanced 795 796 .seealso: `DM`, `DMGetCellCoordinatesLocalSetUp()`, `DMGetCellCoordinatesLocal()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMSetCellCoordinates()`, `DMGetCellCoordinateDM()` 797 @*/ 798 PetscErrorCode DMGetCellCoordinatesLocalNoncollective(DM dm, Vec *c) 799 { 800 PetscFunctionBegin; 801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 802 PetscValidPointer(c, 2); 803 PetscCheck(dm->coordinates[1].xl || !dm->coordinates[1].x, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCellCoordinatesLocalSetUp() has not been called"); 804 *c = dm->coordinates[1].xl; 805 PetscFunctionReturn(PETSC_SUCCESS); 806 } 807 808 /*@ 809 DMSetCellCoordinatesLocal - Sets into the `DM` a local vector including ghost points that holds the cellwise coordinates 810 811 Not Collective 812 813 Input Parameters: 814 + dm - the `DM` 815 - c - cellwise coordinate vector 816 817 Level: intermediate 818 819 Notes: 820 The coordinates of ghost points can be set using `DMSetCoordinates()` 821 followed by `DMGetCoordinatesLocal()`. This is intended to enable the 822 setting of ghost coordinates outside of the domain. 823 824 The vector c should be destroyed by the caller. 825 826 .seealso: `DM`, `DMGetCellCoordinatesLocal()`, `DMSetCellCoordinates()`, `DMGetCellCoordinates()`, `DMGetCellCoordinateDM()` 827 @*/ 828 PetscErrorCode DMSetCellCoordinatesLocal(DM dm, Vec c) 829 { 830 PetscFunctionBegin; 831 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 832 if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2); 833 PetscCall(PetscObjectReference((PetscObject)c)); 834 PetscCall(VecDestroy(&dm->coordinates[1].xl)); 835 dm->coordinates[1].xl = c; 836 PetscCall(VecDestroy(&dm->coordinates[1].x)); 837 PetscFunctionReturn(PETSC_SUCCESS); 838 } 839 840 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 841 { 842 PetscFunctionBegin; 843 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 844 PetscValidPointer(field, 2); 845 if (!dm->coordinates[0].field) { 846 if (dm->ops->createcoordinatefield) PetscCall((*dm->ops->createcoordinatefield)(dm, &dm->coordinates[0].field)); 847 } 848 *field = dm->coordinates[0].field; 849 PetscFunctionReturn(PETSC_SUCCESS); 850 } 851 852 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 853 { 854 PetscFunctionBegin; 855 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 856 if (field) PetscValidHeaderSpecific(field, DMFIELD_CLASSID, 2); 857 PetscCall(PetscObjectReference((PetscObject)field)); 858 PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 859 dm->coordinates[0].field = field; 860 PetscFunctionReturn(PETSC_SUCCESS); 861 } 862 863 /*@ 864 DMGetLocalBoundingBox - Returns the bounding box for the piece of the `DM` on this process. 865 866 Not Collective 867 868 Input Parameter: 869 . dm - the `DM` 870 871 Output Parameters: 872 + lmin - local minimum coordinates (length coord dim, optional) 873 - lmax - local maximum coordinates (length coord dim, optional) 874 875 Level: beginner 876 877 Note: 878 If the `DM` is a `DMDA` and has no coordinates, the index bounds are returned instead. 879 880 .seealso: `DM`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetBoundingBox()` 881 @*/ 882 PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[]) 883 { 884 Vec coords = NULL; 885 PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 886 PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 887 PetscInt cdim, i, j; 888 889 PetscFunctionBegin; 890 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 891 PetscCall(DMGetCoordinateDim(dm, &cdim)); 892 PetscCall(DMGetCoordinatesLocal(dm, &coords)); 893 if (coords) { 894 const PetscScalar *local_coords; 895 PetscInt N, Ni; 896 897 for (j = cdim; j < 3; ++j) { 898 min[j] = 0; 899 max[j] = 0; 900 } 901 PetscCall(VecGetArrayRead(coords, &local_coords)); 902 PetscCall(VecGetLocalSize(coords, &N)); 903 Ni = N / cdim; 904 for (i = 0; i < Ni; ++i) { 905 for (j = 0; j < cdim; ++j) { 906 min[j] = PetscMin(min[j], PetscRealPart(local_coords[i * cdim + j])); 907 max[j] = PetscMax(max[j], PetscRealPart(local_coords[i * cdim + j])); 908 } 909 } 910 PetscCall(VecRestoreArrayRead(coords, &local_coords)); 911 PetscCall(DMGetCellCoordinatesLocal(dm, &coords)); 912 if (coords) { 913 PetscCall(VecGetArrayRead(coords, &local_coords)); 914 PetscCall(VecGetLocalSize(coords, &N)); 915 Ni = N / cdim; 916 for (i = 0; i < Ni; ++i) { 917 for (j = 0; j < cdim; ++j) { 918 min[j] = PetscMin(min[j], PetscRealPart(local_coords[i * cdim + j])); 919 max[j] = PetscMax(max[j], PetscRealPart(local_coords[i * cdim + j])); 920 } 921 } 922 PetscCall(VecRestoreArrayRead(coords, &local_coords)); 923 } 924 } else { 925 PetscBool isda; 926 927 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMDA, &isda)); 928 if (isda) PetscCall(DMGetLocalBoundingIndices_DMDA(dm, min, max)); 929 } 930 if (lmin) PetscCall(PetscArraycpy(lmin, min, cdim)); 931 if (lmax) PetscCall(PetscArraycpy(lmax, max, cdim)); 932 PetscFunctionReturn(PETSC_SUCCESS); 933 } 934 935 /*@ 936 DMGetBoundingBox - Returns the global bounding box for the `DM`. 937 938 Collective 939 940 Input Parameter: 941 . dm - the `DM` 942 943 Output Parameters: 944 + gmin - global minimum coordinates (length coord dim, optional) 945 - gmax - global maximum coordinates (length coord dim, optional) 946 947 Level: beginner 948 949 .seealso: `DM`, `DMGetLocalBoundingBox()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()` 950 @*/ 951 PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[]) 952 { 953 PetscReal lmin[3], lmax[3]; 954 PetscInt cdim; 955 PetscMPIInt count; 956 957 PetscFunctionBegin; 958 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 959 PetscCall(DMGetCoordinateDim(dm, &cdim)); 960 PetscCall(PetscMPIIntCast(cdim, &count)); 961 PetscCall(DMGetLocalBoundingBox(dm, lmin, lmax)); 962 if (gmin) PetscCall(MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)dm))); 963 if (gmax) PetscCall(MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 964 PetscFunctionReturn(PETSC_SUCCESS); 965 } 966 967 static void evaluate_coordinates(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar xnew[]) 968 { 969 for (PetscInt i = 0; i < dim; i++) xnew[i] = x[i]; 970 } 971 972 /*@ 973 DMProjectCoordinates - Project coordinates to a different space 974 975 Input Parameters: 976 + dm - The `DM` object 977 - disc - The new coordinate discretization or NULL to ensure a coordinate discretization exists 978 979 Level: intermediate 980 981 Notes: 982 A `PetscFE` defines an approximation space using a `PetscSpace`, which represents the basis functions, and a `PetscDualSpace`, which defines the interpolation operation 983 in the space. 984 985 This function takes the current mesh coordinates, which are discretized using some `PetscFE` space, and projects this function into a new `PetscFE` space. 986 The coordinate projection is done on the continuous coordinates, and if possible, the discontinuous coordinates are also updated. 987 988 Developer Note: 989 With more effort, we could directly project the discontinuous coordinates also. 990 991 .seealso: `DM`, `PetscFE`, `DMGetCoordinateField()` 992 @*/ 993 PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc) 994 { 995 PetscFE discOld; 996 PetscClassId classid; 997 DM cdmOld, cdmNew; 998 Vec coordsOld, coordsNew; 999 PetscBool same_space = PETSC_TRUE; 1000 const char *prefix; 1001 1002 PetscFunctionBegin; 1003 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1004 if (disc) PetscValidHeaderSpecific(disc, PETSCFE_CLASSID, 2); 1005 1006 PetscCall(DMGetCoordinateDM(dm, &cdmOld)); 1007 /* Check current discretization is compatible */ 1008 PetscCall(DMGetField(cdmOld, 0, NULL, (PetscObject *)&discOld)); 1009 PetscCall(PetscObjectGetClassId((PetscObject)discOld, &classid)); 1010 if (classid != PETSCFE_CLASSID) { 1011 if (classid == PETSC_CONTAINER_CLASSID) { 1012 PetscFE feLinear; 1013 DMPolytopeType ct; 1014 PetscInt dim, dE, cStart, cEnd, ctTmp; 1015 1016 /* Assume linear vertex coordinates */ 1017 PetscCall(DMGetDimension(dm, &dim)); 1018 PetscCall(DMGetCoordinateDim(dm, &dE)); 1019 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1020 if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 1021 else ct = DM_POLYTOPE_UNKNOWN; 1022 ctTmp = (PetscInt)ct; 1023 PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &ctTmp, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 1024 ct = (DMPolytopeType)ctTmp; 1025 PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, 1, -1, &feLinear)); 1026 PetscCall(DMSetField(cdmOld, 0, NULL, (PetscObject)feLinear)); 1027 PetscCall(PetscFEDestroy(&feLinear)); 1028 PetscCall(DMCreateDS(cdmOld)); 1029 PetscCall(DMGetField(cdmOld, 0, NULL, (PetscObject *)&discOld)); 1030 } else { 1031 const char *discname; 1032 1033 PetscCall(PetscObjectGetType((PetscObject)discOld, &discname)); 1034 SETERRQ(PetscObjectComm((PetscObject)discOld), PETSC_ERR_SUP, "Discretization type %s not supported", discname); 1035 } 1036 } 1037 if (!disc) PetscFunctionReturn(PETSC_SUCCESS); 1038 { // Check if the new space is the same as the old modulo quadrature 1039 PetscDualSpace dsOld, ds; 1040 PetscCall(PetscFEGetDualSpace(discOld, &dsOld)); 1041 PetscCall(PetscFEGetDualSpace(disc, &ds)); 1042 PetscCall(PetscDualSpaceEqual(dsOld, ds, &same_space)); 1043 } 1044 /* Make a fresh clone of the coordinate DM */ 1045 PetscCall(DMClone(cdmOld, &cdmNew)); 1046 cdmNew->cloneOpts = PETSC_TRUE; 1047 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdmOld, &prefix)); 1048 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdmNew, prefix)); 1049 PetscCall(DMSetField(cdmNew, 0, NULL, (PetscObject)disc)); 1050 PetscCall(DMCreateDS(cdmNew)); 1051 if (cdmOld->periodic.setup) { 1052 cdmNew->periodic.setup = cdmOld->periodic.setup; 1053 PetscCall(cdmNew->periodic.setup(cdmNew)); 1054 } 1055 if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(cdmNew)); 1056 PetscCall(DMGetCoordinates(dm, &coordsOld)); 1057 PetscCall(DMCreateGlobalVector(cdmNew, &coordsNew)); 1058 if (same_space) { 1059 // Need to copy so that the new vector has the right dm 1060 PetscCall(VecCopy(coordsOld, coordsNew)); 1061 } else { // Project the coordinate vector from old to new space 1062 void (*funcs[])(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]) = {evaluate_coordinates}; 1063 // We can't call DMProjectField directly because it depends on KSP for DMGlobalToLocalSolve(), but we can use the core strategy 1064 Vec X_new_loc; 1065 PetscCall(DMCreateLocalVector(cdmNew, &X_new_loc)); 1066 PetscCall(DMSetCoordinateDM(cdmNew, cdmOld)); 1067 // See DMPlexRemapGeometry() for a similar pattern handling the coordinate field 1068 DMField cf; 1069 PetscCall(DMGetCoordinateField(dm, &cf)); 1070 cdmNew->coordinates[0].field = cf; 1071 PetscCall(DMProjectFieldLocal(cdmNew, 0.0, NULL, funcs, INSERT_VALUES, X_new_loc)); 1072 cdmNew->coordinates[0].field = NULL; 1073 PetscCall(DMSetCoordinateDM(cdmNew, NULL)); 1074 PetscCall(DMLocalToGlobal(cdmNew, X_new_loc, INSERT_VALUES, coordsNew)); 1075 PetscCall(VecDestroy(&X_new_loc)); 1076 } 1077 /* Set new coordinate structures */ 1078 PetscCall(DMSetCoordinateField(dm, NULL)); 1079 PetscCall(DMSetCoordinateDM(dm, cdmNew)); 1080 PetscCall(DMSetCoordinates(dm, coordsNew)); 1081 PetscCall(VecDestroy(&coordsNew)); 1082 PetscCall(DMDestroy(&cdmNew)); 1083 PetscFunctionReturn(PETSC_SUCCESS); 1084 } 1085 1086 /*@ 1087 DMLocatePoints - Locate the points in v in the mesh and return a `PetscSF` of the containing cells 1088 1089 Collective 1090 1091 Input Parameters: 1092 + dm - The `DM` 1093 - ltype - The type of point location, e.g. `DM_POINTLOCATION_NONE` or `DM_POINTLOCATION_NEAREST` 1094 1095 Input/Output Parameters: 1096 + v - The `Vec` of points, on output contains the nearest mesh points to the given points if `DM_POINTLOCATION_NEAREST` is used 1097 - cellSF - Points to either `NULL`, or a `PetscSF` with guesses for which cells contain each point; 1098 on output, the `PetscSF` containing the ranks and local indices of the containing points 1099 1100 Level: developer 1101 1102 Notes: 1103 To do a search of the local cells of the mesh, v should have `PETSC_COMM_SELF` as its communicator. 1104 To do a search of all the cells in the distributed mesh, `v` should have the same communicator as `dm`. 1105 1106 Points will only be located in owned cells, not overlap cells arising from `DMPlexDistribute()` or other overlapping distributions. 1107 1108 If *cellSF is `NULL` on input, a `PetscSF` will be created. 1109 If *cellSF is not `NULL` on input, it should point to an existing `PetscSF`, whose graph will be used as initial guesses. 1110 1111 An array that maps each point to its containing cell can be obtained with 1112 .vb 1113 const PetscSFNode *cells; 1114 PetscInt nFound; 1115 const PetscInt *found; 1116 1117 PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 1118 .ve 1119 1120 Where cells[i].rank is the rank of the process owning the cell containing point found[i] (or i if found == NULL), and cells[i].index is 1121 the index of the cell in its rank's local numbering. This rank is in the communicator for `v`, so if `v` is on `PETSC_COMM_SELF` then the rank will always be 0. 1122 1123 .seealso: `DM`, `DMSetCoordinates()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMPointLocationType` 1124 @*/ 1125 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 1126 { 1127 PetscFunctionBegin; 1128 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1129 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 1130 PetscValidPointer(cellSF, 4); 1131 if (*cellSF) { 1132 PetscMPIInt result; 1133 1134 PetscValidHeaderSpecific(*cellSF, PETSCSF_CLASSID, 4); 1135 PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)v), PetscObjectComm((PetscObject)*cellSF), &result)); 1136 PetscCheck(result == MPI_IDENT || result == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "cellSF must have a communicator congruent to v's"); 1137 } else { 1138 PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)v), cellSF)); 1139 } 1140 PetscCall(PetscLogEventBegin(DM_LocatePoints, dm, 0, 0, 0)); 1141 PetscUseTypeMethod(dm, locatepoints, v, ltype, *cellSF); 1142 PetscCall(PetscLogEventEnd(DM_LocatePoints, dm, 0, 0, 0)); 1143 PetscFunctionReturn(PETSC_SUCCESS); 1144 } 1145