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