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