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