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