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