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