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