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