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