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