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