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