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