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