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 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 4777 if (alreadyLocalized) PetscFunctionReturn(0); 4778 4779 /* We need some generic way of refering to cells/vertices */ 4780 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4781 { 4782 PetscBool isplex; 4783 4784 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4785 if (isplex) { 4786 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4787 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 4788 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4789 pEnd = &pStart[maxHeight + 1]; 4790 newStart = vStart; 4791 newEnd = vEnd; 4792 for (h = 0; h <= maxHeight; h++) { 4793 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 4794 newStart = PetscMin(newStart,pStart[h]); 4795 newEnd = PetscMax(newEnd,pEnd[h]); 4796 } 4797 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4798 } 4799 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4800 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 4801 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4802 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 4803 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4804 4805 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 4806 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 4807 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 4808 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 4809 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 4810 4811 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4812 localized = &anchor[bs]; 4813 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4814 for (h = 0; h <= maxHeight; h++) { 4815 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4816 4817 for (c = cStart; c < cEnd; ++c) { 4818 PetscScalar *cellCoords = NULL; 4819 PetscInt b; 4820 4821 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 4822 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4823 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4824 for (d = 0; d < dof/bs; ++d) { 4825 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 4826 for (b = 0; b < bs; b++) { 4827 if (cellCoords[d*bs + b] != localized[b]) break; 4828 } 4829 if (b < bs) break; 4830 } 4831 if (d < dof/bs) { 4832 if (c >= sStart && c < sEnd) { 4833 PetscInt cdof; 4834 4835 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 4836 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 4837 } 4838 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 4839 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 4840 } 4841 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4842 } 4843 } 4844 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4845 if (alreadyLocalizedGlobal) { 4846 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4847 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4848 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4849 PetscFunctionReturn(0); 4850 } 4851 for (v = vStart; v < vEnd; ++v) { 4852 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4853 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 4854 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 4855 } 4856 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 4857 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 4858 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 4859 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4860 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 4861 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4862 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 4863 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 4864 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 4865 for (v = vStart; v < vEnd; ++v) { 4866 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4867 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4868 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 4869 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 4870 } 4871 for (h = 0; h <= maxHeight; h++) { 4872 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4873 4874 for (c = cStart; c < cEnd; ++c) { 4875 PetscScalar *cellCoords = NULL; 4876 PetscInt b, cdof; 4877 4878 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 4879 if (!cdof) continue; 4880 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4881 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 4882 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4883 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 4884 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4885 } 4886 } 4887 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4888 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4889 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 4890 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 4891 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 4892 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 4893 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 4894 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4895 PetscFunctionReturn(0); 4896 } 4897 4898 /*@ 4899 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 4900 4901 Collective on Vec v (see explanation below) 4902 4903 Input Parameters: 4904 + dm - The DM 4905 . v - The Vec of points 4906 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 4907 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 4908 4909 Output Parameter: 4910 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 4911 - cells - The PetscSF containing the ranks and local indices of the containing points. 4912 4913 4914 Level: developer 4915 4916 Notes: 4917 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 4918 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 4919 4920 If *cellSF is NULL on input, a PetscSF will be created. 4921 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 4922 4923 An array that maps each point to its containing cell can be obtained with 4924 4925 $ const PetscSFNode *cells; 4926 $ PetscInt nFound; 4927 $ const PetscSFNode *found; 4928 $ 4929 $ PetscSFGetGraph(cells,NULL,&nFound,&found,&cells); 4930 4931 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 4932 the index of the cell in its rank's local numbering. 4933 4934 .keywords: point location, mesh 4935 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 4936 @*/ 4937 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 4938 { 4939 PetscErrorCode ierr; 4940 4941 PetscFunctionBegin; 4942 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4943 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4944 PetscValidPointer(cellSF,4); 4945 if (*cellSF) { 4946 PetscMPIInt result; 4947 4948 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 4949 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 4950 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 4951 } else { 4952 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 4953 } 4954 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4955 if (dm->ops->locatepoints) { 4956 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 4957 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4958 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4959 PetscFunctionReturn(0); 4960 } 4961 4962 /*@ 4963 DMGetOutputDM - Retrieve the DM associated with the layout for output 4964 4965 Input Parameter: 4966 . dm - The original DM 4967 4968 Output Parameter: 4969 . odm - The DM which provides the layout for output 4970 4971 Level: intermediate 4972 4973 .seealso: VecView(), DMGetDefaultGlobalSection() 4974 @*/ 4975 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4976 { 4977 PetscSection section; 4978 PetscBool hasConstraints, ghasConstraints; 4979 PetscErrorCode ierr; 4980 4981 PetscFunctionBegin; 4982 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4983 PetscValidPointer(odm,2); 4984 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4985 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4986 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 4987 if (!ghasConstraints) { 4988 *odm = dm; 4989 PetscFunctionReturn(0); 4990 } 4991 if (!dm->dmBC) { 4992 PetscDS ds; 4993 PetscSection newSection, gsection; 4994 PetscSF sf; 4995 4996 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4997 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 4998 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 4999 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 5000 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 5001 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 5002 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 5003 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 5004 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 5005 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 5006 } 5007 *odm = dm->dmBC; 5008 PetscFunctionReturn(0); 5009 } 5010 5011 /*@ 5012 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 5013 5014 Input Parameter: 5015 . dm - The original DM 5016 5017 Output Parameters: 5018 + num - The output sequence number 5019 - val - The output sequence value 5020 5021 Level: intermediate 5022 5023 Note: This is intended for output that should appear in sequence, for instance 5024 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5025 5026 .seealso: VecView() 5027 @*/ 5028 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 5029 { 5030 PetscFunctionBegin; 5031 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5032 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 5033 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 5034 PetscFunctionReturn(0); 5035 } 5036 5037 /*@ 5038 DMSetOutputSequenceNumber - Set the sequence number/value for output 5039 5040 Input Parameters: 5041 + dm - The original DM 5042 . num - The output sequence number 5043 - val - The output sequence value 5044 5045 Level: intermediate 5046 5047 Note: This is intended for output that should appear in sequence, for instance 5048 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5049 5050 .seealso: VecView() 5051 @*/ 5052 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5053 { 5054 PetscFunctionBegin; 5055 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5056 dm->outputSequenceNum = num; 5057 dm->outputSequenceVal = val; 5058 PetscFunctionReturn(0); 5059 } 5060 5061 /*@C 5062 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5063 5064 Input Parameters: 5065 + dm - The original DM 5066 . name - The sequence name 5067 - num - The output sequence number 5068 5069 Output Parameter: 5070 . val - The output sequence value 5071 5072 Level: intermediate 5073 5074 Note: This is intended for output that should appear in sequence, for instance 5075 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5076 5077 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5078 @*/ 5079 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5080 { 5081 PetscBool ishdf5; 5082 PetscErrorCode ierr; 5083 5084 PetscFunctionBegin; 5085 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5086 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5087 PetscValidPointer(val,4); 5088 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5089 if (ishdf5) { 5090 #if defined(PETSC_HAVE_HDF5) 5091 PetscScalar value; 5092 5093 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 5094 *val = PetscRealPart(value); 5095 #endif 5096 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5097 PetscFunctionReturn(0); 5098 } 5099 5100 /*@ 5101 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5102 5103 Not collective 5104 5105 Input Parameter: 5106 . dm - The DM 5107 5108 Output Parameter: 5109 . useNatural - The flag to build the mapping to a natural order during distribution 5110 5111 Level: beginner 5112 5113 .seealso: DMSetUseNatural(), DMCreate() 5114 @*/ 5115 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5116 { 5117 PetscFunctionBegin; 5118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5119 PetscValidPointer(useNatural, 2); 5120 *useNatural = dm->useNatural; 5121 PetscFunctionReturn(0); 5122 } 5123 5124 /*@ 5125 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5126 5127 Collective on dm 5128 5129 Input Parameters: 5130 + dm - The DM 5131 - useNatural - The flag to build the mapping to a natural order during distribution 5132 5133 Level: beginner 5134 5135 .seealso: DMGetUseNatural(), DMCreate() 5136 @*/ 5137 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5138 { 5139 PetscFunctionBegin; 5140 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5141 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 5142 dm->useNatural = useNatural; 5143 PetscFunctionReturn(0); 5144 } 5145 5146 5147 /*@C 5148 DMCreateLabel - Create a label of the given name if it does not already exist 5149 5150 Not Collective 5151 5152 Input Parameters: 5153 + dm - The DM object 5154 - name - The label name 5155 5156 Level: intermediate 5157 5158 .keywords: mesh 5159 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5160 @*/ 5161 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5162 { 5163 DMLabelLink next = dm->labels->next; 5164 PetscBool flg = PETSC_FALSE; 5165 PetscErrorCode ierr; 5166 5167 PetscFunctionBegin; 5168 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5169 PetscValidCharPointer(name, 2); 5170 while (next) { 5171 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5172 if (flg) break; 5173 next = next->next; 5174 } 5175 if (!flg) { 5176 DMLabelLink tmpLabel; 5177 5178 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5179 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5180 tmpLabel->output = PETSC_TRUE; 5181 tmpLabel->next = dm->labels->next; 5182 dm->labels->next = tmpLabel; 5183 } 5184 PetscFunctionReturn(0); 5185 } 5186 5187 /*@C 5188 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5189 5190 Not Collective 5191 5192 Input Parameters: 5193 + dm - The DM object 5194 . name - The label name 5195 - point - The mesh point 5196 5197 Output Parameter: 5198 . value - The label value for this point, or -1 if the point is not in the label 5199 5200 Level: beginner 5201 5202 .keywords: mesh 5203 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5204 @*/ 5205 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5206 { 5207 DMLabel label; 5208 PetscErrorCode ierr; 5209 5210 PetscFunctionBegin; 5211 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5212 PetscValidCharPointer(name, 2); 5213 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5214 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 5215 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5216 PetscFunctionReturn(0); 5217 } 5218 5219 /*@C 5220 DMSetLabelValue - Add a point to a Sieve Label with given value 5221 5222 Not Collective 5223 5224 Input Parameters: 5225 + dm - The DM object 5226 . name - The label name 5227 . point - The mesh point 5228 - value - The label value for this point 5229 5230 Output Parameter: 5231 5232 Level: beginner 5233 5234 .keywords: mesh 5235 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5236 @*/ 5237 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5238 { 5239 DMLabel label; 5240 PetscErrorCode ierr; 5241 5242 PetscFunctionBegin; 5243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5244 PetscValidCharPointer(name, 2); 5245 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5246 if (!label) { 5247 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5248 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5249 } 5250 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5251 PetscFunctionReturn(0); 5252 } 5253 5254 /*@C 5255 DMClearLabelValue - Remove a point from a Sieve Label with given value 5256 5257 Not Collective 5258 5259 Input Parameters: 5260 + dm - The DM object 5261 . name - The label name 5262 . point - The mesh point 5263 - value - The label value for this point 5264 5265 Output Parameter: 5266 5267 Level: beginner 5268 5269 .keywords: mesh 5270 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5271 @*/ 5272 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5273 { 5274 DMLabel label; 5275 PetscErrorCode ierr; 5276 5277 PetscFunctionBegin; 5278 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5279 PetscValidCharPointer(name, 2); 5280 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5281 if (!label) PetscFunctionReturn(0); 5282 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5283 PetscFunctionReturn(0); 5284 } 5285 5286 /*@C 5287 DMGetLabelSize - Get the number of different integer ids in a Label 5288 5289 Not Collective 5290 5291 Input Parameters: 5292 + dm - The DM object 5293 - name - The label name 5294 5295 Output Parameter: 5296 . size - The number of different integer ids, or 0 if the label does not exist 5297 5298 Level: beginner 5299 5300 .keywords: mesh 5301 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5302 @*/ 5303 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5304 { 5305 DMLabel label; 5306 PetscErrorCode ierr; 5307 5308 PetscFunctionBegin; 5309 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5310 PetscValidCharPointer(name, 2); 5311 PetscValidPointer(size, 3); 5312 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5313 *size = 0; 5314 if (!label) PetscFunctionReturn(0); 5315 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5316 PetscFunctionReturn(0); 5317 } 5318 5319 /*@C 5320 DMGetLabelIdIS - Get the integer ids in a label 5321 5322 Not Collective 5323 5324 Input Parameters: 5325 + mesh - The DM object 5326 - name - The label name 5327 5328 Output Parameter: 5329 . ids - The integer ids, or NULL if the label does not exist 5330 5331 Level: beginner 5332 5333 .keywords: mesh 5334 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5335 @*/ 5336 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5337 { 5338 DMLabel label; 5339 PetscErrorCode ierr; 5340 5341 PetscFunctionBegin; 5342 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5343 PetscValidCharPointer(name, 2); 5344 PetscValidPointer(ids, 3); 5345 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5346 *ids = NULL; 5347 if (!label) PetscFunctionReturn(0); 5348 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5349 PetscFunctionReturn(0); 5350 } 5351 5352 /*@C 5353 DMGetStratumSize - Get the number of points in a label stratum 5354 5355 Not Collective 5356 5357 Input Parameters: 5358 + dm - The DM object 5359 . name - The label name 5360 - value - The stratum value 5361 5362 Output Parameter: 5363 . size - The stratum size 5364 5365 Level: beginner 5366 5367 .keywords: mesh 5368 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5369 @*/ 5370 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5371 { 5372 DMLabel label; 5373 PetscErrorCode ierr; 5374 5375 PetscFunctionBegin; 5376 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5377 PetscValidCharPointer(name, 2); 5378 PetscValidPointer(size, 4); 5379 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5380 *size = 0; 5381 if (!label) PetscFunctionReturn(0); 5382 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5383 PetscFunctionReturn(0); 5384 } 5385 5386 /*@C 5387 DMGetStratumIS - Get the points in a label stratum 5388 5389 Not Collective 5390 5391 Input Parameters: 5392 + dm - The DM object 5393 . name - The label name 5394 - value - The stratum value 5395 5396 Output Parameter: 5397 . points - The stratum points, or NULL if the label does not exist or does not have that value 5398 5399 Level: beginner 5400 5401 .keywords: mesh 5402 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5403 @*/ 5404 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5405 { 5406 DMLabel label; 5407 PetscErrorCode ierr; 5408 5409 PetscFunctionBegin; 5410 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5411 PetscValidCharPointer(name, 2); 5412 PetscValidPointer(points, 4); 5413 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5414 *points = NULL; 5415 if (!label) PetscFunctionReturn(0); 5416 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5417 PetscFunctionReturn(0); 5418 } 5419 5420 /*@C 5421 DMGetStratumIS - Set the points in a label stratum 5422 5423 Not Collective 5424 5425 Input Parameters: 5426 + dm - The DM object 5427 . name - The label name 5428 . value - The stratum value 5429 - points - The stratum points 5430 5431 Level: beginner 5432 5433 .keywords: mesh 5434 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 5435 @*/ 5436 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 5437 { 5438 DMLabel label; 5439 PetscErrorCode ierr; 5440 5441 PetscFunctionBegin; 5442 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5443 PetscValidCharPointer(name, 2); 5444 PetscValidPointer(points, 4); 5445 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5446 if (!label) PetscFunctionReturn(0); 5447 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 5448 PetscFunctionReturn(0); 5449 } 5450 5451 /*@C 5452 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5453 5454 Not Collective 5455 5456 Input Parameters: 5457 + dm - The DM object 5458 . name - The label name 5459 - value - The label value for this point 5460 5461 Output Parameter: 5462 5463 Level: beginner 5464 5465 .keywords: mesh 5466 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5467 @*/ 5468 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5469 { 5470 DMLabel label; 5471 PetscErrorCode ierr; 5472 5473 PetscFunctionBegin; 5474 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5475 PetscValidCharPointer(name, 2); 5476 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5477 if (!label) PetscFunctionReturn(0); 5478 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5479 PetscFunctionReturn(0); 5480 } 5481 5482 /*@ 5483 DMGetNumLabels - Return the number of labels defined by the mesh 5484 5485 Not Collective 5486 5487 Input Parameter: 5488 . dm - The DM object 5489 5490 Output Parameter: 5491 . numLabels - the number of Labels 5492 5493 Level: intermediate 5494 5495 .keywords: mesh 5496 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5497 @*/ 5498 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5499 { 5500 DMLabelLink next = dm->labels->next; 5501 PetscInt n = 0; 5502 5503 PetscFunctionBegin; 5504 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5505 PetscValidPointer(numLabels, 2); 5506 while (next) {++n; next = next->next;} 5507 *numLabels = n; 5508 PetscFunctionReturn(0); 5509 } 5510 5511 /*@C 5512 DMGetLabelName - Return the name of nth label 5513 5514 Not Collective 5515 5516 Input Parameters: 5517 + dm - The DM object 5518 - n - the label number 5519 5520 Output Parameter: 5521 . name - the label name 5522 5523 Level: intermediate 5524 5525 .keywords: mesh 5526 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5527 @*/ 5528 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5529 { 5530 DMLabelLink next = dm->labels->next; 5531 PetscInt l = 0; 5532 5533 PetscFunctionBegin; 5534 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5535 PetscValidPointer(name, 3); 5536 while (next) { 5537 if (l == n) { 5538 *name = next->label->name; 5539 PetscFunctionReturn(0); 5540 } 5541 ++l; 5542 next = next->next; 5543 } 5544 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5545 } 5546 5547 /*@C 5548 DMHasLabel - Determine whether the mesh has a label of a given name 5549 5550 Not Collective 5551 5552 Input Parameters: 5553 + dm - The DM object 5554 - name - The label name 5555 5556 Output Parameter: 5557 . hasLabel - PETSC_TRUE if the label is present 5558 5559 Level: intermediate 5560 5561 .keywords: mesh 5562 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5563 @*/ 5564 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5565 { 5566 DMLabelLink next = dm->labels->next; 5567 PetscErrorCode ierr; 5568 5569 PetscFunctionBegin; 5570 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5571 PetscValidCharPointer(name, 2); 5572 PetscValidPointer(hasLabel, 3); 5573 *hasLabel = PETSC_FALSE; 5574 while (next) { 5575 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5576 if (*hasLabel) break; 5577 next = next->next; 5578 } 5579 PetscFunctionReturn(0); 5580 } 5581 5582 /*@C 5583 DMGetLabel - Return the label of a given name, or NULL 5584 5585 Not Collective 5586 5587 Input Parameters: 5588 + dm - The DM object 5589 - name - The label name 5590 5591 Output Parameter: 5592 . label - The DMLabel, or NULL if the label is absent 5593 5594 Level: intermediate 5595 5596 .keywords: mesh 5597 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5598 @*/ 5599 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5600 { 5601 DMLabelLink next = dm->labels->next; 5602 PetscBool hasLabel; 5603 PetscErrorCode ierr; 5604 5605 PetscFunctionBegin; 5606 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5607 PetscValidCharPointer(name, 2); 5608 PetscValidPointer(label, 3); 5609 *label = NULL; 5610 while (next) { 5611 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5612 if (hasLabel) { 5613 *label = next->label; 5614 break; 5615 } 5616 next = next->next; 5617 } 5618 PetscFunctionReturn(0); 5619 } 5620 5621 /*@C 5622 DMGetLabelByNum - Return the nth label 5623 5624 Not Collective 5625 5626 Input Parameters: 5627 + dm - The DM object 5628 - n - the label number 5629 5630 Output Parameter: 5631 . label - the label 5632 5633 Level: intermediate 5634 5635 .keywords: mesh 5636 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5637 @*/ 5638 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5639 { 5640 DMLabelLink next = dm->labels->next; 5641 PetscInt l = 0; 5642 5643 PetscFunctionBegin; 5644 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5645 PetscValidPointer(label, 3); 5646 while (next) { 5647 if (l == n) { 5648 *label = next->label; 5649 PetscFunctionReturn(0); 5650 } 5651 ++l; 5652 next = next->next; 5653 } 5654 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5655 } 5656 5657 /*@C 5658 DMAddLabel - Add the label to this mesh 5659 5660 Not Collective 5661 5662 Input Parameters: 5663 + dm - The DM object 5664 - label - The DMLabel 5665 5666 Level: developer 5667 5668 .keywords: mesh 5669 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5670 @*/ 5671 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5672 { 5673 DMLabelLink tmpLabel; 5674 PetscBool hasLabel; 5675 PetscErrorCode ierr; 5676 5677 PetscFunctionBegin; 5678 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5679 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5680 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5681 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5682 tmpLabel->label = label; 5683 tmpLabel->output = PETSC_TRUE; 5684 tmpLabel->next = dm->labels->next; 5685 dm->labels->next = tmpLabel; 5686 PetscFunctionReturn(0); 5687 } 5688 5689 /*@C 5690 DMRemoveLabel - Remove the label from this mesh 5691 5692 Not Collective 5693 5694 Input Parameters: 5695 + dm - The DM object 5696 - name - The label name 5697 5698 Output Parameter: 5699 . label - The DMLabel, or NULL if the label is absent 5700 5701 Level: developer 5702 5703 .keywords: mesh 5704 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5705 @*/ 5706 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5707 { 5708 DMLabelLink next = dm->labels->next; 5709 DMLabelLink last = NULL; 5710 PetscBool hasLabel; 5711 PetscErrorCode ierr; 5712 5713 PetscFunctionBegin; 5714 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5715 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5716 *label = NULL; 5717 if (!hasLabel) PetscFunctionReturn(0); 5718 while (next) { 5719 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5720 if (hasLabel) { 5721 if (last) last->next = next->next; 5722 else dm->labels->next = next->next; 5723 next->next = NULL; 5724 *label = next->label; 5725 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5726 if (hasLabel) { 5727 dm->depthLabel = NULL; 5728 } 5729 ierr = PetscFree(next);CHKERRQ(ierr); 5730 break; 5731 } 5732 last = next; 5733 next = next->next; 5734 } 5735 PetscFunctionReturn(0); 5736 } 5737 5738 /*@C 5739 DMGetLabelOutput - Get the output flag for a given label 5740 5741 Not Collective 5742 5743 Input Parameters: 5744 + dm - The DM object 5745 - name - The label name 5746 5747 Output Parameter: 5748 . output - The flag for output 5749 5750 Level: developer 5751 5752 .keywords: mesh 5753 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5754 @*/ 5755 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5756 { 5757 DMLabelLink next = dm->labels->next; 5758 PetscErrorCode ierr; 5759 5760 PetscFunctionBegin; 5761 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5762 PetscValidPointer(name, 2); 5763 PetscValidPointer(output, 3); 5764 while (next) { 5765 PetscBool flg; 5766 5767 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5768 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5769 next = next->next; 5770 } 5771 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5772 } 5773 5774 /*@C 5775 DMSetLabelOutput - Set the output flag for a given label 5776 5777 Not Collective 5778 5779 Input Parameters: 5780 + dm - The DM object 5781 . name - The label name 5782 - output - The flag for output 5783 5784 Level: developer 5785 5786 .keywords: mesh 5787 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5788 @*/ 5789 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5790 { 5791 DMLabelLink next = dm->labels->next; 5792 PetscErrorCode ierr; 5793 5794 PetscFunctionBegin; 5795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5796 PetscValidPointer(name, 2); 5797 while (next) { 5798 PetscBool flg; 5799 5800 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5801 if (flg) {next->output = output; PetscFunctionReturn(0);} 5802 next = next->next; 5803 } 5804 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5805 } 5806 5807 5808 /*@ 5809 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5810 5811 Collective on DM 5812 5813 Input Parameter: 5814 . dmA - The DM object with initial labels 5815 5816 Output Parameter: 5817 . dmB - The DM object with copied labels 5818 5819 Level: intermediate 5820 5821 Note: This is typically used when interpolating or otherwise adding to a mesh 5822 5823 .keywords: mesh 5824 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5825 @*/ 5826 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5827 { 5828 PetscInt numLabels, l; 5829 PetscErrorCode ierr; 5830 5831 PetscFunctionBegin; 5832 if (dmA == dmB) PetscFunctionReturn(0); 5833 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5834 for (l = 0; l < numLabels; ++l) { 5835 DMLabel label, labelNew; 5836 const char *name; 5837 PetscBool flg; 5838 5839 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5840 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5841 if (flg) continue; 5842 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5843 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5844 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5845 } 5846 PetscFunctionReturn(0); 5847 } 5848 5849 /*@ 5850 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5851 5852 Input Parameter: 5853 . dm - The DM object 5854 5855 Output Parameter: 5856 . cdm - The coarse DM 5857 5858 Level: intermediate 5859 5860 .seealso: DMSetCoarseDM() 5861 @*/ 5862 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5863 { 5864 PetscFunctionBegin; 5865 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5866 PetscValidPointer(cdm, 2); 5867 *cdm = dm->coarseMesh; 5868 PetscFunctionReturn(0); 5869 } 5870 5871 /*@ 5872 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5873 5874 Input Parameters: 5875 + dm - The DM object 5876 - cdm - The coarse DM 5877 5878 Level: intermediate 5879 5880 .seealso: DMGetCoarseDM() 5881 @*/ 5882 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5883 { 5884 PetscErrorCode ierr; 5885 5886 PetscFunctionBegin; 5887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5888 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5889 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5890 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5891 dm->coarseMesh = cdm; 5892 PetscFunctionReturn(0); 5893 } 5894 5895 /*@ 5896 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 5897 5898 Input Parameter: 5899 . dm - The DM object 5900 5901 Output Parameter: 5902 . fdm - The fine DM 5903 5904 Level: intermediate 5905 5906 .seealso: DMSetFineDM() 5907 @*/ 5908 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 5909 { 5910 PetscFunctionBegin; 5911 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5912 PetscValidPointer(fdm, 2); 5913 *fdm = dm->fineMesh; 5914 PetscFunctionReturn(0); 5915 } 5916 5917 /*@ 5918 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 5919 5920 Input Parameters: 5921 + dm - The DM object 5922 - fdm - The fine DM 5923 5924 Level: intermediate 5925 5926 .seealso: DMGetFineDM() 5927 @*/ 5928 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 5929 { 5930 PetscErrorCode ierr; 5931 5932 PetscFunctionBegin; 5933 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5934 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 5935 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 5936 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 5937 dm->fineMesh = fdm; 5938 PetscFunctionReturn(0); 5939 } 5940 5941 /*=== DMBoundary code ===*/ 5942 5943 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 5944 { 5945 PetscErrorCode ierr; 5946 5947 PetscFunctionBegin; 5948 ierr = PetscDSCopyBoundary(dm->prob,dmNew->prob);CHKERRQ(ierr); 5949 PetscFunctionReturn(0); 5950 } 5951 5952 /*@C 5953 DMAddBoundary - Add a boundary condition to the model 5954 5955 Input Parameters: 5956 + dm - The DM, with a PetscDS that matches the problem being constrained 5957 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 5958 . name - The BC name 5959 . labelname - The label defining constrained points 5960 . field - The field to constrain 5961 . numcomps - The number of constrained field components 5962 . comps - An array of constrained component numbers 5963 . bcFunc - A pointwise function giving boundary values 5964 . numids - The number of DMLabel ids for constrained points 5965 . ids - An array of ids for constrained points 5966 - ctx - An optional user context for bcFunc 5967 5968 Options Database Keys: 5969 + -bc_<boundary name> <num> - Overrides the boundary ids 5970 - -bc_<boundary name>_comp <num> - Overrides the boundary components 5971 5972 Level: developer 5973 5974 .seealso: DMGetBoundary() 5975 @*/ 5976 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) 5977 { 5978 PetscErrorCode ierr; 5979 5980 PetscFunctionBegin; 5981 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5982 ierr = PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);CHKERRQ(ierr); 5983 PetscFunctionReturn(0); 5984 } 5985 5986 /*@ 5987 DMGetNumBoundary - Get the number of registered BC 5988 5989 Input Parameters: 5990 . dm - The mesh object 5991 5992 Output Parameters: 5993 . numBd - The number of BC 5994 5995 Level: intermediate 5996 5997 .seealso: DMAddBoundary(), DMGetBoundary() 5998 @*/ 5999 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6000 { 6001 PetscErrorCode ierr; 6002 6003 PetscFunctionBegin; 6004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6005 ierr = PetscDSGetNumBoundary(dm->prob,numBd);CHKERRQ(ierr); 6006 PetscFunctionReturn(0); 6007 } 6008 6009 /*@C 6010 DMGetBoundary - Get a model boundary condition 6011 6012 Input Parameters: 6013 + dm - The mesh object 6014 - bd - The BC number 6015 6016 Output Parameters: 6017 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6018 . name - The BC name 6019 . labelname - The label defining constrained points 6020 . field - The field to constrain 6021 . numcomps - The number of constrained field components 6022 . comps - An array of constrained component numbers 6023 . bcFunc - A pointwise function giving boundary values 6024 . numids - The number of DMLabel ids for constrained points 6025 . ids - An array of ids for constrained points 6026 - ctx - An optional user context for bcFunc 6027 6028 Options Database Keys: 6029 + -bc_<boundary name> <num> - Overrides the boundary ids 6030 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6031 6032 Level: developer 6033 6034 .seealso: DMAddBoundary() 6035 @*/ 6036 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) 6037 { 6038 PetscErrorCode ierr; 6039 6040 PetscFunctionBegin; 6041 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6042 ierr = PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);CHKERRQ(ierr); 6043 PetscFunctionReturn(0); 6044 } 6045 6046 static PetscErrorCode DMPopulateBoundary(DM dm) 6047 { 6048 DMBoundary *lastnext; 6049 DSBoundary dsbound; 6050 PetscErrorCode ierr; 6051 6052 PetscFunctionBegin; 6053 dsbound = dm->prob->boundary; 6054 if (dm->boundary) { 6055 DMBoundary next = dm->boundary; 6056 6057 /* quick check to see if the PetscDS has changed */ 6058 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 6059 /* the PetscDS has changed: tear down and rebuild */ 6060 while (next) { 6061 DMBoundary b = next; 6062 6063 next = b->next; 6064 ierr = PetscFree(b);CHKERRQ(ierr); 6065 } 6066 dm->boundary = NULL; 6067 } 6068 6069 lastnext = &(dm->boundary); 6070 while (dsbound) { 6071 DMBoundary dmbound; 6072 6073 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 6074 dmbound->dsboundary = dsbound; 6075 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 6076 if (!dmbound->label) PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr); 6077 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 6078 *lastnext = dmbound; 6079 lastnext = &(dmbound->next); 6080 dsbound = dsbound->next; 6081 } 6082 PetscFunctionReturn(0); 6083 } 6084 6085 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6086 { 6087 DMBoundary b; 6088 PetscErrorCode ierr; 6089 6090 PetscFunctionBegin; 6091 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6092 PetscValidPointer(isBd, 3); 6093 *isBd = PETSC_FALSE; 6094 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 6095 b = dm->boundary; 6096 while (b && !(*isBd)) { 6097 DMLabel label = b->label; 6098 DSBoundary dsb = b->dsboundary; 6099 6100 if (label) { 6101 PetscInt i; 6102 6103 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 6104 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 6105 } 6106 } 6107 b = b->next; 6108 } 6109 PetscFunctionReturn(0); 6110 } 6111 6112 /*@C 6113 DMProjectFunction - This projects the given function into the function space provided. 6114 6115 Input Parameters: 6116 + dm - The DM 6117 . time - The time 6118 . funcs - The coordinate functions to evaluate, one per field 6119 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6120 - mode - The insertion mode for values 6121 6122 Output Parameter: 6123 . X - vector 6124 6125 Calling sequence of func: 6126 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6127 6128 + dim - The spatial dimension 6129 . x - The coordinates 6130 . Nf - The number of fields 6131 . u - The output field values 6132 - ctx - optional user-defined function context 6133 6134 Level: developer 6135 6136 .seealso: DMComputeL2Diff() 6137 @*/ 6138 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6139 { 6140 Vec localX; 6141 PetscErrorCode ierr; 6142 6143 PetscFunctionBegin; 6144 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6145 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6146 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6147 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6148 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6149 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6150 PetscFunctionReturn(0); 6151 } 6152 6153 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6154 { 6155 PetscErrorCode ierr; 6156 6157 PetscFunctionBegin; 6158 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6159 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6160 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6161 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6162 PetscFunctionReturn(0); 6163 } 6164 6165 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) 6166 { 6167 Vec localX; 6168 PetscErrorCode ierr; 6169 6170 PetscFunctionBegin; 6171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6172 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6173 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6174 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6175 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6176 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6177 PetscFunctionReturn(0); 6178 } 6179 6180 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) 6181 { 6182 PetscErrorCode ierr; 6183 6184 PetscFunctionBegin; 6185 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6186 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6187 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6188 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6189 PetscFunctionReturn(0); 6190 } 6191 6192 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 6193 void (**funcs)(PetscInt, PetscInt, PetscInt, 6194 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6195 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6196 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6197 InsertMode mode, Vec localX) 6198 { 6199 PetscErrorCode ierr; 6200 6201 PetscFunctionBegin; 6202 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6203 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 6204 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 6205 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6206 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 6207 PetscFunctionReturn(0); 6208 } 6209 6210 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 6211 void (**funcs)(PetscInt, PetscInt, PetscInt, 6212 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6213 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6214 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6215 InsertMode mode, Vec localX) 6216 { 6217 PetscErrorCode ierr; 6218 6219 PetscFunctionBegin; 6220 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6221 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 6222 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 6223 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6224 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 6225 PetscFunctionReturn(0); 6226 } 6227 6228 /*@C 6229 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6230 6231 Input Parameters: 6232 + dm - The DM 6233 . time - The time 6234 . funcs - The functions to evaluate for each field component 6235 . ctxs - Optional array of contexts to pass to each function, or NULL. 6236 - X - The coefficient vector u_h, a global vector 6237 6238 Output Parameter: 6239 . diff - The diff ||u - u_h||_2 6240 6241 Level: developer 6242 6243 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6244 @*/ 6245 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6246 { 6247 PetscErrorCode ierr; 6248 6249 PetscFunctionBegin; 6250 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6251 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6252 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 6253 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6254 PetscFunctionReturn(0); 6255 } 6256 6257 /*@C 6258 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6259 6260 Input Parameters: 6261 + dm - The DM 6262 , time - The time 6263 . funcs - The gradient functions to evaluate for each field component 6264 . ctxs - Optional array of contexts to pass to each function, or NULL. 6265 . X - The coefficient vector u_h, a global vector 6266 - n - The vector to project along 6267 6268 Output Parameter: 6269 . diff - The diff ||(grad u - grad u_h) . n||_2 6270 6271 Level: developer 6272 6273 .seealso: DMProjectFunction(), DMComputeL2Diff() 6274 @*/ 6275 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) 6276 { 6277 PetscErrorCode ierr; 6278 6279 PetscFunctionBegin; 6280 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6281 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6282 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6283 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6284 PetscFunctionReturn(0); 6285 } 6286 6287 /*@C 6288 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6289 6290 Input Parameters: 6291 + dm - The DM 6292 . time - The time 6293 . funcs - The functions to evaluate for each field component 6294 . ctxs - Optional array of contexts to pass to each function, or NULL. 6295 - X - The coefficient vector u_h, a global vector 6296 6297 Output Parameter: 6298 . diff - The array of differences, ||u^f - u^f_h||_2 6299 6300 Level: developer 6301 6302 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6303 @*/ 6304 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6305 { 6306 PetscErrorCode ierr; 6307 6308 PetscFunctionBegin; 6309 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6310 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6311 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6312 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6313 PetscFunctionReturn(0); 6314 } 6315 6316 /*@C 6317 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 6318 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 6319 6320 Collective on dm 6321 6322 Input parameters: 6323 + dm - the pre-adaptation DM object 6324 - label - label with the flags 6325 6326 Output parameters: 6327 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 6328 6329 Level: intermediate 6330 6331 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 6332 @*/ 6333 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 6334 { 6335 PetscErrorCode ierr; 6336 6337 PetscFunctionBegin; 6338 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6339 PetscValidPointer(label,2); 6340 PetscValidPointer(dmAdapt,3); 6341 *dmAdapt = NULL; 6342 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 6343 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 6344 PetscFunctionReturn(0); 6345 } 6346 6347 /*@C 6348 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 6349 6350 Input Parameters: 6351 + dm - The DM object 6352 . metric - The metric to which the mesh is adapted, defined vertex-wise. 6353 - 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_". 6354 6355 Output Parameter: 6356 . dmAdapt - Pointer to the DM object containing the adapted mesh 6357 6358 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 6359 6360 Level: advanced 6361 6362 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 6363 @*/ 6364 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 6365 { 6366 PetscErrorCode ierr; 6367 6368 PetscFunctionBegin; 6369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6370 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 6371 if (bdLabel) PetscValidPointer(bdLabel, 3); 6372 PetscValidPointer(dmAdapt, 4); 6373 *dmAdapt = NULL; 6374 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 6375 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 6376 PetscFunctionReturn(0); 6377 } 6378 6379 /*@C 6380 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6381 6382 Not Collective 6383 6384 Input Parameter: 6385 . dm - The DM 6386 6387 Output Parameter: 6388 . nranks - the number of neighbours 6389 . ranks - the neighbors ranks 6390 6391 Notes: 6392 Do not free the array, it is freed when the DM is destroyed. 6393 6394 Level: beginner 6395 6396 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6397 @*/ 6398 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6399 { 6400 PetscErrorCode ierr; 6401 6402 PetscFunctionBegin; 6403 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6404 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 6405 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6406 PetscFunctionReturn(0); 6407 } 6408 6409 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 6410 6411 /* 6412 Converts the input vector to a ghosted vector and then calls the standard coloring code. 6413 This has be a different function because it requires DM which is not defined in the Mat library 6414 */ 6415 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 6416 { 6417 PetscErrorCode ierr; 6418 6419 PetscFunctionBegin; 6420 if (coloring->ctype == IS_COLORING_LOCAL) { 6421 Vec x1local; 6422 DM dm; 6423 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6424 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 6425 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 6426 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6427 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6428 x1 = x1local; 6429 } 6430 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 6431 if (coloring->ctype == IS_COLORING_LOCAL) { 6432 DM dm; 6433 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6434 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 6435 } 6436 PetscFunctionReturn(0); 6437 } 6438 6439 /*@ 6440 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 6441 6442 Input Parameter: 6443 . coloring - the MatFDColoring object 6444 6445 Developer Notes: this routine exists because the PETSc Mat library does not know about the DM objects 6446 6447 Level: advanced 6448 6449 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 6450 @*/ 6451 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 6452 { 6453 PetscFunctionBegin; 6454 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 6455 PetscFunctionReturn(0); 6456 } 6457