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