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