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