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