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