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