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