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