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