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