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