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