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