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