1 #include <petscvec.h> 2 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 3 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 4 #include <petsc/private/petscdsimpl.h> /*I "petscds.h" I*/ 5 #include <petscdmplex.h> 6 #include <petscdmfield.h> 7 #include <petscsf.h> 8 #include <petscds.h> 9 10 #ifdef PETSC_HAVE_LIBCEED 11 #include <petscfeceed.h> 12 #endif 13 14 #if defined(PETSC_HAVE_VALGRIND) 15 # include <valgrind/memcheck.h> 16 #endif 17 18 PetscClassId DM_CLASSID; 19 PetscClassId DMLABEL_CLASSID; 20 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction, DM_CreateInjection, DM_CreateMatrix, DM_Load, DM_AdaptInterpolator; 21 22 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DMBoundaryType","DM_BOUNDARY_", NULL}; 23 const char *const DMBoundaryConditionTypes[] = {"INVALID","ESSENTIAL","NATURAL","INVALID","INVALID","ESSENTIAL_FIELD","NATURAL_FIELD","INVALID","INVALID","ESSENTIAL_BD_FIELD","NATURAL_RIEMANN","DMBoundaryConditionType","DM_BC_", NULL}; 24 const char *const DMPolytopeTypes[] = {"vertex", "segment", "tensor_segment", "triangle", "quadrilateral", "tensor_quad", "tetrahedron", "hexahedron", "triangular_prism", "tensor_triangular_prism", "tensor_quadrilateral_prism", "pyramid", "FV_ghost_cell", "interior_ghost_cell", "unknown", "invalid", "DMPolytopeType", "DM_POLYTOPE_", NULL}; 25 const char *const DMCopyLabelsModes[] = {"replace","keep","fail","DMCopyLabelsMode","DM_COPY_LABELS_", NULL}; 26 27 /*@ 28 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 29 30 If you never call DMSetType() it will generate an 31 error when you try to use the vector. 32 33 Collective 34 35 Input Parameter: 36 . comm - The communicator for the DM object 37 38 Output Parameter: 39 . dm - The DM object 40 41 Level: beginner 42 43 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK 44 @*/ 45 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 46 { 47 DM v; 48 PetscDS ds; 49 PetscErrorCode ierr; 50 51 PetscFunctionBegin; 52 PetscValidPointer(dm,2); 53 *dm = NULL; 54 ierr = DMInitializePackage();CHKERRQ(ierr); 55 56 ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 57 58 v->setupcalled = PETSC_FALSE; 59 v->setfromoptionscalled = PETSC_FALSE; 60 v->ltogmap = NULL; 61 v->bind_below = 0; 62 v->bs = 1; 63 v->coloringtype = IS_COLORING_GLOBAL; 64 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 65 ierr = PetscSFCreate(comm, &v->sectionSF);CHKERRQ(ierr); 66 v->labels = NULL; 67 v->adjacency[0] = PETSC_FALSE; 68 v->adjacency[1] = PETSC_TRUE; 69 v->depthLabel = NULL; 70 v->celltypeLabel = NULL; 71 v->localSection = NULL; 72 v->globalSection = NULL; 73 v->defaultConstraint.section = NULL; 74 v->defaultConstraint.mat = NULL; 75 v->defaultConstraint.bias = NULL; 76 v->L = NULL; 77 v->maxCell = NULL; 78 v->bdtype = NULL; 79 v->dimEmbed = PETSC_DEFAULT; 80 v->dim = PETSC_DETERMINE; 81 { 82 PetscInt i; 83 for (i = 0; i < 10; ++i) { 84 v->nullspaceConstructors[i] = NULL; 85 v->nearnullspaceConstructors[i] = NULL; 86 } 87 } 88 ierr = PetscDSCreate(PETSC_COMM_SELF, &ds);CHKERRQ(ierr); 89 ierr = DMSetRegionDS(v, NULL, NULL, ds);CHKERRQ(ierr); 90 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 91 ierr = PetscHMapAuxCreate(&v->auxData);CHKERRQ(ierr); 92 v->dmBC = NULL; 93 v->coarseMesh = NULL; 94 v->outputSequenceNum = -1; 95 v->outputSequenceVal = 0.0; 96 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr); 97 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr); 98 99 *dm = v; 100 PetscFunctionReturn(0); 101 } 102 103 /*@ 104 DMClone - Creates a DM object with the same topology as the original. 105 106 Collective 107 108 Input Parameter: 109 . dm - The original DM object 110 111 Output Parameter: 112 . newdm - The new DM object 113 114 Level: beginner 115 116 Notes: 117 For some DM implementations this is a shallow clone, the result of which may share (referent counted) information with its parent. For example, 118 DMClone() applied to a DMPLEX object will result in a new DMPLEX that shares the topology with the original DMPLEX. It does not 119 share the PetscSection of the original DM. 120 121 The clone is considered set up iff the original is. 122 123 .seealso: DMDestroy(), DMCreate(), DMSetType(), DMSetLocalSection(), DMSetGlobalSection() 124 125 @*/ 126 PetscErrorCode DMClone(DM dm, DM *newdm) 127 { 128 PetscSF sf; 129 Vec coords; 130 void *ctx; 131 PetscInt dim, cdim; 132 PetscErrorCode ierr; 133 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 136 PetscValidPointer(newdm,2); 137 ierr = DMCreate(PetscObjectComm((PetscObject) dm), newdm);CHKERRQ(ierr); 138 ierr = DMCopyLabels(dm, *newdm, PETSC_COPY_VALUES, PETSC_TRUE, DM_COPY_LABELS_FAIL);CHKERRQ(ierr); 139 (*newdm)->leveldown = dm->leveldown; 140 (*newdm)->levelup = dm->levelup; 141 (*newdm)->prealloc_only = dm->prealloc_only; 142 ierr = PetscFree((*newdm)->vectype);CHKERRQ(ierr); 143 ierr = PetscStrallocpy(dm->vectype,(char**)&(*newdm)->vectype);CHKERRQ(ierr); 144 ierr = PetscFree((*newdm)->mattype);CHKERRQ(ierr); 145 ierr = PetscStrallocpy(dm->mattype,(char**)&(*newdm)->mattype);CHKERRQ(ierr); 146 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 147 ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr); 148 if (dm->ops->clone) { 149 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr); 150 } 151 (*newdm)->setupcalled = dm->setupcalled; 152 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 153 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr); 154 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); 155 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); 156 if (dm->coordinateDM) { 157 DM ncdm; 158 PetscSection cs; 159 PetscInt pEnd = -1, pEndMax = -1; 160 161 ierr = DMGetLocalSection(dm->coordinateDM, &cs);CHKERRQ(ierr); 162 if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);} 163 ierr = MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 164 if (pEndMax >= 0) { 165 ierr = DMClone(dm->coordinateDM, &ncdm);CHKERRQ(ierr); 166 ierr = DMCopyDisc(dm->coordinateDM, ncdm);CHKERRQ(ierr); 167 ierr = DMSetLocalSection(ncdm, cs);CHKERRQ(ierr); 168 ierr = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr); 169 ierr = DMDestroy(&ncdm);CHKERRQ(ierr); 170 } 171 } 172 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 173 ierr = DMSetCoordinateDim(*newdm, cdim);CHKERRQ(ierr); 174 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); 175 if (coords) { 176 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); 177 } else { 178 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 179 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} 180 } 181 { 182 PetscBool isper; 183 const PetscReal *maxCell, *L; 184 const DMBoundaryType *bd; 185 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 186 ierr = DMSetPeriodicity(*newdm, isper, maxCell, L, bd);CHKERRQ(ierr); 187 } 188 { 189 PetscBool useCone, useClosure; 190 191 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, &useCone, &useClosure);CHKERRQ(ierr); 192 ierr = DMSetAdjacency(*newdm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 193 } 194 PetscFunctionReturn(0); 195 } 196 197 /*@C 198 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 199 200 Logically Collective on da 201 202 Input Parameter: 203 + da - initial distributed array 204 . ctype - the vector type, currently either VECSTANDARD, VECCUDA, or VECVIENNACL 205 206 Options Database: 207 . -dm_vec_type ctype 208 209 Level: intermediate 210 211 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType(), DMSetMatType(), DMGetMatType() 212 @*/ 213 PetscErrorCode DMSetVecType(DM da,VecType ctype) 214 { 215 PetscErrorCode ierr; 216 217 PetscFunctionBegin; 218 PetscValidHeaderSpecific(da,DM_CLASSID,1); 219 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 220 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 221 PetscFunctionReturn(0); 222 } 223 224 /*@C 225 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 226 227 Logically Collective on da 228 229 Input Parameter: 230 . da - initial distributed array 231 232 Output Parameter: 233 . ctype - the vector type 234 235 Level: intermediate 236 237 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMSetMatType(), DMGetMatType(), DMSetVecType() 238 @*/ 239 PetscErrorCode DMGetVecType(DM da,VecType *ctype) 240 { 241 PetscFunctionBegin; 242 PetscValidHeaderSpecific(da,DM_CLASSID,1); 243 *ctype = da->vectype; 244 PetscFunctionReturn(0); 245 } 246 247 /*@ 248 VecGetDM - Gets the DM defining the data layout of the vector 249 250 Not collective 251 252 Input Parameter: 253 . v - The Vec 254 255 Output Parameter: 256 . dm - The DM 257 258 Level: intermediate 259 260 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 261 @*/ 262 PetscErrorCode VecGetDM(Vec v, DM *dm) 263 { 264 PetscErrorCode ierr; 265 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 268 PetscValidPointer(dm,2); 269 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 270 PetscFunctionReturn(0); 271 } 272 273 /*@ 274 VecSetDM - Sets the DM defining the data layout of the vector. 275 276 Not collective 277 278 Input Parameters: 279 + v - The Vec 280 - dm - The DM 281 282 Note: This is NOT the same as DMCreateGlobalVector() since it does not change the view methods or perform other customization, but merely sets the DM member. 283 284 Level: intermediate 285 286 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 287 @*/ 288 PetscErrorCode VecSetDM(Vec v, DM dm) 289 { 290 PetscErrorCode ierr; 291 292 PetscFunctionBegin; 293 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 294 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 295 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 296 PetscFunctionReturn(0); 297 } 298 299 /*@C 300 DMSetISColoringType - Sets the type of coloring, global or local, that is created by the DM 301 302 Logically Collective on dm 303 304 Input Parameters: 305 + dm - the DM context 306 - ctype - the matrix type 307 308 Options Database: 309 . -dm_is_coloring_type - global or local 310 311 Level: intermediate 312 313 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), 314 DMGetISColoringType() 315 @*/ 316 PetscErrorCode DMSetISColoringType(DM dm,ISColoringType ctype) 317 { 318 PetscFunctionBegin; 319 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 320 dm->coloringtype = ctype; 321 PetscFunctionReturn(0); 322 } 323 324 /*@C 325 DMGetISColoringType - Gets the type of coloring, global or local, that is created by the DM 326 327 Logically Collective on dm 328 329 Input Parameter: 330 . dm - the DM context 331 332 Output Parameter: 333 . ctype - the matrix type 334 335 Options Database: 336 . -dm_is_coloring_type - global or local 337 338 Level: intermediate 339 340 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), 341 DMGetISColoringType() 342 @*/ 343 PetscErrorCode DMGetISColoringType(DM dm,ISColoringType *ctype) 344 { 345 PetscFunctionBegin; 346 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 347 *ctype = dm->coloringtype; 348 PetscFunctionReturn(0); 349 } 350 351 /*@C 352 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 353 354 Logically Collective on dm 355 356 Input Parameters: 357 + dm - the DM context 358 - ctype - the matrix type 359 360 Options Database: 361 . -dm_mat_type ctype 362 363 Level: intermediate 364 365 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), DMSetMatType(), DMGetMatType() 366 @*/ 367 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 368 { 369 PetscErrorCode ierr; 370 371 PetscFunctionBegin; 372 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 373 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 374 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 375 PetscFunctionReturn(0); 376 } 377 378 /*@C 379 DMGetMatType - Gets the type of matrix created with DMCreateMatrix() 380 381 Logically Collective on dm 382 383 Input Parameter: 384 . dm - the DM context 385 386 Output Parameter: 387 . ctype - the matrix type 388 389 Options Database: 390 . -dm_mat_type ctype 391 392 Level: intermediate 393 394 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType(), DMSetMatType(), DMGetMatType() 395 @*/ 396 PetscErrorCode DMGetMatType(DM dm,MatType *ctype) 397 { 398 PetscFunctionBegin; 399 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 400 *ctype = dm->mattype; 401 PetscFunctionReturn(0); 402 } 403 404 /*@ 405 MatGetDM - Gets the DM defining the data layout of the matrix 406 407 Not collective 408 409 Input Parameter: 410 . A - The Mat 411 412 Output Parameter: 413 . dm - The DM 414 415 Level: intermediate 416 417 Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with 418 the Mat through a PetscObjectCompose() operation 419 420 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 421 @*/ 422 PetscErrorCode MatGetDM(Mat A, DM *dm) 423 { 424 PetscErrorCode ierr; 425 426 PetscFunctionBegin; 427 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 428 PetscValidPointer(dm,2); 429 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 430 PetscFunctionReturn(0); 431 } 432 433 /*@ 434 MatSetDM - Sets the DM defining the data layout of the matrix 435 436 Not collective 437 438 Input Parameters: 439 + A - The Mat 440 - dm - The DM 441 442 Level: intermediate 443 444 Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with 445 the Mat through a PetscObjectCompose() operation 446 447 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 448 @*/ 449 PetscErrorCode MatSetDM(Mat A, DM dm) 450 { 451 PetscErrorCode ierr; 452 453 PetscFunctionBegin; 454 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 455 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 456 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 457 PetscFunctionReturn(0); 458 } 459 460 /*@C 461 DMSetOptionsPrefix - Sets the prefix used for searching for all 462 DM options in the database. 463 464 Logically Collective on dm 465 466 Input Parameters: 467 + da - the DM context 468 - prefix - the prefix to prepend to all option names 469 470 Notes: 471 A hyphen (-) must NOT be given at the beginning of the prefix name. 472 The first character of all runtime options is AUTOMATICALLY the hyphen. 473 474 Level: advanced 475 476 .seealso: DMSetFromOptions() 477 @*/ 478 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 479 { 480 PetscErrorCode ierr; 481 482 PetscFunctionBegin; 483 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 484 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 485 if (dm->sf) { 486 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr); 487 } 488 if (dm->sectionSF) { 489 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sectionSF,prefix);CHKERRQ(ierr); 490 } 491 PetscFunctionReturn(0); 492 } 493 494 /*@C 495 DMAppendOptionsPrefix - Appends to the prefix used for searching for all 496 DM options in the database. 497 498 Logically Collective on dm 499 500 Input Parameters: 501 + dm - the DM context 502 - prefix - the prefix string to prepend to all DM option requests 503 504 Notes: 505 A hyphen (-) must NOT be given at the beginning of the prefix name. 506 The first character of all runtime options is AUTOMATICALLY the hyphen. 507 508 Level: advanced 509 510 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix() 511 @*/ 512 PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[]) 513 { 514 PetscErrorCode ierr; 515 516 PetscFunctionBegin; 517 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 518 ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 519 PetscFunctionReturn(0); 520 } 521 522 /*@C 523 DMGetOptionsPrefix - Gets the prefix used for searching for all 524 DM options in the database. 525 526 Not Collective 527 528 Input Parameters: 529 . dm - the DM context 530 531 Output Parameters: 532 . prefix - pointer to the prefix string used is returned 533 534 Notes: 535 On the fortran side, the user should pass in a string 'prefix' of 536 sufficient length to hold the prefix. 537 538 Level: advanced 539 540 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix() 541 @*/ 542 PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[]) 543 { 544 PetscErrorCode ierr; 545 546 PetscFunctionBegin; 547 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 548 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 549 PetscFunctionReturn(0); 550 } 551 552 static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct) 553 { 554 PetscInt refct = ((PetscObject) dm)->refct; 555 PetscErrorCode ierr; 556 557 PetscFunctionBegin; 558 *ncrefct = 0; 559 if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) { 560 refct--; 561 if (recurseCoarse) { 562 PetscInt coarseCount; 563 564 ierr = DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);CHKERRQ(ierr); 565 refct += coarseCount; 566 } 567 } 568 if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) { 569 refct--; 570 if (recurseFine) { 571 PetscInt fineCount; 572 573 ierr = DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);CHKERRQ(ierr); 574 refct += fineCount; 575 } 576 } 577 *ncrefct = refct; 578 PetscFunctionReturn(0); 579 } 580 581 PetscErrorCode DMDestroyLabelLinkList_Internal(DM dm) 582 { 583 DMLabelLink next = dm->labels; 584 PetscErrorCode ierr; 585 586 PetscFunctionBegin; 587 /* destroy the labels */ 588 while (next) { 589 DMLabelLink tmp = next->next; 590 591 if (next->label == dm->depthLabel) dm->depthLabel = NULL; 592 if (next->label == dm->celltypeLabel) dm->celltypeLabel = NULL; 593 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 594 ierr = PetscFree(next);CHKERRQ(ierr); 595 next = tmp; 596 } 597 dm->labels = NULL; 598 PetscFunctionReturn(0); 599 } 600 601 /*@C 602 DMDestroy - Destroys a vector packer or DM. 603 604 Collective on dm 605 606 Input Parameter: 607 . dm - the DM object to destroy 608 609 Level: developer 610 611 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 612 613 @*/ 614 PetscErrorCode DMDestroy(DM *dm) 615 { 616 PetscInt cnt; 617 DMNamedVecLink nlink,nnext; 618 PetscErrorCode ierr; 619 620 PetscFunctionBegin; 621 if (!*dm) PetscFunctionReturn(0); 622 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 623 624 /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */ 625 ierr = DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);CHKERRQ(ierr); 626 --((PetscObject)(*dm))->refct; 627 if (--cnt > 0) {*dm = NULL; PetscFunctionReturn(0);} 628 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 629 ((PetscObject)(*dm))->refct = 0; 630 631 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 632 ierr = DMClearLocalVectors(*dm);CHKERRQ(ierr); 633 634 nnext=(*dm)->namedglobal; 635 (*dm)->namedglobal = NULL; 636 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */ 637 nnext = nlink->next; 638 PetscCheckFalse(nlink->status != DMVEC_STATUS_IN,((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 639 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 640 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 641 ierr = PetscFree(nlink);CHKERRQ(ierr); 642 } 643 nnext=(*dm)->namedlocal; 644 (*dm)->namedlocal = NULL; 645 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */ 646 nnext = nlink->next; 647 PetscCheckFalse(nlink->status != DMVEC_STATUS_IN,((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 648 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 649 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 650 ierr = PetscFree(nlink);CHKERRQ(ierr); 651 } 652 653 /* Destroy the list of hooks */ 654 { 655 DMCoarsenHookLink link,next; 656 for (link=(*dm)->coarsenhook; link; link=next) { 657 next = link->next; 658 ierr = PetscFree(link);CHKERRQ(ierr); 659 } 660 (*dm)->coarsenhook = NULL; 661 } 662 { 663 DMRefineHookLink link,next; 664 for (link=(*dm)->refinehook; link; link=next) { 665 next = link->next; 666 ierr = PetscFree(link);CHKERRQ(ierr); 667 } 668 (*dm)->refinehook = NULL; 669 } 670 { 671 DMSubDomainHookLink link,next; 672 for (link=(*dm)->subdomainhook; link; link=next) { 673 next = link->next; 674 ierr = PetscFree(link);CHKERRQ(ierr); 675 } 676 (*dm)->subdomainhook = NULL; 677 } 678 { 679 DMGlobalToLocalHookLink link,next; 680 for (link=(*dm)->gtolhook; link; link=next) { 681 next = link->next; 682 ierr = PetscFree(link);CHKERRQ(ierr); 683 } 684 (*dm)->gtolhook = NULL; 685 } 686 { 687 DMLocalToGlobalHookLink link,next; 688 for (link=(*dm)->ltoghook; link; link=next) { 689 next = link->next; 690 ierr = PetscFree(link);CHKERRQ(ierr); 691 } 692 (*dm)->ltoghook = NULL; 693 } 694 /* Destroy the work arrays */ 695 { 696 DMWorkLink link,next; 697 PetscCheckFalse((*dm)->workout,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 698 for (link=(*dm)->workin; link; link=next) { 699 next = link->next; 700 ierr = PetscFree(link->mem);CHKERRQ(ierr); 701 ierr = PetscFree(link);CHKERRQ(ierr); 702 } 703 (*dm)->workin = NULL; 704 } 705 /* destroy the labels */ 706 ierr = DMDestroyLabelLinkList_Internal(*dm);CHKERRQ(ierr); 707 /* destroy the fields */ 708 ierr = DMClearFields(*dm);CHKERRQ(ierr); 709 /* destroy the boundaries */ 710 { 711 DMBoundary next = (*dm)->boundary; 712 while (next) { 713 DMBoundary b = next; 714 715 next = b->next; 716 ierr = PetscFree(b);CHKERRQ(ierr); 717 } 718 } 719 720 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 721 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 722 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 723 724 if ((*dm)->ctx && (*dm)->ctxdestroy) { 725 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 726 } 727 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 728 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 729 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 730 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 731 732 ierr = PetscSectionDestroy(&(*dm)->localSection);CHKERRQ(ierr); 733 ierr = PetscSectionDestroy(&(*dm)->globalSection);CHKERRQ(ierr); 734 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 735 ierr = PetscSectionDestroy(&(*dm)->defaultConstraint.section);CHKERRQ(ierr); 736 ierr = MatDestroy(&(*dm)->defaultConstraint.mat);CHKERRQ(ierr); 737 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 738 ierr = PetscSFDestroy(&(*dm)->sectionSF);CHKERRQ(ierr); 739 if ((*dm)->useNatural) { 740 if ((*dm)->sfNatural) { 741 ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr); 742 } 743 ierr = PetscObjectDereference((PetscObject) (*dm)->sfMigration);CHKERRQ(ierr); 744 } 745 { 746 Vec *auxData; 747 PetscInt n, i, off = 0; 748 749 ierr = PetscHMapAuxGetSize((*dm)->auxData, &n);CHKERRQ(ierr); 750 ierr = PetscMalloc1(n, &auxData);CHKERRQ(ierr); 751 ierr = PetscHMapAuxGetVals((*dm)->auxData, &off, auxData);CHKERRQ(ierr); 752 for (i = 0; i < n; ++i) {ierr = VecDestroy(&auxData[i]);CHKERRQ(ierr);} 753 ierr = PetscFree(auxData);CHKERRQ(ierr); 754 ierr = PetscHMapAuxDestroy(&(*dm)->auxData);CHKERRQ(ierr); 755 } 756 if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) { 757 ierr = DMSetFineDM((*dm)->coarseMesh,NULL);CHKERRQ(ierr); 758 } 759 760 ierr = DMDestroy(&(*dm)->coarseMesh);CHKERRQ(ierr); 761 if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) { 762 ierr = DMSetCoarseDM((*dm)->fineMesh,NULL);CHKERRQ(ierr); 763 } 764 ierr = DMDestroy(&(*dm)->fineMesh);CHKERRQ(ierr); 765 ierr = DMFieldDestroy(&(*dm)->coordinateField);CHKERRQ(ierr); 766 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 767 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 768 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 769 ierr = PetscFree((*dm)->L);CHKERRQ(ierr); 770 ierr = PetscFree((*dm)->maxCell);CHKERRQ(ierr); 771 ierr = PetscFree((*dm)->bdtype);CHKERRQ(ierr); 772 if ((*dm)->transformDestroy) {ierr = (*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx);CHKERRQ(ierr);} 773 ierr = DMDestroy(&(*dm)->transformDM);CHKERRQ(ierr); 774 ierr = VecDestroy(&(*dm)->transform);CHKERRQ(ierr); 775 776 ierr = DMClearDS(*dm);CHKERRQ(ierr); 777 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr); 778 /* if memory was published with SAWs then destroy it */ 779 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr); 780 781 if ((*dm)->ops->destroy) { 782 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 783 } 784 ierr = DMMonitorCancel(*dm);CHKERRQ(ierr); 785 #ifdef PETSC_HAVE_LIBCEED 786 ierr = CeedElemRestrictionDestroy(&(*dm)->ceedERestrict);CHKERRQ_CEED(ierr); 787 ierr = CeedDestroy(&(*dm)->ceed);CHKERRQ_CEED(ierr); 788 #endif 789 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 790 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 791 PetscFunctionReturn(0); 792 } 793 794 /*@ 795 DMSetUp - sets up the data structures inside a DM object 796 797 Collective on dm 798 799 Input Parameter: 800 . dm - the DM object to setup 801 802 Level: developer 803 804 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 805 806 @*/ 807 PetscErrorCode DMSetUp(DM dm) 808 { 809 PetscErrorCode ierr; 810 811 PetscFunctionBegin; 812 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 813 if (dm->setupcalled) PetscFunctionReturn(0); 814 if (dm->ops->setup) { 815 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 816 } 817 dm->setupcalled = PETSC_TRUE; 818 PetscFunctionReturn(0); 819 } 820 821 /*@ 822 DMSetFromOptions - sets parameters in a DM from the options database 823 824 Collective on dm 825 826 Input Parameter: 827 . dm - the DM object to set options for 828 829 Options Database: 830 + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 831 . -dm_vec_type <type> - type of vector to create inside DM 832 . -dm_mat_type <type> - type of matrix to create inside DM 833 . -dm_is_coloring_type - <global or local> 834 - -dm_bind_below <n> - bind (force execution on CPU) for Vec and Mat objects with local size (number of vector entries or matrix rows) below n; currently only supported for DMDA 835 836 DMPLEX Specific creation options 837 + -dm_plex_filename <str> - File containing a mesh 838 . -dm_plex_boundary_filename <str> - File containing a mesh boundary 839 . -dm_plex_name <str> - Name of the mesh in the file 840 . -dm_plex_shape <shape> - The domain shape, such as DM_SHAPE_BOX, DM_SHAPE_SPHERE, etc. 841 . -dm_plex_cell <ct> - Cell shape 842 . -dm_plex_reference_cell_domain <bool> - Use a reference cell domain 843 . -dm_plex_dim <dim> - Set the topological dimension 844 . -dm_plex_simplex <bool> - PETSC_TRUE for simplex elements, PETSC_FALSE for tensor elements 845 . -dm_plex_interpolate <bool> - PETSC_TRUE turns on topological interpolation (creating edges and faces) 846 . -dm_plex_scale <sc> - Scale factor for mesh coordinates 847 . -dm_plex_box_faces <m,n,p> - Number of faces along each dimension 848 . -dm_plex_box_lower <x,y,z> - Specify lower-left-bottom coordinates for the box 849 . -dm_plex_box_upper <x,y,z> - Specify upper-right-top coordinates for the box 850 . -dm_plex_box_bd <bx,by,bz> - Specify the DMBoundaryType for each direction 851 . -dm_plex_sphere_radius <r> - The sphere radius 852 . -dm_plex_ball_radius <r> - Radius of the ball 853 . -dm_plex_cylinder_bd <bz> - Boundary type in the z direction 854 . -dm_plex_cylinder_num_wedges <n> - Number of wedges around the cylinder 855 . -dm_plex_reorder <order> - Reorder the mesh using the specified algorithm 856 . -dm_refine_pre <n> - The number of refinements before distribution 857 . -dm_refine_uniform_pre <bool> - Flag for uniform refinement before distribution 858 . -dm_refine_volume_limit_pre <v> - The maximum cell volume after refinement before distribution 859 . -dm_refine <n> - The number of refinements after distribution 860 . -dm_extrude <l> - Activate extrusion and specify the number of layers to extrude 861 . -dm_plex_transform_extrude_thickness <t> - The total thickness of extruded layers 862 . -dm_plex_transform_extrude_use_tensor <bool> - Use tensor cells when extruding 863 . -dm_plex_transform_extrude_symmetric <bool> - Extrude layers symmetrically about the surface 864 . -dm_plex_transform_extrude_normal <n0,...,nd> - Specify the extrusion direction 865 . -dm_plex_transform_extrude_thicknesses <t0,...,tl> - Specify thickness of each layer 866 . -dm_plex_create_fv_ghost_cells - Flag to create finite volume ghost cells on the boundary 867 . -dm_plex_fv_ghost_cells_label <name> - Label name for ghost cells boundary 868 . -dm_distribute <bool> - Flag to redistribute a mesh among processes 869 . -dm_distribute_overlap <n> - The size of the overlap halo 870 . -dm_plex_adj_cone <bool> - Set adjacency direction 871 - -dm_plex_adj_closure <bool> - Set adjacency size 872 873 DMPLEX Specific Checks 874 + -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric - DMPlexCheckSymmetry() 875 . -dm_plex_check_skeleton - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - DMPlexCheckSkeleton() 876 . -dm_plex_check_faces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type - DMPlexCheckFaces() 877 . -dm_plex_check_geometry - Check that cells have positive volume - DMPlexCheckGeometry() 878 . -dm_plex_check_pointsf - Check some necessary conditions for PointSF - DMPlexCheckPointSF() 879 . -dm_plex_check_interface_cones - Check points on inter-partition interfaces have conforming order of cone points - DMPlexCheckInterfaceCones() 880 - -dm_plex_check_all - Perform all the checks above 881 882 Level: intermediate 883 884 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), 885 DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces(), DMPlexCheckGeometry(), DMPlexCheckPointSF(), DMPlexCheckInterfaceCones() 886 887 @*/ 888 PetscErrorCode DMSetFromOptions(DM dm) 889 { 890 char typeName[256]; 891 PetscBool flg; 892 PetscErrorCode ierr; 893 894 PetscFunctionBegin; 895 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 896 dm->setfromoptionscalled = PETSC_TRUE; 897 if (dm->sf) {ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr);} 898 if (dm->sectionSF) {ierr = PetscSFSetFromOptions(dm->sectionSF);CHKERRQ(ierr);} 899 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 900 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 901 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 902 if (flg) { 903 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 904 } 905 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 906 if (flg) { 907 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 908 } 909 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","DMSetISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 910 ierr = PetscOptionsInt("-dm_bind_below","Set the size threshold (in entries) below which the Vec is bound to the CPU","VecBindToCPU",dm->bind_below,&dm->bind_below,&flg);CHKERRQ(ierr); 911 if (dm->ops->setfromoptions) { 912 ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr); 913 } 914 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 915 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);CHKERRQ(ierr); 916 ierr = PetscOptionsEnd();CHKERRQ(ierr); 917 PetscFunctionReturn(0); 918 } 919 920 /*@C 921 DMViewFromOptions - View from Options 922 923 Collective on DM 924 925 Input Parameters: 926 + dm - the DM object 927 . obj - Optional object 928 - name - command line option 929 930 Level: intermediate 931 .seealso: DM, DMView, PetscObjectViewFromOptions(), DMCreate() 932 @*/ 933 PetscErrorCode DMViewFromOptions(DM dm,PetscObject obj,const char name[]) 934 { 935 PetscErrorCode ierr; 936 937 PetscFunctionBegin; 938 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 939 ierr = PetscObjectViewFromOptions((PetscObject)dm,obj,name);CHKERRQ(ierr); 940 PetscFunctionReturn(0); 941 } 942 943 /*@C 944 DMView - Views a DM 945 946 Collective on dm 947 948 Input Parameters: 949 + dm - the DM object to view 950 - v - the viewer 951 952 Notes: 953 Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex 954 meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName() 955 before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object. 956 957 Level: beginner 958 959 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMLoad(), PetscObjectSetName() 960 961 @*/ 962 PetscErrorCode DMView(DM dm,PetscViewer v) 963 { 964 PetscErrorCode ierr; 965 PetscBool isbinary; 966 PetscMPIInt size; 967 PetscViewerFormat format; 968 969 PetscFunctionBegin; 970 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 971 if (!v) { 972 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 973 } 974 PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,2); 975 /* Ideally, we would like to have this test on. 976 However, it currently breaks socket viz via GLVis. 977 During DMView(parallel_mesh,glvis_viewer), each 978 process opens a sequential ASCII socket to visualize 979 the local mesh, and PetscObjectView(dm,local_socket) 980 is internally called inside VecView_GLVis, incurring 981 in an error here */ 982 /* PetscCheckSameComm(dm,1,v,2); */ 983 ierr = PetscViewerCheckWritable(v);CHKERRQ(ierr); 984 985 ierr = PetscViewerGetFormat(v,&format);CHKERRQ(ierr); 986 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRMPI(ierr); 987 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 988 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr); 989 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 990 if (isbinary) { 991 PetscInt classid = DM_FILE_CLASSID; 992 char type[256]; 993 994 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT);CHKERRQ(ierr); 995 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 996 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR);CHKERRQ(ierr); 997 } 998 if (dm->ops->view) { 999 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 1000 } 1001 PetscFunctionReturn(0); 1002 } 1003 1004 /*@ 1005 DMCreateGlobalVector - Creates a global vector from a DM object 1006 1007 Collective on dm 1008 1009 Input Parameter: 1010 . dm - the DM object 1011 1012 Output Parameter: 1013 . vec - the global vector 1014 1015 Level: beginner 1016 1017 .seealso DMCreateLocalVector(), DMGetGlobalVector(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1018 1019 @*/ 1020 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 1021 { 1022 PetscErrorCode ierr; 1023 1024 PetscFunctionBegin; 1025 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1026 PetscValidPointer(vec,2); 1027 PetscCheckFalse(!dm->ops->createglobalvector,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateGlobalVector",((PetscObject)dm)->type_name); 1028 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 1029 if (PetscDefined(USE_DEBUG)) { 1030 DM vdm; 1031 1032 ierr = VecGetDM(*vec,&vdm);CHKERRQ(ierr); 1033 PetscCheckFalse(!vdm,PETSC_COMM_SELF,PETSC_ERR_PLIB,"DM type '%s' did not attach the DM to the vector",((PetscObject)dm)->type_name); 1034 } 1035 PetscFunctionReturn(0); 1036 } 1037 1038 /*@ 1039 DMCreateLocalVector - Creates a local vector from a DM object 1040 1041 Not Collective 1042 1043 Input Parameter: 1044 . dm - the DM object 1045 1046 Output Parameter: 1047 . vec - the local vector 1048 1049 Level: beginner 1050 1051 .seealso DMCreateGlobalVector(), DMGetLocalVector(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1052 1053 @*/ 1054 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 1055 { 1056 PetscErrorCode ierr; 1057 1058 PetscFunctionBegin; 1059 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1060 PetscValidPointer(vec,2); 1061 PetscCheckFalse(!dm->ops->createlocalvector,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateLocalVector",((PetscObject)dm)->type_name); 1062 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 1063 if (PetscDefined(USE_DEBUG)) { 1064 DM vdm; 1065 1066 ierr = VecGetDM(*vec,&vdm);CHKERRQ(ierr); 1067 PetscCheckFalse(!vdm,PETSC_COMM_SELF,PETSC_ERR_LIB,"DM type '%s' did not attach the DM to the vector",((PetscObject)dm)->type_name); 1068 } 1069 PetscFunctionReturn(0); 1070 } 1071 1072 /*@ 1073 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 1074 1075 Collective on dm 1076 1077 Input Parameter: 1078 . dm - the DM that provides the mapping 1079 1080 Output Parameter: 1081 . ltog - the mapping 1082 1083 Level: intermediate 1084 1085 Notes: 1086 This mapping can then be used by VecSetLocalToGlobalMapping() or 1087 MatSetLocalToGlobalMapping(). 1088 1089 .seealso: DMCreateLocalVector() 1090 @*/ 1091 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 1092 { 1093 PetscInt bs = -1, bsLocal[2], bsMinMax[2]; 1094 PetscErrorCode ierr; 1095 1096 PetscFunctionBegin; 1097 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1098 PetscValidPointer(ltog,2); 1099 if (!dm->ltogmap) { 1100 PetscSection section, sectionGlobal; 1101 1102 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1103 if (section) { 1104 const PetscInt *cdofs; 1105 PetscInt *ltog; 1106 PetscInt pStart, pEnd, n, p, k, l; 1107 1108 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1109 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 1110 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 1111 ierr = PetscMalloc1(n, <og);CHKERRQ(ierr); /* We want the local+overlap size */ 1112 for (p = pStart, l = 0; p < pEnd; ++p) { 1113 PetscInt bdof, cdof, dof, off, c, cind; 1114 1115 /* Should probably use constrained dofs */ 1116 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 1117 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 1118 ierr = PetscSectionGetConstraintIndices(section, p, &cdofs);CHKERRQ(ierr); 1119 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 1120 /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */ 1121 bdof = cdof && (dof-cdof) ? 1 : dof; 1122 if (dof) { 1123 if (bs < 0) {bs = bdof;} 1124 else if (bs != bdof) {bs = 1;} 1125 } 1126 1127 for (c = 0, cind = 0; c < dof; ++c, ++l) { 1128 if (cind < cdof && c == cdofs[cind]) { 1129 ltog[l] = off < 0 ? off-c : -(off+c+1); 1130 cind++; 1131 } else { 1132 ltog[l] = (off < 0 ? -(off+1) : off) + c - cind; 1133 } 1134 } 1135 } 1136 /* Must have same blocksize on all procs (some might have no points) */ 1137 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 1138 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 1139 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 1140 else {bs = bsMinMax[0];} 1141 bs = bs < 0 ? 1 : bs; 1142 /* Must reduce indices by blocksize */ 1143 if (bs > 1) { 1144 for (l = 0, k = 0; l < n; l += bs, ++k) { 1145 // Integer division of negative values truncates toward zero(!), not toward negative infinity 1146 ltog[k] = ltog[l] >= 0 ? ltog[l]/bs : -(-(ltog[l]+1)/bs + 1); 1147 } 1148 n /= bs; 1149 } 1150 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 1151 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr); 1152 } else { 1153 PetscCheckFalse(!dm->ops->getlocaltoglobalmapping,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetLocalToGlobalMapping",((PetscObject)dm)->type_name); 1154 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 1155 } 1156 } 1157 *ltog = dm->ltogmap; 1158 PetscFunctionReturn(0); 1159 } 1160 1161 /*@ 1162 DMGetBlockSize - Gets the inherent block size associated with a DM 1163 1164 Not Collective 1165 1166 Input Parameter: 1167 . dm - the DM with block structure 1168 1169 Output Parameter: 1170 . bs - the block size, 1 implies no exploitable block structure 1171 1172 Level: intermediate 1173 1174 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping() 1175 @*/ 1176 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 1177 { 1178 PetscFunctionBegin; 1179 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1180 PetscValidIntPointer(bs,2); 1181 PetscCheckFalse(dm->bs < 1,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 1182 *bs = dm->bs; 1183 PetscFunctionReturn(0); 1184 } 1185 1186 /*@C 1187 DMCreateInterpolation - Gets interpolation matrix between two DM objects 1188 1189 Collective on dmc 1190 1191 Input Parameters: 1192 + dmc - the DM object 1193 - dmf - the second, finer DM object 1194 1195 Output Parameters: 1196 + mat - the interpolation 1197 - vec - the scaling (optional) 1198 1199 Level: developer 1200 1201 Notes: 1202 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1203 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 1204 1205 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 1206 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 1207 1208 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolationScale() 1209 1210 @*/ 1211 PetscErrorCode DMCreateInterpolation(DM dmc,DM dmf,Mat *mat,Vec *vec) 1212 { 1213 PetscErrorCode ierr; 1214 1215 PetscFunctionBegin; 1216 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 1217 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 1218 PetscValidPointer(mat,3); 1219 PetscCheckFalse(!dmc->ops->createinterpolation,PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateInterpolation",((PetscObject)dmc)->type_name); 1220 ierr = PetscLogEventBegin(DM_CreateInterpolation,dmc,dmf,0,0);CHKERRQ(ierr); 1221 ierr = (*dmc->ops->createinterpolation)(dmc,dmf,mat,vec);CHKERRQ(ierr); 1222 ierr = PetscLogEventEnd(DM_CreateInterpolation,dmc,dmf,0,0);CHKERRQ(ierr); 1223 PetscFunctionReturn(0); 1224 } 1225 1226 /*@ 1227 DMCreateInterpolationScale - Forms L = 1/(R*1) such that diag(L)*R preserves scale and is thus suitable for state (versus residual) restriction. 1228 1229 Input Parameters: 1230 + dac - DM that defines a coarse mesh 1231 . daf - DM that defines a fine mesh 1232 - mat - the restriction (or interpolation operator) from fine to coarse 1233 1234 Output Parameter: 1235 . scale - the scaled vector 1236 1237 Level: developer 1238 1239 Developer Notes: 1240 If the fine-scale DMDA has the -dm_bind_below option set to true, then DMCreateInterpolationScale() calls MatSetBindingPropagates() 1241 on the restriction/interpolation operator to set the bindingpropagates flag to true. 1242 1243 .seealso: DMCreateInterpolation() 1244 1245 @*/ 1246 PetscErrorCode DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale) 1247 { 1248 PetscErrorCode ierr; 1249 Vec fine; 1250 PetscScalar one = 1.0; 1251 #if defined(PETSC_HAVE_CUDA) 1252 PetscBool bindingpropagates,isbound; 1253 #endif 1254 1255 PetscFunctionBegin; 1256 ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr); 1257 ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr); 1258 ierr = VecSet(fine,one);CHKERRQ(ierr); 1259 #if defined(PETSC_HAVE_CUDA) 1260 /* If the 'fine' Vec is bound to the CPU, it makes sense to bind 'mat' as well. 1261 * Note that we only do this for the CUDA case, right now, but if we add support for MatMultTranspose() via ViennaCL, 1262 * we'll need to do it for that case, too.*/ 1263 ierr = VecGetBindingPropagates(fine,&bindingpropagates);CHKERRQ(ierr); 1264 if (bindingpropagates) { 1265 ierr = MatSetBindingPropagates(mat,PETSC_TRUE);CHKERRQ(ierr); 1266 ierr = VecBoundToCPU(fine,&isbound);CHKERRQ(ierr); 1267 ierr = MatBindToCPU(mat,isbound);CHKERRQ(ierr); 1268 } 1269 #endif 1270 ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr); 1271 ierr = VecDestroy(&fine);CHKERRQ(ierr); 1272 ierr = VecReciprocal(*scale);CHKERRQ(ierr); 1273 PetscFunctionReturn(0); 1274 } 1275 1276 /*@ 1277 DMCreateRestriction - Gets restriction matrix between two DM objects 1278 1279 Collective on dmc 1280 1281 Input Parameters: 1282 + dmc - the DM object 1283 - dmf - the second, finer DM object 1284 1285 Output Parameter: 1286 . mat - the restriction 1287 1288 Level: developer 1289 1290 Notes: 1291 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1292 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 1293 1294 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation() 1295 1296 @*/ 1297 PetscErrorCode DMCreateRestriction(DM dmc,DM dmf,Mat *mat) 1298 { 1299 PetscErrorCode ierr; 1300 1301 PetscFunctionBegin; 1302 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 1303 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 1304 PetscValidPointer(mat,3); 1305 PetscCheckFalse(!dmc->ops->createrestriction,PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateRestriction",((PetscObject)dmc)->type_name); 1306 ierr = PetscLogEventBegin(DM_CreateRestriction,dmc,dmf,0,0);CHKERRQ(ierr); 1307 ierr = (*dmc->ops->createrestriction)(dmc,dmf,mat);CHKERRQ(ierr); 1308 ierr = PetscLogEventEnd(DM_CreateRestriction,dmc,dmf,0,0);CHKERRQ(ierr); 1309 PetscFunctionReturn(0); 1310 } 1311 1312 /*@ 1313 DMCreateInjection - Gets injection matrix between two DM objects 1314 1315 Collective on dac 1316 1317 Input Parameters: 1318 + dac - the DM object 1319 - daf - the second, finer DM object 1320 1321 Output Parameter: 1322 . mat - the injection 1323 1324 Level: developer 1325 1326 Notes: 1327 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1328 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 1329 1330 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 1331 1332 @*/ 1333 PetscErrorCode DMCreateInjection(DM dac,DM daf,Mat *mat) 1334 { 1335 PetscErrorCode ierr; 1336 1337 PetscFunctionBegin; 1338 PetscValidHeaderSpecific(dac,DM_CLASSID,1); 1339 PetscValidHeaderSpecific(daf,DM_CLASSID,2); 1340 PetscValidPointer(mat,3); 1341 PetscCheckFalse(!dac->ops->createinjection,PetscObjectComm((PetscObject)dac),PETSC_ERR_SUP,"DM type %s does not implement DMCreateInjection",((PetscObject)dac)->type_name); 1342 ierr = PetscLogEventBegin(DM_CreateInjection,dac,daf,0,0);CHKERRQ(ierr); 1343 ierr = (*dac->ops->createinjection)(dac,daf,mat);CHKERRQ(ierr); 1344 ierr = PetscLogEventEnd(DM_CreateInjection,dac,daf,0,0);CHKERRQ(ierr); 1345 PetscFunctionReturn(0); 1346 } 1347 1348 /*@ 1349 DMCreateMassMatrix - Gets mass matrix between two DM objects, M_ij = \int \phi_i \psi_j 1350 1351 Collective on dac 1352 1353 Input Parameters: 1354 + dmc - the target DM object 1355 - dmf - the source DM object 1356 1357 Output Parameter: 1358 . mat - the mass matrix 1359 1360 Level: developer 1361 1362 .seealso DMCreateMassMatrixLumped(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection() 1363 @*/ 1364 PetscErrorCode DMCreateMassMatrix(DM dmc, DM dmf, Mat *mat) 1365 { 1366 PetscErrorCode ierr; 1367 1368 PetscFunctionBegin; 1369 PetscValidHeaderSpecific(dmc, DM_CLASSID, 1); 1370 PetscValidHeaderSpecific(dmf, DM_CLASSID, 2); 1371 PetscValidPointer(mat,3); 1372 PetscCheck(dmc->ops->createmassmatrix,PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMassMatrix",((PetscObject)dmc)->type_name); 1373 ierr = (*dmc->ops->createmassmatrix)(dmc, dmf, mat);CHKERRQ(ierr); 1374 PetscFunctionReturn(0); 1375 } 1376 1377 /*@ 1378 DMCreateMassMatrixLumped - Gets the lumped mass matrix for a given DM 1379 1380 Collective on dm 1381 1382 Input Parameter: 1383 . dm - the DM object 1384 1385 Output Parameter: 1386 . lm - the lumped mass matrix 1387 1388 Level: developer 1389 1390 .seealso DMCreateMassMatrix(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection() 1391 @*/ 1392 PetscErrorCode DMCreateMassMatrixLumped(DM dm, Vec *lm) 1393 { 1394 PetscErrorCode ierr; 1395 1396 PetscFunctionBegin; 1397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1398 PetscValidPointer(lm,2); 1399 PetscCheck(dm->ops->createmassmatrixlumped,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMassMatrixLumped",((PetscObject)dm)->type_name); 1400 ierr = (*dm->ops->createmassmatrixlumped)(dm, lm);CHKERRQ(ierr); 1401 PetscFunctionReturn(0); 1402 } 1403 1404 /*@ 1405 DMCreateColoring - Gets coloring for a DM 1406 1407 Collective on dm 1408 1409 Input Parameters: 1410 + dm - the DM object 1411 - ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL 1412 1413 Output Parameter: 1414 . coloring - the coloring 1415 1416 Notes: 1417 Coloring of matrices can be computed directly from the sparse matrix nonzero structure via the MatColoring object or from the mesh from which the 1418 matrix comes from. In general using the mesh produces a more optimal coloring (fewer colors). 1419 1420 This produces a coloring with the distance of 2, see MatSetColoringDistance() which can be used for efficiently computing Jacobians with MatFDColoringCreate() 1421 1422 Level: developer 1423 1424 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType(), MatColoring, MatFDColoringCreate() 1425 1426 @*/ 1427 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring) 1428 { 1429 PetscErrorCode ierr; 1430 1431 PetscFunctionBegin; 1432 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1433 PetscValidPointer(coloring,3); 1434 PetscCheckFalse(!dm->ops->getcoloring,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateColoring",((PetscObject)dm)->type_name); 1435 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr); 1436 PetscFunctionReturn(0); 1437 } 1438 1439 /*@ 1440 DMCreateMatrix - Gets empty Jacobian for a DM 1441 1442 Collective on dm 1443 1444 Input Parameter: 1445 . dm - the DM object 1446 1447 Output Parameter: 1448 . mat - the empty Jacobian 1449 1450 Level: beginner 1451 1452 Options Database Keys: 1453 . -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 1454 1455 Notes: 1456 This properly preallocates the number of nonzeros in the sparse matrix so you 1457 do not need to do it yourself. 1458 1459 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 1460 the nonzero pattern call DMSetMatrixPreallocateOnly() 1461 1462 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 1463 internally by PETSc. 1464 1465 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 1466 the indices for the global numbering for DMDAs which is complicated. 1467 1468 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType() 1469 1470 @*/ 1471 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat) 1472 { 1473 PetscErrorCode ierr; 1474 1475 PetscFunctionBegin; 1476 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1477 PetscValidPointer(mat,2); 1478 PetscCheckFalse(!dm->ops->creatematrix,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMatrix",((PetscObject)dm)->type_name); 1479 ierr = MatInitializePackage();CHKERRQ(ierr); 1480 ierr = PetscLogEventBegin(DM_CreateMatrix,0,0,0,0);CHKERRQ(ierr); 1481 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr); 1482 if (PetscDefined(USE_DEBUG)) { 1483 DM mdm; 1484 1485 ierr = MatGetDM(*mat,&mdm);CHKERRQ(ierr); 1486 PetscCheckFalse(!mdm,PETSC_COMM_SELF,PETSC_ERR_PLIB,"DM type '%s' did not attach the DM to the matrix",((PetscObject)dm)->type_name); 1487 } 1488 /* Handle nullspace and near nullspace */ 1489 if (dm->Nf) { 1490 MatNullSpace nullSpace; 1491 PetscInt Nf, f; 1492 1493 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 1494 for (f = 0; f < Nf; ++f) { 1495 if (dm->nullspaceConstructors[f]) { 1496 ierr = (*dm->nullspaceConstructors[f])(dm, f, f, &nullSpace);CHKERRQ(ierr); 1497 ierr = MatSetNullSpace(*mat, nullSpace);CHKERRQ(ierr); 1498 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1499 break; 1500 } 1501 } 1502 for (f = 0; f < Nf; ++f) { 1503 if (dm->nearnullspaceConstructors[f]) { 1504 ierr = (*dm->nearnullspaceConstructors[f])(dm, f, f, &nullSpace);CHKERRQ(ierr); 1505 ierr = MatSetNearNullSpace(*mat, nullSpace);CHKERRQ(ierr); 1506 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1507 } 1508 } 1509 } 1510 ierr = PetscLogEventEnd(DM_CreateMatrix,0,0,0,0);CHKERRQ(ierr); 1511 PetscFunctionReturn(0); 1512 } 1513 1514 /*@ 1515 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 1516 preallocated but the nonzero structure and zero values will not be set. 1517 1518 Logically Collective on dm 1519 1520 Input Parameters: 1521 + dm - the DM 1522 - only - PETSC_TRUE if only want preallocation 1523 1524 Level: developer 1525 1526 Options Database Keys: 1527 . -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 1528 1529 .seealso DMCreateMatrix(), DMSetMatrixStructureOnly() 1530 @*/ 1531 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 1532 { 1533 PetscFunctionBegin; 1534 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1535 dm->prealloc_only = only; 1536 PetscFunctionReturn(0); 1537 } 1538 1539 /*@ 1540 DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created 1541 but the array for values will not be allocated. 1542 1543 Logically Collective on dm 1544 1545 Input Parameters: 1546 + dm - the DM 1547 - only - PETSC_TRUE if only want matrix stucture 1548 1549 Level: developer 1550 .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly() 1551 @*/ 1552 PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only) 1553 { 1554 PetscFunctionBegin; 1555 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1556 dm->structure_only = only; 1557 PetscFunctionReturn(0); 1558 } 1559 1560 /*@C 1561 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1562 1563 Not Collective 1564 1565 Input Parameters: 1566 + dm - the DM object 1567 . count - The minimum size 1568 - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT) 1569 1570 Output Parameter: 1571 . array - the work array 1572 1573 Level: developer 1574 1575 .seealso DMDestroy(), DMCreate() 1576 @*/ 1577 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem) 1578 { 1579 PetscErrorCode ierr; 1580 DMWorkLink link; 1581 PetscMPIInt dsize; 1582 1583 PetscFunctionBegin; 1584 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1585 PetscValidPointer(mem,4); 1586 if (dm->workin) { 1587 link = dm->workin; 1588 dm->workin = dm->workin->next; 1589 } else { 1590 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr); 1591 } 1592 ierr = MPI_Type_size(dtype,&dsize);CHKERRMPI(ierr); 1593 if (((size_t)dsize*count) > link->bytes) { 1594 ierr = PetscFree(link->mem);CHKERRQ(ierr); 1595 ierr = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr); 1596 link->bytes = dsize*count; 1597 } 1598 link->next = dm->workout; 1599 dm->workout = link; 1600 #if defined(PETSC_HAVE_VALGRIND) 1601 VALGRIND_MAKE_MEM_NOACCESS((char*)link->mem + (size_t)dsize*count, link->bytes - (size_t)dsize*count); 1602 VALGRIND_MAKE_MEM_UNDEFINED(link->mem, (size_t)dsize*count); 1603 #endif 1604 *(void**)mem = link->mem; 1605 PetscFunctionReturn(0); 1606 } 1607 1608 /*@C 1609 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1610 1611 Not Collective 1612 1613 Input Parameters: 1614 + dm - the DM object 1615 . count - The minimum size 1616 - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT 1617 1618 Output Parameter: 1619 . array - the work array 1620 1621 Level: developer 1622 1623 Developer Notes: 1624 count and dtype are ignored, they are only needed for DMGetWorkArray() 1625 .seealso DMDestroy(), DMCreate() 1626 @*/ 1627 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem) 1628 { 1629 DMWorkLink *p,link; 1630 1631 PetscFunctionBegin; 1632 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1633 PetscValidPointer(mem,4); 1634 for (p=&dm->workout; (link=*p); p=&link->next) { 1635 if (link->mem == *(void**)mem) { 1636 *p = link->next; 1637 link->next = dm->workin; 1638 dm->workin = link; 1639 *(void**)mem = NULL; 1640 PetscFunctionReturn(0); 1641 } 1642 } 1643 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1644 } 1645 1646 /*@C 1647 DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field 1648 1649 Logically collective on DM 1650 1651 Input Parameters: 1652 + dm - The DM 1653 . field - The field number for the nullspace 1654 - nullsp - A callback to create the nullspace 1655 1656 Notes: 1657 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is 1658 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace) 1659 $ dm - The present DM 1660 $ origField - The field number given above, in the original DM 1661 $ field - The field number in dm 1662 $ nullSpace - The nullspace for the given field 1663 1664 This function is currently not available from Fortran. 1665 1666 .seealso: DMGetNullSpaceConstructor(), DMSetNearNullSpaceConstructor(), DMGetNearNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM() 1667 */ 1668 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)) 1669 { 1670 PetscFunctionBegin; 1671 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1672 PetscCheckFalse(field >= 10,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1673 dm->nullspaceConstructors[field] = nullsp; 1674 PetscFunctionReturn(0); 1675 } 1676 1677 /*@C 1678 DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, or NULL 1679 1680 Not collective 1681 1682 Input Parameters: 1683 + dm - The DM 1684 - field - The field number for the nullspace 1685 1686 Output Parameter: 1687 . nullsp - A callback to create the nullspace 1688 1689 Notes: 1690 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is 1691 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace) 1692 $ dm - The present DM 1693 $ origField - The field number given above, in the original DM 1694 $ field - The field number in dm 1695 $ nullSpace - The nullspace for the given field 1696 1697 This function is currently not available from Fortran. 1698 1699 .seealso: DMSetNullSpaceConstructor(), DMSetNearNullSpaceConstructor(), DMGetNearNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM() 1700 */ 1701 PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)) 1702 { 1703 PetscFunctionBegin; 1704 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1705 PetscValidPointer(nullsp, 3); 1706 PetscCheckFalse(field >= 10,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1707 *nullsp = dm->nullspaceConstructors[field]; 1708 PetscFunctionReturn(0); 1709 } 1710 1711 /*@C 1712 DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field 1713 1714 Logically collective on DM 1715 1716 Input Parameters: 1717 + dm - The DM 1718 . field - The field number for the nullspace 1719 - nullsp - A callback to create the near-nullspace 1720 1721 Notes: 1722 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is 1723 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace) 1724 $ dm - The present DM 1725 $ origField - The field number given above, in the original DM 1726 $ field - The field number in dm 1727 $ nullSpace - The nullspace for the given field 1728 1729 This function is currently not available from Fortran. 1730 1731 .seealso: DMGetNearNullSpaceConstructor(), DMSetNullSpaceConstructor(), DMGetNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM() 1732 */ 1733 PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)) 1734 { 1735 PetscFunctionBegin; 1736 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1737 PetscCheckFalse(field >= 10,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1738 dm->nearnullspaceConstructors[field] = nullsp; 1739 PetscFunctionReturn(0); 1740 } 1741 1742 /*@C 1743 DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, or NULL 1744 1745 Not collective 1746 1747 Input Parameters: 1748 + dm - The DM 1749 - field - The field number for the nullspace 1750 1751 Output Parameter: 1752 . nullsp - A callback to create the near-nullspace 1753 1754 Notes: 1755 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is 1756 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace) 1757 $ dm - The present DM 1758 $ origField - The field number given above, in the original DM 1759 $ field - The field number in dm 1760 $ nullSpace - The nullspace for the given field 1761 1762 This function is currently not available from Fortran. 1763 1764 .seealso: DMSetNearNullSpaceConstructor(), DMSetNullSpaceConstructor(), DMGetNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM() 1765 */ 1766 PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)) 1767 { 1768 PetscFunctionBegin; 1769 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1770 PetscValidPointer(nullsp, 3); 1771 PetscCheckFalse(field >= 10,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1772 *nullsp = dm->nearnullspaceConstructors[field]; 1773 PetscFunctionReturn(0); 1774 } 1775 1776 /*@C 1777 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1778 1779 Not collective 1780 1781 Input Parameter: 1782 . dm - the DM object 1783 1784 Output Parameters: 1785 + numFields - The number of fields (or NULL if not requested) 1786 . fieldNames - The name for each field (or NULL if not requested) 1787 - fields - The global indices for each field (or NULL if not requested) 1788 1789 Level: intermediate 1790 1791 Notes: 1792 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1793 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1794 PetscFree(). 1795 1796 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1797 @*/ 1798 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1799 { 1800 PetscSection section, sectionGlobal; 1801 PetscErrorCode ierr; 1802 1803 PetscFunctionBegin; 1804 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1805 if (numFields) { 1806 PetscValidIntPointer(numFields,2); 1807 *numFields = 0; 1808 } 1809 if (fieldNames) { 1810 PetscValidPointer(fieldNames,3); 1811 *fieldNames = NULL; 1812 } 1813 if (fields) { 1814 PetscValidPointer(fields,4); 1815 *fields = NULL; 1816 } 1817 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1818 if (section) { 1819 PetscInt *fieldSizes, *fieldNc, **fieldIndices; 1820 PetscInt nF, f, pStart, pEnd, p; 1821 1822 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1823 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1824 ierr = PetscMalloc3(nF,&fieldSizes,nF,&fieldNc,nF,&fieldIndices);CHKERRQ(ierr); 1825 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1826 for (f = 0; f < nF; ++f) { 1827 fieldSizes[f] = 0; 1828 ierr = PetscSectionGetFieldComponents(section, f, &fieldNc[f]);CHKERRQ(ierr); 1829 } 1830 for (p = pStart; p < pEnd; ++p) { 1831 PetscInt gdof; 1832 1833 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1834 if (gdof > 0) { 1835 for (f = 0; f < nF; ++f) { 1836 PetscInt fdof, fcdof, fpdof; 1837 1838 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1839 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1840 fpdof = fdof-fcdof; 1841 if (fpdof && fpdof != fieldNc[f]) { 1842 /* Layout does not admit a pointwise block size */ 1843 fieldNc[f] = 1; 1844 } 1845 fieldSizes[f] += fpdof; 1846 } 1847 } 1848 } 1849 for (f = 0; f < nF; ++f) { 1850 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr); 1851 fieldSizes[f] = 0; 1852 } 1853 for (p = pStart; p < pEnd; ++p) { 1854 PetscInt gdof, goff; 1855 1856 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1857 if (gdof > 0) { 1858 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1859 for (f = 0; f < nF; ++f) { 1860 PetscInt fdof, fcdof, fc; 1861 1862 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1863 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1864 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1865 fieldIndices[f][fieldSizes[f]] = goff++; 1866 } 1867 } 1868 } 1869 } 1870 if (numFields) *numFields = nF; 1871 if (fieldNames) { 1872 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr); 1873 for (f = 0; f < nF; ++f) { 1874 const char *fieldName; 1875 1876 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1877 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1878 } 1879 } 1880 if (fields) { 1881 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr); 1882 for (f = 0; f < nF; ++f) { 1883 PetscInt bs, in[2], out[2]; 1884 1885 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1886 in[0] = -fieldNc[f]; 1887 in[1] = fieldNc[f]; 1888 ierr = MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1889 bs = (-out[0] == out[1]) ? out[1] : 1; 1890 ierr = ISSetBlockSize((*fields)[f], bs);CHKERRQ(ierr); 1891 } 1892 } 1893 ierr = PetscFree3(fieldSizes,fieldNc,fieldIndices);CHKERRQ(ierr); 1894 } else if (dm->ops->createfieldis) { 1895 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1896 } 1897 PetscFunctionReturn(0); 1898 } 1899 1900 /*@C 1901 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1902 corresponding to different fields: each IS contains the global indices of the dofs of the 1903 corresponding field. The optional list of DMs define the DM for each subproblem. 1904 Generalizes DMCreateFieldIS(). 1905 1906 Not collective 1907 1908 Input Parameter: 1909 . dm - the DM object 1910 1911 Output Parameters: 1912 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1913 . namelist - The name for each field (or NULL if not requested) 1914 . islist - The global indices for each field (or NULL if not requested) 1915 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1916 1917 Level: intermediate 1918 1919 Notes: 1920 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1921 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1922 and all of the arrays should be freed with PetscFree(). 1923 1924 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1925 @*/ 1926 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1927 { 1928 PetscErrorCode ierr; 1929 1930 PetscFunctionBegin; 1931 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1932 if (len) { 1933 PetscValidIntPointer(len,2); 1934 *len = 0; 1935 } 1936 if (namelist) { 1937 PetscValidPointer(namelist,3); 1938 *namelist = NULL; 1939 } 1940 if (islist) { 1941 PetscValidPointer(islist,4); 1942 *islist = NULL; 1943 } 1944 if (dmlist) { 1945 PetscValidPointer(dmlist,5); 1946 *dmlist = NULL; 1947 } 1948 /* 1949 Is it a good idea to apply the following check across all impls? 1950 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1951 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1952 */ 1953 PetscCheckFalse(!dm->setupcalled,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1954 if (!dm->ops->createfielddecomposition) { 1955 PetscSection section; 1956 PetscInt numFields, f; 1957 1958 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1959 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1960 if (section && numFields && dm->ops->createsubdm) { 1961 if (len) *len = numFields; 1962 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);} 1963 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);} 1964 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);} 1965 for (f = 0; f < numFields; ++f) { 1966 const char *fieldName; 1967 1968 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr); 1969 if (namelist) { 1970 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1971 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1972 } 1973 } 1974 } else { 1975 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1976 /* By default there are no DMs associated with subproblems. */ 1977 if (dmlist) *dmlist = NULL; 1978 } 1979 } else { 1980 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1981 } 1982 PetscFunctionReturn(0); 1983 } 1984 1985 /*@ 1986 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1987 The fields are defined by DMCreateFieldIS(). 1988 1989 Not collective 1990 1991 Input Parameters: 1992 + dm - The DM object 1993 . numFields - The number of fields in this subproblem 1994 - fields - The field numbers of the selected fields 1995 1996 Output Parameters: 1997 + is - The global indices for the subproblem 1998 - subdm - The DM for the subproblem 1999 2000 Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed 2001 2002 Level: intermediate 2003 2004 .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 2005 @*/ 2006 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 2007 { 2008 PetscErrorCode ierr; 2009 2010 PetscFunctionBegin; 2011 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2012 PetscValidPointer(fields,3); 2013 if (is) PetscValidPointer(is,4); 2014 if (subdm) PetscValidPointer(subdm,5); 2015 PetscCheckFalse(!dm->ops->createsubdm,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateSubDM",((PetscObject)dm)->type_name); 2016 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 2017 PetscFunctionReturn(0); 2018 } 2019 2020 /*@C 2021 DMCreateSuperDM - Returns an arrays of ISes and DM encapsulating a superproblem defined by the DMs passed in. 2022 2023 Not collective 2024 2025 Input Parameters: 2026 + dms - The DM objects 2027 - len - The number of DMs 2028 2029 Output Parameters: 2030 + is - The global indices for the subproblem, or NULL 2031 - superdm - The DM for the superproblem 2032 2033 Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed 2034 2035 Level: intermediate 2036 2037 .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 2038 @*/ 2039 PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt len, IS **is, DM *superdm) 2040 { 2041 PetscInt i; 2042 PetscErrorCode ierr; 2043 2044 PetscFunctionBegin; 2045 PetscValidPointer(dms,1); 2046 for (i = 0; i < len; ++i) {PetscValidHeaderSpecific(dms[i],DM_CLASSID,1);} 2047 if (is) PetscValidPointer(is,3); 2048 PetscValidPointer(superdm,4); 2049 PetscCheckFalse(len < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %D", len); 2050 if (len) { 2051 DM dm = dms[0]; 2052 PetscCheckFalse(!dm->ops->createsuperdm,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateSuperDM",((PetscObject)dm)->type_name); 2053 ierr = (*dm->ops->createsuperdm)(dms, len, is, superdm);CHKERRQ(ierr); 2054 } 2055 PetscFunctionReturn(0); 2056 } 2057 2058 /*@C 2059 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 2060 corresponding to restrictions to pairs nested subdomains: each IS contains the global 2061 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 2062 define a nonoverlapping covering, while outer subdomains can overlap. 2063 The optional list of DMs define the DM for each subproblem. 2064 2065 Not collective 2066 2067 Input Parameter: 2068 . dm - the DM object 2069 2070 Output Parameters: 2071 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 2072 . namelist - The name for each subdomain (or NULL if not requested) 2073 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 2074 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 2075 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 2076 2077 Level: intermediate 2078 2079 Notes: 2080 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 2081 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 2082 and all of the arrays should be freed with PetscFree(). 2083 2084 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldDecomposition() 2085 @*/ 2086 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 2087 { 2088 PetscErrorCode ierr; 2089 DMSubDomainHookLink link; 2090 PetscInt i,l; 2091 2092 PetscFunctionBegin; 2093 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2094 if (len) {PetscValidPointer(len,2); *len = 0;} 2095 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 2096 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 2097 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 2098 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 2099 /* 2100 Is it a good idea to apply the following check across all impls? 2101 Perhaps some impls can have a well-defined decomposition before DMSetUp? 2102 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 2103 */ 2104 PetscCheckFalse(!dm->setupcalled,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 2105 if (dm->ops->createdomaindecomposition) { 2106 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 2107 /* copy subdomain hooks and context over to the subdomain DMs */ 2108 if (dmlist && *dmlist) { 2109 for (i = 0; i < l; i++) { 2110 for (link=dm->subdomainhook; link; link=link->next) { 2111 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 2112 } 2113 if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx; 2114 } 2115 } 2116 if (len) *len = l; 2117 } 2118 PetscFunctionReturn(0); 2119 } 2120 2121 /*@C 2122 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 2123 2124 Not collective 2125 2126 Input Parameters: 2127 + dm - the DM object 2128 . n - the number of subdomain scatters 2129 - subdms - the local subdomains 2130 2131 Output Parameters: 2132 + iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 2133 . oscat - scatter from global vector to overlapping global vector entries on subdomain 2134 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 2135 2136 Notes: 2137 This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 2138 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 2139 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 2140 solution and residual data. 2141 2142 Level: developer 2143 2144 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 2145 @*/ 2146 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 2147 { 2148 PetscErrorCode ierr; 2149 2150 PetscFunctionBegin; 2151 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2152 PetscValidPointer(subdms,3); 2153 PetscCheckFalse(!dm->ops->createddscatters,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateDomainDecompositionScatters",((PetscObject)dm)->type_name); 2154 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 2155 PetscFunctionReturn(0); 2156 } 2157 2158 /*@ 2159 DMRefine - Refines a DM object 2160 2161 Collective on dm 2162 2163 Input Parameters: 2164 + dm - the DM object 2165 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2166 2167 Output Parameter: 2168 . dmf - the refined DM, or NULL 2169 2170 Options Database Keys: 2171 . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex 2172 2173 Note: If no refinement was done, the return value is NULL 2174 2175 Level: developer 2176 2177 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2178 @*/ 2179 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 2180 { 2181 PetscErrorCode ierr; 2182 DMRefineHookLink link; 2183 2184 PetscFunctionBegin; 2185 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2186 PetscCheckFalse(!dm->ops->refine,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMRefine",((PetscObject)dm)->type_name); 2187 ierr = PetscLogEventBegin(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 2188 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 2189 if (*dmf) { 2190 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 2191 2192 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 2193 2194 (*dmf)->ctx = dm->ctx; 2195 (*dmf)->leveldown = dm->leveldown; 2196 (*dmf)->levelup = dm->levelup + 1; 2197 2198 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 2199 for (link=dm->refinehook; link; link=link->next) { 2200 if (link->refinehook) { 2201 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 2202 } 2203 } 2204 } 2205 ierr = PetscLogEventEnd(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 2206 PetscFunctionReturn(0); 2207 } 2208 2209 /*@C 2210 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 2211 2212 Logically Collective 2213 2214 Input Parameters: 2215 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 2216 . refinehook - function to run when setting up a coarser level 2217 . interphook - function to run to update data on finer levels (once per SNESSolve()) 2218 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2219 2220 Calling sequence of refinehook: 2221 $ refinehook(DM coarse,DM fine,void *ctx); 2222 2223 + coarse - coarse level DM 2224 . fine - fine level DM to interpolate problem to 2225 - ctx - optional user-defined function context 2226 2227 Calling sequence for interphook: 2228 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 2229 2230 + coarse - coarse level DM 2231 . interp - matrix interpolating a coarse-level solution to the finer grid 2232 . fine - fine level DM to update 2233 - ctx - optional user-defined function context 2234 2235 Level: advanced 2236 2237 Notes: 2238 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 2239 2240 If this function is called multiple times, the hooks will be run in the order they are added. 2241 2242 This function is currently not available from Fortran. 2243 2244 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2245 @*/ 2246 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 2247 { 2248 PetscErrorCode ierr; 2249 DMRefineHookLink link,*p; 2250 2251 PetscFunctionBegin; 2252 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 2253 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2254 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2255 } 2256 ierr = PetscNew(&link);CHKERRQ(ierr); 2257 link->refinehook = refinehook; 2258 link->interphook = interphook; 2259 link->ctx = ctx; 2260 link->next = NULL; 2261 *p = link; 2262 PetscFunctionReturn(0); 2263 } 2264 2265 /*@C 2266 DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid 2267 2268 Logically Collective 2269 2270 Input Parameters: 2271 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 2272 . refinehook - function to run when setting up a coarser level 2273 . interphook - function to run to update data on finer levels (once per SNESSolve()) 2274 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2275 2276 Level: advanced 2277 2278 Notes: 2279 This function does nothing if the hook is not in the list. 2280 2281 This function is currently not available from Fortran. 2282 2283 .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2284 @*/ 2285 PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 2286 { 2287 PetscErrorCode ierr; 2288 DMRefineHookLink link,*p; 2289 2290 PetscFunctionBegin; 2291 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 2292 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2293 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) { 2294 link = *p; 2295 *p = link->next; 2296 ierr = PetscFree(link);CHKERRQ(ierr); 2297 break; 2298 } 2299 } 2300 PetscFunctionReturn(0); 2301 } 2302 2303 /*@ 2304 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 2305 2306 Collective if any hooks are 2307 2308 Input Parameters: 2309 + coarse - coarser DM to use as a base 2310 . interp - interpolation matrix, apply using MatInterpolate() 2311 - fine - finer DM to update 2312 2313 Level: developer 2314 2315 .seealso: DMRefineHookAdd(), MatInterpolate() 2316 @*/ 2317 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 2318 { 2319 PetscErrorCode ierr; 2320 DMRefineHookLink link; 2321 2322 PetscFunctionBegin; 2323 for (link=fine->refinehook; link; link=link->next) { 2324 if (link->interphook) { 2325 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 2326 } 2327 } 2328 PetscFunctionReturn(0); 2329 } 2330 2331 /*@ 2332 DMInterpolateSolution - Interpolates a solution from a coarse mesh to a fine mesh. 2333 2334 Collective on DM 2335 2336 Input Parameters: 2337 + coarse - coarse DM 2338 . fine - fine DM 2339 . interp - (optional) the matrix computed by DMCreateInterpolation(). Implementations may not need this, but if it 2340 is available it can avoid some recomputation. If it is provided, MatInterpolate() will be used if 2341 the coarse DM does not have a specialized implementation. 2342 - coarseSol - solution on the coarse mesh 2343 2344 Output Parameter: 2345 . fineSol - the interpolation of coarseSol to the fine mesh 2346 2347 Level: developer 2348 2349 Note: This function exists because the interpolation of a solution vector between meshes is not always a linear 2350 map. For example, if a boundary value problem has an inhomogeneous Dirichlet boundary condition that is compressed 2351 out of the solution vector. Or if interpolation is inherently a nonlinear operation, such as a method using 2352 slope-limiting reconstruction. 2353 2354 .seealso DMInterpolate(), DMCreateInterpolation() 2355 @*/ 2356 PetscErrorCode DMInterpolateSolution(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 2357 { 2358 PetscErrorCode (*interpsol)(DM,DM,Mat,Vec,Vec) = NULL; 2359 PetscErrorCode ierr; 2360 2361 PetscFunctionBegin; 2362 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 2363 if (interp) PetscValidHeaderSpecific(interp,MAT_CLASSID,3); 2364 PetscValidHeaderSpecific(coarseSol,VEC_CLASSID,4); 2365 PetscValidHeaderSpecific(fineSol,VEC_CLASSID,5); 2366 2367 ierr = PetscObjectQueryFunction((PetscObject)coarse,"DMInterpolateSolution_C", &interpsol);CHKERRQ(ierr); 2368 if (interpsol) { 2369 ierr = (*interpsol)(coarse, fine, interp, coarseSol, fineSol);CHKERRQ(ierr); 2370 } else if (interp) { 2371 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 2372 } else SETERRQ(PetscObjectComm((PetscObject)coarse), PETSC_ERR_SUP, "DM %s does not implement DMInterpolateSolution()", ((PetscObject)coarse)->type_name); 2373 PetscFunctionReturn(0); 2374 } 2375 2376 /*@ 2377 DMGetRefineLevel - Gets the number of refinements that have generated this DM. 2378 2379 Not Collective 2380 2381 Input Parameter: 2382 . dm - the DM object 2383 2384 Output Parameter: 2385 . level - number of refinements 2386 2387 Level: developer 2388 2389 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2390 2391 @*/ 2392 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 2393 { 2394 PetscFunctionBegin; 2395 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2396 *level = dm->levelup; 2397 PetscFunctionReturn(0); 2398 } 2399 2400 /*@ 2401 DMSetRefineLevel - Sets the number of refinements that have generated this DM. 2402 2403 Not Collective 2404 2405 Input Parameters: 2406 + dm - the DM object 2407 - level - number of refinements 2408 2409 Level: advanced 2410 2411 Notes: 2412 This value is used by PCMG to determine how many multigrid levels to use 2413 2414 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2415 2416 @*/ 2417 PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level) 2418 { 2419 PetscFunctionBegin; 2420 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2421 dm->levelup = level; 2422 PetscFunctionReturn(0); 2423 } 2424 2425 /*@ 2426 DMExtrude - Extrude a DM object from a surface 2427 2428 Collective on dm 2429 2430 Input Parameters: 2431 + dm - the DM object 2432 - layers - the number of extruded cell layers 2433 2434 Output Parameter: 2435 . dme - the extruded DM, or NULL 2436 2437 Note: If no extrusion was done, the return value is NULL 2438 2439 Level: developer 2440 2441 .seealso DMRefine(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector() 2442 @*/ 2443 PetscErrorCode DMExtrude(DM dm, PetscInt layers, DM *dme) 2444 { 2445 PetscErrorCode ierr; 2446 2447 PetscFunctionBegin; 2448 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2449 PetscCheckFalse(!dm->ops->extrude,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "DM type %s does not implement DMExtrude", ((PetscObject) dm)->type_name); 2450 ierr = (*dm->ops->extrude)(dm, layers, dme);CHKERRQ(ierr); 2451 if (*dme) { 2452 (*dme)->ops->creatematrix = dm->ops->creatematrix; 2453 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject) dm, (PetscObject) *dme);CHKERRQ(ierr); 2454 (*dme)->ctx = dm->ctx; 2455 ierr = DMSetMatType(*dme, dm->mattype);CHKERRQ(ierr); 2456 } 2457 PetscFunctionReturn(0); 2458 } 2459 2460 PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm) 2461 { 2462 PetscFunctionBegin; 2463 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2464 PetscValidPointer(tdm, 2); 2465 *tdm = dm->transformDM; 2466 PetscFunctionReturn(0); 2467 } 2468 2469 PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv) 2470 { 2471 PetscFunctionBegin; 2472 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2473 PetscValidPointer(tv, 2); 2474 *tv = dm->transform; 2475 PetscFunctionReturn(0); 2476 } 2477 2478 /*@ 2479 DMHasBasisTransform - Whether we employ a basis transformation from functions in global vectors to functions in local vectors 2480 2481 Input Parameter: 2482 . dm - The DM 2483 2484 Output Parameter: 2485 . flg - PETSC_TRUE if a basis transformation should be done 2486 2487 Level: developer 2488 2489 .seealso: DMPlexGlobalToLocalBasis(), DMPlexLocalToGlobalBasis(), DMPlexCreateBasisRotation() 2490 @*/ 2491 PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg) 2492 { 2493 Vec tv; 2494 PetscErrorCode ierr; 2495 2496 PetscFunctionBegin; 2497 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2498 PetscValidBoolPointer(flg, 2); 2499 ierr = DMGetBasisTransformVec_Internal(dm, &tv);CHKERRQ(ierr); 2500 *flg = tv ? PETSC_TRUE : PETSC_FALSE; 2501 PetscFunctionReturn(0); 2502 } 2503 2504 PetscErrorCode DMConstructBasisTransform_Internal(DM dm) 2505 { 2506 PetscSection s, ts; 2507 PetscScalar *ta; 2508 PetscInt cdim, pStart, pEnd, p, Nf, f, Nc, dof; 2509 PetscErrorCode ierr; 2510 2511 PetscFunctionBegin; 2512 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 2513 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 2514 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2515 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 2516 ierr = DMClone(dm, &dm->transformDM);CHKERRQ(ierr); 2517 ierr = DMGetLocalSection(dm->transformDM, &ts);CHKERRQ(ierr); 2518 ierr = PetscSectionSetNumFields(ts, Nf);CHKERRQ(ierr); 2519 ierr = PetscSectionSetChart(ts, pStart, pEnd);CHKERRQ(ierr); 2520 for (f = 0; f < Nf; ++f) { 2521 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 2522 /* We could start to label fields by their transformation properties */ 2523 if (Nc != cdim) continue; 2524 for (p = pStart; p < pEnd; ++p) { 2525 ierr = PetscSectionGetFieldDof(s, p, f, &dof);CHKERRQ(ierr); 2526 if (!dof) continue; 2527 ierr = PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim));CHKERRQ(ierr); 2528 ierr = PetscSectionAddDof(ts, p, PetscSqr(cdim));CHKERRQ(ierr); 2529 } 2530 } 2531 ierr = PetscSectionSetUp(ts);CHKERRQ(ierr); 2532 ierr = DMCreateLocalVector(dm->transformDM, &dm->transform);CHKERRQ(ierr); 2533 ierr = VecGetArray(dm->transform, &ta);CHKERRQ(ierr); 2534 for (p = pStart; p < pEnd; ++p) { 2535 for (f = 0; f < Nf; ++f) { 2536 ierr = PetscSectionGetFieldDof(ts, p, f, &dof);CHKERRQ(ierr); 2537 if (dof) { 2538 PetscReal x[3] = {0.0, 0.0, 0.0}; 2539 PetscScalar *tva; 2540 const PetscScalar *A; 2541 2542 /* TODO Get quadrature point for this dual basis vector for coordinate */ 2543 ierr = (*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx);CHKERRQ(ierr); 2544 ierr = DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *) &tva);CHKERRQ(ierr); 2545 ierr = PetscArraycpy(tva, A, PetscSqr(cdim));CHKERRQ(ierr); 2546 } 2547 } 2548 } 2549 ierr = VecRestoreArray(dm->transform, &ta);CHKERRQ(ierr); 2550 PetscFunctionReturn(0); 2551 } 2552 2553 PetscErrorCode DMCopyTransform(DM dm, DM newdm) 2554 { 2555 PetscErrorCode ierr; 2556 2557 PetscFunctionBegin; 2558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2559 PetscValidHeaderSpecific(newdm, DM_CLASSID, 2); 2560 newdm->transformCtx = dm->transformCtx; 2561 newdm->transformSetUp = dm->transformSetUp; 2562 newdm->transformDestroy = NULL; 2563 newdm->transformGetMatrix = dm->transformGetMatrix; 2564 if (newdm->transformSetUp) {ierr = DMConstructBasisTransform_Internal(newdm);CHKERRQ(ierr);} 2565 PetscFunctionReturn(0); 2566 } 2567 2568 /*@C 2569 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 2570 2571 Logically Collective 2572 2573 Input Parameters: 2574 + dm - the DM 2575 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 2576 . endhook - function to run after DMGlobalToLocalEnd() has completed 2577 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2578 2579 Calling sequence for beginhook: 2580 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 2581 2582 + dm - global DM 2583 . g - global vector 2584 . mode - mode 2585 . l - local vector 2586 - ctx - optional user-defined function context 2587 2588 Calling sequence for endhook: 2589 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 2590 2591 + global - global DM 2592 - ctx - optional user-defined function context 2593 2594 Level: advanced 2595 2596 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2597 @*/ 2598 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2599 { 2600 PetscErrorCode ierr; 2601 DMGlobalToLocalHookLink link,*p; 2602 2603 PetscFunctionBegin; 2604 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2605 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2606 ierr = PetscNew(&link);CHKERRQ(ierr); 2607 link->beginhook = beginhook; 2608 link->endhook = endhook; 2609 link->ctx = ctx; 2610 link->next = NULL; 2611 *p = link; 2612 PetscFunctionReturn(0); 2613 } 2614 2615 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 2616 { 2617 Mat cMat; 2618 Vec cVec, cBias; 2619 PetscSection section, cSec; 2620 PetscInt pStart, pEnd, p, dof; 2621 PetscErrorCode ierr; 2622 2623 PetscFunctionBegin; 2624 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2625 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat,&cBias);CHKERRQ(ierr); 2626 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 2627 PetscInt nRows; 2628 2629 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2630 if (nRows <= 0) PetscFunctionReturn(0); 2631 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2632 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2633 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 2634 if (cBias) {ierr = VecAXPY(cVec,1.,cBias);CHKERRQ(ierr);} 2635 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2636 for (p = pStart; p < pEnd; p++) { 2637 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2638 if (dof) { 2639 PetscScalar *vals; 2640 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 2641 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 2642 } 2643 } 2644 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2645 } 2646 PetscFunctionReturn(0); 2647 } 2648 2649 /*@ 2650 DMGlobalToLocal - update local vectors from global vector 2651 2652 Neighbor-wise Collective on dm 2653 2654 Input Parameters: 2655 + dm - the DM object 2656 . g - the global vector 2657 . mode - INSERT_VALUES or ADD_VALUES 2658 - l - the local vector 2659 2660 Notes: 2661 The communication involved in this update can be overlapped with computation by using 2662 DMGlobalToLocalBegin() and DMGlobalToLocalEnd(). 2663 2664 Level: beginner 2665 2666 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2667 2668 @*/ 2669 PetscErrorCode DMGlobalToLocal(DM dm,Vec g,InsertMode mode,Vec l) 2670 { 2671 PetscErrorCode ierr; 2672 2673 PetscFunctionBegin; 2674 ierr = DMGlobalToLocalBegin(dm,g,mode,l);CHKERRQ(ierr); 2675 ierr = DMGlobalToLocalEnd(dm,g,mode,l);CHKERRQ(ierr); 2676 PetscFunctionReturn(0); 2677 } 2678 2679 /*@ 2680 DMGlobalToLocalBegin - Begins updating local vectors from global vector 2681 2682 Neighbor-wise Collective on dm 2683 2684 Input Parameters: 2685 + dm - the DM object 2686 . g - the global vector 2687 . mode - INSERT_VALUES or ADD_VALUES 2688 - l - the local vector 2689 2690 Level: intermediate 2691 2692 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2693 2694 @*/ 2695 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2696 { 2697 PetscSF sf; 2698 PetscErrorCode ierr; 2699 DMGlobalToLocalHookLink link; 2700 2701 PetscFunctionBegin; 2702 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2703 for (link=dm->gtolhook; link; link=link->next) { 2704 if (link->beginhook) { 2705 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 2706 } 2707 } 2708 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 2709 if (sf) { 2710 const PetscScalar *gArray; 2711 PetscScalar *lArray; 2712 PetscMemType lmtype,gmtype; 2713 2714 PetscCheckFalse(mode == ADD_VALUES,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2715 ierr = VecGetArrayAndMemType(l, &lArray, &lmtype);CHKERRQ(ierr); 2716 ierr = VecGetArrayReadAndMemType(g, &gArray, &gmtype);CHKERRQ(ierr); 2717 ierr = PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray, MPI_REPLACE);CHKERRQ(ierr); 2718 ierr = VecRestoreArrayAndMemType(l, &lArray);CHKERRQ(ierr); 2719 ierr = VecRestoreArrayReadAndMemType(g, &gArray);CHKERRQ(ierr); 2720 } else { 2721 PetscCheckFalse(!dm->ops->globaltolocalbegin,PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalBegin() for type %s",((PetscObject)dm)->type_name); 2722 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2723 } 2724 PetscFunctionReturn(0); 2725 } 2726 2727 /*@ 2728 DMGlobalToLocalEnd - Ends updating local vectors from global vector 2729 2730 Neighbor-wise Collective on dm 2731 2732 Input Parameters: 2733 + dm - the DM object 2734 . g - the global vector 2735 . mode - INSERT_VALUES or ADD_VALUES 2736 - l - the local vector 2737 2738 Level: intermediate 2739 2740 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2741 2742 @*/ 2743 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2744 { 2745 PetscSF sf; 2746 PetscErrorCode ierr; 2747 const PetscScalar *gArray; 2748 PetscScalar *lArray; 2749 PetscBool transform; 2750 DMGlobalToLocalHookLink link; 2751 PetscMemType lmtype,gmtype; 2752 2753 PetscFunctionBegin; 2754 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2755 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 2756 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr); 2757 if (sf) { 2758 PetscCheckFalse(mode == ADD_VALUES,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2759 2760 ierr = VecGetArrayAndMemType(l, &lArray, &lmtype);CHKERRQ(ierr); 2761 ierr = VecGetArrayReadAndMemType(g, &gArray, &gmtype);CHKERRQ(ierr); 2762 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray,MPI_REPLACE);CHKERRQ(ierr); 2763 ierr = VecRestoreArrayAndMemType(l, &lArray);CHKERRQ(ierr); 2764 ierr = VecRestoreArrayReadAndMemType(g, &gArray);CHKERRQ(ierr); 2765 if (transform) {ierr = DMPlexGlobalToLocalBasis(dm, l);CHKERRQ(ierr);} 2766 } else { 2767 PetscCheckFalse(!dm->ops->globaltolocalend,PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalEnd() for type %s",((PetscObject)dm)->type_name); 2768 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2769 } 2770 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 2771 for (link=dm->gtolhook; link; link=link->next) { 2772 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2773 } 2774 PetscFunctionReturn(0); 2775 } 2776 2777 /*@C 2778 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 2779 2780 Logically Collective 2781 2782 Input Parameters: 2783 + dm - the DM 2784 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 2785 . endhook - function to run after DMLocalToGlobalEnd() has completed 2786 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2787 2788 Calling sequence for beginhook: 2789 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2790 2791 + dm - global DM 2792 . l - local vector 2793 . mode - mode 2794 . g - global vector 2795 - ctx - optional user-defined function context 2796 2797 Calling sequence for endhook: 2798 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2799 2800 + global - global DM 2801 . l - local vector 2802 . mode - mode 2803 . g - global vector 2804 - ctx - optional user-defined function context 2805 2806 Level: advanced 2807 2808 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2809 @*/ 2810 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2811 { 2812 PetscErrorCode ierr; 2813 DMLocalToGlobalHookLink link,*p; 2814 2815 PetscFunctionBegin; 2816 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2817 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2818 ierr = PetscNew(&link);CHKERRQ(ierr); 2819 link->beginhook = beginhook; 2820 link->endhook = endhook; 2821 link->ctx = ctx; 2822 link->next = NULL; 2823 *p = link; 2824 PetscFunctionReturn(0); 2825 } 2826 2827 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 2828 { 2829 Mat cMat; 2830 Vec cVec; 2831 PetscSection section, cSec; 2832 PetscInt pStart, pEnd, p, dof; 2833 PetscErrorCode ierr; 2834 2835 PetscFunctionBegin; 2836 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2837 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat,NULL);CHKERRQ(ierr); 2838 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 2839 PetscInt nRows; 2840 2841 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2842 if (nRows <= 0) PetscFunctionReturn(0); 2843 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2844 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2845 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2846 for (p = pStart; p < pEnd; p++) { 2847 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2848 if (dof) { 2849 PetscInt d; 2850 PetscScalar *vals; 2851 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 2852 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 2853 /* for this to be the true transpose, we have to zero the values that 2854 * we just extracted */ 2855 for (d = 0; d < dof; d++) { 2856 vals[d] = 0.; 2857 } 2858 } 2859 } 2860 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 2861 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2862 } 2863 PetscFunctionReturn(0); 2864 } 2865 /*@ 2866 DMLocalToGlobal - updates global vectors from local vectors 2867 2868 Neighbor-wise Collective on dm 2869 2870 Input Parameters: 2871 + dm - the DM object 2872 . l - the local vector 2873 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point. 2874 - g - the global vector 2875 2876 Notes: 2877 The communication involved in this update can be overlapped with computation by using 2878 DMLocalToGlobalBegin() and DMLocalToGlobalEnd(). 2879 2880 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2881 INSERT_VALUES is not supported for DMDA; in that case simply compute the values directly into a global vector instead of a local one. 2882 2883 Level: beginner 2884 2885 .seealso DMLocalToGlobalBegin(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2886 2887 @*/ 2888 PetscErrorCode DMLocalToGlobal(DM dm,Vec l,InsertMode mode,Vec g) 2889 { 2890 PetscErrorCode ierr; 2891 2892 PetscFunctionBegin; 2893 ierr = DMLocalToGlobalBegin(dm,l,mode,g);CHKERRQ(ierr); 2894 ierr = DMLocalToGlobalEnd(dm,l,mode,g);CHKERRQ(ierr); 2895 PetscFunctionReturn(0); 2896 } 2897 2898 /*@ 2899 DMLocalToGlobalBegin - begins updating global vectors from local vectors 2900 2901 Neighbor-wise Collective on dm 2902 2903 Input Parameters: 2904 + dm - the DM object 2905 . l - the local vector 2906 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point. 2907 - g - the global vector 2908 2909 Notes: 2910 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2911 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 2912 2913 Level: intermediate 2914 2915 .seealso DMLocalToGlobal(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2916 2917 @*/ 2918 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 2919 { 2920 PetscSF sf; 2921 PetscSection s, gs; 2922 DMLocalToGlobalHookLink link; 2923 Vec tmpl; 2924 const PetscScalar *lArray; 2925 PetscScalar *gArray; 2926 PetscBool isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE; 2927 PetscErrorCode ierr; 2928 PetscMemType lmtype=PETSC_MEMTYPE_HOST,gmtype=PETSC_MEMTYPE_HOST; 2929 2930 PetscFunctionBegin; 2931 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2932 for (link=dm->ltoghook; link; link=link->next) { 2933 if (link->beginhook) { 2934 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 2935 } 2936 } 2937 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 2938 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 2939 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 2940 switch (mode) { 2941 case INSERT_VALUES: 2942 case INSERT_ALL_VALUES: 2943 case INSERT_BC_VALUES: 2944 isInsert = PETSC_TRUE; break; 2945 case ADD_VALUES: 2946 case ADD_ALL_VALUES: 2947 case ADD_BC_VALUES: 2948 isInsert = PETSC_FALSE; break; 2949 default: 2950 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2951 } 2952 if ((sf && !isInsert) || (s && isInsert)) { 2953 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr); 2954 if (transform) { 2955 ierr = DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 2956 ierr = VecCopy(l, tmpl);CHKERRQ(ierr); 2957 ierr = DMPlexLocalToGlobalBasis(dm, tmpl);CHKERRQ(ierr); 2958 ierr = VecGetArrayRead(tmpl, &lArray);CHKERRQ(ierr); 2959 } else if (isInsert) { 2960 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2961 } else { 2962 ierr = VecGetArrayReadAndMemType(l, &lArray, &lmtype);CHKERRQ(ierr); 2963 l_inplace = PETSC_TRUE; 2964 } 2965 if (s && isInsert) { 2966 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2967 } else { 2968 ierr = VecGetArrayAndMemType(g, &gArray, &gmtype);CHKERRQ(ierr); 2969 g_inplace = PETSC_TRUE; 2970 } 2971 if (sf && !isInsert) { 2972 ierr = PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM);CHKERRQ(ierr); 2973 } else if (s && isInsert) { 2974 PetscInt gStart, pStart, pEnd, p; 2975 2976 ierr = DMGetGlobalSection(dm, &gs);CHKERRQ(ierr); 2977 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2978 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2979 for (p = pStart; p < pEnd; ++p) { 2980 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2981 2982 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2983 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2984 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2985 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2986 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2987 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2988 /* Ignore off-process data and points with no global data */ 2989 if (!gdof || goff < 0) continue; 2990 PetscCheckFalse(dof != gdof,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 2991 /* If no constraints are enforced in the global vector */ 2992 if (!gcdof) { 2993 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2994 /* If constraints are enforced in the global vector */ 2995 } else if (cdof == gcdof) { 2996 const PetscInt *cdofs; 2997 PetscInt cind = 0; 2998 2999 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 3000 for (d = 0, e = 0; d < dof; ++d) { 3001 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 3002 gArray[goff-gStart+e++] = lArray[off+d]; 3003 } 3004 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 3005 } 3006 } 3007 if (g_inplace) { 3008 ierr = VecRestoreArrayAndMemType(g, &gArray);CHKERRQ(ierr); 3009 } else { 3010 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 3011 } 3012 if (transform) { 3013 ierr = VecRestoreArrayRead(tmpl, &lArray);CHKERRQ(ierr); 3014 ierr = DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 3015 } else if (l_inplace) { 3016 ierr = VecRestoreArrayReadAndMemType(l, &lArray);CHKERRQ(ierr); 3017 } else { 3018 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 3019 } 3020 } else { 3021 PetscCheckFalse(!dm->ops->localtoglobalbegin,PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalBegin() for type %s",((PetscObject)dm)->type_name); 3022 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 3023 } 3024 PetscFunctionReturn(0); 3025 } 3026 3027 /*@ 3028 DMLocalToGlobalEnd - updates global vectors from local vectors 3029 3030 Neighbor-wise Collective on dm 3031 3032 Input Parameters: 3033 + dm - the DM object 3034 . l - the local vector 3035 . mode - INSERT_VALUES or ADD_VALUES 3036 - g - the global vector 3037 3038 Level: intermediate 3039 3040 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 3041 3042 @*/ 3043 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 3044 { 3045 PetscSF sf; 3046 PetscSection s; 3047 DMLocalToGlobalHookLink link; 3048 PetscBool isInsert, transform; 3049 PetscErrorCode ierr; 3050 3051 PetscFunctionBegin; 3052 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3053 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 3054 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 3055 switch (mode) { 3056 case INSERT_VALUES: 3057 case INSERT_ALL_VALUES: 3058 isInsert = PETSC_TRUE; break; 3059 case ADD_VALUES: 3060 case ADD_ALL_VALUES: 3061 isInsert = PETSC_FALSE; break; 3062 default: 3063 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 3064 } 3065 if (sf && !isInsert) { 3066 const PetscScalar *lArray; 3067 PetscScalar *gArray; 3068 Vec tmpl; 3069 3070 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr); 3071 if (transform) { 3072 ierr = DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 3073 ierr = VecGetArrayRead(tmpl, &lArray);CHKERRQ(ierr); 3074 } else { 3075 ierr = VecGetArrayReadAndMemType(l, &lArray, NULL);CHKERRQ(ierr); 3076 } 3077 ierr = VecGetArrayAndMemType(g, &gArray, NULL);CHKERRQ(ierr); 3078 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 3079 if (transform) { 3080 ierr = VecRestoreArrayRead(tmpl, &lArray);CHKERRQ(ierr); 3081 ierr = DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 3082 } else { 3083 ierr = VecRestoreArrayReadAndMemType(l, &lArray);CHKERRQ(ierr); 3084 } 3085 ierr = VecRestoreArrayAndMemType(g, &gArray);CHKERRQ(ierr); 3086 } else if (s && isInsert) { 3087 } else { 3088 PetscCheckFalse(!dm->ops->localtoglobalend,PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalEnd() for type %s",((PetscObject)dm)->type_name); 3089 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 3090 } 3091 for (link=dm->ltoghook; link; link=link->next) { 3092 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 3093 } 3094 PetscFunctionReturn(0); 3095 } 3096 3097 /*@ 3098 DMLocalToLocalBegin - Maps from a local vector (including ghost points 3099 that contain irrelevant values) to another local vector where the ghost 3100 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 3101 3102 Neighbor-wise Collective on dm 3103 3104 Input Parameters: 3105 + dm - the DM object 3106 . g - the original local vector 3107 - mode - one of INSERT_VALUES or ADD_VALUES 3108 3109 Output Parameter: 3110 . l - the local vector with correct ghost values 3111 3112 Level: intermediate 3113 3114 Notes: 3115 The local vectors used here need not be the same as those 3116 obtained from DMCreateLocalVector(), BUT they 3117 must have the same parallel data layout; they could, for example, be 3118 obtained with VecDuplicate() from the DM originating vectors. 3119 3120 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 3121 3122 @*/ 3123 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 3124 { 3125 PetscErrorCode ierr; 3126 3127 PetscFunctionBegin; 3128 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3129 PetscCheckFalse(!dm->ops->localtolocalbegin,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 3130 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 3131 PetscFunctionReturn(0); 3132 } 3133 3134 /*@ 3135 DMLocalToLocalEnd - Maps from a local vector (including ghost points 3136 that contain irrelevant values) to another local vector where the ghost 3137 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 3138 3139 Neighbor-wise Collective on dm 3140 3141 Input Parameters: 3142 + da - the DM object 3143 . g - the original local vector 3144 - mode - one of INSERT_VALUES or ADD_VALUES 3145 3146 Output Parameter: 3147 . l - the local vector with correct ghost values 3148 3149 Level: intermediate 3150 3151 Notes: 3152 The local vectors used here need not be the same as those 3153 obtained from DMCreateLocalVector(), BUT they 3154 must have the same parallel data layout; they could, for example, be 3155 obtained with VecDuplicate() from the DM originating vectors. 3156 3157 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 3158 3159 @*/ 3160 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 3161 { 3162 PetscErrorCode ierr; 3163 3164 PetscFunctionBegin; 3165 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3166 PetscCheckFalse(!dm->ops->localtolocalend,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 3167 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 3168 PetscFunctionReturn(0); 3169 } 3170 3171 /*@ 3172 DMCoarsen - Coarsens a DM object 3173 3174 Collective on dm 3175 3176 Input Parameters: 3177 + dm - the DM object 3178 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 3179 3180 Output Parameter: 3181 . dmc - the coarsened DM 3182 3183 Level: developer 3184 3185 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3186 3187 @*/ 3188 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 3189 { 3190 PetscErrorCode ierr; 3191 DMCoarsenHookLink link; 3192 3193 PetscFunctionBegin; 3194 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3195 PetscCheckFalse(!dm->ops->coarsen,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCoarsen",((PetscObject)dm)->type_name); 3196 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 3197 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 3198 if (*dmc) { 3199 (*dmc)->bind_below = dm->bind_below; /* Propagate this from parent DM; otherwise -dm_bind_below will be useless for multigrid cases. */ 3200 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 3201 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 3202 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 3203 (*dmc)->ctx = dm->ctx; 3204 (*dmc)->levelup = dm->levelup; 3205 (*dmc)->leveldown = dm->leveldown + 1; 3206 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 3207 for (link=dm->coarsenhook; link; link=link->next) { 3208 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 3209 } 3210 } 3211 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 3212 PetscCheckFalse(!(*dmc),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 3213 PetscFunctionReturn(0); 3214 } 3215 3216 /*@C 3217 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 3218 3219 Logically Collective 3220 3221 Input Parameters: 3222 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 3223 . coarsenhook - function to run when setting up a coarser level 3224 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 3225 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3226 3227 Calling sequence of coarsenhook: 3228 $ coarsenhook(DM fine,DM coarse,void *ctx); 3229 3230 + fine - fine level DM 3231 . coarse - coarse level DM to restrict problem to 3232 - ctx - optional user-defined function context 3233 3234 Calling sequence for restricthook: 3235 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 3236 3237 + fine - fine level DM 3238 . mrestrict - matrix restricting a fine-level solution to the coarse grid 3239 . rscale - scaling vector for restriction 3240 . inject - matrix restricting by injection 3241 . coarse - coarse level DM to update 3242 - ctx - optional user-defined function context 3243 3244 Level: advanced 3245 3246 Notes: 3247 This function is only needed if auxiliary data needs to be set up on coarse grids. 3248 3249 If this function is called multiple times, the hooks will be run in the order they are added. 3250 3251 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 3252 extract the finest level information from its context (instead of from the SNES). 3253 3254 This function is currently not available from Fortran. 3255 3256 .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3257 @*/ 3258 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 3259 { 3260 PetscErrorCode ierr; 3261 DMCoarsenHookLink link,*p; 3262 3263 PetscFunctionBegin; 3264 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 3265 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 3266 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 3267 } 3268 ierr = PetscNew(&link);CHKERRQ(ierr); 3269 link->coarsenhook = coarsenhook; 3270 link->restricthook = restricthook; 3271 link->ctx = ctx; 3272 link->next = NULL; 3273 *p = link; 3274 PetscFunctionReturn(0); 3275 } 3276 3277 /*@C 3278 DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid 3279 3280 Logically Collective 3281 3282 Input Parameters: 3283 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 3284 . coarsenhook - function to run when setting up a coarser level 3285 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 3286 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3287 3288 Level: advanced 3289 3290 Notes: 3291 This function does nothing if the hook is not in the list. 3292 3293 This function is currently not available from Fortran. 3294 3295 .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3296 @*/ 3297 PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 3298 { 3299 PetscErrorCode ierr; 3300 DMCoarsenHookLink link,*p; 3301 3302 PetscFunctionBegin; 3303 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 3304 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 3305 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 3306 link = *p; 3307 *p = link->next; 3308 ierr = PetscFree(link);CHKERRQ(ierr); 3309 break; 3310 } 3311 } 3312 PetscFunctionReturn(0); 3313 } 3314 3315 /*@ 3316 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 3317 3318 Collective if any hooks are 3319 3320 Input Parameters: 3321 + fine - finer DM to use as a base 3322 . restrct - restriction matrix, apply using MatRestrict() 3323 . rscale - scaling vector for restriction 3324 . inject - injection matrix, also use MatRestrict() 3325 - coarse - coarser DM to update 3326 3327 Level: developer 3328 3329 .seealso: DMCoarsenHookAdd(), MatRestrict() 3330 @*/ 3331 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 3332 { 3333 PetscErrorCode ierr; 3334 DMCoarsenHookLink link; 3335 3336 PetscFunctionBegin; 3337 for (link=fine->coarsenhook; link; link=link->next) { 3338 if (link->restricthook) { 3339 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 3340 } 3341 } 3342 PetscFunctionReturn(0); 3343 } 3344 3345 /*@C 3346 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 3347 3348 Logically Collective on global 3349 3350 Input Parameters: 3351 + global - global DM 3352 . ddhook - function to run to pass data to the decomposition DM upon its creation 3353 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 3354 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3355 3356 Calling sequence for ddhook: 3357 $ ddhook(DM global,DM block,void *ctx) 3358 3359 + global - global DM 3360 . block - block DM 3361 - ctx - optional user-defined function context 3362 3363 Calling sequence for restricthook: 3364 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 3365 3366 + global - global DM 3367 . out - scatter to the outer (with ghost and overlap points) block vector 3368 . in - scatter to block vector values only owned locally 3369 . block - block DM 3370 - ctx - optional user-defined function context 3371 3372 Level: advanced 3373 3374 Notes: 3375 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 3376 3377 If this function is called multiple times, the hooks will be run in the order they are added. 3378 3379 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 3380 extract the global information from its context (instead of from the SNES). 3381 3382 This function is currently not available from Fortran. 3383 3384 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3385 @*/ 3386 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 3387 { 3388 PetscErrorCode ierr; 3389 DMSubDomainHookLink link,*p; 3390 3391 PetscFunctionBegin; 3392 PetscValidHeaderSpecific(global,DM_CLASSID,1); 3393 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 3394 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 3395 } 3396 ierr = PetscNew(&link);CHKERRQ(ierr); 3397 link->restricthook = restricthook; 3398 link->ddhook = ddhook; 3399 link->ctx = ctx; 3400 link->next = NULL; 3401 *p = link; 3402 PetscFunctionReturn(0); 3403 } 3404 3405 /*@C 3406 DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid 3407 3408 Logically Collective 3409 3410 Input Parameters: 3411 + global - global DM 3412 . ddhook - function to run to pass data to the decomposition DM upon its creation 3413 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 3414 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3415 3416 Level: advanced 3417 3418 Notes: 3419 3420 This function is currently not available from Fortran. 3421 3422 .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3423 @*/ 3424 PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 3425 { 3426 PetscErrorCode ierr; 3427 DMSubDomainHookLink link,*p; 3428 3429 PetscFunctionBegin; 3430 PetscValidHeaderSpecific(global,DM_CLASSID,1); 3431 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 3432 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 3433 link = *p; 3434 *p = link->next; 3435 ierr = PetscFree(link);CHKERRQ(ierr); 3436 break; 3437 } 3438 } 3439 PetscFunctionReturn(0); 3440 } 3441 3442 /*@ 3443 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 3444 3445 Collective if any hooks are 3446 3447 Input Parameters: 3448 + fine - finer DM to use as a base 3449 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 3450 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 3451 - coarse - coarer DM to update 3452 3453 Level: developer 3454 3455 .seealso: DMCoarsenHookAdd(), MatRestrict() 3456 @*/ 3457 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 3458 { 3459 PetscErrorCode ierr; 3460 DMSubDomainHookLink link; 3461 3462 PetscFunctionBegin; 3463 for (link=global->subdomainhook; link; link=link->next) { 3464 if (link->restricthook) { 3465 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 3466 } 3467 } 3468 PetscFunctionReturn(0); 3469 } 3470 3471 /*@ 3472 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 3473 3474 Not Collective 3475 3476 Input Parameter: 3477 . dm - the DM object 3478 3479 Output Parameter: 3480 . level - number of coarsenings 3481 3482 Level: developer 3483 3484 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3485 3486 @*/ 3487 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 3488 { 3489 PetscFunctionBegin; 3490 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3491 PetscValidIntPointer(level,2); 3492 *level = dm->leveldown; 3493 PetscFunctionReturn(0); 3494 } 3495 3496 /*@ 3497 DMSetCoarsenLevel - Sets the number of coarsenings that have generated this DM. 3498 3499 Not Collective 3500 3501 Input Parameters: 3502 + dm - the DM object 3503 - level - number of coarsenings 3504 3505 Level: developer 3506 3507 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3508 @*/ 3509 PetscErrorCode DMSetCoarsenLevel(DM dm,PetscInt level) 3510 { 3511 PetscFunctionBegin; 3512 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3513 dm->leveldown = level; 3514 PetscFunctionReturn(0); 3515 } 3516 3517 /*@C 3518 DMRefineHierarchy - Refines a DM object, all levels at once 3519 3520 Collective on dm 3521 3522 Input Parameters: 3523 + dm - the DM object 3524 - nlevels - the number of levels of refinement 3525 3526 Output Parameter: 3527 . dmf - the refined DM hierarchy 3528 3529 Level: developer 3530 3531 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3532 3533 @*/ 3534 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 3535 { 3536 PetscErrorCode ierr; 3537 3538 PetscFunctionBegin; 3539 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3540 PetscCheckFalse(nlevels < 0,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 3541 if (nlevels == 0) PetscFunctionReturn(0); 3542 PetscValidPointer(dmf,3); 3543 if (dm->ops->refinehierarchy) { 3544 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 3545 } else if (dm->ops->refine) { 3546 PetscInt i; 3547 3548 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 3549 for (i=1; i<nlevels; i++) { 3550 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 3551 } 3552 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 3553 PetscFunctionReturn(0); 3554 } 3555 3556 /*@C 3557 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 3558 3559 Collective on dm 3560 3561 Input Parameters: 3562 + dm - the DM object 3563 - nlevels - the number of levels of coarsening 3564 3565 Output Parameter: 3566 . dmc - the coarsened DM hierarchy 3567 3568 Level: developer 3569 3570 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3571 3572 @*/ 3573 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 3574 { 3575 PetscErrorCode ierr; 3576 3577 PetscFunctionBegin; 3578 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3579 PetscCheckFalse(nlevels < 0,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 3580 if (nlevels == 0) PetscFunctionReturn(0); 3581 PetscValidPointer(dmc,3); 3582 if (dm->ops->coarsenhierarchy) { 3583 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 3584 } else if (dm->ops->coarsen) { 3585 PetscInt i; 3586 3587 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 3588 for (i=1; i<nlevels; i++) { 3589 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 3590 } 3591 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 3592 PetscFunctionReturn(0); 3593 } 3594 3595 /*@C 3596 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 3597 3598 Not Collective 3599 3600 Input Parameters: 3601 + dm - the DM object 3602 - destroy - the destroy function 3603 3604 Level: intermediate 3605 3606 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3607 3608 @*/ 3609 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 3610 { 3611 PetscFunctionBegin; 3612 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3613 dm->ctxdestroy = destroy; 3614 PetscFunctionReturn(0); 3615 } 3616 3617 /*@ 3618 DMSetApplicationContext - Set a user context into a DM object 3619 3620 Not Collective 3621 3622 Input Parameters: 3623 + dm - the DM object 3624 - ctx - the user context 3625 3626 Level: intermediate 3627 3628 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3629 3630 @*/ 3631 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 3632 { 3633 PetscFunctionBegin; 3634 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3635 dm->ctx = ctx; 3636 PetscFunctionReturn(0); 3637 } 3638 3639 /*@ 3640 DMGetApplicationContext - Gets a user context from a DM object 3641 3642 Not Collective 3643 3644 Input Parameter: 3645 . dm - the DM object 3646 3647 Output Parameter: 3648 . ctx - the user context 3649 3650 Level: intermediate 3651 3652 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3653 3654 @*/ 3655 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 3656 { 3657 PetscFunctionBegin; 3658 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3659 *(void**)ctx = dm->ctx; 3660 PetscFunctionReturn(0); 3661 } 3662 3663 /*@C 3664 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 3665 3666 Logically Collective on dm 3667 3668 Input Parameters: 3669 + dm - the DM object 3670 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 3671 3672 Level: intermediate 3673 3674 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 3675 DMSetJacobian() 3676 3677 @*/ 3678 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 3679 { 3680 PetscFunctionBegin; 3681 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3682 dm->ops->computevariablebounds = f; 3683 PetscFunctionReturn(0); 3684 } 3685 3686 /*@ 3687 DMHasVariableBounds - does the DM object have a variable bounds function? 3688 3689 Not Collective 3690 3691 Input Parameter: 3692 . dm - the DM object to destroy 3693 3694 Output Parameter: 3695 . flg - PETSC_TRUE if the variable bounds function exists 3696 3697 Level: developer 3698 3699 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3700 3701 @*/ 3702 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 3703 { 3704 PetscFunctionBegin; 3705 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3706 PetscValidBoolPointer(flg,2); 3707 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 3708 PetscFunctionReturn(0); 3709 } 3710 3711 /*@C 3712 DMComputeVariableBounds - compute variable bounds used by SNESVI. 3713 3714 Logically Collective on dm 3715 3716 Input Parameter: 3717 . dm - the DM object 3718 3719 Output parameters: 3720 + xl - lower bound 3721 - xu - upper bound 3722 3723 Level: advanced 3724 3725 Notes: 3726 This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 3727 3728 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3729 3730 @*/ 3731 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 3732 { 3733 PetscErrorCode ierr; 3734 3735 PetscFunctionBegin; 3736 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3737 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 3738 PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 3739 PetscCheckFalse(!dm->ops->computevariablebounds,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeVariableBounds",((PetscObject)dm)->type_name); 3740 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 3741 PetscFunctionReturn(0); 3742 } 3743 3744 /*@ 3745 DMHasColoring - does the DM object have a method of providing a coloring? 3746 3747 Not Collective 3748 3749 Input Parameter: 3750 . dm - the DM object 3751 3752 Output Parameter: 3753 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 3754 3755 Level: developer 3756 3757 .seealso DMCreateColoring() 3758 3759 @*/ 3760 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 3761 { 3762 PetscFunctionBegin; 3763 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3764 PetscValidBoolPointer(flg,2); 3765 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 3766 PetscFunctionReturn(0); 3767 } 3768 3769 /*@ 3770 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 3771 3772 Not Collective 3773 3774 Input Parameter: 3775 . dm - the DM object 3776 3777 Output Parameter: 3778 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 3779 3780 Level: developer 3781 3782 .seealso DMCreateRestriction() 3783 3784 @*/ 3785 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 3786 { 3787 PetscFunctionBegin; 3788 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3789 PetscValidBoolPointer(flg,2); 3790 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 3791 PetscFunctionReturn(0); 3792 } 3793 3794 /*@ 3795 DMHasCreateInjection - does the DM object have a method of providing an injection? 3796 3797 Not Collective 3798 3799 Input Parameter: 3800 . dm - the DM object 3801 3802 Output Parameter: 3803 . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection(). 3804 3805 Level: developer 3806 3807 .seealso DMCreateInjection() 3808 3809 @*/ 3810 PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg) 3811 { 3812 PetscErrorCode ierr; 3813 3814 PetscFunctionBegin; 3815 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3816 PetscValidBoolPointer(flg,2); 3817 if (dm->ops->hascreateinjection) { 3818 ierr = (*dm->ops->hascreateinjection)(dm,flg);CHKERRQ(ierr); 3819 } else { 3820 *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE; 3821 } 3822 PetscFunctionReturn(0); 3823 } 3824 3825 PetscFunctionList DMList = NULL; 3826 PetscBool DMRegisterAllCalled = PETSC_FALSE; 3827 3828 /*@C 3829 DMSetType - Builds a DM, for a particular DM implementation. 3830 3831 Collective on dm 3832 3833 Input Parameters: 3834 + dm - The DM object 3835 - method - The name of the DM type 3836 3837 Options Database Key: 3838 . -dm_type <type> - Sets the DM type; use -help for a list of available types 3839 3840 Notes: 3841 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 3842 3843 Level: intermediate 3844 3845 .seealso: DMGetType(), DMCreate() 3846 @*/ 3847 PetscErrorCode DMSetType(DM dm, DMType method) 3848 { 3849 PetscErrorCode (*r)(DM); 3850 PetscBool match; 3851 PetscErrorCode ierr; 3852 3853 PetscFunctionBegin; 3854 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3855 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3856 if (match) PetscFunctionReturn(0); 3857 3858 ierr = DMRegisterAll();CHKERRQ(ierr); 3859 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3860 PetscCheckFalse(!r,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3861 3862 if (dm->ops->destroy) { 3863 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3864 } 3865 ierr = PetscMemzero(dm->ops,sizeof(*dm->ops));CHKERRQ(ierr); 3866 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3867 ierr = (*r)(dm);CHKERRQ(ierr); 3868 PetscFunctionReturn(0); 3869 } 3870 3871 /*@C 3872 DMGetType - Gets the DM type name (as a string) from the DM. 3873 3874 Not Collective 3875 3876 Input Parameter: 3877 . dm - The DM 3878 3879 Output Parameter: 3880 . type - The DM type name 3881 3882 Level: intermediate 3883 3884 .seealso: DMSetType(), DMCreate() 3885 @*/ 3886 PetscErrorCode DMGetType(DM dm, DMType *type) 3887 { 3888 PetscErrorCode ierr; 3889 3890 PetscFunctionBegin; 3891 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3892 PetscValidPointer(type,2); 3893 ierr = DMRegisterAll();CHKERRQ(ierr); 3894 *type = ((PetscObject)dm)->type_name; 3895 PetscFunctionReturn(0); 3896 } 3897 3898 /*@C 3899 DMConvert - Converts a DM to another DM, either of the same or different type. 3900 3901 Collective on dm 3902 3903 Input Parameters: 3904 + dm - the DM 3905 - newtype - new DM type (use "same" for the same type) 3906 3907 Output Parameter: 3908 . M - pointer to new DM 3909 3910 Notes: 3911 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3912 the MPI communicator of the generated DM is always the same as the communicator 3913 of the input DM. 3914 3915 Level: intermediate 3916 3917 .seealso: DMCreate() 3918 @*/ 3919 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3920 { 3921 DM B; 3922 char convname[256]; 3923 PetscBool sametype/*, issame */; 3924 PetscErrorCode ierr; 3925 3926 PetscFunctionBegin; 3927 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3928 PetscValidType(dm,1); 3929 PetscValidPointer(M,3); 3930 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3931 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3932 if (sametype) { 3933 *M = dm; 3934 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3935 PetscFunctionReturn(0); 3936 } else { 3937 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3938 3939 /* 3940 Order of precedence: 3941 1) See if a specialized converter is known to the current DM. 3942 2) See if a specialized converter is known to the desired DM class. 3943 3) See if a good general converter is registered for the desired class 3944 4) See if a good general converter is known for the current matrix. 3945 5) Use a really basic converter. 3946 */ 3947 3948 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3949 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3950 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3951 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3952 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3953 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3954 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3955 if (conv) goto foundconv; 3956 3957 /* 2) See if a specialized converter is known to the desired DM class. */ 3958 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3959 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3960 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3961 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3962 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3963 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3964 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3965 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3966 if (conv) { 3967 ierr = DMDestroy(&B);CHKERRQ(ierr); 3968 goto foundconv; 3969 } 3970 3971 #if 0 3972 /* 3) See if a good general converter is registered for the desired class */ 3973 conv = B->ops->convertfrom; 3974 ierr = DMDestroy(&B);CHKERRQ(ierr); 3975 if (conv) goto foundconv; 3976 3977 /* 4) See if a good general converter is known for the current matrix */ 3978 if (dm->ops->convert) { 3979 conv = dm->ops->convert; 3980 } 3981 if (conv) goto foundconv; 3982 #endif 3983 3984 /* 5) Use a really basic converter. */ 3985 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3986 3987 foundconv: 3988 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3989 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3990 /* Things that are independent of DM type: We should consult DMClone() here */ 3991 { 3992 PetscBool isper; 3993 const PetscReal *maxCell, *L; 3994 const DMBoundaryType *bd; 3995 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 3996 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr); 3997 (*M)->prealloc_only = dm->prealloc_only; 3998 ierr = PetscFree((*M)->vectype);CHKERRQ(ierr); 3999 ierr = PetscStrallocpy(dm->vectype,(char**)&(*M)->vectype);CHKERRQ(ierr); 4000 ierr = PetscFree((*M)->mattype);CHKERRQ(ierr); 4001 ierr = PetscStrallocpy(dm->mattype,(char**)&(*M)->mattype);CHKERRQ(ierr); 4002 } 4003 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 4004 } 4005 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 4006 PetscFunctionReturn(0); 4007 } 4008 4009 /*--------------------------------------------------------------------------------------------------------------------*/ 4010 4011 /*@C 4012 DMRegister - Adds a new DM component implementation 4013 4014 Not Collective 4015 4016 Input Parameters: 4017 + name - The name of a new user-defined creation routine 4018 - create_func - The creation routine itself 4019 4020 Notes: 4021 DMRegister() may be called multiple times to add several user-defined DMs 4022 4023 Sample usage: 4024 .vb 4025 DMRegister("my_da", MyDMCreate); 4026 .ve 4027 4028 Then, your DM type can be chosen with the procedural interface via 4029 .vb 4030 DMCreate(MPI_Comm, DM *); 4031 DMSetType(DM,"my_da"); 4032 .ve 4033 or at runtime via the option 4034 .vb 4035 -da_type my_da 4036 .ve 4037 4038 Level: advanced 4039 4040 .seealso: DMRegisterAll(), DMRegisterDestroy() 4041 4042 @*/ 4043 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 4044 { 4045 PetscErrorCode ierr; 4046 4047 PetscFunctionBegin; 4048 ierr = DMInitializePackage();CHKERRQ(ierr); 4049 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 4050 PetscFunctionReturn(0); 4051 } 4052 4053 /*@C 4054 DMLoad - Loads a DM that has been stored in binary with DMView(). 4055 4056 Collective on viewer 4057 4058 Input Parameters: 4059 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 4060 some related function before a call to DMLoad(). 4061 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 4062 HDF5 file viewer, obtained from PetscViewerHDF5Open() 4063 4064 Level: intermediate 4065 4066 Notes: 4067 The type is determined by the data in the file, any type set into the DM before this call is ignored. 4068 4069 Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex 4070 meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName() 4071 before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object. 4072 4073 Notes for advanced users: 4074 Most users should not need to know the details of the binary storage 4075 format, since DMLoad() and DMView() completely hide these details. 4076 But for anyone who's interested, the standard binary matrix storage 4077 format is 4078 .vb 4079 has not yet been determined 4080 .ve 4081 4082 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 4083 @*/ 4084 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 4085 { 4086 PetscBool isbinary, ishdf5; 4087 PetscErrorCode ierr; 4088 4089 PetscFunctionBegin; 4090 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 4091 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4092 ierr = PetscViewerCheckReadable(viewer);CHKERRQ(ierr); 4093 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 4094 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 4095 ierr = PetscLogEventBegin(DM_Load,viewer,0,0,0);CHKERRQ(ierr); 4096 if (isbinary) { 4097 PetscInt classid; 4098 char type[256]; 4099 4100 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 4101 PetscCheckFalse(classid != DM_FILE_CLASSID,PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 4102 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 4103 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 4104 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 4105 } else if (ishdf5) { 4106 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 4107 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 4108 ierr = PetscLogEventEnd(DM_Load,viewer,0,0,0);CHKERRQ(ierr); 4109 PetscFunctionReturn(0); 4110 } 4111 4112 /*@ 4113 DMGetLocalBoundingBox - Returns the bounding box for the piece of the DM on this process. 4114 4115 Not collective 4116 4117 Input Parameter: 4118 . dm - the DM 4119 4120 Output Parameters: 4121 + lmin - local minimum coordinates (length coord dim, optional) 4122 - lmax - local maximim coordinates (length coord dim, optional) 4123 4124 Level: beginner 4125 4126 Note: If the DM is a DMDA and has no coordinates, the index bounds are returned instead. 4127 4128 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetBoundingBox() 4129 @*/ 4130 PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[]) 4131 { 4132 Vec coords = NULL; 4133 PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 4134 PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 4135 const PetscScalar *local_coords; 4136 PetscInt N, Ni; 4137 PetscInt cdim, i, j; 4138 PetscErrorCode ierr; 4139 4140 PetscFunctionBegin; 4141 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4142 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 4143 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 4144 if (coords) { 4145 ierr = VecGetArrayRead(coords, &local_coords);CHKERRQ(ierr); 4146 ierr = VecGetLocalSize(coords, &N);CHKERRQ(ierr); 4147 Ni = N/cdim; 4148 for (i = 0; i < Ni; ++i) { 4149 for (j = 0; j < 3; ++j) { 4150 min[j] = j < cdim ? PetscMin(min[j], PetscRealPart(local_coords[i*cdim+j])) : 0; 4151 max[j] = j < cdim ? PetscMax(max[j], PetscRealPart(local_coords[i*cdim+j])) : 0; 4152 } 4153 } 4154 ierr = VecRestoreArrayRead(coords, &local_coords);CHKERRQ(ierr); 4155 } else { 4156 PetscBool isda; 4157 4158 ierr = PetscObjectTypeCompare((PetscObject) dm, DMDA, &isda);CHKERRQ(ierr); 4159 if (isda) {ierr = DMGetLocalBoundingIndices_DMDA(dm, min, max);CHKERRQ(ierr);} 4160 } 4161 if (lmin) {ierr = PetscArraycpy(lmin, min, cdim);CHKERRQ(ierr);} 4162 if (lmax) {ierr = PetscArraycpy(lmax, max, cdim);CHKERRQ(ierr);} 4163 PetscFunctionReturn(0); 4164 } 4165 4166 /*@ 4167 DMGetBoundingBox - Returns the global bounding box for the DM. 4168 4169 Collective 4170 4171 Input Parameter: 4172 . dm - the DM 4173 4174 Output Parameters: 4175 + gmin - global minimum coordinates (length coord dim, optional) 4176 - gmax - global maximim coordinates (length coord dim, optional) 4177 4178 Level: beginner 4179 4180 .seealso: DMGetLocalBoundingBox(), DMGetCoordinates(), DMGetCoordinatesLocal() 4181 @*/ 4182 PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[]) 4183 { 4184 PetscReal lmin[3], lmax[3]; 4185 PetscInt cdim; 4186 PetscMPIInt count; 4187 PetscErrorCode ierr; 4188 4189 PetscFunctionBegin; 4190 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4191 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 4192 ierr = PetscMPIIntCast(cdim, &count);CHKERRQ(ierr); 4193 ierr = DMGetLocalBoundingBox(dm, lmin, lmax);CHKERRQ(ierr); 4194 if (gmin) {ierr = MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);} 4195 if (gmax) {ierr = MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);} 4196 PetscFunctionReturn(0); 4197 } 4198 4199 /******************************** FEM Support **********************************/ 4200 4201 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 4202 { 4203 PetscInt f; 4204 PetscErrorCode ierr; 4205 4206 PetscFunctionBegin; 4207 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 4208 for (f = 0; f < len; ++f) { 4209 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 4210 } 4211 PetscFunctionReturn(0); 4212 } 4213 4214 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 4215 { 4216 PetscInt f, g; 4217 PetscErrorCode ierr; 4218 4219 PetscFunctionBegin; 4220 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 4221 for (f = 0; f < rows; ++f) { 4222 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 4223 for (g = 0; g < cols; ++g) { 4224 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 4225 } 4226 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 4227 } 4228 PetscFunctionReturn(0); 4229 } 4230 4231 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 4232 { 4233 PetscInt localSize, bs; 4234 PetscMPIInt size; 4235 Vec x, xglob; 4236 const PetscScalar *xarray; 4237 PetscErrorCode ierr; 4238 4239 PetscFunctionBegin; 4240 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRMPI(ierr); 4241 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 4242 ierr = VecCopy(X, x);CHKERRQ(ierr); 4243 ierr = VecChop(x, tol);CHKERRQ(ierr); 4244 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 4245 if (size > 1) { 4246 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 4247 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 4248 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 4249 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 4250 } else { 4251 xglob = x; 4252 } 4253 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 4254 if (size > 1) { 4255 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 4256 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 4257 } 4258 ierr = VecDestroy(&x);CHKERRQ(ierr); 4259 PetscFunctionReturn(0); 4260 } 4261 4262 /*@ 4263 DMGetSection - Get the PetscSection encoding the local data layout for the DM. This is equivalent to DMGetLocalSection(). Deprecated in v3.12 4264 4265 Input Parameter: 4266 . dm - The DM 4267 4268 Output Parameter: 4269 . section - The PetscSection 4270 4271 Options Database Keys: 4272 . -dm_petscsection_view - View the Section created by the DM 4273 4274 Level: advanced 4275 4276 Notes: 4277 Use DMGetLocalSection() in new code. 4278 4279 This gets a borrowed reference, so the user should not destroy this PetscSection. 4280 4281 .seealso: DMGetLocalSection(), DMSetLocalSection(), DMGetGlobalSection() 4282 @*/ 4283 PetscErrorCode DMGetSection(DM dm, PetscSection *section) 4284 { 4285 PetscErrorCode ierr; 4286 4287 PetscFunctionBegin; 4288 ierr = DMGetLocalSection(dm,section);CHKERRQ(ierr); 4289 PetscFunctionReturn(0); 4290 } 4291 4292 /*@ 4293 DMGetLocalSection - Get the PetscSection encoding the local data layout for the DM. 4294 4295 Input Parameter: 4296 . dm - The DM 4297 4298 Output Parameter: 4299 . section - The PetscSection 4300 4301 Options Database Keys: 4302 . -dm_petscsection_view - View the Section created by the DM 4303 4304 Level: intermediate 4305 4306 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 4307 4308 .seealso: DMSetLocalSection(), DMGetGlobalSection() 4309 @*/ 4310 PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section) 4311 { 4312 PetscErrorCode ierr; 4313 4314 PetscFunctionBegin; 4315 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4316 PetscValidPointer(section, 2); 4317 if (!dm->localSection && dm->ops->createlocalsection) { 4318 PetscInt d; 4319 4320 if (dm->setfromoptionscalled) { 4321 PetscObject obj = (PetscObject) dm; 4322 PetscViewer viewer; 4323 PetscViewerFormat format; 4324 PetscBool flg; 4325 4326 ierr = PetscOptionsGetViewer(PetscObjectComm(obj), obj->options, obj->prefix, "-dm_petscds_view", &viewer, &format, &flg);CHKERRQ(ierr); 4327 if (flg) {ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr);} 4328 for (d = 0; d < dm->Nds; ++d) { 4329 ierr = PetscDSSetFromOptions(dm->probs[d].ds);CHKERRQ(ierr); 4330 if (flg) {ierr = PetscDSView(dm->probs[d].ds, viewer);CHKERRQ(ierr);} 4331 } 4332 if (flg) { 4333 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 4334 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 4335 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 4336 } 4337 } 4338 ierr = (*dm->ops->createlocalsection)(dm);CHKERRQ(ierr); 4339 if (dm->localSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->localSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 4340 } 4341 *section = dm->localSection; 4342 PetscFunctionReturn(0); 4343 } 4344 4345 /*@ 4346 DMSetSection - Set the PetscSection encoding the local data layout for the DM. This is equivalent to DMSetLocalSection(). Deprecated in v3.12 4347 4348 Input Parameters: 4349 + dm - The DM 4350 - section - The PetscSection 4351 4352 Level: advanced 4353 4354 Notes: 4355 Use DMSetLocalSection() in new code. 4356 4357 Any existing Section will be destroyed 4358 4359 .seealso: DMSetLocalSection(), DMGetLocalSection(), DMSetGlobalSection() 4360 @*/ 4361 PetscErrorCode DMSetSection(DM dm, PetscSection section) 4362 { 4363 PetscErrorCode ierr; 4364 4365 PetscFunctionBegin; 4366 ierr = DMSetLocalSection(dm,section);CHKERRQ(ierr); 4367 PetscFunctionReturn(0); 4368 } 4369 4370 /*@ 4371 DMSetLocalSection - Set the PetscSection encoding the local data layout for the DM. 4372 4373 Input Parameters: 4374 + dm - The DM 4375 - section - The PetscSection 4376 4377 Level: intermediate 4378 4379 Note: Any existing Section will be destroyed 4380 4381 .seealso: DMGetLocalSection(), DMSetGlobalSection() 4382 @*/ 4383 PetscErrorCode DMSetLocalSection(DM dm, PetscSection section) 4384 { 4385 PetscInt numFields = 0; 4386 PetscInt f; 4387 PetscErrorCode ierr; 4388 4389 PetscFunctionBegin; 4390 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4391 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4392 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4393 ierr = PetscSectionDestroy(&dm->localSection);CHKERRQ(ierr); 4394 dm->localSection = section; 4395 if (section) {ierr = PetscSectionGetNumFields(dm->localSection, &numFields);CHKERRQ(ierr);} 4396 if (numFields) { 4397 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 4398 for (f = 0; f < numFields; ++f) { 4399 PetscObject disc; 4400 const char *name; 4401 4402 ierr = PetscSectionGetFieldName(dm->localSection, f, &name);CHKERRQ(ierr); 4403 ierr = DMGetField(dm, f, NULL, &disc);CHKERRQ(ierr); 4404 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 4405 } 4406 } 4407 /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */ 4408 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr); 4409 PetscFunctionReturn(0); 4410 } 4411 4412 /*@ 4413 DMGetDefaultConstraints - Get the PetscSection and Mat that specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 4414 4415 not collective 4416 4417 Input Parameter: 4418 . dm - The DM 4419 4420 Output Parameters: 4421 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Returns NULL if there are no local constraints. 4422 . mat - The Mat that interpolates local constraints: its width should be the layout size of the default section. Returns NULL if there are no local constraints. 4423 - bias - Vector containing bias to be added to constrained dofs 4424 4425 Level: advanced 4426 4427 Note: This gets borrowed references, so the user should not destroy the PetscSection, Mat, or Vec. 4428 4429 .seealso: DMSetDefaultConstraints() 4430 @*/ 4431 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat, Vec *bias) 4432 { 4433 PetscErrorCode ierr; 4434 4435 PetscFunctionBegin; 4436 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4437 if (!dm->defaultConstraint.section && !dm->defaultConstraint.mat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 4438 if (section) *section = dm->defaultConstraint.section; 4439 if (mat) *mat = dm->defaultConstraint.mat; 4440 if (bias) *bias = dm->defaultConstraint.bias; 4441 PetscFunctionReturn(0); 4442 } 4443 4444 /*@ 4445 DMSetDefaultConstraints - Set the PetscSection and Mat that specify the local constraint interpolation. 4446 4447 If a constraint matrix is specified, then it is applied during DMGlobalToLocalEnd() when mode is INSERT_VALUES, INSERT_BC_VALUES, or INSERT_ALL_VALUES. Without a constraint matrix, the local vector l returned by DMGlobalToLocalEnd() contains values that have been scattered from a global vector without modification; with a constraint matrix A, l is modified by computing c = A * l + bias, l[s[i]] = c[i], where the scatter s is defined by the PetscSection returned by DMGetDefaultConstraints(). 4448 4449 If a constraint matrix is specified, then its adjoint is applied during DMLocalToGlobalBegin() when mode is ADD_VALUES, ADD_BC_VALUES, or ADD_ALL_VALUES. Without a constraint matrix, the local vector l is accumulated into a global vector without modification; with a constraint matrix A, l is first modified by computing c[i] = l[s[i]], l[s[i]] = 0, l = l + A'*c, which is the adjoint of the operation described above. Any bias, if specified, is ignored when accumulating. 4450 4451 collective on dm 4452 4453 Input Parameters: 4454 + dm - The DM 4455 . section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Must have a local communicator (PETSC_COMM_SELF or derivative). 4456 . mat - The Mat that interpolates local constraints: its width should be the layout size of the default section: NULL indicates no constraints. Must have a local communicator (PETSC_COMM_SELF or derivative). 4457 - bias - A bias vector to be added to constrained values in the local vector. NULL indicates no bias. Must have a local communicator (PETSC_COMM_SELF or derivative). 4458 4459 Level: advanced 4460 4461 Note: This increments the references of the PetscSection, Mat, and Vec, so they user can destroy them. 4462 4463 .seealso: DMGetDefaultConstraints() 4464 @*/ 4465 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat, Vec bias) 4466 { 4467 PetscMPIInt result; 4468 PetscErrorCode ierr; 4469 4470 PetscFunctionBegin; 4471 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4472 if (section) { 4473 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4474 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRMPI(ierr); 4475 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 4476 } 4477 if (mat) { 4478 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 4479 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRMPI(ierr); 4480 PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 4481 } 4482 if (bias) { 4483 PetscValidHeaderSpecific(bias,VEC_CLASSID,4); 4484 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)bias),&result);CHKERRMPI(ierr); 4485 PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint bias must have local communicator"); 4486 } 4487 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4488 ierr = PetscSectionDestroy(&dm->defaultConstraint.section);CHKERRQ(ierr); 4489 dm->defaultConstraint.section = section; 4490 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 4491 ierr = MatDestroy(&dm->defaultConstraint.mat);CHKERRQ(ierr); 4492 dm->defaultConstraint.mat = mat; 4493 ierr = PetscObjectReference((PetscObject)bias);CHKERRQ(ierr); 4494 ierr = VecDestroy(&dm->defaultConstraint.bias);CHKERRQ(ierr); 4495 dm->defaultConstraint.bias = bias; 4496 PetscFunctionReturn(0); 4497 } 4498 4499 #if defined(PETSC_USE_DEBUG) 4500 /* 4501 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 4502 4503 Input Parameters: 4504 + dm - The DM 4505 . localSection - PetscSection describing the local data layout 4506 - globalSection - PetscSection describing the global data layout 4507 4508 Level: intermediate 4509 4510 .seealso: DMGetSectionSF(), DMSetSectionSF() 4511 */ 4512 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 4513 { 4514 MPI_Comm comm; 4515 PetscLayout layout; 4516 const PetscInt *ranges; 4517 PetscInt pStart, pEnd, p, nroots; 4518 PetscMPIInt size, rank; 4519 PetscBool valid = PETSC_TRUE, gvalid; 4520 PetscErrorCode ierr; 4521 4522 PetscFunctionBegin; 4523 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4524 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4525 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 4526 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 4527 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 4528 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 4529 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 4530 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 4531 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 4532 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 4533 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 4534 for (p = pStart; p < pEnd; ++p) { 4535 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 4536 4537 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 4538 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 4539 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 4540 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4541 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4542 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 4543 if (!gdof) continue; /* Censored point */ 4544 if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof);CHKERRQ(ierr); valid = PETSC_FALSE;} 4545 if (gcdof && (gcdof != cdof)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof);CHKERRQ(ierr); valid = PETSC_FALSE;} 4546 if (gdof < 0) { 4547 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4548 for (d = 0; d < gsize; ++d) { 4549 PetscInt offset = -(goff+1) + d, r; 4550 4551 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4552 if (r < 0) r = -(r+2); 4553 if ((r < 0) || (r >= size)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff);CHKERRQ(ierr); valid = PETSC_FALSE;break;} 4554 } 4555 } 4556 } 4557 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4558 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 4559 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRMPI(ierr); 4560 if (!gvalid) { 4561 ierr = DMView(dm, NULL);CHKERRQ(ierr); 4562 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 4563 } 4564 PetscFunctionReturn(0); 4565 } 4566 #endif 4567 4568 /*@ 4569 DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM. 4570 4571 Collective on dm 4572 4573 Input Parameter: 4574 . dm - The DM 4575 4576 Output Parameter: 4577 . section - The PetscSection 4578 4579 Level: intermediate 4580 4581 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 4582 4583 .seealso: DMSetLocalSection(), DMGetLocalSection() 4584 @*/ 4585 PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section) 4586 { 4587 PetscErrorCode ierr; 4588 4589 PetscFunctionBegin; 4590 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4591 PetscValidPointer(section, 2); 4592 if (!dm->globalSection) { 4593 PetscSection s; 4594 4595 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 4596 PetscCheckFalse(!s,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 4597 PetscCheckFalse(!dm->sf,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection"); 4598 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection);CHKERRQ(ierr); 4599 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 4600 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map);CHKERRQ(ierr); 4601 ierr = PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view");CHKERRQ(ierr); 4602 } 4603 *section = dm->globalSection; 4604 PetscFunctionReturn(0); 4605 } 4606 4607 /*@ 4608 DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM. 4609 4610 Input Parameters: 4611 + dm - The DM 4612 - section - The PetscSection, or NULL 4613 4614 Level: intermediate 4615 4616 Note: Any existing Section will be destroyed 4617 4618 .seealso: DMGetGlobalSection(), DMSetLocalSection() 4619 @*/ 4620 PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section) 4621 { 4622 PetscErrorCode ierr; 4623 4624 PetscFunctionBegin; 4625 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4626 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4627 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4628 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr); 4629 dm->globalSection = section; 4630 #if defined(PETSC_USE_DEBUG) 4631 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section);CHKERRQ(ierr);} 4632 #endif 4633 PetscFunctionReturn(0); 4634 } 4635 4636 /*@ 4637 DMGetSectionSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 4638 it is created from the default PetscSection layouts in the DM. 4639 4640 Input Parameter: 4641 . dm - The DM 4642 4643 Output Parameter: 4644 . sf - The PetscSF 4645 4646 Level: intermediate 4647 4648 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4649 4650 .seealso: DMSetSectionSF(), DMCreateSectionSF() 4651 @*/ 4652 PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf) 4653 { 4654 PetscInt nroots; 4655 PetscErrorCode ierr; 4656 4657 PetscFunctionBegin; 4658 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4659 PetscValidPointer(sf, 2); 4660 if (!dm->sectionSF) { 4661 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&dm->sectionSF);CHKERRQ(ierr); 4662 } 4663 ierr = PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 4664 if (nroots < 0) { 4665 PetscSection section, gSection; 4666 4667 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 4668 if (section) { 4669 ierr = DMGetGlobalSection(dm, &gSection);CHKERRQ(ierr); 4670 ierr = DMCreateSectionSF(dm, section, gSection);CHKERRQ(ierr); 4671 } else { 4672 *sf = NULL; 4673 PetscFunctionReturn(0); 4674 } 4675 } 4676 *sf = dm->sectionSF; 4677 PetscFunctionReturn(0); 4678 } 4679 4680 /*@ 4681 DMSetSectionSF - Set the PetscSF encoding the parallel dof overlap for the DM 4682 4683 Input Parameters: 4684 + dm - The DM 4685 - sf - The PetscSF 4686 4687 Level: intermediate 4688 4689 Note: Any previous SF is destroyed 4690 4691 .seealso: DMGetSectionSF(), DMCreateSectionSF() 4692 @*/ 4693 PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf) 4694 { 4695 PetscErrorCode ierr; 4696 4697 PetscFunctionBegin; 4698 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4699 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4700 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4701 ierr = PetscSFDestroy(&dm->sectionSF);CHKERRQ(ierr); 4702 dm->sectionSF = sf; 4703 PetscFunctionReturn(0); 4704 } 4705 4706 /*@C 4707 DMCreateSectionSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 4708 describing the data layout. 4709 4710 Input Parameters: 4711 + dm - The DM 4712 . localSection - PetscSection describing the local data layout 4713 - globalSection - PetscSection describing the global data layout 4714 4715 Notes: One usually uses DMGetSectionSF() to obtain the PetscSF 4716 4717 Level: developer 4718 4719 Developer Note: Since this routine has for arguments the two sections from the DM and puts the resulting PetscSF 4720 directly into the DM, perhaps this function should not take the local and global sections as 4721 input and should just obtain them from the DM? 4722 4723 .seealso: DMGetSectionSF(), DMSetSectionSF(), DMGetLocalSection(), DMGetGlobalSection() 4724 @*/ 4725 PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection) 4726 { 4727 PetscErrorCode ierr; 4728 4729 PetscFunctionBegin; 4730 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4731 ierr = PetscSFSetGraphSection(dm->sectionSF, localSection, globalSection);CHKERRQ(ierr); 4732 PetscFunctionReturn(0); 4733 } 4734 4735 /*@ 4736 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 4737 4738 Input Parameter: 4739 . dm - The DM 4740 4741 Output Parameter: 4742 . sf - The PetscSF 4743 4744 Level: intermediate 4745 4746 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4747 4748 .seealso: DMSetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF() 4749 @*/ 4750 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 4751 { 4752 PetscFunctionBegin; 4753 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4754 PetscValidPointer(sf, 2); 4755 *sf = dm->sf; 4756 PetscFunctionReturn(0); 4757 } 4758 4759 /*@ 4760 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 4761 4762 Input Parameters: 4763 + dm - The DM 4764 - sf - The PetscSF 4765 4766 Level: intermediate 4767 4768 .seealso: DMGetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF() 4769 @*/ 4770 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 4771 { 4772 PetscErrorCode ierr; 4773 4774 PetscFunctionBegin; 4775 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4776 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4777 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4778 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 4779 dm->sf = sf; 4780 PetscFunctionReturn(0); 4781 } 4782 4783 /*@ 4784 DMGetNaturalSF - Get the PetscSF encoding the map back to the original mesh ordering 4785 4786 Input Parameter: 4787 . dm - The DM 4788 4789 Output Parameter: 4790 . sf - The PetscSF 4791 4792 Level: intermediate 4793 4794 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4795 4796 .seealso: DMSetNaturalSF(), DMSetUseNatural(), DMGetUseNatural(), DMPlexCreateGlobalToNaturalSF(), DMPlexDistribute() 4797 @*/ 4798 PetscErrorCode DMGetNaturalSF(DM dm, PetscSF *sf) 4799 { 4800 PetscFunctionBegin; 4801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4802 PetscValidPointer(sf, 2); 4803 *sf = dm->sfNatural; 4804 PetscFunctionReturn(0); 4805 } 4806 4807 /*@ 4808 DMSetNaturalSF - Set the PetscSF encoding the map back to the original mesh ordering 4809 4810 Input Parameters: 4811 + dm - The DM 4812 - sf - The PetscSF 4813 4814 Level: intermediate 4815 4816 .seealso: DMGetNaturalSF(), DMSetUseNatural(), DMGetUseNatural(), DMPlexCreateGlobalToNaturalSF(), DMPlexDistribute() 4817 @*/ 4818 PetscErrorCode DMSetNaturalSF(DM dm, PetscSF sf) 4819 { 4820 PetscErrorCode ierr; 4821 4822 PetscFunctionBegin; 4823 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4824 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4825 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4826 ierr = PetscSFDestroy(&dm->sfNatural);CHKERRQ(ierr); 4827 dm->sfNatural = sf; 4828 PetscFunctionReturn(0); 4829 } 4830 4831 static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc) 4832 { 4833 PetscClassId id; 4834 PetscErrorCode ierr; 4835 4836 PetscFunctionBegin; 4837 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 4838 if (id == PETSCFE_CLASSID) { 4839 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4840 } else if (id == PETSCFV_CLASSID) { 4841 ierr = DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 4842 } else { 4843 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4844 } 4845 PetscFunctionReturn(0); 4846 } 4847 4848 static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew) 4849 { 4850 RegionField *tmpr; 4851 PetscInt Nf = dm->Nf, f; 4852 PetscErrorCode ierr; 4853 4854 PetscFunctionBegin; 4855 if (Nf >= NfNew) PetscFunctionReturn(0); 4856 ierr = PetscMalloc1(NfNew, &tmpr);CHKERRQ(ierr); 4857 for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f]; 4858 for (f = Nf; f < NfNew; ++f) {tmpr[f].disc = NULL; tmpr[f].label = NULL; tmpr[f].avoidTensor = PETSC_FALSE;} 4859 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4860 dm->Nf = NfNew; 4861 dm->fields = tmpr; 4862 PetscFunctionReturn(0); 4863 } 4864 4865 /*@ 4866 DMClearFields - Remove all fields from the DM 4867 4868 Logically collective on dm 4869 4870 Input Parameter: 4871 . dm - The DM 4872 4873 Level: intermediate 4874 4875 .seealso: DMGetNumFields(), DMSetNumFields(), DMSetField() 4876 @*/ 4877 PetscErrorCode DMClearFields(DM dm) 4878 { 4879 PetscInt f; 4880 PetscErrorCode ierr; 4881 4882 PetscFunctionBegin; 4883 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4884 for (f = 0; f < dm->Nf; ++f) { 4885 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4886 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4887 } 4888 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4889 dm->fields = NULL; 4890 dm->Nf = 0; 4891 PetscFunctionReturn(0); 4892 } 4893 4894 /*@ 4895 DMGetNumFields - Get the number of fields in the DM 4896 4897 Not collective 4898 4899 Input Parameter: 4900 . dm - The DM 4901 4902 Output Parameter: 4903 . Nf - The number of fields 4904 4905 Level: intermediate 4906 4907 .seealso: DMSetNumFields(), DMSetField() 4908 @*/ 4909 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4910 { 4911 PetscFunctionBegin; 4912 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4913 PetscValidIntPointer(numFields, 2); 4914 *numFields = dm->Nf; 4915 PetscFunctionReturn(0); 4916 } 4917 4918 /*@ 4919 DMSetNumFields - Set the number of fields in the DM 4920 4921 Logically collective on dm 4922 4923 Input Parameters: 4924 + dm - The DM 4925 - Nf - The number of fields 4926 4927 Level: intermediate 4928 4929 .seealso: DMGetNumFields(), DMSetField() 4930 @*/ 4931 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4932 { 4933 PetscInt Nf, f; 4934 PetscErrorCode ierr; 4935 4936 PetscFunctionBegin; 4937 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4938 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4939 for (f = Nf; f < numFields; ++f) { 4940 PetscContainer obj; 4941 4942 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4943 ierr = DMAddField(dm, NULL, (PetscObject) obj);CHKERRQ(ierr); 4944 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4945 } 4946 PetscFunctionReturn(0); 4947 } 4948 4949 /*@ 4950 DMGetField - Return the discretization object for a given DM field 4951 4952 Not collective 4953 4954 Input Parameters: 4955 + dm - The DM 4956 - f - The field number 4957 4958 Output Parameters: 4959 + label - The label indicating the support of the field, or NULL for the entire mesh 4960 - field - The discretization object 4961 4962 Level: intermediate 4963 4964 .seealso: DMAddField(), DMSetField() 4965 @*/ 4966 PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *field) 4967 { 4968 PetscFunctionBegin; 4969 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4970 PetscValidPointer(field, 4); 4971 PetscCheckFalse((f < 0) || (f >= dm->Nf),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, dm->Nf); 4972 if (label) *label = dm->fields[f].label; 4973 if (field) *field = dm->fields[f].disc; 4974 PetscFunctionReturn(0); 4975 } 4976 4977 /* Does not clear the DS */ 4978 PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject field) 4979 { 4980 PetscErrorCode ierr; 4981 4982 PetscFunctionBegin; 4983 ierr = DMFieldEnlarge_Static(dm, f+1);CHKERRQ(ierr); 4984 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4985 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4986 dm->fields[f].label = label; 4987 dm->fields[f].disc = field; 4988 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4989 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4990 PetscFunctionReturn(0); 4991 } 4992 4993 /*@ 4994 DMSetField - Set the discretization object for a given DM field 4995 4996 Logically collective on dm 4997 4998 Input Parameters: 4999 + dm - The DM 5000 . f - The field number 5001 . label - The label indicating the support of the field, or NULL for the entire mesh 5002 - field - The discretization object 5003 5004 Level: intermediate 5005 5006 .seealso: DMAddField(), DMGetField() 5007 @*/ 5008 PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject field) 5009 { 5010 PetscErrorCode ierr; 5011 5012 PetscFunctionBegin; 5013 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5014 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 5015 PetscValidHeader(field, 4); 5016 PetscCheckFalse(f < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 5017 ierr = DMSetField_Internal(dm, f, label, field);CHKERRQ(ierr); 5018 ierr = DMSetDefaultAdjacency_Private(dm, f, field);CHKERRQ(ierr); 5019 ierr = DMClearDS(dm);CHKERRQ(ierr); 5020 PetscFunctionReturn(0); 5021 } 5022 5023 /*@ 5024 DMAddField - Add the discretization object for the given DM field 5025 5026 Logically collective on dm 5027 5028 Input Parameters: 5029 + dm - The DM 5030 . label - The label indicating the support of the field, or NULL for the entire mesh 5031 - field - The discretization object 5032 5033 Level: intermediate 5034 5035 .seealso: DMSetField(), DMGetField() 5036 @*/ 5037 PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject field) 5038 { 5039 PetscInt Nf = dm->Nf; 5040 PetscErrorCode ierr; 5041 5042 PetscFunctionBegin; 5043 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5044 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5045 PetscValidHeader(field, 3); 5046 ierr = DMFieldEnlarge_Static(dm, Nf+1);CHKERRQ(ierr); 5047 dm->fields[Nf].label = label; 5048 dm->fields[Nf].disc = field; 5049 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 5050 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 5051 ierr = DMSetDefaultAdjacency_Private(dm, Nf, field);CHKERRQ(ierr); 5052 ierr = DMClearDS(dm);CHKERRQ(ierr); 5053 PetscFunctionReturn(0); 5054 } 5055 5056 /*@ 5057 DMSetFieldAvoidTensor - Set flag to avoid defining the field on tensor cells 5058 5059 Logically collective on dm 5060 5061 Input Parameters: 5062 + dm - The DM 5063 . f - The field index 5064 - avoidTensor - The flag to avoid defining the field on tensor cells 5065 5066 Level: intermediate 5067 5068 .seealso: DMGetFieldAvoidTensor(), DMSetField(), DMGetField() 5069 @*/ 5070 PetscErrorCode DMSetFieldAvoidTensor(DM dm, PetscInt f, PetscBool avoidTensor) 5071 { 5072 PetscFunctionBegin; 5073 PetscCheckFalse((f < 0) || (f >= dm->Nf),PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Field %D is not in [0, %D)", f, dm->Nf); 5074 dm->fields[f].avoidTensor = avoidTensor; 5075 PetscFunctionReturn(0); 5076 } 5077 5078 /*@ 5079 DMGetFieldAvoidTensor - Get flag to avoid defining the field on tensor cells 5080 5081 Logically collective on dm 5082 5083 Input Parameters: 5084 + dm - The DM 5085 - f - The field index 5086 5087 Output Parameter: 5088 . avoidTensor - The flag to avoid defining the field on tensor cells 5089 5090 Level: intermediate 5091 5092 .seealso: DMSetFieldAvoidTensor(), DMSetField(), DMGetField() 5093 @*/ 5094 PetscErrorCode DMGetFieldAvoidTensor(DM dm, PetscInt f, PetscBool *avoidTensor) 5095 { 5096 PetscFunctionBegin; 5097 PetscCheckFalse((f < 0) || (f >= dm->Nf),PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Field %D is not in [0, %D)", f, dm->Nf); 5098 *avoidTensor = dm->fields[f].avoidTensor; 5099 PetscFunctionReturn(0); 5100 } 5101 5102 /*@ 5103 DMCopyFields - Copy the discretizations for the DM into another DM 5104 5105 Collective on dm 5106 5107 Input Parameter: 5108 . dm - The DM 5109 5110 Output Parameter: 5111 . newdm - The DM 5112 5113 Level: advanced 5114 5115 .seealso: DMGetField(), DMSetField(), DMAddField(), DMCopyDS(), DMGetDS(), DMGetCellDS() 5116 @*/ 5117 PetscErrorCode DMCopyFields(DM dm, DM newdm) 5118 { 5119 PetscInt Nf, f; 5120 PetscErrorCode ierr; 5121 5122 PetscFunctionBegin; 5123 if (dm == newdm) PetscFunctionReturn(0); 5124 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5125 ierr = DMClearFields(newdm);CHKERRQ(ierr); 5126 for (f = 0; f < Nf; ++f) { 5127 DMLabel label; 5128 PetscObject field; 5129 PetscBool useCone, useClosure; 5130 5131 ierr = DMGetField(dm, f, &label, &field);CHKERRQ(ierr); 5132 ierr = DMSetField(newdm, f, label, field);CHKERRQ(ierr); 5133 ierr = DMGetAdjacency(dm, f, &useCone, &useClosure);CHKERRQ(ierr); 5134 ierr = DMSetAdjacency(newdm, f, useCone, useClosure);CHKERRQ(ierr); 5135 } 5136 PetscFunctionReturn(0); 5137 } 5138 5139 /*@ 5140 DMGetAdjacency - Returns the flags for determining variable influence 5141 5142 Not collective 5143 5144 Input Parameters: 5145 + dm - The DM object 5146 - f - The field number, or PETSC_DEFAULT for the default adjacency 5147 5148 Output Parameters: 5149 + useCone - Flag for variable influence starting with the cone operation 5150 - useClosure - Flag for variable influence using transitive closure 5151 5152 Notes: 5153 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 5154 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 5155 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 5156 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 5157 5158 Level: developer 5159 5160 .seealso: DMSetAdjacency(), DMGetField(), DMSetField() 5161 @*/ 5162 PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure) 5163 { 5164 PetscFunctionBegin; 5165 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5166 if (useCone) PetscValidBoolPointer(useCone, 3); 5167 if (useClosure) PetscValidBoolPointer(useClosure, 4); 5168 if (f < 0) { 5169 if (useCone) *useCone = dm->adjacency[0]; 5170 if (useClosure) *useClosure = dm->adjacency[1]; 5171 } else { 5172 PetscInt Nf; 5173 PetscErrorCode ierr; 5174 5175 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5176 PetscCheckFalse(f >= Nf,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 5177 if (useCone) *useCone = dm->fields[f].adjacency[0]; 5178 if (useClosure) *useClosure = dm->fields[f].adjacency[1]; 5179 } 5180 PetscFunctionReturn(0); 5181 } 5182 5183 /*@ 5184 DMSetAdjacency - Set the flags for determining variable influence 5185 5186 Not collective 5187 5188 Input Parameters: 5189 + dm - The DM object 5190 . f - The field number 5191 . useCone - Flag for variable influence starting with the cone operation 5192 - useClosure - Flag for variable influence using transitive closure 5193 5194 Notes: 5195 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 5196 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 5197 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 5198 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 5199 5200 Level: developer 5201 5202 .seealso: DMGetAdjacency(), DMGetField(), DMSetField() 5203 @*/ 5204 PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure) 5205 { 5206 PetscFunctionBegin; 5207 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5208 if (f < 0) { 5209 dm->adjacency[0] = useCone; 5210 dm->adjacency[1] = useClosure; 5211 } else { 5212 PetscInt Nf; 5213 PetscErrorCode ierr; 5214 5215 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5216 PetscCheckFalse(f >= Nf,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 5217 dm->fields[f].adjacency[0] = useCone; 5218 dm->fields[f].adjacency[1] = useClosure; 5219 } 5220 PetscFunctionReturn(0); 5221 } 5222 5223 /*@ 5224 DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined 5225 5226 Not collective 5227 5228 Input Parameter: 5229 . dm - The DM object 5230 5231 Output Parameters: 5232 + useCone - Flag for variable influence starting with the cone operation 5233 - useClosure - Flag for variable influence using transitive closure 5234 5235 Notes: 5236 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 5237 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 5238 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 5239 5240 Level: developer 5241 5242 .seealso: DMSetBasicAdjacency(), DMGetField(), DMSetField() 5243 @*/ 5244 PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure) 5245 { 5246 PetscInt Nf; 5247 PetscErrorCode ierr; 5248 5249 PetscFunctionBegin; 5250 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5251 if (useCone) PetscValidBoolPointer(useCone, 2); 5252 if (useClosure) PetscValidBoolPointer(useClosure, 3); 5253 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5254 if (!Nf) { 5255 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 5256 } else { 5257 ierr = DMGetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 5258 } 5259 PetscFunctionReturn(0); 5260 } 5261 5262 /*@ 5263 DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined 5264 5265 Not collective 5266 5267 Input Parameters: 5268 + dm - The DM object 5269 . useCone - Flag for variable influence starting with the cone operation 5270 - useClosure - Flag for variable influence using transitive closure 5271 5272 Notes: 5273 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 5274 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 5275 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 5276 5277 Level: developer 5278 5279 .seealso: DMGetBasicAdjacency(), DMGetField(), DMSetField() 5280 @*/ 5281 PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure) 5282 { 5283 PetscInt Nf; 5284 PetscErrorCode ierr; 5285 5286 PetscFunctionBegin; 5287 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5288 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5289 if (!Nf) { 5290 ierr = DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 5291 } else { 5292 ierr = DMSetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 5293 } 5294 PetscFunctionReturn(0); 5295 } 5296 5297 /* Complete labels that are being used for FEM BC */ 5298 static PetscErrorCode DMCompleteBoundaryLabel_Internal(DM dm, PetscDS ds, PetscInt field, PetscInt bdNum, DMLabel label) 5299 { 5300 PetscObject obj; 5301 PetscClassId id; 5302 PetscInt Nbd, bd; 5303 PetscBool isFE = PETSC_FALSE; 5304 PetscBool duplicate = PETSC_FALSE; 5305 PetscErrorCode ierr; 5306 5307 PetscFunctionBegin; 5308 ierr = DMGetField(dm, field, NULL, &obj);CHKERRQ(ierr); 5309 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5310 if (id == PETSCFE_CLASSID) isFE = PETSC_TRUE; 5311 if (isFE && label) { 5312 /* Only want to modify label once */ 5313 ierr = PetscDSGetNumBoundary(ds, &Nbd);CHKERRQ(ierr); 5314 for (bd = 0; bd < PetscMin(Nbd, bdNum); ++bd) { 5315 DMLabel l; 5316 5317 ierr = PetscDSGetBoundary(ds, bd, NULL, NULL, NULL, &l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5318 duplicate = l == label ? PETSC_TRUE : PETSC_FALSE; 5319 if (duplicate) break; 5320 } 5321 if (!duplicate) { 5322 DM plex; 5323 5324 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 5325 if (plex) {ierr = DMPlexLabelComplete(plex, label);CHKERRQ(ierr);} 5326 ierr = DMDestroy(&plex);CHKERRQ(ierr); 5327 } 5328 } 5329 PetscFunctionReturn(0); 5330 } 5331 5332 static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew) 5333 { 5334 DMSpace *tmpd; 5335 PetscInt Nds = dm->Nds, s; 5336 PetscErrorCode ierr; 5337 5338 PetscFunctionBegin; 5339 if (Nds >= NdsNew) PetscFunctionReturn(0); 5340 ierr = PetscMalloc1(NdsNew, &tmpd);CHKERRQ(ierr); 5341 for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s]; 5342 for (s = Nds; s < NdsNew; ++s) {tmpd[s].ds = NULL; tmpd[s].label = NULL; tmpd[s].fields = NULL;} 5343 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 5344 dm->Nds = NdsNew; 5345 dm->probs = tmpd; 5346 PetscFunctionReturn(0); 5347 } 5348 5349 /*@ 5350 DMGetNumDS - Get the number of discrete systems in the DM 5351 5352 Not collective 5353 5354 Input Parameter: 5355 . dm - The DM 5356 5357 Output Parameter: 5358 . Nds - The number of PetscDS objects 5359 5360 Level: intermediate 5361 5362 .seealso: DMGetDS(), DMGetCellDS() 5363 @*/ 5364 PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds) 5365 { 5366 PetscFunctionBegin; 5367 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5368 PetscValidIntPointer(Nds, 2); 5369 *Nds = dm->Nds; 5370 PetscFunctionReturn(0); 5371 } 5372 5373 /*@ 5374 DMClearDS - Remove all discrete systems from the DM 5375 5376 Logically collective on dm 5377 5378 Input Parameter: 5379 . dm - The DM 5380 5381 Level: intermediate 5382 5383 .seealso: DMGetNumDS(), DMGetDS(), DMSetField() 5384 @*/ 5385 PetscErrorCode DMClearDS(DM dm) 5386 { 5387 PetscInt s; 5388 PetscErrorCode ierr; 5389 5390 PetscFunctionBegin; 5391 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5392 for (s = 0; s < dm->Nds; ++s) { 5393 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 5394 ierr = DMLabelDestroy(&dm->probs[s].label);CHKERRQ(ierr); 5395 ierr = ISDestroy(&dm->probs[s].fields);CHKERRQ(ierr); 5396 } 5397 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 5398 dm->probs = NULL; 5399 dm->Nds = 0; 5400 PetscFunctionReturn(0); 5401 } 5402 5403 /*@ 5404 DMGetDS - Get the default PetscDS 5405 5406 Not collective 5407 5408 Input Parameter: 5409 . dm - The DM 5410 5411 Output Parameter: 5412 . prob - The default PetscDS 5413 5414 Level: intermediate 5415 5416 .seealso: DMGetCellDS(), DMGetRegionDS() 5417 @*/ 5418 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 5419 { 5420 PetscErrorCode ierr; 5421 5422 PetscFunctionBeginHot; 5423 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5424 PetscValidPointer(prob, 2); 5425 if (dm->Nds <= 0) { 5426 PetscDS ds; 5427 5428 ierr = PetscDSCreate(PETSC_COMM_SELF, &ds);CHKERRQ(ierr); 5429 ierr = DMSetRegionDS(dm, NULL, NULL, ds);CHKERRQ(ierr); 5430 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 5431 } 5432 *prob = dm->probs[0].ds; 5433 PetscFunctionReturn(0); 5434 } 5435 5436 /*@ 5437 DMGetCellDS - Get the PetscDS defined on a given cell 5438 5439 Not collective 5440 5441 Input Parameters: 5442 + dm - The DM 5443 - point - Cell for the DS 5444 5445 Output Parameter: 5446 . prob - The PetscDS defined on the given cell 5447 5448 Level: developer 5449 5450 .seealso: DMGetDS(), DMSetRegionDS() 5451 @*/ 5452 PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob) 5453 { 5454 PetscDS probDef = NULL; 5455 PetscInt s; 5456 PetscErrorCode ierr; 5457 5458 PetscFunctionBeginHot; 5459 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5460 PetscValidPointer(prob, 3); 5461 PetscCheckFalse(point < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %D", point); 5462 *prob = NULL; 5463 for (s = 0; s < dm->Nds; ++s) { 5464 PetscInt val; 5465 5466 if (!dm->probs[s].label) {probDef = dm->probs[s].ds;} 5467 else { 5468 ierr = DMLabelGetValue(dm->probs[s].label, point, &val);CHKERRQ(ierr); 5469 if (val >= 0) {*prob = dm->probs[s].ds; break;} 5470 } 5471 } 5472 if (!*prob) *prob = probDef; 5473 PetscFunctionReturn(0); 5474 } 5475 5476 /*@ 5477 DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel 5478 5479 Not collective 5480 5481 Input Parameters: 5482 + dm - The DM 5483 - label - The DMLabel defining the mesh region, or NULL for the entire mesh 5484 5485 Output Parameters: 5486 + fields - The IS containing the DM field numbers for the fields in this DS, or NULL 5487 - prob - The PetscDS defined on the given region, or NULL 5488 5489 Note: 5490 If a non-NULL label is given, but there is no PetscDS on that specific label, 5491 the PetscDS for the full domain (if present) is returned. Returns with 5492 fields=NULL and prob=NULL if there is no PetscDS for the full domain. 5493 5494 Level: advanced 5495 5496 .seealso: DMGetRegionNumDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5497 @*/ 5498 PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds) 5499 { 5500 PetscInt Nds = dm->Nds, s; 5501 5502 PetscFunctionBegin; 5503 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5504 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5505 if (fields) {PetscValidPointer(fields, 3); *fields = NULL;} 5506 if (ds) {PetscValidPointer(ds, 4); *ds = NULL;} 5507 for (s = 0; s < Nds; ++s) { 5508 if (dm->probs[s].label == label || !dm->probs[s].label) { 5509 if (fields) *fields = dm->probs[s].fields; 5510 if (ds) *ds = dm->probs[s].ds; 5511 if (dm->probs[s].label) PetscFunctionReturn(0); 5512 } 5513 } 5514 PetscFunctionReturn(0); 5515 } 5516 5517 /*@ 5518 DMSetRegionDS - Set the PetscDS for a given mesh region, defined by a DMLabel 5519 5520 Collective on dm 5521 5522 Input Parameters: 5523 + dm - The DM 5524 . label - The DMLabel defining the mesh region, or NULL for the entire mesh 5525 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL for all fields 5526 - prob - The PetscDS defined on the given cell 5527 5528 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. If DS is replaced, 5529 the fields argument is ignored. 5530 5531 Level: advanced 5532 5533 .seealso: DMGetRegionDS(), DMSetRegionNumDS(), DMGetDS(), DMGetCellDS() 5534 @*/ 5535 PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds) 5536 { 5537 PetscInt Nds = dm->Nds, s; 5538 PetscErrorCode ierr; 5539 5540 PetscFunctionBegin; 5541 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5542 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5543 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4); 5544 for (s = 0; s < Nds; ++s) { 5545 if (dm->probs[s].label == label) { 5546 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 5547 dm->probs[s].ds = ds; 5548 PetscFunctionReturn(0); 5549 } 5550 } 5551 ierr = DMDSEnlarge_Static(dm, Nds+1);CHKERRQ(ierr); 5552 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 5553 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr); 5554 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr); 5555 if (!label) { 5556 /* Put the NULL label at the front, so it is returned as the default */ 5557 for (s = Nds-1; s >=0; --s) dm->probs[s+1] = dm->probs[s]; 5558 Nds = 0; 5559 } 5560 dm->probs[Nds].label = label; 5561 dm->probs[Nds].fields = fields; 5562 dm->probs[Nds].ds = ds; 5563 PetscFunctionReturn(0); 5564 } 5565 5566 /*@ 5567 DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number 5568 5569 Not collective 5570 5571 Input Parameters: 5572 + dm - The DM 5573 - num - The region number, in [0, Nds) 5574 5575 Output Parameters: 5576 + label - The region label, or NULL 5577 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL 5578 - ds - The PetscDS defined on the given region, or NULL 5579 5580 Level: advanced 5581 5582 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5583 @*/ 5584 PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds) 5585 { 5586 PetscInt Nds; 5587 PetscErrorCode ierr; 5588 5589 PetscFunctionBegin; 5590 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5591 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5592 PetscCheckFalse((num < 0) || (num >= Nds),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds); 5593 if (label) { 5594 PetscValidPointer(label, 3); 5595 *label = dm->probs[num].label; 5596 } 5597 if (fields) { 5598 PetscValidPointer(fields, 4); 5599 *fields = dm->probs[num].fields; 5600 } 5601 if (ds) { 5602 PetscValidPointer(ds, 5); 5603 *ds = dm->probs[num].ds; 5604 } 5605 PetscFunctionReturn(0); 5606 } 5607 5608 /*@ 5609 DMSetRegionNumDS - Set the PetscDS for a given mesh region, defined by the region number 5610 5611 Not collective 5612 5613 Input Parameters: 5614 + dm - The DM 5615 . num - The region number, in [0, Nds) 5616 . label - The region label, or NULL 5617 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL to prevent setting 5618 - ds - The PetscDS defined on the given region, or NULL to prevent setting 5619 5620 Level: advanced 5621 5622 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5623 @*/ 5624 PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds) 5625 { 5626 PetscInt Nds; 5627 PetscErrorCode ierr; 5628 5629 PetscFunctionBegin; 5630 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5631 if (label) {PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);} 5632 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5633 PetscCheckFalse((num < 0) || (num >= Nds),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds); 5634 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 5635 ierr = DMLabelDestroy(&dm->probs[num].label);CHKERRQ(ierr); 5636 dm->probs[num].label = label; 5637 if (fields) { 5638 PetscValidHeaderSpecific(fields, IS_CLASSID, 4); 5639 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr); 5640 ierr = ISDestroy(&dm->probs[num].fields);CHKERRQ(ierr); 5641 dm->probs[num].fields = fields; 5642 } 5643 if (ds) { 5644 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5); 5645 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr); 5646 ierr = PetscDSDestroy(&dm->probs[num].ds);CHKERRQ(ierr); 5647 dm->probs[num].ds = ds; 5648 } 5649 PetscFunctionReturn(0); 5650 } 5651 5652 /*@ 5653 DMFindRegionNum - Find the region number for a given PetscDS, or -1 if it is not found. 5654 5655 Not collective 5656 5657 Input Parameters: 5658 + dm - The DM 5659 - ds - The PetscDS defined on the given region 5660 5661 Output Parameter: 5662 . num - The region number, in [0, Nds), or -1 if not found 5663 5664 Level: advanced 5665 5666 .seealso: DMGetRegionNumDS(), DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5667 @*/ 5668 PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num) 5669 { 5670 PetscInt Nds, n; 5671 PetscErrorCode ierr; 5672 5673 PetscFunctionBegin; 5674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5675 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2); 5676 PetscValidPointer(num, 3); 5677 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5678 for (n = 0; n < Nds; ++n) if (ds == dm->probs[n].ds) break; 5679 if (n >= Nds) *num = -1; 5680 else *num = n; 5681 PetscFunctionReturn(0); 5682 } 5683 5684 /*@C 5685 DMCreateFEDefault - Create a PetscFE based on the celltype for the mesh 5686 5687 Not collective 5688 5689 Input Parameters: 5690 + dm - The DM 5691 . Nc - The number of components for the field 5692 . prefix - The options prefix for the output PetscFE, or NULL 5693 - qorder - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree 5694 5695 Output Parameter: 5696 . fem - The PetscFE 5697 5698 Note: This is a convenience method that just calls PetscFECreateByCell() underneath. 5699 5700 Level: intermediate 5701 5702 .seealso: PetscFECreateByCell(), DMAddField(), DMCreateDS(), DMGetCellDS(), DMGetRegionDS() 5703 @*/ 5704 PetscErrorCode DMCreateFEDefault(DM dm, PetscInt Nc, const char prefix[], PetscInt qorder, PetscFE *fem) 5705 { 5706 DMPolytopeType ct; 5707 PetscInt dim, cStart; 5708 PetscErrorCode ierr; 5709 5710 PetscFunctionBegin; 5711 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5712 PetscValidLogicalCollectiveInt(dm, Nc, 2); 5713 if (prefix) PetscValidCharPointer(prefix, 3); 5714 PetscValidLogicalCollectiveInt(dm, qorder, 4); 5715 PetscValidPointer(fem, 5); 5716 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5717 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 5718 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 5719 ierr = PetscFECreateByCell(PETSC_COMM_SELF, dim, Nc, ct, prefix, qorder, fem);CHKERRQ(ierr); 5720 PetscFunctionReturn(0); 5721 } 5722 5723 /*@ 5724 DMCreateDS - Create the discrete systems for the DM based upon the fields added to the DM 5725 5726 Collective on dm 5727 5728 Input Parameter: 5729 . dm - The DM 5730 5731 Options Database Keys: 5732 . -dm_petscds_view - View all the PetscDS objects in this DM 5733 5734 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. 5735 5736 Level: intermediate 5737 5738 .seealso: DMSetField, DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5739 @*/ 5740 PetscErrorCode DMCreateDS(DM dm) 5741 { 5742 MPI_Comm comm; 5743 PetscDS dsDef; 5744 DMLabel *labelSet; 5745 PetscInt dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k; 5746 PetscBool doSetup = PETSC_TRUE, flg; 5747 PetscErrorCode ierr; 5748 5749 PetscFunctionBegin; 5750 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5751 if (!dm->fields) PetscFunctionReturn(0); 5752 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 5753 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 5754 /* Determine how many regions we have */ 5755 ierr = PetscMalloc1(Nf, &labelSet);CHKERRQ(ierr); 5756 Nl = 0; 5757 Ndef = 0; 5758 for (f = 0; f < Nf; ++f) { 5759 DMLabel label = dm->fields[f].label; 5760 PetscInt l; 5761 5762 #ifdef PETSC_HAVE_LIBCEED 5763 /* Move CEED context to discretizations */ 5764 { 5765 PetscClassId id; 5766 5767 ierr = PetscObjectGetClassId(dm->fields[f].disc, &id);CHKERRQ(ierr); 5768 if (id == PETSCFE_CLASSID) { 5769 Ceed ceed; 5770 5771 ierr = DMGetCeed(dm, &ceed);CHKERRQ(ierr); 5772 ierr = PetscFESetCeed((PetscFE) dm->fields[f].disc, ceed);CHKERRQ(ierr); 5773 } 5774 } 5775 #endif 5776 if (!label) {++Ndef; continue;} 5777 for (l = 0; l < Nl; ++l) if (label == labelSet[l]) break; 5778 if (l < Nl) continue; 5779 labelSet[Nl++] = label; 5780 } 5781 /* Create default DS if there are no labels to intersect with */ 5782 ierr = DMGetRegionDS(dm, NULL, NULL, &dsDef);CHKERRQ(ierr); 5783 if (!dsDef && Ndef && !Nl) { 5784 IS fields; 5785 PetscInt *fld, nf; 5786 5787 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) ++nf; 5788 PetscCheckFalse(!nf,comm, PETSC_ERR_PLIB, "All fields have labels, but we are trying to create a default DS"); 5789 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr); 5790 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) fld[nf++] = f; 5791 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5792 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5793 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5794 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5795 5796 ierr = PetscDSCreate(PETSC_COMM_SELF, &dsDef);CHKERRQ(ierr); 5797 ierr = DMSetRegionDS(dm, NULL, fields, dsDef);CHKERRQ(ierr); 5798 ierr = PetscDSDestroy(&dsDef);CHKERRQ(ierr); 5799 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5800 } 5801 ierr = DMGetRegionDS(dm, NULL, NULL, &dsDef);CHKERRQ(ierr); 5802 if (dsDef) {ierr = PetscDSSetCoordinateDimension(dsDef, dE);CHKERRQ(ierr);} 5803 /* Intersect labels with default fields */ 5804 if (Ndef && Nl) { 5805 DM plex; 5806 DMLabel cellLabel; 5807 IS fieldIS, allcellIS, defcellIS = NULL; 5808 PetscInt *fields; 5809 const PetscInt *cells; 5810 PetscInt depth, nf = 0, n, c; 5811 5812 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 5813 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 5814 ierr = DMGetStratumIS(plex, "dim", depth, &allcellIS);CHKERRQ(ierr); 5815 if (!allcellIS) {ierr = DMGetStratumIS(plex, "depth", depth, &allcellIS);CHKERRQ(ierr);} 5816 /* TODO This looks like it only works for one label */ 5817 for (l = 0; l < Nl; ++l) { 5818 DMLabel label = labelSet[l]; 5819 IS pointIS; 5820 5821 ierr = ISDestroy(&defcellIS);CHKERRQ(ierr); 5822 ierr = DMLabelGetStratumIS(label, 1, &pointIS);CHKERRQ(ierr); 5823 ierr = ISDifference(allcellIS, pointIS, &defcellIS);CHKERRQ(ierr); 5824 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 5825 } 5826 ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 5827 5828 ierr = DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel);CHKERRQ(ierr); 5829 ierr = ISGetLocalSize(defcellIS, &n);CHKERRQ(ierr); 5830 ierr = ISGetIndices(defcellIS, &cells);CHKERRQ(ierr); 5831 for (c = 0; c < n; ++c) {ierr = DMLabelSetValue(cellLabel, cells[c], 1);CHKERRQ(ierr);} 5832 ierr = ISRestoreIndices(defcellIS, &cells);CHKERRQ(ierr); 5833 ierr = ISDestroy(&defcellIS);CHKERRQ(ierr); 5834 ierr = DMPlexLabelComplete(plex, cellLabel);CHKERRQ(ierr); 5835 5836 ierr = PetscMalloc1(Ndef, &fields);CHKERRQ(ierr); 5837 for (f = 0; f < Nf; ++f) if (!dm->fields[f].label) fields[nf++] = f; 5838 ierr = ISCreate(PETSC_COMM_SELF, &fieldIS);CHKERRQ(ierr); 5839 ierr = PetscObjectSetOptionsPrefix((PetscObject) fieldIS, "dm_fields_");CHKERRQ(ierr); 5840 ierr = ISSetType(fieldIS, ISGENERAL);CHKERRQ(ierr); 5841 ierr = ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER);CHKERRQ(ierr); 5842 5843 ierr = PetscDSCreate(PETSC_COMM_SELF, &dsDef);CHKERRQ(ierr); 5844 ierr = DMSetRegionDS(dm, cellLabel, fieldIS, dsDef);CHKERRQ(ierr); 5845 ierr = PetscDSSetCoordinateDimension(dsDef, dE);CHKERRQ(ierr); 5846 ierr = DMLabelDestroy(&cellLabel);CHKERRQ(ierr); 5847 ierr = PetscDSDestroy(&dsDef);CHKERRQ(ierr); 5848 ierr = ISDestroy(&fieldIS);CHKERRQ(ierr); 5849 ierr = DMDestroy(&plex);CHKERRQ(ierr); 5850 } 5851 /* Create label DSes 5852 - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS 5853 */ 5854 /* TODO Should check that labels are disjoint */ 5855 for (l = 0; l < Nl; ++l) { 5856 DMLabel label = labelSet[l]; 5857 PetscDS ds; 5858 IS fields; 5859 PetscInt *fld, nf; 5860 5861 ierr = PetscDSCreate(PETSC_COMM_SELF, &ds);CHKERRQ(ierr); 5862 for (f = 0, nf = 0; f < Nf; ++f) if (label == dm->fields[f].label || !dm->fields[f].label) ++nf; 5863 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr); 5864 for (f = 0, nf = 0; f < Nf; ++f) if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f; 5865 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5866 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5867 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5868 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5869 ierr = DMSetRegionDS(dm, label, fields, ds);CHKERRQ(ierr); 5870 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5871 ierr = PetscDSSetCoordinateDimension(ds, dE);CHKERRQ(ierr); 5872 { 5873 DMPolytopeType ct; 5874 PetscInt lStart, lEnd; 5875 PetscBool isCohesiveLocal = PETSC_FALSE, isCohesive; 5876 5877 ierr = DMLabelGetBounds(label, &lStart, &lEnd);CHKERRQ(ierr); 5878 if (lStart >= 0) { 5879 ierr = DMPlexGetCellType(dm, lStart, &ct);CHKERRQ(ierr); 5880 switch (ct) { 5881 case DM_POLYTOPE_POINT_PRISM_TENSOR: 5882 case DM_POLYTOPE_SEG_PRISM_TENSOR: 5883 case DM_POLYTOPE_TRI_PRISM_TENSOR: 5884 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 5885 isCohesiveLocal = PETSC_TRUE;break; 5886 default: break; 5887 } 5888 } 5889 ierr = MPI_Allreduce(&isCohesiveLocal, &isCohesive, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRMPI(ierr); 5890 for (f = 0, nf = 0; f < Nf; ++f) { 5891 if (label == dm->fields[f].label || !dm->fields[f].label) { 5892 if (label == dm->fields[f].label) { 5893 ierr = PetscDSSetDiscretization(ds, nf, NULL);CHKERRQ(ierr); 5894 ierr = PetscDSSetCohesive(ds, nf, isCohesive);CHKERRQ(ierr); 5895 } 5896 ++nf; 5897 } 5898 } 5899 } 5900 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 5901 } 5902 ierr = PetscFree(labelSet);CHKERRQ(ierr); 5903 /* Set fields in DSes */ 5904 for (s = 0; s < dm->Nds; ++s) { 5905 PetscDS ds = dm->probs[s].ds; 5906 IS fields = dm->probs[s].fields; 5907 const PetscInt *fld; 5908 PetscInt nf, dsnf; 5909 PetscBool isCohesive; 5910 5911 ierr = PetscDSGetNumFields(ds, &dsnf);CHKERRQ(ierr); 5912 ierr = PetscDSIsCohesive(ds, &isCohesive);CHKERRQ(ierr); 5913 ierr = ISGetLocalSize(fields, &nf);CHKERRQ(ierr); 5914 ierr = ISGetIndices(fields, &fld);CHKERRQ(ierr); 5915 for (f = 0; f < nf; ++f) { 5916 PetscObject disc = dm->fields[fld[f]].disc; 5917 PetscBool isCohesiveField; 5918 PetscClassId id; 5919 5920 /* Handle DS with no fields */ 5921 if (dsnf) {ierr = PetscDSGetCohesive(ds, f, &isCohesiveField);CHKERRQ(ierr);} 5922 /* If this is a cohesive cell, then regular fields need the lower dimensional discretization */ 5923 if (isCohesive && !isCohesiveField) {ierr = PetscFEGetHeightSubspace((PetscFE) disc, 1, (PetscFE *) &disc);CHKERRQ(ierr);} 5924 ierr = PetscDSSetDiscretization(ds, f, disc);CHKERRQ(ierr); 5925 /* We allow people to have placeholder fields and construct the Section by hand */ 5926 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 5927 if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE; 5928 } 5929 ierr = ISRestoreIndices(fields, &fld);CHKERRQ(ierr); 5930 } 5931 /* Allow k-jet tabulation */ 5932 ierr = PetscOptionsGetInt(NULL, ((PetscObject) dm)->prefix, "-dm_ds_jet_degree", &k, &flg);CHKERRQ(ierr); 5933 if (flg) { 5934 for (s = 0; s < dm->Nds; ++s) { 5935 PetscDS ds = dm->probs[s].ds; 5936 PetscInt Nf, f; 5937 5938 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 5939 for (f = 0; f < Nf; ++f) {ierr = PetscDSSetJetDegree(ds, f, k);CHKERRQ(ierr);} 5940 } 5941 } 5942 /* Setup DSes */ 5943 if (doSetup) { 5944 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);} 5945 } 5946 PetscFunctionReturn(0); 5947 } 5948 5949 /*@ 5950 DMComputeExactSolution - Compute the exact solution for a given DM, using the PetscDS information. 5951 5952 Collective on DM 5953 5954 Input Parameters: 5955 + dm - The DM 5956 - time - The time 5957 5958 Output Parameters: 5959 + u - The vector will be filled with exact solution values, or NULL 5960 - u_t - The vector will be filled with the time derivative of exact solution values, or NULL 5961 5962 Note: The user must call PetscDSSetExactSolution() beforehand 5963 5964 Level: developer 5965 5966 .seealso: PetscDSSetExactSolution() 5967 @*/ 5968 PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t) 5969 { 5970 PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 5971 void **ectxs; 5972 PetscInt Nf, Nds, s; 5973 PetscErrorCode ierr; 5974 5975 PetscFunctionBegin; 5976 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5977 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 5978 if (u_t) PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4); 5979 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5980 ierr = PetscMalloc2(Nf, &exacts, Nf, &ectxs);CHKERRQ(ierr); 5981 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5982 for (s = 0; s < Nds; ++s) { 5983 PetscDS ds; 5984 DMLabel label; 5985 IS fieldIS; 5986 const PetscInt *fields, id = 1; 5987 PetscInt dsNf, f; 5988 5989 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 5990 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 5991 ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr); 5992 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr); 5993 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr); 5994 if (u) { 5995 for (f = 0; f < dsNf; ++f) { 5996 const PetscInt field = fields[f]; 5997 ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 5998 } 5999 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 6000 if (label) { 6001 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); 6002 } else { 6003 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); 6004 } 6005 } 6006 if (u_t) { 6007 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr); 6008 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr); 6009 for (f = 0; f < dsNf; ++f) { 6010 const PetscInt field = fields[f]; 6011 ierr = PetscDSGetExactSolutionTimeDerivative(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 6012 } 6013 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 6014 if (label) { 6015 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr); 6016 } else { 6017 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr); 6018 } 6019 } 6020 } 6021 if (u) { 6022 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution");CHKERRQ(ierr); 6023 ierr = PetscObjectSetOptionsPrefix((PetscObject) u, "exact_");CHKERRQ(ierr); 6024 } 6025 if (u_t) { 6026 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution Time Derivative");CHKERRQ(ierr); 6027 ierr = PetscObjectSetOptionsPrefix((PetscObject) u_t, "exact_t_");CHKERRQ(ierr); 6028 } 6029 ierr = PetscFree2(exacts, ectxs);CHKERRQ(ierr); 6030 PetscFunctionReturn(0); 6031 } 6032 6033 PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscDS ds) 6034 { 6035 PetscDS dsNew; 6036 DSBoundary b; 6037 PetscInt cdim, Nf, f; 6038 PetscBool isCohesive; 6039 void *ctx; 6040 PetscErrorCode ierr; 6041 6042 PetscFunctionBegin; 6043 ierr = PetscDSCreate(PetscObjectComm((PetscObject) ds), &dsNew);CHKERRQ(ierr); 6044 ierr = PetscDSCopyConstants(ds, dsNew);CHKERRQ(ierr); 6045 ierr = PetscDSCopyExactSolutions(ds, dsNew);CHKERRQ(ierr); 6046 ierr = PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew);CHKERRQ(ierr); 6047 ierr = PetscDSCopyEquations(ds, dsNew);CHKERRQ(ierr); 6048 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 6049 for (f = 0; f < Nf; ++f) { 6050 ierr = PetscDSGetContext(ds, f, &ctx);CHKERRQ(ierr); 6051 ierr = PetscDSSetContext(dsNew, f, ctx);CHKERRQ(ierr); 6052 ierr = PetscDSGetCohesive(ds, f, &isCohesive);CHKERRQ(ierr); 6053 ierr = PetscDSSetCohesive(dsNew, f, isCohesive);CHKERRQ(ierr); 6054 } 6055 if (Nf) { 6056 ierr = PetscDSGetCoordinateDimension(ds, &cdim);CHKERRQ(ierr); 6057 ierr = PetscDSSetCoordinateDimension(dsNew, cdim);CHKERRQ(ierr); 6058 } 6059 ierr = PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew);CHKERRQ(ierr); 6060 for (b = dsNew->boundary; b; b = b->next) { 6061 ierr = DMGetLabel(dm, b->lname, &b->label);CHKERRQ(ierr); 6062 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */ 6063 //PetscCheckFalse(!b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name); 6064 } 6065 6066 ierr = DMSetRegionDS(dm, label, fields, dsNew);CHKERRQ(ierr); 6067 ierr = PetscDSDestroy(&dsNew);CHKERRQ(ierr); 6068 PetscFunctionReturn(0); 6069 } 6070 6071 /*@ 6072 DMCopyDS - Copy the discrete systems for the DM into another DM 6073 6074 Collective on dm 6075 6076 Input Parameter: 6077 . dm - The DM 6078 6079 Output Parameter: 6080 . newdm - The DM 6081 6082 Level: advanced 6083 6084 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 6085 @*/ 6086 PetscErrorCode DMCopyDS(DM dm, DM newdm) 6087 { 6088 PetscInt Nds, s; 6089 PetscErrorCode ierr; 6090 6091 PetscFunctionBegin; 6092 if (dm == newdm) PetscFunctionReturn(0); 6093 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 6094 ierr = DMClearDS(newdm);CHKERRQ(ierr); 6095 for (s = 0; s < Nds; ++s) { 6096 DMLabel label; 6097 IS fields; 6098 PetscDS ds, newds; 6099 PetscInt Nbd, bd; 6100 6101 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 6102 /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */ 6103 ierr = DMTransferDS_Internal(newdm, label, fields, ds);CHKERRQ(ierr); 6104 /* Commplete new labels in the new DS */ 6105 ierr = DMGetRegionDS(newdm, label, NULL, &newds);CHKERRQ(ierr); 6106 ierr = PetscDSGetNumBoundary(newds, &Nbd);CHKERRQ(ierr); 6107 for (bd = 0; bd < Nbd; ++bd) { 6108 PetscWeakForm wf; 6109 DMLabel label; 6110 PetscInt field; 6111 6112 ierr = PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6113 ierr = DMCompleteBoundaryLabel_Internal(newdm, newds, field, bd, label);CHKERRQ(ierr); 6114 ierr = PetscWeakFormReplaceLabel(wf, label);CHKERRQ(ierr); 6115 } 6116 } 6117 PetscFunctionReturn(0); 6118 } 6119 6120 /*@ 6121 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 6122 6123 Collective on dm 6124 6125 Input Parameter: 6126 . dm - The DM 6127 6128 Output Parameter: 6129 . newdm - The DM 6130 6131 Level: advanced 6132 6133 .seealso: DMCopyFields(), DMCopyDS() 6134 @*/ 6135 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 6136 { 6137 PetscErrorCode ierr; 6138 6139 PetscFunctionBegin; 6140 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 6141 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 6142 PetscFunctionReturn(0); 6143 } 6144 6145 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 6146 { 6147 DM dm_coord,dmc_coord; 6148 PetscErrorCode ierr; 6149 Vec coords,ccoords; 6150 Mat inject; 6151 PetscFunctionBegin; 6152 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 6153 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 6154 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 6155 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 6156 if (coords && !ccoords) { 6157 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 6158 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 6159 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 6160 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 6161 ierr = MatDestroy(&inject);CHKERRQ(ierr); 6162 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 6163 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 6164 } 6165 PetscFunctionReturn(0); 6166 } 6167 6168 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 6169 { 6170 DM dm_coord,subdm_coord; 6171 PetscErrorCode ierr; 6172 Vec coords,ccoords,clcoords; 6173 VecScatter *scat_i,*scat_g; 6174 PetscFunctionBegin; 6175 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 6176 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 6177 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 6178 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 6179 if (coords && !ccoords) { 6180 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 6181 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 6182 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 6183 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 6184 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 6185 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6186 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6187 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6188 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6189 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 6190 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 6191 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 6192 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 6193 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 6194 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 6195 ierr = PetscFree(scat_i);CHKERRQ(ierr); 6196 ierr = PetscFree(scat_g);CHKERRQ(ierr); 6197 } 6198 PetscFunctionReturn(0); 6199 } 6200 6201 /*@ 6202 DMGetDimension - Return the topological dimension of the DM 6203 6204 Not collective 6205 6206 Input Parameter: 6207 . dm - The DM 6208 6209 Output Parameter: 6210 . dim - The topological dimension 6211 6212 Level: beginner 6213 6214 .seealso: DMSetDimension(), DMCreate() 6215 @*/ 6216 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 6217 { 6218 PetscFunctionBegin; 6219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6220 PetscValidIntPointer(dim, 2); 6221 *dim = dm->dim; 6222 PetscFunctionReturn(0); 6223 } 6224 6225 /*@ 6226 DMSetDimension - Set the topological dimension of the DM 6227 6228 Collective on dm 6229 6230 Input Parameters: 6231 + dm - The DM 6232 - dim - The topological dimension 6233 6234 Level: beginner 6235 6236 .seealso: DMGetDimension(), DMCreate() 6237 @*/ 6238 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 6239 { 6240 PetscDS ds; 6241 PetscInt Nds, n; 6242 PetscErrorCode ierr; 6243 6244 PetscFunctionBegin; 6245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6246 PetscValidLogicalCollectiveInt(dm, dim, 2); 6247 dm->dim = dim; 6248 if (dm->dim >= 0) { 6249 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 6250 for (n = 0; n < Nds; ++n) { 6251 ierr = DMGetRegionNumDS(dm, n, NULL, NULL, &ds);CHKERRQ(ierr); 6252 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr);} 6253 } 6254 } 6255 PetscFunctionReturn(0); 6256 } 6257 6258 /*@ 6259 DMGetDimPoints - Get the half-open interval for all points of a given dimension 6260 6261 Collective on dm 6262 6263 Input Parameters: 6264 + dm - the DM 6265 - dim - the dimension 6266 6267 Output Parameters: 6268 + pStart - The first point of the given dimension 6269 - pEnd - The first point following points of the given dimension 6270 6271 Note: 6272 The points are vertices in the Hasse diagram encoding the topology. This is explained in 6273 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 6274 then the interval is empty. 6275 6276 Level: intermediate 6277 6278 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 6279 @*/ 6280 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 6281 { 6282 PetscInt d; 6283 PetscErrorCode ierr; 6284 6285 PetscFunctionBegin; 6286 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6287 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 6288 PetscCheckFalse((dim < 0) || (dim > d),PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 6289 PetscCheckFalse(!dm->ops->getdimpoints,PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name); 6290 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 6291 PetscFunctionReturn(0); 6292 } 6293 6294 /*@ 6295 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 6296 6297 Collective on dm 6298 6299 Input Parameters: 6300 + dm - the DM 6301 - c - coordinate vector 6302 6303 Notes: 6304 The coordinates do include those for ghost points, which are in the local vector. 6305 6306 The vector c should be destroyed by the caller. 6307 6308 Level: intermediate 6309 6310 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMDASetUniformCoordinates() 6311 @*/ 6312 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 6313 { 6314 PetscErrorCode ierr; 6315 6316 PetscFunctionBegin; 6317 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6318 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 6319 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 6320 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 6321 dm->coordinates = c; 6322 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 6323 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 6324 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 6325 PetscFunctionReturn(0); 6326 } 6327 6328 /*@ 6329 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 6330 6331 Not collective 6332 6333 Input Parameters: 6334 + dm - the DM 6335 - c - coordinate vector 6336 6337 Notes: 6338 The coordinates of ghost points can be set using DMSetCoordinates() 6339 followed by DMGetCoordinatesLocal(). This is intended to enable the 6340 setting of ghost coordinates outside of the domain. 6341 6342 The vector c should be destroyed by the caller. 6343 6344 Level: intermediate 6345 6346 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 6347 @*/ 6348 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 6349 { 6350 PetscErrorCode ierr; 6351 6352 PetscFunctionBegin; 6353 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6354 if (c) PetscValidHeaderSpecific(c,VEC_CLASSID,2); 6355 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 6356 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 6357 6358 dm->coordinatesLocal = c; 6359 6360 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 6361 PetscFunctionReturn(0); 6362 } 6363 6364 /*@ 6365 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 6366 6367 Collective on dm 6368 6369 Input Parameter: 6370 . dm - the DM 6371 6372 Output Parameter: 6373 . c - global coordinate vector 6374 6375 Note: 6376 This is a borrowed reference, so the user should NOT destroy this vector. When the DM is 6377 destroyed the array will no longer be valid. 6378 6379 Each process has only the locally-owned portion of the global coordinates (does NOT have the ghost coordinates). 6380 6381 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6382 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6383 6384 Level: intermediate 6385 6386 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMDASetUniformCoordinates() 6387 @*/ 6388 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 6389 { 6390 PetscErrorCode ierr; 6391 6392 PetscFunctionBegin; 6393 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6394 PetscValidPointer(c,2); 6395 if (!dm->coordinates && dm->coordinatesLocal) { 6396 DM cdm = NULL; 6397 PetscBool localized; 6398 6399 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6400 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 6401 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 6402 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 6403 if (localized) { 6404 PetscInt cdim; 6405 6406 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 6407 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 6408 } 6409 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 6410 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 6411 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 6412 } 6413 *c = dm->coordinates; 6414 PetscFunctionReturn(0); 6415 } 6416 6417 /*@ 6418 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 6419 6420 Collective on dm 6421 6422 Input Parameter: 6423 . dm - the DM 6424 6425 Level: advanced 6426 6427 .seealso: DMGetCoordinatesLocalNoncollective() 6428 @*/ 6429 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 6430 { 6431 PetscErrorCode ierr; 6432 6433 PetscFunctionBegin; 6434 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6435 if (!dm->coordinatesLocal && dm->coordinates) { 6436 DM cdm = NULL; 6437 PetscBool localized; 6438 6439 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6440 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 6441 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 6442 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 6443 if (localized) { 6444 PetscInt cdim; 6445 6446 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 6447 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 6448 } 6449 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 6450 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 6451 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 6452 } 6453 PetscFunctionReturn(0); 6454 } 6455 6456 /*@ 6457 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 6458 6459 Collective on dm 6460 6461 Input Parameter: 6462 . dm - the DM 6463 6464 Output Parameter: 6465 . c - coordinate vector 6466 6467 Note: 6468 This is a borrowed reference, so the user should NOT destroy this vector 6469 6470 Each process has the local and ghost coordinates 6471 6472 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6473 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6474 6475 Level: intermediate 6476 6477 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 6478 @*/ 6479 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 6480 { 6481 PetscErrorCode ierr; 6482 6483 PetscFunctionBegin; 6484 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6485 PetscValidPointer(c,2); 6486 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 6487 *c = dm->coordinatesLocal; 6488 PetscFunctionReturn(0); 6489 } 6490 6491 /*@ 6492 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 6493 6494 Not collective 6495 6496 Input Parameter: 6497 . dm - the DM 6498 6499 Output Parameter: 6500 . c - coordinate vector 6501 6502 Level: advanced 6503 6504 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6505 @*/ 6506 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 6507 { 6508 PetscFunctionBegin; 6509 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6510 PetscValidPointer(c,2); 6511 PetscCheckFalse(!dm->coordinatesLocal && dm->coordinates,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 6512 *c = dm->coordinatesLocal; 6513 PetscFunctionReturn(0); 6514 } 6515 6516 /*@ 6517 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 6518 6519 Not collective 6520 6521 Input Parameters: 6522 + dm - the DM 6523 - p - the IS of points whose coordinates will be returned 6524 6525 Output Parameters: 6526 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 6527 - pCoord - the Vec with coordinates of points in p 6528 6529 Note: 6530 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 6531 6532 This creates a new vector, so the user SHOULD destroy this vector 6533 6534 Each process has the local and ghost coordinates 6535 6536 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6537 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6538 6539 Level: advanced 6540 6541 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6542 @*/ 6543 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 6544 { 6545 PetscSection cs, newcs; 6546 Vec coords; 6547 const PetscScalar *arr; 6548 PetscScalar *newarr=NULL; 6549 PetscInt n; 6550 PetscErrorCode ierr; 6551 6552 PetscFunctionBegin; 6553 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6554 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 6555 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 6556 if (pCoord) PetscValidPointer(pCoord, 4); 6557 PetscCheckFalse(!dm->coordinatesLocal,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 6558 PetscCheckFalse(!dm->coordinateDM || !dm->coordinateDM->localSection,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 6559 cs = dm->coordinateDM->localSection; 6560 coords = dm->coordinatesLocal; 6561 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 6562 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 6563 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 6564 if (pCoord) { 6565 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 6566 /* set array in two steps to mimic PETSC_OWN_POINTER */ 6567 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 6568 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 6569 } else { 6570 ierr = PetscFree(newarr);CHKERRQ(ierr); 6571 } 6572 if (pCoordSection) {*pCoordSection = newcs;} 6573 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 6574 PetscFunctionReturn(0); 6575 } 6576 6577 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 6578 { 6579 PetscErrorCode ierr; 6580 6581 PetscFunctionBegin; 6582 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6583 PetscValidPointer(field,2); 6584 if (!dm->coordinateField) { 6585 if (dm->ops->createcoordinatefield) { 6586 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 6587 } 6588 } 6589 *field = dm->coordinateField; 6590 PetscFunctionReturn(0); 6591 } 6592 6593 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 6594 { 6595 PetscErrorCode ierr; 6596 6597 PetscFunctionBegin; 6598 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6599 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 6600 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 6601 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 6602 dm->coordinateField = field; 6603 PetscFunctionReturn(0); 6604 } 6605 6606 /*@ 6607 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 6608 6609 Collective on dm 6610 6611 Input Parameter: 6612 . dm - the DM 6613 6614 Output Parameter: 6615 . cdm - coordinate DM 6616 6617 Level: intermediate 6618 6619 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6620 @*/ 6621 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 6622 { 6623 PetscErrorCode ierr; 6624 6625 PetscFunctionBegin; 6626 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6627 PetscValidPointer(cdm,2); 6628 if (!dm->coordinateDM) { 6629 DM cdm; 6630 6631 PetscCheckFalse(!dm->ops->createcoordinatedm,PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 6632 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 6633 ierr = PetscObjectSetName((PetscObject)cdm, "coordinateDM");CHKERRQ(ierr); 6634 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 6635 * until the call to CreateCoordinateDM) */ 6636 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6637 dm->coordinateDM = cdm; 6638 } 6639 *cdm = dm->coordinateDM; 6640 PetscFunctionReturn(0); 6641 } 6642 6643 /*@ 6644 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 6645 6646 Logically Collective on dm 6647 6648 Input Parameters: 6649 + dm - the DM 6650 - cdm - coordinate DM 6651 6652 Level: intermediate 6653 6654 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6655 @*/ 6656 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 6657 { 6658 PetscErrorCode ierr; 6659 6660 PetscFunctionBegin; 6661 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6662 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 6663 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6664 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6665 dm->coordinateDM = cdm; 6666 PetscFunctionReturn(0); 6667 } 6668 6669 /*@ 6670 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 6671 6672 Not Collective 6673 6674 Input Parameter: 6675 . dm - The DM object 6676 6677 Output Parameter: 6678 . dim - The embedding dimension 6679 6680 Level: intermediate 6681 6682 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6683 @*/ 6684 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 6685 { 6686 PetscFunctionBegin; 6687 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6688 PetscValidIntPointer(dim, 2); 6689 if (dm->dimEmbed == PETSC_DEFAULT) { 6690 dm->dimEmbed = dm->dim; 6691 } 6692 *dim = dm->dimEmbed; 6693 PetscFunctionReturn(0); 6694 } 6695 6696 /*@ 6697 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 6698 6699 Not Collective 6700 6701 Input Parameters: 6702 + dm - The DM object 6703 - dim - The embedding dimension 6704 6705 Level: intermediate 6706 6707 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6708 @*/ 6709 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 6710 { 6711 PetscDS ds; 6712 PetscInt Nds, n; 6713 PetscErrorCode ierr; 6714 6715 PetscFunctionBegin; 6716 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6717 dm->dimEmbed = dim; 6718 if (dm->dim >= 0) { 6719 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 6720 for (n = 0; n < Nds; ++n) { 6721 ierr = DMGetRegionNumDS(dm, n, NULL, NULL, &ds);CHKERRQ(ierr); 6722 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 6723 } 6724 } 6725 PetscFunctionReturn(0); 6726 } 6727 6728 /*@ 6729 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6730 6731 Collective on dm 6732 6733 Input Parameter: 6734 . dm - The DM object 6735 6736 Output Parameter: 6737 . section - The PetscSection object 6738 6739 Level: intermediate 6740 6741 .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6742 @*/ 6743 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 6744 { 6745 DM cdm; 6746 PetscErrorCode ierr; 6747 6748 PetscFunctionBegin; 6749 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6750 PetscValidPointer(section, 2); 6751 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6752 ierr = DMGetLocalSection(cdm, section);CHKERRQ(ierr); 6753 PetscFunctionReturn(0); 6754 } 6755 6756 /*@ 6757 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 6758 6759 Not Collective 6760 6761 Input Parameters: 6762 + dm - The DM object 6763 . dim - The embedding dimension, or PETSC_DETERMINE 6764 - section - The PetscSection object 6765 6766 Level: intermediate 6767 6768 .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6769 @*/ 6770 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 6771 { 6772 DM cdm; 6773 PetscErrorCode ierr; 6774 6775 PetscFunctionBegin; 6776 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6777 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 6778 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6779 ierr = DMSetLocalSection(cdm, section);CHKERRQ(ierr); 6780 if (dim == PETSC_DETERMINE) { 6781 PetscInt d = PETSC_DEFAULT; 6782 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 6783 6784 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6785 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6786 pStart = PetscMax(vStart, pStart); 6787 pEnd = PetscMin(vEnd, pEnd); 6788 for (v = pStart; v < pEnd; ++v) { 6789 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 6790 if (dd) {d = dd; break;} 6791 } 6792 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 6793 } 6794 PetscFunctionReturn(0); 6795 } 6796 6797 /*@ 6798 DMProjectCoordinates - Project coordinates to a different space 6799 6800 Input Parameters: 6801 + dm - The DM object 6802 - disc - The new coordinate discretization 6803 6804 Level: intermediate 6805 6806 .seealso: DMGetCoordinateField() 6807 @*/ 6808 PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc) 6809 { 6810 PetscObject discOld; 6811 PetscClassId classid; 6812 DM cdmOld,cdmNew; 6813 Vec coordsOld,coordsNew; 6814 Mat matInterp; 6815 PetscErrorCode ierr; 6816 6817 PetscFunctionBegin; 6818 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6819 PetscValidHeaderSpecific(disc,PETSCFE_CLASSID,2); 6820 6821 ierr = DMGetCoordinateDM(dm, &cdmOld);CHKERRQ(ierr); 6822 /* Check current discretization is compatible */ 6823 ierr = DMGetField(cdmOld, 0, NULL, &discOld);CHKERRQ(ierr); 6824 ierr = PetscObjectGetClassId(discOld, &classid);CHKERRQ(ierr); 6825 if (classid != PETSCFE_CLASSID) { 6826 if (classid == PETSC_CONTAINER_CLASSID) { 6827 PetscFE feLinear; 6828 DMPolytopeType ct; 6829 PetscInt dim, dE, cStart; 6830 PetscBool simplex; 6831 6832 /* Assume linear vertex coordinates */ 6833 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6834 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 6835 ierr = DMPlexGetHeightStratum(cdmOld, 0, &cStart, NULL);CHKERRQ(ierr); 6836 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 6837 switch (ct) { 6838 case DM_POLYTOPE_TRI_PRISM: 6839 case DM_POLYTOPE_TRI_PRISM_TENSOR: 6840 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot autoamtically create coordinate space for prisms"); 6841 default: break; 6842 } 6843 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 6844 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, 1, -1, &feLinear);CHKERRQ(ierr); 6845 ierr = DMSetField(cdmOld, 0, NULL, (PetscObject) feLinear);CHKERRQ(ierr); 6846 ierr = PetscFEDestroy(&feLinear);CHKERRQ(ierr); 6847 ierr = DMCreateDS(cdmOld);CHKERRQ(ierr); 6848 } else { 6849 const char *discname; 6850 6851 ierr = PetscObjectGetType(discOld, &discname);CHKERRQ(ierr); 6852 SETERRQ(PetscObjectComm(discOld), PETSC_ERR_SUP, "Discretization type %s not supported", discname); 6853 } 6854 } 6855 /* Make a fresh clone of the coordinate DM */ 6856 ierr = DMClone(cdmOld, &cdmNew);CHKERRQ(ierr); 6857 ierr = DMSetField(cdmNew, 0, NULL, (PetscObject) disc);CHKERRQ(ierr); 6858 ierr = DMCreateDS(cdmNew);CHKERRQ(ierr); 6859 /* Project the coordinate vector from old to new space */ 6860 ierr = DMGetCoordinates(dm, &coordsOld);CHKERRQ(ierr); 6861 ierr = DMCreateGlobalVector(cdmNew, &coordsNew);CHKERRQ(ierr); 6862 ierr = DMCreateInterpolation(cdmOld, cdmNew, &matInterp, NULL);CHKERRQ(ierr); 6863 ierr = MatInterpolate(matInterp, coordsOld, coordsNew);CHKERRQ(ierr); 6864 ierr = MatDestroy(&matInterp);CHKERRQ(ierr); 6865 /* Set new coordinate structures */ 6866 ierr = DMSetCoordinateField(dm, NULL);CHKERRQ(ierr); 6867 ierr = DMSetCoordinateDM(dm, cdmNew);CHKERRQ(ierr); 6868 ierr = DMSetCoordinates(dm, coordsNew);CHKERRQ(ierr); 6869 ierr = VecDestroy(&coordsNew);CHKERRQ(ierr); 6870 ierr = DMDestroy(&cdmNew);CHKERRQ(ierr); 6871 PetscFunctionReturn(0); 6872 } 6873 6874 /*@C 6875 DMGetPeriodicity - Get the description of mesh periodicity 6876 6877 Input Parameter: 6878 . dm - The DM object 6879 6880 Output Parameters: 6881 + per - Whether the DM is periodic or not 6882 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6883 . L - If we assume the mesh is a torus, this is the length of each coordinate 6884 - bd - This describes the type of periodicity in each topological dimension 6885 6886 Level: developer 6887 6888 .seealso: DMGetPeriodicity() 6889 @*/ 6890 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 6891 { 6892 PetscFunctionBegin; 6893 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6894 if (per) *per = dm->periodic; 6895 if (L) *L = dm->L; 6896 if (maxCell) *maxCell = dm->maxCell; 6897 if (bd) *bd = dm->bdtype; 6898 PetscFunctionReturn(0); 6899 } 6900 6901 /*@C 6902 DMSetPeriodicity - Set the description of mesh periodicity 6903 6904 Input Parameters: 6905 + dm - The DM object 6906 . per - Whether the DM is periodic or not. 6907 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates. Pass NULL to remove such information. 6908 . L - If we assume the mesh is a torus, this is the length of each coordinate 6909 - bd - This describes the type of periodicity in each topological dimension 6910 6911 Notes: If per is PETSC_TRUE and maxCell is not provided, coordinates need to be already localized, or must be localized by hand by the user. 6912 6913 Level: developer 6914 6915 .seealso: DMGetPeriodicity() 6916 @*/ 6917 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6918 { 6919 PetscInt dim, d; 6920 PetscErrorCode ierr; 6921 6922 PetscFunctionBegin; 6923 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6924 PetscValidLogicalCollectiveBool(dm,per,2); 6925 if (maxCell) {PetscValidRealPointer(maxCell,3);} 6926 if (L) {PetscValidRealPointer(L,4);} 6927 if (bd) {PetscValidPointer(bd,5);} 6928 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6929 if (maxCell) { 6930 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);} 6931 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 6932 } else { /* remove maxCell information to disable automatic computation of localized vertices */ 6933 ierr = PetscFree(dm->maxCell);CHKERRQ(ierr); 6934 } 6935 6936 if (L) { 6937 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);} 6938 for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 6939 } 6940 if (bd) { 6941 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);} 6942 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d]; 6943 } 6944 dm->periodic = per; 6945 PetscFunctionReturn(0); 6946 } 6947 6948 /*@ 6949 DMLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension. 6950 6951 Input Parameters: 6952 + dm - The DM 6953 . in - The input coordinate point (dim numbers) 6954 - endpoint - Include the endpoint L_i 6955 6956 Output Parameter: 6957 . out - The localized coordinate point 6958 6959 Level: developer 6960 6961 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6962 @*/ 6963 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 6964 { 6965 PetscInt dim, d; 6966 PetscErrorCode ierr; 6967 6968 PetscFunctionBegin; 6969 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 6970 if (!dm->maxCell) { 6971 for (d = 0; d < dim; ++d) out[d] = in[d]; 6972 } else { 6973 if (endpoint) { 6974 for (d = 0; d < dim; ++d) { 6975 if ((PetscAbsReal(PetscRealPart(in[d])/dm->L[d] - PetscFloorReal(PetscRealPart(in[d])/dm->L[d])) < PETSC_SMALL) && (PetscRealPart(in[d])/dm->L[d] > PETSC_SMALL)) { 6976 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 6977 } else { 6978 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6979 } 6980 } 6981 } else { 6982 for (d = 0; d < dim; ++d) { 6983 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6984 } 6985 } 6986 } 6987 PetscFunctionReturn(0); 6988 } 6989 6990 /* 6991 DMLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 6992 6993 Input Parameters: 6994 + dm - The DM 6995 . dim - The spatial dimension 6996 . anchor - The anchor point, the input point can be no more than maxCell away from it 6997 - in - The input coordinate point (dim numbers) 6998 6999 Output Parameter: 7000 . out - The localized coordinate point 7001 7002 Level: developer 7003 7004 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 7005 7006 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 7007 */ 7008 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 7009 { 7010 PetscInt d; 7011 7012 PetscFunctionBegin; 7013 if (!dm->maxCell) { 7014 for (d = 0; d < dim; ++d) out[d] = in[d]; 7015 } else { 7016 for (d = 0; d < dim; ++d) { 7017 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 7018 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 7019 } else { 7020 out[d] = in[d]; 7021 } 7022 } 7023 } 7024 PetscFunctionReturn(0); 7025 } 7026 7027 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 7028 { 7029 PetscInt d; 7030 7031 PetscFunctionBegin; 7032 if (!dm->maxCell) { 7033 for (d = 0; d < dim; ++d) out[d] = in[d]; 7034 } else { 7035 for (d = 0; d < dim; ++d) { 7036 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 7037 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 7038 } else { 7039 out[d] = in[d]; 7040 } 7041 } 7042 } 7043 PetscFunctionReturn(0); 7044 } 7045 7046 /* 7047 DMLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 7048 7049 Input Parameters: 7050 + dm - The DM 7051 . dim - The spatial dimension 7052 . anchor - The anchor point, the input point can be no more than maxCell away from it 7053 . in - The input coordinate delta (dim numbers) 7054 - out - The input coordinate point (dim numbers) 7055 7056 Output Parameter: 7057 . out - The localized coordinate in + out 7058 7059 Level: developer 7060 7061 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 7062 7063 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 7064 */ 7065 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 7066 { 7067 PetscInt d; 7068 7069 PetscFunctionBegin; 7070 if (!dm->maxCell) { 7071 for (d = 0; d < dim; ++d) out[d] += in[d]; 7072 } else { 7073 for (d = 0; d < dim; ++d) { 7074 const PetscReal maxC = dm->maxCell[d]; 7075 7076 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 7077 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 7078 7079 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 7080 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "%D-Coordinate %g more than %g away from anchor %g", d, (double) PetscRealPart(in[d]), (double) maxC, (double) PetscRealPart(anchor[d])); 7081 out[d] += newCoord; 7082 } else { 7083 out[d] += in[d]; 7084 } 7085 } 7086 } 7087 PetscFunctionReturn(0); 7088 } 7089 7090 /*@ 7091 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 7092 7093 Not collective 7094 7095 Input Parameter: 7096 . dm - The DM 7097 7098 Output Parameter: 7099 areLocalized - True if localized 7100 7101 Level: developer 7102 7103 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 7104 @*/ 7105 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 7106 { 7107 DM cdm; 7108 PetscSection coordSection; 7109 PetscInt depth, cStart, cEnd, sStart, sEnd, c, dof; 7110 PetscBool isPlex, alreadyLocalized; 7111 PetscErrorCode ierr; 7112 7113 PetscFunctionBegin; 7114 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7115 PetscValidBoolPointer(areLocalized, 2); 7116 *areLocalized = PETSC_FALSE; 7117 7118 /* We need some generic way of refering to cells/vertices */ 7119 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7120 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 7121 if (!isPlex) PetscFunctionReturn(0); 7122 ierr = DMPlexGetDepth(cdm, &depth);CHKERRQ(ierr); 7123 if (!depth) PetscFunctionReturn(0); 7124 7125 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7126 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7127 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 7128 alreadyLocalized = PETSC_FALSE; 7129 for (c = cStart; c < cEnd; ++c) { 7130 if (c < sStart || c >= sEnd) continue; 7131 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 7132 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 7133 } 7134 *areLocalized = alreadyLocalized; 7135 PetscFunctionReturn(0); 7136 } 7137 7138 /*@ 7139 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 7140 7141 Collective on dm 7142 7143 Input Parameter: 7144 . dm - The DM 7145 7146 Output Parameter: 7147 areLocalized - True if localized 7148 7149 Level: developer 7150 7151 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 7152 @*/ 7153 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 7154 { 7155 PetscBool localized; 7156 PetscErrorCode ierr; 7157 7158 PetscFunctionBegin; 7159 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7160 PetscValidBoolPointer(areLocalized, 2); 7161 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 7162 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 7163 PetscFunctionReturn(0); 7164 } 7165 7166 /*@ 7167 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 7168 7169 Collective on dm 7170 7171 Input Parameter: 7172 . dm - The DM 7173 7174 Level: developer 7175 7176 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 7177 @*/ 7178 PetscErrorCode DMLocalizeCoordinates(DM dm) 7179 { 7180 DM cdm; 7181 PetscSection coordSection, cSection; 7182 Vec coordinates, cVec; 7183 PetscScalar *coords, *coords2, *anchor, *localized; 7184 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 7185 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 7186 PetscInt maxHeight = 0, h; 7187 PetscInt *pStart = NULL, *pEnd = NULL; 7188 PetscErrorCode ierr; 7189 7190 PetscFunctionBegin; 7191 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7192 if (!dm->periodic) PetscFunctionReturn(0); 7193 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 7194 if (alreadyLocalized) PetscFunctionReturn(0); 7195 7196 /* We need some generic way of refering to cells/vertices */ 7197 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7198 { 7199 PetscBool isplex; 7200 7201 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 7202 if (isplex) { 7203 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7204 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 7205 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7206 pEnd = &pStart[maxHeight + 1]; 7207 newStart = vStart; 7208 newEnd = vEnd; 7209 for (h = 0; h <= maxHeight; h++) { 7210 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 7211 newStart = PetscMin(newStart,pStart[h]); 7212 newEnd = PetscMax(newEnd,pEnd[h]); 7213 } 7214 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 7215 } 7216 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 7217 PetscCheckFalse(!coordinates,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 7218 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7219 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 7220 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 7221 7222 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 7223 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 7224 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 7225 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 7226 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 7227 7228 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7229 localized = &anchor[bs]; 7230 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 7231 for (h = 0; h <= maxHeight; h++) { 7232 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 7233 7234 for (c = cStart; c < cEnd; ++c) { 7235 PetscScalar *cellCoords = NULL; 7236 PetscInt b; 7237 7238 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 7239 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7240 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7241 for (d = 0; d < dof/bs; ++d) { 7242 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 7243 for (b = 0; b < bs; b++) { 7244 if (cellCoords[d*bs + b] != localized[b]) break; 7245 } 7246 if (b < bs) break; 7247 } 7248 if (d < dof/bs) { 7249 if (c >= sStart && c < sEnd) { 7250 PetscInt cdof; 7251 7252 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 7253 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 7254 } 7255 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 7256 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 7257 } 7258 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7259 } 7260 } 7261 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 7262 if (alreadyLocalizedGlobal) { 7263 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7264 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7265 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7266 PetscFunctionReturn(0); 7267 } 7268 for (v = vStart; v < vEnd; ++v) { 7269 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7270 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 7271 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 7272 } 7273 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 7274 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 7275 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 7276 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 7277 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 7278 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 7279 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 7280 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7281 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 7282 for (v = vStart; v < vEnd; ++v) { 7283 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7284 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 7285 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 7286 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 7287 } 7288 for (h = 0; h <= maxHeight; h++) { 7289 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 7290 7291 for (c = cStart; c < cEnd; ++c) { 7292 PetscScalar *cellCoords = NULL; 7293 PetscInt b, cdof; 7294 7295 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 7296 if (!cdof) continue; 7297 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7298 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 7299 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7300 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 7301 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7302 } 7303 } 7304 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7305 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7306 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7307 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 7308 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 7309 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 7310 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 7311 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7312 PetscFunctionReturn(0); 7313 } 7314 7315 /*@ 7316 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 7317 7318 Collective on v (see explanation below) 7319 7320 Input Parameters: 7321 + dm - The DM 7322 - ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 7323 7324 Input/Output Parameters: 7325 + v - The Vec of points, on output contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 7326 - cellSF - Points to either NULL, or a PetscSF with guesses for which cells contain each point; 7327 on output, the PetscSF containing the ranks and local indices of the containing points 7328 7329 Level: developer 7330 7331 Notes: 7332 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 7333 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 7334 7335 If *cellSF is NULL on input, a PetscSF will be created. 7336 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 7337 7338 An array that maps each point to its containing cell can be obtained with 7339 7340 $ const PetscSFNode *cells; 7341 $ PetscInt nFound; 7342 $ const PetscInt *found; 7343 $ 7344 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 7345 7346 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 7347 the index of the cell in its rank's local numbering. 7348 7349 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 7350 @*/ 7351 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 7352 { 7353 PetscErrorCode ierr; 7354 7355 PetscFunctionBegin; 7356 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7357 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 7358 PetscValidPointer(cellSF,4); 7359 if (*cellSF) { 7360 PetscMPIInt result; 7361 7362 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 7363 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRMPI(ierr); 7364 PetscCheckFalse(result != MPI_IDENT && result != MPI_CONGRUENT,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 7365 } else { 7366 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 7367 } 7368 PetscCheckFalse(!dm->ops->locatepoints,PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 7369 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7370 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 7371 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7372 PetscFunctionReturn(0); 7373 } 7374 7375 /*@ 7376 DMGetOutputDM - Retrieve the DM associated with the layout for output 7377 7378 Collective on dm 7379 7380 Input Parameter: 7381 . dm - The original DM 7382 7383 Output Parameter: 7384 . odm - The DM which provides the layout for output 7385 7386 Level: intermediate 7387 7388 .seealso: VecView(), DMGetGlobalSection() 7389 @*/ 7390 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 7391 { 7392 PetscSection section; 7393 PetscBool hasConstraints, ghasConstraints; 7394 PetscErrorCode ierr; 7395 7396 PetscFunctionBegin; 7397 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7398 PetscValidPointer(odm,2); 7399 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 7400 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 7401 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 7402 if (!ghasConstraints) { 7403 *odm = dm; 7404 PetscFunctionReturn(0); 7405 } 7406 if (!dm->dmBC) { 7407 PetscSection newSection, gsection; 7408 PetscSF sf; 7409 7410 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 7411 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 7412 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 7413 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 7414 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 7415 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 7416 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 7417 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 7418 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 7419 } 7420 *odm = dm->dmBC; 7421 PetscFunctionReturn(0); 7422 } 7423 7424 /*@ 7425 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 7426 7427 Input Parameter: 7428 . dm - The original DM 7429 7430 Output Parameters: 7431 + num - The output sequence number 7432 - val - The output sequence value 7433 7434 Level: intermediate 7435 7436 Note: This is intended for output that should appear in sequence, for instance 7437 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7438 7439 .seealso: VecView() 7440 @*/ 7441 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 7442 { 7443 PetscFunctionBegin; 7444 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7445 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 7446 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 7447 PetscFunctionReturn(0); 7448 } 7449 7450 /*@ 7451 DMSetOutputSequenceNumber - Set the sequence number/value for output 7452 7453 Input Parameters: 7454 + dm - The original DM 7455 . num - The output sequence number 7456 - val - The output sequence value 7457 7458 Level: intermediate 7459 7460 Note: This is intended for output that should appear in sequence, for instance 7461 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7462 7463 .seealso: VecView() 7464 @*/ 7465 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 7466 { 7467 PetscFunctionBegin; 7468 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7469 dm->outputSequenceNum = num; 7470 dm->outputSequenceVal = val; 7471 PetscFunctionReturn(0); 7472 } 7473 7474 /*@C 7475 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 7476 7477 Input Parameters: 7478 + dm - The original DM 7479 . name - The sequence name 7480 - num - The output sequence number 7481 7482 Output Parameter: 7483 . val - The output sequence value 7484 7485 Level: intermediate 7486 7487 Note: This is intended for output that should appear in sequence, for instance 7488 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7489 7490 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 7491 @*/ 7492 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 7493 { 7494 PetscBool ishdf5; 7495 PetscErrorCode ierr; 7496 7497 PetscFunctionBegin; 7498 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7499 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 7500 PetscValidRealPointer(val,5); 7501 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 7502 if (ishdf5) { 7503 #if defined(PETSC_HAVE_HDF5) 7504 PetscScalar value; 7505 7506 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 7507 *val = PetscRealPart(value); 7508 #endif 7509 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 7510 PetscFunctionReturn(0); 7511 } 7512 7513 /*@ 7514 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 7515 7516 Not collective 7517 7518 Input Parameter: 7519 . dm - The DM 7520 7521 Output Parameter: 7522 . useNatural - The flag to build the mapping to a natural order during distribution 7523 7524 Level: beginner 7525 7526 .seealso: DMSetUseNatural(), DMCreate() 7527 @*/ 7528 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 7529 { 7530 PetscFunctionBegin; 7531 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7532 PetscValidBoolPointer(useNatural, 2); 7533 *useNatural = dm->useNatural; 7534 PetscFunctionReturn(0); 7535 } 7536 7537 /*@ 7538 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 7539 7540 Collective on dm 7541 7542 Input Parameters: 7543 + dm - The DM 7544 - useNatural - The flag to build the mapping to a natural order during distribution 7545 7546 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 7547 7548 Level: beginner 7549 7550 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 7551 @*/ 7552 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 7553 { 7554 PetscFunctionBegin; 7555 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7556 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 7557 dm->useNatural = useNatural; 7558 PetscFunctionReturn(0); 7559 } 7560 7561 /*@C 7562 DMCreateLabel - Create a label of the given name if it does not already exist 7563 7564 Not Collective 7565 7566 Input Parameters: 7567 + dm - The DM object 7568 - name - The label name 7569 7570 Level: intermediate 7571 7572 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7573 @*/ 7574 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 7575 { 7576 PetscBool flg; 7577 DMLabel label; 7578 PetscErrorCode ierr; 7579 7580 PetscFunctionBegin; 7581 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7582 PetscValidCharPointer(name, 2); 7583 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7584 if (!flg) { 7585 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7586 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7587 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7588 } 7589 PetscFunctionReturn(0); 7590 } 7591 7592 /*@C 7593 DMCreateLabelAtIndex - Create a label of the given name at the iven index. If it already exists, move it to this index. 7594 7595 Not Collective 7596 7597 Input Parameters: 7598 + dm - The DM object 7599 . l - The index for the label 7600 - name - The label name 7601 7602 Level: intermediate 7603 7604 .seealso: DMCreateLabel(), DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7605 @*/ 7606 PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[]) 7607 { 7608 DMLabelLink orig, prev = NULL; 7609 DMLabel label; 7610 PetscInt Nl, m; 7611 PetscBool flg, match; 7612 const char *lname; 7613 PetscErrorCode ierr; 7614 7615 PetscFunctionBegin; 7616 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7617 PetscValidCharPointer(name, 3); 7618 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7619 if (!flg) { 7620 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7621 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7622 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7623 } 7624 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 7625 PetscCheckFalse(l >= Nl,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %D must be in [0, %D)", l, Nl); 7626 for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) { 7627 ierr = PetscObjectGetName((PetscObject) orig->label, &lname);CHKERRQ(ierr); 7628 ierr = PetscStrcmp(name, lname, &match);CHKERRQ(ierr); 7629 if (match) break; 7630 } 7631 if (m == l) PetscFunctionReturn(0); 7632 if (!m) dm->labels = orig->next; 7633 else prev->next = orig->next; 7634 if (!l) { 7635 orig->next = dm->labels; 7636 dm->labels = orig; 7637 } else { 7638 for (m = 0, prev = dm->labels; m < l-1; ++m, prev = prev->next); 7639 orig->next = prev->next; 7640 prev->next = orig; 7641 } 7642 PetscFunctionReturn(0); 7643 } 7644 7645 /*@C 7646 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 7647 7648 Not Collective 7649 7650 Input Parameters: 7651 + dm - The DM object 7652 . name - The label name 7653 - point - The mesh point 7654 7655 Output Parameter: 7656 . value - The label value for this point, or -1 if the point is not in the label 7657 7658 Level: beginner 7659 7660 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 7661 @*/ 7662 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 7663 { 7664 DMLabel label; 7665 PetscErrorCode ierr; 7666 7667 PetscFunctionBegin; 7668 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7669 PetscValidCharPointer(name, 2); 7670 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7671 PetscCheckFalse(!label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 7672 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 7673 PetscFunctionReturn(0); 7674 } 7675 7676 /*@C 7677 DMSetLabelValue - Add a point to a Sieve Label with given value 7678 7679 Not Collective 7680 7681 Input Parameters: 7682 + dm - The DM object 7683 . name - The label name 7684 . point - The mesh point 7685 - value - The label value for this point 7686 7687 Output Parameter: 7688 7689 Level: beginner 7690 7691 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 7692 @*/ 7693 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7694 { 7695 DMLabel label; 7696 PetscErrorCode ierr; 7697 7698 PetscFunctionBegin; 7699 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7700 PetscValidCharPointer(name, 2); 7701 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7702 if (!label) { 7703 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 7704 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7705 } 7706 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 7707 PetscFunctionReturn(0); 7708 } 7709 7710 /*@C 7711 DMClearLabelValue - Remove a point from a Sieve Label with given value 7712 7713 Not Collective 7714 7715 Input Parameters: 7716 + dm - The DM object 7717 . name - The label name 7718 . point - The mesh point 7719 - value - The label value for this point 7720 7721 Output Parameter: 7722 7723 Level: beginner 7724 7725 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 7726 @*/ 7727 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7728 { 7729 DMLabel label; 7730 PetscErrorCode ierr; 7731 7732 PetscFunctionBegin; 7733 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7734 PetscValidCharPointer(name, 2); 7735 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7736 if (!label) PetscFunctionReturn(0); 7737 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 7738 PetscFunctionReturn(0); 7739 } 7740 7741 /*@C 7742 DMGetLabelSize - Get the number of different integer ids in a Label 7743 7744 Not Collective 7745 7746 Input Parameters: 7747 + dm - The DM object 7748 - name - The label name 7749 7750 Output Parameter: 7751 . size - The number of different integer ids, or 0 if the label does not exist 7752 7753 Level: beginner 7754 7755 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 7756 @*/ 7757 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 7758 { 7759 DMLabel label; 7760 PetscErrorCode ierr; 7761 7762 PetscFunctionBegin; 7763 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7764 PetscValidCharPointer(name, 2); 7765 PetscValidIntPointer(size, 3); 7766 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7767 *size = 0; 7768 if (!label) PetscFunctionReturn(0); 7769 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 7770 PetscFunctionReturn(0); 7771 } 7772 7773 /*@C 7774 DMGetLabelIdIS - Get the integer ids in a label 7775 7776 Not Collective 7777 7778 Input Parameters: 7779 + mesh - The DM object 7780 - name - The label name 7781 7782 Output Parameter: 7783 . ids - The integer ids, or NULL if the label does not exist 7784 7785 Level: beginner 7786 7787 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 7788 @*/ 7789 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 7790 { 7791 DMLabel label; 7792 PetscErrorCode ierr; 7793 7794 PetscFunctionBegin; 7795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7796 PetscValidCharPointer(name, 2); 7797 PetscValidPointer(ids, 3); 7798 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7799 *ids = NULL; 7800 if (label) { 7801 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 7802 } else { 7803 /* returning an empty IS */ 7804 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 7805 } 7806 PetscFunctionReturn(0); 7807 } 7808 7809 /*@C 7810 DMGetStratumSize - Get the number of points in a label stratum 7811 7812 Not Collective 7813 7814 Input Parameters: 7815 + dm - The DM object 7816 . name - The label name 7817 - value - The stratum value 7818 7819 Output Parameter: 7820 . size - The stratum size 7821 7822 Level: beginner 7823 7824 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 7825 @*/ 7826 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 7827 { 7828 DMLabel label; 7829 PetscErrorCode ierr; 7830 7831 PetscFunctionBegin; 7832 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7833 PetscValidCharPointer(name, 2); 7834 PetscValidIntPointer(size, 4); 7835 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7836 *size = 0; 7837 if (!label) PetscFunctionReturn(0); 7838 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 7839 PetscFunctionReturn(0); 7840 } 7841 7842 /*@C 7843 DMGetStratumIS - Get the points in a label stratum 7844 7845 Not Collective 7846 7847 Input Parameters: 7848 + dm - The DM object 7849 . name - The label name 7850 - value - The stratum value 7851 7852 Output Parameter: 7853 . points - The stratum points, or NULL if the label does not exist or does not have that value 7854 7855 Level: beginner 7856 7857 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 7858 @*/ 7859 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 7860 { 7861 DMLabel label; 7862 PetscErrorCode ierr; 7863 7864 PetscFunctionBegin; 7865 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7866 PetscValidCharPointer(name, 2); 7867 PetscValidPointer(points, 4); 7868 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7869 *points = NULL; 7870 if (!label) PetscFunctionReturn(0); 7871 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 7872 PetscFunctionReturn(0); 7873 } 7874 7875 /*@C 7876 DMSetStratumIS - Set the points in a label stratum 7877 7878 Not Collective 7879 7880 Input Parameters: 7881 + dm - The DM object 7882 . name - The label name 7883 . value - The stratum value 7884 - points - The stratum points 7885 7886 Level: beginner 7887 7888 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 7889 @*/ 7890 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 7891 { 7892 DMLabel label; 7893 PetscErrorCode ierr; 7894 7895 PetscFunctionBegin; 7896 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7897 PetscValidCharPointer(name, 2); 7898 PetscValidPointer(points, 4); 7899 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7900 if (!label) PetscFunctionReturn(0); 7901 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 7902 PetscFunctionReturn(0); 7903 } 7904 7905 /*@C 7906 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 7907 7908 Not Collective 7909 7910 Input Parameters: 7911 + dm - The DM object 7912 . name - The label name 7913 - value - The label value for this point 7914 7915 Output Parameter: 7916 7917 Level: beginner 7918 7919 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7920 @*/ 7921 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7922 { 7923 DMLabel label; 7924 PetscErrorCode ierr; 7925 7926 PetscFunctionBegin; 7927 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7928 PetscValidCharPointer(name, 2); 7929 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7930 if (!label) PetscFunctionReturn(0); 7931 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7932 PetscFunctionReturn(0); 7933 } 7934 7935 /*@ 7936 DMGetNumLabels - Return the number of labels defined by the mesh 7937 7938 Not Collective 7939 7940 Input Parameter: 7941 . dm - The DM object 7942 7943 Output Parameter: 7944 . numLabels - the number of Labels 7945 7946 Level: intermediate 7947 7948 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7949 @*/ 7950 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7951 { 7952 DMLabelLink next = dm->labels; 7953 PetscInt n = 0; 7954 7955 PetscFunctionBegin; 7956 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7957 PetscValidIntPointer(numLabels, 2); 7958 while (next) {++n; next = next->next;} 7959 *numLabels = n; 7960 PetscFunctionReturn(0); 7961 } 7962 7963 /*@C 7964 DMGetLabelName - Return the name of nth label 7965 7966 Not Collective 7967 7968 Input Parameters: 7969 + dm - The DM object 7970 - n - the label number 7971 7972 Output Parameter: 7973 . name - the label name 7974 7975 Level: intermediate 7976 7977 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7978 @*/ 7979 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7980 { 7981 DMLabelLink next = dm->labels; 7982 PetscInt l = 0; 7983 PetscErrorCode ierr; 7984 7985 PetscFunctionBegin; 7986 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7987 PetscValidPointer(name, 3); 7988 while (next) { 7989 if (l == n) { 7990 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7991 PetscFunctionReturn(0); 7992 } 7993 ++l; 7994 next = next->next; 7995 } 7996 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7997 } 7998 7999 /*@C 8000 DMHasLabel - Determine whether the mesh has a label of a given name 8001 8002 Not Collective 8003 8004 Input Parameters: 8005 + dm - The DM object 8006 - name - The label name 8007 8008 Output Parameter: 8009 . hasLabel - PETSC_TRUE if the label is present 8010 8011 Level: intermediate 8012 8013 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8014 @*/ 8015 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 8016 { 8017 DMLabelLink next = dm->labels; 8018 const char *lname; 8019 PetscErrorCode ierr; 8020 8021 PetscFunctionBegin; 8022 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8023 PetscValidCharPointer(name, 2); 8024 PetscValidBoolPointer(hasLabel, 3); 8025 *hasLabel = PETSC_FALSE; 8026 while (next) { 8027 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8028 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 8029 if (*hasLabel) break; 8030 next = next->next; 8031 } 8032 PetscFunctionReturn(0); 8033 } 8034 8035 /*@C 8036 DMGetLabel - Return the label of a given name, or NULL 8037 8038 Not Collective 8039 8040 Input Parameters: 8041 + dm - The DM object 8042 - name - The label name 8043 8044 Output Parameter: 8045 . label - The DMLabel, or NULL if the label is absent 8046 8047 Note: Some of the default labels in a DMPlex will be 8048 $ "depth" - Holds the depth (co-dimension) of each mesh point 8049 $ "celltype" - Holds the topological type of each cell 8050 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 8051 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 8052 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 8053 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 8054 8055 Level: intermediate 8056 8057 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 8058 @*/ 8059 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 8060 { 8061 DMLabelLink next = dm->labels; 8062 PetscBool hasLabel; 8063 const char *lname; 8064 PetscErrorCode ierr; 8065 8066 PetscFunctionBegin; 8067 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8068 PetscValidCharPointer(name, 2); 8069 PetscValidPointer(label, 3); 8070 *label = NULL; 8071 while (next) { 8072 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8073 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8074 if (hasLabel) { 8075 *label = next->label; 8076 break; 8077 } 8078 next = next->next; 8079 } 8080 PetscFunctionReturn(0); 8081 } 8082 8083 /*@C 8084 DMGetLabelByNum - Return the nth label 8085 8086 Not Collective 8087 8088 Input Parameters: 8089 + dm - The DM object 8090 - n - the label number 8091 8092 Output Parameter: 8093 . label - the label 8094 8095 Level: intermediate 8096 8097 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8098 @*/ 8099 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 8100 { 8101 DMLabelLink next = dm->labels; 8102 PetscInt l = 0; 8103 8104 PetscFunctionBegin; 8105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8106 PetscValidPointer(label, 3); 8107 while (next) { 8108 if (l == n) { 8109 *label = next->label; 8110 PetscFunctionReturn(0); 8111 } 8112 ++l; 8113 next = next->next; 8114 } 8115 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 8116 } 8117 8118 /*@C 8119 DMAddLabel - Add the label to this mesh 8120 8121 Not Collective 8122 8123 Input Parameters: 8124 + dm - The DM object 8125 - label - The DMLabel 8126 8127 Level: developer 8128 8129 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8130 @*/ 8131 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 8132 { 8133 DMLabelLink l, *p, tmpLabel; 8134 PetscBool hasLabel; 8135 const char *lname; 8136 PetscBool flg; 8137 PetscErrorCode ierr; 8138 8139 PetscFunctionBegin; 8140 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8141 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 8142 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 8143 PetscCheckFalse(hasLabel,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 8144 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 8145 tmpLabel->label = label; 8146 tmpLabel->output = PETSC_TRUE; 8147 for (p=&dm->labels; (l=*p); p=&l->next) {} 8148 *p = tmpLabel; 8149 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 8150 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 8151 if (flg) dm->depthLabel = label; 8152 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 8153 if (flg) dm->celltypeLabel = label; 8154 PetscFunctionReturn(0); 8155 } 8156 8157 /*@C 8158 DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present 8159 8160 Not Collective 8161 8162 Input Parameters: 8163 + dm - The DM object 8164 - label - The DMLabel, having the same name, to substitute 8165 8166 Note: Some of the default labels in a DMPlex will be 8167 $ "depth" - Holds the depth (co-dimension) of each mesh point 8168 $ "celltype" - Holds the topological type of each cell 8169 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 8170 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 8171 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 8172 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 8173 8174 Level: intermediate 8175 8176 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 8177 @*/ 8178 PetscErrorCode DMSetLabel(DM dm, DMLabel label) 8179 { 8180 DMLabelLink next = dm->labels; 8181 PetscBool hasLabel, flg; 8182 const char *name, *lname; 8183 PetscErrorCode ierr; 8184 8185 PetscFunctionBegin; 8186 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8187 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 8188 ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr); 8189 while (next) { 8190 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8191 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8192 if (hasLabel) { 8193 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 8194 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 8195 if (flg) dm->depthLabel = label; 8196 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 8197 if (flg) dm->celltypeLabel = label; 8198 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 8199 next->label = label; 8200 break; 8201 } 8202 next = next->next; 8203 } 8204 PetscFunctionReturn(0); 8205 } 8206 8207 /*@C 8208 DMRemoveLabel - Remove the label given by name from this mesh 8209 8210 Not Collective 8211 8212 Input Parameters: 8213 + dm - The DM object 8214 - name - The label name 8215 8216 Output Parameter: 8217 . label - The DMLabel, or NULL if the label is absent 8218 8219 Level: developer 8220 8221 Notes: 8222 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 8223 DMLabelDestroy() on the label. 8224 8225 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 8226 call DMLabelDestroy(). Instead, the label is returned and the user is 8227 responsible of calling DMLabelDestroy() at some point. 8228 8229 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 8230 @*/ 8231 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 8232 { 8233 DMLabelLink link, *pnext; 8234 PetscBool hasLabel; 8235 const char *lname; 8236 PetscErrorCode ierr; 8237 8238 PetscFunctionBegin; 8239 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8240 PetscValidCharPointer(name, 2); 8241 if (label) { 8242 PetscValidPointer(label, 3); 8243 *label = NULL; 8244 } 8245 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 8246 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 8247 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8248 if (hasLabel) { 8249 *pnext = link->next; /* Remove from list */ 8250 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 8251 if (hasLabel) dm->depthLabel = NULL; 8252 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 8253 if (hasLabel) dm->celltypeLabel = NULL; 8254 if (label) *label = link->label; 8255 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 8256 ierr = PetscFree(link);CHKERRQ(ierr); 8257 break; 8258 } 8259 } 8260 PetscFunctionReturn(0); 8261 } 8262 8263 /*@ 8264 DMRemoveLabelBySelf - Remove the label from this mesh 8265 8266 Not Collective 8267 8268 Input Parameters: 8269 + dm - The DM object 8270 . label - The DMLabel to be removed from the DM 8271 - failNotFound - Should it fail if the label is not found in the DM? 8272 8273 Level: developer 8274 8275 Notes: 8276 Only exactly the same instance is removed if found, name match is ignored. 8277 If the DM has an exclusive reference to the label, it gets destroyed and 8278 *label nullified. 8279 8280 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 8281 @*/ 8282 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 8283 { 8284 DMLabelLink link, *pnext; 8285 PetscBool hasLabel = PETSC_FALSE; 8286 PetscErrorCode ierr; 8287 8288 PetscFunctionBegin; 8289 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8290 PetscValidPointer(label, 2); 8291 if (!*label && !failNotFound) PetscFunctionReturn(0); 8292 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 8293 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 8294 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 8295 if (*label == link->label) { 8296 hasLabel = PETSC_TRUE; 8297 *pnext = link->next; /* Remove from list */ 8298 if (*label == dm->depthLabel) dm->depthLabel = NULL; 8299 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 8300 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 8301 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 8302 ierr = PetscFree(link);CHKERRQ(ierr); 8303 break; 8304 } 8305 } 8306 PetscCheckFalse(!hasLabel && failNotFound,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 8307 PetscFunctionReturn(0); 8308 } 8309 8310 /*@C 8311 DMGetLabelOutput - Get the output flag for a given label 8312 8313 Not Collective 8314 8315 Input Parameters: 8316 + dm - The DM object 8317 - name - The label name 8318 8319 Output Parameter: 8320 . output - The flag for output 8321 8322 Level: developer 8323 8324 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8325 @*/ 8326 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 8327 { 8328 DMLabelLink next = dm->labels; 8329 const char *lname; 8330 PetscErrorCode ierr; 8331 8332 PetscFunctionBegin; 8333 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8334 PetscValidPointer(name, 2); 8335 PetscValidPointer(output, 3); 8336 while (next) { 8337 PetscBool flg; 8338 8339 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8340 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8341 if (flg) {*output = next->output; PetscFunctionReturn(0);} 8342 next = next->next; 8343 } 8344 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8345 } 8346 8347 /*@C 8348 DMSetLabelOutput - Set the output flag for a given label 8349 8350 Not Collective 8351 8352 Input Parameters: 8353 + dm - The DM object 8354 . name - The label name 8355 - output - The flag for output 8356 8357 Level: developer 8358 8359 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8360 @*/ 8361 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 8362 { 8363 DMLabelLink next = dm->labels; 8364 const char *lname; 8365 PetscErrorCode ierr; 8366 8367 PetscFunctionBegin; 8368 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8369 PetscValidCharPointer(name, 2); 8370 while (next) { 8371 PetscBool flg; 8372 8373 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8374 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8375 if (flg) {next->output = output; PetscFunctionReturn(0);} 8376 next = next->next; 8377 } 8378 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8379 } 8380 8381 /*@ 8382 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 8383 8384 Collective on dmA 8385 8386 Input Parameters: 8387 + dmA - The DM object with initial labels 8388 . dmB - The DM object to which labels are copied 8389 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 8390 . all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 8391 - emode - How to behave when a DMLabel in the source and destination DMs with the same name is encountered (see DMCopyLabelsMode) 8392 8393 Level: intermediate 8394 8395 Notes: 8396 This is typically used when interpolating or otherwise adding to a mesh, or testing. 8397 8398 .seealso: DMAddLabel(), DMCopyLabelsMode 8399 @*/ 8400 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode) 8401 { 8402 DMLabel label, labelNew, labelOld; 8403 const char *name; 8404 PetscBool flg; 8405 DMLabelLink link; 8406 PetscErrorCode ierr; 8407 8408 PetscFunctionBegin; 8409 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 8410 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 8411 PetscValidLogicalCollectiveEnum(dmA, mode,3); 8412 PetscValidLogicalCollectiveBool(dmA, all, 4); 8413 PetscCheckFalse(mode==PETSC_USE_POINTER,PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 8414 if (dmA == dmB) PetscFunctionReturn(0); 8415 for (link=dmA->labels; link; link=link->next) { 8416 label=link->label; 8417 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 8418 if (!all) { 8419 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 8420 if (flg) continue; 8421 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 8422 if (flg) continue; 8423 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 8424 if (flg) continue; 8425 } 8426 ierr = DMGetLabel(dmB, name, &labelOld);CHKERRQ(ierr); 8427 if (labelOld) { 8428 switch (emode) { 8429 case DM_COPY_LABELS_KEEP: 8430 continue; 8431 case DM_COPY_LABELS_REPLACE: 8432 ierr = DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE);CHKERRQ(ierr); 8433 break; 8434 case DM_COPY_LABELS_FAIL: 8435 SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name); 8436 default: 8437 SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", emode); 8438 } 8439 } 8440 if (mode==PETSC_COPY_VALUES) { 8441 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 8442 } else { 8443 labelNew = label; 8444 } 8445 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 8446 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 8447 } 8448 PetscFunctionReturn(0); 8449 } 8450 8451 /*@C 8452 DMCompareLabels - Compare labels of two DMPlex meshes 8453 8454 Collective 8455 8456 Input Parameters: 8457 + dm0 - First DM object 8458 - dm1 - Second DM object 8459 8460 Output Parameters 8461 + equal - (Optional) Flag whether labels of dm0 and dm1 are the same 8462 - message - (Optional) Message describing the difference, or NULL if there is no difference 8463 8464 Level: intermediate 8465 8466 Notes: 8467 The output flag equal is the same on all processes. 8468 If it is passed as NULL and difference is found, an error is thrown on all processes. 8469 Make sure to pass NULL on all processes. 8470 8471 The output message is set independently on each rank. 8472 It is set to NULL if no difference was found on the current rank. It must be freed by user. 8473 If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner. 8474 Make sure to pass NULL on all processes. 8475 8476 Labels are matched by name. If the number of labels and their names are equal, 8477 DMLabelCompare() is used to compare each pair of labels with the same name. 8478 8479 Fortran Notes: 8480 This function is currently not available from Fortran. 8481 8482 .seealso: DMAddLabel(), DMCopyLabelsMode, DMLabelCompare() 8483 @*/ 8484 PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message) 8485 { 8486 PetscInt n, i; 8487 char msg[PETSC_MAX_PATH_LEN] = ""; 8488 PetscBool eq; 8489 MPI_Comm comm; 8490 PetscMPIInt rank; 8491 PetscErrorCode ierr; 8492 8493 PetscFunctionBegin; 8494 PetscValidHeaderSpecific(dm0,DM_CLASSID,1); 8495 PetscValidHeaderSpecific(dm1,DM_CLASSID,2); 8496 PetscCheckSameComm(dm0,1,dm1,2); 8497 if (equal) PetscValidBoolPointer(equal,3); 8498 if (message) PetscValidPointer(message, 4); 8499 ierr = PetscObjectGetComm((PetscObject)dm0, &comm);CHKERRQ(ierr); 8500 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8501 { 8502 PetscInt n1; 8503 8504 ierr = DMGetNumLabels(dm0, &n);CHKERRQ(ierr); 8505 ierr = DMGetNumLabels(dm1, &n1);CHKERRQ(ierr); 8506 eq = (PetscBool) (n == n1); 8507 if (!eq) { 8508 ierr = PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %D != %D = Number of labels in dm1", n, n1);CHKERRQ(ierr); 8509 } 8510 ierr = MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRMPI(ierr); 8511 if (!eq) goto finish; 8512 } 8513 for (i=0; i<n; i++) { 8514 DMLabel l0, l1; 8515 const char *name; 8516 char *msgInner; 8517 8518 /* Ignore label order */ 8519 ierr = DMGetLabelByNum(dm0, i, &l0);CHKERRQ(ierr); 8520 ierr = PetscObjectGetName((PetscObject)l0, &name);CHKERRQ(ierr); 8521 ierr = DMGetLabel(dm1, name, &l1);CHKERRQ(ierr); 8522 if (!l1) { 8523 ierr = PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%D in dm0) not found in dm1", name, i);CHKERRQ(ierr); 8524 eq = PETSC_FALSE; 8525 break; 8526 } 8527 ierr = DMLabelCompare(comm, l0, l1, &eq, &msgInner);CHKERRQ(ierr); 8528 ierr = PetscStrncpy(msg, msgInner, sizeof(msg));CHKERRQ(ierr); 8529 ierr = PetscFree(msgInner);CHKERRQ(ierr); 8530 if (!eq) break; 8531 } 8532 ierr = MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRMPI(ierr); 8533 finish: 8534 /* If message output arg not set, print to stderr */ 8535 if (message) { 8536 *message = NULL; 8537 if (msg[0]) { 8538 ierr = PetscStrallocpy(msg, message);CHKERRQ(ierr); 8539 } 8540 } else { 8541 if (msg[0]) { 8542 ierr = PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg);CHKERRQ(ierr); 8543 } 8544 ierr = PetscSynchronizedFlush(comm, PETSC_STDERR);CHKERRQ(ierr); 8545 } 8546 /* If same output arg not ser and labels are not equal, throw error */ 8547 if (equal) *equal = eq; 8548 else PetscCheckFalse(!eq,comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1"); 8549 PetscFunctionReturn(0); 8550 } 8551 8552 PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value) 8553 { 8554 PetscErrorCode ierr; 8555 8556 PetscFunctionBegin; 8557 PetscValidPointer(label,2); 8558 if (!*label) { 8559 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 8560 ierr = DMGetLabel(dm, name, label);CHKERRQ(ierr); 8561 } 8562 ierr = DMLabelSetValue(*label, point, value);CHKERRQ(ierr); 8563 PetscFunctionReturn(0); 8564 } 8565 8566 /* 8567 Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would 8568 like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every 8569 (label, id) pair in the DM. 8570 8571 However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to 8572 each label. 8573 */ 8574 PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal) 8575 { 8576 DMUniversalLabel ul; 8577 PetscBool *active; 8578 PetscInt pStart, pEnd, p, Nl, l, m; 8579 PetscErrorCode ierr; 8580 8581 PetscFunctionBegin; 8582 ierr = PetscMalloc1(1, &ul);CHKERRQ(ierr); 8583 ierr = DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label);CHKERRQ(ierr); 8584 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 8585 ierr = PetscCalloc1(Nl, &active);CHKERRQ(ierr); 8586 ul->Nl = 0; 8587 for (l = 0; l < Nl; ++l) { 8588 PetscBool isdepth, iscelltype; 8589 const char *name; 8590 8591 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8592 ierr = PetscStrncmp(name, "depth", 6, &isdepth);CHKERRQ(ierr); 8593 ierr = PetscStrncmp(name, "celltype", 9, &iscelltype);CHKERRQ(ierr); 8594 active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE; 8595 if (active[l]) ++ul->Nl; 8596 } 8597 ierr = PetscCalloc5(ul->Nl, &ul->names, ul->Nl, &ul->indices, ul->Nl+1, &ul->offsets, ul->Nl+1, &ul->bits, ul->Nl, &ul->masks);CHKERRQ(ierr); 8598 ul->Nv = 0; 8599 for (l = 0, m = 0; l < Nl; ++l) { 8600 DMLabel label; 8601 PetscInt nv; 8602 const char *name; 8603 8604 if (!active[l]) continue; 8605 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8606 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8607 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8608 ierr = PetscStrallocpy(name, &ul->names[m]);CHKERRQ(ierr); 8609 ul->indices[m] = l; 8610 ul->Nv += nv; 8611 ul->offsets[m+1] = nv; 8612 ul->bits[m+1] = PetscCeilReal(PetscLog2Real(nv+1)); 8613 ++m; 8614 } 8615 for (l = 1; l <= ul->Nl; ++l) { 8616 ul->offsets[l] = ul->offsets[l-1] + ul->offsets[l]; 8617 ul->bits[l] = ul->bits[l-1] + ul->bits[l]; 8618 } 8619 for (l = 0; l < ul->Nl; ++l) { 8620 PetscInt b; 8621 8622 ul->masks[l] = 0; 8623 for (b = ul->bits[l]; b < ul->bits[l+1]; ++b) ul->masks[l] |= 1 << b; 8624 } 8625 ierr = PetscMalloc1(ul->Nv, &ul->values);CHKERRQ(ierr); 8626 for (l = 0, m = 0; l < Nl; ++l) { 8627 DMLabel label; 8628 IS valueIS; 8629 const PetscInt *varr; 8630 PetscInt nv, v; 8631 8632 if (!active[l]) continue; 8633 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8634 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8635 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 8636 ierr = ISGetIndices(valueIS, &varr);CHKERRQ(ierr); 8637 for (v = 0; v < nv; ++v) { 8638 ul->values[ul->offsets[m]+v] = varr[v]; 8639 } 8640 ierr = ISRestoreIndices(valueIS, &varr);CHKERRQ(ierr); 8641 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 8642 ierr = PetscSortInt(nv, &ul->values[ul->offsets[m]]);CHKERRQ(ierr); 8643 ++m; 8644 } 8645 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8646 for (p = pStart; p < pEnd; ++p) { 8647 PetscInt uval = 0; 8648 PetscBool marked = PETSC_FALSE; 8649 8650 for (l = 0, m = 0; l < Nl; ++l) { 8651 DMLabel label; 8652 PetscInt val, defval, loc, nv; 8653 8654 if (!active[l]) continue; 8655 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8656 ierr = DMLabelGetValue(label, p, &val);CHKERRQ(ierr); 8657 ierr = DMLabelGetDefaultValue(label, &defval);CHKERRQ(ierr); 8658 if (val == defval) {++m; continue;} 8659 nv = ul->offsets[m+1]-ul->offsets[m]; 8660 marked = PETSC_TRUE; 8661 ierr = PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc);CHKERRQ(ierr); 8662 PetscCheckFalse(loc < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %D not found in compression array", val); 8663 uval += (loc+1) << ul->bits[m]; 8664 ++m; 8665 } 8666 if (marked) {ierr = DMLabelSetValue(ul->label, p, uval);CHKERRQ(ierr);} 8667 } 8668 ierr = PetscFree(active);CHKERRQ(ierr); 8669 *universal = ul; 8670 PetscFunctionReturn(0); 8671 } 8672 8673 PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal) 8674 { 8675 PetscInt l; 8676 PetscErrorCode ierr; 8677 8678 PetscFunctionBegin; 8679 for (l = 0; l < (*universal)->Nl; ++l) {ierr = PetscFree((*universal)->names[l]);CHKERRQ(ierr);} 8680 ierr = DMLabelDestroy(&(*universal)->label);CHKERRQ(ierr); 8681 ierr = PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks);CHKERRQ(ierr); 8682 ierr = PetscFree((*universal)->values);CHKERRQ(ierr); 8683 ierr = PetscFree(*universal);CHKERRQ(ierr); 8684 *universal = NULL; 8685 PetscFunctionReturn(0); 8686 } 8687 8688 PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel) 8689 { 8690 PetscFunctionBegin; 8691 PetscValidPointer(ulabel, 2); 8692 *ulabel = ul->label; 8693 PetscFunctionReturn(0); 8694 } 8695 8696 PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm) 8697 { 8698 PetscInt Nl = ul->Nl, l; 8699 PetscErrorCode ierr; 8700 8701 PetscFunctionBegin; 8702 PetscValidHeaderSpecific(dm, DM_CLASSID, 3); 8703 for (l = 0; l < Nl; ++l) { 8704 if (preserveOrder) {ierr = DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]);CHKERRQ(ierr);} 8705 else {ierr = DMCreateLabel(dm, ul->names[l]);CHKERRQ(ierr);} 8706 } 8707 if (preserveOrder) { 8708 for (l = 0; l < ul->Nl; ++l) { 8709 const char *name; 8710 PetscBool match; 8711 8712 ierr = DMGetLabelName(dm, ul->indices[l], &name);CHKERRQ(ierr); 8713 ierr = PetscStrcmp(name, ul->names[l], &match);CHKERRQ(ierr); 8714 PetscCheckFalse(!match,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %D name %s does not match new name %s", l, name, ul->names[l]); 8715 } 8716 } 8717 PetscFunctionReturn(0); 8718 } 8719 8720 PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value) 8721 { 8722 PetscInt l; 8723 PetscErrorCode ierr; 8724 8725 PetscFunctionBegin; 8726 for (l = 0; l < ul->Nl; ++l) { 8727 DMLabel label; 8728 PetscInt lval = (value & ul->masks[l]) >> ul->bits[l]; 8729 8730 if (lval) { 8731 if (useIndex) {ierr = DMGetLabelByNum(dm, ul->indices[l], &label);CHKERRQ(ierr);} 8732 else {ierr = DMGetLabel(dm, ul->names[l], &label);CHKERRQ(ierr);} 8733 ierr = DMLabelSetValue(label, p, ul->values[ul->offsets[l]+lval-1]);CHKERRQ(ierr); 8734 } 8735 } 8736 PetscFunctionReturn(0); 8737 } 8738 8739 /*@ 8740 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 8741 8742 Input Parameter: 8743 . dm - The DM object 8744 8745 Output Parameter: 8746 . cdm - The coarse DM 8747 8748 Level: intermediate 8749 8750 .seealso: DMSetCoarseDM() 8751 @*/ 8752 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 8753 { 8754 PetscFunctionBegin; 8755 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8756 PetscValidPointer(cdm, 2); 8757 *cdm = dm->coarseMesh; 8758 PetscFunctionReturn(0); 8759 } 8760 8761 /*@ 8762 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 8763 8764 Input Parameters: 8765 + dm - The DM object 8766 - cdm - The coarse DM 8767 8768 Level: intermediate 8769 8770 .seealso: DMGetCoarseDM() 8771 @*/ 8772 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 8773 { 8774 PetscErrorCode ierr; 8775 8776 PetscFunctionBegin; 8777 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8778 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 8779 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 8780 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 8781 dm->coarseMesh = cdm; 8782 PetscFunctionReturn(0); 8783 } 8784 8785 /*@ 8786 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 8787 8788 Input Parameter: 8789 . dm - The DM object 8790 8791 Output Parameter: 8792 . fdm - The fine DM 8793 8794 Level: intermediate 8795 8796 .seealso: DMSetFineDM() 8797 @*/ 8798 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 8799 { 8800 PetscFunctionBegin; 8801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8802 PetscValidPointer(fdm, 2); 8803 *fdm = dm->fineMesh; 8804 PetscFunctionReturn(0); 8805 } 8806 8807 /*@ 8808 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 8809 8810 Input Parameters: 8811 + dm - The DM object 8812 - fdm - The fine DM 8813 8814 Level: intermediate 8815 8816 .seealso: DMGetFineDM() 8817 @*/ 8818 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 8819 { 8820 PetscErrorCode ierr; 8821 8822 PetscFunctionBegin; 8823 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8824 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 8825 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 8826 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 8827 dm->fineMesh = fdm; 8828 PetscFunctionReturn(0); 8829 } 8830 8831 /*=== DMBoundary code ===*/ 8832 8833 /*@C 8834 DMAddBoundary - Add a boundary condition to the model 8835 8836 Collective on dm 8837 8838 Input Parameters: 8839 + dm - The DM, with a PetscDS that matches the problem being constrained 8840 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 8841 . name - The BC name 8842 . label - The label defining constrained points 8843 . Nv - The number of DMLabel values for constrained points 8844 . values - An array of values for constrained points 8845 . field - The field to constrain 8846 . Nc - The number of constrained field components (0 will constrain all fields) 8847 . comps - An array of constrained component numbers 8848 . bcFunc - A pointwise function giving boundary values 8849 . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL 8850 - ctx - An optional user context for bcFunc 8851 8852 Output Parameter: 8853 . bd - (Optional) Boundary number 8854 8855 Options Database Keys: 8856 + -bc_<boundary name> <num> - Overrides the boundary ids 8857 - -bc_<boundary name>_comp <num> - Overrides the boundary components 8858 8859 Note: 8860 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is: 8861 8862 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 8863 8864 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is: 8865 8866 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8867 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8868 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8869 $ PetscReal time, const PetscReal x[], PetscScalar bcval[]) 8870 8871 + dim - the spatial dimension 8872 . Nf - the number of fields 8873 . uOff - the offset into u[] and u_t[] for each field 8874 . uOff_x - the offset into u_x[] for each field 8875 . u - each field evaluated at the current point 8876 . u_t - the time derivative of each field evaluated at the current point 8877 . u_x - the gradient of each field evaluated at the current point 8878 . aOff - the offset into a[] and a_t[] for each auxiliary field 8879 . aOff_x - the offset into a_x[] for each auxiliary field 8880 . a - each auxiliary field evaluated at the current point 8881 . a_t - the time derivative of each auxiliary field evaluated at the current point 8882 . a_x - the gradient of auxiliary each field evaluated at the current point 8883 . t - current time 8884 . x - coordinates of the current point 8885 . numConstants - number of constant parameters 8886 . constants - constant parameters 8887 - bcval - output values at the current point 8888 8889 Level: intermediate 8890 8891 .seealso: DSGetBoundary(), PetscDSAddBoundary() 8892 @*/ 8893 PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd) 8894 { 8895 PetscDS ds; 8896 PetscErrorCode ierr; 8897 8898 PetscFunctionBegin; 8899 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8900 PetscValidLogicalCollectiveEnum(dm, type, 2); 8901 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 8902 PetscValidLogicalCollectiveInt(dm, Nv, 5); 8903 PetscValidLogicalCollectiveInt(dm, field, 7); 8904 PetscValidLogicalCollectiveInt(dm, Nc, 8); 8905 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8906 ierr = DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, label);CHKERRQ(ierr); 8907 ierr = PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd);CHKERRQ(ierr); 8908 PetscFunctionReturn(0); 8909 } 8910 8911 /* TODO Remove this since now the structures are the same */ 8912 static PetscErrorCode DMPopulateBoundary(DM dm) 8913 { 8914 PetscDS ds; 8915 DMBoundary *lastnext; 8916 DSBoundary dsbound; 8917 PetscErrorCode ierr; 8918 8919 PetscFunctionBegin; 8920 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8921 dsbound = ds->boundary; 8922 if (dm->boundary) { 8923 DMBoundary next = dm->boundary; 8924 8925 /* quick check to see if the PetscDS has changed */ 8926 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 8927 /* the PetscDS has changed: tear down and rebuild */ 8928 while (next) { 8929 DMBoundary b = next; 8930 8931 next = b->next; 8932 ierr = PetscFree(b);CHKERRQ(ierr); 8933 } 8934 dm->boundary = NULL; 8935 } 8936 8937 lastnext = &(dm->boundary); 8938 while (dsbound) { 8939 DMBoundary dmbound; 8940 8941 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 8942 dmbound->dsboundary = dsbound; 8943 dmbound->label = dsbound->label; 8944 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 8945 *lastnext = dmbound; 8946 lastnext = &(dmbound->next); 8947 dsbound = dsbound->next; 8948 } 8949 PetscFunctionReturn(0); 8950 } 8951 8952 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 8953 { 8954 DMBoundary b; 8955 PetscErrorCode ierr; 8956 8957 PetscFunctionBegin; 8958 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8959 PetscValidBoolPointer(isBd, 3); 8960 *isBd = PETSC_FALSE; 8961 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 8962 b = dm->boundary; 8963 while (b && !(*isBd)) { 8964 DMLabel label = b->label; 8965 DSBoundary dsb = b->dsboundary; 8966 PetscInt i; 8967 8968 if (label) { 8969 for (i = 0; i < dsb->Nv && !(*isBd); ++i) {ierr = DMLabelStratumHasPoint(label, dsb->values[i], point, isBd);CHKERRQ(ierr);} 8970 } 8971 b = b->next; 8972 } 8973 PetscFunctionReturn(0); 8974 } 8975 8976 /*@C 8977 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 8978 8979 Collective on DM 8980 8981 Input Parameters: 8982 + dm - The DM 8983 . time - The time 8984 . funcs - The coordinate functions to evaluate, one per field 8985 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8986 - mode - The insertion mode for values 8987 8988 Output Parameter: 8989 . X - vector 8990 8991 Calling sequence of func: 8992 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 8993 8994 + dim - The spatial dimension 8995 . time - The time at which to sample 8996 . x - The coordinates 8997 . Nc - The number of components 8998 . u - The output field values 8999 - ctx - optional user-defined function context 9000 9001 Level: developer 9002 9003 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 9004 @*/ 9005 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 9006 { 9007 Vec localX; 9008 PetscErrorCode ierr; 9009 9010 PetscFunctionBegin; 9011 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9012 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9013 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 9014 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9015 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9016 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9017 PetscFunctionReturn(0); 9018 } 9019 9020 /*@C 9021 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 9022 9023 Not collective 9024 9025 Input Parameters: 9026 + dm - The DM 9027 . time - The time 9028 . funcs - The coordinate functions to evaluate, one per field 9029 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 9030 - mode - The insertion mode for values 9031 9032 Output Parameter: 9033 . localX - vector 9034 9035 Calling sequence of func: 9036 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 9037 9038 + dim - The spatial dimension 9039 . x - The coordinates 9040 . Nc - The number of components 9041 . u - The output field values 9042 - ctx - optional user-defined function context 9043 9044 Level: developer 9045 9046 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 9047 @*/ 9048 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 9049 { 9050 PetscErrorCode ierr; 9051 9052 PetscFunctionBegin; 9053 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9054 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 9055 PetscCheckFalse(!dm->ops->projectfunctionlocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 9056 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 9057 PetscFunctionReturn(0); 9058 } 9059 9060 /*@C 9061 DMProjectFunctionLabel - This projects the given function into the function space provided, putting the coefficients in a global vector, setting values only for points in the given label. 9062 9063 Collective on DM 9064 9065 Input Parameters: 9066 + dm - The DM 9067 . time - The time 9068 . label - The DMLabel selecting the portion of the mesh for projection 9069 . funcs - The coordinate functions to evaluate, one per field 9070 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 9071 - mode - The insertion mode for values 9072 9073 Output Parameter: 9074 . X - vector 9075 9076 Calling sequence of func: 9077 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 9078 9079 + dim - The spatial dimension 9080 . x - The coordinates 9081 . Nc - The number of components 9082 . u - The output field values 9083 - ctx - optional user-defined function context 9084 9085 Level: developer 9086 9087 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 9088 @*/ 9089 PetscErrorCode DMProjectFunctionLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 9090 { 9091 Vec localX; 9092 PetscErrorCode ierr; 9093 9094 PetscFunctionBegin; 9095 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9096 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9097 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 9098 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9099 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9100 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9101 PetscFunctionReturn(0); 9102 } 9103 9104 /*@C 9105 DMProjectFunctionLabelLocal - This projects the given function into the function space provided, putting the coefficients in a local vector, setting values only for points in the given label. 9106 9107 Not collective 9108 9109 Input Parameters: 9110 + dm - The DM 9111 . time - The time 9112 . label - The DMLabel selecting the portion of the mesh for projection 9113 . funcs - The coordinate functions to evaluate, one per field 9114 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 9115 - mode - The insertion mode for values 9116 9117 Output Parameter: 9118 . localX - vector 9119 9120 Calling sequence of func: 9121 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 9122 9123 + dim - The spatial dimension 9124 . x - The coordinates 9125 . Nc - The number of components 9126 . u - The output field values 9127 - ctx - optional user-defined function context 9128 9129 Level: developer 9130 9131 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 9132 @*/ 9133 PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 9134 { 9135 PetscErrorCode ierr; 9136 9137 PetscFunctionBegin; 9138 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9139 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9140 PetscCheckFalse(!dm->ops->projectfunctionlabellocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 9141 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 9142 PetscFunctionReturn(0); 9143 } 9144 9145 /*@C 9146 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 9147 9148 Not collective 9149 9150 Input Parameters: 9151 + dm - The DM 9152 . time - The time 9153 . localU - The input field vector 9154 . funcs - The functions to evaluate, one per field 9155 - mode - The insertion mode for values 9156 9157 Output Parameter: 9158 . localX - The output vector 9159 9160 Calling sequence of func: 9161 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9162 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9163 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9164 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9165 9166 + dim - The spatial dimension 9167 . Nf - The number of input fields 9168 . NfAux - The number of input auxiliary fields 9169 . uOff - The offset of each field in u[] 9170 . uOff_x - The offset of each field in u_x[] 9171 . u - The field values at this point in space 9172 . u_t - The field time derivative at this point in space (or NULL) 9173 . u_x - The field derivatives at this point in space 9174 . aOff - The offset of each auxiliary field in u[] 9175 . aOff_x - The offset of each auxiliary field in u_x[] 9176 . a - The auxiliary field values at this point in space 9177 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9178 . a_x - The auxiliary field derivatives at this point in space 9179 . t - The current time 9180 . x - The coordinates of this point 9181 . numConstants - The number of constants 9182 . constants - The value of each constant 9183 - f - The value of the function at this point in space 9184 9185 Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 9186 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or 9187 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9188 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9189 9190 Level: intermediate 9191 9192 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9193 @*/ 9194 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 9195 void (**funcs)(PetscInt, PetscInt, PetscInt, 9196 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9197 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9198 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9199 InsertMode mode, Vec localX) 9200 { 9201 PetscErrorCode ierr; 9202 9203 PetscFunctionBegin; 9204 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9205 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 9206 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 9207 PetscCheckFalse(!dm->ops->projectfieldlocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 9208 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 9209 PetscFunctionReturn(0); 9210 } 9211 9212 /*@C 9213 DMProjectFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain specified by the label. 9214 9215 Not collective 9216 9217 Input Parameters: 9218 + dm - The DM 9219 . time - The time 9220 . label - The DMLabel marking the portion of the domain to output 9221 . numIds - The number of label ids to use 9222 . ids - The label ids to use for marking 9223 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 9224 . comps - The components to set in the output, or NULL for all components 9225 . localU - The input field vector 9226 . funcs - The functions to evaluate, one per field 9227 - mode - The insertion mode for values 9228 9229 Output Parameter: 9230 . localX - The output vector 9231 9232 Calling sequence of func: 9233 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9234 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9235 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9236 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9237 9238 + dim - The spatial dimension 9239 . Nf - The number of input fields 9240 . NfAux - The number of input auxiliary fields 9241 . uOff - The offset of each field in u[] 9242 . uOff_x - The offset of each field in u_x[] 9243 . u - The field values at this point in space 9244 . u_t - The field time derivative at this point in space (or NULL) 9245 . u_x - The field derivatives at this point in space 9246 . aOff - The offset of each auxiliary field in u[] 9247 . aOff_x - The offset of each auxiliary field in u_x[] 9248 . a - The auxiliary field values at this point in space 9249 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9250 . a_x - The auxiliary field derivatives at this point in space 9251 . t - The current time 9252 . x - The coordinates of this point 9253 . numConstants - The number of constants 9254 . constants - The value of each constant 9255 - f - The value of the function at this point in space 9256 9257 Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 9258 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or 9259 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9260 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9261 9262 Level: intermediate 9263 9264 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9265 @*/ 9266 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 9267 void (**funcs)(PetscInt, PetscInt, PetscInt, 9268 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9269 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9270 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9271 InsertMode mode, Vec localX) 9272 { 9273 PetscErrorCode ierr; 9274 9275 PetscFunctionBegin; 9276 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9277 PetscValidHeaderSpecific(localU,VEC_CLASSID,8); 9278 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9279 PetscCheckFalse(!dm->ops->projectfieldlabellocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name); 9280 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 9281 PetscFunctionReturn(0); 9282 } 9283 9284 /*@C 9285 DMProjectBdFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain boundary specified by the label. 9286 9287 Not collective 9288 9289 Input Parameters: 9290 + dm - The DM 9291 . time - The time 9292 . label - The DMLabel marking the portion of the domain boundary to output 9293 . numIds - The number of label ids to use 9294 . ids - The label ids to use for marking 9295 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 9296 . comps - The components to set in the output, or NULL for all components 9297 . localU - The input field vector 9298 . funcs - The functions to evaluate, one per field 9299 - mode - The insertion mode for values 9300 9301 Output Parameter: 9302 . localX - The output vector 9303 9304 Calling sequence of func: 9305 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9306 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9307 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9308 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9309 9310 + dim - The spatial dimension 9311 . Nf - The number of input fields 9312 . NfAux - The number of input auxiliary fields 9313 . uOff - The offset of each field in u[] 9314 . uOff_x - The offset of each field in u_x[] 9315 . u - The field values at this point in space 9316 . u_t - The field time derivative at this point in space (or NULL) 9317 . u_x - The field derivatives at this point in space 9318 . aOff - The offset of each auxiliary field in u[] 9319 . aOff_x - The offset of each auxiliary field in u_x[] 9320 . a - The auxiliary field values at this point in space 9321 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9322 . a_x - The auxiliary field derivatives at this point in space 9323 . t - The current time 9324 . x - The coordinates of this point 9325 . n - The face normal 9326 . numConstants - The number of constants 9327 . constants - The value of each constant 9328 - f - The value of the function at this point in space 9329 9330 Note: 9331 There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 9332 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or 9333 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9334 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9335 9336 Level: intermediate 9337 9338 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9339 @*/ 9340 PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 9341 void (**funcs)(PetscInt, PetscInt, PetscInt, 9342 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9343 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9344 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9345 InsertMode mode, Vec localX) 9346 { 9347 PetscErrorCode ierr; 9348 9349 PetscFunctionBegin; 9350 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9351 PetscValidHeaderSpecific(localU,VEC_CLASSID,8); 9352 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9353 PetscCheckFalse(!dm->ops->projectbdfieldlabellocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name); 9354 ierr = (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 9355 PetscFunctionReturn(0); 9356 } 9357 9358 /*@C 9359 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9360 9361 Input Parameters: 9362 + dm - The DM 9363 . time - The time 9364 . funcs - The functions to evaluate for each field component 9365 . ctxs - Optional array of contexts to pass to each function, or NULL. 9366 - X - The coefficient vector u_h, a global vector 9367 9368 Output Parameter: 9369 . diff - The diff ||u - u_h||_2 9370 9371 Level: developer 9372 9373 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 9374 @*/ 9375 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 9376 { 9377 PetscErrorCode ierr; 9378 9379 PetscFunctionBegin; 9380 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9381 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9382 PetscCheckFalse(!dm->ops->computel2diff,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 9383 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 9384 PetscFunctionReturn(0); 9385 } 9386 9387 /*@C 9388 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 9389 9390 Collective on dm 9391 9392 Input Parameters: 9393 + dm - The DM 9394 , time - The time 9395 . funcs - The gradient functions to evaluate for each field component 9396 . ctxs - Optional array of contexts to pass to each function, or NULL. 9397 . X - The coefficient vector u_h, a global vector 9398 - n - The vector to project along 9399 9400 Output Parameter: 9401 . diff - The diff ||(grad u - grad u_h) . n||_2 9402 9403 Level: developer 9404 9405 .seealso: DMProjectFunction(), DMComputeL2Diff() 9406 @*/ 9407 PetscErrorCode DMComputeL2GradientDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff) 9408 { 9409 PetscErrorCode ierr; 9410 9411 PetscFunctionBegin; 9412 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9413 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9414 PetscCheckFalse(!dm->ops->computel2gradientdiff,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 9415 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 9416 PetscFunctionReturn(0); 9417 } 9418 9419 /*@C 9420 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 9421 9422 Collective on dm 9423 9424 Input Parameters: 9425 + dm - The DM 9426 . time - The time 9427 . funcs - The functions to evaluate for each field component 9428 . ctxs - Optional array of contexts to pass to each function, or NULL. 9429 - X - The coefficient vector u_h, a global vector 9430 9431 Output Parameter: 9432 . diff - The array of differences, ||u^f - u^f_h||_2 9433 9434 Level: developer 9435 9436 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 9437 @*/ 9438 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 9439 { 9440 PetscErrorCode ierr; 9441 9442 PetscFunctionBegin; 9443 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9444 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9445 PetscCheckFalse(!dm->ops->computel2fielddiff,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 9446 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 9447 PetscFunctionReturn(0); 9448 } 9449 9450 /*@C 9451 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 9452 9453 Not Collective 9454 9455 Input Parameter: 9456 . dm - The DM 9457 9458 Output Parameters: 9459 + nranks - the number of neighbours 9460 - ranks - the neighbors ranks 9461 9462 Notes: 9463 Do not free the array, it is freed when the DM is destroyed. 9464 9465 Level: beginner 9466 9467 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 9468 @*/ 9469 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 9470 { 9471 PetscErrorCode ierr; 9472 9473 PetscFunctionBegin; 9474 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9475 PetscCheckFalse(!dm->ops->getneighbors,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 9476 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 9477 PetscFunctionReturn(0); 9478 } 9479 9480 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 9481 9482 /* 9483 Converts the input vector to a ghosted vector and then calls the standard coloring code. 9484 This has be a different function because it requires DM which is not defined in the Mat library 9485 */ 9486 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 9487 { 9488 PetscErrorCode ierr; 9489 9490 PetscFunctionBegin; 9491 if (coloring->ctype == IS_COLORING_LOCAL) { 9492 Vec x1local; 9493 DM dm; 9494 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9495 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 9496 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 9497 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9498 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9499 x1 = x1local; 9500 } 9501 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 9502 if (coloring->ctype == IS_COLORING_LOCAL) { 9503 DM dm; 9504 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9505 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 9506 } 9507 PetscFunctionReturn(0); 9508 } 9509 9510 /*@ 9511 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 9512 9513 Input Parameter: 9514 . coloring - the MatFDColoring object 9515 9516 Developer Notes: 9517 this routine exists because the PETSc Mat library does not know about the DM objects 9518 9519 Level: advanced 9520 9521 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 9522 @*/ 9523 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 9524 { 9525 PetscFunctionBegin; 9526 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 9527 PetscFunctionReturn(0); 9528 } 9529 9530 /*@ 9531 DMGetCompatibility - determine if two DMs are compatible 9532 9533 Collective 9534 9535 Input Parameters: 9536 + dm1 - the first DM 9537 - dm2 - the second DM 9538 9539 Output Parameters: 9540 + compatible - whether or not the two DMs are compatible 9541 - set - whether or not the compatible value was set 9542 9543 Notes: 9544 Two DMs are deemed compatible if they represent the same parallel decomposition 9545 of the same topology. This implies that the section (field data) on one 9546 "makes sense" with respect to the topology and parallel decomposition of the other. 9547 Loosely speaking, compatible DMs represent the same domain and parallel 9548 decomposition, but hold different data. 9549 9550 Typically, one would confirm compatibility if intending to simultaneously iterate 9551 over a pair of vectors obtained from different DMs. 9552 9553 For example, two DMDA objects are compatible if they have the same local 9554 and global sizes and the same stencil width. They can have different numbers 9555 of degrees of freedom per node. Thus, one could use the node numbering from 9556 either DM in bounds for a loop over vectors derived from either DM. 9557 9558 Consider the operation of summing data living on a 2-dof DMDA to data living 9559 on a 1-dof DMDA, which should be compatible, as in the following snippet. 9560 .vb 9561 ... 9562 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 9563 if (set && compatible) { 9564 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9565 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9566 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 9567 for (j=y; j<y+n; ++j) { 9568 for (i=x; i<x+m, ++i) { 9569 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 9570 } 9571 } 9572 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9573 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9574 } else { 9575 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 9576 } 9577 ... 9578 .ve 9579 9580 Checking compatibility might be expensive for a given implementation of DM, 9581 or might be impossible to unambiguously confirm or deny. For this reason, 9582 this function may decline to determine compatibility, and hence users should 9583 always check the "set" output parameter. 9584 9585 A DM is always compatible with itself. 9586 9587 In the current implementation, DMs which live on "unequal" communicators 9588 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 9589 incompatible. 9590 9591 This function is labeled "Collective," as information about all subdomains 9592 is required on each rank. However, in DM implementations which store all this 9593 information locally, this function may be merely "Logically Collective". 9594 9595 Developer Notes: 9596 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 9597 iff B is compatible with A. Thus, this function checks the implementations 9598 of both dm and dmc (if they are of different types), attempting to determine 9599 compatibility. It is left to DM implementers to ensure that symmetry is 9600 preserved. The simplest way to do this is, when implementing type-specific 9601 logic for this function, is to check for existing logic in the implementation 9602 of other DM types and let *set = PETSC_FALSE if found. 9603 9604 Level: advanced 9605 9606 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 9607 @*/ 9608 9609 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 9610 { 9611 PetscErrorCode ierr; 9612 PetscMPIInt compareResult; 9613 DMType type,type2; 9614 PetscBool sameType; 9615 9616 PetscFunctionBegin; 9617 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 9618 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 9619 9620 /* Declare a DM compatible with itself */ 9621 if (dm1 == dm2) { 9622 *set = PETSC_TRUE; 9623 *compatible = PETSC_TRUE; 9624 PetscFunctionReturn(0); 9625 } 9626 9627 /* Declare a DM incompatible with a DM that lives on an "unequal" 9628 communicator. Note that this does not preclude compatibility with 9629 DMs living on "congruent" or "similar" communicators, but this must be 9630 determined by the implementation-specific logic */ 9631 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRMPI(ierr); 9632 if (compareResult == MPI_UNEQUAL) { 9633 *set = PETSC_TRUE; 9634 *compatible = PETSC_FALSE; 9635 PetscFunctionReturn(0); 9636 } 9637 9638 /* Pass to the implementation-specific routine, if one exists. */ 9639 if (dm1->ops->getcompatibility) { 9640 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 9641 if (*set) PetscFunctionReturn(0); 9642 } 9643 9644 /* If dm1 and dm2 are of different types, then attempt to check compatibility 9645 with an implementation of this function from dm2 */ 9646 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 9647 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 9648 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 9649 if (!sameType && dm2->ops->getcompatibility) { 9650 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 9651 } else { 9652 *set = PETSC_FALSE; 9653 } 9654 PetscFunctionReturn(0); 9655 } 9656 9657 /*@C 9658 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 9659 9660 Logically Collective on DM 9661 9662 Input Parameters: 9663 + DM - the DM 9664 . f - the monitor function 9665 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 9666 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 9667 9668 Options Database Keys: 9669 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 9670 does not cancel those set via the options database. 9671 9672 Notes: 9673 Several different monitoring routines may be set by calling 9674 DMMonitorSet() multiple times; all will be called in the 9675 order in which they were set. 9676 9677 Fortran Notes: 9678 Only a single monitor function can be set for each DM object 9679 9680 Level: intermediate 9681 9682 .seealso: DMMonitorCancel() 9683 @*/ 9684 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 9685 { 9686 PetscInt m; 9687 PetscErrorCode ierr; 9688 9689 PetscFunctionBegin; 9690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9691 for (m = 0; m < dm->numbermonitors; ++m) { 9692 PetscBool identical; 9693 9694 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 9695 if (identical) PetscFunctionReturn(0); 9696 } 9697 PetscCheckFalse(dm->numbermonitors >= MAXDMMONITORS,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 9698 dm->monitor[dm->numbermonitors] = f; 9699 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 9700 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 9701 PetscFunctionReturn(0); 9702 } 9703 9704 /*@ 9705 DMMonitorCancel - Clears all the monitor functions for a DM object. 9706 9707 Logically Collective on DM 9708 9709 Input Parameter: 9710 . dm - the DM 9711 9712 Options Database Key: 9713 . -dm_monitor_cancel - cancels all monitors that have been hardwired 9714 into a code by calls to DMonitorSet(), but does not cancel those 9715 set via the options database 9716 9717 Notes: 9718 There is no way to clear one specific monitor from a DM object. 9719 9720 Level: intermediate 9721 9722 .seealso: DMMonitorSet() 9723 @*/ 9724 PetscErrorCode DMMonitorCancel(DM dm) 9725 { 9726 PetscErrorCode ierr; 9727 PetscInt m; 9728 9729 PetscFunctionBegin; 9730 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9731 for (m = 0; m < dm->numbermonitors; ++m) { 9732 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 9733 } 9734 dm->numbermonitors = 0; 9735 PetscFunctionReturn(0); 9736 } 9737 9738 /*@C 9739 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 9740 9741 Collective on DM 9742 9743 Input Parameters: 9744 + dm - DM object you wish to monitor 9745 . name - the monitor type one is seeking 9746 . help - message indicating what monitoring is done 9747 . manual - manual page for the monitor 9748 . monitor - the monitor function 9749 - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the DM or PetscViewer objects 9750 9751 Output Parameter: 9752 . flg - Flag set if the monitor was created 9753 9754 Level: developer 9755 9756 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 9757 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 9758 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 9759 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 9760 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 9761 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 9762 PetscOptionsFList(), PetscOptionsEList() 9763 @*/ 9764 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 9765 { 9766 PetscViewer viewer; 9767 PetscViewerFormat format; 9768 PetscErrorCode ierr; 9769 9770 PetscFunctionBegin; 9771 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9772 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 9773 if (*flg) { 9774 PetscViewerAndFormat *vf; 9775 9776 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 9777 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 9778 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 9779 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 9780 } 9781 PetscFunctionReturn(0); 9782 } 9783 9784 /*@ 9785 DMMonitor - runs the user provided monitor routines, if they exist 9786 9787 Collective on DM 9788 9789 Input Parameters: 9790 . dm - The DM 9791 9792 Level: developer 9793 9794 .seealso: DMMonitorSet() 9795 @*/ 9796 PetscErrorCode DMMonitor(DM dm) 9797 { 9798 PetscInt m; 9799 PetscErrorCode ierr; 9800 9801 PetscFunctionBegin; 9802 if (!dm) PetscFunctionReturn(0); 9803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9804 for (m = 0; m < dm->numbermonitors; ++m) { 9805 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 9806 } 9807 PetscFunctionReturn(0); 9808 } 9809 9810 /*@ 9811 DMComputeError - Computes the error assuming the user has given exact solution functions 9812 9813 Collective on DM 9814 9815 Input Parameters: 9816 + dm - The DM 9817 - sol - The solution vector 9818 9819 Input/Output Parameter: 9820 . errors - An array of length Nf, the number of fields, or NULL for no output; on output 9821 contains the error in each field 9822 9823 Output Parameter: 9824 . errorVec - A vector to hold the cellwise error (may be NULL) 9825 9826 Note: The exact solutions come from the PetscDS object, and the time comes from DMGetOutputSequenceNumber(). 9827 9828 Level: developer 9829 9830 .seealso: DMMonitorSet(), DMGetRegionNumDS(), PetscDSGetExactSolution(), DMGetOutputSequenceNumber() 9831 @*/ 9832 PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec) 9833 { 9834 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 9835 void **ctxs; 9836 PetscReal time; 9837 PetscInt Nf, f, Nds, s; 9838 PetscErrorCode ierr; 9839 9840 PetscFunctionBegin; 9841 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9842 ierr = PetscCalloc2(Nf, &exactSol, Nf, &ctxs);CHKERRQ(ierr); 9843 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 9844 for (s = 0; s < Nds; ++s) { 9845 PetscDS ds; 9846 DMLabel label; 9847 IS fieldIS; 9848 const PetscInt *fields; 9849 PetscInt dsNf; 9850 9851 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 9852 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 9853 if (fieldIS) {ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);} 9854 for (f = 0; f < dsNf; ++f) { 9855 const PetscInt field = fields[f]; 9856 ierr = PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]);CHKERRQ(ierr); 9857 } 9858 if (fieldIS) {ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);} 9859 } 9860 for (f = 0; f < Nf; ++f) { 9861 PetscCheckFalse(!exactSol[f],PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "DS must contain exact solution functions in order to calculate error, missing for field %D", f); 9862 } 9863 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 9864 if (errors) {ierr = DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors);CHKERRQ(ierr);} 9865 if (errorVec) { 9866 DM edm; 9867 DMPolytopeType ct; 9868 PetscBool simplex; 9869 PetscInt dim, cStart, Nf; 9870 9871 ierr = DMClone(dm, &edm);CHKERRQ(ierr); 9872 ierr = DMGetDimension(edm, &dim);CHKERRQ(ierr); 9873 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 9874 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 9875 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 9876 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9877 for (f = 0; f < Nf; ++f) { 9878 PetscFE fe, efe; 9879 PetscQuadrature q; 9880 const char *name; 9881 9882 ierr = DMGetField(dm, f, NULL, (PetscObject *) &fe);CHKERRQ(ierr); 9883 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe);CHKERRQ(ierr); 9884 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 9885 ierr = PetscObjectSetName((PetscObject) efe, name);CHKERRQ(ierr); 9886 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 9887 ierr = PetscFESetQuadrature(efe, q);CHKERRQ(ierr); 9888 ierr = DMSetField(edm, f, NULL, (PetscObject) efe);CHKERRQ(ierr); 9889 ierr = PetscFEDestroy(&efe);CHKERRQ(ierr); 9890 } 9891 ierr = DMCreateDS(edm);CHKERRQ(ierr); 9892 9893 ierr = DMCreateGlobalVector(edm, errorVec);CHKERRQ(ierr); 9894 ierr = PetscObjectSetName((PetscObject) *errorVec, "Error");CHKERRQ(ierr); 9895 ierr = DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec);CHKERRQ(ierr); 9896 ierr = DMDestroy(&edm);CHKERRQ(ierr); 9897 } 9898 ierr = PetscFree2(exactSol, ctxs);CHKERRQ(ierr); 9899 PetscFunctionReturn(0); 9900 } 9901 9902 /*@ 9903 DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this DM 9904 9905 Not collective 9906 9907 Input Parameter: 9908 . dm - The DM 9909 9910 Output Parameter: 9911 . numAux - The number of auxiliary data vectors 9912 9913 Level: advanced 9914 9915 .seealso: DMGetAuxiliaryLabels(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9916 @*/ 9917 PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux) 9918 { 9919 PetscErrorCode ierr; 9920 9921 PetscFunctionBegin; 9922 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9923 ierr = PetscHMapAuxGetSize(dm->auxData, numAux);CHKERRQ(ierr); 9924 PetscFunctionReturn(0); 9925 } 9926 9927 /*@ 9928 DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value 9929 9930 Not collective 9931 9932 Input Parameters: 9933 + dm - The DM 9934 . label - The DMLabel 9935 - value - The label value indicating the region 9936 9937 Output Parameter: 9938 . aux - The Vec holding auxiliary field data 9939 9940 Note: If no auxiliary vector is found for this (label, value), (NULL, 0) is checked as well. 9941 9942 Level: advanced 9943 9944 .seealso: DMSetAuxiliaryVec(), DMGetNumAuxiliaryVec() 9945 @*/ 9946 PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec *aux) 9947 { 9948 PetscHashAuxKey key, wild = {NULL, 0}; 9949 PetscBool has; 9950 PetscErrorCode ierr; 9951 9952 PetscFunctionBegin; 9953 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9954 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9955 key.label = label; 9956 key.value = value; 9957 ierr = PetscHMapAuxHas(dm->auxData, key, &has);CHKERRQ(ierr); 9958 if (has) {ierr = PetscHMapAuxGet(dm->auxData, key, aux);CHKERRQ(ierr);} 9959 else {ierr = PetscHMapAuxGet(dm->auxData, wild, aux);CHKERRQ(ierr);} 9960 PetscFunctionReturn(0); 9961 } 9962 9963 /*@ 9964 DMSetAuxiliaryVec - Set the auxiliary vector for region specified by the given label and value 9965 9966 Not collective 9967 9968 Input Parameters: 9969 + dm - The DM 9970 . label - The DMLabel 9971 . value - The label value indicating the region 9972 - aux - The Vec holding auxiliary field data 9973 9974 Level: advanced 9975 9976 .seealso: DMGetAuxiliaryVec() 9977 @*/ 9978 PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec aux) 9979 { 9980 Vec old; 9981 PetscHashAuxKey key; 9982 PetscErrorCode ierr; 9983 9984 PetscFunctionBegin; 9985 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9986 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9987 key.label = label; 9988 key.value = value; 9989 ierr = PetscHMapAuxGet(dm->auxData, key, &old);CHKERRQ(ierr); 9990 ierr = PetscObjectReference((PetscObject) aux);CHKERRQ(ierr); 9991 ierr = PetscObjectDereference((PetscObject) old);CHKERRQ(ierr); 9992 if (!aux) {ierr = PetscHMapAuxDel(dm->auxData, key);CHKERRQ(ierr);} 9993 else {ierr = PetscHMapAuxSet(dm->auxData, key, aux);CHKERRQ(ierr);} 9994 PetscFunctionReturn(0); 9995 } 9996 9997 /*@C 9998 DMGetAuxiliaryLabels - Get the labels and values for all auxiliary vectors in this DM 9999 10000 Not collective 10001 10002 Input Parameter: 10003 . dm - The DM 10004 10005 Output Parameters: 10006 + labels - The DMLabels for each Vec 10007 - values - The label values for each Vec 10008 10009 Note: The arrays passed in must be at least as large as DMGetNumAuxiliaryVec(). 10010 10011 Level: advanced 10012 10013 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 10014 @*/ 10015 PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[]) 10016 { 10017 PetscHashAuxKey *keys; 10018 PetscInt n, i, off = 0; 10019 PetscErrorCode ierr; 10020 10021 PetscFunctionBegin; 10022 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10023 PetscValidPointer(labels, 2); 10024 PetscValidPointer(values, 3); 10025 ierr = DMGetNumAuxiliaryVec(dm, &n);CHKERRQ(ierr); 10026 ierr = PetscMalloc1(n, &keys);CHKERRQ(ierr); 10027 ierr = PetscHMapAuxGetKeys(dm->auxData, &off, keys);CHKERRQ(ierr); 10028 for (i = 0; i < n; ++i) {labels[i] = keys[i].label; values[i] = keys[i].value;} 10029 ierr = PetscFree(keys);CHKERRQ(ierr); 10030 PetscFunctionReturn(0); 10031 } 10032 10033 /*@ 10034 DMCopyAuxiliaryVec - Copy the auxiliary data to a new DM 10035 10036 Not collective 10037 10038 Input Parameter: 10039 . dm - The DM 10040 10041 Output Parameter: 10042 . dmNew - The new DM, now with the same auxiliary data 10043 10044 Level: advanced 10045 10046 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 10047 @*/ 10048 PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew) 10049 { 10050 PetscErrorCode ierr; 10051 10052 PetscFunctionBegin; 10053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10054 ierr = PetscHMapAuxDestroy(&dmNew->auxData);CHKERRQ(ierr); 10055 ierr = PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData);CHKERRQ(ierr); 10056 PetscFunctionReturn(0); 10057 } 10058 10059 /*@C 10060 DMPolytopeMatchOrientation - Determine an orientation that takes the source face arrangement to the target face arrangement 10061 10062 Not collective 10063 10064 Input Parameters: 10065 + ct - The DMPolytopeType 10066 . sourceCone - The source arrangement of faces 10067 - targetCone - The target arrangement of faces 10068 10069 Output Parameters: 10070 + ornt - The orientation which will take the source arrangement to the target arrangement 10071 - found - Flag indicating that a suitable orientation was found 10072 10073 Level: advanced 10074 10075 .seealso: DMPolytopeGetOrientation(), DMPolytopeMatchVertexOrientation() 10076 @*/ 10077 PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found) 10078 { 10079 const PetscInt cS = DMPolytopeTypeGetConeSize(ct); 10080 const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct)/2; 10081 PetscInt o, c; 10082 10083 PetscFunctionBegin; 10084 if (!nO) {*ornt = 0; *found = PETSC_TRUE; PetscFunctionReturn(0);} 10085 for (o = -nO; o < nO; ++o) { 10086 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 10087 10088 for (c = 0; c < cS; ++c) if (sourceCone[arr[c*2]] != targetCone[c]) break; 10089 if (c == cS) {*ornt = o; break;} 10090 } 10091 *found = o == nO ? PETSC_FALSE : PETSC_TRUE; 10092 PetscFunctionReturn(0); 10093 } 10094 10095 /*@C 10096 DMPolytopeGetOrientation - Determine an orientation that takes the source face arrangement to the target face arrangement 10097 10098 Not collective 10099 10100 Input Parameters: 10101 + ct - The DMPolytopeType 10102 . sourceCone - The source arrangement of faces 10103 - targetCone - The target arrangement of faces 10104 10105 Output Parameters: 10106 . ornt - The orientation which will take the source arrangement to the target arrangement 10107 10108 Note: This function will fail if no suitable orientation can be found. 10109 10110 Level: advanced 10111 10112 .seealso: DMPolytopeMatchOrientation(), DMPolytopeGetVertexOrientation() 10113 @*/ 10114 PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt) 10115 { 10116 PetscBool found; 10117 PetscErrorCode ierr; 10118 10119 PetscFunctionBegin; 10120 ierr = DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found);CHKERRQ(ierr); 10121 PetscCheckFalse(!found,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]); 10122 PetscFunctionReturn(0); 10123 } 10124 10125 /*@C 10126 DMPolytopeMatchVertexOrientation - Determine an orientation that takes the source vertex arrangement to the target vertex arrangement 10127 10128 Not collective 10129 10130 Input Parameters: 10131 + ct - The DMPolytopeType 10132 . sourceVert - The source arrangement of vertices 10133 - targetVert - The target arrangement of vertices 10134 10135 Output Parameters: 10136 + ornt - The orientation which will take the source arrangement to the target arrangement 10137 - found - Flag indicating that a suitable orientation was found 10138 10139 Level: advanced 10140 10141 .seealso: DMPolytopeGetOrientation(), DMPolytopeMatchOrientation() 10142 @*/ 10143 PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found) 10144 { 10145 const PetscInt cS = DMPolytopeTypeGetNumVertices(ct); 10146 const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct)/2; 10147 PetscInt o, c; 10148 10149 PetscFunctionBegin; 10150 if (!nO) {*ornt = 0; *found = PETSC_TRUE; PetscFunctionReturn(0);} 10151 for (o = -nO; o < nO; ++o) { 10152 const PetscInt *arr = DMPolytopeTypeGetVertexArrangment(ct, o); 10153 10154 for (c = 0; c < cS; ++c) if (sourceVert[arr[c]] != targetVert[c]) break; 10155 if (c == cS) {*ornt = o; break;} 10156 } 10157 *found = o == nO ? PETSC_FALSE : PETSC_TRUE; 10158 PetscFunctionReturn(0); 10159 } 10160 10161 /*@C 10162 DMPolytopeGetVertexOrientation - Determine an orientation that takes the source vertex arrangement to the target vertex arrangement 10163 10164 Not collective 10165 10166 Input Parameters: 10167 + ct - The DMPolytopeType 10168 . sourceCone - The source arrangement of vertices 10169 - targetCone - The target arrangement of vertices 10170 10171 Output Parameters: 10172 . ornt - The orientation which will take the source arrangement to the target arrangement 10173 10174 Note: This function will fail if no suitable orientation can be found. 10175 10176 Level: advanced 10177 10178 .seealso: DMPolytopeMatchVertexOrientation(), DMPolytopeGetOrientation() 10179 @*/ 10180 PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt) 10181 { 10182 PetscBool found; 10183 PetscErrorCode ierr; 10184 10185 PetscFunctionBegin; 10186 ierr = DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found);CHKERRQ(ierr); 10187 PetscCheckFalse(!found,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]); 10188 PetscFunctionReturn(0); 10189 } 10190 10191 /*@C 10192 DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type 10193 10194 Not collective 10195 10196 Input Parameters: 10197 + ct - The DMPolytopeType 10198 - point - Coordinates of the point 10199 10200 Output Parameters: 10201 . inside - Flag indicating whether the point is inside the reference cell of given type 10202 10203 Level: advanced 10204 10205 .seealso: DMLocatePoints() 10206 @*/ 10207 PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside) 10208 { 10209 PetscReal sum = 0.0; 10210 PetscInt d; 10211 10212 PetscFunctionBegin; 10213 *inside = PETSC_TRUE; 10214 switch (ct) { 10215 case DM_POLYTOPE_TRIANGLE: 10216 case DM_POLYTOPE_TETRAHEDRON: 10217 for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) { 10218 if (point[d] < -1.0) {*inside = PETSC_FALSE; break;} 10219 sum += point[d]; 10220 } 10221 if (sum > PETSC_SMALL) {*inside = PETSC_FALSE; break;} 10222 break; 10223 case DM_POLYTOPE_QUADRILATERAL: 10224 case DM_POLYTOPE_HEXAHEDRON: 10225 for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) 10226 if (PetscAbsReal(point[d]) > 1.+PETSC_SMALL) {*inside = PETSC_FALSE; break;} 10227 break; 10228 default: 10229 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]); 10230 } 10231 PetscFunctionReturn(0); 10232 } 10233