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