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