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