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