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