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