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