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