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