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