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 Options Database Keys: 3452 . -dm_petscsection_view - View the Section created by the DM 3453 3454 Level: intermediate 3455 3456 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3457 3458 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3459 @*/ 3460 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3461 { 3462 PetscErrorCode ierr; 3463 3464 PetscFunctionBegin; 3465 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3466 PetscValidPointer(section, 2); 3467 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3468 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3469 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3470 } 3471 *section = dm->defaultSection; 3472 PetscFunctionReturn(0); 3473 } 3474 3475 /*@ 3476 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3477 3478 Input Parameters: 3479 + dm - The DM 3480 - section - The PetscSection 3481 3482 Level: intermediate 3483 3484 Note: Any existing Section will be destroyed 3485 3486 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3487 @*/ 3488 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3489 { 3490 PetscInt numFields = 0; 3491 PetscInt f; 3492 PetscErrorCode ierr; 3493 3494 PetscFunctionBegin; 3495 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3496 if (section) { 3497 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3498 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3499 } 3500 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3501 dm->defaultSection = section; 3502 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3503 if (numFields) { 3504 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3505 for (f = 0; f < numFields; ++f) { 3506 PetscObject disc; 3507 const char *name; 3508 3509 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3510 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3511 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3512 } 3513 } 3514 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3515 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3516 PetscFunctionReturn(0); 3517 } 3518 3519 /*@ 3520 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3521 3522 not collective 3523 3524 Input Parameter: 3525 . dm - The DM 3526 3527 Output Parameter: 3528 + 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. 3529 - 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. 3530 3531 Level: advanced 3532 3533 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3534 3535 .seealso: DMSetDefaultConstraints() 3536 @*/ 3537 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3538 { 3539 PetscErrorCode ierr; 3540 3541 PetscFunctionBegin; 3542 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3543 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3544 if (section) {*section = dm->defaultConstraintSection;} 3545 if (mat) {*mat = dm->defaultConstraintMat;} 3546 PetscFunctionReturn(0); 3547 } 3548 3549 /*@ 3550 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3551 3552 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(). 3553 3554 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. 3555 3556 collective on dm 3557 3558 Input Parameters: 3559 + dm - The DM 3560 + 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). 3561 - 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). 3562 3563 Level: advanced 3564 3565 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3566 3567 .seealso: DMGetDefaultConstraints() 3568 @*/ 3569 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3570 { 3571 PetscMPIInt result; 3572 PetscErrorCode ierr; 3573 3574 PetscFunctionBegin; 3575 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3576 if (section) { 3577 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3578 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3579 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3580 } 3581 if (mat) { 3582 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3583 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3584 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3585 } 3586 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3587 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3588 dm->defaultConstraintSection = section; 3589 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3590 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3591 dm->defaultConstraintMat = mat; 3592 PetscFunctionReturn(0); 3593 } 3594 3595 #ifdef PETSC_USE_DEBUG 3596 /* 3597 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3598 3599 Input Parameters: 3600 + dm - The DM 3601 . localSection - PetscSection describing the local data layout 3602 - globalSection - PetscSection describing the global data layout 3603 3604 Level: intermediate 3605 3606 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3607 */ 3608 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3609 { 3610 MPI_Comm comm; 3611 PetscLayout layout; 3612 const PetscInt *ranges; 3613 PetscInt pStart, pEnd, p, nroots; 3614 PetscMPIInt size, rank; 3615 PetscBool valid = PETSC_TRUE, gvalid; 3616 PetscErrorCode ierr; 3617 3618 PetscFunctionBegin; 3619 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3620 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3621 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3622 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3623 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3624 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3625 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3626 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3627 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3628 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3629 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3630 for (p = pStart; p < pEnd; ++p) { 3631 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3632 3633 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3634 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3635 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3636 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3637 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3638 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3639 if (!gdof) continue; /* Censored point */ 3640 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;} 3641 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;} 3642 if (gdof < 0) { 3643 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3644 for (d = 0; d < gsize; ++d) { 3645 PetscInt offset = -(goff+1) + d, r; 3646 3647 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3648 if (r < 0) r = -(r+2); 3649 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;} 3650 } 3651 } 3652 } 3653 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3654 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3655 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3656 if (!gvalid) { 3657 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3658 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3659 } 3660 PetscFunctionReturn(0); 3661 } 3662 #endif 3663 3664 /*@ 3665 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3666 3667 Collective on DM 3668 3669 Input Parameter: 3670 . dm - The DM 3671 3672 Output Parameter: 3673 . section - The PetscSection 3674 3675 Level: intermediate 3676 3677 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3678 3679 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3680 @*/ 3681 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3682 { 3683 PetscErrorCode ierr; 3684 3685 PetscFunctionBegin; 3686 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3687 PetscValidPointer(section, 2); 3688 if (!dm->defaultGlobalSection) { 3689 PetscSection s; 3690 3691 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3692 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3693 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3694 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3695 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3696 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3697 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3698 } 3699 *section = dm->defaultGlobalSection; 3700 PetscFunctionReturn(0); 3701 } 3702 3703 /*@ 3704 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3705 3706 Input Parameters: 3707 + dm - The DM 3708 - section - The PetscSection, or NULL 3709 3710 Level: intermediate 3711 3712 Note: Any existing Section will be destroyed 3713 3714 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3715 @*/ 3716 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3717 { 3718 PetscErrorCode ierr; 3719 3720 PetscFunctionBegin; 3721 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3722 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3723 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3724 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3725 dm->defaultGlobalSection = section; 3726 #ifdef PETSC_USE_DEBUG 3727 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3728 #endif 3729 PetscFunctionReturn(0); 3730 } 3731 3732 /*@ 3733 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3734 it is created from the default PetscSection layouts in the DM. 3735 3736 Input Parameter: 3737 . dm - The DM 3738 3739 Output Parameter: 3740 . sf - The PetscSF 3741 3742 Level: intermediate 3743 3744 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3745 3746 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3747 @*/ 3748 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3749 { 3750 PetscInt nroots; 3751 PetscErrorCode ierr; 3752 3753 PetscFunctionBegin; 3754 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3755 PetscValidPointer(sf, 2); 3756 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3757 if (nroots < 0) { 3758 PetscSection section, gSection; 3759 3760 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3761 if (section) { 3762 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3763 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3764 } else { 3765 *sf = NULL; 3766 PetscFunctionReturn(0); 3767 } 3768 } 3769 *sf = dm->defaultSF; 3770 PetscFunctionReturn(0); 3771 } 3772 3773 /*@ 3774 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3775 3776 Input Parameters: 3777 + dm - The DM 3778 - sf - The PetscSF 3779 3780 Level: intermediate 3781 3782 Note: Any previous SF is destroyed 3783 3784 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3785 @*/ 3786 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3787 { 3788 PetscErrorCode ierr; 3789 3790 PetscFunctionBegin; 3791 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3792 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3793 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3794 dm->defaultSF = sf; 3795 PetscFunctionReturn(0); 3796 } 3797 3798 /*@C 3799 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3800 describing the data layout. 3801 3802 Input Parameters: 3803 + dm - The DM 3804 . localSection - PetscSection describing the local data layout 3805 - globalSection - PetscSection describing the global data layout 3806 3807 Level: intermediate 3808 3809 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3810 @*/ 3811 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3812 { 3813 MPI_Comm comm; 3814 PetscLayout layout; 3815 const PetscInt *ranges; 3816 PetscInt *local; 3817 PetscSFNode *remote; 3818 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3819 PetscMPIInt size, rank; 3820 PetscErrorCode ierr; 3821 3822 PetscFunctionBegin; 3823 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3824 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3825 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3826 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3827 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3828 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3829 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3830 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3831 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3832 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3833 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3834 for (p = pStart; p < pEnd; ++p) { 3835 PetscInt gdof, gcdof; 3836 3837 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3838 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3839 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)); 3840 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3841 } 3842 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3843 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3844 for (p = pStart, l = 0; p < pEnd; ++p) { 3845 const PetscInt *cind; 3846 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3847 3848 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3849 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3850 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3851 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3852 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3853 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3854 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3855 if (!gdof) continue; /* Censored point */ 3856 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3857 if (gsize != dof-cdof) { 3858 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); 3859 cdof = 0; /* Ignore constraints */ 3860 } 3861 for (d = 0, c = 0; d < dof; ++d) { 3862 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3863 local[l+d-c] = off+d; 3864 } 3865 if (gdof < 0) { 3866 for (d = 0; d < gsize; ++d, ++l) { 3867 PetscInt offset = -(goff+1) + d, r; 3868 3869 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3870 if (r < 0) r = -(r+2); 3871 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); 3872 remote[l].rank = r; 3873 remote[l].index = offset - ranges[r]; 3874 } 3875 } else { 3876 for (d = 0; d < gsize; ++d, ++l) { 3877 remote[l].rank = rank; 3878 remote[l].index = goff+d - ranges[rank]; 3879 } 3880 } 3881 } 3882 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3883 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3884 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3885 PetscFunctionReturn(0); 3886 } 3887 3888 /*@ 3889 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3890 3891 Input Parameter: 3892 . dm - The DM 3893 3894 Output Parameter: 3895 . sf - The PetscSF 3896 3897 Level: intermediate 3898 3899 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3900 3901 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3902 @*/ 3903 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3904 { 3905 PetscFunctionBegin; 3906 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3907 PetscValidPointer(sf, 2); 3908 *sf = dm->sf; 3909 PetscFunctionReturn(0); 3910 } 3911 3912 /*@ 3913 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3914 3915 Input Parameters: 3916 + dm - The DM 3917 - sf - The PetscSF 3918 3919 Level: intermediate 3920 3921 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3922 @*/ 3923 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3924 { 3925 PetscErrorCode ierr; 3926 3927 PetscFunctionBegin; 3928 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3929 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3930 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3931 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3932 dm->sf = sf; 3933 PetscFunctionReturn(0); 3934 } 3935 3936 /*@ 3937 DMGetDS - Get the PetscDS 3938 3939 Input Parameter: 3940 . dm - The DM 3941 3942 Output Parameter: 3943 . prob - The PetscDS 3944 3945 Level: developer 3946 3947 .seealso: DMSetDS() 3948 @*/ 3949 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3950 { 3951 PetscFunctionBegin; 3952 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3953 PetscValidPointer(prob, 2); 3954 *prob = dm->prob; 3955 PetscFunctionReturn(0); 3956 } 3957 3958 /*@ 3959 DMSetDS - Set the PetscDS 3960 3961 Input Parameters: 3962 + dm - The DM 3963 - prob - The PetscDS 3964 3965 Level: developer 3966 3967 .seealso: DMGetDS() 3968 @*/ 3969 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3970 { 3971 PetscInt dimEmbed; 3972 PetscErrorCode ierr; 3973 3974 PetscFunctionBegin; 3975 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3976 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3977 ierr = PetscObjectReference((PetscObject) prob);CHKERRQ(ierr); 3978 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3979 dm->prob = prob; 3980 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 3981 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 3982 PetscFunctionReturn(0); 3983 } 3984 3985 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3986 { 3987 PetscErrorCode ierr; 3988 3989 PetscFunctionBegin; 3990 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3991 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3992 PetscFunctionReturn(0); 3993 } 3994 3995 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3996 { 3997 PetscInt Nf, f; 3998 PetscErrorCode ierr; 3999 4000 PetscFunctionBegin; 4001 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4002 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 4003 for (f = Nf; f < numFields; ++f) { 4004 PetscContainer obj; 4005 4006 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4007 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 4008 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4009 } 4010 PetscFunctionReturn(0); 4011 } 4012 4013 /*@ 4014 DMGetField - Return the discretization object for a given DM field 4015 4016 Not collective 4017 4018 Input Parameters: 4019 + dm - The DM 4020 - f - The field number 4021 4022 Output Parameter: 4023 . field - The discretization object 4024 4025 Level: developer 4026 4027 .seealso: DMSetField() 4028 @*/ 4029 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 4030 { 4031 PetscErrorCode ierr; 4032 4033 PetscFunctionBegin; 4034 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4035 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 4036 PetscFunctionReturn(0); 4037 } 4038 4039 /*@ 4040 DMSetField - Set the discretization object for a given DM field 4041 4042 Logically collective on DM 4043 4044 Input Parameters: 4045 + dm - The DM 4046 . f - The field number 4047 - field - The discretization object 4048 4049 Level: developer 4050 4051 .seealso: DMGetField() 4052 @*/ 4053 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 4054 { 4055 PetscErrorCode ierr; 4056 4057 PetscFunctionBegin; 4058 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4059 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 4060 PetscFunctionReturn(0); 4061 } 4062 4063 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 4064 { 4065 DM dm_coord,dmc_coord; 4066 PetscErrorCode ierr; 4067 Vec coords,ccoords; 4068 Mat inject; 4069 PetscFunctionBegin; 4070 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4071 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 4072 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4073 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 4074 if (coords && !ccoords) { 4075 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 4076 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4077 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 4078 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 4079 ierr = MatDestroy(&inject);CHKERRQ(ierr); 4080 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 4081 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4082 } 4083 PetscFunctionReturn(0); 4084 } 4085 4086 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 4087 { 4088 DM dm_coord,subdm_coord; 4089 PetscErrorCode ierr; 4090 Vec coords,ccoords,clcoords; 4091 VecScatter *scat_i,*scat_g; 4092 PetscFunctionBegin; 4093 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4094 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 4095 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4096 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 4097 if (coords && !ccoords) { 4098 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 4099 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4100 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 4101 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 4102 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 4103 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4104 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4105 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4106 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4107 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 4108 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 4109 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 4110 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 4111 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4112 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 4113 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4114 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4115 } 4116 PetscFunctionReturn(0); 4117 } 4118 4119 /*@ 4120 DMGetDimension - Return the topological dimension of the DM 4121 4122 Not collective 4123 4124 Input Parameter: 4125 . dm - The DM 4126 4127 Output Parameter: 4128 . dim - The topological dimension 4129 4130 Level: beginner 4131 4132 .seealso: DMSetDimension(), DMCreate() 4133 @*/ 4134 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4135 { 4136 PetscFunctionBegin; 4137 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4138 PetscValidPointer(dim, 2); 4139 *dim = dm->dim; 4140 PetscFunctionReturn(0); 4141 } 4142 4143 /*@ 4144 DMSetDimension - Set the topological dimension of the DM 4145 4146 Collective on dm 4147 4148 Input Parameters: 4149 + dm - The DM 4150 - dim - The topological dimension 4151 4152 Level: beginner 4153 4154 .seealso: DMGetDimension(), DMCreate() 4155 @*/ 4156 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4157 { 4158 PetscErrorCode ierr; 4159 4160 PetscFunctionBegin; 4161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4162 PetscValidLogicalCollectiveInt(dm, dim, 2); 4163 dm->dim = dim; 4164 if (dm->prob->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dim);CHKERRQ(ierr);} 4165 PetscFunctionReturn(0); 4166 } 4167 4168 /*@ 4169 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4170 4171 Collective on DM 4172 4173 Input Parameters: 4174 + dm - the DM 4175 - dim - the dimension 4176 4177 Output Parameters: 4178 + pStart - The first point of the given dimension 4179 . pEnd - The first point following points of the given dimension 4180 4181 Note: 4182 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4183 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4184 then the interval is empty. 4185 4186 Level: intermediate 4187 4188 .keywords: point, Hasse Diagram, dimension 4189 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4190 @*/ 4191 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4192 { 4193 PetscInt d; 4194 PetscErrorCode ierr; 4195 4196 PetscFunctionBegin; 4197 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4198 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4199 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4200 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4201 PetscFunctionReturn(0); 4202 } 4203 4204 /*@ 4205 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4206 4207 Collective on DM 4208 4209 Input Parameters: 4210 + dm - the DM 4211 - c - coordinate vector 4212 4213 Note: 4214 The coordinates do include those for ghost points, which are in the local vector 4215 4216 Level: intermediate 4217 4218 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4219 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 4220 @*/ 4221 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4222 { 4223 PetscErrorCode ierr; 4224 4225 PetscFunctionBegin; 4226 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4227 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4228 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4229 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4230 dm->coordinates = c; 4231 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4232 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4233 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4234 PetscFunctionReturn(0); 4235 } 4236 4237 /*@ 4238 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4239 4240 Collective on DM 4241 4242 Input Parameters: 4243 + dm - the DM 4244 - c - coordinate vector 4245 4246 Note: 4247 The coordinates of ghost points can be set using DMSetCoordinates() 4248 followed by DMGetCoordinatesLocal(). This is intended to enable the 4249 setting of ghost coordinates outside of the domain. 4250 4251 Level: intermediate 4252 4253 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4254 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4255 @*/ 4256 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4257 { 4258 PetscErrorCode ierr; 4259 4260 PetscFunctionBegin; 4261 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4262 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4263 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4264 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4265 4266 dm->coordinatesLocal = c; 4267 4268 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4269 PetscFunctionReturn(0); 4270 } 4271 4272 /*@ 4273 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4274 4275 Not Collective 4276 4277 Input Parameter: 4278 . dm - the DM 4279 4280 Output Parameter: 4281 . c - global coordinate vector 4282 4283 Note: 4284 This is a borrowed reference, so the user should NOT destroy this vector 4285 4286 Each process has only the local coordinates (does NOT have the ghost coordinates). 4287 4288 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4289 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4290 4291 Level: intermediate 4292 4293 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4294 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4295 @*/ 4296 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4297 { 4298 PetscErrorCode ierr; 4299 4300 PetscFunctionBegin; 4301 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4302 PetscValidPointer(c,2); 4303 if (!dm->coordinates && dm->coordinatesLocal) { 4304 DM cdm = NULL; 4305 4306 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4307 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4308 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4309 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4310 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4311 } 4312 *c = dm->coordinates; 4313 PetscFunctionReturn(0); 4314 } 4315 4316 /*@ 4317 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4318 4319 Collective on DM 4320 4321 Input Parameter: 4322 . dm - the DM 4323 4324 Output Parameter: 4325 . c - coordinate vector 4326 4327 Note: 4328 This is a borrowed reference, so the user should NOT destroy this vector 4329 4330 Each process has the local and ghost coordinates 4331 4332 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4333 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4334 4335 Level: intermediate 4336 4337 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4338 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4339 @*/ 4340 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4341 { 4342 PetscErrorCode ierr; 4343 4344 PetscFunctionBegin; 4345 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4346 PetscValidPointer(c,2); 4347 if (!dm->coordinatesLocal && dm->coordinates) { 4348 DM cdm = NULL; 4349 4350 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4351 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4352 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4353 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4354 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4355 } 4356 *c = dm->coordinatesLocal; 4357 PetscFunctionReturn(0); 4358 } 4359 4360 /*@ 4361 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4362 4363 Collective on DM 4364 4365 Input Parameter: 4366 . dm - the DM 4367 4368 Output Parameter: 4369 . cdm - coordinate DM 4370 4371 Level: intermediate 4372 4373 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4374 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4375 @*/ 4376 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4377 { 4378 PetscErrorCode ierr; 4379 4380 PetscFunctionBegin; 4381 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4382 PetscValidPointer(cdm,2); 4383 if (!dm->coordinateDM) { 4384 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4385 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4386 } 4387 *cdm = dm->coordinateDM; 4388 PetscFunctionReturn(0); 4389 } 4390 4391 /*@ 4392 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4393 4394 Logically Collective on DM 4395 4396 Input Parameters: 4397 + dm - the DM 4398 - cdm - coordinate DM 4399 4400 Level: intermediate 4401 4402 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4403 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4404 @*/ 4405 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4406 { 4407 PetscErrorCode ierr; 4408 4409 PetscFunctionBegin; 4410 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4411 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4412 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 4413 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4414 dm->coordinateDM = cdm; 4415 PetscFunctionReturn(0); 4416 } 4417 4418 /*@ 4419 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4420 4421 Not Collective 4422 4423 Input Parameter: 4424 . dm - The DM object 4425 4426 Output Parameter: 4427 . dim - The embedding dimension 4428 4429 Level: intermediate 4430 4431 .keywords: mesh, coordinates 4432 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4433 @*/ 4434 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4435 { 4436 PetscFunctionBegin; 4437 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4438 PetscValidPointer(dim, 2); 4439 if (dm->dimEmbed == PETSC_DEFAULT) { 4440 dm->dimEmbed = dm->dim; 4441 } 4442 *dim = dm->dimEmbed; 4443 PetscFunctionReturn(0); 4444 } 4445 4446 /*@ 4447 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4448 4449 Not Collective 4450 4451 Input Parameters: 4452 + dm - The DM object 4453 - dim - The embedding dimension 4454 4455 Level: intermediate 4456 4457 .keywords: mesh, coordinates 4458 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4459 @*/ 4460 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4461 { 4462 PetscErrorCode ierr; 4463 4464 PetscFunctionBegin; 4465 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4466 dm->dimEmbed = dim; 4467 ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);CHKERRQ(ierr); 4468 PetscFunctionReturn(0); 4469 } 4470 4471 /*@ 4472 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4473 4474 Not Collective 4475 4476 Input Parameter: 4477 . dm - The DM object 4478 4479 Output Parameter: 4480 . section - The PetscSection object 4481 4482 Level: intermediate 4483 4484 .keywords: mesh, coordinates 4485 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4486 @*/ 4487 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4488 { 4489 DM cdm; 4490 PetscErrorCode ierr; 4491 4492 PetscFunctionBegin; 4493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4494 PetscValidPointer(section, 2); 4495 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4496 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4497 PetscFunctionReturn(0); 4498 } 4499 4500 /*@ 4501 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4502 4503 Not Collective 4504 4505 Input Parameters: 4506 + dm - The DM object 4507 . dim - The embedding dimension, or PETSC_DETERMINE 4508 - section - The PetscSection object 4509 4510 Level: intermediate 4511 4512 .keywords: mesh, coordinates 4513 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4514 @*/ 4515 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4516 { 4517 DM cdm; 4518 PetscErrorCode ierr; 4519 4520 PetscFunctionBegin; 4521 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4522 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4523 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4524 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4525 if (dim == PETSC_DETERMINE) { 4526 PetscInt d = PETSC_DEFAULT; 4527 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4528 4529 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4530 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4531 pStart = PetscMax(vStart, pStart); 4532 pEnd = PetscMin(vEnd, pEnd); 4533 for (v = pStart; v < pEnd; ++v) { 4534 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4535 if (dd) {d = dd; break;} 4536 } 4537 if (d < 0) d = PETSC_DEFAULT; 4538 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4539 } 4540 PetscFunctionReturn(0); 4541 } 4542 4543 /*@C 4544 DMGetPeriodicity - Get the description of mesh periodicity 4545 4546 Input Parameters: 4547 . dm - The DM object 4548 4549 Output Parameters: 4550 + per - Whether the DM is periodic or not 4551 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4552 . L - If we assume the mesh is a torus, this is the length of each coordinate 4553 - bd - This describes the type of periodicity in each topological dimension 4554 4555 Level: developer 4556 4557 .seealso: DMGetPeriodicity() 4558 @*/ 4559 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4560 { 4561 PetscFunctionBegin; 4562 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4563 if (per) *per = dm->periodic; 4564 if (L) *L = dm->L; 4565 if (maxCell) *maxCell = dm->maxCell; 4566 if (bd) *bd = dm->bdtype; 4567 PetscFunctionReturn(0); 4568 } 4569 4570 /*@C 4571 DMSetPeriodicity - Set the description of mesh periodicity 4572 4573 Input Parameters: 4574 + dm - The DM object 4575 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 4576 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4577 . L - If we assume the mesh is a torus, this is the length of each coordinate 4578 - bd - This describes the type of periodicity in each topological dimension 4579 4580 Level: developer 4581 4582 .seealso: DMGetPeriodicity() 4583 @*/ 4584 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4585 { 4586 PetscInt dim, d; 4587 PetscErrorCode ierr; 4588 4589 PetscFunctionBegin; 4590 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4591 PetscValidLogicalCollectiveBool(dm,per,2); 4592 if (maxCell) { 4593 PetscValidPointer(maxCell,3); 4594 PetscValidPointer(L,4); 4595 PetscValidPointer(bd,5); 4596 } 4597 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4598 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4599 if (maxCell) { 4600 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4601 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4602 dm->periodic = PETSC_TRUE; 4603 } else { 4604 dm->periodic = per; 4605 } 4606 PetscFunctionReturn(0); 4607 } 4608 4609 /*@ 4610 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. 4611 4612 Input Parameters: 4613 + dm - The DM 4614 . in - The input coordinate point (dim numbers) 4615 - endpoint - Include the endpoint L_i 4616 4617 Output Parameter: 4618 . out - The localized coordinate point 4619 4620 Level: developer 4621 4622 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4623 @*/ 4624 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 4625 { 4626 PetscInt dim, d; 4627 PetscErrorCode ierr; 4628 4629 PetscFunctionBegin; 4630 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4631 if (!dm->maxCell) { 4632 for (d = 0; d < dim; ++d) out[d] = in[d]; 4633 } else { 4634 if (endpoint) { 4635 for (d = 0; d < dim; ++d) { 4636 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)) { 4637 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 4638 } else { 4639 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4640 } 4641 } 4642 } else { 4643 for (d = 0; d < dim; ++d) { 4644 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4645 } 4646 } 4647 } 4648 PetscFunctionReturn(0); 4649 } 4650 4651 /* 4652 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. 4653 4654 Input Parameters: 4655 + dm - The DM 4656 . dim - The spatial dimension 4657 . anchor - The anchor point, the input point can be no more than maxCell away from it 4658 - in - The input coordinate point (dim numbers) 4659 4660 Output Parameter: 4661 . out - The localized coordinate point 4662 4663 Level: developer 4664 4665 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 4666 4667 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4668 */ 4669 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4670 { 4671 PetscInt d; 4672 4673 PetscFunctionBegin; 4674 if (!dm->maxCell) { 4675 for (d = 0; d < dim; ++d) out[d] = in[d]; 4676 } else { 4677 for (d = 0; d < dim; ++d) { 4678 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 4679 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4680 } else { 4681 out[d] = in[d]; 4682 } 4683 } 4684 } 4685 PetscFunctionReturn(0); 4686 } 4687 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 4688 { 4689 PetscInt d; 4690 4691 PetscFunctionBegin; 4692 if (!dm->maxCell) { 4693 for (d = 0; d < dim; ++d) out[d] = in[d]; 4694 } else { 4695 for (d = 0; d < dim; ++d) { 4696 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 4697 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4698 } else { 4699 out[d] = in[d]; 4700 } 4701 } 4702 } 4703 PetscFunctionReturn(0); 4704 } 4705 4706 /* 4707 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. 4708 4709 Input Parameters: 4710 + dm - The DM 4711 . dim - The spatial dimension 4712 . anchor - The anchor point, the input point can be no more than maxCell away from it 4713 . in - The input coordinate delta (dim numbers) 4714 - out - The input coordinate point (dim numbers) 4715 4716 Output Parameter: 4717 . out - The localized coordinate in + out 4718 4719 Level: developer 4720 4721 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 4722 4723 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 4724 */ 4725 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4726 { 4727 PetscInt d; 4728 4729 PetscFunctionBegin; 4730 if (!dm->maxCell) { 4731 for (d = 0; d < dim; ++d) out[d] += in[d]; 4732 } else { 4733 for (d = 0; d < dim; ++d) { 4734 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 4735 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4736 } else { 4737 out[d] += in[d]; 4738 } 4739 } 4740 } 4741 PetscFunctionReturn(0); 4742 } 4743 4744 /*@ 4745 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 4746 4747 Input Parameter: 4748 . dm - The DM 4749 4750 Output Parameter: 4751 areLocalized - True if localized 4752 4753 Level: developer 4754 4755 .seealso: DMLocalizeCoordinates() 4756 @*/ 4757 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 4758 { 4759 DM cdm; 4760 PetscSection coordSection; 4761 PetscInt cStart, cEnd, c, sStart, sEnd, dof; 4762 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4763 PetscErrorCode ierr; 4764 4765 PetscFunctionBegin; 4766 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4767 if (!dm->periodic) { 4768 *areLocalized = PETSC_FALSE; 4769 PetscFunctionReturn(0); 4770 } 4771 /* We need some generic way of refering to cells/vertices */ 4772 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4773 { 4774 PetscBool isplex; 4775 4776 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4777 if (isplex) { 4778 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4779 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4780 } 4781 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4782 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4783 alreadyLocalized = alreadyLocalizedGlobal = PETSC_FALSE; 4784 for (c = cStart; c < cEnd; ++c) { 4785 if (c < sStart || c >= sEnd) { 4786 alreadyLocalized = PETSC_FALSE; 4787 break; 4788 } 4789 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4790 if (dof) { 4791 alreadyLocalized = PETSC_TRUE; 4792 break; 4793 } 4794 } 4795 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4796 *areLocalized = alreadyLocalizedGlobal; 4797 PetscFunctionReturn(0); 4798 } 4799 4800 4801 /*@ 4802 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 4803 4804 Input Parameter: 4805 . dm - The DM 4806 4807 Level: developer 4808 4809 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 4810 @*/ 4811 PetscErrorCode DMLocalizeCoordinates(DM dm) 4812 { 4813 DM cdm; 4814 PetscSection coordSection, cSection; 4815 Vec coordinates, cVec; 4816 PetscScalar *coords, *coords2, *anchor, *localized; 4817 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 4818 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4819 PetscInt maxHeight = 0, h; 4820 PetscInt *pStart = NULL, *pEnd = NULL; 4821 PetscErrorCode ierr; 4822 4823 PetscFunctionBegin; 4824 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4825 if (!dm->periodic) PetscFunctionReturn(0); 4826 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 4827 if (alreadyLocalized) PetscFunctionReturn(0); 4828 4829 /* We need some generic way of refering to cells/vertices */ 4830 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4831 { 4832 PetscBool isplex; 4833 4834 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4835 if (isplex) { 4836 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4837 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 4838 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4839 pEnd = &pStart[maxHeight + 1]; 4840 newStart = vStart; 4841 newEnd = vEnd; 4842 for (h = 0; h <= maxHeight; h++) { 4843 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 4844 newStart = PetscMin(newStart,pStart[h]); 4845 newEnd = PetscMax(newEnd,pEnd[h]); 4846 } 4847 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4848 } 4849 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4850 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 4851 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4852 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 4853 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4854 4855 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 4856 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 4857 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 4858 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 4859 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 4860 4861 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4862 localized = &anchor[bs]; 4863 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4864 for (h = 0; h <= maxHeight; h++) { 4865 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4866 4867 for (c = cStart; c < cEnd; ++c) { 4868 PetscScalar *cellCoords = NULL; 4869 PetscInt b; 4870 4871 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 4872 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4873 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4874 for (d = 0; d < dof/bs; ++d) { 4875 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 4876 for (b = 0; b < bs; b++) { 4877 if (cellCoords[d*bs + b] != localized[b]) break; 4878 } 4879 if (b < bs) break; 4880 } 4881 if (d < dof/bs) { 4882 if (c >= sStart && c < sEnd) { 4883 PetscInt cdof; 4884 4885 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 4886 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 4887 } 4888 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 4889 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 4890 } 4891 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4892 } 4893 } 4894 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4895 if (alreadyLocalizedGlobal) { 4896 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4897 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4898 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4899 PetscFunctionReturn(0); 4900 } 4901 for (v = vStart; v < vEnd; ++v) { 4902 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4903 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 4904 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 4905 } 4906 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 4907 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 4908 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 4909 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4910 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 4911 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4912 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 4913 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 4914 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 4915 for (v = vStart; v < vEnd; ++v) { 4916 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4917 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4918 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 4919 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 4920 } 4921 for (h = 0; h <= maxHeight; h++) { 4922 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4923 4924 for (c = cStart; c < cEnd; ++c) { 4925 PetscScalar *cellCoords = NULL; 4926 PetscInt b, cdof; 4927 4928 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 4929 if (!cdof) continue; 4930 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4931 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 4932 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4933 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 4934 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4935 } 4936 } 4937 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4938 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4939 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 4940 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 4941 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 4942 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 4943 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 4944 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4945 PetscFunctionReturn(0); 4946 } 4947 4948 /*@ 4949 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 4950 4951 Collective on Vec v (see explanation below) 4952 4953 Input Parameters: 4954 + dm - The DM 4955 . v - The Vec of points 4956 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 4957 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 4958 4959 Output Parameter: 4960 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 4961 - cells - The PetscSF containing the ranks and local indices of the containing points. 4962 4963 4964 Level: developer 4965 4966 Notes: 4967 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 4968 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 4969 4970 If *cellSF is NULL on input, a PetscSF will be created. 4971 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 4972 4973 An array that maps each point to its containing cell can be obtained with 4974 4975 $ const PetscSFNode *cells; 4976 $ PetscInt nFound; 4977 $ const PetscSFNode *found; 4978 $ 4979 $ PetscSFGetGraph(cells,NULL,&nFound,&found,&cells); 4980 4981 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 4982 the index of the cell in its rank's local numbering. 4983 4984 .keywords: point location, mesh 4985 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 4986 @*/ 4987 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 4988 { 4989 PetscErrorCode ierr; 4990 4991 PetscFunctionBegin; 4992 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4993 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4994 PetscValidPointer(cellSF,4); 4995 if (*cellSF) { 4996 PetscMPIInt result; 4997 4998 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 4999 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 5000 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 5001 } else { 5002 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 5003 } 5004 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5005 if (dm->ops->locatepoints) { 5006 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 5007 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 5008 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5009 PetscFunctionReturn(0); 5010 } 5011 5012 /*@ 5013 DMGetOutputDM - Retrieve the DM associated with the layout for output 5014 5015 Input Parameter: 5016 . dm - The original DM 5017 5018 Output Parameter: 5019 . odm - The DM which provides the layout for output 5020 5021 Level: intermediate 5022 5023 .seealso: VecView(), DMGetDefaultGlobalSection() 5024 @*/ 5025 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 5026 { 5027 PetscSection section; 5028 PetscBool hasConstraints, ghasConstraints; 5029 PetscErrorCode ierr; 5030 5031 PetscFunctionBegin; 5032 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5033 PetscValidPointer(odm,2); 5034 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 5035 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 5036 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 5037 if (!ghasConstraints) { 5038 *odm = dm; 5039 PetscFunctionReturn(0); 5040 } 5041 if (!dm->dmBC) { 5042 PetscDS ds; 5043 PetscSection newSection, gsection; 5044 PetscSF sf; 5045 5046 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 5047 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5048 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 5049 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 5050 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 5051 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 5052 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 5053 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 5054 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 5055 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 5056 } 5057 *odm = dm->dmBC; 5058 PetscFunctionReturn(0); 5059 } 5060 5061 /*@ 5062 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 5063 5064 Input Parameter: 5065 . dm - The original DM 5066 5067 Output Parameters: 5068 + num - The output sequence number 5069 - val - The output sequence value 5070 5071 Level: intermediate 5072 5073 Note: This is intended for output that should appear in sequence, for instance 5074 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5075 5076 .seealso: VecView() 5077 @*/ 5078 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 5079 { 5080 PetscFunctionBegin; 5081 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5082 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 5083 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 5084 PetscFunctionReturn(0); 5085 } 5086 5087 /*@ 5088 DMSetOutputSequenceNumber - Set the sequence number/value for output 5089 5090 Input Parameters: 5091 + dm - The original DM 5092 . num - The output sequence number 5093 - val - The output sequence value 5094 5095 Level: intermediate 5096 5097 Note: This is intended for output that should appear in sequence, for instance 5098 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5099 5100 .seealso: VecView() 5101 @*/ 5102 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5103 { 5104 PetscFunctionBegin; 5105 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5106 dm->outputSequenceNum = num; 5107 dm->outputSequenceVal = val; 5108 PetscFunctionReturn(0); 5109 } 5110 5111 /*@C 5112 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5113 5114 Input Parameters: 5115 + dm - The original DM 5116 . name - The sequence name 5117 - num - The output sequence number 5118 5119 Output Parameter: 5120 . val - The output sequence value 5121 5122 Level: intermediate 5123 5124 Note: This is intended for output that should appear in sequence, for instance 5125 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5126 5127 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5128 @*/ 5129 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5130 { 5131 PetscBool ishdf5; 5132 PetscErrorCode ierr; 5133 5134 PetscFunctionBegin; 5135 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5136 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5137 PetscValidPointer(val,4); 5138 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5139 if (ishdf5) { 5140 #if defined(PETSC_HAVE_HDF5) 5141 PetscScalar value; 5142 5143 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 5144 *val = PetscRealPart(value); 5145 #endif 5146 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5147 PetscFunctionReturn(0); 5148 } 5149 5150 /*@ 5151 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5152 5153 Not collective 5154 5155 Input Parameter: 5156 . dm - The DM 5157 5158 Output Parameter: 5159 . useNatural - The flag to build the mapping to a natural order during distribution 5160 5161 Level: beginner 5162 5163 .seealso: DMSetUseNatural(), DMCreate() 5164 @*/ 5165 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5166 { 5167 PetscFunctionBegin; 5168 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5169 PetscValidPointer(useNatural, 2); 5170 *useNatural = dm->useNatural; 5171 PetscFunctionReturn(0); 5172 } 5173 5174 /*@ 5175 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5176 5177 Collective on dm 5178 5179 Input Parameters: 5180 + dm - The DM 5181 - useNatural - The flag to build the mapping to a natural order during distribution 5182 5183 Level: beginner 5184 5185 .seealso: DMGetUseNatural(), DMCreate() 5186 @*/ 5187 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5188 { 5189 PetscFunctionBegin; 5190 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5191 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 5192 dm->useNatural = useNatural; 5193 PetscFunctionReturn(0); 5194 } 5195 5196 5197 /*@C 5198 DMCreateLabel - Create a label of the given name if it does not already exist 5199 5200 Not Collective 5201 5202 Input Parameters: 5203 + dm - The DM object 5204 - name - The label name 5205 5206 Level: intermediate 5207 5208 .keywords: mesh 5209 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5210 @*/ 5211 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5212 { 5213 DMLabelLink next = dm->labels->next; 5214 PetscBool flg = PETSC_FALSE; 5215 PetscErrorCode ierr; 5216 5217 PetscFunctionBegin; 5218 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5219 PetscValidCharPointer(name, 2); 5220 while (next) { 5221 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5222 if (flg) break; 5223 next = next->next; 5224 } 5225 if (!flg) { 5226 DMLabelLink tmpLabel; 5227 5228 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5229 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5230 tmpLabel->output = PETSC_TRUE; 5231 tmpLabel->next = dm->labels->next; 5232 dm->labels->next = tmpLabel; 5233 } 5234 PetscFunctionReturn(0); 5235 } 5236 5237 /*@C 5238 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5239 5240 Not Collective 5241 5242 Input Parameters: 5243 + dm - The DM object 5244 . name - The label name 5245 - point - The mesh point 5246 5247 Output Parameter: 5248 . value - The label value for this point, or -1 if the point is not in the label 5249 5250 Level: beginner 5251 5252 .keywords: mesh 5253 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5254 @*/ 5255 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5256 { 5257 DMLabel label; 5258 PetscErrorCode ierr; 5259 5260 PetscFunctionBegin; 5261 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5262 PetscValidCharPointer(name, 2); 5263 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5264 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 5265 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5266 PetscFunctionReturn(0); 5267 } 5268 5269 /*@C 5270 DMSetLabelValue - Add a point to a Sieve Label with given value 5271 5272 Not Collective 5273 5274 Input Parameters: 5275 + dm - The DM object 5276 . name - The label name 5277 . point - The mesh point 5278 - value - The label value for this point 5279 5280 Output Parameter: 5281 5282 Level: beginner 5283 5284 .keywords: mesh 5285 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5286 @*/ 5287 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5288 { 5289 DMLabel label; 5290 PetscErrorCode ierr; 5291 5292 PetscFunctionBegin; 5293 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5294 PetscValidCharPointer(name, 2); 5295 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5296 if (!label) { 5297 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5298 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5299 } 5300 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5301 PetscFunctionReturn(0); 5302 } 5303 5304 /*@C 5305 DMClearLabelValue - Remove a point from a Sieve Label with given value 5306 5307 Not Collective 5308 5309 Input Parameters: 5310 + dm - The DM object 5311 . name - The label name 5312 . point - The mesh point 5313 - value - The label value for this point 5314 5315 Output Parameter: 5316 5317 Level: beginner 5318 5319 .keywords: mesh 5320 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5321 @*/ 5322 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5323 { 5324 DMLabel label; 5325 PetscErrorCode ierr; 5326 5327 PetscFunctionBegin; 5328 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5329 PetscValidCharPointer(name, 2); 5330 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5331 if (!label) PetscFunctionReturn(0); 5332 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5333 PetscFunctionReturn(0); 5334 } 5335 5336 /*@C 5337 DMGetLabelSize - Get the number of different integer ids in a Label 5338 5339 Not Collective 5340 5341 Input Parameters: 5342 + dm - The DM object 5343 - name - The label name 5344 5345 Output Parameter: 5346 . size - The number of different integer ids, or 0 if the label does not exist 5347 5348 Level: beginner 5349 5350 .keywords: mesh 5351 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5352 @*/ 5353 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5354 { 5355 DMLabel label; 5356 PetscErrorCode ierr; 5357 5358 PetscFunctionBegin; 5359 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5360 PetscValidCharPointer(name, 2); 5361 PetscValidPointer(size, 3); 5362 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5363 *size = 0; 5364 if (!label) PetscFunctionReturn(0); 5365 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5366 PetscFunctionReturn(0); 5367 } 5368 5369 /*@C 5370 DMGetLabelIdIS - Get the integer ids in a label 5371 5372 Not Collective 5373 5374 Input Parameters: 5375 + mesh - The DM object 5376 - name - The label name 5377 5378 Output Parameter: 5379 . ids - The integer ids, or NULL if the label does not exist 5380 5381 Level: beginner 5382 5383 .keywords: mesh 5384 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5385 @*/ 5386 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5387 { 5388 DMLabel label; 5389 PetscErrorCode ierr; 5390 5391 PetscFunctionBegin; 5392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5393 PetscValidCharPointer(name, 2); 5394 PetscValidPointer(ids, 3); 5395 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5396 *ids = NULL; 5397 if (label) { 5398 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5399 } else { 5400 /* returning an empty IS */ 5401 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 5402 } 5403 PetscFunctionReturn(0); 5404 } 5405 5406 /*@C 5407 DMGetStratumSize - Get the number of points in a label stratum 5408 5409 Not Collective 5410 5411 Input Parameters: 5412 + dm - The DM object 5413 . name - The label name 5414 - value - The stratum value 5415 5416 Output Parameter: 5417 . size - The stratum size 5418 5419 Level: beginner 5420 5421 .keywords: mesh 5422 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5423 @*/ 5424 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5425 { 5426 DMLabel label; 5427 PetscErrorCode ierr; 5428 5429 PetscFunctionBegin; 5430 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5431 PetscValidCharPointer(name, 2); 5432 PetscValidPointer(size, 4); 5433 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5434 *size = 0; 5435 if (!label) PetscFunctionReturn(0); 5436 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5437 PetscFunctionReturn(0); 5438 } 5439 5440 /*@C 5441 DMGetStratumIS - Get the points in a label stratum 5442 5443 Not Collective 5444 5445 Input Parameters: 5446 + dm - The DM object 5447 . name - The label name 5448 - value - The stratum value 5449 5450 Output Parameter: 5451 . points - The stratum points, or NULL if the label does not exist or does not have that value 5452 5453 Level: beginner 5454 5455 .keywords: mesh 5456 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5457 @*/ 5458 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5459 { 5460 DMLabel label; 5461 PetscErrorCode ierr; 5462 5463 PetscFunctionBegin; 5464 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5465 PetscValidCharPointer(name, 2); 5466 PetscValidPointer(points, 4); 5467 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5468 *points = NULL; 5469 if (!label) PetscFunctionReturn(0); 5470 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5471 PetscFunctionReturn(0); 5472 } 5473 5474 /*@C 5475 DMGetStratumIS - Set the points in a label stratum 5476 5477 Not Collective 5478 5479 Input Parameters: 5480 + dm - The DM object 5481 . name - The label name 5482 . value - The stratum value 5483 - points - The stratum points 5484 5485 Level: beginner 5486 5487 .keywords: mesh 5488 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 5489 @*/ 5490 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 5491 { 5492 DMLabel label; 5493 PetscErrorCode ierr; 5494 5495 PetscFunctionBegin; 5496 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5497 PetscValidCharPointer(name, 2); 5498 PetscValidPointer(points, 4); 5499 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5500 if (!label) PetscFunctionReturn(0); 5501 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 5502 PetscFunctionReturn(0); 5503 } 5504 5505 /*@C 5506 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5507 5508 Not Collective 5509 5510 Input Parameters: 5511 + dm - The DM object 5512 . name - The label name 5513 - value - The label value for this point 5514 5515 Output Parameter: 5516 5517 Level: beginner 5518 5519 .keywords: mesh 5520 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5521 @*/ 5522 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5523 { 5524 DMLabel label; 5525 PetscErrorCode ierr; 5526 5527 PetscFunctionBegin; 5528 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5529 PetscValidCharPointer(name, 2); 5530 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5531 if (!label) PetscFunctionReturn(0); 5532 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5533 PetscFunctionReturn(0); 5534 } 5535 5536 /*@ 5537 DMGetNumLabels - Return the number of labels defined by the mesh 5538 5539 Not Collective 5540 5541 Input Parameter: 5542 . dm - The DM object 5543 5544 Output Parameter: 5545 . numLabels - the number of Labels 5546 5547 Level: intermediate 5548 5549 .keywords: mesh 5550 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5551 @*/ 5552 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5553 { 5554 DMLabelLink next = dm->labels->next; 5555 PetscInt n = 0; 5556 5557 PetscFunctionBegin; 5558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5559 PetscValidPointer(numLabels, 2); 5560 while (next) {++n; next = next->next;} 5561 *numLabels = n; 5562 PetscFunctionReturn(0); 5563 } 5564 5565 /*@C 5566 DMGetLabelName - Return the name of nth label 5567 5568 Not Collective 5569 5570 Input Parameters: 5571 + dm - The DM object 5572 - n - the label number 5573 5574 Output Parameter: 5575 . name - the label name 5576 5577 Level: intermediate 5578 5579 .keywords: mesh 5580 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5581 @*/ 5582 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5583 { 5584 DMLabelLink next = dm->labels->next; 5585 PetscInt l = 0; 5586 5587 PetscFunctionBegin; 5588 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5589 PetscValidPointer(name, 3); 5590 while (next) { 5591 if (l == n) { 5592 *name = next->label->name; 5593 PetscFunctionReturn(0); 5594 } 5595 ++l; 5596 next = next->next; 5597 } 5598 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5599 } 5600 5601 /*@C 5602 DMHasLabel - Determine whether the mesh has a label of a given name 5603 5604 Not Collective 5605 5606 Input Parameters: 5607 + dm - The DM object 5608 - name - The label name 5609 5610 Output Parameter: 5611 . hasLabel - PETSC_TRUE if the label is present 5612 5613 Level: intermediate 5614 5615 .keywords: mesh 5616 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5617 @*/ 5618 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5619 { 5620 DMLabelLink next = dm->labels->next; 5621 PetscErrorCode ierr; 5622 5623 PetscFunctionBegin; 5624 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5625 PetscValidCharPointer(name, 2); 5626 PetscValidPointer(hasLabel, 3); 5627 *hasLabel = PETSC_FALSE; 5628 while (next) { 5629 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5630 if (*hasLabel) break; 5631 next = next->next; 5632 } 5633 PetscFunctionReturn(0); 5634 } 5635 5636 /*@C 5637 DMGetLabel - Return the label of a given name, or NULL 5638 5639 Not Collective 5640 5641 Input Parameters: 5642 + dm - The DM object 5643 - name - The label name 5644 5645 Output Parameter: 5646 . label - The DMLabel, or NULL if the label is absent 5647 5648 Level: intermediate 5649 5650 .keywords: mesh 5651 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5652 @*/ 5653 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5654 { 5655 DMLabelLink next = dm->labels->next; 5656 PetscBool hasLabel; 5657 PetscErrorCode ierr; 5658 5659 PetscFunctionBegin; 5660 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5661 PetscValidCharPointer(name, 2); 5662 PetscValidPointer(label, 3); 5663 *label = NULL; 5664 while (next) { 5665 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5666 if (hasLabel) { 5667 *label = next->label; 5668 break; 5669 } 5670 next = next->next; 5671 } 5672 PetscFunctionReturn(0); 5673 } 5674 5675 /*@C 5676 DMGetLabelByNum - Return the nth label 5677 5678 Not Collective 5679 5680 Input Parameters: 5681 + dm - The DM object 5682 - n - the label number 5683 5684 Output Parameter: 5685 . label - the label 5686 5687 Level: intermediate 5688 5689 .keywords: mesh 5690 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5691 @*/ 5692 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5693 { 5694 DMLabelLink next = dm->labels->next; 5695 PetscInt l = 0; 5696 5697 PetscFunctionBegin; 5698 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5699 PetscValidPointer(label, 3); 5700 while (next) { 5701 if (l == n) { 5702 *label = next->label; 5703 PetscFunctionReturn(0); 5704 } 5705 ++l; 5706 next = next->next; 5707 } 5708 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5709 } 5710 5711 /*@C 5712 DMAddLabel - Add the label to this mesh 5713 5714 Not Collective 5715 5716 Input Parameters: 5717 + dm - The DM object 5718 - label - The DMLabel 5719 5720 Level: developer 5721 5722 .keywords: mesh 5723 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5724 @*/ 5725 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5726 { 5727 DMLabelLink tmpLabel; 5728 PetscBool hasLabel; 5729 PetscErrorCode ierr; 5730 5731 PetscFunctionBegin; 5732 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5733 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5734 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5735 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5736 tmpLabel->label = label; 5737 tmpLabel->output = PETSC_TRUE; 5738 tmpLabel->next = dm->labels->next; 5739 dm->labels->next = tmpLabel; 5740 PetscFunctionReturn(0); 5741 } 5742 5743 /*@C 5744 DMRemoveLabel - Remove the label from this mesh 5745 5746 Not Collective 5747 5748 Input Parameters: 5749 + dm - The DM object 5750 - name - The label name 5751 5752 Output Parameter: 5753 . label - The DMLabel, or NULL if the label is absent 5754 5755 Level: developer 5756 5757 .keywords: mesh 5758 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5759 @*/ 5760 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5761 { 5762 DMLabelLink next = dm->labels->next; 5763 DMLabelLink last = NULL; 5764 PetscBool hasLabel; 5765 PetscErrorCode ierr; 5766 5767 PetscFunctionBegin; 5768 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5769 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5770 *label = NULL; 5771 if (!hasLabel) PetscFunctionReturn(0); 5772 while (next) { 5773 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5774 if (hasLabel) { 5775 if (last) last->next = next->next; 5776 else dm->labels->next = next->next; 5777 next->next = NULL; 5778 *label = next->label; 5779 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5780 if (hasLabel) { 5781 dm->depthLabel = NULL; 5782 } 5783 ierr = PetscFree(next);CHKERRQ(ierr); 5784 break; 5785 } 5786 last = next; 5787 next = next->next; 5788 } 5789 PetscFunctionReturn(0); 5790 } 5791 5792 /*@C 5793 DMGetLabelOutput - Get the output flag for a given label 5794 5795 Not Collective 5796 5797 Input Parameters: 5798 + dm - The DM object 5799 - name - The label name 5800 5801 Output Parameter: 5802 . output - The flag for output 5803 5804 Level: developer 5805 5806 .keywords: mesh 5807 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5808 @*/ 5809 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5810 { 5811 DMLabelLink next = dm->labels->next; 5812 PetscErrorCode ierr; 5813 5814 PetscFunctionBegin; 5815 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5816 PetscValidPointer(name, 2); 5817 PetscValidPointer(output, 3); 5818 while (next) { 5819 PetscBool flg; 5820 5821 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5822 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5823 next = next->next; 5824 } 5825 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5826 } 5827 5828 /*@C 5829 DMSetLabelOutput - Set the output flag for a given label 5830 5831 Not Collective 5832 5833 Input Parameters: 5834 + dm - The DM object 5835 . name - The label name 5836 - output - The flag for output 5837 5838 Level: developer 5839 5840 .keywords: mesh 5841 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5842 @*/ 5843 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5844 { 5845 DMLabelLink next = dm->labels->next; 5846 PetscErrorCode ierr; 5847 5848 PetscFunctionBegin; 5849 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5850 PetscValidPointer(name, 2); 5851 while (next) { 5852 PetscBool flg; 5853 5854 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5855 if (flg) {next->output = output; PetscFunctionReturn(0);} 5856 next = next->next; 5857 } 5858 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5859 } 5860 5861 5862 /*@ 5863 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5864 5865 Collective on DM 5866 5867 Input Parameter: 5868 . dmA - The DM object with initial labels 5869 5870 Output Parameter: 5871 . dmB - The DM object with copied labels 5872 5873 Level: intermediate 5874 5875 Note: This is typically used when interpolating or otherwise adding to a mesh 5876 5877 .keywords: mesh 5878 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5879 @*/ 5880 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5881 { 5882 PetscInt numLabels, l; 5883 PetscErrorCode ierr; 5884 5885 PetscFunctionBegin; 5886 if (dmA == dmB) PetscFunctionReturn(0); 5887 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5888 for (l = 0; l < numLabels; ++l) { 5889 DMLabel label, labelNew; 5890 const char *name; 5891 PetscBool flg; 5892 5893 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5894 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5895 if (flg) continue; 5896 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5897 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5898 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5899 } 5900 PetscFunctionReturn(0); 5901 } 5902 5903 /*@ 5904 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5905 5906 Input Parameter: 5907 . dm - The DM object 5908 5909 Output Parameter: 5910 . cdm - The coarse DM 5911 5912 Level: intermediate 5913 5914 .seealso: DMSetCoarseDM() 5915 @*/ 5916 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5917 { 5918 PetscFunctionBegin; 5919 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5920 PetscValidPointer(cdm, 2); 5921 *cdm = dm->coarseMesh; 5922 PetscFunctionReturn(0); 5923 } 5924 5925 /*@ 5926 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5927 5928 Input Parameters: 5929 + dm - The DM object 5930 - cdm - The coarse DM 5931 5932 Level: intermediate 5933 5934 .seealso: DMGetCoarseDM() 5935 @*/ 5936 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5937 { 5938 PetscErrorCode ierr; 5939 5940 PetscFunctionBegin; 5941 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5942 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5943 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5944 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5945 dm->coarseMesh = cdm; 5946 PetscFunctionReturn(0); 5947 } 5948 5949 /*@ 5950 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 5951 5952 Input Parameter: 5953 . dm - The DM object 5954 5955 Output Parameter: 5956 . fdm - The fine DM 5957 5958 Level: intermediate 5959 5960 .seealso: DMSetFineDM() 5961 @*/ 5962 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 5963 { 5964 PetscFunctionBegin; 5965 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5966 PetscValidPointer(fdm, 2); 5967 *fdm = dm->fineMesh; 5968 PetscFunctionReturn(0); 5969 } 5970 5971 /*@ 5972 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 5973 5974 Input Parameters: 5975 + dm - The DM object 5976 - fdm - The fine DM 5977 5978 Level: intermediate 5979 5980 .seealso: DMGetFineDM() 5981 @*/ 5982 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 5983 { 5984 PetscErrorCode ierr; 5985 5986 PetscFunctionBegin; 5987 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5988 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 5989 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 5990 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 5991 dm->fineMesh = fdm; 5992 PetscFunctionReturn(0); 5993 } 5994 5995 /*=== DMBoundary code ===*/ 5996 5997 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 5998 { 5999 PetscErrorCode ierr; 6000 6001 PetscFunctionBegin; 6002 ierr = PetscDSCopyBoundary(dm->prob,dmNew->prob);CHKERRQ(ierr); 6003 PetscFunctionReturn(0); 6004 } 6005 6006 /*@C 6007 DMAddBoundary - Add a boundary condition to the model 6008 6009 Input Parameters: 6010 + dm - The DM, with a PetscDS that matches the problem being constrained 6011 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6012 . name - The BC name 6013 . labelname - The label defining constrained points 6014 . field - The field to constrain 6015 . numcomps - The number of constrained field components 6016 . comps - An array of constrained component numbers 6017 . bcFunc - A pointwise function giving boundary values 6018 . numids - The number of DMLabel ids for constrained points 6019 . ids - An array of ids for constrained points 6020 - ctx - An optional user context for bcFunc 6021 6022 Options Database Keys: 6023 + -bc_<boundary name> <num> - Overrides the boundary ids 6024 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6025 6026 Level: developer 6027 6028 .seealso: DMGetBoundary() 6029 @*/ 6030 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) 6031 { 6032 PetscErrorCode ierr; 6033 6034 PetscFunctionBegin; 6035 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6036 ierr = PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);CHKERRQ(ierr); 6037 PetscFunctionReturn(0); 6038 } 6039 6040 /*@ 6041 DMGetNumBoundary - Get the number of registered BC 6042 6043 Input Parameters: 6044 . dm - The mesh object 6045 6046 Output Parameters: 6047 . numBd - The number of BC 6048 6049 Level: intermediate 6050 6051 .seealso: DMAddBoundary(), DMGetBoundary() 6052 @*/ 6053 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6054 { 6055 PetscErrorCode ierr; 6056 6057 PetscFunctionBegin; 6058 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6059 ierr = PetscDSGetNumBoundary(dm->prob,numBd);CHKERRQ(ierr); 6060 PetscFunctionReturn(0); 6061 } 6062 6063 /*@C 6064 DMGetBoundary - Get a model boundary condition 6065 6066 Input Parameters: 6067 + dm - The mesh object 6068 - bd - The BC number 6069 6070 Output Parameters: 6071 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6072 . name - The BC name 6073 . labelname - The label defining constrained points 6074 . field - The field to constrain 6075 . numcomps - The number of constrained field components 6076 . comps - An array of constrained component numbers 6077 . bcFunc - A pointwise function giving boundary values 6078 . numids - The number of DMLabel ids for constrained points 6079 . ids - An array of ids for constrained points 6080 - ctx - An optional user context for bcFunc 6081 6082 Options Database Keys: 6083 + -bc_<boundary name> <num> - Overrides the boundary ids 6084 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6085 6086 Level: developer 6087 6088 .seealso: DMAddBoundary() 6089 @*/ 6090 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) 6091 { 6092 PetscErrorCode ierr; 6093 6094 PetscFunctionBegin; 6095 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6096 ierr = PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);CHKERRQ(ierr); 6097 PetscFunctionReturn(0); 6098 } 6099 6100 static PetscErrorCode DMPopulateBoundary(DM dm) 6101 { 6102 DMBoundary *lastnext; 6103 DSBoundary dsbound; 6104 PetscErrorCode ierr; 6105 6106 PetscFunctionBegin; 6107 dsbound = dm->prob->boundary; 6108 if (dm->boundary) { 6109 DMBoundary next = dm->boundary; 6110 6111 /* quick check to see if the PetscDS has changed */ 6112 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 6113 /* the PetscDS has changed: tear down and rebuild */ 6114 while (next) { 6115 DMBoundary b = next; 6116 6117 next = b->next; 6118 ierr = PetscFree(b);CHKERRQ(ierr); 6119 } 6120 dm->boundary = NULL; 6121 } 6122 6123 lastnext = &(dm->boundary); 6124 while (dsbound) { 6125 DMBoundary dmbound; 6126 6127 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 6128 dmbound->dsboundary = dsbound; 6129 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 6130 if (!dmbound->label) PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr); 6131 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 6132 *lastnext = dmbound; 6133 lastnext = &(dmbound->next); 6134 dsbound = dsbound->next; 6135 } 6136 PetscFunctionReturn(0); 6137 } 6138 6139 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6140 { 6141 DMBoundary b; 6142 PetscErrorCode ierr; 6143 6144 PetscFunctionBegin; 6145 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6146 PetscValidPointer(isBd, 3); 6147 *isBd = PETSC_FALSE; 6148 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 6149 b = dm->boundary; 6150 while (b && !(*isBd)) { 6151 DMLabel label = b->label; 6152 DSBoundary dsb = b->dsboundary; 6153 6154 if (label) { 6155 PetscInt i; 6156 6157 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 6158 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 6159 } 6160 } 6161 b = b->next; 6162 } 6163 PetscFunctionReturn(0); 6164 } 6165 6166 /*@C 6167 DMProjectFunction - This projects the given function into the function space provided. 6168 6169 Input Parameters: 6170 + dm - The DM 6171 . time - The time 6172 . funcs - The coordinate functions to evaluate, one per field 6173 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6174 - mode - The insertion mode for values 6175 6176 Output Parameter: 6177 . X - vector 6178 6179 Calling sequence of func: 6180 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6181 6182 + dim - The spatial dimension 6183 . x - The coordinates 6184 . Nf - The number of fields 6185 . u - The output field values 6186 - ctx - optional user-defined function context 6187 6188 Level: developer 6189 6190 .seealso: DMComputeL2Diff() 6191 @*/ 6192 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6193 { 6194 Vec localX; 6195 PetscErrorCode ierr; 6196 6197 PetscFunctionBegin; 6198 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6199 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6200 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6201 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6202 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6203 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6204 PetscFunctionReturn(0); 6205 } 6206 6207 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6208 { 6209 PetscErrorCode ierr; 6210 6211 PetscFunctionBegin; 6212 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6213 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6214 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6215 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6216 PetscFunctionReturn(0); 6217 } 6218 6219 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) 6220 { 6221 Vec localX; 6222 PetscErrorCode ierr; 6223 6224 PetscFunctionBegin; 6225 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6226 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6227 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6228 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6229 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6230 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6231 PetscFunctionReturn(0); 6232 } 6233 6234 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) 6235 { 6236 PetscErrorCode ierr; 6237 6238 PetscFunctionBegin; 6239 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6240 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6241 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6242 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6243 PetscFunctionReturn(0); 6244 } 6245 6246 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 6247 void (**funcs)(PetscInt, PetscInt, PetscInt, 6248 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6249 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6250 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6251 InsertMode mode, Vec localX) 6252 { 6253 PetscErrorCode ierr; 6254 6255 PetscFunctionBegin; 6256 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6257 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 6258 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 6259 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6260 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 6261 PetscFunctionReturn(0); 6262 } 6263 6264 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 6265 void (**funcs)(PetscInt, PetscInt, PetscInt, 6266 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6267 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6268 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6269 InsertMode mode, Vec localX) 6270 { 6271 PetscErrorCode ierr; 6272 6273 PetscFunctionBegin; 6274 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6275 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 6276 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 6277 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6278 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 6279 PetscFunctionReturn(0); 6280 } 6281 6282 /*@C 6283 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6284 6285 Input Parameters: 6286 + dm - The DM 6287 . time - The time 6288 . funcs - The functions to evaluate for each field component 6289 . ctxs - Optional array of contexts to pass to each function, or NULL. 6290 - X - The coefficient vector u_h, a global vector 6291 6292 Output Parameter: 6293 . diff - The diff ||u - u_h||_2 6294 6295 Level: developer 6296 6297 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6298 @*/ 6299 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6300 { 6301 PetscErrorCode ierr; 6302 6303 PetscFunctionBegin; 6304 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6305 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6306 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 6307 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6308 PetscFunctionReturn(0); 6309 } 6310 6311 /*@C 6312 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6313 6314 Input Parameters: 6315 + dm - The DM 6316 , time - The time 6317 . funcs - The gradient functions to evaluate for each field component 6318 . ctxs - Optional array of contexts to pass to each function, or NULL. 6319 . X - The coefficient vector u_h, a global vector 6320 - n - The vector to project along 6321 6322 Output Parameter: 6323 . diff - The diff ||(grad u - grad u_h) . n||_2 6324 6325 Level: developer 6326 6327 .seealso: DMProjectFunction(), DMComputeL2Diff() 6328 @*/ 6329 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) 6330 { 6331 PetscErrorCode ierr; 6332 6333 PetscFunctionBegin; 6334 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6335 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6336 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6337 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6338 PetscFunctionReturn(0); 6339 } 6340 6341 /*@C 6342 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6343 6344 Input Parameters: 6345 + dm - The DM 6346 . time - The time 6347 . funcs - The functions to evaluate for each field component 6348 . ctxs - Optional array of contexts to pass to each function, or NULL. 6349 - X - The coefficient vector u_h, a global vector 6350 6351 Output Parameter: 6352 . diff - The array of differences, ||u^f - u^f_h||_2 6353 6354 Level: developer 6355 6356 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6357 @*/ 6358 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6359 { 6360 PetscErrorCode ierr; 6361 6362 PetscFunctionBegin; 6363 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6364 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6365 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6366 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6367 PetscFunctionReturn(0); 6368 } 6369 6370 /*@C 6371 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 6372 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 6373 6374 Collective on dm 6375 6376 Input parameters: 6377 + dm - the pre-adaptation DM object 6378 - label - label with the flags 6379 6380 Output parameters: 6381 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 6382 6383 Level: intermediate 6384 6385 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 6386 @*/ 6387 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 6388 { 6389 PetscErrorCode ierr; 6390 6391 PetscFunctionBegin; 6392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6393 PetscValidPointer(label,2); 6394 PetscValidPointer(dmAdapt,3); 6395 *dmAdapt = NULL; 6396 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 6397 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 6398 PetscFunctionReturn(0); 6399 } 6400 6401 /*@C 6402 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 6403 6404 Input Parameters: 6405 + dm - The DM object 6406 . metric - The metric to which the mesh is adapted, defined vertex-wise. 6407 - 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_". 6408 6409 Output Parameter: 6410 . dmAdapt - Pointer to the DM object containing the adapted mesh 6411 6412 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 6413 6414 Level: advanced 6415 6416 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 6417 @*/ 6418 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 6419 { 6420 PetscErrorCode ierr; 6421 6422 PetscFunctionBegin; 6423 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6424 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 6425 if (bdLabel) PetscValidPointer(bdLabel, 3); 6426 PetscValidPointer(dmAdapt, 4); 6427 *dmAdapt = NULL; 6428 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 6429 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 6430 PetscFunctionReturn(0); 6431 } 6432 6433 /*@C 6434 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6435 6436 Not Collective 6437 6438 Input Parameter: 6439 . dm - The DM 6440 6441 Output Parameter: 6442 . nranks - the number of neighbours 6443 . ranks - the neighbors ranks 6444 6445 Notes: 6446 Do not free the array, it is freed when the DM is destroyed. 6447 6448 Level: beginner 6449 6450 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6451 @*/ 6452 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6453 { 6454 PetscErrorCode ierr; 6455 6456 PetscFunctionBegin; 6457 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6458 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 6459 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6460 PetscFunctionReturn(0); 6461 } 6462 6463 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 6464 6465 /* 6466 Converts the input vector to a ghosted vector and then calls the standard coloring code. 6467 This has be a different function because it requires DM which is not defined in the Mat library 6468 */ 6469 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 6470 { 6471 PetscErrorCode ierr; 6472 6473 PetscFunctionBegin; 6474 if (coloring->ctype == IS_COLORING_LOCAL) { 6475 Vec x1local; 6476 DM dm; 6477 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6478 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 6479 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 6480 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6481 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6482 x1 = x1local; 6483 } 6484 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 6485 if (coloring->ctype == IS_COLORING_LOCAL) { 6486 DM dm; 6487 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6488 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 6489 } 6490 PetscFunctionReturn(0); 6491 } 6492 6493 /*@ 6494 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 6495 6496 Input Parameter: 6497 . coloring - the MatFDColoring object 6498 6499 Developer Notes: this routine exists because the PETSc Mat library does not know about the DM objects 6500 6501 Level: advanced 6502 6503 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 6504 @*/ 6505 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 6506 { 6507 PetscFunctionBegin; 6508 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 6509 PetscFunctionReturn(0); 6510 } 6511