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