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