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