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