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