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