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