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