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