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 = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 4906 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 4907 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 4908 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 4909 4910 ierr = PetscDSCreate(comm, &prob);CHKERRQ(ierr); 4911 ierr = DMSetRegionDS(dm, NULL, fields, prob);CHKERRQ(ierr); 4912 ierr = PetscDSDestroy(&prob);CHKERRQ(ierr); 4913 ierr = ISDestroy(&fields);CHKERRQ(ierr); 4914 ierr = DMGetRegionDS(dm, NULL, NULL, &prob);CHKERRQ(ierr); 4915 } 4916 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 4917 /* Optionally create hybrid DS */ 4918 for (f = 0; f < Nf; ++f) { 4919 DMLabel label = dm->fields[f].label; 4920 PetscInt lStart, lEnd; 4921 4922 if (label) { 4923 DM plex; 4924 PetscInt depth, pMax[4]; 4925 4926 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 4927 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 4928 ierr = DMPlexGetHybridBounds(plex, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 4929 ierr = DMDestroy(&plex);CHKERRQ(ierr); 4930 4931 ierr = DMLabelGetBounds(label, &lStart, &lEnd);CHKERRQ(ierr); 4932 if (lStart < pMax[depth]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support labels over hybrid cells right now"); 4933 ierr = PetscDSCreate(comm, &probh);CHKERRQ(ierr); 4934 ierr = DMSetRegionDS(dm, label, NULL, probh);CHKERRQ(ierr); 4935 ierr = PetscDSSetHybrid(probh, PETSC_TRUE);CHKERRQ(ierr); 4936 ierr = PetscDSSetCoordinateDimension(probh, dimEmbed);CHKERRQ(ierr); 4937 break; 4938 } 4939 } 4940 /* Set fields in DSes */ 4941 for (f = 0; f < Nf; ++f) { 4942 DMLabel label = dm->fields[f].label; 4943 PetscObject disc = dm->fields[f].disc; 4944 4945 if (!label) { 4946 ierr = PetscDSSetDiscretization(prob, field++, disc);CHKERRQ(ierr); 4947 if (probh) { 4948 PetscFE subfe; 4949 4950 ierr = PetscFEGetHeightSubspace((PetscFE) disc, 1, &subfe);CHKERRQ(ierr); 4951 ierr = PetscDSSetDiscretization(probh, fieldh++, (PetscObject) subfe);CHKERRQ(ierr); 4952 } 4953 } else { 4954 ierr = PetscDSSetDiscretization(probh, fieldh++, disc);CHKERRQ(ierr); 4955 } 4956 /* We allow people to have placeholder fields and construct the Section by hand */ 4957 { 4958 PetscClassId id; 4959 4960 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 4961 if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE; 4962 } 4963 } 4964 ierr = PetscDSDestroy(&probh);CHKERRQ(ierr); 4965 /* Setup DSes */ 4966 if (doSetup) { 4967 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);} 4968 } 4969 PetscFunctionReturn(0); 4970 } 4971 4972 /*@ 4973 DMCopyDS - Copy the discrete systems for the DM into another DM 4974 4975 Collective on DM 4976 4977 Input Parameter: 4978 . dm - The DM 4979 4980 Output Parameter: 4981 . newdm - The DM 4982 4983 Level: advanced 4984 4985 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 4986 @*/ 4987 PetscErrorCode DMCopyDS(DM dm, DM newdm) 4988 { 4989 PetscInt Nds, s; 4990 PetscErrorCode ierr; 4991 4992 PetscFunctionBegin; 4993 if (dm == newdm) PetscFunctionReturn(0); 4994 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 4995 ierr = DMClearDS(newdm);CHKERRQ(ierr); 4996 for (s = 0; s < Nds; ++s) { 4997 DMLabel label; 4998 IS fields; 4999 PetscDS ds; 5000 5001 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5002 ierr = DMSetRegionDS(newdm, label, fields, ds);CHKERRQ(ierr); 5003 } 5004 PetscFunctionReturn(0); 5005 } 5006 5007 /*@ 5008 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 5009 5010 Collective on DM 5011 5012 Input Parameter: 5013 . dm - The DM 5014 5015 Output Parameter: 5016 . newdm - The DM 5017 5018 Level: advanced 5019 5020 .seealso: DMCopyFields(), DMCopyDS() 5021 @*/ 5022 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 5023 { 5024 PetscErrorCode ierr; 5025 5026 PetscFunctionBegin; 5027 if (dm == newdm) PetscFunctionReturn(0); 5028 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 5029 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 5030 PetscFunctionReturn(0); 5031 } 5032 5033 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 5034 { 5035 DM dm_coord,dmc_coord; 5036 PetscErrorCode ierr; 5037 Vec coords,ccoords; 5038 Mat inject; 5039 PetscFunctionBegin; 5040 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5041 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 5042 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5043 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 5044 if (coords && !ccoords) { 5045 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 5046 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5047 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 5048 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 5049 ierr = MatDestroy(&inject);CHKERRQ(ierr); 5050 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 5051 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5052 } 5053 PetscFunctionReturn(0); 5054 } 5055 5056 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 5057 { 5058 DM dm_coord,subdm_coord; 5059 PetscErrorCode ierr; 5060 Vec coords,ccoords,clcoords; 5061 VecScatter *scat_i,*scat_g; 5062 PetscFunctionBegin; 5063 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5064 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 5065 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5066 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 5067 if (coords && !ccoords) { 5068 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 5069 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5070 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 5071 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 5072 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 5073 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5074 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5075 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5076 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5077 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 5078 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 5079 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 5080 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 5081 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5082 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 5083 ierr = PetscFree(scat_i);CHKERRQ(ierr); 5084 ierr = PetscFree(scat_g);CHKERRQ(ierr); 5085 } 5086 PetscFunctionReturn(0); 5087 } 5088 5089 /*@ 5090 DMGetDimension - Return the topological dimension of the DM 5091 5092 Not collective 5093 5094 Input Parameter: 5095 . dm - The DM 5096 5097 Output Parameter: 5098 . dim - The topological dimension 5099 5100 Level: beginner 5101 5102 .seealso: DMSetDimension(), DMCreate() 5103 @*/ 5104 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 5105 { 5106 PetscFunctionBegin; 5107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5108 PetscValidPointer(dim, 2); 5109 *dim = dm->dim; 5110 PetscFunctionReturn(0); 5111 } 5112 5113 /*@ 5114 DMSetDimension - Set the topological dimension of the DM 5115 5116 Collective on dm 5117 5118 Input Parameters: 5119 + dm - The DM 5120 - dim - The topological dimension 5121 5122 Level: beginner 5123 5124 .seealso: DMGetDimension(), DMCreate() 5125 @*/ 5126 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 5127 { 5128 PetscDS ds; 5129 PetscErrorCode ierr; 5130 5131 PetscFunctionBegin; 5132 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5133 PetscValidLogicalCollectiveInt(dm, dim, 2); 5134 dm->dim = dim; 5135 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5136 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dm->dim);CHKERRQ(ierr);} 5137 PetscFunctionReturn(0); 5138 } 5139 5140 /*@ 5141 DMGetDimPoints - Get the half-open interval for all points of a given dimension 5142 5143 Collective on DM 5144 5145 Input Parameters: 5146 + dm - the DM 5147 - dim - the dimension 5148 5149 Output Parameters: 5150 + pStart - The first point of the given dimension 5151 . pEnd - The first point following points of the given dimension 5152 5153 Note: 5154 The points are vertices in the Hasse diagram encoding the topology. This is explained in 5155 http://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 5156 then the interval is empty. 5157 5158 Level: intermediate 5159 5160 .keywords: point, Hasse Diagram, dimension 5161 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 5162 @*/ 5163 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5164 { 5165 PetscInt d; 5166 PetscErrorCode ierr; 5167 5168 PetscFunctionBegin; 5169 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5170 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 5171 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 5172 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 5173 PetscFunctionReturn(0); 5174 } 5175 5176 /*@ 5177 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 5178 5179 Collective on DM 5180 5181 Input Parameters: 5182 + dm - the DM 5183 - c - coordinate vector 5184 5185 Notes: 5186 The coordinates do include those for ghost points, which are in the local vector. 5187 5188 The vector c should be destroyed by the caller. 5189 5190 Level: intermediate 5191 5192 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5193 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5194 @*/ 5195 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 5196 { 5197 PetscErrorCode ierr; 5198 5199 PetscFunctionBegin; 5200 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5201 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5202 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5203 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5204 dm->coordinates = c; 5205 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5206 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5207 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5208 PetscFunctionReturn(0); 5209 } 5210 5211 /*@ 5212 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 5213 5214 Not collective 5215 5216 Input Parameters: 5217 + dm - the DM 5218 - c - coordinate vector 5219 5220 Notes: 5221 The coordinates of ghost points can be set using DMSetCoordinates() 5222 followed by DMGetCoordinatesLocal(). This is intended to enable the 5223 setting of ghost coordinates outside of the domain. 5224 5225 The vector c should be destroyed by the caller. 5226 5227 Level: intermediate 5228 5229 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5230 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 5231 @*/ 5232 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 5233 { 5234 PetscErrorCode ierr; 5235 5236 PetscFunctionBegin; 5237 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5238 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5239 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5240 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5241 5242 dm->coordinatesLocal = c; 5243 5244 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5245 PetscFunctionReturn(0); 5246 } 5247 5248 /*@ 5249 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 5250 5251 Collective on DM 5252 5253 Input Parameter: 5254 . dm - the DM 5255 5256 Output Parameter: 5257 . c - global coordinate vector 5258 5259 Note: 5260 This is a borrowed reference, so the user should NOT destroy this vector 5261 5262 Each process has only the local coordinates (does NOT have the ghost coordinates). 5263 5264 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5265 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5266 5267 Level: intermediate 5268 5269 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5270 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5271 @*/ 5272 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 5273 { 5274 PetscErrorCode ierr; 5275 5276 PetscFunctionBegin; 5277 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5278 PetscValidPointer(c,2); 5279 if (!dm->coordinates && dm->coordinatesLocal) { 5280 DM cdm = NULL; 5281 PetscBool localized; 5282 5283 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5284 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 5285 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5286 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 5287 if (localized) { 5288 PetscInt cdim; 5289 5290 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5291 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5292 } 5293 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 5294 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5295 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5296 } 5297 *c = dm->coordinates; 5298 PetscFunctionReturn(0); 5299 } 5300 5301 /*@ 5302 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 5303 5304 Collective on DM 5305 5306 Input Parameter: 5307 . dm - the DM 5308 5309 Level: advanced 5310 5311 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5312 .seealso: DMGetCoordinatesLocalNoncollective() 5313 @*/ 5314 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 5315 { 5316 PetscErrorCode ierr; 5317 5318 PetscFunctionBegin; 5319 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5320 if (!dm->coordinatesLocal && dm->coordinates) { 5321 DM cdm = NULL; 5322 PetscBool localized; 5323 5324 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5325 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 5326 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5327 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 5328 if (localized) { 5329 PetscInt cdim; 5330 5331 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5332 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5333 } 5334 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 5335 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5336 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5337 } 5338 PetscFunctionReturn(0); 5339 } 5340 5341 /*@ 5342 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 5343 5344 Collective on DM 5345 5346 Input Parameter: 5347 . dm - the DM 5348 5349 Output Parameter: 5350 . c - coordinate vector 5351 5352 Note: 5353 This is a borrowed reference, so the user should NOT destroy this vector 5354 5355 Each process has the local and ghost coordinates 5356 5357 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5358 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5359 5360 Level: intermediate 5361 5362 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5363 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 5364 @*/ 5365 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 5366 { 5367 PetscErrorCode ierr; 5368 5369 PetscFunctionBegin; 5370 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5371 PetscValidPointer(c,2); 5372 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 5373 *c = dm->coordinatesLocal; 5374 PetscFunctionReturn(0); 5375 } 5376 5377 /*@ 5378 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 5379 5380 Not collective 5381 5382 Input Parameter: 5383 . dm - the DM 5384 5385 Output Parameter: 5386 . c - coordinate vector 5387 5388 Level: advanced 5389 5390 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5391 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5392 @*/ 5393 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 5394 { 5395 PetscFunctionBegin; 5396 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5397 PetscValidPointer(c,2); 5398 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 5399 *c = dm->coordinatesLocal; 5400 PetscFunctionReturn(0); 5401 } 5402 5403 /*@ 5404 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 5405 5406 Not collective 5407 5408 Input Parameter: 5409 + dm - the DM 5410 - p - the IS of points whose coordinates will be returned 5411 5412 Output Parameter: 5413 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 5414 - pCoord - the Vec with coordinates of points in p 5415 5416 Note: 5417 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 5418 5419 This creates a new vector, so the user SHOULD destroy this vector 5420 5421 Each process has the local and ghost coordinates 5422 5423 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5424 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5425 5426 Level: advanced 5427 5428 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5429 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5430 @*/ 5431 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 5432 { 5433 PetscSection cs, newcs; 5434 Vec coords; 5435 const PetscScalar *arr; 5436 PetscScalar *newarr=NULL; 5437 PetscInt n; 5438 PetscErrorCode ierr; 5439 5440 PetscFunctionBegin; 5441 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5442 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 5443 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 5444 if (pCoord) PetscValidPointer(pCoord, 4); 5445 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 5446 if (!dm->coordinateDM || !dm->coordinateDM->defaultSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 5447 cs = dm->coordinateDM->defaultSection; 5448 coords = dm->coordinatesLocal; 5449 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 5450 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 5451 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 5452 if (pCoord) { 5453 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 5454 /* set array in two steps to mimic PETSC_OWN_POINTER */ 5455 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 5456 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 5457 } else { 5458 ierr = PetscFree(newarr);CHKERRQ(ierr); 5459 } 5460 if (pCoordSection) {*pCoordSection = newcs;} 5461 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 5462 PetscFunctionReturn(0); 5463 } 5464 5465 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 5466 { 5467 PetscErrorCode ierr; 5468 5469 PetscFunctionBegin; 5470 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5471 PetscValidPointer(field,2); 5472 if (!dm->coordinateField) { 5473 if (dm->ops->createcoordinatefield) { 5474 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 5475 } 5476 } 5477 *field = dm->coordinateField; 5478 PetscFunctionReturn(0); 5479 } 5480 5481 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 5482 { 5483 PetscErrorCode ierr; 5484 5485 PetscFunctionBegin; 5486 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5487 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 5488 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 5489 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 5490 dm->coordinateField = field; 5491 PetscFunctionReturn(0); 5492 } 5493 5494 /*@ 5495 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 5496 5497 Collective on DM 5498 5499 Input Parameter: 5500 . dm - the DM 5501 5502 Output Parameter: 5503 . cdm - coordinate DM 5504 5505 Level: intermediate 5506 5507 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5508 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5509 @*/ 5510 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 5511 { 5512 PetscErrorCode ierr; 5513 5514 PetscFunctionBegin; 5515 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5516 PetscValidPointer(cdm,2); 5517 if (!dm->coordinateDM) { 5518 DM cdm; 5519 5520 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 5521 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 5522 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 5523 * until the call to CreateCoordinateDM) */ 5524 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5525 dm->coordinateDM = cdm; 5526 } 5527 *cdm = dm->coordinateDM; 5528 PetscFunctionReturn(0); 5529 } 5530 5531 /*@ 5532 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 5533 5534 Logically Collective on DM 5535 5536 Input Parameters: 5537 + dm - the DM 5538 - cdm - coordinate DM 5539 5540 Level: intermediate 5541 5542 .keywords: distributed array, get, corners, nodes, local indices, coordinates 5543 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5544 @*/ 5545 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 5546 { 5547 PetscErrorCode ierr; 5548 5549 PetscFunctionBegin; 5550 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5551 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 5552 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5553 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5554 dm->coordinateDM = cdm; 5555 PetscFunctionReturn(0); 5556 } 5557 5558 /*@ 5559 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 5560 5561 Not Collective 5562 5563 Input Parameter: 5564 . dm - The DM object 5565 5566 Output Parameter: 5567 . dim - The embedding dimension 5568 5569 Level: intermediate 5570 5571 .keywords: mesh, coordinates 5572 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetSection(), DMSetSection() 5573 @*/ 5574 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 5575 { 5576 PetscFunctionBegin; 5577 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5578 PetscValidPointer(dim, 2); 5579 if (dm->dimEmbed == PETSC_DEFAULT) { 5580 dm->dimEmbed = dm->dim; 5581 } 5582 *dim = dm->dimEmbed; 5583 PetscFunctionReturn(0); 5584 } 5585 5586 /*@ 5587 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 5588 5589 Not Collective 5590 5591 Input Parameters: 5592 + dm - The DM object 5593 - dim - The embedding dimension 5594 5595 Level: intermediate 5596 5597 .keywords: mesh, coordinates 5598 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetSection(), DMSetSection() 5599 @*/ 5600 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 5601 { 5602 PetscDS ds; 5603 PetscErrorCode ierr; 5604 5605 PetscFunctionBegin; 5606 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5607 dm->dimEmbed = dim; 5608 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5609 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 5610 PetscFunctionReturn(0); 5611 } 5612 5613 /*@ 5614 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 5615 5616 Collective on DM 5617 5618 Input Parameter: 5619 . dm - The DM object 5620 5621 Output Parameter: 5622 . section - The PetscSection object 5623 5624 Level: intermediate 5625 5626 .keywords: mesh, coordinates 5627 .seealso: DMGetCoordinateDM(), DMGetSection(), DMSetSection() 5628 @*/ 5629 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 5630 { 5631 DM cdm; 5632 PetscErrorCode ierr; 5633 5634 PetscFunctionBegin; 5635 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5636 PetscValidPointer(section, 2); 5637 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5638 ierr = DMGetSection(cdm, section);CHKERRQ(ierr); 5639 PetscFunctionReturn(0); 5640 } 5641 5642 /*@ 5643 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 5644 5645 Not Collective 5646 5647 Input Parameters: 5648 + dm - The DM object 5649 . dim - The embedding dimension, or PETSC_DETERMINE 5650 - section - The PetscSection object 5651 5652 Level: intermediate 5653 5654 .keywords: mesh, coordinates 5655 .seealso: DMGetCoordinateSection(), DMGetSection(), DMSetSection() 5656 @*/ 5657 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 5658 { 5659 DM cdm; 5660 PetscErrorCode ierr; 5661 5662 PetscFunctionBegin; 5663 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5664 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 5665 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5666 ierr = DMSetSection(cdm, section);CHKERRQ(ierr); 5667 if (dim == PETSC_DETERMINE) { 5668 PetscInt d = PETSC_DEFAULT; 5669 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 5670 5671 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5672 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5673 pStart = PetscMax(vStart, pStart); 5674 pEnd = PetscMin(vEnd, pEnd); 5675 for (v = pStart; v < pEnd; ++v) { 5676 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 5677 if (dd) {d = dd; break;} 5678 } 5679 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 5680 } 5681 PetscFunctionReturn(0); 5682 } 5683 5684 /*@C 5685 DMGetPeriodicity - Get the description of mesh periodicity 5686 5687 Input Parameters: 5688 . dm - The DM object 5689 5690 Output Parameters: 5691 + per - Whether the DM is periodic or not 5692 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5693 . L - If we assume the mesh is a torus, this is the length of each coordinate 5694 - bd - This describes the type of periodicity in each topological dimension 5695 5696 Level: developer 5697 5698 .seealso: DMGetPeriodicity() 5699 @*/ 5700 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 5701 { 5702 PetscFunctionBegin; 5703 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5704 if (per) *per = dm->periodic; 5705 if (L) *L = dm->L; 5706 if (maxCell) *maxCell = dm->maxCell; 5707 if (bd) *bd = dm->bdtype; 5708 PetscFunctionReturn(0); 5709 } 5710 5711 /*@C 5712 DMSetPeriodicity - Set the description of mesh periodicity 5713 5714 Input Parameters: 5715 + dm - The DM object 5716 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 5717 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5718 . L - If we assume the mesh is a torus, this is the length of each coordinate 5719 - bd - This describes the type of periodicity in each topological dimension 5720 5721 Level: developer 5722 5723 .seealso: DMGetPeriodicity() 5724 @*/ 5725 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 5726 { 5727 PetscInt dim, d; 5728 PetscErrorCode ierr; 5729 5730 PetscFunctionBegin; 5731 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5732 PetscValidLogicalCollectiveBool(dm,per,2); 5733 if (maxCell) { 5734 PetscValidPointer(maxCell,3); 5735 PetscValidPointer(L,4); 5736 PetscValidPointer(bd,5); 5737 } 5738 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 5739 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5740 if (maxCell) { 5741 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 5742 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 5743 } 5744 dm->periodic = per; 5745 PetscFunctionReturn(0); 5746 } 5747 5748 /*@ 5749 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. 5750 5751 Input Parameters: 5752 + dm - The DM 5753 . in - The input coordinate point (dim numbers) 5754 - endpoint - Include the endpoint L_i 5755 5756 Output Parameter: 5757 . out - The localized coordinate point 5758 5759 Level: developer 5760 5761 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5762 @*/ 5763 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 5764 { 5765 PetscInt dim, d; 5766 PetscErrorCode ierr; 5767 5768 PetscFunctionBegin; 5769 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 5770 if (!dm->maxCell) { 5771 for (d = 0; d < dim; ++d) out[d] = in[d]; 5772 } else { 5773 if (endpoint) { 5774 for (d = 0; d < dim; ++d) { 5775 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)) { 5776 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 5777 } else { 5778 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5779 } 5780 } 5781 } else { 5782 for (d = 0; d < dim; ++d) { 5783 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5784 } 5785 } 5786 } 5787 PetscFunctionReturn(0); 5788 } 5789 5790 /* 5791 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. 5792 5793 Input Parameters: 5794 + dm - The DM 5795 . dim - The spatial dimension 5796 . anchor - The anchor point, the input point can be no more than maxCell away from it 5797 - in - The input coordinate point (dim numbers) 5798 5799 Output Parameter: 5800 . out - The localized coordinate point 5801 5802 Level: developer 5803 5804 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 5805 5806 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5807 */ 5808 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5809 { 5810 PetscInt d; 5811 5812 PetscFunctionBegin; 5813 if (!dm->maxCell) { 5814 for (d = 0; d < dim; ++d) out[d] = in[d]; 5815 } else { 5816 for (d = 0; d < dim; ++d) { 5817 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5818 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5819 } else { 5820 out[d] = in[d]; 5821 } 5822 } 5823 } 5824 PetscFunctionReturn(0); 5825 } 5826 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 5827 { 5828 PetscInt d; 5829 5830 PetscFunctionBegin; 5831 if (!dm->maxCell) { 5832 for (d = 0; d < dim; ++d) out[d] = in[d]; 5833 } else { 5834 for (d = 0; d < dim; ++d) { 5835 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 5836 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5837 } else { 5838 out[d] = in[d]; 5839 } 5840 } 5841 } 5842 PetscFunctionReturn(0); 5843 } 5844 5845 /* 5846 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. 5847 5848 Input Parameters: 5849 + dm - The DM 5850 . dim - The spatial dimension 5851 . anchor - The anchor point, the input point can be no more than maxCell away from it 5852 . in - The input coordinate delta (dim numbers) 5853 - out - The input coordinate point (dim numbers) 5854 5855 Output Parameter: 5856 . out - The localized coordinate in + out 5857 5858 Level: developer 5859 5860 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 5861 5862 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 5863 */ 5864 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5865 { 5866 PetscInt d; 5867 5868 PetscFunctionBegin; 5869 if (!dm->maxCell) { 5870 for (d = 0; d < dim; ++d) out[d] += in[d]; 5871 } else { 5872 for (d = 0; d < dim; ++d) { 5873 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5874 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5875 } else { 5876 out[d] += in[d]; 5877 } 5878 } 5879 } 5880 PetscFunctionReturn(0); 5881 } 5882 5883 /*@ 5884 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 5885 5886 Not collective 5887 5888 Input Parameter: 5889 . dm - The DM 5890 5891 Output Parameter: 5892 areLocalized - True if localized 5893 5894 Level: developer 5895 5896 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 5897 @*/ 5898 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 5899 { 5900 DM cdm; 5901 PetscSection coordSection; 5902 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 5903 PetscBool isPlex, alreadyLocalized; 5904 PetscErrorCode ierr; 5905 5906 PetscFunctionBegin; 5907 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5908 PetscValidPointer(areLocalized, 2); 5909 *areLocalized = PETSC_FALSE; 5910 5911 /* We need some generic way of refering to cells/vertices */ 5912 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5913 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 5914 if (!isPlex) PetscFunctionReturn(0); 5915 5916 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5917 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5918 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 5919 alreadyLocalized = PETSC_FALSE; 5920 for (c = cStart; c < cEnd; ++c) { 5921 if (c < sStart || c >= sEnd) continue; 5922 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 5923 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 5924 } 5925 *areLocalized = alreadyLocalized; 5926 PetscFunctionReturn(0); 5927 } 5928 5929 /*@ 5930 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 5931 5932 Collective on dm 5933 5934 Input Parameter: 5935 . dm - The DM 5936 5937 Output Parameter: 5938 areLocalized - True if localized 5939 5940 Level: developer 5941 5942 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 5943 @*/ 5944 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 5945 { 5946 PetscBool localized; 5947 PetscErrorCode ierr; 5948 5949 PetscFunctionBegin; 5950 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5951 PetscValidPointer(areLocalized, 2); 5952 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 5953 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 5954 PetscFunctionReturn(0); 5955 } 5956 5957 /*@ 5958 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 5959 5960 Collective on dm 5961 5962 Input Parameter: 5963 . dm - The DM 5964 5965 Level: developer 5966 5967 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 5968 @*/ 5969 PetscErrorCode DMLocalizeCoordinates(DM dm) 5970 { 5971 DM cdm; 5972 PetscSection coordSection, cSection; 5973 Vec coordinates, cVec; 5974 PetscScalar *coords, *coords2, *anchor, *localized; 5975 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 5976 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 5977 PetscInt maxHeight = 0, h; 5978 PetscInt *pStart = NULL, *pEnd = NULL; 5979 PetscErrorCode ierr; 5980 5981 PetscFunctionBegin; 5982 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5983 if (!dm->periodic) PetscFunctionReturn(0); 5984 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 5985 if (alreadyLocalized) PetscFunctionReturn(0); 5986 5987 /* We need some generic way of refering to cells/vertices */ 5988 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5989 { 5990 PetscBool isplex; 5991 5992 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 5993 if (isplex) { 5994 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5995 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 5996 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5997 pEnd = &pStart[maxHeight + 1]; 5998 newStart = vStart; 5999 newEnd = vEnd; 6000 for (h = 0; h <= maxHeight; h++) { 6001 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6002 newStart = PetscMin(newStart,pStart[h]); 6003 newEnd = PetscMax(newEnd,pEnd[h]); 6004 } 6005 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6006 } 6007 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6008 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6009 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6010 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6011 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6012 6013 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6014 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6015 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6016 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6017 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6018 6019 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6020 localized = &anchor[bs]; 6021 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6022 for (h = 0; h <= maxHeight; h++) { 6023 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6024 6025 for (c = cStart; c < cEnd; ++c) { 6026 PetscScalar *cellCoords = NULL; 6027 PetscInt b; 6028 6029 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6030 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6031 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6032 for (d = 0; d < dof/bs; ++d) { 6033 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6034 for (b = 0; b < bs; b++) { 6035 if (cellCoords[d*bs + b] != localized[b]) break; 6036 } 6037 if (b < bs) break; 6038 } 6039 if (d < dof/bs) { 6040 if (c >= sStart && c < sEnd) { 6041 PetscInt cdof; 6042 6043 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6044 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6045 } 6046 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6047 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6048 } 6049 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6050 } 6051 } 6052 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6053 if (alreadyLocalizedGlobal) { 6054 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6055 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6056 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6057 PetscFunctionReturn(0); 6058 } 6059 for (v = vStart; v < vEnd; ++v) { 6060 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6061 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6062 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6063 } 6064 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6065 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6066 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6067 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6068 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6069 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6070 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6071 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6072 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 6073 for (v = vStart; v < vEnd; ++v) { 6074 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6075 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6076 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 6077 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 6078 } 6079 for (h = 0; h <= maxHeight; h++) { 6080 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6081 6082 for (c = cStart; c < cEnd; ++c) { 6083 PetscScalar *cellCoords = NULL; 6084 PetscInt b, cdof; 6085 6086 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 6087 if (!cdof) continue; 6088 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6089 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 6090 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6091 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 6092 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6093 } 6094 } 6095 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6096 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6097 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6098 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 6099 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 6100 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 6101 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 6102 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6103 PetscFunctionReturn(0); 6104 } 6105 6106 /*@ 6107 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 6108 6109 Collective on Vec v (see explanation below) 6110 6111 Input Parameters: 6112 + dm - The DM 6113 . v - The Vec of points 6114 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 6115 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 6116 6117 Output Parameter: 6118 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 6119 - cells - The PetscSF containing the ranks and local indices of the containing points. 6120 6121 6122 Level: developer 6123 6124 Notes: 6125 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 6126 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 6127 6128 If *cellSF is NULL on input, a PetscSF will be created. 6129 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 6130 6131 An array that maps each point to its containing cell can be obtained with 6132 6133 $ const PetscSFNode *cells; 6134 $ PetscInt nFound; 6135 $ const PetscInt *found; 6136 $ 6137 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 6138 6139 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 6140 the index of the cell in its rank's local numbering. 6141 6142 .keywords: point location, mesh 6143 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 6144 @*/ 6145 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 6146 { 6147 PetscErrorCode ierr; 6148 6149 PetscFunctionBegin; 6150 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6151 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 6152 PetscValidPointer(cellSF,4); 6153 if (*cellSF) { 6154 PetscMPIInt result; 6155 6156 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 6157 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 6158 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 6159 } else { 6160 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 6161 } 6162 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6163 if (dm->ops->locatepoints) { 6164 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 6165 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 6166 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6167 PetscFunctionReturn(0); 6168 } 6169 6170 /*@ 6171 DMGetOutputDM - Retrieve the DM associated with the layout for output 6172 6173 Collective on dm 6174 6175 Input Parameter: 6176 . dm - The original DM 6177 6178 Output Parameter: 6179 . odm - The DM which provides the layout for output 6180 6181 Level: intermediate 6182 6183 .seealso: VecView(), DMGetGlobalSection() 6184 @*/ 6185 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 6186 { 6187 PetscSection section; 6188 PetscBool hasConstraints, ghasConstraints; 6189 PetscErrorCode ierr; 6190 6191 PetscFunctionBegin; 6192 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6193 PetscValidPointer(odm,2); 6194 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 6195 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 6196 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6197 if (!ghasConstraints) { 6198 *odm = dm; 6199 PetscFunctionReturn(0); 6200 } 6201 if (!dm->dmBC) { 6202 PetscSection newSection, gsection; 6203 PetscSF sf; 6204 6205 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 6206 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 6207 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 6208 ierr = DMSetSection(dm->dmBC, newSection);CHKERRQ(ierr); 6209 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 6210 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 6211 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 6212 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 6213 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 6214 } 6215 *odm = dm->dmBC; 6216 PetscFunctionReturn(0); 6217 } 6218 6219 /*@ 6220 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 6221 6222 Input Parameter: 6223 . dm - The original DM 6224 6225 Output Parameters: 6226 + num - The output sequence number 6227 - val - The output sequence value 6228 6229 Level: intermediate 6230 6231 Note: This is intended for output that should appear in sequence, for instance 6232 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6233 6234 .seealso: VecView() 6235 @*/ 6236 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 6237 { 6238 PetscFunctionBegin; 6239 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6240 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 6241 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 6242 PetscFunctionReturn(0); 6243 } 6244 6245 /*@ 6246 DMSetOutputSequenceNumber - Set the sequence number/value for output 6247 6248 Input Parameters: 6249 + dm - The original DM 6250 . num - The output sequence number 6251 - val - The output sequence value 6252 6253 Level: intermediate 6254 6255 Note: This is intended for output that should appear in sequence, for instance 6256 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6257 6258 .seealso: VecView() 6259 @*/ 6260 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 6261 { 6262 PetscFunctionBegin; 6263 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6264 dm->outputSequenceNum = num; 6265 dm->outputSequenceVal = val; 6266 PetscFunctionReturn(0); 6267 } 6268 6269 /*@C 6270 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 6271 6272 Input Parameters: 6273 + dm - The original DM 6274 . name - The sequence name 6275 - num - The output sequence number 6276 6277 Output Parameter: 6278 . val - The output sequence value 6279 6280 Level: intermediate 6281 6282 Note: This is intended for output that should appear in sequence, for instance 6283 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6284 6285 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 6286 @*/ 6287 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 6288 { 6289 PetscBool ishdf5; 6290 PetscErrorCode ierr; 6291 6292 PetscFunctionBegin; 6293 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6294 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 6295 PetscValidPointer(val,4); 6296 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 6297 if (ishdf5) { 6298 #if defined(PETSC_HAVE_HDF5) 6299 PetscScalar value; 6300 6301 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 6302 *val = PetscRealPart(value); 6303 #endif 6304 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 6305 PetscFunctionReturn(0); 6306 } 6307 6308 /*@ 6309 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 6310 6311 Not collective 6312 6313 Input Parameter: 6314 . dm - The DM 6315 6316 Output Parameter: 6317 . useNatural - The flag to build the mapping to a natural order during distribution 6318 6319 Level: beginner 6320 6321 .seealso: DMSetUseNatural(), DMCreate() 6322 @*/ 6323 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 6324 { 6325 PetscFunctionBegin; 6326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6327 PetscValidPointer(useNatural, 2); 6328 *useNatural = dm->useNatural; 6329 PetscFunctionReturn(0); 6330 } 6331 6332 /*@ 6333 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 6334 6335 Collective on dm 6336 6337 Input Parameters: 6338 + dm - The DM 6339 - useNatural - The flag to build the mapping to a natural order during distribution 6340 6341 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 6342 6343 Level: beginner 6344 6345 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 6346 @*/ 6347 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 6348 { 6349 PetscFunctionBegin; 6350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6351 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 6352 dm->useNatural = useNatural; 6353 PetscFunctionReturn(0); 6354 } 6355 6356 6357 /*@C 6358 DMCreateLabel - Create a label of the given name if it does not already exist 6359 6360 Not Collective 6361 6362 Input Parameters: 6363 + dm - The DM object 6364 - name - The label name 6365 6366 Level: intermediate 6367 6368 .keywords: mesh 6369 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6370 @*/ 6371 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 6372 { 6373 DMLabelLink next = dm->labels->next; 6374 PetscBool flg = PETSC_FALSE; 6375 const char *lname; 6376 PetscErrorCode ierr; 6377 6378 PetscFunctionBegin; 6379 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6380 PetscValidCharPointer(name, 2); 6381 while (next) { 6382 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6383 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 6384 if (flg) break; 6385 next = next->next; 6386 } 6387 if (!flg) { 6388 DMLabelLink tmpLabel; 6389 6390 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 6391 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &tmpLabel->label);CHKERRQ(ierr); 6392 tmpLabel->output = PETSC_TRUE; 6393 tmpLabel->next = dm->labels->next; 6394 dm->labels->next = tmpLabel; 6395 } 6396 PetscFunctionReturn(0); 6397 } 6398 6399 /*@C 6400 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 6401 6402 Not Collective 6403 6404 Input Parameters: 6405 + dm - The DM object 6406 . name - The label name 6407 - point - The mesh point 6408 6409 Output Parameter: 6410 . value - The label value for this point, or -1 if the point is not in the label 6411 6412 Level: beginner 6413 6414 .keywords: mesh 6415 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 6416 @*/ 6417 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 6418 { 6419 DMLabel label; 6420 PetscErrorCode ierr; 6421 6422 PetscFunctionBegin; 6423 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6424 PetscValidCharPointer(name, 2); 6425 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6426 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 6427 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 6428 PetscFunctionReturn(0); 6429 } 6430 6431 /*@C 6432 DMSetLabelValue - Add a point to a Sieve Label with given value 6433 6434 Not Collective 6435 6436 Input Parameters: 6437 + dm - The DM object 6438 . name - The label name 6439 . point - The mesh point 6440 - value - The label value for this point 6441 6442 Output Parameter: 6443 6444 Level: beginner 6445 6446 .keywords: mesh 6447 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 6448 @*/ 6449 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6450 { 6451 DMLabel label; 6452 PetscErrorCode ierr; 6453 6454 PetscFunctionBegin; 6455 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6456 PetscValidCharPointer(name, 2); 6457 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6458 if (!label) { 6459 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 6460 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6461 } 6462 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 6463 PetscFunctionReturn(0); 6464 } 6465 6466 /*@C 6467 DMClearLabelValue - Remove a point from a Sieve Label with given value 6468 6469 Not Collective 6470 6471 Input Parameters: 6472 + dm - The DM object 6473 . name - The label name 6474 . point - The mesh point 6475 - value - The label value for this point 6476 6477 Output Parameter: 6478 6479 Level: beginner 6480 6481 .keywords: mesh 6482 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 6483 @*/ 6484 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6485 { 6486 DMLabel label; 6487 PetscErrorCode ierr; 6488 6489 PetscFunctionBegin; 6490 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6491 PetscValidCharPointer(name, 2); 6492 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6493 if (!label) PetscFunctionReturn(0); 6494 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 6495 PetscFunctionReturn(0); 6496 } 6497 6498 /*@C 6499 DMGetLabelSize - Get the number of different integer ids in a Label 6500 6501 Not Collective 6502 6503 Input Parameters: 6504 + dm - The DM object 6505 - name - The label name 6506 6507 Output Parameter: 6508 . size - The number of different integer ids, or 0 if the label does not exist 6509 6510 Level: beginner 6511 6512 .keywords: mesh 6513 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 6514 @*/ 6515 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 6516 { 6517 DMLabel label; 6518 PetscErrorCode ierr; 6519 6520 PetscFunctionBegin; 6521 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6522 PetscValidCharPointer(name, 2); 6523 PetscValidPointer(size, 3); 6524 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6525 *size = 0; 6526 if (!label) PetscFunctionReturn(0); 6527 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 6528 PetscFunctionReturn(0); 6529 } 6530 6531 /*@C 6532 DMGetLabelIdIS - Get the integer ids in a label 6533 6534 Not Collective 6535 6536 Input Parameters: 6537 + mesh - The DM object 6538 - name - The label name 6539 6540 Output Parameter: 6541 . ids - The integer ids, or NULL if the label does not exist 6542 6543 Level: beginner 6544 6545 .keywords: mesh 6546 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 6547 @*/ 6548 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 6549 { 6550 DMLabel label; 6551 PetscErrorCode ierr; 6552 6553 PetscFunctionBegin; 6554 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6555 PetscValidCharPointer(name, 2); 6556 PetscValidPointer(ids, 3); 6557 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6558 *ids = NULL; 6559 if (label) { 6560 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 6561 } else { 6562 /* returning an empty IS */ 6563 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 6564 } 6565 PetscFunctionReturn(0); 6566 } 6567 6568 /*@C 6569 DMGetStratumSize - Get the number of points in a label stratum 6570 6571 Not Collective 6572 6573 Input Parameters: 6574 + dm - The DM object 6575 . name - The label name 6576 - value - The stratum value 6577 6578 Output Parameter: 6579 . size - The stratum size 6580 6581 Level: beginner 6582 6583 .keywords: mesh 6584 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 6585 @*/ 6586 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 6587 { 6588 DMLabel label; 6589 PetscErrorCode ierr; 6590 6591 PetscFunctionBegin; 6592 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6593 PetscValidCharPointer(name, 2); 6594 PetscValidPointer(size, 4); 6595 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6596 *size = 0; 6597 if (!label) PetscFunctionReturn(0); 6598 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 6599 PetscFunctionReturn(0); 6600 } 6601 6602 /*@C 6603 DMGetStratumIS - Get the points in a label stratum 6604 6605 Not Collective 6606 6607 Input Parameters: 6608 + dm - The DM object 6609 . name - The label name 6610 - value - The stratum value 6611 6612 Output Parameter: 6613 . points - The stratum points, or NULL if the label does not exist or does not have that value 6614 6615 Level: beginner 6616 6617 .keywords: mesh 6618 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 6619 @*/ 6620 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 6621 { 6622 DMLabel label; 6623 PetscErrorCode ierr; 6624 6625 PetscFunctionBegin; 6626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6627 PetscValidCharPointer(name, 2); 6628 PetscValidPointer(points, 4); 6629 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6630 *points = NULL; 6631 if (!label) PetscFunctionReturn(0); 6632 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 6633 PetscFunctionReturn(0); 6634 } 6635 6636 /*@C 6637 DMSetStratumIS - Set the points in a label stratum 6638 6639 Not Collective 6640 6641 Input Parameters: 6642 + dm - The DM object 6643 . name - The label name 6644 . value - The stratum value 6645 - points - The stratum points 6646 6647 Level: beginner 6648 6649 .keywords: mesh 6650 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 6651 @*/ 6652 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 6653 { 6654 DMLabel label; 6655 PetscErrorCode ierr; 6656 6657 PetscFunctionBegin; 6658 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6659 PetscValidCharPointer(name, 2); 6660 PetscValidPointer(points, 4); 6661 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6662 if (!label) PetscFunctionReturn(0); 6663 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 6664 PetscFunctionReturn(0); 6665 } 6666 6667 /*@C 6668 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 6669 6670 Not Collective 6671 6672 Input Parameters: 6673 + dm - The DM object 6674 . name - The label name 6675 - value - The label value for this point 6676 6677 Output Parameter: 6678 6679 Level: beginner 6680 6681 .keywords: mesh 6682 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 6683 @*/ 6684 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 6685 { 6686 DMLabel label; 6687 PetscErrorCode ierr; 6688 6689 PetscFunctionBegin; 6690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6691 PetscValidCharPointer(name, 2); 6692 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6693 if (!label) PetscFunctionReturn(0); 6694 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 6695 PetscFunctionReturn(0); 6696 } 6697 6698 /*@ 6699 DMGetNumLabels - Return the number of labels defined by the mesh 6700 6701 Not Collective 6702 6703 Input Parameter: 6704 . dm - The DM object 6705 6706 Output Parameter: 6707 . numLabels - the number of Labels 6708 6709 Level: intermediate 6710 6711 .keywords: mesh 6712 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6713 @*/ 6714 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 6715 { 6716 DMLabelLink next = dm->labels->next; 6717 PetscInt n = 0; 6718 6719 PetscFunctionBegin; 6720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6721 PetscValidPointer(numLabels, 2); 6722 while (next) {++n; next = next->next;} 6723 *numLabels = n; 6724 PetscFunctionReturn(0); 6725 } 6726 6727 /*@C 6728 DMGetLabelName - Return the name of nth label 6729 6730 Not Collective 6731 6732 Input Parameters: 6733 + dm - The DM object 6734 - n - the label number 6735 6736 Output Parameter: 6737 . name - the label name 6738 6739 Level: intermediate 6740 6741 .keywords: mesh 6742 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6743 @*/ 6744 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 6745 { 6746 DMLabelLink next = dm->labels->next; 6747 PetscInt l = 0; 6748 PetscErrorCode ierr; 6749 6750 PetscFunctionBegin; 6751 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6752 PetscValidPointer(name, 3); 6753 while (next) { 6754 if (l == n) { 6755 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 6756 PetscFunctionReturn(0); 6757 } 6758 ++l; 6759 next = next->next; 6760 } 6761 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6762 } 6763 6764 /*@C 6765 DMHasLabel - Determine whether the mesh has a label of a given name 6766 6767 Not Collective 6768 6769 Input Parameters: 6770 + dm - The DM object 6771 - name - The label name 6772 6773 Output Parameter: 6774 . hasLabel - PETSC_TRUE if the label is present 6775 6776 Level: intermediate 6777 6778 .keywords: mesh 6779 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6780 @*/ 6781 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 6782 { 6783 DMLabelLink next = dm->labels->next; 6784 const char *lname; 6785 PetscErrorCode ierr; 6786 6787 PetscFunctionBegin; 6788 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6789 PetscValidCharPointer(name, 2); 6790 PetscValidPointer(hasLabel, 3); 6791 *hasLabel = PETSC_FALSE; 6792 while (next) { 6793 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6794 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 6795 if (*hasLabel) break; 6796 next = next->next; 6797 } 6798 PetscFunctionReturn(0); 6799 } 6800 6801 /*@C 6802 DMGetLabel - Return the label of a given name, or NULL 6803 6804 Not Collective 6805 6806 Input Parameters: 6807 + dm - The DM object 6808 - name - The label name 6809 6810 Output Parameter: 6811 . label - The DMLabel, or NULL if the label is absent 6812 6813 Level: intermediate 6814 6815 .keywords: mesh 6816 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6817 @*/ 6818 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 6819 { 6820 DMLabelLink next = dm->labels->next; 6821 PetscBool hasLabel; 6822 const char *lname; 6823 PetscErrorCode ierr; 6824 6825 PetscFunctionBegin; 6826 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6827 PetscValidCharPointer(name, 2); 6828 PetscValidPointer(label, 3); 6829 *label = NULL; 6830 while (next) { 6831 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6832 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 6833 if (hasLabel) { 6834 *label = next->label; 6835 break; 6836 } 6837 next = next->next; 6838 } 6839 PetscFunctionReturn(0); 6840 } 6841 6842 /*@C 6843 DMGetLabelByNum - Return the nth label 6844 6845 Not Collective 6846 6847 Input Parameters: 6848 + dm - The DM object 6849 - n - the label number 6850 6851 Output Parameter: 6852 . label - the label 6853 6854 Level: intermediate 6855 6856 .keywords: mesh 6857 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6858 @*/ 6859 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 6860 { 6861 DMLabelLink next = dm->labels->next; 6862 PetscInt l = 0; 6863 6864 PetscFunctionBegin; 6865 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6866 PetscValidPointer(label, 3); 6867 while (next) { 6868 if (l == n) { 6869 *label = next->label; 6870 PetscFunctionReturn(0); 6871 } 6872 ++l; 6873 next = next->next; 6874 } 6875 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6876 } 6877 6878 /*@C 6879 DMAddLabel - Add the label to this mesh 6880 6881 Not Collective 6882 6883 Input Parameters: 6884 + dm - The DM object 6885 - label - The DMLabel 6886 6887 Level: developer 6888 6889 .keywords: mesh 6890 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6891 @*/ 6892 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 6893 { 6894 DMLabelLink tmpLabel; 6895 PetscBool hasLabel; 6896 const char *lname; 6897 PetscErrorCode ierr; 6898 6899 PetscFunctionBegin; 6900 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6901 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 6902 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 6903 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 6904 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 6905 tmpLabel->label = label; 6906 tmpLabel->output = PETSC_TRUE; 6907 tmpLabel->next = dm->labels->next; 6908 dm->labels->next = tmpLabel; 6909 PetscFunctionReturn(0); 6910 } 6911 6912 /*@C 6913 DMRemoveLabel - Remove the label from this mesh 6914 6915 Not Collective 6916 6917 Input Parameters: 6918 + dm - The DM object 6919 - name - The label name 6920 6921 Output Parameter: 6922 . label - The DMLabel, or NULL if the label is absent 6923 6924 Level: developer 6925 6926 .keywords: mesh 6927 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6928 @*/ 6929 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 6930 { 6931 DMLabelLink next = dm->labels->next; 6932 DMLabelLink last = NULL; 6933 PetscBool hasLabel; 6934 const char *lname; 6935 PetscErrorCode ierr; 6936 6937 PetscFunctionBegin; 6938 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6939 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 6940 *label = NULL; 6941 if (!hasLabel) PetscFunctionReturn(0); 6942 while (next) { 6943 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6944 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 6945 if (hasLabel) { 6946 if (last) last->next = next->next; 6947 else dm->labels->next = next->next; 6948 next->next = NULL; 6949 *label = next->label; 6950 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 6951 if (hasLabel) { 6952 dm->depthLabel = NULL; 6953 } 6954 ierr = PetscFree(next);CHKERRQ(ierr); 6955 break; 6956 } 6957 last = next; 6958 next = next->next; 6959 } 6960 PetscFunctionReturn(0); 6961 } 6962 6963 /*@C 6964 DMGetLabelOutput - Get the output flag for a given label 6965 6966 Not Collective 6967 6968 Input Parameters: 6969 + dm - The DM object 6970 - name - The label name 6971 6972 Output Parameter: 6973 . output - The flag for output 6974 6975 Level: developer 6976 6977 .keywords: mesh 6978 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6979 @*/ 6980 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 6981 { 6982 DMLabelLink next = dm->labels->next; 6983 const char *lname; 6984 PetscErrorCode ierr; 6985 6986 PetscFunctionBegin; 6987 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6988 PetscValidPointer(name, 2); 6989 PetscValidPointer(output, 3); 6990 while (next) { 6991 PetscBool flg; 6992 6993 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6994 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 6995 if (flg) {*output = next->output; PetscFunctionReturn(0);} 6996 next = next->next; 6997 } 6998 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 6999 } 7000 7001 /*@C 7002 DMSetLabelOutput - Set the output flag for a given label 7003 7004 Not Collective 7005 7006 Input Parameters: 7007 + dm - The DM object 7008 . name - The label name 7009 - output - The flag for output 7010 7011 Level: developer 7012 7013 .keywords: mesh 7014 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7015 @*/ 7016 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 7017 { 7018 DMLabelLink next = dm->labels->next; 7019 const char *lname; 7020 PetscErrorCode ierr; 7021 7022 PetscFunctionBegin; 7023 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7024 PetscValidPointer(name, 2); 7025 while (next) { 7026 PetscBool flg; 7027 7028 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7029 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7030 if (flg) {next->output = output; PetscFunctionReturn(0);} 7031 next = next->next; 7032 } 7033 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7034 } 7035 7036 7037 /*@ 7038 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 7039 7040 Collective on DM 7041 7042 Input Parameter: 7043 . dmA - The DM object with initial labels 7044 7045 Output Parameter: 7046 . dmB - The DM object with copied labels 7047 7048 Level: intermediate 7049 7050 Note: This is typically used when interpolating or otherwise adding to a mesh 7051 7052 .keywords: mesh 7053 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 7054 @*/ 7055 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 7056 { 7057 PetscInt numLabels, l; 7058 PetscErrorCode ierr; 7059 7060 PetscFunctionBegin; 7061 if (dmA == dmB) PetscFunctionReturn(0); 7062 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 7063 for (l = 0; l < numLabels; ++l) { 7064 DMLabel label, labelNew; 7065 const char *name; 7066 PetscBool flg; 7067 7068 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 7069 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 7070 if (flg) continue; 7071 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 7072 if (flg) continue; 7073 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 7074 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 7075 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 7076 } 7077 PetscFunctionReturn(0); 7078 } 7079 7080 /*@ 7081 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 7082 7083 Input Parameter: 7084 . dm - The DM object 7085 7086 Output Parameter: 7087 . cdm - The coarse DM 7088 7089 Level: intermediate 7090 7091 .seealso: DMSetCoarseDM() 7092 @*/ 7093 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 7094 { 7095 PetscFunctionBegin; 7096 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7097 PetscValidPointer(cdm, 2); 7098 *cdm = dm->coarseMesh; 7099 PetscFunctionReturn(0); 7100 } 7101 7102 /*@ 7103 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 7104 7105 Input Parameters: 7106 + dm - The DM object 7107 - cdm - The coarse DM 7108 7109 Level: intermediate 7110 7111 .seealso: DMGetCoarseDM() 7112 @*/ 7113 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 7114 { 7115 PetscErrorCode ierr; 7116 7117 PetscFunctionBegin; 7118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7119 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 7120 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 7121 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 7122 dm->coarseMesh = cdm; 7123 PetscFunctionReturn(0); 7124 } 7125 7126 /*@ 7127 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 7128 7129 Input Parameter: 7130 . dm - The DM object 7131 7132 Output Parameter: 7133 . fdm - The fine DM 7134 7135 Level: intermediate 7136 7137 .seealso: DMSetFineDM() 7138 @*/ 7139 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 7140 { 7141 PetscFunctionBegin; 7142 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7143 PetscValidPointer(fdm, 2); 7144 *fdm = dm->fineMesh; 7145 PetscFunctionReturn(0); 7146 } 7147 7148 /*@ 7149 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 7150 7151 Input Parameters: 7152 + dm - The DM object 7153 - fdm - The fine DM 7154 7155 Level: intermediate 7156 7157 .seealso: DMGetFineDM() 7158 @*/ 7159 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 7160 { 7161 PetscErrorCode ierr; 7162 7163 PetscFunctionBegin; 7164 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7165 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 7166 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 7167 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 7168 dm->fineMesh = fdm; 7169 PetscFunctionReturn(0); 7170 } 7171 7172 /*=== DMBoundary code ===*/ 7173 7174 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 7175 { 7176 PetscInt d; 7177 PetscErrorCode ierr; 7178 7179 PetscFunctionBegin; 7180 for (d = 0; d < dm->Nds; ++d) { 7181 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr); 7182 } 7183 PetscFunctionReturn(0); 7184 } 7185 7186 /*@C 7187 DMAddBoundary - Add a boundary condition to the model 7188 7189 Input Parameters: 7190 + dm - The DM, with a PetscDS that matches the problem being constrained 7191 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7192 . name - The BC name 7193 . labelname - The label defining constrained points 7194 . field - The field to constrain 7195 . numcomps - The number of constrained field components (0 will constrain all fields) 7196 . comps - An array of constrained component numbers 7197 . bcFunc - A pointwise function giving boundary values 7198 . numids - The number of DMLabel ids for constrained points 7199 . ids - An array of ids for constrained points 7200 - ctx - An optional user context for bcFunc 7201 7202 Options Database Keys: 7203 + -bc_<boundary name> <num> - Overrides the boundary ids 7204 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7205 7206 Level: developer 7207 7208 .seealso: DMGetBoundary() 7209 @*/ 7210 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) 7211 { 7212 PetscDS ds; 7213 PetscErrorCode ierr; 7214 7215 PetscFunctionBegin; 7216 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7217 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7218 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, numids, ids, ctx);CHKERRQ(ierr); 7219 PetscFunctionReturn(0); 7220 } 7221 7222 /*@ 7223 DMGetNumBoundary - Get the number of registered BC 7224 7225 Input Parameters: 7226 . dm - The mesh object 7227 7228 Output Parameters: 7229 . numBd - The number of BC 7230 7231 Level: intermediate 7232 7233 .seealso: DMAddBoundary(), DMGetBoundary() 7234 @*/ 7235 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 7236 { 7237 PetscDS ds; 7238 PetscErrorCode ierr; 7239 7240 PetscFunctionBegin; 7241 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7242 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7243 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr); 7244 PetscFunctionReturn(0); 7245 } 7246 7247 /*@C 7248 DMGetBoundary - Get a model boundary condition 7249 7250 Input Parameters: 7251 + dm - The mesh object 7252 - bd - The BC number 7253 7254 Output Parameters: 7255 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7256 . name - The BC name 7257 . labelname - The label defining constrained points 7258 . field - The field to constrain 7259 . numcomps - The number of constrained field components 7260 . comps - An array of constrained component numbers 7261 . bcFunc - A pointwise function giving boundary values 7262 . numids - The number of DMLabel ids for constrained points 7263 . ids - An array of ids for constrained points 7264 - ctx - An optional user context for bcFunc 7265 7266 Options Database Keys: 7267 + -bc_<boundary name> <num> - Overrides the boundary ids 7268 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7269 7270 Level: developer 7271 7272 .seealso: DMAddBoundary() 7273 @*/ 7274 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) 7275 { 7276 PetscDS ds; 7277 PetscErrorCode ierr; 7278 7279 PetscFunctionBegin; 7280 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7281 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7282 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, numids, ids, ctx);CHKERRQ(ierr); 7283 PetscFunctionReturn(0); 7284 } 7285 7286 static PetscErrorCode DMPopulateBoundary(DM dm) 7287 { 7288 PetscDS ds; 7289 DMBoundary *lastnext; 7290 DSBoundary dsbound; 7291 PetscErrorCode ierr; 7292 7293 PetscFunctionBegin; 7294 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7295 dsbound = ds->boundary; 7296 if (dm->boundary) { 7297 DMBoundary next = dm->boundary; 7298 7299 /* quick check to see if the PetscDS has changed */ 7300 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 7301 /* the PetscDS has changed: tear down and rebuild */ 7302 while (next) { 7303 DMBoundary b = next; 7304 7305 next = b->next; 7306 ierr = PetscFree(b);CHKERRQ(ierr); 7307 } 7308 dm->boundary = NULL; 7309 } 7310 7311 lastnext = &(dm->boundary); 7312 while (dsbound) { 7313 DMBoundary dmbound; 7314 7315 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 7316 dmbound->dsboundary = dsbound; 7317 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 7318 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 7319 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 7320 *lastnext = dmbound; 7321 lastnext = &(dmbound->next); 7322 dsbound = dsbound->next; 7323 } 7324 PetscFunctionReturn(0); 7325 } 7326 7327 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 7328 { 7329 DMBoundary b; 7330 PetscErrorCode ierr; 7331 7332 PetscFunctionBegin; 7333 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7334 PetscValidPointer(isBd, 3); 7335 *isBd = PETSC_FALSE; 7336 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 7337 b = dm->boundary; 7338 while (b && !(*isBd)) { 7339 DMLabel label = b->label; 7340 DSBoundary dsb = b->dsboundary; 7341 7342 if (label) { 7343 PetscInt i; 7344 7345 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 7346 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 7347 } 7348 } 7349 b = b->next; 7350 } 7351 PetscFunctionReturn(0); 7352 } 7353 7354 /*@C 7355 DMProjectFunction - This projects the given function into the function space provided. 7356 7357 Input Parameters: 7358 + dm - The DM 7359 . time - The time 7360 . funcs - The coordinate functions to evaluate, one per field 7361 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7362 - mode - The insertion mode for values 7363 7364 Output Parameter: 7365 . X - vector 7366 7367 Calling sequence of func: 7368 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7369 7370 + dim - The spatial dimension 7371 . x - The coordinates 7372 . Nf - The number of fields 7373 . u - The output field values 7374 - ctx - optional user-defined function context 7375 7376 Level: developer 7377 7378 .seealso: DMComputeL2Diff() 7379 @*/ 7380 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 7381 { 7382 Vec localX; 7383 PetscErrorCode ierr; 7384 7385 PetscFunctionBegin; 7386 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7387 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7388 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7389 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7390 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7391 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7392 PetscFunctionReturn(0); 7393 } 7394 7395 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 7396 { 7397 PetscErrorCode ierr; 7398 7399 PetscFunctionBegin; 7400 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7401 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7402 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 7403 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7404 PetscFunctionReturn(0); 7405 } 7406 7407 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) 7408 { 7409 Vec localX; 7410 PetscErrorCode ierr; 7411 7412 PetscFunctionBegin; 7413 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7414 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7415 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7416 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7417 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7418 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7419 PetscFunctionReturn(0); 7420 } 7421 7422 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) 7423 { 7424 PetscErrorCode ierr; 7425 7426 PetscFunctionBegin; 7427 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7428 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7429 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 7430 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7431 PetscFunctionReturn(0); 7432 } 7433 7434 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 7435 void (**funcs)(PetscInt, PetscInt, PetscInt, 7436 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7437 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7438 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7439 InsertMode mode, Vec localX) 7440 { 7441 PetscErrorCode ierr; 7442 7443 PetscFunctionBegin; 7444 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7445 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 7446 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 7447 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7448 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 7449 PetscFunctionReturn(0); 7450 } 7451 7452 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 7453 void (**funcs)(PetscInt, PetscInt, PetscInt, 7454 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7455 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7456 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7457 InsertMode mode, Vec localX) 7458 { 7459 PetscErrorCode ierr; 7460 7461 PetscFunctionBegin; 7462 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7463 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 7464 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 7465 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7466 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 7467 PetscFunctionReturn(0); 7468 } 7469 7470 /*@C 7471 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 7472 7473 Input Parameters: 7474 + dm - The DM 7475 . time - The time 7476 . funcs - The functions to evaluate for each field component 7477 . ctxs - Optional array of contexts to pass to each function, or NULL. 7478 - X - The coefficient vector u_h, a global vector 7479 7480 Output Parameter: 7481 . diff - The diff ||u - u_h||_2 7482 7483 Level: developer 7484 7485 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 7486 @*/ 7487 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 7488 { 7489 PetscErrorCode ierr; 7490 7491 PetscFunctionBegin; 7492 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7493 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7494 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 7495 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 7496 PetscFunctionReturn(0); 7497 } 7498 7499 /*@C 7500 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 7501 7502 Input Parameters: 7503 + dm - The DM 7504 , time - The time 7505 . funcs - The gradient functions to evaluate for each field component 7506 . ctxs - Optional array of contexts to pass to each function, or NULL. 7507 . X - The coefficient vector u_h, a global vector 7508 - n - The vector to project along 7509 7510 Output Parameter: 7511 . diff - The diff ||(grad u - grad u_h) . n||_2 7512 7513 Level: developer 7514 7515 .seealso: DMProjectFunction(), DMComputeL2Diff() 7516 @*/ 7517 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) 7518 { 7519 PetscErrorCode ierr; 7520 7521 PetscFunctionBegin; 7522 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7523 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7524 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 7525 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 7526 PetscFunctionReturn(0); 7527 } 7528 7529 /*@C 7530 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 7531 7532 Input Parameters: 7533 + dm - The DM 7534 . time - The time 7535 . funcs - The functions to evaluate for each field component 7536 . ctxs - Optional array of contexts to pass to each function, or NULL. 7537 - X - The coefficient vector u_h, a global vector 7538 7539 Output Parameter: 7540 . diff - The array of differences, ||u^f - u^f_h||_2 7541 7542 Level: developer 7543 7544 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 7545 @*/ 7546 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 7547 { 7548 PetscErrorCode ierr; 7549 7550 PetscFunctionBegin; 7551 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7552 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7553 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 7554 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 7555 PetscFunctionReturn(0); 7556 } 7557 7558 /*@C 7559 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 7560 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 7561 7562 Collective on dm 7563 7564 Input parameters: 7565 + dm - the pre-adaptation DM object 7566 - label - label with the flags 7567 7568 Output parameters: 7569 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 7570 7571 Level: intermediate 7572 7573 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 7574 @*/ 7575 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 7576 { 7577 PetscErrorCode ierr; 7578 7579 PetscFunctionBegin; 7580 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7581 PetscValidPointer(label,2); 7582 PetscValidPointer(dmAdapt,3); 7583 *dmAdapt = NULL; 7584 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 7585 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 7586 PetscFunctionReturn(0); 7587 } 7588 7589 /*@C 7590 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 7591 7592 Input Parameters: 7593 + dm - The DM object 7594 . metric - The metric to which the mesh is adapted, defined vertex-wise. 7595 - 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_". 7596 7597 Output Parameter: 7598 . dmAdapt - Pointer to the DM object containing the adapted mesh 7599 7600 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 7601 7602 Level: advanced 7603 7604 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 7605 @*/ 7606 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 7607 { 7608 PetscErrorCode ierr; 7609 7610 PetscFunctionBegin; 7611 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7612 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 7613 if (bdLabel) PetscValidPointer(bdLabel, 3); 7614 PetscValidPointer(dmAdapt, 4); 7615 *dmAdapt = NULL; 7616 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 7617 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 7618 PetscFunctionReturn(0); 7619 } 7620 7621 /*@C 7622 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 7623 7624 Not Collective 7625 7626 Input Parameter: 7627 . dm - The DM 7628 7629 Output Parameter: 7630 . nranks - the number of neighbours 7631 . ranks - the neighbors ranks 7632 7633 Notes: 7634 Do not free the array, it is freed when the DM is destroyed. 7635 7636 Level: beginner 7637 7638 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 7639 @*/ 7640 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 7641 { 7642 PetscErrorCode ierr; 7643 7644 PetscFunctionBegin; 7645 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7646 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 7647 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 7648 PetscFunctionReturn(0); 7649 } 7650 7651 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 7652 7653 /* 7654 Converts the input vector to a ghosted vector and then calls the standard coloring code. 7655 This has be a different function because it requires DM which is not defined in the Mat library 7656 */ 7657 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 7658 { 7659 PetscErrorCode ierr; 7660 7661 PetscFunctionBegin; 7662 if (coloring->ctype == IS_COLORING_LOCAL) { 7663 Vec x1local; 7664 DM dm; 7665 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 7666 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 7667 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 7668 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 7669 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 7670 x1 = x1local; 7671 } 7672 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 7673 if (coloring->ctype == IS_COLORING_LOCAL) { 7674 DM dm; 7675 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 7676 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 7677 } 7678 PetscFunctionReturn(0); 7679 } 7680 7681 /*@ 7682 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 7683 7684 Input Parameter: 7685 . coloring - the MatFDColoring object 7686 7687 Developer Notes: 7688 this routine exists because the PETSc Mat library does not know about the DM objects 7689 7690 Level: advanced 7691 7692 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 7693 @*/ 7694 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 7695 { 7696 PetscFunctionBegin; 7697 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 7698 PetscFunctionReturn(0); 7699 } 7700 7701 /*@ 7702 DMGetCompatibility - determine if two DMs are compatible 7703 7704 Collective 7705 7706 Input Parameters: 7707 + dm - the first DM 7708 - dm2 - the second DM 7709 7710 Output Parameters: 7711 + compatible - whether or not the two DMs are compatible 7712 - set - whether or not the compatible value was set 7713 7714 Notes: 7715 Two DMs are deemed compatible if they represent the same parallel decomposition 7716 of the same topology. This implies that the section (field data) on one 7717 "makes sense" with respect to the topology and parallel decomposition of the other. 7718 Loosely speaking, compatible DMs represent the same domain and parallel 7719 decomposition, but hold different data. 7720 7721 Typically, one would confirm compatibility if intending to simultaneously iterate 7722 over a pair of vectors obtained from different DMs. 7723 7724 For example, two DMDA objects are compatible if they have the same local 7725 and global sizes and the same stencil width. They can have different numbers 7726 of degrees of freedom per node. Thus, one could use the node numbering from 7727 either DM in bounds for a loop over vectors derived from either DM. 7728 7729 Consider the operation of summing data living on a 2-dof DMDA to data living 7730 on a 1-dof DMDA, which should be compatible, as in the following snippet. 7731 .vb 7732 ... 7733 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 7734 if (set && compatible) { 7735 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 7736 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 7737 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 7738 for (j=y; j<y+n; ++j) { 7739 for (i=x; i<x+m, ++i) { 7740 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 7741 } 7742 } 7743 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 7744 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 7745 } else { 7746 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 7747 } 7748 ... 7749 .ve 7750 7751 Checking compatibility might be expensive for a given implementation of DM, 7752 or might be impossible to unambiguously confirm or deny. For this reason, 7753 this function may decline to determine compatibility, and hence users should 7754 always check the "set" output parameter. 7755 7756 A DM is always compatible with itself. 7757 7758 In the current implementation, DMs which live on "unequal" communicators 7759 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 7760 incompatible. 7761 7762 This function is labeled "Collective," as information about all subdomains 7763 is required on each rank. However, in DM implementations which store all this 7764 information locally, this function may be merely "Logically Collective". 7765 7766 Developer Notes: 7767 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 7768 iff B is compatible with A. Thus, this function checks the implementations 7769 of both dm and dm2 (if they are of different types), attempting to determine 7770 compatibility. It is left to DM implementers to ensure that symmetry is 7771 preserved. The simplest way to do this is, when implementing type-specific 7772 logic for this function, is to check for existing logic in the implementation 7773 of other DM types and let *set = PETSC_FALSE if found. 7774 7775 Level: advanced 7776 7777 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 7778 @*/ 7779 7780 PetscErrorCode DMGetCompatibility(DM dm,DM dm2,PetscBool *compatible,PetscBool *set) 7781 { 7782 PetscErrorCode ierr; 7783 PetscMPIInt compareResult; 7784 DMType type,type2; 7785 PetscBool sameType; 7786 7787 PetscFunctionBegin; 7788 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7789 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 7790 7791 /* Declare a DM compatible with itself */ 7792 if (dm == dm2) { 7793 *set = PETSC_TRUE; 7794 *compatible = PETSC_TRUE; 7795 PetscFunctionReturn(0); 7796 } 7797 7798 /* Declare a DM incompatible with a DM that lives on an "unequal" 7799 communicator. Note that this does not preclude compatibility with 7800 DMs living on "congruent" or "similar" communicators, but this must be 7801 determined by the implementation-specific logic */ 7802 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 7803 if (compareResult == MPI_UNEQUAL) { 7804 *set = PETSC_TRUE; 7805 *compatible = PETSC_FALSE; 7806 PetscFunctionReturn(0); 7807 } 7808 7809 /* Pass to the implementation-specific routine, if one exists. */ 7810 if (dm->ops->getcompatibility) { 7811 ierr = (*dm->ops->getcompatibility)(dm,dm2,compatible,set);CHKERRQ(ierr); 7812 if (*set) { 7813 PetscFunctionReturn(0); 7814 } 7815 } 7816 7817 /* If dm and dm2 are of different types, then attempt to check compatibility 7818 with an implementation of this function from dm2 */ 7819 ierr = DMGetType(dm,&type);CHKERRQ(ierr); 7820 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 7821 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 7822 if (!sameType && dm2->ops->getcompatibility) { 7823 ierr = (*dm2->ops->getcompatibility)(dm2,dm,compatible,set);CHKERRQ(ierr); /* Note argument order */ 7824 } else { 7825 *set = PETSC_FALSE; 7826 } 7827 PetscFunctionReturn(0); 7828 } 7829