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