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 6365 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 6366 { 6367 PetscInt d; 6368 6369 PetscFunctionBegin; 6370 if (!dm->maxCell) { 6371 for (d = 0; d < dim; ++d) out[d] = in[d]; 6372 } else { 6373 for (d = 0; d < dim; ++d) { 6374 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 6375 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6376 } else { 6377 out[d] = in[d]; 6378 } 6379 } 6380 } 6381 PetscFunctionReturn(0); 6382 } 6383 6384 /* 6385 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. 6386 6387 Input Parameters: 6388 + dm - The DM 6389 . dim - The spatial dimension 6390 . anchor - The anchor point, the input point can be no more than maxCell away from it 6391 . in - The input coordinate delta (dim numbers) 6392 - out - The input coordinate point (dim numbers) 6393 6394 Output Parameter: 6395 . out - The localized coordinate in + out 6396 6397 Level: developer 6398 6399 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 6400 6401 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 6402 */ 6403 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6404 { 6405 PetscInt d; 6406 6407 PetscFunctionBegin; 6408 if (!dm->maxCell) { 6409 for (d = 0; d < dim; ++d) out[d] += in[d]; 6410 } else { 6411 for (d = 0; d < dim; ++d) { 6412 const PetscReal maxC = dm->maxCell[d]; 6413 6414 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 6415 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6416 6417 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 6418 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])); 6419 out[d] += newCoord; 6420 } else { 6421 out[d] += in[d]; 6422 } 6423 } 6424 } 6425 PetscFunctionReturn(0); 6426 } 6427 6428 /*@ 6429 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 6430 6431 Not collective 6432 6433 Input Parameter: 6434 . dm - The DM 6435 6436 Output Parameter: 6437 areLocalized - True if localized 6438 6439 Level: developer 6440 6441 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6442 @*/ 6443 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6444 { 6445 DM cdm; 6446 PetscSection coordSection; 6447 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 6448 PetscBool isPlex, alreadyLocalized; 6449 PetscErrorCode ierr; 6450 6451 PetscFunctionBegin; 6452 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6453 PetscValidBoolPointer(areLocalized, 2); 6454 *areLocalized = PETSC_FALSE; 6455 6456 /* We need some generic way of refering to cells/vertices */ 6457 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6458 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6459 if (!isPlex) PetscFunctionReturn(0); 6460 6461 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6462 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6463 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6464 alreadyLocalized = PETSC_FALSE; 6465 for (c = cStart; c < cEnd; ++c) { 6466 if (c < sStart || c >= sEnd) continue; 6467 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6468 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6469 } 6470 *areLocalized = alreadyLocalized; 6471 PetscFunctionReturn(0); 6472 } 6473 6474 /*@ 6475 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6476 6477 Collective on dm 6478 6479 Input Parameter: 6480 . dm - The DM 6481 6482 Output Parameter: 6483 areLocalized - True if localized 6484 6485 Level: developer 6486 6487 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6488 @*/ 6489 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6490 { 6491 PetscBool localized; 6492 PetscErrorCode ierr; 6493 6494 PetscFunctionBegin; 6495 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6496 PetscValidBoolPointer(areLocalized, 2); 6497 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6498 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6499 PetscFunctionReturn(0); 6500 } 6501 6502 /*@ 6503 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6504 6505 Collective on dm 6506 6507 Input Parameter: 6508 . dm - The DM 6509 6510 Level: developer 6511 6512 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6513 @*/ 6514 PetscErrorCode DMLocalizeCoordinates(DM dm) 6515 { 6516 DM cdm; 6517 PetscSection coordSection, cSection; 6518 Vec coordinates, cVec; 6519 PetscScalar *coords, *coords2, *anchor, *localized; 6520 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6521 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6522 PetscInt maxHeight = 0, h; 6523 PetscInt *pStart = NULL, *pEnd = NULL; 6524 PetscErrorCode ierr; 6525 6526 PetscFunctionBegin; 6527 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6528 if (!dm->periodic) PetscFunctionReturn(0); 6529 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6530 if (alreadyLocalized) PetscFunctionReturn(0); 6531 6532 /* We need some generic way of refering to cells/vertices */ 6533 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6534 { 6535 PetscBool isplex; 6536 6537 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6538 if (isplex) { 6539 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6540 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6541 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6542 pEnd = &pStart[maxHeight + 1]; 6543 newStart = vStart; 6544 newEnd = vEnd; 6545 for (h = 0; h <= maxHeight; h++) { 6546 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6547 newStart = PetscMin(newStart,pStart[h]); 6548 newEnd = PetscMax(newEnd,pEnd[h]); 6549 } 6550 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6551 } 6552 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6553 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6554 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6555 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6556 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6557 6558 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6559 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6560 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6561 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6562 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6563 6564 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6565 localized = &anchor[bs]; 6566 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6567 for (h = 0; h <= maxHeight; h++) { 6568 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6569 6570 for (c = cStart; c < cEnd; ++c) { 6571 PetscScalar *cellCoords = NULL; 6572 PetscInt b; 6573 6574 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6575 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6576 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6577 for (d = 0; d < dof/bs; ++d) { 6578 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6579 for (b = 0; b < bs; b++) { 6580 if (cellCoords[d*bs + b] != localized[b]) break; 6581 } 6582 if (b < bs) break; 6583 } 6584 if (d < dof/bs) { 6585 if (c >= sStart && c < sEnd) { 6586 PetscInt cdof; 6587 6588 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6589 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6590 } 6591 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6592 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6593 } 6594 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6595 } 6596 } 6597 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6598 if (alreadyLocalizedGlobal) { 6599 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6600 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6601 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6602 PetscFunctionReturn(0); 6603 } 6604 for (v = vStart; v < vEnd; ++v) { 6605 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6606 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6607 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6608 } 6609 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6610 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6611 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6612 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6613 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6614 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6615 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6616 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6617 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 6618 for (v = vStart; v < vEnd; ++v) { 6619 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6620 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6621 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 6622 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 6623 } 6624 for (h = 0; h <= maxHeight; h++) { 6625 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6626 6627 for (c = cStart; c < cEnd; ++c) { 6628 PetscScalar *cellCoords = NULL; 6629 PetscInt b, cdof; 6630 6631 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 6632 if (!cdof) continue; 6633 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6634 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 6635 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6636 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 6637 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6638 } 6639 } 6640 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6641 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6642 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6643 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 6644 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 6645 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 6646 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 6647 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6648 PetscFunctionReturn(0); 6649 } 6650 6651 /*@ 6652 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 6653 6654 Collective on v (see explanation below) 6655 6656 Input Parameters: 6657 + dm - The DM 6658 . v - The Vec of points 6659 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 6660 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 6661 6662 Output Parameter: 6663 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 6664 - cells - The PetscSF containing the ranks and local indices of the containing points. 6665 6666 6667 Level: developer 6668 6669 Notes: 6670 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 6671 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 6672 6673 If *cellSF is NULL on input, a PetscSF will be created. 6674 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 6675 6676 An array that maps each point to its containing cell can be obtained with 6677 6678 $ const PetscSFNode *cells; 6679 $ PetscInt nFound; 6680 $ const PetscInt *found; 6681 $ 6682 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 6683 6684 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 6685 the index of the cell in its rank's local numbering. 6686 6687 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 6688 @*/ 6689 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 6690 { 6691 PetscErrorCode ierr; 6692 6693 PetscFunctionBegin; 6694 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6695 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 6696 PetscValidPointer(cellSF,4); 6697 if (*cellSF) { 6698 PetscMPIInt result; 6699 6700 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 6701 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 6702 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 6703 } else { 6704 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 6705 } 6706 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 6707 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6708 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 6709 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6710 PetscFunctionReturn(0); 6711 } 6712 6713 /*@ 6714 DMGetOutputDM - Retrieve the DM associated with the layout for output 6715 6716 Collective on dm 6717 6718 Input Parameter: 6719 . dm - The original DM 6720 6721 Output Parameter: 6722 . odm - The DM which provides the layout for output 6723 6724 Level: intermediate 6725 6726 .seealso: VecView(), DMGetGlobalSection() 6727 @*/ 6728 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 6729 { 6730 PetscSection section; 6731 PetscBool hasConstraints, ghasConstraints; 6732 PetscErrorCode ierr; 6733 6734 PetscFunctionBegin; 6735 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6736 PetscValidPointer(odm,2); 6737 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 6738 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 6739 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6740 if (!ghasConstraints) { 6741 *odm = dm; 6742 PetscFunctionReturn(0); 6743 } 6744 if (!dm->dmBC) { 6745 PetscSection newSection, gsection; 6746 PetscSF sf; 6747 6748 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 6749 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 6750 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 6751 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 6752 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 6753 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 6754 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 6755 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 6756 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 6757 } 6758 *odm = dm->dmBC; 6759 PetscFunctionReturn(0); 6760 } 6761 6762 /*@ 6763 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 6764 6765 Input Parameter: 6766 . dm - The original DM 6767 6768 Output Parameters: 6769 + num - The output sequence number 6770 - val - The output sequence value 6771 6772 Level: intermediate 6773 6774 Note: This is intended for output that should appear in sequence, for instance 6775 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6776 6777 .seealso: VecView() 6778 @*/ 6779 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 6780 { 6781 PetscFunctionBegin; 6782 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6783 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 6784 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 6785 PetscFunctionReturn(0); 6786 } 6787 6788 /*@ 6789 DMSetOutputSequenceNumber - Set the sequence number/value for output 6790 6791 Input Parameters: 6792 + dm - The original DM 6793 . num - The output sequence number 6794 - val - The output sequence value 6795 6796 Level: intermediate 6797 6798 Note: This is intended for output that should appear in sequence, for instance 6799 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6800 6801 .seealso: VecView() 6802 @*/ 6803 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 6804 { 6805 PetscFunctionBegin; 6806 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6807 dm->outputSequenceNum = num; 6808 dm->outputSequenceVal = val; 6809 PetscFunctionReturn(0); 6810 } 6811 6812 /*@C 6813 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 6814 6815 Input Parameters: 6816 + dm - The original DM 6817 . name - The sequence name 6818 - num - The output sequence number 6819 6820 Output Parameter: 6821 . val - The output sequence value 6822 6823 Level: intermediate 6824 6825 Note: This is intended for output that should appear in sequence, for instance 6826 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6827 6828 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 6829 @*/ 6830 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 6831 { 6832 PetscBool ishdf5; 6833 PetscErrorCode ierr; 6834 6835 PetscFunctionBegin; 6836 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6837 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 6838 PetscValidRealPointer(val,4); 6839 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 6840 if (ishdf5) { 6841 #if defined(PETSC_HAVE_HDF5) 6842 PetscScalar value; 6843 6844 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 6845 *val = PetscRealPart(value); 6846 #endif 6847 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 6848 PetscFunctionReturn(0); 6849 } 6850 6851 /*@ 6852 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 6853 6854 Not collective 6855 6856 Input Parameter: 6857 . dm - The DM 6858 6859 Output Parameter: 6860 . useNatural - The flag to build the mapping to a natural order during distribution 6861 6862 Level: beginner 6863 6864 .seealso: DMSetUseNatural(), DMCreate() 6865 @*/ 6866 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 6867 { 6868 PetscFunctionBegin; 6869 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6870 PetscValidBoolPointer(useNatural, 2); 6871 *useNatural = dm->useNatural; 6872 PetscFunctionReturn(0); 6873 } 6874 6875 /*@ 6876 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 6877 6878 Collective on dm 6879 6880 Input Parameters: 6881 + dm - The DM 6882 - useNatural - The flag to build the mapping to a natural order during distribution 6883 6884 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 6885 6886 Level: beginner 6887 6888 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 6889 @*/ 6890 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 6891 { 6892 PetscFunctionBegin; 6893 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6894 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 6895 dm->useNatural = useNatural; 6896 PetscFunctionReturn(0); 6897 } 6898 6899 6900 /*@C 6901 DMCreateLabel - Create a label of the given name if it does not already exist 6902 6903 Not Collective 6904 6905 Input Parameters: 6906 + dm - The DM object 6907 - name - The label name 6908 6909 Level: intermediate 6910 6911 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6912 @*/ 6913 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 6914 { 6915 PetscBool flg; 6916 DMLabel label; 6917 PetscErrorCode ierr; 6918 6919 PetscFunctionBegin; 6920 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6921 PetscValidCharPointer(name, 2); 6922 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 6923 if (!flg) { 6924 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 6925 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 6926 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 6927 } 6928 PetscFunctionReturn(0); 6929 } 6930 6931 /*@C 6932 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 6933 6934 Not Collective 6935 6936 Input Parameters: 6937 + dm - The DM object 6938 . name - The label name 6939 - point - The mesh point 6940 6941 Output Parameter: 6942 . value - The label value for this point, or -1 if the point is not in the label 6943 6944 Level: beginner 6945 6946 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 6947 @*/ 6948 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 6949 { 6950 DMLabel label; 6951 PetscErrorCode ierr; 6952 6953 PetscFunctionBegin; 6954 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6955 PetscValidCharPointer(name, 2); 6956 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6957 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 6958 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 6959 PetscFunctionReturn(0); 6960 } 6961 6962 /*@C 6963 DMSetLabelValue - Add a point to a Sieve Label with given value 6964 6965 Not Collective 6966 6967 Input Parameters: 6968 + dm - The DM object 6969 . name - The label name 6970 . point - The mesh point 6971 - value - The label value for this point 6972 6973 Output Parameter: 6974 6975 Level: beginner 6976 6977 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 6978 @*/ 6979 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6980 { 6981 DMLabel label; 6982 PetscErrorCode ierr; 6983 6984 PetscFunctionBegin; 6985 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6986 PetscValidCharPointer(name, 2); 6987 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6988 if (!label) { 6989 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 6990 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6991 } 6992 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 6993 PetscFunctionReturn(0); 6994 } 6995 6996 /*@C 6997 DMClearLabelValue - Remove a point from a Sieve Label with given value 6998 6999 Not Collective 7000 7001 Input Parameters: 7002 + dm - The DM object 7003 . name - The label name 7004 . point - The mesh point 7005 - value - The label value for this point 7006 7007 Output Parameter: 7008 7009 Level: beginner 7010 7011 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 7012 @*/ 7013 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7014 { 7015 DMLabel label; 7016 PetscErrorCode ierr; 7017 7018 PetscFunctionBegin; 7019 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7020 PetscValidCharPointer(name, 2); 7021 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7022 if (!label) PetscFunctionReturn(0); 7023 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 7024 PetscFunctionReturn(0); 7025 } 7026 7027 /*@C 7028 DMGetLabelSize - Get the number of different integer ids in a Label 7029 7030 Not Collective 7031 7032 Input Parameters: 7033 + dm - The DM object 7034 - name - The label name 7035 7036 Output Parameter: 7037 . size - The number of different integer ids, or 0 if the label does not exist 7038 7039 Level: beginner 7040 7041 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 7042 @*/ 7043 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 7044 { 7045 DMLabel label; 7046 PetscErrorCode ierr; 7047 7048 PetscFunctionBegin; 7049 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7050 PetscValidCharPointer(name, 2); 7051 PetscValidIntPointer(size, 3); 7052 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7053 *size = 0; 7054 if (!label) PetscFunctionReturn(0); 7055 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 7056 PetscFunctionReturn(0); 7057 } 7058 7059 /*@C 7060 DMGetLabelIdIS - Get the integer ids in a label 7061 7062 Not Collective 7063 7064 Input Parameters: 7065 + mesh - The DM object 7066 - name - The label name 7067 7068 Output Parameter: 7069 . ids - The integer ids, or NULL if the label does not exist 7070 7071 Level: beginner 7072 7073 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 7074 @*/ 7075 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 7076 { 7077 DMLabel label; 7078 PetscErrorCode ierr; 7079 7080 PetscFunctionBegin; 7081 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7082 PetscValidCharPointer(name, 2); 7083 PetscValidPointer(ids, 3); 7084 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7085 *ids = NULL; 7086 if (label) { 7087 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 7088 } else { 7089 /* returning an empty IS */ 7090 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 7091 } 7092 PetscFunctionReturn(0); 7093 } 7094 7095 /*@C 7096 DMGetStratumSize - Get the number of points in a label stratum 7097 7098 Not Collective 7099 7100 Input Parameters: 7101 + dm - The DM object 7102 . name - The label name 7103 - value - The stratum value 7104 7105 Output Parameter: 7106 . size - The stratum size 7107 7108 Level: beginner 7109 7110 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 7111 @*/ 7112 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 7113 { 7114 DMLabel label; 7115 PetscErrorCode ierr; 7116 7117 PetscFunctionBegin; 7118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7119 PetscValidCharPointer(name, 2); 7120 PetscValidIntPointer(size, 4); 7121 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7122 *size = 0; 7123 if (!label) PetscFunctionReturn(0); 7124 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 7125 PetscFunctionReturn(0); 7126 } 7127 7128 /*@C 7129 DMGetStratumIS - Get the points in a label stratum 7130 7131 Not Collective 7132 7133 Input Parameters: 7134 + dm - The DM object 7135 . name - The label name 7136 - value - The stratum value 7137 7138 Output Parameter: 7139 . points - The stratum points, or NULL if the label does not exist or does not have that value 7140 7141 Level: beginner 7142 7143 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 7144 @*/ 7145 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 7146 { 7147 DMLabel label; 7148 PetscErrorCode ierr; 7149 7150 PetscFunctionBegin; 7151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7152 PetscValidCharPointer(name, 2); 7153 PetscValidPointer(points, 4); 7154 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7155 *points = NULL; 7156 if (!label) PetscFunctionReturn(0); 7157 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 7158 PetscFunctionReturn(0); 7159 } 7160 7161 /*@C 7162 DMSetStratumIS - Set the points in a label stratum 7163 7164 Not Collective 7165 7166 Input Parameters: 7167 + dm - The DM object 7168 . name - The label name 7169 . value - The stratum value 7170 - points - The stratum points 7171 7172 Level: beginner 7173 7174 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 7175 @*/ 7176 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 7177 { 7178 DMLabel label; 7179 PetscErrorCode ierr; 7180 7181 PetscFunctionBegin; 7182 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7183 PetscValidCharPointer(name, 2); 7184 PetscValidPointer(points, 4); 7185 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7186 if (!label) PetscFunctionReturn(0); 7187 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 7188 PetscFunctionReturn(0); 7189 } 7190 7191 /*@C 7192 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 7193 7194 Not Collective 7195 7196 Input Parameters: 7197 + dm - The DM object 7198 . name - The label name 7199 - value - The label value for this point 7200 7201 Output Parameter: 7202 7203 Level: beginner 7204 7205 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7206 @*/ 7207 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7208 { 7209 DMLabel label; 7210 PetscErrorCode ierr; 7211 7212 PetscFunctionBegin; 7213 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7214 PetscValidCharPointer(name, 2); 7215 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7216 if (!label) PetscFunctionReturn(0); 7217 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7218 PetscFunctionReturn(0); 7219 } 7220 7221 /*@ 7222 DMGetNumLabels - Return the number of labels defined by the mesh 7223 7224 Not Collective 7225 7226 Input Parameter: 7227 . dm - The DM object 7228 7229 Output Parameter: 7230 . numLabels - the number of Labels 7231 7232 Level: intermediate 7233 7234 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7235 @*/ 7236 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7237 { 7238 DMLabelLink next = dm->labels; 7239 PetscInt n = 0; 7240 7241 PetscFunctionBegin; 7242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7243 PetscValidIntPointer(numLabels, 2); 7244 while (next) {++n; next = next->next;} 7245 *numLabels = n; 7246 PetscFunctionReturn(0); 7247 } 7248 7249 /*@C 7250 DMGetLabelName - Return the name of nth label 7251 7252 Not Collective 7253 7254 Input Parameters: 7255 + dm - The DM object 7256 - n - the label number 7257 7258 Output Parameter: 7259 . name - the label name 7260 7261 Level: intermediate 7262 7263 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7264 @*/ 7265 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7266 { 7267 DMLabelLink next = dm->labels; 7268 PetscInt l = 0; 7269 PetscErrorCode ierr; 7270 7271 PetscFunctionBegin; 7272 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7273 PetscValidPointer(name, 3); 7274 while (next) { 7275 if (l == n) { 7276 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7277 PetscFunctionReturn(0); 7278 } 7279 ++l; 7280 next = next->next; 7281 } 7282 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7283 } 7284 7285 /*@C 7286 DMHasLabel - Determine whether the mesh has a label of a given name 7287 7288 Not Collective 7289 7290 Input Parameters: 7291 + dm - The DM object 7292 - name - The label name 7293 7294 Output Parameter: 7295 . hasLabel - PETSC_TRUE if the label is present 7296 7297 Level: intermediate 7298 7299 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7300 @*/ 7301 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 7302 { 7303 DMLabelLink next = dm->labels; 7304 const char *lname; 7305 PetscErrorCode ierr; 7306 7307 PetscFunctionBegin; 7308 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7309 PetscValidCharPointer(name, 2); 7310 PetscValidBoolPointer(hasLabel, 3); 7311 *hasLabel = PETSC_FALSE; 7312 while (next) { 7313 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7314 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 7315 if (*hasLabel) break; 7316 next = next->next; 7317 } 7318 PetscFunctionReturn(0); 7319 } 7320 7321 /*@C 7322 DMGetLabel - Return the label of a given name, or NULL 7323 7324 Not Collective 7325 7326 Input Parameters: 7327 + dm - The DM object 7328 - name - The label name 7329 7330 Output Parameter: 7331 . label - The DMLabel, or NULL if the label is absent 7332 7333 Level: intermediate 7334 7335 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7336 @*/ 7337 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 7338 { 7339 DMLabelLink next = dm->labels; 7340 PetscBool hasLabel; 7341 const char *lname; 7342 PetscErrorCode ierr; 7343 7344 PetscFunctionBegin; 7345 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7346 PetscValidCharPointer(name, 2); 7347 PetscValidPointer(label, 3); 7348 *label = NULL; 7349 while (next) { 7350 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7351 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7352 if (hasLabel) { 7353 *label = next->label; 7354 break; 7355 } 7356 next = next->next; 7357 } 7358 PetscFunctionReturn(0); 7359 } 7360 7361 /*@C 7362 DMGetLabelByNum - Return the nth label 7363 7364 Not Collective 7365 7366 Input Parameters: 7367 + dm - The DM object 7368 - n - the label number 7369 7370 Output Parameter: 7371 . label - the label 7372 7373 Level: intermediate 7374 7375 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7376 @*/ 7377 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 7378 { 7379 DMLabelLink next = dm->labels; 7380 PetscInt l = 0; 7381 7382 PetscFunctionBegin; 7383 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7384 PetscValidPointer(label, 3); 7385 while (next) { 7386 if (l == n) { 7387 *label = next->label; 7388 PetscFunctionReturn(0); 7389 } 7390 ++l; 7391 next = next->next; 7392 } 7393 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7394 } 7395 7396 /*@C 7397 DMAddLabel - Add the label to this mesh 7398 7399 Not Collective 7400 7401 Input Parameters: 7402 + dm - The DM object 7403 - label - The DMLabel 7404 7405 Level: developer 7406 7407 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7408 @*/ 7409 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 7410 { 7411 DMLabelLink l, *p, tmpLabel; 7412 PetscBool hasLabel; 7413 const char *lname; 7414 PetscBool flg; 7415 PetscErrorCode ierr; 7416 7417 PetscFunctionBegin; 7418 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7419 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 7420 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 7421 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 7422 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 7423 tmpLabel->label = label; 7424 tmpLabel->output = PETSC_TRUE; 7425 for (p=&dm->labels; (l=*p); p=&l->next) {} 7426 *p = tmpLabel; 7427 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 7428 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 7429 if (flg) dm->depthLabel = label; 7430 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 7431 if (flg) dm->celltypeLabel = label; 7432 PetscFunctionReturn(0); 7433 } 7434 7435 /*@C 7436 DMRemoveLabel - Remove the label given by name from this mesh 7437 7438 Not Collective 7439 7440 Input Parameters: 7441 + dm - The DM object 7442 - name - The label name 7443 7444 Output Parameter: 7445 . label - The DMLabel, or NULL if the label is absent 7446 7447 Level: developer 7448 7449 Notes: 7450 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 7451 DMLabelDestroy() on the label. 7452 7453 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 7454 call DMLabelDestroy(). Instead, the label is returned and the user is 7455 responsible of calling DMLabelDestroy() at some point. 7456 7457 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 7458 @*/ 7459 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7460 { 7461 DMLabelLink link, *pnext; 7462 PetscBool hasLabel; 7463 const char *lname; 7464 PetscErrorCode ierr; 7465 7466 PetscFunctionBegin; 7467 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7468 PetscValidCharPointer(name, 2); 7469 if (label) { 7470 PetscValidPointer(label, 3); 7471 *label = NULL; 7472 } 7473 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7474 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 7475 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7476 if (hasLabel) { 7477 *pnext = link->next; /* Remove from list */ 7478 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 7479 if (hasLabel) dm->depthLabel = NULL; 7480 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 7481 if (hasLabel) dm->celltypeLabel = NULL; 7482 if (label) *label = link->label; 7483 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 7484 ierr = PetscFree(link);CHKERRQ(ierr); 7485 break; 7486 } 7487 } 7488 PetscFunctionReturn(0); 7489 } 7490 7491 /*@ 7492 DMRemoveLabelBySelf - Remove the label from this mesh 7493 7494 Not Collective 7495 7496 Input Parameters: 7497 + dm - The DM object 7498 . label - (Optional) The DMLabel to be removed from the DM 7499 - failNotFound - Should it fail if the label is not found in the DM? 7500 7501 Level: developer 7502 7503 Notes: 7504 Only exactly the same instance is removed if found, name match is ignored. 7505 If the DM has an exclusive reference to the label, it gets destroyed and 7506 *label nullified. 7507 7508 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 7509 @*/ 7510 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 7511 { 7512 DMLabelLink link, *pnext; 7513 PetscBool hasLabel = PETSC_FALSE; 7514 PetscErrorCode ierr; 7515 7516 PetscFunctionBegin; 7517 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7518 PetscValidPointer(label, 2); 7519 if (!*label && !failNotFound) PetscFunctionReturn(0); 7520 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 7521 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 7522 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7523 if (*label == link->label) { 7524 hasLabel = PETSC_TRUE; 7525 *pnext = link->next; /* Remove from list */ 7526 if (*label == dm->depthLabel) dm->depthLabel = NULL; 7527 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 7528 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 7529 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 7530 ierr = PetscFree(link);CHKERRQ(ierr); 7531 break; 7532 } 7533 } 7534 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 7535 PetscFunctionReturn(0); 7536 } 7537 7538 /*@C 7539 DMGetLabelOutput - Get the output flag for a given label 7540 7541 Not Collective 7542 7543 Input Parameters: 7544 + dm - The DM object 7545 - name - The label name 7546 7547 Output Parameter: 7548 . output - The flag for output 7549 7550 Level: developer 7551 7552 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7553 @*/ 7554 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 7555 { 7556 DMLabelLink next = dm->labels; 7557 const char *lname; 7558 PetscErrorCode ierr; 7559 7560 PetscFunctionBegin; 7561 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7562 PetscValidPointer(name, 2); 7563 PetscValidPointer(output, 3); 7564 while (next) { 7565 PetscBool flg; 7566 7567 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7568 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7569 if (flg) {*output = next->output; PetscFunctionReturn(0);} 7570 next = next->next; 7571 } 7572 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7573 } 7574 7575 /*@C 7576 DMSetLabelOutput - Set the output flag for a given label 7577 7578 Not Collective 7579 7580 Input Parameters: 7581 + dm - The DM object 7582 . name - The label name 7583 - output - The flag for output 7584 7585 Level: developer 7586 7587 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7588 @*/ 7589 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 7590 { 7591 DMLabelLink next = dm->labels; 7592 const char *lname; 7593 PetscErrorCode ierr; 7594 7595 PetscFunctionBegin; 7596 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7597 PetscValidCharPointer(name, 2); 7598 while (next) { 7599 PetscBool flg; 7600 7601 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7602 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7603 if (flg) {next->output = output; PetscFunctionReturn(0);} 7604 next = next->next; 7605 } 7606 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7607 } 7608 7609 /*@ 7610 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 7611 7612 Collective on dmA 7613 7614 Input Parameter: 7615 + dmA - The DM object with initial labels 7616 . dmB - The DM object with copied labels 7617 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 7618 - all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 7619 7620 Level: intermediate 7621 7622 Note: This is typically used when interpolating or otherwise adding to a mesh 7623 7624 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels() 7625 @*/ 7626 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all) 7627 { 7628 DMLabel label, labelNew; 7629 const char *name; 7630 PetscBool flg; 7631 DMLabelLink link; 7632 PetscErrorCode ierr; 7633 7634 PetscFunctionBegin; 7635 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 7636 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 7637 PetscValidLogicalCollectiveEnum(dmA, mode,3); 7638 PetscValidLogicalCollectiveBool(dmA, all, 4); 7639 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 7640 if (dmA == dmB) PetscFunctionReturn(0); 7641 for (link=dmA->labels; link; link=link->next) { 7642 label=link->label; 7643 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 7644 if (!all) { 7645 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 7646 if (flg) continue; 7647 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 7648 if (flg) continue; 7649 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 7650 if (flg) continue; 7651 } 7652 if (mode==PETSC_COPY_VALUES) { 7653 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 7654 } else { 7655 labelNew = label; 7656 } 7657 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 7658 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 7659 } 7660 PetscFunctionReturn(0); 7661 } 7662 7663 /*@ 7664 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 7665 7666 Input Parameter: 7667 . dm - The DM object 7668 7669 Output Parameter: 7670 . cdm - The coarse DM 7671 7672 Level: intermediate 7673 7674 .seealso: DMSetCoarseDM() 7675 @*/ 7676 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 7677 { 7678 PetscFunctionBegin; 7679 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7680 PetscValidPointer(cdm, 2); 7681 *cdm = dm->coarseMesh; 7682 PetscFunctionReturn(0); 7683 } 7684 7685 /*@ 7686 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 7687 7688 Input Parameters: 7689 + dm - The DM object 7690 - cdm - The coarse DM 7691 7692 Level: intermediate 7693 7694 .seealso: DMGetCoarseDM() 7695 @*/ 7696 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 7697 { 7698 PetscErrorCode ierr; 7699 7700 PetscFunctionBegin; 7701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7702 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 7703 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 7704 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 7705 dm->coarseMesh = cdm; 7706 PetscFunctionReturn(0); 7707 } 7708 7709 /*@ 7710 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 7711 7712 Input Parameter: 7713 . dm - The DM object 7714 7715 Output Parameter: 7716 . fdm - The fine DM 7717 7718 Level: intermediate 7719 7720 .seealso: DMSetFineDM() 7721 @*/ 7722 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 7723 { 7724 PetscFunctionBegin; 7725 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7726 PetscValidPointer(fdm, 2); 7727 *fdm = dm->fineMesh; 7728 PetscFunctionReturn(0); 7729 } 7730 7731 /*@ 7732 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 7733 7734 Input Parameters: 7735 + dm - The DM object 7736 - fdm - The fine DM 7737 7738 Level: intermediate 7739 7740 .seealso: DMGetFineDM() 7741 @*/ 7742 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 7743 { 7744 PetscErrorCode ierr; 7745 7746 PetscFunctionBegin; 7747 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7748 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 7749 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 7750 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 7751 dm->fineMesh = fdm; 7752 PetscFunctionReturn(0); 7753 } 7754 7755 /*=== DMBoundary code ===*/ 7756 7757 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 7758 { 7759 PetscInt d; 7760 PetscErrorCode ierr; 7761 7762 PetscFunctionBegin; 7763 for (d = 0; d < dm->Nds; ++d) { 7764 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr); 7765 } 7766 PetscFunctionReturn(0); 7767 } 7768 7769 /*@C 7770 DMAddBoundary - Add a boundary condition to the model 7771 7772 Collective on dm 7773 7774 Input Parameters: 7775 + dm - The DM, with a PetscDS that matches the problem being constrained 7776 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7777 . name - The BC name 7778 . labelname - The label defining constrained points 7779 . field - The field to constrain 7780 . numcomps - The number of constrained field components (0 will constrain all fields) 7781 . comps - An array of constrained component numbers 7782 . bcFunc - A pointwise function giving boundary values 7783 . numids - The number of DMLabel ids for constrained points 7784 . ids - An array of ids for constrained points 7785 - ctx - An optional user context for bcFunc 7786 7787 Options Database Keys: 7788 + -bc_<boundary name> <num> - Overrides the boundary ids 7789 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7790 7791 Level: developer 7792 7793 .seealso: DMGetBoundary() 7794 @*/ 7795 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) 7796 { 7797 PetscDS ds; 7798 PetscErrorCode ierr; 7799 7800 PetscFunctionBegin; 7801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7802 PetscValidLogicalCollectiveEnum(dm, type, 2); 7803 PetscValidLogicalCollectiveInt(dm, field, 5); 7804 PetscValidLogicalCollectiveInt(dm, numcomps, 6); 7805 PetscValidLogicalCollectiveInt(dm, numids, 9); 7806 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7807 ierr = DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, labelname);CHKERRQ(ierr); 7808 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, numids, ids, ctx);CHKERRQ(ierr); 7809 PetscFunctionReturn(0); 7810 } 7811 7812 /*@ 7813 DMGetNumBoundary - Get the number of registered BC 7814 7815 Input Parameters: 7816 . dm - The mesh object 7817 7818 Output Parameters: 7819 . numBd - The number of BC 7820 7821 Level: intermediate 7822 7823 .seealso: DMAddBoundary(), DMGetBoundary() 7824 @*/ 7825 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 7826 { 7827 PetscDS ds; 7828 PetscErrorCode ierr; 7829 7830 PetscFunctionBegin; 7831 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7832 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7833 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr); 7834 PetscFunctionReturn(0); 7835 } 7836 7837 /*@C 7838 DMGetBoundary - Get a model boundary condition 7839 7840 Input Parameters: 7841 + dm - The mesh object 7842 - bd - The BC number 7843 7844 Output Parameters: 7845 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7846 . name - The BC name 7847 . labelname - The label defining constrained points 7848 . field - The field to constrain 7849 . numcomps - The number of constrained field components 7850 . comps - An array of constrained component numbers 7851 . bcFunc - A pointwise function giving boundary values 7852 . numids - The number of DMLabel ids for constrained points 7853 . ids - An array of ids for constrained points 7854 - ctx - An optional user context for bcFunc 7855 7856 Options Database Keys: 7857 + -bc_<boundary name> <num> - Overrides the boundary ids 7858 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7859 7860 Level: developer 7861 7862 .seealso: DMAddBoundary() 7863 @*/ 7864 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) 7865 { 7866 PetscDS ds; 7867 PetscErrorCode ierr; 7868 7869 PetscFunctionBegin; 7870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7871 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7872 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, numids, ids, ctx);CHKERRQ(ierr); 7873 PetscFunctionReturn(0); 7874 } 7875 7876 static PetscErrorCode DMPopulateBoundary(DM dm) 7877 { 7878 PetscDS ds; 7879 DMBoundary *lastnext; 7880 DSBoundary dsbound; 7881 PetscErrorCode ierr; 7882 7883 PetscFunctionBegin; 7884 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7885 dsbound = ds->boundary; 7886 if (dm->boundary) { 7887 DMBoundary next = dm->boundary; 7888 7889 /* quick check to see if the PetscDS has changed */ 7890 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 7891 /* the PetscDS has changed: tear down and rebuild */ 7892 while (next) { 7893 DMBoundary b = next; 7894 7895 next = b->next; 7896 ierr = PetscFree(b);CHKERRQ(ierr); 7897 } 7898 dm->boundary = NULL; 7899 } 7900 7901 lastnext = &(dm->boundary); 7902 while (dsbound) { 7903 DMBoundary dmbound; 7904 7905 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 7906 dmbound->dsboundary = dsbound; 7907 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 7908 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 7909 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 7910 *lastnext = dmbound; 7911 lastnext = &(dmbound->next); 7912 dsbound = dsbound->next; 7913 } 7914 PetscFunctionReturn(0); 7915 } 7916 7917 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 7918 { 7919 DMBoundary b; 7920 PetscErrorCode ierr; 7921 7922 PetscFunctionBegin; 7923 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7924 PetscValidBoolPointer(isBd, 3); 7925 *isBd = PETSC_FALSE; 7926 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 7927 b = dm->boundary; 7928 while (b && !(*isBd)) { 7929 DMLabel label = b->label; 7930 DSBoundary dsb = b->dsboundary; 7931 7932 if (label) { 7933 PetscInt i; 7934 7935 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 7936 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 7937 } 7938 } 7939 b = b->next; 7940 } 7941 PetscFunctionReturn(0); 7942 } 7943 7944 /*@C 7945 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 7946 7947 Collective on DM 7948 7949 Input Parameters: 7950 + dm - The DM 7951 . time - The time 7952 . funcs - The coordinate functions to evaluate, one per field 7953 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7954 - mode - The insertion mode for values 7955 7956 Output Parameter: 7957 . X - vector 7958 7959 Calling sequence of func: 7960 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7961 7962 + dim - The spatial dimension 7963 . x - The coordinates 7964 . Nf - The number of fields 7965 . u - The output field values 7966 - ctx - optional user-defined function context 7967 7968 Level: developer 7969 7970 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 7971 @*/ 7972 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 7973 { 7974 Vec localX; 7975 PetscErrorCode ierr; 7976 7977 PetscFunctionBegin; 7978 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7979 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7980 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7981 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7982 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7983 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7984 PetscFunctionReturn(0); 7985 } 7986 7987 /*@C 7988 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 7989 7990 Not collective 7991 7992 Input Parameters: 7993 + dm - The DM 7994 . time - The time 7995 . funcs - The coordinate functions to evaluate, one per field 7996 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7997 - mode - The insertion mode for values 7998 7999 Output Parameter: 8000 . localX - vector 8001 8002 Calling sequence of func: 8003 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8004 8005 + dim - The spatial dimension 8006 . x - The coordinates 8007 . Nf - The number of fields 8008 . u - The output field values 8009 - ctx - optional user-defined function context 8010 8011 Level: developer 8012 8013 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 8014 @*/ 8015 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 8016 { 8017 PetscErrorCode ierr; 8018 8019 PetscFunctionBegin; 8020 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8021 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 8022 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 8023 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8024 PetscFunctionReturn(0); 8025 } 8026 8027 /*@C 8028 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. 8029 8030 Collective on DM 8031 8032 Input Parameters: 8033 + dm - The DM 8034 . time - The time 8035 . label - The DMLabel selecting the portion of the mesh for projection 8036 . funcs - The coordinate functions to evaluate, one per field 8037 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8038 - mode - The insertion mode for values 8039 8040 Output Parameter: 8041 . X - vector 8042 8043 Calling sequence of func: 8044 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8045 8046 + dim - The spatial dimension 8047 . x - The coordinates 8048 . Nf - The number of fields 8049 . u - The output field values 8050 - ctx - optional user-defined function context 8051 8052 Level: developer 8053 8054 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 8055 @*/ 8056 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) 8057 { 8058 Vec localX; 8059 PetscErrorCode ierr; 8060 8061 PetscFunctionBegin; 8062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8063 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8064 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8065 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8066 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8067 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8068 PetscFunctionReturn(0); 8069 } 8070 8071 /*@C 8072 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. 8073 8074 Not collective 8075 8076 Input Parameters: 8077 + dm - The DM 8078 . time - The time 8079 . label - The DMLabel selecting the portion of the mesh for projection 8080 . funcs - The coordinate functions to evaluate, one per field 8081 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8082 - mode - The insertion mode for values 8083 8084 Output Parameter: 8085 . localX - vector 8086 8087 Calling sequence of func: 8088 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8089 8090 + dim - The spatial dimension 8091 . x - The coordinates 8092 . Nf - The number of fields 8093 . u - The output field values 8094 - ctx - optional user-defined function context 8095 8096 Level: developer 8097 8098 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8099 @*/ 8100 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) 8101 { 8102 PetscErrorCode ierr; 8103 8104 PetscFunctionBegin; 8105 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8106 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 8107 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 8108 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8109 PetscFunctionReturn(0); 8110 } 8111 8112 /*@C 8113 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 8114 8115 Not collective 8116 8117 Input Parameters: 8118 + dm - The DM 8119 . time - The time 8120 . localU - The input field vector 8121 . funcs - The functions to evaluate, one per field 8122 - mode - The insertion mode for values 8123 8124 Output Parameter: 8125 . localX - The output vector 8126 8127 Calling sequence of func: 8128 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8129 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8130 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8131 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8132 8133 + dim - The spatial dimension 8134 . Nf - The number of input fields 8135 . NfAux - The number of input auxiliary fields 8136 . uOff - The offset of each field in u[] 8137 . uOff_x - The offset of each field in u_x[] 8138 . u - The field values at this point in space 8139 . u_t - The field time derivative at this point in space (or NULL) 8140 . u_x - The field derivatives at this point in space 8141 . aOff - The offset of each auxiliary field in u[] 8142 . aOff_x - The offset of each auxiliary field in u_x[] 8143 . a - The auxiliary field values at this point in space 8144 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8145 . a_x - The auxiliary field derivatives at this point in space 8146 . t - The current time 8147 . x - The coordinates of this point 8148 . numConstants - The number of constants 8149 . constants - The value of each constant 8150 - f - The value of the function at this point in space 8151 8152 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. 8153 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 8154 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8155 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8156 8157 Level: intermediate 8158 8159 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8160 @*/ 8161 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 8162 void (**funcs)(PetscInt, PetscInt, PetscInt, 8163 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8164 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8165 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8166 InsertMode mode, Vec localX) 8167 { 8168 PetscErrorCode ierr; 8169 8170 PetscFunctionBegin; 8171 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8172 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 8173 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 8174 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 8175 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 8176 PetscFunctionReturn(0); 8177 } 8178 8179 /*@C 8180 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. 8181 8182 Not collective 8183 8184 Input Parameters: 8185 + dm - The DM 8186 . time - The time 8187 . label - The DMLabel marking the portion of the domain to output 8188 . numIds - The number of label ids to use 8189 . ids - The label ids to use for marking 8190 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 8191 . comps - The components to set in the output, or NULL for all components 8192 . localU - The input field vector 8193 . funcs - The functions to evaluate, one per field 8194 - mode - The insertion mode for values 8195 8196 Output Parameter: 8197 . localX - The output vector 8198 8199 Calling sequence of func: 8200 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8201 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8202 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8203 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8204 8205 + dim - The spatial dimension 8206 . Nf - The number of input fields 8207 . NfAux - The number of input auxiliary fields 8208 . uOff - The offset of each field in u[] 8209 . uOff_x - The offset of each field in u_x[] 8210 . u - The field values at this point in space 8211 . u_t - The field time derivative at this point in space (or NULL) 8212 . u_x - The field derivatives at this point in space 8213 . aOff - The offset of each auxiliary field in u[] 8214 . aOff_x - The offset of each auxiliary field in u_x[] 8215 . a - The auxiliary field values at this point in space 8216 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8217 . a_x - The auxiliary field derivatives at this point in space 8218 . t - The current time 8219 . x - The coordinates of this point 8220 . numConstants - The number of constants 8221 . constants - The value of each constant 8222 - f - The value of the function at this point in space 8223 8224 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. 8225 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 8226 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8227 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8228 8229 Level: intermediate 8230 8231 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8232 @*/ 8233 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8234 void (**funcs)(PetscInt, PetscInt, PetscInt, 8235 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8236 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8237 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8238 InsertMode mode, Vec localX) 8239 { 8240 PetscErrorCode ierr; 8241 8242 PetscFunctionBegin; 8243 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8244 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 8245 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 8246 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name); 8247 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8248 PetscFunctionReturn(0); 8249 } 8250 8251 /*@C 8252 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. 8253 8254 Not collective 8255 8256 Input Parameters: 8257 + dm - The DM 8258 . time - The time 8259 . label - The DMLabel marking the portion of the domain boundary to output 8260 . numIds - The number of label ids to use 8261 . ids - The label ids to use for marking 8262 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 8263 . comps - The components to set in the output, or NULL for all components 8264 . localU - The input field vector 8265 . funcs - The functions to evaluate, one per field 8266 - mode - The insertion mode for values 8267 8268 Output Parameter: 8269 . localX - The output vector 8270 8271 Calling sequence of func: 8272 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8273 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8274 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8275 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8276 8277 + dim - The spatial dimension 8278 . Nf - The number of input fields 8279 . NfAux - The number of input auxiliary fields 8280 . uOff - The offset of each field in u[] 8281 . uOff_x - The offset of each field in u_x[] 8282 . u - The field values at this point in space 8283 . u_t - The field time derivative at this point in space (or NULL) 8284 . u_x - The field derivatives at this point in space 8285 . aOff - The offset of each auxiliary field in u[] 8286 . aOff_x - The offset of each auxiliary field in u_x[] 8287 . a - The auxiliary field values at this point in space 8288 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8289 . a_x - The auxiliary field derivatives at this point in space 8290 . t - The current time 8291 . x - The coordinates of this point 8292 . n - The face normal 8293 . numConstants - The number of constants 8294 . constants - The value of each constant 8295 - f - The value of the function at this point in space 8296 8297 Note: 8298 There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 8299 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 8300 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8301 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8302 8303 Level: intermediate 8304 8305 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8306 @*/ 8307 PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8308 void (**funcs)(PetscInt, PetscInt, PetscInt, 8309 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8310 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8311 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8312 InsertMode mode, Vec localX) 8313 { 8314 PetscErrorCode ierr; 8315 8316 PetscFunctionBegin; 8317 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8318 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 8319 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 8320 if (!dm->ops->projectbdfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name); 8321 ierr = (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8322 PetscFunctionReturn(0); 8323 } 8324 8325 /*@C 8326 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 8327 8328 Input Parameters: 8329 + dm - The DM 8330 . time - The time 8331 . funcs - The functions to evaluate for each field component 8332 . ctxs - Optional array of contexts to pass to each function, or NULL. 8333 - X - The coefficient vector u_h, a global vector 8334 8335 Output Parameter: 8336 . diff - The diff ||u - u_h||_2 8337 8338 Level: developer 8339 8340 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8341 @*/ 8342 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 8343 { 8344 PetscErrorCode ierr; 8345 8346 PetscFunctionBegin; 8347 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8348 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8349 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 8350 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8351 PetscFunctionReturn(0); 8352 } 8353 8354 /*@C 8355 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 8356 8357 Collective on dm 8358 8359 Input Parameters: 8360 + dm - The DM 8361 , time - The time 8362 . funcs - The gradient functions to evaluate for each field component 8363 . ctxs - Optional array of contexts to pass to each function, or NULL. 8364 . X - The coefficient vector u_h, a global vector 8365 - n - The vector to project along 8366 8367 Output Parameter: 8368 . diff - The diff ||(grad u - grad u_h) . n||_2 8369 8370 Level: developer 8371 8372 .seealso: DMProjectFunction(), DMComputeL2Diff() 8373 @*/ 8374 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) 8375 { 8376 PetscErrorCode ierr; 8377 8378 PetscFunctionBegin; 8379 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8380 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8381 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 8382 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 8383 PetscFunctionReturn(0); 8384 } 8385 8386 /*@C 8387 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 8388 8389 Collective on dm 8390 8391 Input Parameters: 8392 + dm - The DM 8393 . time - The time 8394 . funcs - The functions to evaluate for each field component 8395 . ctxs - Optional array of contexts to pass to each function, or NULL. 8396 - X - The coefficient vector u_h, a global vector 8397 8398 Output Parameter: 8399 . diff - The array of differences, ||u^f - u^f_h||_2 8400 8401 Level: developer 8402 8403 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8404 @*/ 8405 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 8406 { 8407 PetscErrorCode ierr; 8408 8409 PetscFunctionBegin; 8410 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8411 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8412 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 8413 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8414 PetscFunctionReturn(0); 8415 } 8416 8417 /*@C 8418 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 8419 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 8420 8421 Collective on dm 8422 8423 Input parameters: 8424 + dm - the pre-adaptation DM object 8425 - label - label with the flags 8426 8427 Output parameters: 8428 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 8429 8430 Level: intermediate 8431 8432 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 8433 @*/ 8434 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 8435 { 8436 PetscErrorCode ierr; 8437 8438 PetscFunctionBegin; 8439 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8440 PetscValidPointer(label,2); 8441 PetscValidPointer(dmAdapt,3); 8442 *dmAdapt = NULL; 8443 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 8444 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 8445 PetscFunctionReturn(0); 8446 } 8447 8448 /*@C 8449 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 8450 8451 Input Parameters: 8452 + dm - The DM object 8453 . metric - The metric to which the mesh is adapted, defined vertex-wise. 8454 - 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_". 8455 8456 Output Parameter: 8457 . dmAdapt - Pointer to the DM object containing the adapted mesh 8458 8459 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 8460 8461 Level: advanced 8462 8463 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 8464 @*/ 8465 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 8466 { 8467 PetscErrorCode ierr; 8468 8469 PetscFunctionBegin; 8470 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8471 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 8472 if (bdLabel) PetscValidPointer(bdLabel, 3); 8473 PetscValidPointer(dmAdapt, 4); 8474 *dmAdapt = NULL; 8475 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 8476 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 8477 PetscFunctionReturn(0); 8478 } 8479 8480 /*@C 8481 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 8482 8483 Not Collective 8484 8485 Input Parameter: 8486 . dm - The DM 8487 8488 Output Parameters: 8489 + nranks - the number of neighbours 8490 - ranks - the neighbors ranks 8491 8492 Notes: 8493 Do not free the array, it is freed when the DM is destroyed. 8494 8495 Level: beginner 8496 8497 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 8498 @*/ 8499 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 8500 { 8501 PetscErrorCode ierr; 8502 8503 PetscFunctionBegin; 8504 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8505 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 8506 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 8507 PetscFunctionReturn(0); 8508 } 8509 8510 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 8511 8512 /* 8513 Converts the input vector to a ghosted vector and then calls the standard coloring code. 8514 This has be a different function because it requires DM which is not defined in the Mat library 8515 */ 8516 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 8517 { 8518 PetscErrorCode ierr; 8519 8520 PetscFunctionBegin; 8521 if (coloring->ctype == IS_COLORING_LOCAL) { 8522 Vec x1local; 8523 DM dm; 8524 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8525 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 8526 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 8527 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8528 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8529 x1 = x1local; 8530 } 8531 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 8532 if (coloring->ctype == IS_COLORING_LOCAL) { 8533 DM dm; 8534 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8535 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 8536 } 8537 PetscFunctionReturn(0); 8538 } 8539 8540 /*@ 8541 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 8542 8543 Input Parameter: 8544 . coloring - the MatFDColoring object 8545 8546 Developer Notes: 8547 this routine exists because the PETSc Mat library does not know about the DM objects 8548 8549 Level: advanced 8550 8551 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 8552 @*/ 8553 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 8554 { 8555 PetscFunctionBegin; 8556 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 8557 PetscFunctionReturn(0); 8558 } 8559 8560 /*@ 8561 DMGetCompatibility - determine if two DMs are compatible 8562 8563 Collective 8564 8565 Input Parameters: 8566 + dm1 - the first DM 8567 - dm2 - the second DM 8568 8569 Output Parameters: 8570 + compatible - whether or not the two DMs are compatible 8571 - set - whether or not the compatible value was set 8572 8573 Notes: 8574 Two DMs are deemed compatible if they represent the same parallel decomposition 8575 of the same topology. This implies that the section (field data) on one 8576 "makes sense" with respect to the topology and parallel decomposition of the other. 8577 Loosely speaking, compatible DMs represent the same domain and parallel 8578 decomposition, but hold different data. 8579 8580 Typically, one would confirm compatibility if intending to simultaneously iterate 8581 over a pair of vectors obtained from different DMs. 8582 8583 For example, two DMDA objects are compatible if they have the same local 8584 and global sizes and the same stencil width. They can have different numbers 8585 of degrees of freedom per node. Thus, one could use the node numbering from 8586 either DM in bounds for a loop over vectors derived from either DM. 8587 8588 Consider the operation of summing data living on a 2-dof DMDA to data living 8589 on a 1-dof DMDA, which should be compatible, as in the following snippet. 8590 .vb 8591 ... 8592 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 8593 if (set && compatible) { 8594 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8595 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8596 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 8597 for (j=y; j<y+n; ++j) { 8598 for (i=x; i<x+m, ++i) { 8599 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 8600 } 8601 } 8602 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8603 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8604 } else { 8605 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 8606 } 8607 ... 8608 .ve 8609 8610 Checking compatibility might be expensive for a given implementation of DM, 8611 or might be impossible to unambiguously confirm or deny. For this reason, 8612 this function may decline to determine compatibility, and hence users should 8613 always check the "set" output parameter. 8614 8615 A DM is always compatible with itself. 8616 8617 In the current implementation, DMs which live on "unequal" communicators 8618 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 8619 incompatible. 8620 8621 This function is labeled "Collective," as information about all subdomains 8622 is required on each rank. However, in DM implementations which store all this 8623 information locally, this function may be merely "Logically Collective". 8624 8625 Developer Notes: 8626 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 8627 iff B is compatible with A. Thus, this function checks the implementations 8628 of both dm and dmc (if they are of different types), attempting to determine 8629 compatibility. It is left to DM implementers to ensure that symmetry is 8630 preserved. The simplest way to do this is, when implementing type-specific 8631 logic for this function, is to check for existing logic in the implementation 8632 of other DM types and let *set = PETSC_FALSE if found. 8633 8634 Level: advanced 8635 8636 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 8637 @*/ 8638 8639 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 8640 { 8641 PetscErrorCode ierr; 8642 PetscMPIInt compareResult; 8643 DMType type,type2; 8644 PetscBool sameType; 8645 8646 PetscFunctionBegin; 8647 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 8648 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 8649 8650 /* Declare a DM compatible with itself */ 8651 if (dm1 == dm2) { 8652 *set = PETSC_TRUE; 8653 *compatible = PETSC_TRUE; 8654 PetscFunctionReturn(0); 8655 } 8656 8657 /* Declare a DM incompatible with a DM that lives on an "unequal" 8658 communicator. Note that this does not preclude compatibility with 8659 DMs living on "congruent" or "similar" communicators, but this must be 8660 determined by the implementation-specific logic */ 8661 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 8662 if (compareResult == MPI_UNEQUAL) { 8663 *set = PETSC_TRUE; 8664 *compatible = PETSC_FALSE; 8665 PetscFunctionReturn(0); 8666 } 8667 8668 /* Pass to the implementation-specific routine, if one exists. */ 8669 if (dm1->ops->getcompatibility) { 8670 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 8671 if (*set) PetscFunctionReturn(0); 8672 } 8673 8674 /* If dm1 and dm2 are of different types, then attempt to check compatibility 8675 with an implementation of this function from dm2 */ 8676 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 8677 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 8678 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 8679 if (!sameType && dm2->ops->getcompatibility) { 8680 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 8681 } else { 8682 *set = PETSC_FALSE; 8683 } 8684 PetscFunctionReturn(0); 8685 } 8686 8687 /*@C 8688 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 8689 8690 Logically Collective on DM 8691 8692 Input Parameters: 8693 + DM - the DM 8694 . f - the monitor function 8695 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 8696 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 8697 8698 Options Database Keys: 8699 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 8700 does not cancel those set via the options database. 8701 8702 Notes: 8703 Several different monitoring routines may be set by calling 8704 DMMonitorSet() multiple times; all will be called in the 8705 order in which they were set. 8706 8707 Fortran Notes: 8708 Only a single monitor function can be set for each DM object 8709 8710 Level: intermediate 8711 8712 .seealso: DMMonitorCancel() 8713 @*/ 8714 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 8715 { 8716 PetscInt m; 8717 PetscErrorCode ierr; 8718 8719 PetscFunctionBegin; 8720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8721 for (m = 0; m < dm->numbermonitors; ++m) { 8722 PetscBool identical; 8723 8724 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 8725 if (identical) PetscFunctionReturn(0); 8726 } 8727 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 8728 dm->monitor[dm->numbermonitors] = f; 8729 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 8730 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 8731 PetscFunctionReturn(0); 8732 } 8733 8734 /*@ 8735 DMMonitorCancel - Clears all the monitor functions for a DM object. 8736 8737 Logically Collective on DM 8738 8739 Input Parameter: 8740 . dm - the DM 8741 8742 Options Database Key: 8743 . -dm_monitor_cancel - cancels all monitors that have been hardwired 8744 into a code by calls to DMonitorSet(), but does not cancel those 8745 set via the options database 8746 8747 Notes: 8748 There is no way to clear one specific monitor from a DM object. 8749 8750 Level: intermediate 8751 8752 .seealso: DMMonitorSet() 8753 @*/ 8754 PetscErrorCode DMMonitorCancel(DM dm) 8755 { 8756 PetscErrorCode ierr; 8757 PetscInt m; 8758 8759 PetscFunctionBegin; 8760 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8761 for (m = 0; m < dm->numbermonitors; ++m) { 8762 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 8763 } 8764 dm->numbermonitors = 0; 8765 PetscFunctionReturn(0); 8766 } 8767 8768 /*@C 8769 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 8770 8771 Collective on DM 8772 8773 Input Parameters: 8774 + dm - DM object you wish to monitor 8775 . name - the monitor type one is seeking 8776 . help - message indicating what monitoring is done 8777 . manual - manual page for the monitor 8778 . monitor - the monitor function 8779 - 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 8780 8781 Output Parameter: 8782 . flg - Flag set if the monitor was created 8783 8784 Level: developer 8785 8786 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 8787 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 8788 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 8789 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 8790 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 8791 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 8792 PetscOptionsFList(), PetscOptionsEList() 8793 @*/ 8794 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 8795 { 8796 PetscViewer viewer; 8797 PetscViewerFormat format; 8798 PetscErrorCode ierr; 8799 8800 PetscFunctionBegin; 8801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8802 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 8803 if (*flg) { 8804 PetscViewerAndFormat *vf; 8805 8806 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 8807 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 8808 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 8809 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 8810 } 8811 PetscFunctionReturn(0); 8812 } 8813 8814 /*@ 8815 DMMonitor - runs the user provided monitor routines, if they exist 8816 8817 Collective on DM 8818 8819 Input Parameters: 8820 . dm - The DM 8821 8822 Level: developer 8823 8824 .seealso: DMMonitorSet() 8825 @*/ 8826 PetscErrorCode DMMonitor(DM dm) 8827 { 8828 PetscInt m; 8829 PetscErrorCode ierr; 8830 8831 PetscFunctionBegin; 8832 if (!dm) PetscFunctionReturn(0); 8833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8834 for (m = 0; m < dm->numbermonitors; ++m) { 8835 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 8836 } 8837 PetscFunctionReturn(0); 8838 } 8839