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