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