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