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(0); 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(0); 58 } 59 60 /*@ 61 DMGetCoordinateDM - Gets the `DM` that prescribes coordinate layout and scatters between global and local coordinates 62 63 Collective on dm 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(0); 93 } 94 95 /*@ 96 DMSetCoordinateDM - Sets the `DM` that prescribes coordinate layout and scatters between global and local coordinates 97 98 Logically Collective on dm 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 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(0); 118 } 119 120 /*@ 121 DMGetCellCoordinateDM - Gets the `DM` that prescribes cellwise coordinate layout and scatters between global and local cellwise coordinates 122 123 Collective on dm 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(0); 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 on dm 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 discontinous 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(0); 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(0); 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(0); 236 } 237 238 /*@ 239 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 240 241 Collective on dm 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(0); 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(0); 313 } 314 315 /*@ 316 DMGetCellCoordinateSection - Retrieve the layout of cellwise coordinate values over the mesh. 317 318 Collective on dm 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(0); 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(0); 392 } 393 394 /*@ 395 DMGetCoordinates - Gets a global vector with the coordinates associated with the `DM`. 396 397 Collective on dm 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(0); 434 } 435 436 /*@ 437 DMSetCoordinates - Sets into the `DM` a global vector that holds the coordinates 438 439 Collective on dm 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(0); 466 } 467 468 /*@ 469 DMGetCellCoordinates - Gets a global vector with the cellwise coordinates associated with the `DM`. 470 471 Collective on dm 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(0); 505 } 506 507 /*@ 508 DMSetCellCoordinates - Sets into the `DM` a global vector that holds the cellwise coordinates 509 510 Collective on dm 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(0); 535 } 536 537 /*@ 538 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that `DMGetCoordinatesLocalNoncollective()` can be used as non-collective afterwards. 539 540 Collective on dm 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 556 PetscCall(DMGetCoordinateDM(dm, &cdm)); 557 PetscCall(DMCreateLocalVector(cdm, &dm->coordinates[0].xl)); 558 PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[0].xl, "coordinates")); 559 PetscCall(DMGlobalToLocalBegin(cdm, dm->coordinates[0].x, INSERT_VALUES, dm->coordinates[0].xl)); 560 PetscCall(DMGlobalToLocalEnd(cdm, dm->coordinates[0].x, INSERT_VALUES, dm->coordinates[0].xl)); 561 } 562 PetscFunctionReturn(0); 563 } 564 565 /*@ 566 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the `DM`. 567 568 Collective on dm the first time it is called 569 570 Input Parameter: 571 . dm - the `DM` 572 573 Output Parameter: 574 . c - coordinate vector 575 576 Level: intermediate 577 578 Notes: 579 This is a borrowed reference, so the user should NOT destroy this vector 580 581 Each process has the local and ghost coordinates 582 583 For `DMDA`, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 584 and (x_0,y_0,z_0,x_1,y_1,z_1...) 585 586 .seealso: `DM`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()`, `DMGetCoordinatesLocalNoncollective()` 587 @*/ 588 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 592 PetscValidPointer(c, 2); 593 PetscCall(DMGetCoordinatesLocalSetUp(dm)); 594 *c = dm->coordinates[0].xl; 595 PetscFunctionReturn(0); 596 } 597 598 /*@ 599 DMGetCoordinatesLocalNoncollective - Non-collective version of `DMGetCoordinatesLocal()`. Fails if global coordinates have been set and `DMGetCoordinatesLocalSetUp()` not called. 600 601 Not collective 602 603 Input Parameter: 604 . dm - the `DM` 605 606 Output Parameter: 607 . c - coordinate vector 608 609 Level: advanced 610 611 Note: 612 A previous call to `DMGetCoordinatesLocal()` or `DMGetCoordinatesLocalSetUp()` ensures that a call to this function will not error. 613 614 .seealso: `DM`, `DMGetCoordinatesLocalSetUp()`, `DMGetCoordinatesLocal()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()` 615 @*/ 616 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 617 { 618 PetscFunctionBegin; 619 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 620 PetscValidPointer(c, 2); 621 PetscCheck(dm->coordinates[0].xl || !dm->coordinates[0].x, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 622 *c = dm->coordinates[0].xl; 623 PetscFunctionReturn(0); 624 } 625 626 /*@ 627 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and the section describing its layout. 628 629 Not collective 630 631 Input Parameters: 632 + dm - the `DM` 633 - p - the `IS` of points whose coordinates will be returned 634 635 Output Parameters: 636 + pCoordSection - the `PetscSection` describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 637 - pCoord - the `Vec` with coordinates of points in p 638 639 Level: advanced 640 641 Notes: 642 `DMGetCoordinatesLocalSetUp()` must be called first. This function employs `DMGetCoordinatesLocalNoncollective()` so it is not collective. 643 644 This creates a new vector, so the user SHOULD destroy this vector 645 646 Each process has the local and ghost coordinates 647 648 For `DMDA`, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 649 and (x_0,y_0,z_0,x_1,y_1,z_1...) 650 651 .seealso: `DM`, `DMDA`, `DMSetCoordinatesLocal()`, `DMGetCoordinatesLocal()`, `DMGetCoordinatesLocalNoncollective()`, `DMGetCoordinatesLocalSetUp()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()` 652 @*/ 653 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 654 { 655 DM cdm; 656 PetscSection cs, newcs; 657 Vec coords; 658 const PetscScalar *arr; 659 PetscScalar *newarr = NULL; 660 PetscInt n; 661 662 PetscFunctionBegin; 663 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 664 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 665 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 666 if (pCoord) PetscValidPointer(pCoord, 4); 667 PetscCall(DMGetCoordinateDM(dm, &cdm)); 668 PetscCall(DMGetLocalSection(cdm, &cs)); 669 PetscCall(DMGetCoordinatesLocal(dm, &coords)); 670 PetscCheck(coords, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 671 PetscCheck(cdm && cs, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 672 PetscCall(VecGetArrayRead(coords, &arr)); 673 PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void **)&newarr) : NULL)); 674 PetscCall(VecRestoreArrayRead(coords, &arr)); 675 if (pCoord) { 676 PetscCall(PetscSectionGetStorageSize(newcs, &n)); 677 /* set array in two steps to mimic PETSC_OWN_POINTER */ 678 PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord)); 679 PetscCall(VecReplaceArray(*pCoord, newarr)); 680 } else { 681 PetscCall(PetscFree(newarr)); 682 } 683 if (pCoordSection) { 684 *pCoordSection = newcs; 685 } else PetscCall(PetscSectionDestroy(&newcs)); 686 PetscFunctionReturn(0); 687 } 688 689 /*@ 690 DMSetCoordinatesLocal - Sets into the `DM` a local vector, including ghost points, that holds the coordinates 691 692 Not collective 693 694 Input Parameters: 695 + dm - the `DM` 696 - c - coordinate vector 697 698 Level: intermediate 699 700 Notes: 701 The coordinates of ghost points can be set using `DMSetCoordinates()` 702 followed by `DMGetCoordinatesLocal()`. This is intended to enable the 703 setting of ghost coordinates outside of the domain. 704 705 The vector c should be destroyed by the caller. 706 707 .seealso: `DM`, `DMGetCoordinatesLocal()`, `DMSetCoordinates()`, `DMGetCoordinates()`, `DMGetCoordinateDM()` 708 @*/ 709 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 710 { 711 PetscFunctionBegin; 712 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 713 if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2); 714 PetscCall(PetscObjectReference((PetscObject)c)); 715 PetscCall(VecDestroy(&dm->coordinates[0].xl)); 716 dm->coordinates[0].xl = c; 717 PetscCall(VecDestroy(&dm->coordinates[0].x)); 718 PetscFunctionReturn(0); 719 } 720 721 /*@ 722 DMGetCellCoordinatesLocalSetUp - Prepares a local vector of cellwise coordinates, so that `DMGetCellCoordinatesLocalNoncollective()` can be used as non-collective afterwards. 723 724 Collective on dm 725 726 Input Parameter: 727 . dm - the `DM` 728 729 Level: advanced 730 731 .seealso: `DM`, `DMGetCellCoordinatesLocalNoncollective()` 732 @*/ 733 PetscErrorCode DMGetCellCoordinatesLocalSetUp(DM dm) 734 { 735 PetscFunctionBegin; 736 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 737 if (!dm->coordinates[1].xl && dm->coordinates[1].x) { 738 DM cdm = NULL; 739 740 PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 741 PetscCall(DMCreateLocalVector(cdm, &dm->coordinates[1].xl)); 742 PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[1].xl, "DG coordinates")); 743 PetscCall(DMGlobalToLocalBegin(cdm, dm->coordinates[1].x, INSERT_VALUES, dm->coordinates[1].xl)); 744 PetscCall(DMGlobalToLocalEnd(cdm, dm->coordinates[1].x, INSERT_VALUES, dm->coordinates[1].xl)); 745 } 746 PetscFunctionReturn(0); 747 } 748 749 /*@ 750 DMGetCellCoordinatesLocal - Gets a local vector with the cellwise coordinates associated with the `DM`. 751 752 Collective on dm 753 754 Input Parameter: 755 . dm - the `DM` 756 757 Output Parameter: 758 . c - coordinate vector 759 760 Level: intermediate 761 762 Notes: 763 This is a borrowed reference, so the user should NOT destroy this vector 764 765 Each process has the local and ghost coordinates 766 767 .seealso: `DM`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMSetCellCoordinates()`, `DMGetCellCoordinateDM()`, `DMGetCellCoordinatesLocalNoncollective()` 768 @*/ 769 PetscErrorCode DMGetCellCoordinatesLocal(DM dm, Vec *c) 770 { 771 PetscFunctionBegin; 772 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 773 PetscValidPointer(c, 2); 774 PetscCall(DMGetCellCoordinatesLocalSetUp(dm)); 775 *c = dm->coordinates[1].xl; 776 PetscFunctionReturn(0); 777 } 778 779 /*@ 780 DMGetCellCoordinatesLocalNoncollective - Non-collective version of `DMGetCellCoordinatesLocal()`. Fails if global cellwise coordinates have been set and `DMGetCellCoordinatesLocalSetUp()` not called. 781 782 Not collective 783 784 Input Parameter: 785 . dm - the `DM` 786 787 Output Parameter: 788 . c - cellwise coordinate vector 789 790 Level: advanced 791 792 .seealso: `DM`, `DMGetCellCoordinatesLocalSetUp()`, `DMGetCellCoordinatesLocal()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMSetCellCoordinates()`, `DMGetCellCoordinateDM()` 793 @*/ 794 PetscErrorCode DMGetCellCoordinatesLocalNoncollective(DM dm, Vec *c) 795 { 796 PetscFunctionBegin; 797 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 798 PetscValidPointer(c, 2); 799 PetscCheck(dm->coordinates[1].xl || !dm->coordinates[1].x, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCellCoordinatesLocalSetUp() has not been called"); 800 *c = dm->coordinates[1].xl; 801 PetscFunctionReturn(0); 802 } 803 804 /*@ 805 DMSetCellCoordinatesLocal - Sets into the `DM` a local vector including ghost points that holds the cellwise coordinates 806 807 Not collective 808 809 Input Parameters: 810 + dm - the `DM` 811 - c - cellwise coordinate vector 812 813 Level: intermediate 814 815 Notes: 816 The coordinates of ghost points can be set using `DMSetCoordinates()` 817 followed by `DMGetCoordinatesLocal()`. This is intended to enable the 818 setting of ghost coordinates outside of the domain. 819 820 The vector c should be destroyed by the caller. 821 822 .seealso: `DM`, `DMGetCellCoordinatesLocal()`, `DMSetCellCoordinates()`, `DMGetCellCoordinates()`, `DMGetCellCoordinateDM()` 823 @*/ 824 PetscErrorCode DMSetCellCoordinatesLocal(DM dm, Vec c) 825 { 826 PetscFunctionBegin; 827 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 828 if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2); 829 PetscCall(PetscObjectReference((PetscObject)c)); 830 PetscCall(VecDestroy(&dm->coordinates[1].xl)); 831 dm->coordinates[1].xl = c; 832 PetscCall(VecDestroy(&dm->coordinates[1].x)); 833 PetscFunctionReturn(0); 834 } 835 836 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 837 { 838 PetscFunctionBegin; 839 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 840 PetscValidPointer(field, 2); 841 if (!dm->coordinates[0].field) { 842 if (dm->ops->createcoordinatefield) PetscCall((*dm->ops->createcoordinatefield)(dm, &dm->coordinates[0].field)); 843 } 844 *field = dm->coordinates[0].field; 845 PetscFunctionReturn(0); 846 } 847 848 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 849 { 850 PetscFunctionBegin; 851 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 852 if (field) PetscValidHeaderSpecific(field, DMFIELD_CLASSID, 2); 853 PetscCall(PetscObjectReference((PetscObject)field)); 854 PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 855 dm->coordinates[0].field = field; 856 PetscFunctionReturn(0); 857 } 858 859 /*@ 860 DMGetLocalBoundingBox - Returns the bounding box for the piece of the `DM` on this process. 861 862 Not collective 863 864 Input Parameter: 865 . dm - the `DM` 866 867 Output Parameters: 868 + lmin - local minimum coordinates (length coord dim, optional) 869 - lmax - local maximim coordinates (length coord dim, optional) 870 871 Level: beginner 872 873 Note: 874 If the `DM` is a `DMDA` and has no coordinates, the index bounds are returned instead. 875 876 .seealso: `DM`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetBoundingBox()` 877 @*/ 878 PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[]) 879 { 880 Vec coords = NULL; 881 PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 882 PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 883 PetscInt cdim, i, j; 884 885 PetscFunctionBegin; 886 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 887 PetscCall(DMGetCoordinateDim(dm, &cdim)); 888 PetscCall(DMGetCoordinatesLocal(dm, &coords)); 889 if (coords) { 890 const PetscScalar *local_coords; 891 PetscInt N, Ni; 892 893 for (j = cdim; j < 3; ++j) { 894 min[j] = 0; 895 max[j] = 0; 896 } 897 PetscCall(VecGetArrayRead(coords, &local_coords)); 898 PetscCall(VecGetLocalSize(coords, &N)); 899 Ni = N / cdim; 900 for (i = 0; i < Ni; ++i) { 901 for (j = 0; j < cdim; ++j) { 902 min[j] = PetscMin(min[j], PetscRealPart(local_coords[i * cdim + j])); 903 max[j] = PetscMax(max[j], PetscRealPart(local_coords[i * cdim + j])); 904 } 905 } 906 PetscCall(VecRestoreArrayRead(coords, &local_coords)); 907 PetscCall(DMGetCellCoordinatesLocal(dm, &coords)); 908 if (coords) { 909 PetscCall(VecGetArrayRead(coords, &local_coords)); 910 PetscCall(VecGetLocalSize(coords, &N)); 911 Ni = N / cdim; 912 for (i = 0; i < Ni; ++i) { 913 for (j = 0; j < cdim; ++j) { 914 min[j] = PetscMin(min[j], PetscRealPart(local_coords[i * cdim + j])); 915 max[j] = PetscMax(max[j], PetscRealPart(local_coords[i * cdim + j])); 916 } 917 } 918 PetscCall(VecRestoreArrayRead(coords, &local_coords)); 919 } 920 } else { 921 PetscBool isda; 922 923 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMDA, &isda)); 924 if (isda) PetscCall(DMGetLocalBoundingIndices_DMDA(dm, min, max)); 925 } 926 if (lmin) PetscCall(PetscArraycpy(lmin, min, cdim)); 927 if (lmax) PetscCall(PetscArraycpy(lmax, max, cdim)); 928 PetscFunctionReturn(0); 929 } 930 931 /*@ 932 DMGetBoundingBox - Returns the global bounding box for the `DM`. 933 934 Collective 935 936 Input Parameter: 937 . dm - the `DM` 938 939 Output Parameters: 940 + gmin - global minimum coordinates (length coord dim, optional) 941 - gmax - global maximim coordinates (length coord dim, optional) 942 943 Level: beginner 944 945 .seealso: `DM`, `DMGetLocalBoundingBox()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()` 946 @*/ 947 PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[]) 948 { 949 PetscReal lmin[3], lmax[3]; 950 PetscInt cdim; 951 PetscMPIInt count; 952 953 PetscFunctionBegin; 954 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 955 PetscCall(DMGetCoordinateDim(dm, &cdim)); 956 PetscCall(PetscMPIIntCast(cdim, &count)); 957 PetscCall(DMGetLocalBoundingBox(dm, lmin, lmax)); 958 if (gmin) PetscCall(MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)dm))); 959 if (gmax) PetscCall(MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 960 PetscFunctionReturn(0); 961 } 962 963 /*@ 964 DMProjectCoordinates - Project coordinates to a different space 965 966 Input Parameters: 967 + dm - The `DM` object 968 - disc - The new coordinate discretization or NULL to ensure a coordinate discretization exists 969 970 Level: intermediate 971 972 Notes: 973 A `PetscFE` defines an approximation space using a `PetscSpace`, which represents the basis functions, and a `PetscDualSpace`, which defines the interpolation operation 974 in the space. 975 976 This function takes the current mesh coordinates, which are discretized using some `PetscFE` space, and projects this function into a new `PetscFE` space. 977 The coordinate projection is done on the continuous coordinates, and if possible, the discontinuous coordinates are also updated. 978 979 Developer Note: 980 With more effort, we could directly project the discontinuous coordinates also. 981 982 .seealso: `DM`, `PetscFE`, `DMGetCoordinateField()` 983 @*/ 984 PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc) 985 { 986 PetscFE discOld; 987 PetscClassId classid; 988 DM cdmOld, cdmNew; 989 Vec coordsOld, coordsNew; 990 Mat matInterp; 991 PetscBool same_space = PETSC_TRUE; 992 993 PetscFunctionBegin; 994 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 995 if (disc) PetscValidHeaderSpecific(disc, PETSCFE_CLASSID, 2); 996 997 PetscCall(DMGetCoordinateDM(dm, &cdmOld)); 998 /* Check current discretization is compatible */ 999 PetscCall(DMGetField(cdmOld, 0, NULL, (PetscObject *)&discOld)); 1000 PetscCall(PetscObjectGetClassId((PetscObject)discOld, &classid)); 1001 if (classid != PETSCFE_CLASSID) { 1002 if (classid == PETSC_CONTAINER_CLASSID) { 1003 PetscFE feLinear; 1004 DMPolytopeType ct; 1005 PetscInt dim, dE, cStart, cEnd; 1006 PetscBool simplex; 1007 1008 /* Assume linear vertex coordinates */ 1009 PetscCall(DMGetDimension(dm, &dim)); 1010 PetscCall(DMGetCoordinateDim(dm, &dE)); 1011 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1012 if (cEnd > cStart) { 1013 PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 1014 switch (ct) { 1015 case DM_POLYTOPE_TRI_PRISM: 1016 case DM_POLYTOPE_TRI_PRISM_TENSOR: 1017 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot autoamtically create coordinate space for prisms"); 1018 default: 1019 break; 1020 } 1021 } 1022 PetscCall(DMPlexIsSimplex(dm, &simplex)); 1023 PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, 1, -1, &feLinear)); 1024 PetscCall(DMSetField(cdmOld, 0, NULL, (PetscObject)feLinear)); 1025 PetscCall(PetscFEDestroy(&feLinear)); 1026 PetscCall(DMCreateDS(cdmOld)); 1027 PetscCall(DMGetField(cdmOld, 0, NULL, (PetscObject *)&discOld)); 1028 } else { 1029 const char *discname; 1030 1031 PetscCall(PetscObjectGetType((PetscObject)discOld, &discname)); 1032 SETERRQ(PetscObjectComm((PetscObject)discOld), PETSC_ERR_SUP, "Discretization type %s not supported", discname); 1033 } 1034 } 1035 if (!disc) PetscFunctionReturn(0); 1036 { // Check if the new space is the same as the old modulo quadrature 1037 PetscDualSpace dsOld, ds; 1038 PetscCall(PetscFEGetDualSpace(discOld, &dsOld)); 1039 PetscCall(PetscFEGetDualSpace(disc, &ds)); 1040 PetscCall(PetscDualSpaceEqual(dsOld, ds, &same_space)); 1041 } 1042 /* Make a fresh clone of the coordinate DM */ 1043 PetscCall(DMClone(cdmOld, &cdmNew)); 1044 PetscCall(DMSetField(cdmNew, 0, NULL, (PetscObject)disc)); 1045 PetscCall(DMCreateDS(cdmNew)); 1046 PetscCall(DMGetCoordinates(dm, &coordsOld)); 1047 if (same_space) { 1048 PetscCall(PetscObjectReference((PetscObject)coordsOld)); 1049 coordsNew = coordsOld; 1050 } else { // Project the coordinate vector from old to new space 1051 PetscCall(DMCreateGlobalVector(cdmNew, &coordsNew)); 1052 PetscCall(DMCreateInterpolation(cdmOld, cdmNew, &matInterp, NULL)); 1053 PetscCall(MatInterpolate(matInterp, coordsOld, coordsNew)); 1054 PetscCall(MatDestroy(&matInterp)); 1055 } 1056 /* Set new coordinate structures */ 1057 PetscCall(DMSetCoordinateField(dm, NULL)); 1058 PetscCall(DMSetCoordinateDM(dm, cdmNew)); 1059 PetscCall(DMSetCoordinates(dm, coordsNew)); 1060 PetscCall(VecDestroy(&coordsNew)); 1061 PetscCall(DMDestroy(&cdmNew)); 1062 PetscFunctionReturn(0); 1063 } 1064 1065 /*@ 1066 DMLocatePoints - Locate the points in v in the mesh and return a `PetscSF` of the containing cells 1067 1068 Collective on v (see explanation below) 1069 1070 Input Parameters: 1071 + dm - The `DM` 1072 - ltype - The type of point location, e.g. `DM_POINTLOCATION_NONE` or `DM_POINTLOCATION_NEAREST` 1073 1074 Input/Output Parameters: 1075 + v - The `Vec` of points, on output contains the nearest mesh points to the given points if `DM_POINTLOCATION_NEAREST` is used 1076 - cellSF - Points to either NULL, or a `PetscSF` with guesses for which cells contain each point; 1077 on output, the `PetscSF` containing the ranks and local indices of the containing points 1078 1079 Level: developer 1080 1081 Notes: 1082 To do a search of the local cells of the mesh, v should have `PETSC_COMM_SELF` as its communicator. 1083 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 1084 1085 Points will only be located in owned cells, not overlap cells arising from `DMPlexDistribute()` or other overlapping distributions. 1086 1087 If *cellSF is NULL on input, a `PetscSF` will be created. 1088 If *cellSF is not NULL on input, it should point to an existing `PetscSF`, whose graph will be used as initial guesses. 1089 1090 An array that maps each point to its containing cell can be obtained with 1091 .vb 1092 const PetscSFNode *cells; 1093 PetscInt nFound; 1094 const PetscInt *found; 1095 1096 PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 1097 .ve 1098 1099 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 1100 the index of the cell in its rank's local numbering. 1101 1102 .seealso: `DM`, `DMSetCoordinates()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMPointLocationType` 1103 @*/ 1104 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 1105 { 1106 PetscFunctionBegin; 1107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1108 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 1109 PetscValidPointer(cellSF, 4); 1110 if (*cellSF) { 1111 PetscMPIInt result; 1112 1113 PetscValidHeaderSpecific(*cellSF, PETSCSF_CLASSID, 4); 1114 PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)v), PetscObjectComm((PetscObject)*cellSF), &result)); 1115 PetscCheck(result == MPI_IDENT || result == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "cellSF must have a communicator congruent to v's"); 1116 } else { 1117 PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)v), cellSF)); 1118 } 1119 PetscCall(PetscLogEventBegin(DM_LocatePoints, dm, 0, 0, 0)); 1120 PetscUseTypeMethod(dm, locatepoints, v, ltype, *cellSF); 1121 PetscCall(PetscLogEventEnd(DM_LocatePoints, dm, 0, 0, 0)); 1122 PetscFunctionReturn(0); 1123 } 1124