1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 2 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 3 #include <petsc/private/petscdsimpl.h> /*I "petscds.h" I*/ 4 #include <petscdmplex.h> 5 #include <petscdmfield.h> 6 #include <petscsf.h> 7 #include <petscds.h> 8 9 PetscClassId DM_CLASSID; 10 PetscClassId DMLABEL_CLASSID; 11 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction; 12 13 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DMBoundaryType","DM_BOUNDARY_",0}; 14 const char *const DMBoundaryConditionTypes[] = {"INVALID","ESSENTIAL","NATURAL","INVALID","INVALID","ESSENTIAL_FIELD","NATURAL_FIELD","INVALID","INVALID","INVALID","NATURAL_RIEMANN","DMBoundaryConditionType","DM_BC_",0}; 15 16 static PetscErrorCode DMHasCreateInjection_Default(DM dm, PetscBool *flg) 17 { 18 PetscFunctionBegin; 19 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 20 PetscValidPointer(flg,2); 21 *flg = PETSC_FALSE; 22 PetscFunctionReturn(0); 23 } 24 25 /*@ 26 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 27 28 If you never call DMSetType() it will generate an 29 error when you try to use the vector. 30 31 Collective on MPI_Comm 32 33 Input Parameter: 34 . comm - The communicator for the DM object 35 36 Output Parameter: 37 . dm - The DM object 38 39 Level: beginner 40 41 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK 42 @*/ 43 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 44 { 45 DM v; 46 PetscDS ds; 47 PetscErrorCode ierr; 48 49 PetscFunctionBegin; 50 PetscValidPointer(dm,2); 51 *dm = NULL; 52 ierr = DMInitializePackage();CHKERRQ(ierr); 53 54 ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 55 56 v->setupcalled = PETSC_FALSE; 57 v->setfromoptionscalled = PETSC_FALSE; 58 v->ltogmap = NULL; 59 v->bs = 1; 60 v->coloringtype = IS_COLORING_GLOBAL; 61 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 62 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 63 v->labels = NULL; 64 v->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 on MPI_Comm 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 DM 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 DM 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 DM 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 DM 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 DM 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 DM 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 and Vec 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 and Vec 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 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 DM 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 PetscViewer 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 PetscInt depth, pMax[4]; 5049 5050 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 5051 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 5052 ierr = DMPlexGetHybridBounds(plex, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 5053 ierr = DMDestroy(&plex);CHKERRQ(ierr); 5054 5055 ierr = DMLabelGetBounds(label, &lStart, &lEnd);CHKERRQ(ierr); 5056 if (lStart < pMax[depth]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support labels over hybrid cells right now"); 5057 ierr = PetscDSCreate(comm, &probh);CHKERRQ(ierr); 5058 ierr = DMSetRegionDS(dm, label, NULL, probh);CHKERRQ(ierr); 5059 ierr = PetscDSSetHybrid(probh, PETSC_TRUE);CHKERRQ(ierr); 5060 ierr = PetscDSSetCoordinateDimension(probh, dimEmbed);CHKERRQ(ierr); 5061 break; 5062 } 5063 } 5064 /* Set fields in DSes */ 5065 for (f = 0; f < Nf; ++f) { 5066 DMLabel label = dm->fields[f].label; 5067 PetscObject disc = dm->fields[f].disc; 5068 5069 if (!label) { 5070 ierr = PetscDSSetDiscretization(prob, field++, disc);CHKERRQ(ierr); 5071 if (probh) { 5072 PetscFE subfe; 5073 5074 ierr = PetscFEGetHeightSubspace((PetscFE) disc, 1, &subfe);CHKERRQ(ierr); 5075 ierr = PetscDSSetDiscretization(probh, fieldh++, (PetscObject) subfe);CHKERRQ(ierr); 5076 } 5077 } else { 5078 ierr = PetscDSSetDiscretization(probh, fieldh++, disc);CHKERRQ(ierr); 5079 } 5080 /* We allow people to have placeholder fields and construct the Section by hand */ 5081 { 5082 PetscClassId id; 5083 5084 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 5085 if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE; 5086 } 5087 } 5088 ierr = PetscDSDestroy(&probh);CHKERRQ(ierr); 5089 /* Setup DSes */ 5090 if (doSetup) { 5091 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);} 5092 } 5093 PetscFunctionReturn(0); 5094 } 5095 5096 /*@ 5097 DMCopyDS - Copy the discrete systems for the DM into another DM 5098 5099 Collective on DM 5100 5101 Input Parameter: 5102 . dm - The DM 5103 5104 Output Parameter: 5105 . newdm - The DM 5106 5107 Level: advanced 5108 5109 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5110 @*/ 5111 PetscErrorCode DMCopyDS(DM dm, DM newdm) 5112 { 5113 PetscInt Nds, s; 5114 PetscErrorCode ierr; 5115 5116 PetscFunctionBegin; 5117 if (dm == newdm) PetscFunctionReturn(0); 5118 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5119 ierr = DMClearDS(newdm);CHKERRQ(ierr); 5120 for (s = 0; s < Nds; ++s) { 5121 DMLabel label; 5122 IS fields; 5123 PetscDS ds; 5124 5125 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5126 ierr = DMSetRegionDS(newdm, label, fields, ds);CHKERRQ(ierr); 5127 } 5128 PetscFunctionReturn(0); 5129 } 5130 5131 /*@ 5132 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 5133 5134 Collective on DM 5135 5136 Input Parameter: 5137 . dm - The DM 5138 5139 Output Parameter: 5140 . newdm - The DM 5141 5142 Level: advanced 5143 5144 .seealso: DMCopyFields(), DMCopyDS() 5145 @*/ 5146 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 5147 { 5148 PetscErrorCode ierr; 5149 5150 PetscFunctionBegin; 5151 if (dm == newdm) PetscFunctionReturn(0); 5152 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 5153 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 5154 PetscFunctionReturn(0); 5155 } 5156 5157 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 5158 { 5159 DM dm_coord,dmc_coord; 5160 PetscErrorCode ierr; 5161 Vec coords,ccoords; 5162 Mat inject; 5163 PetscFunctionBegin; 5164 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5165 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 5166 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5167 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 5168 if (coords && !ccoords) { 5169 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 5170 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5171 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 5172 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 5173 ierr = MatDestroy(&inject);CHKERRQ(ierr); 5174 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 5175 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5176 } 5177 PetscFunctionReturn(0); 5178 } 5179 5180 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 5181 { 5182 DM dm_coord,subdm_coord; 5183 PetscErrorCode ierr; 5184 Vec coords,ccoords,clcoords; 5185 VecScatter *scat_i,*scat_g; 5186 PetscFunctionBegin; 5187 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5188 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 5189 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5190 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 5191 if (coords && !ccoords) { 5192 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 5193 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5194 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 5195 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 5196 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 5197 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5198 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5199 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5200 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5201 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 5202 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 5203 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 5204 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 5205 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5206 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 5207 ierr = PetscFree(scat_i);CHKERRQ(ierr); 5208 ierr = PetscFree(scat_g);CHKERRQ(ierr); 5209 } 5210 PetscFunctionReturn(0); 5211 } 5212 5213 /*@ 5214 DMGetDimension - Return the topological dimension of the DM 5215 5216 Not collective 5217 5218 Input Parameter: 5219 . dm - The DM 5220 5221 Output Parameter: 5222 . dim - The topological dimension 5223 5224 Level: beginner 5225 5226 .seealso: DMSetDimension(), DMCreate() 5227 @*/ 5228 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 5229 { 5230 PetscFunctionBegin; 5231 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5232 PetscValidPointer(dim, 2); 5233 *dim = dm->dim; 5234 PetscFunctionReturn(0); 5235 } 5236 5237 /*@ 5238 DMSetDimension - Set the topological dimension of the DM 5239 5240 Collective on dm 5241 5242 Input Parameters: 5243 + dm - The DM 5244 - dim - The topological dimension 5245 5246 Level: beginner 5247 5248 .seealso: DMGetDimension(), DMCreate() 5249 @*/ 5250 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 5251 { 5252 PetscDS ds; 5253 PetscErrorCode ierr; 5254 5255 PetscFunctionBegin; 5256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5257 PetscValidLogicalCollectiveInt(dm, dim, 2); 5258 dm->dim = dim; 5259 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5260 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dm->dim);CHKERRQ(ierr);} 5261 PetscFunctionReturn(0); 5262 } 5263 5264 /*@ 5265 DMGetDimPoints - Get the half-open interval for all points of a given dimension 5266 5267 Collective on DM 5268 5269 Input Parameters: 5270 + dm - the DM 5271 - dim - the dimension 5272 5273 Output Parameters: 5274 + pStart - The first point of the given dimension 5275 - pEnd - The first point following points of the given dimension 5276 5277 Note: 5278 The points are vertices in the Hasse diagram encoding the topology. This is explained in 5279 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 5280 then the interval is empty. 5281 5282 Level: intermediate 5283 5284 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 5285 @*/ 5286 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5287 { 5288 PetscInt d; 5289 PetscErrorCode ierr; 5290 5291 PetscFunctionBegin; 5292 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5293 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 5294 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 5295 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 5296 PetscFunctionReturn(0); 5297 } 5298 5299 /*@ 5300 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 5301 5302 Collective on DM 5303 5304 Input Parameters: 5305 + dm - the DM 5306 - c - coordinate vector 5307 5308 Notes: 5309 The coordinates do include those for ghost points, which are in the local vector. 5310 5311 The vector c should be destroyed by the caller. 5312 5313 Level: intermediate 5314 5315 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5316 @*/ 5317 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 5318 { 5319 PetscErrorCode ierr; 5320 5321 PetscFunctionBegin; 5322 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5323 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5324 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5325 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5326 dm->coordinates = c; 5327 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5328 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5329 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5330 PetscFunctionReturn(0); 5331 } 5332 5333 /*@ 5334 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 5335 5336 Not collective 5337 5338 Input Parameters: 5339 + dm - the DM 5340 - c - coordinate vector 5341 5342 Notes: 5343 The coordinates of ghost points can be set using DMSetCoordinates() 5344 followed by DMGetCoordinatesLocal(). This is intended to enable the 5345 setting of ghost coordinates outside of the domain. 5346 5347 The vector c should be destroyed by the caller. 5348 5349 Level: intermediate 5350 5351 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 5352 @*/ 5353 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 5354 { 5355 PetscErrorCode ierr; 5356 5357 PetscFunctionBegin; 5358 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5359 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5360 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5361 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5362 5363 dm->coordinatesLocal = c; 5364 5365 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5366 PetscFunctionReturn(0); 5367 } 5368 5369 /*@ 5370 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 5371 5372 Collective on DM 5373 5374 Input Parameter: 5375 . dm - the DM 5376 5377 Output Parameter: 5378 . c - global coordinate vector 5379 5380 Note: 5381 This is a borrowed reference, so the user should NOT destroy this vector 5382 5383 Each process has only the local coordinates (does NOT have the ghost coordinates). 5384 5385 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5386 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5387 5388 Level: intermediate 5389 5390 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5391 @*/ 5392 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 5393 { 5394 PetscErrorCode ierr; 5395 5396 PetscFunctionBegin; 5397 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5398 PetscValidPointer(c,2); 5399 if (!dm->coordinates && dm->coordinatesLocal) { 5400 DM cdm = NULL; 5401 PetscBool localized; 5402 5403 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5404 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 5405 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5406 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 5407 if (localized) { 5408 PetscInt cdim; 5409 5410 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5411 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5412 } 5413 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 5414 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5415 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5416 } 5417 *c = dm->coordinates; 5418 PetscFunctionReturn(0); 5419 } 5420 5421 /*@ 5422 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 5423 5424 Collective on DM 5425 5426 Input Parameter: 5427 . dm - the DM 5428 5429 Level: advanced 5430 5431 .seealso: DMGetCoordinatesLocalNoncollective() 5432 @*/ 5433 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 5434 { 5435 PetscErrorCode ierr; 5436 5437 PetscFunctionBegin; 5438 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5439 if (!dm->coordinatesLocal && dm->coordinates) { 5440 DM cdm = NULL; 5441 PetscBool localized; 5442 5443 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5444 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 5445 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5446 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 5447 if (localized) { 5448 PetscInt cdim; 5449 5450 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5451 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5452 } 5453 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 5454 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5455 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5456 } 5457 PetscFunctionReturn(0); 5458 } 5459 5460 /*@ 5461 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 5462 5463 Collective on DM 5464 5465 Input Parameter: 5466 . dm - the DM 5467 5468 Output Parameter: 5469 . c - coordinate vector 5470 5471 Note: 5472 This is a borrowed reference, so the user should NOT destroy this vector 5473 5474 Each process has the local and ghost coordinates 5475 5476 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5477 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5478 5479 Level: intermediate 5480 5481 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 5482 @*/ 5483 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 5484 { 5485 PetscErrorCode ierr; 5486 5487 PetscFunctionBegin; 5488 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5489 PetscValidPointer(c,2); 5490 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 5491 *c = dm->coordinatesLocal; 5492 PetscFunctionReturn(0); 5493 } 5494 5495 /*@ 5496 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 5497 5498 Not collective 5499 5500 Input Parameter: 5501 . dm - the DM 5502 5503 Output Parameter: 5504 . c - coordinate vector 5505 5506 Level: advanced 5507 5508 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5509 @*/ 5510 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 5511 { 5512 PetscFunctionBegin; 5513 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5514 PetscValidPointer(c,2); 5515 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 5516 *c = dm->coordinatesLocal; 5517 PetscFunctionReturn(0); 5518 } 5519 5520 /*@ 5521 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 5522 5523 Not collective 5524 5525 Input Parameter: 5526 + dm - the DM 5527 - p - the IS of points whose coordinates will be returned 5528 5529 Output Parameter: 5530 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 5531 - pCoord - the Vec with coordinates of points in p 5532 5533 Note: 5534 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 5535 5536 This creates a new vector, so the user SHOULD destroy this vector 5537 5538 Each process has the local and ghost coordinates 5539 5540 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5541 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5542 5543 Level: advanced 5544 5545 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5546 @*/ 5547 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 5548 { 5549 PetscSection cs, newcs; 5550 Vec coords; 5551 const PetscScalar *arr; 5552 PetscScalar *newarr=NULL; 5553 PetscInt n; 5554 PetscErrorCode ierr; 5555 5556 PetscFunctionBegin; 5557 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5558 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 5559 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 5560 if (pCoord) PetscValidPointer(pCoord, 4); 5561 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 5562 if (!dm->coordinateDM || !dm->coordinateDM->defaultSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 5563 cs = dm->coordinateDM->defaultSection; 5564 coords = dm->coordinatesLocal; 5565 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 5566 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 5567 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 5568 if (pCoord) { 5569 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 5570 /* set array in two steps to mimic PETSC_OWN_POINTER */ 5571 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 5572 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 5573 } else { 5574 ierr = PetscFree(newarr);CHKERRQ(ierr); 5575 } 5576 if (pCoordSection) {*pCoordSection = newcs;} 5577 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 5578 PetscFunctionReturn(0); 5579 } 5580 5581 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 5582 { 5583 PetscErrorCode ierr; 5584 5585 PetscFunctionBegin; 5586 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5587 PetscValidPointer(field,2); 5588 if (!dm->coordinateField) { 5589 if (dm->ops->createcoordinatefield) { 5590 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 5591 } 5592 } 5593 *field = dm->coordinateField; 5594 PetscFunctionReturn(0); 5595 } 5596 5597 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 5598 { 5599 PetscErrorCode ierr; 5600 5601 PetscFunctionBegin; 5602 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5603 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 5604 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 5605 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 5606 dm->coordinateField = field; 5607 PetscFunctionReturn(0); 5608 } 5609 5610 /*@ 5611 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 5612 5613 Collective on DM 5614 5615 Input Parameter: 5616 . dm - the DM 5617 5618 Output Parameter: 5619 . cdm - coordinate DM 5620 5621 Level: intermediate 5622 5623 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5624 @*/ 5625 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 5626 { 5627 PetscErrorCode ierr; 5628 5629 PetscFunctionBegin; 5630 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5631 PetscValidPointer(cdm,2); 5632 if (!dm->coordinateDM) { 5633 DM cdm; 5634 5635 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 5636 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 5637 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 5638 * until the call to CreateCoordinateDM) */ 5639 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5640 dm->coordinateDM = cdm; 5641 } 5642 *cdm = dm->coordinateDM; 5643 PetscFunctionReturn(0); 5644 } 5645 5646 /*@ 5647 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 5648 5649 Logically Collective on DM 5650 5651 Input Parameters: 5652 + dm - the DM 5653 - cdm - coordinate DM 5654 5655 Level: intermediate 5656 5657 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5658 @*/ 5659 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 5660 { 5661 PetscErrorCode ierr; 5662 5663 PetscFunctionBegin; 5664 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5665 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 5666 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5667 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5668 dm->coordinateDM = cdm; 5669 PetscFunctionReturn(0); 5670 } 5671 5672 /*@ 5673 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 5674 5675 Not Collective 5676 5677 Input Parameter: 5678 . dm - The DM object 5679 5680 Output Parameter: 5681 . dim - The embedding dimension 5682 5683 Level: intermediate 5684 5685 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetSection(), DMSetSection() 5686 @*/ 5687 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 5688 { 5689 PetscFunctionBegin; 5690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5691 PetscValidPointer(dim, 2); 5692 if (dm->dimEmbed == PETSC_DEFAULT) { 5693 dm->dimEmbed = dm->dim; 5694 } 5695 *dim = dm->dimEmbed; 5696 PetscFunctionReturn(0); 5697 } 5698 5699 /*@ 5700 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 5701 5702 Not Collective 5703 5704 Input Parameters: 5705 + dm - The DM object 5706 - dim - The embedding dimension 5707 5708 Level: intermediate 5709 5710 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetSection(), DMSetSection() 5711 @*/ 5712 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 5713 { 5714 PetscDS ds; 5715 PetscErrorCode ierr; 5716 5717 PetscFunctionBegin; 5718 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5719 dm->dimEmbed = dim; 5720 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5721 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 5722 PetscFunctionReturn(0); 5723 } 5724 5725 /*@ 5726 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 5727 5728 Collective on DM 5729 5730 Input Parameter: 5731 . dm - The DM object 5732 5733 Output Parameter: 5734 . section - The PetscSection object 5735 5736 Level: intermediate 5737 5738 .seealso: DMGetCoordinateDM(), DMGetSection(), DMSetSection() 5739 @*/ 5740 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 5741 { 5742 DM cdm; 5743 PetscErrorCode ierr; 5744 5745 PetscFunctionBegin; 5746 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5747 PetscValidPointer(section, 2); 5748 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5749 ierr = DMGetSection(cdm, section);CHKERRQ(ierr); 5750 PetscFunctionReturn(0); 5751 } 5752 5753 /*@ 5754 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 5755 5756 Not Collective 5757 5758 Input Parameters: 5759 + dm - The DM object 5760 . dim - The embedding dimension, or PETSC_DETERMINE 5761 - section - The PetscSection object 5762 5763 Level: intermediate 5764 5765 .seealso: DMGetCoordinateSection(), DMGetSection(), DMSetSection() 5766 @*/ 5767 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 5768 { 5769 DM cdm; 5770 PetscErrorCode ierr; 5771 5772 PetscFunctionBegin; 5773 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5774 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 5775 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5776 ierr = DMSetSection(cdm, section);CHKERRQ(ierr); 5777 if (dim == PETSC_DETERMINE) { 5778 PetscInt d = PETSC_DEFAULT; 5779 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 5780 5781 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5782 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5783 pStart = PetscMax(vStart, pStart); 5784 pEnd = PetscMin(vEnd, pEnd); 5785 for (v = pStart; v < pEnd; ++v) { 5786 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 5787 if (dd) {d = dd; break;} 5788 } 5789 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 5790 } 5791 PetscFunctionReturn(0); 5792 } 5793 5794 /*@C 5795 DMGetPeriodicity - Get the description of mesh periodicity 5796 5797 Input Parameters: 5798 . dm - The DM object 5799 5800 Output Parameters: 5801 + per - Whether the DM is periodic or not 5802 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5803 . L - If we assume the mesh is a torus, this is the length of each coordinate 5804 - bd - This describes the type of periodicity in each topological dimension 5805 5806 Level: developer 5807 5808 .seealso: DMGetPeriodicity() 5809 @*/ 5810 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 5811 { 5812 PetscFunctionBegin; 5813 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5814 if (per) *per = dm->periodic; 5815 if (L) *L = dm->L; 5816 if (maxCell) *maxCell = dm->maxCell; 5817 if (bd) *bd = dm->bdtype; 5818 PetscFunctionReturn(0); 5819 } 5820 5821 /*@C 5822 DMSetPeriodicity - Set the description of mesh periodicity 5823 5824 Input Parameters: 5825 + dm - The DM object 5826 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 5827 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5828 . L - If we assume the mesh is a torus, this is the length of each coordinate 5829 - bd - This describes the type of periodicity in each topological dimension 5830 5831 Level: developer 5832 5833 .seealso: DMGetPeriodicity() 5834 @*/ 5835 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 5836 { 5837 PetscInt dim, d; 5838 PetscErrorCode ierr; 5839 5840 PetscFunctionBegin; 5841 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5842 PetscValidLogicalCollectiveBool(dm,per,2); 5843 if (maxCell) { 5844 PetscValidPointer(maxCell,3); 5845 PetscValidPointer(L,4); 5846 PetscValidPointer(bd,5); 5847 } 5848 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 5849 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5850 if (maxCell) { 5851 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 5852 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 5853 } 5854 dm->periodic = per; 5855 PetscFunctionReturn(0); 5856 } 5857 5858 /*@ 5859 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. 5860 5861 Input Parameters: 5862 + dm - The DM 5863 . in - The input coordinate point (dim numbers) 5864 - endpoint - Include the endpoint L_i 5865 5866 Output Parameter: 5867 . out - The localized coordinate point 5868 5869 Level: developer 5870 5871 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5872 @*/ 5873 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 5874 { 5875 PetscInt dim, d; 5876 PetscErrorCode ierr; 5877 5878 PetscFunctionBegin; 5879 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 5880 if (!dm->maxCell) { 5881 for (d = 0; d < dim; ++d) out[d] = in[d]; 5882 } else { 5883 if (endpoint) { 5884 for (d = 0; d < dim; ++d) { 5885 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)) { 5886 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 5887 } else { 5888 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5889 } 5890 } 5891 } else { 5892 for (d = 0; d < dim; ++d) { 5893 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5894 } 5895 } 5896 } 5897 PetscFunctionReturn(0); 5898 } 5899 5900 /* 5901 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. 5902 5903 Input Parameters: 5904 + dm - The DM 5905 . dim - The spatial dimension 5906 . anchor - The anchor point, the input point can be no more than maxCell away from it 5907 - in - The input coordinate point (dim numbers) 5908 5909 Output Parameter: 5910 . out - The localized coordinate point 5911 5912 Level: developer 5913 5914 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 5915 5916 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5917 */ 5918 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5919 { 5920 PetscInt d; 5921 5922 PetscFunctionBegin; 5923 if (!dm->maxCell) { 5924 for (d = 0; d < dim; ++d) out[d] = in[d]; 5925 } else { 5926 for (d = 0; d < dim; ++d) { 5927 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5928 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5929 } else { 5930 out[d] = in[d]; 5931 } 5932 } 5933 } 5934 PetscFunctionReturn(0); 5935 } 5936 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 5937 { 5938 PetscInt d; 5939 5940 PetscFunctionBegin; 5941 if (!dm->maxCell) { 5942 for (d = 0; d < dim; ++d) out[d] = in[d]; 5943 } else { 5944 for (d = 0; d < dim; ++d) { 5945 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 5946 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5947 } else { 5948 out[d] = in[d]; 5949 } 5950 } 5951 } 5952 PetscFunctionReturn(0); 5953 } 5954 5955 /* 5956 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. 5957 5958 Input Parameters: 5959 + dm - The DM 5960 . dim - The spatial dimension 5961 . anchor - The anchor point, the input point can be no more than maxCell away from it 5962 . in - The input coordinate delta (dim numbers) 5963 - out - The input coordinate point (dim numbers) 5964 5965 Output Parameter: 5966 . out - The localized coordinate in + out 5967 5968 Level: developer 5969 5970 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 5971 5972 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 5973 */ 5974 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5975 { 5976 PetscInt d; 5977 5978 PetscFunctionBegin; 5979 if (!dm->maxCell) { 5980 for (d = 0; d < dim; ++d) out[d] += in[d]; 5981 } else { 5982 for (d = 0; d < dim; ++d) { 5983 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5984 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5985 } else { 5986 out[d] += in[d]; 5987 } 5988 } 5989 } 5990 PetscFunctionReturn(0); 5991 } 5992 5993 /*@ 5994 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 5995 5996 Not collective 5997 5998 Input Parameter: 5999 . dm - The DM 6000 6001 Output Parameter: 6002 areLocalized - True if localized 6003 6004 Level: developer 6005 6006 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6007 @*/ 6008 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6009 { 6010 DM cdm; 6011 PetscSection coordSection; 6012 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 6013 PetscBool isPlex, alreadyLocalized; 6014 PetscErrorCode ierr; 6015 6016 PetscFunctionBegin; 6017 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6018 PetscValidPointer(areLocalized, 2); 6019 *areLocalized = PETSC_FALSE; 6020 6021 /* We need some generic way of refering to cells/vertices */ 6022 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6023 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6024 if (!isPlex) PetscFunctionReturn(0); 6025 6026 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6027 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6028 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6029 alreadyLocalized = PETSC_FALSE; 6030 for (c = cStart; c < cEnd; ++c) { 6031 if (c < sStart || c >= sEnd) continue; 6032 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6033 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6034 } 6035 *areLocalized = alreadyLocalized; 6036 PetscFunctionReturn(0); 6037 } 6038 6039 /*@ 6040 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6041 6042 Collective on dm 6043 6044 Input Parameter: 6045 . dm - The DM 6046 6047 Output Parameter: 6048 areLocalized - True if localized 6049 6050 Level: developer 6051 6052 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6053 @*/ 6054 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6055 { 6056 PetscBool localized; 6057 PetscErrorCode ierr; 6058 6059 PetscFunctionBegin; 6060 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6061 PetscValidPointer(areLocalized, 2); 6062 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6063 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6064 PetscFunctionReturn(0); 6065 } 6066 6067 /*@ 6068 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6069 6070 Collective on dm 6071 6072 Input Parameter: 6073 . dm - The DM 6074 6075 Level: developer 6076 6077 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6078 @*/ 6079 PetscErrorCode DMLocalizeCoordinates(DM dm) 6080 { 6081 DM cdm; 6082 PetscSection coordSection, cSection; 6083 Vec coordinates, cVec; 6084 PetscScalar *coords, *coords2, *anchor, *localized; 6085 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6086 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6087 PetscInt maxHeight = 0, h; 6088 PetscInt *pStart = NULL, *pEnd = NULL; 6089 PetscErrorCode ierr; 6090 6091 PetscFunctionBegin; 6092 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6093 if (!dm->periodic) PetscFunctionReturn(0); 6094 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6095 if (alreadyLocalized) PetscFunctionReturn(0); 6096 6097 /* We need some generic way of refering to cells/vertices */ 6098 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6099 { 6100 PetscBool isplex; 6101 6102 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6103 if (isplex) { 6104 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6105 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6106 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6107 pEnd = &pStart[maxHeight + 1]; 6108 newStart = vStart; 6109 newEnd = vEnd; 6110 for (h = 0; h <= maxHeight; h++) { 6111 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6112 newStart = PetscMin(newStart,pStart[h]); 6113 newEnd = PetscMax(newEnd,pEnd[h]); 6114 } 6115 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6116 } 6117 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6118 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6119 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6120 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6121 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6122 6123 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6124 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6125 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6126 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6127 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6128 6129 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6130 localized = &anchor[bs]; 6131 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6132 for (h = 0; h <= maxHeight; h++) { 6133 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6134 6135 for (c = cStart; c < cEnd; ++c) { 6136 PetscScalar *cellCoords = NULL; 6137 PetscInt b; 6138 6139 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6140 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6141 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6142 for (d = 0; d < dof/bs; ++d) { 6143 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6144 for (b = 0; b < bs; b++) { 6145 if (cellCoords[d*bs + b] != localized[b]) break; 6146 } 6147 if (b < bs) break; 6148 } 6149 if (d < dof/bs) { 6150 if (c >= sStart && c < sEnd) { 6151 PetscInt cdof; 6152 6153 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6154 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6155 } 6156 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6157 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6158 } 6159 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6160 } 6161 } 6162 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6163 if (alreadyLocalizedGlobal) { 6164 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6165 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6166 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6167 PetscFunctionReturn(0); 6168 } 6169 for (v = vStart; v < vEnd; ++v) { 6170 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6171 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6172 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6173 } 6174 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6175 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6176 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6177 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6178 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6179 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6180 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6181 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6182 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 6183 for (v = vStart; v < vEnd; ++v) { 6184 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6185 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6186 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 6187 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 6188 } 6189 for (h = 0; h <= maxHeight; h++) { 6190 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6191 6192 for (c = cStart; c < cEnd; ++c) { 6193 PetscScalar *cellCoords = NULL; 6194 PetscInt b, cdof; 6195 6196 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 6197 if (!cdof) continue; 6198 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6199 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 6200 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6201 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 6202 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6203 } 6204 } 6205 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6206 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6207 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6208 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 6209 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 6210 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 6211 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 6212 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6213 PetscFunctionReturn(0); 6214 } 6215 6216 /*@ 6217 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 6218 6219 Collective on Vec v (see explanation below) 6220 6221 Input Parameters: 6222 + dm - The DM 6223 . v - The Vec of points 6224 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 6225 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 6226 6227 Output Parameter: 6228 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 6229 - cells - The PetscSF containing the ranks and local indices of the containing points. 6230 6231 6232 Level: developer 6233 6234 Notes: 6235 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 6236 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 6237 6238 If *cellSF is NULL on input, a PetscSF will be created. 6239 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 6240 6241 An array that maps each point to its containing cell can be obtained with 6242 6243 $ const PetscSFNode *cells; 6244 $ PetscInt nFound; 6245 $ const PetscInt *found; 6246 $ 6247 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 6248 6249 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 6250 the index of the cell in its rank's local numbering. 6251 6252 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 6253 @*/ 6254 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 6255 { 6256 PetscErrorCode ierr; 6257 6258 PetscFunctionBegin; 6259 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6260 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 6261 PetscValidPointer(cellSF,4); 6262 if (*cellSF) { 6263 PetscMPIInt result; 6264 6265 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 6266 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 6267 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 6268 } else { 6269 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 6270 } 6271 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6272 if (dm->ops->locatepoints) { 6273 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 6274 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 6275 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6276 PetscFunctionReturn(0); 6277 } 6278 6279 /*@ 6280 DMGetOutputDM - Retrieve the DM associated with the layout for output 6281 6282 Collective on dm 6283 6284 Input Parameter: 6285 . dm - The original DM 6286 6287 Output Parameter: 6288 . odm - The DM which provides the layout for output 6289 6290 Level: intermediate 6291 6292 .seealso: VecView(), DMGetGlobalSection() 6293 @*/ 6294 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 6295 { 6296 PetscSection section; 6297 PetscBool hasConstraints, ghasConstraints; 6298 PetscErrorCode ierr; 6299 6300 PetscFunctionBegin; 6301 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6302 PetscValidPointer(odm,2); 6303 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 6304 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 6305 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6306 if (!ghasConstraints) { 6307 *odm = dm; 6308 PetscFunctionReturn(0); 6309 } 6310 if (!dm->dmBC) { 6311 PetscSection newSection, gsection; 6312 PetscSF sf; 6313 6314 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 6315 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 6316 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 6317 ierr = DMSetSection(dm->dmBC, newSection);CHKERRQ(ierr); 6318 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 6319 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 6320 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 6321 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 6322 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 6323 } 6324 *odm = dm->dmBC; 6325 PetscFunctionReturn(0); 6326 } 6327 6328 /*@ 6329 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 6330 6331 Input Parameter: 6332 . dm - The original DM 6333 6334 Output Parameters: 6335 + num - The output sequence number 6336 - val - The output sequence value 6337 6338 Level: intermediate 6339 6340 Note: This is intended for output that should appear in sequence, for instance 6341 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6342 6343 .seealso: VecView() 6344 @*/ 6345 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 6346 { 6347 PetscFunctionBegin; 6348 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6349 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 6350 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 6351 PetscFunctionReturn(0); 6352 } 6353 6354 /*@ 6355 DMSetOutputSequenceNumber - Set the sequence number/value for output 6356 6357 Input Parameters: 6358 + dm - The original DM 6359 . num - The output sequence number 6360 - val - The output sequence value 6361 6362 Level: intermediate 6363 6364 Note: This is intended for output that should appear in sequence, for instance 6365 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6366 6367 .seealso: VecView() 6368 @*/ 6369 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 6370 { 6371 PetscFunctionBegin; 6372 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6373 dm->outputSequenceNum = num; 6374 dm->outputSequenceVal = val; 6375 PetscFunctionReturn(0); 6376 } 6377 6378 /*@C 6379 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 6380 6381 Input Parameters: 6382 + dm - The original DM 6383 . name - The sequence name 6384 - num - The output sequence number 6385 6386 Output Parameter: 6387 . val - The output sequence value 6388 6389 Level: intermediate 6390 6391 Note: This is intended for output that should appear in sequence, for instance 6392 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6393 6394 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 6395 @*/ 6396 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 6397 { 6398 PetscBool ishdf5; 6399 PetscErrorCode ierr; 6400 6401 PetscFunctionBegin; 6402 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6403 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 6404 PetscValidPointer(val,4); 6405 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 6406 if (ishdf5) { 6407 #if defined(PETSC_HAVE_HDF5) 6408 PetscScalar value; 6409 6410 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 6411 *val = PetscRealPart(value); 6412 #endif 6413 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 6414 PetscFunctionReturn(0); 6415 } 6416 6417 /*@ 6418 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 6419 6420 Not collective 6421 6422 Input Parameter: 6423 . dm - The DM 6424 6425 Output Parameter: 6426 . useNatural - The flag to build the mapping to a natural order during distribution 6427 6428 Level: beginner 6429 6430 .seealso: DMSetUseNatural(), DMCreate() 6431 @*/ 6432 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 6433 { 6434 PetscFunctionBegin; 6435 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6436 PetscValidPointer(useNatural, 2); 6437 *useNatural = dm->useNatural; 6438 PetscFunctionReturn(0); 6439 } 6440 6441 /*@ 6442 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 6443 6444 Collective on dm 6445 6446 Input Parameters: 6447 + dm - The DM 6448 - useNatural - The flag to build the mapping to a natural order during distribution 6449 6450 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 6451 6452 Level: beginner 6453 6454 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 6455 @*/ 6456 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 6457 { 6458 PetscFunctionBegin; 6459 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6460 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 6461 dm->useNatural = useNatural; 6462 PetscFunctionReturn(0); 6463 } 6464 6465 6466 /*@C 6467 DMCreateLabel - Create a label of the given name if it does not already exist 6468 6469 Not Collective 6470 6471 Input Parameters: 6472 + dm - The DM object 6473 - name - The label name 6474 6475 Level: intermediate 6476 6477 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6478 @*/ 6479 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 6480 { 6481 DMLabelLink next = dm->labels->next; 6482 PetscBool flg = PETSC_FALSE; 6483 const char *lname; 6484 PetscErrorCode ierr; 6485 6486 PetscFunctionBegin; 6487 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6488 PetscValidCharPointer(name, 2); 6489 while (next) { 6490 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6491 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 6492 if (flg) break; 6493 next = next->next; 6494 } 6495 if (!flg) { 6496 DMLabelLink tmpLabel; 6497 6498 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 6499 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &tmpLabel->label);CHKERRQ(ierr); 6500 tmpLabel->output = PETSC_TRUE; 6501 tmpLabel->next = dm->labels->next; 6502 dm->labels->next = tmpLabel; 6503 } 6504 PetscFunctionReturn(0); 6505 } 6506 6507 /*@C 6508 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 6509 6510 Not Collective 6511 6512 Input Parameters: 6513 + dm - The DM object 6514 . name - The label name 6515 - point - The mesh point 6516 6517 Output Parameter: 6518 . value - The label value for this point, or -1 if the point is not in the label 6519 6520 Level: beginner 6521 6522 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 6523 @*/ 6524 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 6525 { 6526 DMLabel label; 6527 PetscErrorCode ierr; 6528 6529 PetscFunctionBegin; 6530 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6531 PetscValidCharPointer(name, 2); 6532 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6533 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 6534 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 6535 PetscFunctionReturn(0); 6536 } 6537 6538 /*@C 6539 DMSetLabelValue - Add a point to a Sieve Label with given value 6540 6541 Not Collective 6542 6543 Input Parameters: 6544 + dm - The DM object 6545 . name - The label name 6546 . point - The mesh point 6547 - value - The label value for this point 6548 6549 Output Parameter: 6550 6551 Level: beginner 6552 6553 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 6554 @*/ 6555 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6556 { 6557 DMLabel label; 6558 PetscErrorCode ierr; 6559 6560 PetscFunctionBegin; 6561 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6562 PetscValidCharPointer(name, 2); 6563 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6564 if (!label) { 6565 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 6566 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6567 } 6568 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 6569 PetscFunctionReturn(0); 6570 } 6571 6572 /*@C 6573 DMClearLabelValue - Remove a point from a Sieve Label with given value 6574 6575 Not Collective 6576 6577 Input Parameters: 6578 + dm - The DM object 6579 . name - The label name 6580 . point - The mesh point 6581 - value - The label value for this point 6582 6583 Output Parameter: 6584 6585 Level: beginner 6586 6587 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 6588 @*/ 6589 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6590 { 6591 DMLabel label; 6592 PetscErrorCode ierr; 6593 6594 PetscFunctionBegin; 6595 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6596 PetscValidCharPointer(name, 2); 6597 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6598 if (!label) PetscFunctionReturn(0); 6599 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 6600 PetscFunctionReturn(0); 6601 } 6602 6603 /*@C 6604 DMGetLabelSize - Get the number of different integer ids in a Label 6605 6606 Not Collective 6607 6608 Input Parameters: 6609 + dm - The DM object 6610 - name - The label name 6611 6612 Output Parameter: 6613 . size - The number of different integer ids, or 0 if the label does not exist 6614 6615 Level: beginner 6616 6617 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 6618 @*/ 6619 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 6620 { 6621 DMLabel label; 6622 PetscErrorCode ierr; 6623 6624 PetscFunctionBegin; 6625 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6626 PetscValidCharPointer(name, 2); 6627 PetscValidPointer(size, 3); 6628 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6629 *size = 0; 6630 if (!label) PetscFunctionReturn(0); 6631 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 6632 PetscFunctionReturn(0); 6633 } 6634 6635 /*@C 6636 DMGetLabelIdIS - Get the integer ids in a label 6637 6638 Not Collective 6639 6640 Input Parameters: 6641 + mesh - The DM object 6642 - name - The label name 6643 6644 Output Parameter: 6645 . ids - The integer ids, or NULL if the label does not exist 6646 6647 Level: beginner 6648 6649 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 6650 @*/ 6651 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 6652 { 6653 DMLabel label; 6654 PetscErrorCode ierr; 6655 6656 PetscFunctionBegin; 6657 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6658 PetscValidCharPointer(name, 2); 6659 PetscValidPointer(ids, 3); 6660 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6661 *ids = NULL; 6662 if (label) { 6663 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 6664 } else { 6665 /* returning an empty IS */ 6666 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 6667 } 6668 PetscFunctionReturn(0); 6669 } 6670 6671 /*@C 6672 DMGetStratumSize - Get the number of points in a label stratum 6673 6674 Not Collective 6675 6676 Input Parameters: 6677 + dm - The DM object 6678 . name - The label name 6679 - value - The stratum value 6680 6681 Output Parameter: 6682 . size - The stratum size 6683 6684 Level: beginner 6685 6686 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 6687 @*/ 6688 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 6689 { 6690 DMLabel label; 6691 PetscErrorCode ierr; 6692 6693 PetscFunctionBegin; 6694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6695 PetscValidCharPointer(name, 2); 6696 PetscValidPointer(size, 4); 6697 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6698 *size = 0; 6699 if (!label) PetscFunctionReturn(0); 6700 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 6701 PetscFunctionReturn(0); 6702 } 6703 6704 /*@C 6705 DMGetStratumIS - Get the points in a label stratum 6706 6707 Not Collective 6708 6709 Input Parameters: 6710 + dm - The DM object 6711 . name - The label name 6712 - value - The stratum value 6713 6714 Output Parameter: 6715 . points - The stratum points, or NULL if the label does not exist or does not have that value 6716 6717 Level: beginner 6718 6719 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 6720 @*/ 6721 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 6722 { 6723 DMLabel label; 6724 PetscErrorCode ierr; 6725 6726 PetscFunctionBegin; 6727 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6728 PetscValidCharPointer(name, 2); 6729 PetscValidPointer(points, 4); 6730 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6731 *points = NULL; 6732 if (!label) PetscFunctionReturn(0); 6733 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 6734 PetscFunctionReturn(0); 6735 } 6736 6737 /*@C 6738 DMSetStratumIS - Set the points in a label stratum 6739 6740 Not Collective 6741 6742 Input Parameters: 6743 + dm - The DM object 6744 . name - The label name 6745 . value - The stratum value 6746 - points - The stratum points 6747 6748 Level: beginner 6749 6750 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 6751 @*/ 6752 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 6753 { 6754 DMLabel label; 6755 PetscErrorCode ierr; 6756 6757 PetscFunctionBegin; 6758 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6759 PetscValidCharPointer(name, 2); 6760 PetscValidPointer(points, 4); 6761 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6762 if (!label) PetscFunctionReturn(0); 6763 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 6764 PetscFunctionReturn(0); 6765 } 6766 6767 /*@C 6768 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 6769 6770 Not Collective 6771 6772 Input Parameters: 6773 + dm - The DM object 6774 . name - The label name 6775 - value - The label value for this point 6776 6777 Output Parameter: 6778 6779 Level: beginner 6780 6781 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 6782 @*/ 6783 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 6784 { 6785 DMLabel label; 6786 PetscErrorCode ierr; 6787 6788 PetscFunctionBegin; 6789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6790 PetscValidCharPointer(name, 2); 6791 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6792 if (!label) PetscFunctionReturn(0); 6793 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 6794 PetscFunctionReturn(0); 6795 } 6796 6797 /*@ 6798 DMGetNumLabels - Return the number of labels defined by the mesh 6799 6800 Not Collective 6801 6802 Input Parameter: 6803 . dm - The DM object 6804 6805 Output Parameter: 6806 . numLabels - the number of Labels 6807 6808 Level: intermediate 6809 6810 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6811 @*/ 6812 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 6813 { 6814 DMLabelLink next = dm->labels->next; 6815 PetscInt n = 0; 6816 6817 PetscFunctionBegin; 6818 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6819 PetscValidPointer(numLabels, 2); 6820 while (next) {++n; next = next->next;} 6821 *numLabels = n; 6822 PetscFunctionReturn(0); 6823 } 6824 6825 /*@C 6826 DMGetLabelName - Return the name of nth label 6827 6828 Not Collective 6829 6830 Input Parameters: 6831 + dm - The DM object 6832 - n - the label number 6833 6834 Output Parameter: 6835 . name - the label name 6836 6837 Level: intermediate 6838 6839 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6840 @*/ 6841 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 6842 { 6843 DMLabelLink next = dm->labels->next; 6844 PetscInt l = 0; 6845 PetscErrorCode ierr; 6846 6847 PetscFunctionBegin; 6848 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6849 PetscValidPointer(name, 3); 6850 while (next) { 6851 if (l == n) { 6852 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 6853 PetscFunctionReturn(0); 6854 } 6855 ++l; 6856 next = next->next; 6857 } 6858 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6859 } 6860 6861 /*@C 6862 DMHasLabel - Determine whether the mesh has a label of a given name 6863 6864 Not Collective 6865 6866 Input Parameters: 6867 + dm - The DM object 6868 - name - The label name 6869 6870 Output Parameter: 6871 . hasLabel - PETSC_TRUE if the label is present 6872 6873 Level: intermediate 6874 6875 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6876 @*/ 6877 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 6878 { 6879 DMLabelLink next = dm->labels->next; 6880 const char *lname; 6881 PetscErrorCode ierr; 6882 6883 PetscFunctionBegin; 6884 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6885 PetscValidCharPointer(name, 2); 6886 PetscValidPointer(hasLabel, 3); 6887 *hasLabel = PETSC_FALSE; 6888 while (next) { 6889 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6890 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 6891 if (*hasLabel) break; 6892 next = next->next; 6893 } 6894 PetscFunctionReturn(0); 6895 } 6896 6897 /*@C 6898 DMGetLabel - Return the label of a given name, or NULL 6899 6900 Not Collective 6901 6902 Input Parameters: 6903 + dm - The DM object 6904 - name - The label name 6905 6906 Output Parameter: 6907 . label - The DMLabel, or NULL if the label is absent 6908 6909 Level: intermediate 6910 6911 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6912 @*/ 6913 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 6914 { 6915 DMLabelLink next = dm->labels->next; 6916 PetscBool hasLabel; 6917 const char *lname; 6918 PetscErrorCode ierr; 6919 6920 PetscFunctionBegin; 6921 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6922 PetscValidCharPointer(name, 2); 6923 PetscValidPointer(label, 3); 6924 *label = NULL; 6925 while (next) { 6926 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6927 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 6928 if (hasLabel) { 6929 *label = next->label; 6930 break; 6931 } 6932 next = next->next; 6933 } 6934 PetscFunctionReturn(0); 6935 } 6936 6937 /*@C 6938 DMGetLabelByNum - Return the nth label 6939 6940 Not Collective 6941 6942 Input Parameters: 6943 + dm - The DM object 6944 - n - the label number 6945 6946 Output Parameter: 6947 . label - the label 6948 6949 Level: intermediate 6950 6951 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6952 @*/ 6953 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 6954 { 6955 DMLabelLink next = dm->labels->next; 6956 PetscInt l = 0; 6957 6958 PetscFunctionBegin; 6959 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6960 PetscValidPointer(label, 3); 6961 while (next) { 6962 if (l == n) { 6963 *label = next->label; 6964 PetscFunctionReturn(0); 6965 } 6966 ++l; 6967 next = next->next; 6968 } 6969 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6970 } 6971 6972 /*@C 6973 DMAddLabel - Add the label to this mesh 6974 6975 Not Collective 6976 6977 Input Parameters: 6978 + dm - The DM object 6979 - label - The DMLabel 6980 6981 Level: developer 6982 6983 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6984 @*/ 6985 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 6986 { 6987 DMLabelLink tmpLabel; 6988 PetscBool hasLabel; 6989 const char *lname; 6990 PetscErrorCode ierr; 6991 6992 PetscFunctionBegin; 6993 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6994 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 6995 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 6996 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 6997 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 6998 tmpLabel->label = label; 6999 tmpLabel->output = PETSC_TRUE; 7000 tmpLabel->next = dm->labels->next; 7001 dm->labels->next = tmpLabel; 7002 PetscFunctionReturn(0); 7003 } 7004 7005 /*@C 7006 DMRemoveLabel - Remove the label from this mesh 7007 7008 Not Collective 7009 7010 Input Parameters: 7011 + dm - The DM object 7012 - name - The label name 7013 7014 Output Parameter: 7015 . label - The DMLabel, or NULL if the label is absent 7016 7017 Level: developer 7018 7019 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7020 @*/ 7021 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7022 { 7023 DMLabelLink next = dm->labels->next; 7024 DMLabelLink last = NULL; 7025 PetscBool hasLabel; 7026 const char *lname; 7027 PetscErrorCode ierr; 7028 7029 PetscFunctionBegin; 7030 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7031 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 7032 *label = NULL; 7033 if (!hasLabel) PetscFunctionReturn(0); 7034 while (next) { 7035 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7036 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7037 if (hasLabel) { 7038 if (last) last->next = next->next; 7039 else dm->labels->next = next->next; 7040 next->next = NULL; 7041 *label = next->label; 7042 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 7043 if (hasLabel) { 7044 dm->depthLabel = NULL; 7045 } 7046 ierr = PetscFree(next);CHKERRQ(ierr); 7047 break; 7048 } 7049 last = next; 7050 next = next->next; 7051 } 7052 PetscFunctionReturn(0); 7053 } 7054 7055 /*@C 7056 DMGetLabelOutput - Get the output flag for a given label 7057 7058 Not Collective 7059 7060 Input Parameters: 7061 + dm - The DM object 7062 - name - The label name 7063 7064 Output Parameter: 7065 . output - The flag for output 7066 7067 Level: developer 7068 7069 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7070 @*/ 7071 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 7072 { 7073 DMLabelLink next = dm->labels->next; 7074 const char *lname; 7075 PetscErrorCode ierr; 7076 7077 PetscFunctionBegin; 7078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7079 PetscValidPointer(name, 2); 7080 PetscValidPointer(output, 3); 7081 while (next) { 7082 PetscBool flg; 7083 7084 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7085 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7086 if (flg) {*output = next->output; PetscFunctionReturn(0);} 7087 next = next->next; 7088 } 7089 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7090 } 7091 7092 /*@C 7093 DMSetLabelOutput - Set the output flag for a given label 7094 7095 Not Collective 7096 7097 Input Parameters: 7098 + dm - The DM object 7099 . name - The label name 7100 - output - The flag for output 7101 7102 Level: developer 7103 7104 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7105 @*/ 7106 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 7107 { 7108 DMLabelLink next = dm->labels->next; 7109 const char *lname; 7110 PetscErrorCode ierr; 7111 7112 PetscFunctionBegin; 7113 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7114 PetscValidPointer(name, 2); 7115 while (next) { 7116 PetscBool flg; 7117 7118 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7119 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7120 if (flg) {next->output = output; PetscFunctionReturn(0);} 7121 next = next->next; 7122 } 7123 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7124 } 7125 7126 7127 /*@ 7128 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 7129 7130 Collective on DM 7131 7132 Input Parameter: 7133 . dmA - The DM object with initial labels 7134 7135 Output Parameter: 7136 . dmB - The DM object with copied labels 7137 7138 Level: intermediate 7139 7140 Note: This is typically used when interpolating or otherwise adding to a mesh 7141 7142 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 7143 @*/ 7144 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 7145 { 7146 PetscInt numLabels, l; 7147 PetscErrorCode ierr; 7148 7149 PetscFunctionBegin; 7150 if (dmA == dmB) PetscFunctionReturn(0); 7151 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 7152 for (l = 0; l < numLabels; ++l) { 7153 DMLabel label, labelNew; 7154 const char *name; 7155 PetscBool flg; 7156 7157 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 7158 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 7159 if (flg) continue; 7160 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 7161 if (flg) continue; 7162 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 7163 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 7164 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 7165 } 7166 PetscFunctionReturn(0); 7167 } 7168 7169 /*@ 7170 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 7171 7172 Input Parameter: 7173 . dm - The DM object 7174 7175 Output Parameter: 7176 . cdm - The coarse DM 7177 7178 Level: intermediate 7179 7180 .seealso: DMSetCoarseDM() 7181 @*/ 7182 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 7183 { 7184 PetscFunctionBegin; 7185 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7186 PetscValidPointer(cdm, 2); 7187 *cdm = dm->coarseMesh; 7188 PetscFunctionReturn(0); 7189 } 7190 7191 /*@ 7192 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 7193 7194 Input Parameters: 7195 + dm - The DM object 7196 - cdm - The coarse DM 7197 7198 Level: intermediate 7199 7200 .seealso: DMGetCoarseDM() 7201 @*/ 7202 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 7203 { 7204 PetscErrorCode ierr; 7205 7206 PetscFunctionBegin; 7207 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7208 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 7209 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 7210 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 7211 dm->coarseMesh = cdm; 7212 PetscFunctionReturn(0); 7213 } 7214 7215 /*@ 7216 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 7217 7218 Input Parameter: 7219 . dm - The DM object 7220 7221 Output Parameter: 7222 . fdm - The fine DM 7223 7224 Level: intermediate 7225 7226 .seealso: DMSetFineDM() 7227 @*/ 7228 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 7229 { 7230 PetscFunctionBegin; 7231 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7232 PetscValidPointer(fdm, 2); 7233 *fdm = dm->fineMesh; 7234 PetscFunctionReturn(0); 7235 } 7236 7237 /*@ 7238 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 7239 7240 Input Parameters: 7241 + dm - The DM object 7242 - fdm - The fine DM 7243 7244 Level: intermediate 7245 7246 .seealso: DMGetFineDM() 7247 @*/ 7248 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 7249 { 7250 PetscErrorCode ierr; 7251 7252 PetscFunctionBegin; 7253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7254 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 7255 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 7256 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 7257 dm->fineMesh = fdm; 7258 PetscFunctionReturn(0); 7259 } 7260 7261 /*=== DMBoundary code ===*/ 7262 7263 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 7264 { 7265 PetscInt d; 7266 PetscErrorCode ierr; 7267 7268 PetscFunctionBegin; 7269 for (d = 0; d < dm->Nds; ++d) { 7270 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr); 7271 } 7272 PetscFunctionReturn(0); 7273 } 7274 7275 /*@C 7276 DMAddBoundary - Add a boundary condition to the model 7277 7278 Input Parameters: 7279 + dm - The DM, with a PetscDS that matches the problem being constrained 7280 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7281 . name - The BC name 7282 . labelname - The label defining constrained points 7283 . field - The field to constrain 7284 . numcomps - The number of constrained field components (0 will constrain all fields) 7285 . comps - An array of constrained component numbers 7286 . bcFunc - A pointwise function giving boundary values 7287 . numids - The number of DMLabel ids for constrained points 7288 . ids - An array of ids for constrained points 7289 - ctx - An optional user context for bcFunc 7290 7291 Options Database Keys: 7292 + -bc_<boundary name> <num> - Overrides the boundary ids 7293 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7294 7295 Level: developer 7296 7297 .seealso: DMGetBoundary() 7298 @*/ 7299 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) 7300 { 7301 PetscDS ds; 7302 PetscErrorCode ierr; 7303 7304 PetscFunctionBegin; 7305 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7306 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7307 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, numids, ids, ctx);CHKERRQ(ierr); 7308 PetscFunctionReturn(0); 7309 } 7310 7311 /*@ 7312 DMGetNumBoundary - Get the number of registered BC 7313 7314 Input Parameters: 7315 . dm - The mesh object 7316 7317 Output Parameters: 7318 . numBd - The number of BC 7319 7320 Level: intermediate 7321 7322 .seealso: DMAddBoundary(), DMGetBoundary() 7323 @*/ 7324 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 7325 { 7326 PetscDS ds; 7327 PetscErrorCode ierr; 7328 7329 PetscFunctionBegin; 7330 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7331 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7332 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr); 7333 PetscFunctionReturn(0); 7334 } 7335 7336 /*@C 7337 DMGetBoundary - Get a model boundary condition 7338 7339 Input Parameters: 7340 + dm - The mesh object 7341 - bd - The BC number 7342 7343 Output Parameters: 7344 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7345 . name - The BC name 7346 . labelname - The label defining constrained points 7347 . field - The field to constrain 7348 . numcomps - The number of constrained field components 7349 . comps - An array of constrained component numbers 7350 . bcFunc - A pointwise function giving boundary values 7351 . numids - The number of DMLabel ids for constrained points 7352 . ids - An array of ids for constrained points 7353 - ctx - An optional user context for bcFunc 7354 7355 Options Database Keys: 7356 + -bc_<boundary name> <num> - Overrides the boundary ids 7357 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7358 7359 Level: developer 7360 7361 .seealso: DMAddBoundary() 7362 @*/ 7363 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) 7364 { 7365 PetscDS ds; 7366 PetscErrorCode ierr; 7367 7368 PetscFunctionBegin; 7369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7370 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7371 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, numids, ids, ctx);CHKERRQ(ierr); 7372 PetscFunctionReturn(0); 7373 } 7374 7375 static PetscErrorCode DMPopulateBoundary(DM dm) 7376 { 7377 PetscDS ds; 7378 DMBoundary *lastnext; 7379 DSBoundary dsbound; 7380 PetscErrorCode ierr; 7381 7382 PetscFunctionBegin; 7383 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7384 dsbound = ds->boundary; 7385 if (dm->boundary) { 7386 DMBoundary next = dm->boundary; 7387 7388 /* quick check to see if the PetscDS has changed */ 7389 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 7390 /* the PetscDS has changed: tear down and rebuild */ 7391 while (next) { 7392 DMBoundary b = next; 7393 7394 next = b->next; 7395 ierr = PetscFree(b);CHKERRQ(ierr); 7396 } 7397 dm->boundary = NULL; 7398 } 7399 7400 lastnext = &(dm->boundary); 7401 while (dsbound) { 7402 DMBoundary dmbound; 7403 7404 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 7405 dmbound->dsboundary = dsbound; 7406 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 7407 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 7408 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 7409 *lastnext = dmbound; 7410 lastnext = &(dmbound->next); 7411 dsbound = dsbound->next; 7412 } 7413 PetscFunctionReturn(0); 7414 } 7415 7416 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 7417 { 7418 DMBoundary b; 7419 PetscErrorCode ierr; 7420 7421 PetscFunctionBegin; 7422 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7423 PetscValidPointer(isBd, 3); 7424 *isBd = PETSC_FALSE; 7425 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 7426 b = dm->boundary; 7427 while (b && !(*isBd)) { 7428 DMLabel label = b->label; 7429 DSBoundary dsb = b->dsboundary; 7430 7431 if (label) { 7432 PetscInt i; 7433 7434 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 7435 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 7436 } 7437 } 7438 b = b->next; 7439 } 7440 PetscFunctionReturn(0); 7441 } 7442 7443 /*@C 7444 DMProjectFunction - This projects the given function into the function space provided. 7445 7446 Input Parameters: 7447 + dm - The DM 7448 . time - The time 7449 . funcs - The coordinate functions to evaluate, one per field 7450 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7451 - mode - The insertion mode for values 7452 7453 Output Parameter: 7454 . X - vector 7455 7456 Calling sequence of func: 7457 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7458 7459 + dim - The spatial dimension 7460 . x - The coordinates 7461 . Nf - The number of fields 7462 . u - The output field values 7463 - ctx - optional user-defined function context 7464 7465 Level: developer 7466 7467 .seealso: DMComputeL2Diff() 7468 @*/ 7469 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 7470 { 7471 Vec localX; 7472 PetscErrorCode ierr; 7473 7474 PetscFunctionBegin; 7475 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7476 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7477 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7478 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7479 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7480 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7481 PetscFunctionReturn(0); 7482 } 7483 7484 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 7485 { 7486 PetscErrorCode ierr; 7487 7488 PetscFunctionBegin; 7489 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7490 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7491 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 7492 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7493 PetscFunctionReturn(0); 7494 } 7495 7496 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) 7497 { 7498 Vec localX; 7499 PetscErrorCode ierr; 7500 7501 PetscFunctionBegin; 7502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7503 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7504 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7505 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7506 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7507 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7508 PetscFunctionReturn(0); 7509 } 7510 7511 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) 7512 { 7513 PetscErrorCode ierr; 7514 7515 PetscFunctionBegin; 7516 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7517 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7518 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 7519 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7520 PetscFunctionReturn(0); 7521 } 7522 7523 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 7524 void (**funcs)(PetscInt, PetscInt, PetscInt, 7525 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7526 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7527 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7528 InsertMode mode, Vec localX) 7529 { 7530 PetscErrorCode ierr; 7531 7532 PetscFunctionBegin; 7533 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7534 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 7535 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 7536 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7537 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 7538 PetscFunctionReturn(0); 7539 } 7540 7541 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 7542 void (**funcs)(PetscInt, PetscInt, PetscInt, 7543 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7544 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7545 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7546 InsertMode mode, Vec localX) 7547 { 7548 PetscErrorCode ierr; 7549 7550 PetscFunctionBegin; 7551 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7552 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 7553 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 7554 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7555 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 7556 PetscFunctionReturn(0); 7557 } 7558 7559 /*@C 7560 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 7561 7562 Input Parameters: 7563 + dm - The DM 7564 . time - The time 7565 . funcs - The functions to evaluate for each field component 7566 . ctxs - Optional array of contexts to pass to each function, or NULL. 7567 - X - The coefficient vector u_h, a global vector 7568 7569 Output Parameter: 7570 . diff - The diff ||u - u_h||_2 7571 7572 Level: developer 7573 7574 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 7575 @*/ 7576 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 7577 { 7578 PetscErrorCode ierr; 7579 7580 PetscFunctionBegin; 7581 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7582 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7583 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 7584 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 7585 PetscFunctionReturn(0); 7586 } 7587 7588 /*@C 7589 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 7590 7591 Input Parameters: 7592 + dm - The DM 7593 , time - The time 7594 . funcs - The gradient functions to evaluate for each field component 7595 . ctxs - Optional array of contexts to pass to each function, or NULL. 7596 . X - The coefficient vector u_h, a global vector 7597 - n - The vector to project along 7598 7599 Output Parameter: 7600 . diff - The diff ||(grad u - grad u_h) . n||_2 7601 7602 Level: developer 7603 7604 .seealso: DMProjectFunction(), DMComputeL2Diff() 7605 @*/ 7606 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) 7607 { 7608 PetscErrorCode ierr; 7609 7610 PetscFunctionBegin; 7611 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7612 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7613 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 7614 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 7615 PetscFunctionReturn(0); 7616 } 7617 7618 /*@C 7619 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 7620 7621 Input Parameters: 7622 + dm - The DM 7623 . time - The time 7624 . funcs - The functions to evaluate for each field component 7625 . ctxs - Optional array of contexts to pass to each function, or NULL. 7626 - X - The coefficient vector u_h, a global vector 7627 7628 Output Parameter: 7629 . diff - The array of differences, ||u^f - u^f_h||_2 7630 7631 Level: developer 7632 7633 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 7634 @*/ 7635 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 7636 { 7637 PetscErrorCode ierr; 7638 7639 PetscFunctionBegin; 7640 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7641 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7642 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 7643 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 7644 PetscFunctionReturn(0); 7645 } 7646 7647 /*@C 7648 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 7649 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 7650 7651 Collective on dm 7652 7653 Input parameters: 7654 + dm - the pre-adaptation DM object 7655 - label - label with the flags 7656 7657 Output parameters: 7658 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 7659 7660 Level: intermediate 7661 7662 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 7663 @*/ 7664 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 7665 { 7666 PetscErrorCode ierr; 7667 7668 PetscFunctionBegin; 7669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7670 PetscValidPointer(label,2); 7671 PetscValidPointer(dmAdapt,3); 7672 *dmAdapt = NULL; 7673 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 7674 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 7675 PetscFunctionReturn(0); 7676 } 7677 7678 /*@C 7679 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 7680 7681 Input Parameters: 7682 + dm - The DM object 7683 . metric - The metric to which the mesh is adapted, defined vertex-wise. 7684 - 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_". 7685 7686 Output Parameter: 7687 . dmAdapt - Pointer to the DM object containing the adapted mesh 7688 7689 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 7690 7691 Level: advanced 7692 7693 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 7694 @*/ 7695 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 7696 { 7697 PetscErrorCode ierr; 7698 7699 PetscFunctionBegin; 7700 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7701 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 7702 if (bdLabel) PetscValidPointer(bdLabel, 3); 7703 PetscValidPointer(dmAdapt, 4); 7704 *dmAdapt = NULL; 7705 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 7706 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 7707 PetscFunctionReturn(0); 7708 } 7709 7710 /*@C 7711 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 7712 7713 Not Collective 7714 7715 Input Parameter: 7716 . dm - The DM 7717 7718 Output Parameter: 7719 . nranks - the number of neighbours 7720 . ranks - the neighbors ranks 7721 7722 Notes: 7723 Do not free the array, it is freed when the DM is destroyed. 7724 7725 Level: beginner 7726 7727 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 7728 @*/ 7729 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 7730 { 7731 PetscErrorCode ierr; 7732 7733 PetscFunctionBegin; 7734 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7735 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 7736 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 7737 PetscFunctionReturn(0); 7738 } 7739 7740 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 7741 7742 /* 7743 Converts the input vector to a ghosted vector and then calls the standard coloring code. 7744 This has be a different function because it requires DM which is not defined in the Mat library 7745 */ 7746 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 7747 { 7748 PetscErrorCode ierr; 7749 7750 PetscFunctionBegin; 7751 if (coloring->ctype == IS_COLORING_LOCAL) { 7752 Vec x1local; 7753 DM dm; 7754 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 7755 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 7756 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 7757 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 7758 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 7759 x1 = x1local; 7760 } 7761 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 7762 if (coloring->ctype == IS_COLORING_LOCAL) { 7763 DM dm; 7764 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 7765 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 7766 } 7767 PetscFunctionReturn(0); 7768 } 7769 7770 /*@ 7771 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 7772 7773 Input Parameter: 7774 . coloring - the MatFDColoring object 7775 7776 Developer Notes: 7777 this routine exists because the PETSc Mat library does not know about the DM objects 7778 7779 Level: advanced 7780 7781 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 7782 @*/ 7783 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 7784 { 7785 PetscFunctionBegin; 7786 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 7787 PetscFunctionReturn(0); 7788 } 7789 7790 /*@ 7791 DMGetCompatibility - determine if two DMs are compatible 7792 7793 Collective 7794 7795 Input Parameters: 7796 + dm - the first DM 7797 - dm2 - the second DM 7798 7799 Output Parameters: 7800 + compatible - whether or not the two DMs are compatible 7801 - set - whether or not the compatible value was set 7802 7803 Notes: 7804 Two DMs are deemed compatible if they represent the same parallel decomposition 7805 of the same topology. This implies that the section (field data) on one 7806 "makes sense" with respect to the topology and parallel decomposition of the other. 7807 Loosely speaking, compatible DMs represent the same domain and parallel 7808 decomposition, but hold different data. 7809 7810 Typically, one would confirm compatibility if intending to simultaneously iterate 7811 over a pair of vectors obtained from different DMs. 7812 7813 For example, two DMDA objects are compatible if they have the same local 7814 and global sizes and the same stencil width. They can have different numbers 7815 of degrees of freedom per node. Thus, one could use the node numbering from 7816 either DM in bounds for a loop over vectors derived from either DM. 7817 7818 Consider the operation of summing data living on a 2-dof DMDA to data living 7819 on a 1-dof DMDA, which should be compatible, as in the following snippet. 7820 .vb 7821 ... 7822 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 7823 if (set && compatible) { 7824 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 7825 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 7826 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 7827 for (j=y; j<y+n; ++j) { 7828 for (i=x; i<x+m, ++i) { 7829 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 7830 } 7831 } 7832 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 7833 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 7834 } else { 7835 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 7836 } 7837 ... 7838 .ve 7839 7840 Checking compatibility might be expensive for a given implementation of DM, 7841 or might be impossible to unambiguously confirm or deny. For this reason, 7842 this function may decline to determine compatibility, and hence users should 7843 always check the "set" output parameter. 7844 7845 A DM is always compatible with itself. 7846 7847 In the current implementation, DMs which live on "unequal" communicators 7848 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 7849 incompatible. 7850 7851 This function is labeled "Collective," as information about all subdomains 7852 is required on each rank. However, in DM implementations which store all this 7853 information locally, this function may be merely "Logically Collective". 7854 7855 Developer Notes: 7856 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 7857 iff B is compatible with A. Thus, this function checks the implementations 7858 of both dm and dm2 (if they are of different types), attempting to determine 7859 compatibility. It is left to DM implementers to ensure that symmetry is 7860 preserved. The simplest way to do this is, when implementing type-specific 7861 logic for this function, is to check for existing logic in the implementation 7862 of other DM types and let *set = PETSC_FALSE if found. 7863 7864 Level: advanced 7865 7866 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 7867 @*/ 7868 7869 PetscErrorCode DMGetCompatibility(DM dm,DM dm2,PetscBool *compatible,PetscBool *set) 7870 { 7871 PetscErrorCode ierr; 7872 PetscMPIInt compareResult; 7873 DMType type,type2; 7874 PetscBool sameType; 7875 7876 PetscFunctionBegin; 7877 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7878 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 7879 7880 /* Declare a DM compatible with itself */ 7881 if (dm == dm2) { 7882 *set = PETSC_TRUE; 7883 *compatible = PETSC_TRUE; 7884 PetscFunctionReturn(0); 7885 } 7886 7887 /* Declare a DM incompatible with a DM that lives on an "unequal" 7888 communicator. Note that this does not preclude compatibility with 7889 DMs living on "congruent" or "similar" communicators, but this must be 7890 determined by the implementation-specific logic */ 7891 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 7892 if (compareResult == MPI_UNEQUAL) { 7893 *set = PETSC_TRUE; 7894 *compatible = PETSC_FALSE; 7895 PetscFunctionReturn(0); 7896 } 7897 7898 /* Pass to the implementation-specific routine, if one exists. */ 7899 if (dm->ops->getcompatibility) { 7900 ierr = (*dm->ops->getcompatibility)(dm,dm2,compatible,set);CHKERRQ(ierr); 7901 if (*set) { 7902 PetscFunctionReturn(0); 7903 } 7904 } 7905 7906 /* If dm and dm2 are of different types, then attempt to check compatibility 7907 with an implementation of this function from dm2 */ 7908 ierr = DMGetType(dm,&type);CHKERRQ(ierr); 7909 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 7910 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 7911 if (!sameType && dm2->ops->getcompatibility) { 7912 ierr = (*dm2->ops->getcompatibility)(dm2,dm,compatible,set);CHKERRQ(ierr); /* Note argument order */ 7913 } else { 7914 *set = PETSC_FALSE; 7915 } 7916 PetscFunctionReturn(0); 7917 } 7918