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