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