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