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