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