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