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 DMGlobalToLocalBegin - Begins updating 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 2146 Level: beginner 2147 2148 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2149 2150 @*/ 2151 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2152 { 2153 PetscSF sf; 2154 PetscErrorCode ierr; 2155 DMGlobalToLocalHookLink link; 2156 2157 PetscFunctionBegin; 2158 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2159 for (link=dm->gtolhook; link; link=link->next) { 2160 if (link->beginhook) { 2161 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 2162 } 2163 } 2164 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2165 if (sf) { 2166 const PetscScalar *gArray; 2167 PetscScalar *lArray; 2168 2169 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2170 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 2171 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 2172 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2173 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 2174 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 2175 } else { 2176 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2177 } 2178 PetscFunctionReturn(0); 2179 } 2180 2181 /*@ 2182 DMGlobalToLocalEnd - Ends updating local vectors from global vector 2183 2184 Neighbor-wise Collective on DM 2185 2186 Input Parameters: 2187 + dm - the DM object 2188 . g - the global vector 2189 . mode - INSERT_VALUES or ADD_VALUES 2190 - l - the local vector 2191 2192 2193 Level: beginner 2194 2195 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2196 2197 @*/ 2198 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2199 { 2200 PetscSF sf; 2201 PetscErrorCode ierr; 2202 const PetscScalar *gArray; 2203 PetscScalar *lArray; 2204 DMGlobalToLocalHookLink link; 2205 2206 PetscFunctionBegin; 2207 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2208 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2209 if (sf) { 2210 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2211 2212 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 2213 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 2214 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2215 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 2216 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 2217 } else { 2218 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2219 } 2220 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 2221 for (link=dm->gtolhook; link; link=link->next) { 2222 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2223 } 2224 PetscFunctionReturn(0); 2225 } 2226 2227 /*@C 2228 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 2229 2230 Logically Collective 2231 2232 Input Arguments: 2233 + dm - the DM 2234 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 2235 . endhook - function to run after DMLocalToGlobalEnd() has completed 2236 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2237 2238 Calling sequence for beginhook: 2239 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2240 2241 + dm - global DM 2242 . l - local vector 2243 . mode - mode 2244 . g - global vector 2245 - ctx - optional user-defined function context 2246 2247 2248 Calling sequence for endhook: 2249 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2250 2251 + global - global DM 2252 . l - local vector 2253 . mode - mode 2254 . g - global vector 2255 - ctx - optional user-defined function context 2256 2257 Level: advanced 2258 2259 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2260 @*/ 2261 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2262 { 2263 PetscErrorCode ierr; 2264 DMLocalToGlobalHookLink link,*p; 2265 2266 PetscFunctionBegin; 2267 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2268 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2269 ierr = PetscNew(&link);CHKERRQ(ierr); 2270 link->beginhook = beginhook; 2271 link->endhook = endhook; 2272 link->ctx = ctx; 2273 link->next = NULL; 2274 *p = link; 2275 PetscFunctionReturn(0); 2276 } 2277 2278 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 2279 { 2280 Mat cMat; 2281 Vec cVec; 2282 PetscSection section, cSec; 2283 PetscInt pStart, pEnd, p, dof; 2284 PetscErrorCode ierr; 2285 2286 PetscFunctionBegin; 2287 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2288 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2289 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 2290 PetscInt nRows; 2291 2292 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2293 if (nRows <= 0) PetscFunctionReturn(0); 2294 ierr = DMGetSection(dm,§ion);CHKERRQ(ierr); 2295 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2296 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2297 for (p = pStart; p < pEnd; p++) { 2298 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2299 if (dof) { 2300 PetscInt d; 2301 PetscScalar *vals; 2302 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 2303 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 2304 /* for this to be the true transpose, we have to zero the values that 2305 * we just extracted */ 2306 for (d = 0; d < dof; d++) { 2307 vals[d] = 0.; 2308 } 2309 } 2310 } 2311 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 2312 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2313 } 2314 PetscFunctionReturn(0); 2315 } 2316 2317 /*@ 2318 DMLocalToGlobalBegin - updates global vectors from local vectors 2319 2320 Neighbor-wise Collective on DM 2321 2322 Input Parameters: 2323 + dm - the DM object 2324 . l - the local vector 2325 . 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. 2326 - g - the global vector 2327 2328 Notes: 2329 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2330 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 2331 2332 Level: beginner 2333 2334 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2335 2336 @*/ 2337 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 2338 { 2339 PetscSF sf; 2340 PetscSection s, gs; 2341 DMLocalToGlobalHookLink link; 2342 const PetscScalar *lArray; 2343 PetscScalar *gArray; 2344 PetscBool isInsert; 2345 PetscErrorCode ierr; 2346 2347 PetscFunctionBegin; 2348 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2349 for (link=dm->ltoghook; link; link=link->next) { 2350 if (link->beginhook) { 2351 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 2352 } 2353 } 2354 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 2355 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2356 ierr = DMGetSection(dm, &s);CHKERRQ(ierr); 2357 switch (mode) { 2358 case INSERT_VALUES: 2359 case INSERT_ALL_VALUES: 2360 case INSERT_BC_VALUES: 2361 isInsert = PETSC_TRUE; break; 2362 case ADD_VALUES: 2363 case ADD_ALL_VALUES: 2364 case ADD_BC_VALUES: 2365 isInsert = PETSC_FALSE; break; 2366 default: 2367 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2368 } 2369 if (sf && !isInsert) { 2370 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2371 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2372 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2373 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2374 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2375 } else if (s && isInsert) { 2376 PetscInt gStart, pStart, pEnd, p; 2377 2378 ierr = DMGetGlobalSection(dm, &gs);CHKERRQ(ierr); 2379 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2380 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2381 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2382 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2383 for (p = pStart; p < pEnd; ++p) { 2384 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2385 2386 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2387 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2388 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2389 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2390 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2391 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2392 /* Ignore off-process data and points with no global data */ 2393 if (!gdof || goff < 0) continue; 2394 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); 2395 /* If no constraints are enforced in the global vector */ 2396 if (!gcdof) { 2397 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2398 /* If constraints are enforced in the global vector */ 2399 } else if (cdof == gcdof) { 2400 const PetscInt *cdofs; 2401 PetscInt cind = 0; 2402 2403 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2404 for (d = 0, e = 0; d < dof; ++d) { 2405 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2406 gArray[goff-gStart+e++] = lArray[off+d]; 2407 } 2408 } 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); 2409 } 2410 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2411 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2412 } else { 2413 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2414 } 2415 PetscFunctionReturn(0); 2416 } 2417 2418 /*@ 2419 DMLocalToGlobalEnd - updates global vectors from local vectors 2420 2421 Neighbor-wise Collective on DM 2422 2423 Input Parameters: 2424 + dm - the DM object 2425 . l - the local vector 2426 . mode - INSERT_VALUES or ADD_VALUES 2427 - g - the global vector 2428 2429 2430 Level: beginner 2431 2432 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2433 2434 @*/ 2435 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2436 { 2437 PetscSF sf; 2438 PetscSection s; 2439 DMLocalToGlobalHookLink link; 2440 PetscBool isInsert; 2441 PetscErrorCode ierr; 2442 2443 PetscFunctionBegin; 2444 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2445 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2446 ierr = DMGetSection(dm, &s);CHKERRQ(ierr); 2447 switch (mode) { 2448 case INSERT_VALUES: 2449 case INSERT_ALL_VALUES: 2450 isInsert = PETSC_TRUE; break; 2451 case ADD_VALUES: 2452 case ADD_ALL_VALUES: 2453 isInsert = PETSC_FALSE; break; 2454 default: 2455 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2456 } 2457 if (sf && !isInsert) { 2458 const PetscScalar *lArray; 2459 PetscScalar *gArray; 2460 2461 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2462 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2463 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2464 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2465 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2466 } else if (s && isInsert) { 2467 } else { 2468 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2469 } 2470 for (link=dm->ltoghook; link; link=link->next) { 2471 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2472 } 2473 PetscFunctionReturn(0); 2474 } 2475 2476 /*@ 2477 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2478 that contain irrelevant values) to another local vector where the ghost 2479 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2480 2481 Neighbor-wise Collective on DM and Vec 2482 2483 Input Parameters: 2484 + dm - the DM object 2485 . g - the original local vector 2486 - mode - one of INSERT_VALUES or ADD_VALUES 2487 2488 Output Parameter: 2489 . l - the local vector with correct ghost values 2490 2491 Level: intermediate 2492 2493 Notes: 2494 The local vectors used here need not be the same as those 2495 obtained from DMCreateLocalVector(), BUT they 2496 must have the same parallel data layout; they could, for example, be 2497 obtained with VecDuplicate() from the DM originating vectors. 2498 2499 .keywords: DM, local-to-local, begin 2500 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2501 2502 @*/ 2503 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2504 { 2505 PetscErrorCode ierr; 2506 2507 PetscFunctionBegin; 2508 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2509 if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2510 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2511 PetscFunctionReturn(0); 2512 } 2513 2514 /*@ 2515 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2516 that contain irrelevant values) to another local vector where the ghost 2517 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2518 2519 Neighbor-wise Collective on DM and Vec 2520 2521 Input Parameters: 2522 + da - the DM object 2523 . g - the original local vector 2524 - mode - one of INSERT_VALUES or ADD_VALUES 2525 2526 Output Parameter: 2527 . l - the local vector with correct ghost values 2528 2529 Level: intermediate 2530 2531 Notes: 2532 The local vectors used here need not be the same as those 2533 obtained from DMCreateLocalVector(), BUT they 2534 must have the same parallel data layout; they could, for example, be 2535 obtained with VecDuplicate() from the DM originating vectors. 2536 2537 .keywords: DM, local-to-local, end 2538 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2539 2540 @*/ 2541 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2542 { 2543 PetscErrorCode ierr; 2544 2545 PetscFunctionBegin; 2546 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2547 if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2548 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2549 PetscFunctionReturn(0); 2550 } 2551 2552 2553 /*@ 2554 DMCoarsen - Coarsens a DM object 2555 2556 Collective on DM 2557 2558 Input Parameter: 2559 + dm - the DM object 2560 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2561 2562 Output Parameter: 2563 . dmc - the coarsened DM 2564 2565 Level: developer 2566 2567 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2568 2569 @*/ 2570 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2571 { 2572 PetscErrorCode ierr; 2573 DMCoarsenHookLink link; 2574 2575 PetscFunctionBegin; 2576 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2577 if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen"); 2578 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2579 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2580 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2581 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 2582 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2583 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2584 (*dmc)->ctx = dm->ctx; 2585 (*dmc)->levelup = dm->levelup; 2586 (*dmc)->leveldown = dm->leveldown + 1; 2587 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2588 for (link=dm->coarsenhook; link; link=link->next) { 2589 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2590 } 2591 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2592 PetscFunctionReturn(0); 2593 } 2594 2595 /*@C 2596 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2597 2598 Logically Collective 2599 2600 Input Arguments: 2601 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2602 . coarsenhook - function to run when setting up a coarser level 2603 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2604 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2605 2606 Calling sequence of coarsenhook: 2607 $ coarsenhook(DM fine,DM coarse,void *ctx); 2608 2609 + fine - fine level DM 2610 . coarse - coarse level DM to restrict problem to 2611 - ctx - optional user-defined function context 2612 2613 Calling sequence for restricthook: 2614 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2615 2616 + fine - fine level DM 2617 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2618 . rscale - scaling vector for restriction 2619 . inject - matrix restricting by injection 2620 . coarse - coarse level DM to update 2621 - ctx - optional user-defined function context 2622 2623 Level: advanced 2624 2625 Notes: 2626 This function is only needed if auxiliary data needs to be set up on coarse grids. 2627 2628 If this function is called multiple times, the hooks will be run in the order they are added. 2629 2630 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2631 extract the finest level information from its context (instead of from the SNES). 2632 2633 This function is currently not available from Fortran. 2634 2635 .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2636 @*/ 2637 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2638 { 2639 PetscErrorCode ierr; 2640 DMCoarsenHookLink link,*p; 2641 2642 PetscFunctionBegin; 2643 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2644 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2645 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2646 } 2647 ierr = PetscNew(&link);CHKERRQ(ierr); 2648 link->coarsenhook = coarsenhook; 2649 link->restricthook = restricthook; 2650 link->ctx = ctx; 2651 link->next = NULL; 2652 *p = link; 2653 PetscFunctionReturn(0); 2654 } 2655 2656 /*@C 2657 DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid 2658 2659 Logically Collective 2660 2661 Input Arguments: 2662 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2663 . coarsenhook - function to run when setting up a coarser level 2664 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2665 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2666 2667 Level: advanced 2668 2669 Notes: 2670 This function does nothing if the hook is not in the list. 2671 2672 This function is currently not available from Fortran. 2673 2674 .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2675 @*/ 2676 PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2677 { 2678 PetscErrorCode ierr; 2679 DMCoarsenHookLink link,*p; 2680 2681 PetscFunctionBegin; 2682 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2683 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2684 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 2685 link = *p; 2686 *p = link->next; 2687 ierr = PetscFree(link);CHKERRQ(ierr); 2688 break; 2689 } 2690 } 2691 PetscFunctionReturn(0); 2692 } 2693 2694 2695 /*@ 2696 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2697 2698 Collective if any hooks are 2699 2700 Input Arguments: 2701 + fine - finer DM to use as a base 2702 . restrct - restriction matrix, apply using MatRestrict() 2703 . rscale - scaling vector for restriction 2704 . inject - injection matrix, also use MatRestrict() 2705 - coarse - coarser DM to update 2706 2707 Level: developer 2708 2709 .seealso: DMCoarsenHookAdd(), MatRestrict() 2710 @*/ 2711 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2712 { 2713 PetscErrorCode ierr; 2714 DMCoarsenHookLink link; 2715 2716 PetscFunctionBegin; 2717 for (link=fine->coarsenhook; link; link=link->next) { 2718 if (link->restricthook) { 2719 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2720 } 2721 } 2722 PetscFunctionReturn(0); 2723 } 2724 2725 /*@C 2726 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2727 2728 Logically Collective 2729 2730 Input Arguments: 2731 + global - global DM 2732 . ddhook - function to run to pass data to the decomposition DM upon its creation 2733 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2734 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2735 2736 2737 Calling sequence for ddhook: 2738 $ ddhook(DM global,DM block,void *ctx) 2739 2740 + global - global DM 2741 . block - block DM 2742 - ctx - optional user-defined function context 2743 2744 Calling sequence for restricthook: 2745 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2746 2747 + global - global DM 2748 . out - scatter to the outer (with ghost and overlap points) block vector 2749 . in - scatter to block vector values only owned locally 2750 . block - block DM 2751 - ctx - optional user-defined function context 2752 2753 Level: advanced 2754 2755 Notes: 2756 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2757 2758 If this function is called multiple times, the hooks will be run in the order they are added. 2759 2760 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2761 extract the global information from its context (instead of from the SNES). 2762 2763 This function is currently not available from Fortran. 2764 2765 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2766 @*/ 2767 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2768 { 2769 PetscErrorCode ierr; 2770 DMSubDomainHookLink link,*p; 2771 2772 PetscFunctionBegin; 2773 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2774 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2775 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2776 } 2777 ierr = PetscNew(&link);CHKERRQ(ierr); 2778 link->restricthook = restricthook; 2779 link->ddhook = ddhook; 2780 link->ctx = ctx; 2781 link->next = NULL; 2782 *p = link; 2783 PetscFunctionReturn(0); 2784 } 2785 2786 /*@C 2787 DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid 2788 2789 Logically Collective 2790 2791 Input Arguments: 2792 + global - global DM 2793 . ddhook - function to run to pass data to the decomposition DM upon its creation 2794 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2795 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2796 2797 Level: advanced 2798 2799 Notes: 2800 2801 This function is currently not available from Fortran. 2802 2803 .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2804 @*/ 2805 PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2806 { 2807 PetscErrorCode ierr; 2808 DMSubDomainHookLink link,*p; 2809 2810 PetscFunctionBegin; 2811 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2812 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2813 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 2814 link = *p; 2815 *p = link->next; 2816 ierr = PetscFree(link);CHKERRQ(ierr); 2817 break; 2818 } 2819 } 2820 PetscFunctionReturn(0); 2821 } 2822 2823 /*@ 2824 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2825 2826 Collective if any hooks are 2827 2828 Input Arguments: 2829 + fine - finer DM to use as a base 2830 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2831 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2832 - coarse - coarer DM to update 2833 2834 Level: developer 2835 2836 .seealso: DMCoarsenHookAdd(), MatRestrict() 2837 @*/ 2838 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2839 { 2840 PetscErrorCode ierr; 2841 DMSubDomainHookLink link; 2842 2843 PetscFunctionBegin; 2844 for (link=global->subdomainhook; link; link=link->next) { 2845 if (link->restricthook) { 2846 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2847 } 2848 } 2849 PetscFunctionReturn(0); 2850 } 2851 2852 /*@ 2853 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2854 2855 Not Collective 2856 2857 Input Parameter: 2858 . dm - the DM object 2859 2860 Output Parameter: 2861 . level - number of coarsenings 2862 2863 Level: developer 2864 2865 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2866 2867 @*/ 2868 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2869 { 2870 PetscFunctionBegin; 2871 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2872 *level = dm->leveldown; 2873 PetscFunctionReturn(0); 2874 } 2875 2876 2877 2878 /*@C 2879 DMRefineHierarchy - Refines a DM object, all levels at once 2880 2881 Collective on DM 2882 2883 Input Parameter: 2884 + dm - the DM object 2885 - nlevels - the number of levels of refinement 2886 2887 Output Parameter: 2888 . dmf - the refined DM hierarchy 2889 2890 Level: developer 2891 2892 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2893 2894 @*/ 2895 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2896 { 2897 PetscErrorCode ierr; 2898 2899 PetscFunctionBegin; 2900 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2901 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2902 if (nlevels == 0) PetscFunctionReturn(0); 2903 if (dm->ops->refinehierarchy) { 2904 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2905 } else if (dm->ops->refine) { 2906 PetscInt i; 2907 2908 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2909 for (i=1; i<nlevels; i++) { 2910 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2911 } 2912 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2913 PetscFunctionReturn(0); 2914 } 2915 2916 /*@C 2917 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2918 2919 Collective on DM 2920 2921 Input Parameter: 2922 + dm - the DM object 2923 - nlevels - the number of levels of coarsening 2924 2925 Output Parameter: 2926 . dmc - the coarsened DM hierarchy 2927 2928 Level: developer 2929 2930 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2931 2932 @*/ 2933 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2934 { 2935 PetscErrorCode ierr; 2936 2937 PetscFunctionBegin; 2938 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2939 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2940 if (nlevels == 0) PetscFunctionReturn(0); 2941 PetscValidPointer(dmc,3); 2942 if (dm->ops->coarsenhierarchy) { 2943 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2944 } else if (dm->ops->coarsen) { 2945 PetscInt i; 2946 2947 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2948 for (i=1; i<nlevels; i++) { 2949 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2950 } 2951 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2952 PetscFunctionReturn(0); 2953 } 2954 2955 /*@ 2956 DMCreateAggregates - Gets the aggregates that map between 2957 grids associated with two DMs. 2958 2959 Collective on DM 2960 2961 Input Parameters: 2962 + dmc - the coarse grid DM 2963 - dmf - the fine grid DM 2964 2965 Output Parameters: 2966 . rest - the restriction matrix (transpose of the projection matrix) 2967 2968 Level: intermediate 2969 2970 .keywords: interpolation, restriction, multigrid 2971 2972 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2973 @*/ 2974 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2975 { 2976 PetscErrorCode ierr; 2977 2978 PetscFunctionBegin; 2979 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2980 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2981 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2982 PetscFunctionReturn(0); 2983 } 2984 2985 /*@C 2986 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2987 2988 Not Collective 2989 2990 Input Parameters: 2991 + dm - the DM object 2992 - destroy - the destroy function 2993 2994 Level: intermediate 2995 2996 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2997 2998 @*/ 2999 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 3000 { 3001 PetscFunctionBegin; 3002 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3003 dm->ctxdestroy = destroy; 3004 PetscFunctionReturn(0); 3005 } 3006 3007 /*@ 3008 DMSetApplicationContext - Set a user context into a DM object 3009 3010 Not Collective 3011 3012 Input Parameters: 3013 + dm - the DM object 3014 - ctx - the user context 3015 3016 Level: intermediate 3017 3018 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3019 3020 @*/ 3021 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 3022 { 3023 PetscFunctionBegin; 3024 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3025 dm->ctx = ctx; 3026 PetscFunctionReturn(0); 3027 } 3028 3029 /*@ 3030 DMGetApplicationContext - Gets a user context from a DM object 3031 3032 Not Collective 3033 3034 Input Parameter: 3035 . dm - the DM object 3036 3037 Output Parameter: 3038 . ctx - the user context 3039 3040 Level: intermediate 3041 3042 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3043 3044 @*/ 3045 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 3046 { 3047 PetscFunctionBegin; 3048 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3049 *(void**)ctx = dm->ctx; 3050 PetscFunctionReturn(0); 3051 } 3052 3053 /*@C 3054 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 3055 3056 Logically Collective on DM 3057 3058 Input Parameter: 3059 + dm - the DM object 3060 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 3061 3062 Level: intermediate 3063 3064 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 3065 DMSetJacobian() 3066 3067 @*/ 3068 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 3069 { 3070 PetscFunctionBegin; 3071 dm->ops->computevariablebounds = f; 3072 PetscFunctionReturn(0); 3073 } 3074 3075 /*@ 3076 DMHasVariableBounds - does the DM object have a variable bounds function? 3077 3078 Not Collective 3079 3080 Input Parameter: 3081 . dm - the DM object to destroy 3082 3083 Output Parameter: 3084 . flg - PETSC_TRUE if the variable bounds function exists 3085 3086 Level: developer 3087 3088 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3089 3090 @*/ 3091 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 3092 { 3093 PetscFunctionBegin; 3094 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 3095 PetscFunctionReturn(0); 3096 } 3097 3098 /*@C 3099 DMComputeVariableBounds - compute variable bounds used by SNESVI. 3100 3101 Logically Collective on DM 3102 3103 Input Parameters: 3104 . dm - the DM object 3105 3106 Output parameters: 3107 + xl - lower bound 3108 - xu - upper bound 3109 3110 Level: advanced 3111 3112 Notes: 3113 This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 3114 3115 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3116 3117 @*/ 3118 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 3119 { 3120 PetscErrorCode ierr; 3121 3122 PetscFunctionBegin; 3123 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 3124 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 3125 if (dm->ops->computevariablebounds) { 3126 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 3127 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 3128 PetscFunctionReturn(0); 3129 } 3130 3131 /*@ 3132 DMHasColoring - does the DM object have a method of providing a coloring? 3133 3134 Not Collective 3135 3136 Input Parameter: 3137 . dm - the DM object 3138 3139 Output Parameter: 3140 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 3141 3142 Level: developer 3143 3144 .seealso DMHasFunction(), DMCreateColoring() 3145 3146 @*/ 3147 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 3148 { 3149 PetscFunctionBegin; 3150 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 3151 PetscFunctionReturn(0); 3152 } 3153 3154 /*@ 3155 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 3156 3157 Not Collective 3158 3159 Input Parameter: 3160 . dm - the DM object 3161 3162 Output Parameter: 3163 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 3164 3165 Level: developer 3166 3167 .seealso DMHasFunction(), DMCreateRestriction() 3168 3169 @*/ 3170 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 3171 { 3172 PetscFunctionBegin; 3173 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 3174 PetscFunctionReturn(0); 3175 } 3176 3177 3178 /*@ 3179 DMHasCreateInjection - does the DM object have a method of providing an injection? 3180 3181 Not Collective 3182 3183 Input Parameter: 3184 . dm - the DM object 3185 3186 Output Parameter: 3187 . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection(). 3188 3189 Level: developer 3190 3191 .seealso DMHasFunction(), DMCreateInjection() 3192 3193 @*/ 3194 PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg) 3195 { 3196 PetscErrorCode ierr; 3197 PetscFunctionBegin; 3198 if (!dm->ops->hascreateinjection) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMHasCreateInjection not implemented for this type"); 3199 ierr = (*dm->ops->hascreateinjection)(dm,flg);CHKERRQ(ierr); 3200 PetscFunctionReturn(0); 3201 } 3202 3203 /*@C 3204 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 3205 3206 Collective on DM 3207 3208 Input Parameter: 3209 + dm - the DM object 3210 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 3211 3212 Level: developer 3213 3214 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3215 3216 @*/ 3217 PetscErrorCode DMSetVec(DM dm,Vec x) 3218 { 3219 PetscErrorCode ierr; 3220 3221 PetscFunctionBegin; 3222 if (x) { 3223 if (!dm->x) { 3224 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 3225 } 3226 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 3227 } else if (dm->x) { 3228 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 3229 } 3230 PetscFunctionReturn(0); 3231 } 3232 3233 PetscFunctionList DMList = NULL; 3234 PetscBool DMRegisterAllCalled = PETSC_FALSE; 3235 3236 /*@C 3237 DMSetType - Builds a DM, for a particular DM implementation. 3238 3239 Collective on DM 3240 3241 Input Parameters: 3242 + dm - The DM object 3243 - method - The name of the DM type 3244 3245 Options Database Key: 3246 . -dm_type <type> - Sets the DM type; use -help for a list of available types 3247 3248 Notes: 3249 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 3250 3251 Level: intermediate 3252 3253 .keywords: DM, set, type 3254 .seealso: DMGetType(), DMCreate() 3255 @*/ 3256 PetscErrorCode DMSetType(DM dm, DMType method) 3257 { 3258 PetscErrorCode (*r)(DM); 3259 PetscBool match; 3260 PetscErrorCode ierr; 3261 3262 PetscFunctionBegin; 3263 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3264 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3265 if (match) PetscFunctionReturn(0); 3266 3267 ierr = DMRegisterAll();CHKERRQ(ierr); 3268 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3269 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3270 3271 if (dm->ops->destroy) { 3272 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3273 dm->ops->destroy = NULL; 3274 } 3275 ierr = (*r)(dm);CHKERRQ(ierr); 3276 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3277 PetscFunctionReturn(0); 3278 } 3279 3280 /*@C 3281 DMGetType - Gets the DM type name (as a string) from the DM. 3282 3283 Not Collective 3284 3285 Input Parameter: 3286 . dm - The DM 3287 3288 Output Parameter: 3289 . type - The DM type name 3290 3291 Level: intermediate 3292 3293 .keywords: DM, get, type, name 3294 .seealso: DMSetType(), DMCreate() 3295 @*/ 3296 PetscErrorCode DMGetType(DM dm, DMType *type) 3297 { 3298 PetscErrorCode ierr; 3299 3300 PetscFunctionBegin; 3301 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3302 PetscValidPointer(type,2); 3303 ierr = DMRegisterAll();CHKERRQ(ierr); 3304 *type = ((PetscObject)dm)->type_name; 3305 PetscFunctionReturn(0); 3306 } 3307 3308 /*@C 3309 DMConvert - Converts a DM to another DM, either of the same or different type. 3310 3311 Collective on DM 3312 3313 Input Parameters: 3314 + dm - the DM 3315 - newtype - new DM type (use "same" for the same type) 3316 3317 Output Parameter: 3318 . M - pointer to new DM 3319 3320 Notes: 3321 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3322 the MPI communicator of the generated DM is always the same as the communicator 3323 of the input DM. 3324 3325 Level: intermediate 3326 3327 .seealso: DMCreate() 3328 @*/ 3329 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3330 { 3331 DM B; 3332 char convname[256]; 3333 PetscBool sametype/*, issame */; 3334 PetscErrorCode ierr; 3335 3336 PetscFunctionBegin; 3337 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3338 PetscValidType(dm,1); 3339 PetscValidPointer(M,3); 3340 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3341 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3342 if (sametype) { 3343 *M = dm; 3344 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3345 PetscFunctionReturn(0); 3346 } else { 3347 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3348 3349 /* 3350 Order of precedence: 3351 1) See if a specialized converter is known to the current DM. 3352 2) See if a specialized converter is known to the desired DM class. 3353 3) See if a good general converter is registered for the desired class 3354 4) See if a good general converter is known for the current matrix. 3355 5) Use a really basic converter. 3356 */ 3357 3358 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3359 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3360 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3361 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3362 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3363 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3364 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3365 if (conv) goto foundconv; 3366 3367 /* 2) See if a specialized converter is known to the desired DM class. */ 3368 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3369 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3370 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3371 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3372 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3373 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3374 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3375 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3376 if (conv) { 3377 ierr = DMDestroy(&B);CHKERRQ(ierr); 3378 goto foundconv; 3379 } 3380 3381 #if 0 3382 /* 3) See if a good general converter is registered for the desired class */ 3383 conv = B->ops->convertfrom; 3384 ierr = DMDestroy(&B);CHKERRQ(ierr); 3385 if (conv) goto foundconv; 3386 3387 /* 4) See if a good general converter is known for the current matrix */ 3388 if (dm->ops->convert) { 3389 conv = dm->ops->convert; 3390 } 3391 if (conv) goto foundconv; 3392 #endif 3393 3394 /* 5) Use a really basic converter. */ 3395 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3396 3397 foundconv: 3398 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3399 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3400 /* Things that are independent of DM type: We should consult DMClone() here */ 3401 { 3402 PetscBool isper; 3403 const PetscReal *maxCell, *L; 3404 const DMBoundaryType *bd; 3405 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 3406 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr); 3407 } 3408 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3409 } 3410 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3411 PetscFunctionReturn(0); 3412 } 3413 3414 /*--------------------------------------------------------------------------------------------------------------------*/ 3415 3416 /*@C 3417 DMRegister - Adds a new DM component implementation 3418 3419 Not Collective 3420 3421 Input Parameters: 3422 + name - The name of a new user-defined creation routine 3423 - create_func - The creation routine itself 3424 3425 Notes: 3426 DMRegister() may be called multiple times to add several user-defined DMs 3427 3428 3429 Sample usage: 3430 .vb 3431 DMRegister("my_da", MyDMCreate); 3432 .ve 3433 3434 Then, your DM type can be chosen with the procedural interface via 3435 .vb 3436 DMCreate(MPI_Comm, DM *); 3437 DMSetType(DM,"my_da"); 3438 .ve 3439 or at runtime via the option 3440 .vb 3441 -da_type my_da 3442 .ve 3443 3444 Level: advanced 3445 3446 .keywords: DM, register 3447 .seealso: DMRegisterAll(), DMRegisterDestroy() 3448 3449 @*/ 3450 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3451 { 3452 PetscErrorCode ierr; 3453 3454 PetscFunctionBegin; 3455 ierr = DMInitializePackage();CHKERRQ(ierr); 3456 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3457 PetscFunctionReturn(0); 3458 } 3459 3460 /*@C 3461 DMLoad - Loads a DM that has been stored in binary with DMView(). 3462 3463 Collective on PetscViewer 3464 3465 Input Parameters: 3466 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3467 some related function before a call to DMLoad(). 3468 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3469 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3470 3471 Level: intermediate 3472 3473 Notes: 3474 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3475 3476 Notes for advanced users: 3477 Most users should not need to know the details of the binary storage 3478 format, since DMLoad() and DMView() completely hide these details. 3479 But for anyone who's interested, the standard binary matrix storage 3480 format is 3481 .vb 3482 has not yet been determined 3483 .ve 3484 3485 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3486 @*/ 3487 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3488 { 3489 PetscBool isbinary, ishdf5; 3490 PetscErrorCode ierr; 3491 3492 PetscFunctionBegin; 3493 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3494 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3495 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3496 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3497 if (isbinary) { 3498 PetscInt classid; 3499 char type[256]; 3500 3501 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3502 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3503 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3504 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3505 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3506 } else if (ishdf5) { 3507 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3508 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3509 PetscFunctionReturn(0); 3510 } 3511 3512 /******************************** FEM Support **********************************/ 3513 3514 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3515 { 3516 PetscInt f; 3517 PetscErrorCode ierr; 3518 3519 PetscFunctionBegin; 3520 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3521 for (f = 0; f < len; ++f) { 3522 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3523 } 3524 PetscFunctionReturn(0); 3525 } 3526 3527 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3528 { 3529 PetscInt f, g; 3530 PetscErrorCode ierr; 3531 3532 PetscFunctionBegin; 3533 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3534 for (f = 0; f < rows; ++f) { 3535 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3536 for (g = 0; g < cols; ++g) { 3537 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3538 } 3539 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3540 } 3541 PetscFunctionReturn(0); 3542 } 3543 3544 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3545 { 3546 PetscInt localSize, bs; 3547 PetscMPIInt size; 3548 Vec x, xglob; 3549 const PetscScalar *xarray; 3550 PetscErrorCode ierr; 3551 3552 PetscFunctionBegin; 3553 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRQ(ierr); 3554 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3555 ierr = VecCopy(X, x);CHKERRQ(ierr); 3556 ierr = VecChop(x, tol);CHKERRQ(ierr); 3557 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 3558 if (size > 1) { 3559 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 3560 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 3561 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 3562 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 3563 } else { 3564 xglob = x; 3565 } 3566 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 3567 if (size > 1) { 3568 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 3569 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 3570 } 3571 ierr = VecDestroy(&x);CHKERRQ(ierr); 3572 PetscFunctionReturn(0); 3573 } 3574 3575 /*@ 3576 DMGetSection - Get the PetscSection encoding the local data layout for the DM. 3577 3578 Input Parameter: 3579 . dm - The DM 3580 3581 Output Parameter: 3582 . section - The PetscSection 3583 3584 Options Database Keys: 3585 . -dm_petscsection_view - View the Section created by the DM 3586 3587 Level: intermediate 3588 3589 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3590 3591 .seealso: DMSetSection(), DMGetGlobalSection() 3592 @*/ 3593 PetscErrorCode DMGetSection(DM dm, PetscSection *section) 3594 { 3595 PetscErrorCode ierr; 3596 3597 PetscFunctionBegin; 3598 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3599 PetscValidPointer(section, 2); 3600 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3601 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3602 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3603 } 3604 *section = dm->defaultSection; 3605 PetscFunctionReturn(0); 3606 } 3607 3608 /*@ 3609 DMSetSection - Set the PetscSection encoding the local data layout for the DM. 3610 3611 Input Parameters: 3612 + dm - The DM 3613 - section - The PetscSection 3614 3615 Level: intermediate 3616 3617 Note: Any existing Section will be destroyed 3618 3619 .seealso: DMSetSection(), DMGetGlobalSection() 3620 @*/ 3621 PetscErrorCode DMSetSection(DM dm, PetscSection section) 3622 { 3623 PetscInt numFields = 0; 3624 PetscInt f; 3625 PetscErrorCode ierr; 3626 3627 PetscFunctionBegin; 3628 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3629 if (section) { 3630 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3631 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3632 } 3633 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3634 dm->defaultSection = section; 3635 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3636 if (numFields) { 3637 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3638 for (f = 0; f < numFields; ++f) { 3639 PetscObject disc; 3640 const char *name; 3641 3642 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3643 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3644 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3645 } 3646 } 3647 /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */ 3648 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3649 PetscFunctionReturn(0); 3650 } 3651 3652 /*@ 3653 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3654 3655 not collective 3656 3657 Input Parameter: 3658 . dm - The DM 3659 3660 Output Parameter: 3661 + 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. 3662 - 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. 3663 3664 Level: advanced 3665 3666 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3667 3668 .seealso: DMSetDefaultConstraints() 3669 @*/ 3670 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3671 { 3672 PetscErrorCode ierr; 3673 3674 PetscFunctionBegin; 3675 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3676 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3677 if (section) {*section = dm->defaultConstraintSection;} 3678 if (mat) {*mat = dm->defaultConstraintMat;} 3679 PetscFunctionReturn(0); 3680 } 3681 3682 /*@ 3683 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3684 3685 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(). 3686 3687 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. 3688 3689 collective on dm 3690 3691 Input Parameters: 3692 + dm - The DM 3693 + 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). 3694 - 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). 3695 3696 Level: advanced 3697 3698 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3699 3700 .seealso: DMGetDefaultConstraints() 3701 @*/ 3702 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3703 { 3704 PetscMPIInt result; 3705 PetscErrorCode ierr; 3706 3707 PetscFunctionBegin; 3708 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3709 if (section) { 3710 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3711 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3712 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3713 } 3714 if (mat) { 3715 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3716 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3717 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3718 } 3719 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3720 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3721 dm->defaultConstraintSection = section; 3722 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3723 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3724 dm->defaultConstraintMat = mat; 3725 PetscFunctionReturn(0); 3726 } 3727 3728 #if defined(PETSC_USE_DEBUG) 3729 /* 3730 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3731 3732 Input Parameters: 3733 + dm - The DM 3734 . localSection - PetscSection describing the local data layout 3735 - globalSection - PetscSection describing the global data layout 3736 3737 Level: intermediate 3738 3739 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3740 */ 3741 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3742 { 3743 MPI_Comm comm; 3744 PetscLayout layout; 3745 const PetscInt *ranges; 3746 PetscInt pStart, pEnd, p, nroots; 3747 PetscMPIInt size, rank; 3748 PetscBool valid = PETSC_TRUE, gvalid; 3749 PetscErrorCode ierr; 3750 3751 PetscFunctionBegin; 3752 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3753 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3754 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3755 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3756 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3757 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3758 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3759 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3760 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3761 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3762 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3763 for (p = pStart; p < pEnd; ++p) { 3764 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3765 3766 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3767 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3768 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3769 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3770 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3771 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3772 if (!gdof) continue; /* Censored point */ 3773 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;} 3774 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;} 3775 if (gdof < 0) { 3776 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3777 for (d = 0; d < gsize; ++d) { 3778 PetscInt offset = -(goff+1) + d, r; 3779 3780 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3781 if (r < 0) r = -(r+2); 3782 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;} 3783 } 3784 } 3785 } 3786 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3787 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3788 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3789 if (!gvalid) { 3790 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3791 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3792 } 3793 PetscFunctionReturn(0); 3794 } 3795 #endif 3796 3797 /*@ 3798 DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3799 3800 Collective on DM 3801 3802 Input Parameter: 3803 . dm - The DM 3804 3805 Output Parameter: 3806 . section - The PetscSection 3807 3808 Level: intermediate 3809 3810 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3811 3812 .seealso: DMSetSection(), DMGetSection() 3813 @*/ 3814 PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section) 3815 { 3816 PetscErrorCode ierr; 3817 3818 PetscFunctionBegin; 3819 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3820 PetscValidPointer(section, 2); 3821 if (!dm->defaultGlobalSection) { 3822 PetscSection s; 3823 3824 ierr = DMGetSection(dm, &s);CHKERRQ(ierr); 3825 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3826 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3827 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3828 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3829 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3830 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3831 } 3832 *section = dm->defaultGlobalSection; 3833 PetscFunctionReturn(0); 3834 } 3835 3836 /*@ 3837 DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3838 3839 Input Parameters: 3840 + dm - The DM 3841 - section - The PetscSection, or NULL 3842 3843 Level: intermediate 3844 3845 Note: Any existing Section will be destroyed 3846 3847 .seealso: DMGetGlobalSection(), DMSetSection() 3848 @*/ 3849 PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section) 3850 { 3851 PetscErrorCode ierr; 3852 3853 PetscFunctionBegin; 3854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3855 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3856 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3857 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3858 dm->defaultGlobalSection = section; 3859 #if defined(PETSC_USE_DEBUG) 3860 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3861 #endif 3862 PetscFunctionReturn(0); 3863 } 3864 3865 /*@ 3866 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3867 it is created from the default PetscSection layouts in the DM. 3868 3869 Input Parameter: 3870 . dm - The DM 3871 3872 Output Parameter: 3873 . sf - The PetscSF 3874 3875 Level: intermediate 3876 3877 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3878 3879 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3880 @*/ 3881 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3882 { 3883 PetscInt nroots; 3884 PetscErrorCode ierr; 3885 3886 PetscFunctionBegin; 3887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3888 PetscValidPointer(sf, 2); 3889 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3890 if (nroots < 0) { 3891 PetscSection section, gSection; 3892 3893 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 3894 if (section) { 3895 ierr = DMGetGlobalSection(dm, &gSection);CHKERRQ(ierr); 3896 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3897 } else { 3898 *sf = NULL; 3899 PetscFunctionReturn(0); 3900 } 3901 } 3902 *sf = dm->defaultSF; 3903 PetscFunctionReturn(0); 3904 } 3905 3906 /*@ 3907 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3908 3909 Input Parameters: 3910 + dm - The DM 3911 - sf - The PetscSF 3912 3913 Level: intermediate 3914 3915 Note: Any previous SF is destroyed 3916 3917 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3918 @*/ 3919 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3920 { 3921 PetscErrorCode ierr; 3922 3923 PetscFunctionBegin; 3924 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3925 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3926 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3927 dm->defaultSF = sf; 3928 PetscFunctionReturn(0); 3929 } 3930 3931 /*@C 3932 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3933 describing the data layout. 3934 3935 Input Parameters: 3936 + dm - The DM 3937 . localSection - PetscSection describing the local data layout 3938 - globalSection - PetscSection describing the global data layout 3939 3940 Level: intermediate 3941 3942 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3943 @*/ 3944 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3945 { 3946 MPI_Comm comm; 3947 PetscLayout layout; 3948 const PetscInt *ranges; 3949 PetscInt *local; 3950 PetscSFNode *remote; 3951 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3952 PetscMPIInt size, rank; 3953 PetscErrorCode ierr; 3954 3955 PetscFunctionBegin; 3956 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3957 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3958 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3959 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3960 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3961 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3962 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3963 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3964 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3965 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3966 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3967 for (p = pStart; p < pEnd; ++p) { 3968 PetscInt gdof, gcdof; 3969 3970 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3971 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3972 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)); 3973 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3974 } 3975 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3976 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3977 for (p = pStart, l = 0; p < pEnd; ++p) { 3978 const PetscInt *cind; 3979 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3980 3981 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3982 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3983 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3984 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3985 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3986 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3987 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3988 if (!gdof) continue; /* Censored point */ 3989 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3990 if (gsize != dof-cdof) { 3991 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); 3992 cdof = 0; /* Ignore constraints */ 3993 } 3994 for (d = 0, c = 0; d < dof; ++d) { 3995 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3996 local[l+d-c] = off+d; 3997 } 3998 if (gdof < 0) { 3999 for (d = 0; d < gsize; ++d, ++l) { 4000 PetscInt offset = -(goff+1) + d, r; 4001 4002 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4003 if (r < 0) r = -(r+2); 4004 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); 4005 remote[l].rank = r; 4006 remote[l].index = offset - ranges[r]; 4007 } 4008 } else { 4009 for (d = 0; d < gsize; ++d, ++l) { 4010 remote[l].rank = rank; 4011 remote[l].index = goff+d - ranges[rank]; 4012 } 4013 } 4014 } 4015 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 4016 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4017 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 4018 PetscFunctionReturn(0); 4019 } 4020 4021 /*@ 4022 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 4023 4024 Input Parameter: 4025 . dm - The DM 4026 4027 Output Parameter: 4028 . sf - The PetscSF 4029 4030 Level: intermediate 4031 4032 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4033 4034 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 4035 @*/ 4036 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 4037 { 4038 PetscFunctionBegin; 4039 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4040 PetscValidPointer(sf, 2); 4041 *sf = dm->sf; 4042 PetscFunctionReturn(0); 4043 } 4044 4045 /*@ 4046 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 4047 4048 Input Parameters: 4049 + dm - The DM 4050 - sf - The PetscSF 4051 4052 Level: intermediate 4053 4054 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 4055 @*/ 4056 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 4057 { 4058 PetscErrorCode ierr; 4059 4060 PetscFunctionBegin; 4061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4062 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 4063 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 4064 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4065 dm->sf = sf; 4066 PetscFunctionReturn(0); 4067 } 4068 4069 /*@ 4070 DMGetDS - Get the PetscDS 4071 4072 Input Parameter: 4073 . dm - The DM 4074 4075 Output Parameter: 4076 . prob - The PetscDS 4077 4078 Level: developer 4079 4080 .seealso: DMSetDS() 4081 @*/ 4082 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 4083 { 4084 PetscFunctionBegin; 4085 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4086 PetscValidPointer(prob, 2); 4087 *prob = dm->prob; 4088 PetscFunctionReturn(0); 4089 } 4090 4091 /*@ 4092 DMSetDS - Set the PetscDS 4093 4094 Input Parameters: 4095 + dm - The DM 4096 - prob - The PetscDS 4097 4098 Level: developer 4099 4100 .seealso: DMGetDS() 4101 @*/ 4102 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 4103 { 4104 PetscInt dimEmbed; 4105 PetscErrorCode ierr; 4106 4107 PetscFunctionBegin; 4108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4109 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 4110 ierr = PetscObjectReference((PetscObject) prob);CHKERRQ(ierr); 4111 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 4112 dm->prob = prob; 4113 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 4114 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 4115 PetscFunctionReturn(0); 4116 } 4117 4118 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4119 { 4120 PetscErrorCode ierr; 4121 4122 PetscFunctionBegin; 4123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4124 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 4125 PetscFunctionReturn(0); 4126 } 4127 4128 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4129 { 4130 PetscInt Nf, f; 4131 PetscErrorCode ierr; 4132 4133 PetscFunctionBegin; 4134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4135 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 4136 for (f = Nf; f < numFields; ++f) { 4137 PetscContainer obj; 4138 4139 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4140 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 4141 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4142 } 4143 PetscFunctionReturn(0); 4144 } 4145 4146 /*@ 4147 DMGetField - Return the discretization object for a given DM field 4148 4149 Not collective 4150 4151 Input Parameters: 4152 + dm - The DM 4153 - f - The field number 4154 4155 Output Parameter: 4156 . field - The discretization object 4157 4158 Level: developer 4159 4160 .seealso: DMSetField() 4161 @*/ 4162 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 4163 { 4164 PetscErrorCode ierr; 4165 4166 PetscFunctionBegin; 4167 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4168 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 4169 PetscFunctionReturn(0); 4170 } 4171 4172 /*@ 4173 DMSetField - Set the discretization object for a given DM field 4174 4175 Logically collective on DM 4176 4177 Input Parameters: 4178 + dm - The DM 4179 . f - The field number 4180 - field - The discretization object 4181 4182 Level: developer 4183 4184 .seealso: DMGetField() 4185 @*/ 4186 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 4187 { 4188 PetscErrorCode ierr; 4189 4190 PetscFunctionBegin; 4191 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4192 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 4193 PetscFunctionReturn(0); 4194 } 4195 4196 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 4197 { 4198 DM dm_coord,dmc_coord; 4199 PetscErrorCode ierr; 4200 Vec coords,ccoords; 4201 Mat inject; 4202 PetscFunctionBegin; 4203 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4204 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 4205 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4206 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 4207 if (coords && !ccoords) { 4208 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 4209 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4210 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 4211 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 4212 ierr = MatDestroy(&inject);CHKERRQ(ierr); 4213 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 4214 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4215 } 4216 PetscFunctionReturn(0); 4217 } 4218 4219 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 4220 { 4221 DM dm_coord,subdm_coord; 4222 PetscErrorCode ierr; 4223 Vec coords,ccoords,clcoords; 4224 VecScatter *scat_i,*scat_g; 4225 PetscFunctionBegin; 4226 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4227 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 4228 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4229 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 4230 if (coords && !ccoords) { 4231 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 4232 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4233 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 4234 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 4235 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 4236 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4237 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4238 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4239 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4240 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 4241 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 4242 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 4243 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 4244 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4245 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 4246 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4247 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4248 } 4249 PetscFunctionReturn(0); 4250 } 4251 4252 /*@ 4253 DMGetDimension - Return the topological dimension of the DM 4254 4255 Not collective 4256 4257 Input Parameter: 4258 . dm - The DM 4259 4260 Output Parameter: 4261 . dim - The topological dimension 4262 4263 Level: beginner 4264 4265 .seealso: DMSetDimension(), DMCreate() 4266 @*/ 4267 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4268 { 4269 PetscFunctionBegin; 4270 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4271 PetscValidPointer(dim, 2); 4272 *dim = dm->dim; 4273 PetscFunctionReturn(0); 4274 } 4275 4276 /*@ 4277 DMSetDimension - Set the topological dimension of the DM 4278 4279 Collective on dm 4280 4281 Input Parameters: 4282 + dm - The DM 4283 - dim - The topological dimension 4284 4285 Level: beginner 4286 4287 .seealso: DMGetDimension(), DMCreate() 4288 @*/ 4289 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4290 { 4291 PetscErrorCode ierr; 4292 4293 PetscFunctionBegin; 4294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4295 PetscValidLogicalCollectiveInt(dm, dim, 2); 4296 dm->dim = dim; 4297 if (dm->prob->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dim);CHKERRQ(ierr);} 4298 PetscFunctionReturn(0); 4299 } 4300 4301 /*@ 4302 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4303 4304 Collective on DM 4305 4306 Input Parameters: 4307 + dm - the DM 4308 - dim - the dimension 4309 4310 Output Parameters: 4311 + pStart - The first point of the given dimension 4312 . pEnd - The first point following points of the given dimension 4313 4314 Note: 4315 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4316 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4317 then the interval is empty. 4318 4319 Level: intermediate 4320 4321 .keywords: point, Hasse Diagram, dimension 4322 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4323 @*/ 4324 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4325 { 4326 PetscInt d; 4327 PetscErrorCode ierr; 4328 4329 PetscFunctionBegin; 4330 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4331 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4332 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4333 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4334 PetscFunctionReturn(0); 4335 } 4336 4337 /*@ 4338 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4339 4340 Collective on DM 4341 4342 Input Parameters: 4343 + dm - the DM 4344 - c - coordinate vector 4345 4346 Notes: 4347 The coordinates do include those for ghost points, which are in the local vector. 4348 4349 The vector c should be destroyed by the caller. 4350 4351 Level: intermediate 4352 4353 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4354 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4355 @*/ 4356 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4357 { 4358 PetscErrorCode ierr; 4359 4360 PetscFunctionBegin; 4361 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4362 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4363 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4364 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4365 dm->coordinates = c; 4366 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4367 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4368 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4369 PetscFunctionReturn(0); 4370 } 4371 4372 /*@ 4373 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4374 4375 Collective on DM 4376 4377 Input Parameters: 4378 + dm - the DM 4379 - c - coordinate vector 4380 4381 Notes: 4382 The coordinates of ghost points can be set using DMSetCoordinates() 4383 followed by DMGetCoordinatesLocal(). This is intended to enable the 4384 setting of ghost coordinates outside of the domain. 4385 4386 The vector c should be destroyed by the caller. 4387 4388 Level: intermediate 4389 4390 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4391 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4392 @*/ 4393 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4394 { 4395 PetscErrorCode ierr; 4396 4397 PetscFunctionBegin; 4398 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4399 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4400 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4401 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4402 4403 dm->coordinatesLocal = c; 4404 4405 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4406 PetscFunctionReturn(0); 4407 } 4408 4409 /*@ 4410 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4411 4412 Not Collective 4413 4414 Input Parameter: 4415 . dm - the DM 4416 4417 Output Parameter: 4418 . c - global coordinate vector 4419 4420 Note: 4421 This is a borrowed reference, so the user should NOT destroy this vector 4422 4423 Each process has only the local coordinates (does NOT have the ghost coordinates). 4424 4425 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4426 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4427 4428 Level: intermediate 4429 4430 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4431 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4432 @*/ 4433 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4434 { 4435 PetscErrorCode ierr; 4436 4437 PetscFunctionBegin; 4438 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4439 PetscValidPointer(c,2); 4440 if (!dm->coordinates && dm->coordinatesLocal) { 4441 DM cdm = NULL; 4442 4443 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4444 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4445 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4446 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4447 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4448 } 4449 *c = dm->coordinates; 4450 PetscFunctionReturn(0); 4451 } 4452 4453 /*@ 4454 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4455 4456 Collective on DM 4457 4458 Input Parameter: 4459 . dm - the DM 4460 4461 Output Parameter: 4462 . c - coordinate vector 4463 4464 Note: 4465 This is a borrowed reference, so the user should NOT destroy this vector 4466 4467 Each process has the local and ghost coordinates 4468 4469 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4470 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4471 4472 Level: intermediate 4473 4474 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4475 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4476 @*/ 4477 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4478 { 4479 PetscErrorCode ierr; 4480 4481 PetscFunctionBegin; 4482 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4483 PetscValidPointer(c,2); 4484 if (!dm->coordinatesLocal && dm->coordinates) { 4485 DM cdm = NULL; 4486 4487 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4488 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4489 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4490 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4491 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4492 } 4493 *c = dm->coordinatesLocal; 4494 PetscFunctionReturn(0); 4495 } 4496 4497 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 4498 { 4499 PetscErrorCode ierr; 4500 4501 PetscFunctionBegin; 4502 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4503 PetscValidPointer(field,2); 4504 if (!dm->coordinateField) { 4505 if (dm->ops->createcoordinatefield) { 4506 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 4507 } 4508 } 4509 *field = dm->coordinateField; 4510 PetscFunctionReturn(0); 4511 } 4512 4513 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 4514 { 4515 PetscErrorCode ierr; 4516 4517 PetscFunctionBegin; 4518 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4519 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 4520 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 4521 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 4522 dm->coordinateField = field; 4523 PetscFunctionReturn(0); 4524 } 4525 4526 /*@ 4527 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4528 4529 Collective on DM 4530 4531 Input Parameter: 4532 . dm - the DM 4533 4534 Output Parameter: 4535 . cdm - coordinate DM 4536 4537 Level: intermediate 4538 4539 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4540 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4541 @*/ 4542 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4543 { 4544 PetscErrorCode ierr; 4545 4546 PetscFunctionBegin; 4547 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4548 PetscValidPointer(cdm,2); 4549 if (!dm->coordinateDM) { 4550 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4551 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4552 } 4553 *cdm = dm->coordinateDM; 4554 PetscFunctionReturn(0); 4555 } 4556 4557 /*@ 4558 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4559 4560 Logically Collective on DM 4561 4562 Input Parameters: 4563 + dm - the DM 4564 - cdm - coordinate DM 4565 4566 Level: intermediate 4567 4568 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4569 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4570 @*/ 4571 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4572 { 4573 PetscErrorCode ierr; 4574 4575 PetscFunctionBegin; 4576 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4577 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4578 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 4579 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4580 dm->coordinateDM = cdm; 4581 PetscFunctionReturn(0); 4582 } 4583 4584 /*@ 4585 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4586 4587 Not Collective 4588 4589 Input Parameter: 4590 . dm - The DM object 4591 4592 Output Parameter: 4593 . dim - The embedding dimension 4594 4595 Level: intermediate 4596 4597 .keywords: mesh, coordinates 4598 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetSection(), DMSetSection() 4599 @*/ 4600 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4601 { 4602 PetscFunctionBegin; 4603 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4604 PetscValidPointer(dim, 2); 4605 if (dm->dimEmbed == PETSC_DEFAULT) { 4606 dm->dimEmbed = dm->dim; 4607 } 4608 *dim = dm->dimEmbed; 4609 PetscFunctionReturn(0); 4610 } 4611 4612 /*@ 4613 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4614 4615 Not Collective 4616 4617 Input Parameters: 4618 + dm - The DM object 4619 - dim - The embedding dimension 4620 4621 Level: intermediate 4622 4623 .keywords: mesh, coordinates 4624 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetSection(), DMSetSection() 4625 @*/ 4626 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4627 { 4628 PetscErrorCode ierr; 4629 4630 PetscFunctionBegin; 4631 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4632 dm->dimEmbed = dim; 4633 ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);CHKERRQ(ierr); 4634 PetscFunctionReturn(0); 4635 } 4636 4637 /*@ 4638 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4639 4640 Not Collective 4641 4642 Input Parameter: 4643 . dm - The DM object 4644 4645 Output Parameter: 4646 . section - The PetscSection object 4647 4648 Level: intermediate 4649 4650 .keywords: mesh, coordinates 4651 .seealso: DMGetCoordinateDM(), DMGetSection(), DMSetSection() 4652 @*/ 4653 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4654 { 4655 DM cdm; 4656 PetscErrorCode ierr; 4657 4658 PetscFunctionBegin; 4659 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4660 PetscValidPointer(section, 2); 4661 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4662 ierr = DMGetSection(cdm, section);CHKERRQ(ierr); 4663 PetscFunctionReturn(0); 4664 } 4665 4666 /*@ 4667 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4668 4669 Not Collective 4670 4671 Input Parameters: 4672 + dm - The DM object 4673 . dim - The embedding dimension, or PETSC_DETERMINE 4674 - section - The PetscSection object 4675 4676 Level: intermediate 4677 4678 .keywords: mesh, coordinates 4679 .seealso: DMGetCoordinateSection(), DMGetSection(), DMSetSection() 4680 @*/ 4681 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4682 { 4683 DM cdm; 4684 PetscErrorCode ierr; 4685 4686 PetscFunctionBegin; 4687 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4688 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4689 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4690 ierr = DMSetSection(cdm, section);CHKERRQ(ierr); 4691 if (dim == PETSC_DETERMINE) { 4692 PetscInt d = PETSC_DEFAULT; 4693 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4694 4695 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4696 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4697 pStart = PetscMax(vStart, pStart); 4698 pEnd = PetscMin(vEnd, pEnd); 4699 for (v = pStart; v < pEnd; ++v) { 4700 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4701 if (dd) {d = dd; break;} 4702 } 4703 if (d < 0) d = PETSC_DEFAULT; 4704 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4705 } 4706 PetscFunctionReturn(0); 4707 } 4708 4709 /*@C 4710 DMGetPeriodicity - Get the description of mesh periodicity 4711 4712 Input Parameters: 4713 . dm - The DM object 4714 4715 Output Parameters: 4716 + per - Whether the DM is periodic or not 4717 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4718 . L - If we assume the mesh is a torus, this is the length of each coordinate 4719 - bd - This describes the type of periodicity in each topological dimension 4720 4721 Level: developer 4722 4723 .seealso: DMGetPeriodicity() 4724 @*/ 4725 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4726 { 4727 PetscFunctionBegin; 4728 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4729 if (per) *per = dm->periodic; 4730 if (L) *L = dm->L; 4731 if (maxCell) *maxCell = dm->maxCell; 4732 if (bd) *bd = dm->bdtype; 4733 PetscFunctionReturn(0); 4734 } 4735 4736 /*@C 4737 DMSetPeriodicity - Set the description of mesh periodicity 4738 4739 Input Parameters: 4740 + dm - The DM object 4741 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 4742 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4743 . L - If we assume the mesh is a torus, this is the length of each coordinate 4744 - bd - This describes the type of periodicity in each topological dimension 4745 4746 Level: developer 4747 4748 .seealso: DMGetPeriodicity() 4749 @*/ 4750 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4751 { 4752 PetscInt dim, d; 4753 PetscErrorCode ierr; 4754 4755 PetscFunctionBegin; 4756 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4757 PetscValidLogicalCollectiveBool(dm,per,2); 4758 if (maxCell) { 4759 PetscValidPointer(maxCell,3); 4760 PetscValidPointer(L,4); 4761 PetscValidPointer(bd,5); 4762 } 4763 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4764 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4765 if (maxCell) { 4766 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4767 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4768 dm->periodic = PETSC_TRUE; 4769 } else { 4770 dm->periodic = per; 4771 } 4772 PetscFunctionReturn(0); 4773 } 4774 4775 /*@ 4776 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. 4777 4778 Input Parameters: 4779 + dm - The DM 4780 . in - The input coordinate point (dim numbers) 4781 - endpoint - Include the endpoint L_i 4782 4783 Output Parameter: 4784 . out - The localized coordinate point 4785 4786 Level: developer 4787 4788 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4789 @*/ 4790 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 4791 { 4792 PetscInt dim, d; 4793 PetscErrorCode ierr; 4794 4795 PetscFunctionBegin; 4796 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4797 if (!dm->maxCell) { 4798 for (d = 0; d < dim; ++d) out[d] = in[d]; 4799 } else { 4800 if (endpoint) { 4801 for (d = 0; d < dim; ++d) { 4802 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)) { 4803 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 4804 } else { 4805 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4806 } 4807 } 4808 } else { 4809 for (d = 0; d < dim; ++d) { 4810 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4811 } 4812 } 4813 } 4814 PetscFunctionReturn(0); 4815 } 4816 4817 /* 4818 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. 4819 4820 Input Parameters: 4821 + dm - The DM 4822 . dim - The spatial dimension 4823 . anchor - The anchor point, the input point can be no more than maxCell away from it 4824 - in - The input coordinate point (dim numbers) 4825 4826 Output Parameter: 4827 . out - The localized coordinate point 4828 4829 Level: developer 4830 4831 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 4832 4833 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4834 */ 4835 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4836 { 4837 PetscInt d; 4838 4839 PetscFunctionBegin; 4840 if (!dm->maxCell) { 4841 for (d = 0; d < dim; ++d) out[d] = in[d]; 4842 } else { 4843 for (d = 0; d < dim; ++d) { 4844 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 4845 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4846 } else { 4847 out[d] = in[d]; 4848 } 4849 } 4850 } 4851 PetscFunctionReturn(0); 4852 } 4853 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 4854 { 4855 PetscInt d; 4856 4857 PetscFunctionBegin; 4858 if (!dm->maxCell) { 4859 for (d = 0; d < dim; ++d) out[d] = in[d]; 4860 } else { 4861 for (d = 0; d < dim; ++d) { 4862 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 4863 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4864 } else { 4865 out[d] = in[d]; 4866 } 4867 } 4868 } 4869 PetscFunctionReturn(0); 4870 } 4871 4872 /* 4873 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. 4874 4875 Input Parameters: 4876 + dm - The DM 4877 . dim - The spatial dimension 4878 . anchor - The anchor point, the input point can be no more than maxCell away from it 4879 . in - The input coordinate delta (dim numbers) 4880 - out - The input coordinate point (dim numbers) 4881 4882 Output Parameter: 4883 . out - The localized coordinate in + out 4884 4885 Level: developer 4886 4887 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 4888 4889 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 4890 */ 4891 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4892 { 4893 PetscInt d; 4894 4895 PetscFunctionBegin; 4896 if (!dm->maxCell) { 4897 for (d = 0; d < dim; ++d) out[d] += in[d]; 4898 } else { 4899 for (d = 0; d < dim; ++d) { 4900 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 4901 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4902 } else { 4903 out[d] += in[d]; 4904 } 4905 } 4906 } 4907 PetscFunctionReturn(0); 4908 } 4909 4910 /*@ 4911 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 4912 4913 Input Parameter: 4914 . dm - The DM 4915 4916 Output Parameter: 4917 areLocalized - True if localized 4918 4919 Level: developer 4920 4921 .seealso: DMLocalizeCoordinates() 4922 @*/ 4923 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 4924 { 4925 DM cdm; 4926 PetscSection coordSection; 4927 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 4928 PetscBool isPlex, alreadyLocalized; 4929 PetscErrorCode ierr; 4930 4931 PetscFunctionBegin; 4932 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4933 PetscValidPointer(areLocalized, 2); 4934 4935 *areLocalized = PETSC_FALSE; 4936 if (!dm->periodic) PetscFunctionReturn(0); /* This is a hideous optimization hack! */ 4937 4938 /* We need some generic way of refering to cells/vertices */ 4939 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4940 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4941 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 4942 if (!isPlex) SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4943 4944 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4945 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 4946 alreadyLocalized = PETSC_FALSE; 4947 for (c = cStart; c < cEnd; ++c) { 4948 if (c < sStart || c >= sEnd) continue; 4949 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4950 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 4951 } 4952 ierr = MPIU_Allreduce(&alreadyLocalized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4953 PetscFunctionReturn(0); 4954 } 4955 4956 4957 /*@ 4958 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 4959 4960 Input Parameter: 4961 . dm - The DM 4962 4963 Level: developer 4964 4965 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 4966 @*/ 4967 PetscErrorCode DMLocalizeCoordinates(DM dm) 4968 { 4969 DM cdm; 4970 PetscSection coordSection, cSection; 4971 Vec coordinates, cVec; 4972 PetscScalar *coords, *coords2, *anchor, *localized; 4973 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 4974 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4975 PetscInt maxHeight = 0, h; 4976 PetscInt *pStart = NULL, *pEnd = NULL; 4977 PetscErrorCode ierr; 4978 4979 PetscFunctionBegin; 4980 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4981 if (!dm->periodic) PetscFunctionReturn(0); 4982 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 4983 if (alreadyLocalized) PetscFunctionReturn(0); 4984 4985 /* We need some generic way of refering to cells/vertices */ 4986 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4987 { 4988 PetscBool isplex; 4989 4990 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4991 if (isplex) { 4992 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4993 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 4994 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4995 pEnd = &pStart[maxHeight + 1]; 4996 newStart = vStart; 4997 newEnd = vEnd; 4998 for (h = 0; h <= maxHeight; h++) { 4999 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 5000 newStart = PetscMin(newStart,pStart[h]); 5001 newEnd = PetscMax(newEnd,pEnd[h]); 5002 } 5003 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 5004 } 5005 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5006 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 5007 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5008 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 5009 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 5010 5011 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 5012 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 5013 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 5014 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 5015 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 5016 5017 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5018 localized = &anchor[bs]; 5019 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 5020 for (h = 0; h <= maxHeight; h++) { 5021 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 5022 5023 for (c = cStart; c < cEnd; ++c) { 5024 PetscScalar *cellCoords = NULL; 5025 PetscInt b; 5026 5027 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 5028 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5029 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 5030 for (d = 0; d < dof/bs; ++d) { 5031 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 5032 for (b = 0; b < bs; b++) { 5033 if (cellCoords[d*bs + b] != localized[b]) break; 5034 } 5035 if (b < bs) break; 5036 } 5037 if (d < dof/bs) { 5038 if (c >= sStart && c < sEnd) { 5039 PetscInt cdof; 5040 5041 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 5042 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 5043 } 5044 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 5045 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 5046 } 5047 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5048 } 5049 } 5050 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 5051 if (alreadyLocalizedGlobal) { 5052 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5053 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 5054 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5055 PetscFunctionReturn(0); 5056 } 5057 for (v = vStart; v < vEnd; ++v) { 5058 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 5059 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 5060 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 5061 } 5062 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 5063 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 5064 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 5065 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 5066 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 5067 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 5068 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 5069 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 5070 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 5071 for (v = vStart; v < vEnd; ++v) { 5072 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 5073 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5074 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 5075 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 5076 } 5077 for (h = 0; h <= maxHeight; h++) { 5078 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 5079 5080 for (c = cStart; c < cEnd; ++c) { 5081 PetscScalar *cellCoords = NULL; 5082 PetscInt b, cdof; 5083 5084 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 5085 if (!cdof) continue; 5086 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5087 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 5088 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 5089 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 5090 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5091 } 5092 } 5093 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5094 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5095 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 5096 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 5097 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 5098 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 5099 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 5100 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 5101 PetscFunctionReturn(0); 5102 } 5103 5104 /*@ 5105 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 5106 5107 Collective on Vec v (see explanation below) 5108 5109 Input Parameters: 5110 + dm - The DM 5111 . v - The Vec of points 5112 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 5113 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 5114 5115 Output Parameter: 5116 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 5117 - cells - The PetscSF containing the ranks and local indices of the containing points. 5118 5119 5120 Level: developer 5121 5122 Notes: 5123 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 5124 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 5125 5126 If *cellSF is NULL on input, a PetscSF will be created. 5127 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 5128 5129 An array that maps each point to its containing cell can be obtained with 5130 5131 $ const PetscSFNode *cells; 5132 $ PetscInt nFound; 5133 $ const PetscInt *found; 5134 $ 5135 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 5136 5137 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 5138 the index of the cell in its rank's local numbering. 5139 5140 .keywords: point location, mesh 5141 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 5142 @*/ 5143 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 5144 { 5145 PetscErrorCode ierr; 5146 5147 PetscFunctionBegin; 5148 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5149 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 5150 PetscValidPointer(cellSF,4); 5151 if (*cellSF) { 5152 PetscMPIInt result; 5153 5154 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 5155 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 5156 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 5157 } else { 5158 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 5159 } 5160 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5161 if (dm->ops->locatepoints) { 5162 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 5163 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 5164 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5165 PetscFunctionReturn(0); 5166 } 5167 5168 /*@ 5169 DMGetOutputDM - Retrieve the DM associated with the layout for output 5170 5171 Input Parameter: 5172 . dm - The original DM 5173 5174 Output Parameter: 5175 . odm - The DM which provides the layout for output 5176 5177 Level: intermediate 5178 5179 .seealso: VecView(), DMGetGlobalSection() 5180 @*/ 5181 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 5182 { 5183 PetscSection section; 5184 PetscBool hasConstraints, ghasConstraints; 5185 PetscErrorCode ierr; 5186 5187 PetscFunctionBegin; 5188 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5189 PetscValidPointer(odm,2); 5190 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 5191 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 5192 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 5193 if (!ghasConstraints) { 5194 *odm = dm; 5195 PetscFunctionReturn(0); 5196 } 5197 if (!dm->dmBC) { 5198 PetscDS ds; 5199 PetscSection newSection, gsection; 5200 PetscSF sf; 5201 5202 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 5203 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5204 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 5205 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 5206 ierr = DMSetSection(dm->dmBC, newSection);CHKERRQ(ierr); 5207 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 5208 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 5209 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 5210 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 5211 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 5212 } 5213 *odm = dm->dmBC; 5214 PetscFunctionReturn(0); 5215 } 5216 5217 /*@ 5218 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 5219 5220 Input Parameter: 5221 . dm - The original DM 5222 5223 Output Parameters: 5224 + num - The output sequence number 5225 - val - The output sequence value 5226 5227 Level: intermediate 5228 5229 Note: This is intended for output that should appear in sequence, for instance 5230 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5231 5232 .seealso: VecView() 5233 @*/ 5234 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 5235 { 5236 PetscFunctionBegin; 5237 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5238 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 5239 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 5240 PetscFunctionReturn(0); 5241 } 5242 5243 /*@ 5244 DMSetOutputSequenceNumber - Set the sequence number/value for output 5245 5246 Input Parameters: 5247 + dm - The original DM 5248 . num - The output sequence number 5249 - val - The output sequence value 5250 5251 Level: intermediate 5252 5253 Note: This is intended for output that should appear in sequence, for instance 5254 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5255 5256 .seealso: VecView() 5257 @*/ 5258 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5259 { 5260 PetscFunctionBegin; 5261 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5262 dm->outputSequenceNum = num; 5263 dm->outputSequenceVal = val; 5264 PetscFunctionReturn(0); 5265 } 5266 5267 /*@C 5268 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5269 5270 Input Parameters: 5271 + dm - The original DM 5272 . name - The sequence name 5273 - num - The output sequence number 5274 5275 Output Parameter: 5276 . val - The output sequence value 5277 5278 Level: intermediate 5279 5280 Note: This is intended for output that should appear in sequence, for instance 5281 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5282 5283 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5284 @*/ 5285 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5286 { 5287 PetscBool ishdf5; 5288 PetscErrorCode ierr; 5289 5290 PetscFunctionBegin; 5291 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5292 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5293 PetscValidPointer(val,4); 5294 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5295 if (ishdf5) { 5296 #if defined(PETSC_HAVE_HDF5) 5297 PetscScalar value; 5298 5299 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 5300 *val = PetscRealPart(value); 5301 #endif 5302 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5303 PetscFunctionReturn(0); 5304 } 5305 5306 /*@ 5307 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5308 5309 Not collective 5310 5311 Input Parameter: 5312 . dm - The DM 5313 5314 Output Parameter: 5315 . useNatural - The flag to build the mapping to a natural order during distribution 5316 5317 Level: beginner 5318 5319 .seealso: DMSetUseNatural(), DMCreate() 5320 @*/ 5321 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5322 { 5323 PetscFunctionBegin; 5324 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5325 PetscValidPointer(useNatural, 2); 5326 *useNatural = dm->useNatural; 5327 PetscFunctionReturn(0); 5328 } 5329 5330 /*@ 5331 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5332 5333 Collective on dm 5334 5335 Input Parameters: 5336 + dm - The DM 5337 - useNatural - The flag to build the mapping to a natural order during distribution 5338 5339 Level: beginner 5340 5341 .seealso: DMGetUseNatural(), DMCreate() 5342 @*/ 5343 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5344 { 5345 PetscFunctionBegin; 5346 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5347 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 5348 dm->useNatural = useNatural; 5349 PetscFunctionReturn(0); 5350 } 5351 5352 5353 /*@C 5354 DMCreateLabel - Create a label of the given name if it does not already exist 5355 5356 Not Collective 5357 5358 Input Parameters: 5359 + dm - The DM object 5360 - name - The label name 5361 5362 Level: intermediate 5363 5364 .keywords: mesh 5365 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5366 @*/ 5367 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5368 { 5369 DMLabelLink next = dm->labels->next; 5370 PetscBool flg = PETSC_FALSE; 5371 PetscErrorCode ierr; 5372 5373 PetscFunctionBegin; 5374 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5375 PetscValidCharPointer(name, 2); 5376 while (next) { 5377 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5378 if (flg) break; 5379 next = next->next; 5380 } 5381 if (!flg) { 5382 DMLabelLink tmpLabel; 5383 5384 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5385 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5386 tmpLabel->output = PETSC_TRUE; 5387 tmpLabel->next = dm->labels->next; 5388 dm->labels->next = tmpLabel; 5389 } 5390 PetscFunctionReturn(0); 5391 } 5392 5393 /*@C 5394 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5395 5396 Not Collective 5397 5398 Input Parameters: 5399 + dm - The DM object 5400 . name - The label name 5401 - point - The mesh point 5402 5403 Output Parameter: 5404 . value - The label value for this point, or -1 if the point is not in the label 5405 5406 Level: beginner 5407 5408 .keywords: mesh 5409 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5410 @*/ 5411 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5412 { 5413 DMLabel label; 5414 PetscErrorCode ierr; 5415 5416 PetscFunctionBegin; 5417 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5418 PetscValidCharPointer(name, 2); 5419 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5420 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 5421 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5422 PetscFunctionReturn(0); 5423 } 5424 5425 /*@C 5426 DMSetLabelValue - Add a point to a Sieve Label with given value 5427 5428 Not Collective 5429 5430 Input Parameters: 5431 + dm - The DM object 5432 . name - The label name 5433 . point - The mesh point 5434 - value - The label value for this point 5435 5436 Output Parameter: 5437 5438 Level: beginner 5439 5440 .keywords: mesh 5441 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5442 @*/ 5443 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5444 { 5445 DMLabel label; 5446 PetscErrorCode ierr; 5447 5448 PetscFunctionBegin; 5449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5450 PetscValidCharPointer(name, 2); 5451 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5452 if (!label) { 5453 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5454 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5455 } 5456 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5457 PetscFunctionReturn(0); 5458 } 5459 5460 /*@C 5461 DMClearLabelValue - Remove a point from a Sieve Label with given value 5462 5463 Not Collective 5464 5465 Input Parameters: 5466 + dm - The DM object 5467 . name - The label name 5468 . point - The mesh point 5469 - value - The label value for this point 5470 5471 Output Parameter: 5472 5473 Level: beginner 5474 5475 .keywords: mesh 5476 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5477 @*/ 5478 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5479 { 5480 DMLabel label; 5481 PetscErrorCode ierr; 5482 5483 PetscFunctionBegin; 5484 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5485 PetscValidCharPointer(name, 2); 5486 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5487 if (!label) PetscFunctionReturn(0); 5488 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5489 PetscFunctionReturn(0); 5490 } 5491 5492 /*@C 5493 DMGetLabelSize - Get the number of different integer ids in a Label 5494 5495 Not Collective 5496 5497 Input Parameters: 5498 + dm - The DM object 5499 - name - The label name 5500 5501 Output Parameter: 5502 . size - The number of different integer ids, or 0 if the label does not exist 5503 5504 Level: beginner 5505 5506 .keywords: mesh 5507 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5508 @*/ 5509 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5510 { 5511 DMLabel label; 5512 PetscErrorCode ierr; 5513 5514 PetscFunctionBegin; 5515 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5516 PetscValidCharPointer(name, 2); 5517 PetscValidPointer(size, 3); 5518 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5519 *size = 0; 5520 if (!label) PetscFunctionReturn(0); 5521 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5522 PetscFunctionReturn(0); 5523 } 5524 5525 /*@C 5526 DMGetLabelIdIS - Get the integer ids in a label 5527 5528 Not Collective 5529 5530 Input Parameters: 5531 + mesh - The DM object 5532 - name - The label name 5533 5534 Output Parameter: 5535 . ids - The integer ids, or NULL if the label does not exist 5536 5537 Level: beginner 5538 5539 .keywords: mesh 5540 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5541 @*/ 5542 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5543 { 5544 DMLabel label; 5545 PetscErrorCode ierr; 5546 5547 PetscFunctionBegin; 5548 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5549 PetscValidCharPointer(name, 2); 5550 PetscValidPointer(ids, 3); 5551 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5552 *ids = NULL; 5553 if (label) { 5554 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5555 } else { 5556 /* returning an empty IS */ 5557 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 5558 } 5559 PetscFunctionReturn(0); 5560 } 5561 5562 /*@C 5563 DMGetStratumSize - Get the number of points in a label stratum 5564 5565 Not Collective 5566 5567 Input Parameters: 5568 + dm - The DM object 5569 . name - The label name 5570 - value - The stratum value 5571 5572 Output Parameter: 5573 . size - The stratum size 5574 5575 Level: beginner 5576 5577 .keywords: mesh 5578 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5579 @*/ 5580 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5581 { 5582 DMLabel label; 5583 PetscErrorCode ierr; 5584 5585 PetscFunctionBegin; 5586 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5587 PetscValidCharPointer(name, 2); 5588 PetscValidPointer(size, 4); 5589 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5590 *size = 0; 5591 if (!label) PetscFunctionReturn(0); 5592 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5593 PetscFunctionReturn(0); 5594 } 5595 5596 /*@C 5597 DMGetStratumIS - Get the points in a label stratum 5598 5599 Not Collective 5600 5601 Input Parameters: 5602 + dm - The DM object 5603 . name - The label name 5604 - value - The stratum value 5605 5606 Output Parameter: 5607 . points - The stratum points, or NULL if the label does not exist or does not have that value 5608 5609 Level: beginner 5610 5611 .keywords: mesh 5612 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5613 @*/ 5614 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5615 { 5616 DMLabel label; 5617 PetscErrorCode ierr; 5618 5619 PetscFunctionBegin; 5620 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5621 PetscValidCharPointer(name, 2); 5622 PetscValidPointer(points, 4); 5623 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5624 *points = NULL; 5625 if (!label) PetscFunctionReturn(0); 5626 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5627 PetscFunctionReturn(0); 5628 } 5629 5630 /*@C 5631 DMSetStratumIS - Set the points in a label stratum 5632 5633 Not Collective 5634 5635 Input Parameters: 5636 + dm - The DM object 5637 . name - The label name 5638 . value - The stratum value 5639 - points - The stratum points 5640 5641 Level: beginner 5642 5643 .keywords: mesh 5644 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 5645 @*/ 5646 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 5647 { 5648 DMLabel label; 5649 PetscErrorCode ierr; 5650 5651 PetscFunctionBegin; 5652 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5653 PetscValidCharPointer(name, 2); 5654 PetscValidPointer(points, 4); 5655 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5656 if (!label) PetscFunctionReturn(0); 5657 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 5658 PetscFunctionReturn(0); 5659 } 5660 5661 /*@C 5662 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5663 5664 Not Collective 5665 5666 Input Parameters: 5667 + dm - The DM object 5668 . name - The label name 5669 - value - The label value for this point 5670 5671 Output Parameter: 5672 5673 Level: beginner 5674 5675 .keywords: mesh 5676 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5677 @*/ 5678 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5679 { 5680 DMLabel label; 5681 PetscErrorCode ierr; 5682 5683 PetscFunctionBegin; 5684 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5685 PetscValidCharPointer(name, 2); 5686 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5687 if (!label) PetscFunctionReturn(0); 5688 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5689 PetscFunctionReturn(0); 5690 } 5691 5692 /*@ 5693 DMGetNumLabels - Return the number of labels defined by the mesh 5694 5695 Not Collective 5696 5697 Input Parameter: 5698 . dm - The DM object 5699 5700 Output Parameter: 5701 . numLabels - the number of Labels 5702 5703 Level: intermediate 5704 5705 .keywords: mesh 5706 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5707 @*/ 5708 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5709 { 5710 DMLabelLink next = dm->labels->next; 5711 PetscInt n = 0; 5712 5713 PetscFunctionBegin; 5714 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5715 PetscValidPointer(numLabels, 2); 5716 while (next) {++n; next = next->next;} 5717 *numLabels = n; 5718 PetscFunctionReturn(0); 5719 } 5720 5721 /*@C 5722 DMGetLabelName - Return the name of nth label 5723 5724 Not Collective 5725 5726 Input Parameters: 5727 + dm - The DM object 5728 - n - the label number 5729 5730 Output Parameter: 5731 . name - the label name 5732 5733 Level: intermediate 5734 5735 .keywords: mesh 5736 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5737 @*/ 5738 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5739 { 5740 DMLabelLink next = dm->labels->next; 5741 PetscInt l = 0; 5742 5743 PetscFunctionBegin; 5744 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5745 PetscValidPointer(name, 3); 5746 while (next) { 5747 if (l == n) { 5748 *name = next->label->name; 5749 PetscFunctionReturn(0); 5750 } 5751 ++l; 5752 next = next->next; 5753 } 5754 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5755 } 5756 5757 /*@C 5758 DMHasLabel - Determine whether the mesh has a label of a given name 5759 5760 Not Collective 5761 5762 Input Parameters: 5763 + dm - The DM object 5764 - name - The label name 5765 5766 Output Parameter: 5767 . hasLabel - PETSC_TRUE if the label is present 5768 5769 Level: intermediate 5770 5771 .keywords: mesh 5772 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5773 @*/ 5774 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5775 { 5776 DMLabelLink next = dm->labels->next; 5777 PetscErrorCode ierr; 5778 5779 PetscFunctionBegin; 5780 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5781 PetscValidCharPointer(name, 2); 5782 PetscValidPointer(hasLabel, 3); 5783 *hasLabel = PETSC_FALSE; 5784 while (next) { 5785 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5786 if (*hasLabel) break; 5787 next = next->next; 5788 } 5789 PetscFunctionReturn(0); 5790 } 5791 5792 /*@C 5793 DMGetLabel - Return the label of a given name, or NULL 5794 5795 Not Collective 5796 5797 Input Parameters: 5798 + dm - The DM object 5799 - name - The label name 5800 5801 Output Parameter: 5802 . label - The DMLabel, or NULL if the label is absent 5803 5804 Level: intermediate 5805 5806 .keywords: mesh 5807 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5808 @*/ 5809 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5810 { 5811 DMLabelLink next = dm->labels->next; 5812 PetscBool hasLabel; 5813 PetscErrorCode ierr; 5814 5815 PetscFunctionBegin; 5816 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5817 PetscValidCharPointer(name, 2); 5818 PetscValidPointer(label, 3); 5819 *label = NULL; 5820 while (next) { 5821 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5822 if (hasLabel) { 5823 *label = next->label; 5824 break; 5825 } 5826 next = next->next; 5827 } 5828 PetscFunctionReturn(0); 5829 } 5830 5831 /*@C 5832 DMGetLabelByNum - Return the nth label 5833 5834 Not Collective 5835 5836 Input Parameters: 5837 + dm - The DM object 5838 - n - the label number 5839 5840 Output Parameter: 5841 . label - the label 5842 5843 Level: intermediate 5844 5845 .keywords: mesh 5846 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5847 @*/ 5848 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5849 { 5850 DMLabelLink next = dm->labels->next; 5851 PetscInt l = 0; 5852 5853 PetscFunctionBegin; 5854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5855 PetscValidPointer(label, 3); 5856 while (next) { 5857 if (l == n) { 5858 *label = next->label; 5859 PetscFunctionReturn(0); 5860 } 5861 ++l; 5862 next = next->next; 5863 } 5864 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5865 } 5866 5867 /*@C 5868 DMAddLabel - Add the label to this mesh 5869 5870 Not Collective 5871 5872 Input Parameters: 5873 + dm - The DM object 5874 - label - The DMLabel 5875 5876 Level: developer 5877 5878 .keywords: mesh 5879 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5880 @*/ 5881 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5882 { 5883 DMLabelLink tmpLabel; 5884 PetscBool hasLabel; 5885 PetscErrorCode ierr; 5886 5887 PetscFunctionBegin; 5888 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5889 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5890 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5891 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5892 tmpLabel->label = label; 5893 tmpLabel->output = PETSC_TRUE; 5894 tmpLabel->next = dm->labels->next; 5895 dm->labels->next = tmpLabel; 5896 PetscFunctionReturn(0); 5897 } 5898 5899 /*@C 5900 DMRemoveLabel - Remove the label from this mesh 5901 5902 Not Collective 5903 5904 Input Parameters: 5905 + dm - The DM object 5906 - name - The label name 5907 5908 Output Parameter: 5909 . label - The DMLabel, or NULL if the label is absent 5910 5911 Level: developer 5912 5913 .keywords: mesh 5914 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5915 @*/ 5916 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5917 { 5918 DMLabelLink next = dm->labels->next; 5919 DMLabelLink last = NULL; 5920 PetscBool hasLabel; 5921 PetscErrorCode ierr; 5922 5923 PetscFunctionBegin; 5924 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5925 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5926 *label = NULL; 5927 if (!hasLabel) PetscFunctionReturn(0); 5928 while (next) { 5929 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5930 if (hasLabel) { 5931 if (last) last->next = next->next; 5932 else dm->labels->next = next->next; 5933 next->next = NULL; 5934 *label = next->label; 5935 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5936 if (hasLabel) { 5937 dm->depthLabel = NULL; 5938 } 5939 ierr = PetscFree(next);CHKERRQ(ierr); 5940 break; 5941 } 5942 last = next; 5943 next = next->next; 5944 } 5945 PetscFunctionReturn(0); 5946 } 5947 5948 /*@C 5949 DMGetLabelOutput - Get the output flag for a given label 5950 5951 Not Collective 5952 5953 Input Parameters: 5954 + dm - The DM object 5955 - name - The label name 5956 5957 Output Parameter: 5958 . output - The flag for output 5959 5960 Level: developer 5961 5962 .keywords: mesh 5963 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5964 @*/ 5965 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5966 { 5967 DMLabelLink next = dm->labels->next; 5968 PetscErrorCode ierr; 5969 5970 PetscFunctionBegin; 5971 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5972 PetscValidPointer(name, 2); 5973 PetscValidPointer(output, 3); 5974 while (next) { 5975 PetscBool flg; 5976 5977 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5978 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5979 next = next->next; 5980 } 5981 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5982 } 5983 5984 /*@C 5985 DMSetLabelOutput - Set the output flag for a given label 5986 5987 Not Collective 5988 5989 Input Parameters: 5990 + dm - The DM object 5991 . name - The label name 5992 - output - The flag for output 5993 5994 Level: developer 5995 5996 .keywords: mesh 5997 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5998 @*/ 5999 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 6000 { 6001 DMLabelLink next = dm->labels->next; 6002 PetscErrorCode ierr; 6003 6004 PetscFunctionBegin; 6005 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6006 PetscValidPointer(name, 2); 6007 while (next) { 6008 PetscBool flg; 6009 6010 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 6011 if (flg) {next->output = output; PetscFunctionReturn(0);} 6012 next = next->next; 6013 } 6014 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 6015 } 6016 6017 6018 /*@ 6019 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 6020 6021 Collective on DM 6022 6023 Input Parameter: 6024 . dmA - The DM object with initial labels 6025 6026 Output Parameter: 6027 . dmB - The DM object with copied labels 6028 6029 Level: intermediate 6030 6031 Note: This is typically used when interpolating or otherwise adding to a mesh 6032 6033 .keywords: mesh 6034 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 6035 @*/ 6036 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 6037 { 6038 PetscInt numLabels, l; 6039 PetscErrorCode ierr; 6040 6041 PetscFunctionBegin; 6042 if (dmA == dmB) PetscFunctionReturn(0); 6043 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 6044 for (l = 0; l < numLabels; ++l) { 6045 DMLabel label, labelNew; 6046 const char *name; 6047 PetscBool flg; 6048 6049 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 6050 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 6051 if (flg) continue; 6052 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 6053 if (flg) continue; 6054 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 6055 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 6056 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 6057 } 6058 PetscFunctionReturn(0); 6059 } 6060 6061 /*@ 6062 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 6063 6064 Input Parameter: 6065 . dm - The DM object 6066 6067 Output Parameter: 6068 . cdm - The coarse DM 6069 6070 Level: intermediate 6071 6072 .seealso: DMSetCoarseDM() 6073 @*/ 6074 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 6075 { 6076 PetscFunctionBegin; 6077 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6078 PetscValidPointer(cdm, 2); 6079 *cdm = dm->coarseMesh; 6080 PetscFunctionReturn(0); 6081 } 6082 6083 /*@ 6084 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 6085 6086 Input Parameters: 6087 + dm - The DM object 6088 - cdm - The coarse DM 6089 6090 Level: intermediate 6091 6092 .seealso: DMGetCoarseDM() 6093 @*/ 6094 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 6095 { 6096 PetscErrorCode ierr; 6097 6098 PetscFunctionBegin; 6099 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6100 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 6101 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6102 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 6103 dm->coarseMesh = cdm; 6104 PetscFunctionReturn(0); 6105 } 6106 6107 /*@ 6108 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 6109 6110 Input Parameter: 6111 . dm - The DM object 6112 6113 Output Parameter: 6114 . fdm - The fine DM 6115 6116 Level: intermediate 6117 6118 .seealso: DMSetFineDM() 6119 @*/ 6120 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 6121 { 6122 PetscFunctionBegin; 6123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6124 PetscValidPointer(fdm, 2); 6125 *fdm = dm->fineMesh; 6126 PetscFunctionReturn(0); 6127 } 6128 6129 /*@ 6130 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 6131 6132 Input Parameters: 6133 + dm - The DM object 6134 - fdm - The fine DM 6135 6136 Level: intermediate 6137 6138 .seealso: DMGetFineDM() 6139 @*/ 6140 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 6141 { 6142 PetscErrorCode ierr; 6143 6144 PetscFunctionBegin; 6145 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6146 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 6147 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 6148 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 6149 dm->fineMesh = fdm; 6150 PetscFunctionReturn(0); 6151 } 6152 6153 /*=== DMBoundary code ===*/ 6154 6155 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 6156 { 6157 PetscErrorCode ierr; 6158 6159 PetscFunctionBegin; 6160 ierr = PetscDSCopyBoundary(dm->prob,dmNew->prob);CHKERRQ(ierr); 6161 PetscFunctionReturn(0); 6162 } 6163 6164 /*@C 6165 DMAddBoundary - Add a boundary condition to the model 6166 6167 Input Parameters: 6168 + dm - The DM, with a PetscDS that matches the problem being constrained 6169 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6170 . name - The BC name 6171 . labelname - The label defining constrained points 6172 . field - The field to constrain 6173 . numcomps - The number of constrained field components 6174 . comps - An array of constrained component numbers 6175 . bcFunc - A pointwise function giving boundary values 6176 . numids - The number of DMLabel ids for constrained points 6177 . ids - An array of ids for constrained points 6178 - ctx - An optional user context for bcFunc 6179 6180 Options Database Keys: 6181 + -bc_<boundary name> <num> - Overrides the boundary ids 6182 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6183 6184 Level: developer 6185 6186 .seealso: DMGetBoundary() 6187 @*/ 6188 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) 6189 { 6190 PetscErrorCode ierr; 6191 6192 PetscFunctionBegin; 6193 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6194 ierr = PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);CHKERRQ(ierr); 6195 PetscFunctionReturn(0); 6196 } 6197 6198 /*@ 6199 DMGetNumBoundary - Get the number of registered BC 6200 6201 Input Parameters: 6202 . dm - The mesh object 6203 6204 Output Parameters: 6205 . numBd - The number of BC 6206 6207 Level: intermediate 6208 6209 .seealso: DMAddBoundary(), DMGetBoundary() 6210 @*/ 6211 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6212 { 6213 PetscErrorCode ierr; 6214 6215 PetscFunctionBegin; 6216 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6217 ierr = PetscDSGetNumBoundary(dm->prob,numBd);CHKERRQ(ierr); 6218 PetscFunctionReturn(0); 6219 } 6220 6221 /*@C 6222 DMGetBoundary - Get a model boundary condition 6223 6224 Input Parameters: 6225 + dm - The mesh object 6226 - bd - The BC number 6227 6228 Output Parameters: 6229 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6230 . name - The BC name 6231 . labelname - The label defining constrained points 6232 . field - The field to constrain 6233 . numcomps - The number of constrained field components 6234 . comps - An array of constrained component numbers 6235 . bcFunc - A pointwise function giving boundary values 6236 . numids - The number of DMLabel ids for constrained points 6237 . ids - An array of ids for constrained points 6238 - ctx - An optional user context for bcFunc 6239 6240 Options Database Keys: 6241 + -bc_<boundary name> <num> - Overrides the boundary ids 6242 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6243 6244 Level: developer 6245 6246 .seealso: DMAddBoundary() 6247 @*/ 6248 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) 6249 { 6250 PetscErrorCode ierr; 6251 6252 PetscFunctionBegin; 6253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6254 ierr = PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);CHKERRQ(ierr); 6255 PetscFunctionReturn(0); 6256 } 6257 6258 static PetscErrorCode DMPopulateBoundary(DM dm) 6259 { 6260 DMBoundary *lastnext; 6261 DSBoundary dsbound; 6262 PetscErrorCode ierr; 6263 6264 PetscFunctionBegin; 6265 dsbound = dm->prob->boundary; 6266 if (dm->boundary) { 6267 DMBoundary next = dm->boundary; 6268 6269 /* quick check to see if the PetscDS has changed */ 6270 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 6271 /* the PetscDS has changed: tear down and rebuild */ 6272 while (next) { 6273 DMBoundary b = next; 6274 6275 next = b->next; 6276 ierr = PetscFree(b);CHKERRQ(ierr); 6277 } 6278 dm->boundary = NULL; 6279 } 6280 6281 lastnext = &(dm->boundary); 6282 while (dsbound) { 6283 DMBoundary dmbound; 6284 6285 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 6286 dmbound->dsboundary = dsbound; 6287 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 6288 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 6289 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 6290 *lastnext = dmbound; 6291 lastnext = &(dmbound->next); 6292 dsbound = dsbound->next; 6293 } 6294 PetscFunctionReturn(0); 6295 } 6296 6297 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6298 { 6299 DMBoundary b; 6300 PetscErrorCode ierr; 6301 6302 PetscFunctionBegin; 6303 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6304 PetscValidPointer(isBd, 3); 6305 *isBd = PETSC_FALSE; 6306 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 6307 b = dm->boundary; 6308 while (b && !(*isBd)) { 6309 DMLabel label = b->label; 6310 DSBoundary dsb = b->dsboundary; 6311 6312 if (label) { 6313 PetscInt i; 6314 6315 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 6316 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 6317 } 6318 } 6319 b = b->next; 6320 } 6321 PetscFunctionReturn(0); 6322 } 6323 6324 /*@C 6325 DMProjectFunction - This projects the given function into the function space provided. 6326 6327 Input Parameters: 6328 + dm - The DM 6329 . time - The time 6330 . funcs - The coordinate functions to evaluate, one per field 6331 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6332 - mode - The insertion mode for values 6333 6334 Output Parameter: 6335 . X - vector 6336 6337 Calling sequence of func: 6338 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6339 6340 + dim - The spatial dimension 6341 . x - The coordinates 6342 . Nf - The number of fields 6343 . u - The output field values 6344 - ctx - optional user-defined function context 6345 6346 Level: developer 6347 6348 .seealso: DMComputeL2Diff() 6349 @*/ 6350 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6351 { 6352 Vec localX; 6353 PetscErrorCode ierr; 6354 6355 PetscFunctionBegin; 6356 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6357 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6358 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6359 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6360 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6361 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6362 PetscFunctionReturn(0); 6363 } 6364 6365 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6366 { 6367 PetscErrorCode ierr; 6368 6369 PetscFunctionBegin; 6370 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6371 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6372 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6373 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6374 PetscFunctionReturn(0); 6375 } 6376 6377 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) 6378 { 6379 Vec localX; 6380 PetscErrorCode ierr; 6381 6382 PetscFunctionBegin; 6383 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6384 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6385 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6386 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6387 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6388 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6389 PetscFunctionReturn(0); 6390 } 6391 6392 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) 6393 { 6394 PetscErrorCode ierr; 6395 6396 PetscFunctionBegin; 6397 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6398 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6399 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6400 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6401 PetscFunctionReturn(0); 6402 } 6403 6404 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 6405 void (**funcs)(PetscInt, PetscInt, PetscInt, 6406 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6407 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6408 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6409 InsertMode mode, Vec localX) 6410 { 6411 PetscErrorCode ierr; 6412 6413 PetscFunctionBegin; 6414 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6415 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 6416 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 6417 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6418 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 6419 PetscFunctionReturn(0); 6420 } 6421 6422 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 6423 void (**funcs)(PetscInt, PetscInt, PetscInt, 6424 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6425 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6426 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6427 InsertMode mode, Vec localX) 6428 { 6429 PetscErrorCode ierr; 6430 6431 PetscFunctionBegin; 6432 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6433 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 6434 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 6435 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6436 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 6437 PetscFunctionReturn(0); 6438 } 6439 6440 /*@C 6441 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6442 6443 Input Parameters: 6444 + dm - The DM 6445 . time - The time 6446 . funcs - The functions to evaluate for each field component 6447 . ctxs - Optional array of contexts to pass to each function, or NULL. 6448 - X - The coefficient vector u_h, a global vector 6449 6450 Output Parameter: 6451 . diff - The diff ||u - u_h||_2 6452 6453 Level: developer 6454 6455 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6456 @*/ 6457 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6458 { 6459 PetscErrorCode ierr; 6460 6461 PetscFunctionBegin; 6462 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6463 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6464 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 6465 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6466 PetscFunctionReturn(0); 6467 } 6468 6469 /*@C 6470 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6471 6472 Input Parameters: 6473 + dm - The DM 6474 , time - The time 6475 . funcs - The gradient functions to evaluate for each field component 6476 . ctxs - Optional array of contexts to pass to each function, or NULL. 6477 . X - The coefficient vector u_h, a global vector 6478 - n - The vector to project along 6479 6480 Output Parameter: 6481 . diff - The diff ||(grad u - grad u_h) . n||_2 6482 6483 Level: developer 6484 6485 .seealso: DMProjectFunction(), DMComputeL2Diff() 6486 @*/ 6487 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) 6488 { 6489 PetscErrorCode ierr; 6490 6491 PetscFunctionBegin; 6492 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6493 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6494 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6495 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6496 PetscFunctionReturn(0); 6497 } 6498 6499 /*@C 6500 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 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 array of differences, ||u^f - u^f_h||_2 6511 6512 Level: developer 6513 6514 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6515 @*/ 6516 PetscErrorCode DMComputeL2FieldDiff(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->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6524 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6525 PetscFunctionReturn(0); 6526 } 6527 6528 /*@C 6529 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 6530 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 6531 6532 Collective on dm 6533 6534 Input parameters: 6535 + dm - the pre-adaptation DM object 6536 - label - label with the flags 6537 6538 Output parameters: 6539 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 6540 6541 Level: intermediate 6542 6543 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 6544 @*/ 6545 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 6546 { 6547 PetscErrorCode ierr; 6548 6549 PetscFunctionBegin; 6550 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6551 PetscValidPointer(label,2); 6552 PetscValidPointer(dmAdapt,3); 6553 *dmAdapt = NULL; 6554 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 6555 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 6556 PetscFunctionReturn(0); 6557 } 6558 6559 /*@C 6560 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 6561 6562 Input Parameters: 6563 + dm - The DM object 6564 . metric - The metric to which the mesh is adapted, defined vertex-wise. 6565 - 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_". 6566 6567 Output Parameter: 6568 . dmAdapt - Pointer to the DM object containing the adapted mesh 6569 6570 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 6571 6572 Level: advanced 6573 6574 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 6575 @*/ 6576 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 6577 { 6578 PetscErrorCode ierr; 6579 6580 PetscFunctionBegin; 6581 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6582 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 6583 if (bdLabel) PetscValidPointer(bdLabel, 3); 6584 PetscValidPointer(dmAdapt, 4); 6585 *dmAdapt = NULL; 6586 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 6587 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 6588 PetscFunctionReturn(0); 6589 } 6590 6591 /*@C 6592 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6593 6594 Not Collective 6595 6596 Input Parameter: 6597 . dm - The DM 6598 6599 Output Parameter: 6600 . nranks - the number of neighbours 6601 . ranks - the neighbors ranks 6602 6603 Notes: 6604 Do not free the array, it is freed when the DM is destroyed. 6605 6606 Level: beginner 6607 6608 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6609 @*/ 6610 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6611 { 6612 PetscErrorCode ierr; 6613 6614 PetscFunctionBegin; 6615 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6616 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 6617 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6618 PetscFunctionReturn(0); 6619 } 6620 6621 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 6622 6623 /* 6624 Converts the input vector to a ghosted vector and then calls the standard coloring code. 6625 This has be a different function because it requires DM which is not defined in the Mat library 6626 */ 6627 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 6628 { 6629 PetscErrorCode ierr; 6630 6631 PetscFunctionBegin; 6632 if (coloring->ctype == IS_COLORING_LOCAL) { 6633 Vec x1local; 6634 DM dm; 6635 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6636 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 6637 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 6638 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6639 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6640 x1 = x1local; 6641 } 6642 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 6643 if (coloring->ctype == IS_COLORING_LOCAL) { 6644 DM dm; 6645 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6646 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 6647 } 6648 PetscFunctionReturn(0); 6649 } 6650 6651 /*@ 6652 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 6653 6654 Input Parameter: 6655 . coloring - the MatFDColoring object 6656 6657 Developer Notes: 6658 this routine exists because the PETSc Mat library does not know about the DM objects 6659 6660 Level: advanced 6661 6662 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 6663 @*/ 6664 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 6665 { 6666 PetscFunctionBegin; 6667 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 6668 PetscFunctionReturn(0); 6669 } 6670 6671 /*@ 6672 DMGetCompatibility - determine if two DMs are compatible 6673 6674 Collective 6675 6676 Input Parameters: 6677 + dm - the first DM 6678 - dm2 - the second DM 6679 6680 Output Parameters: 6681 + compatible - whether or not the two DMs are compatible 6682 - set - whether or not the compatible value was set 6683 6684 Notes: 6685 Two DMs are deemed compatible if they represent the same parallel decomposition 6686 of the same topology. This implies that the the section (field data) on one 6687 "makes sense" with respect to the topology and parallel decomposition of the other. 6688 Loosely speaking, compatibile DMs represent the same domain, with the same parallel 6689 decomposition, with different data. 6690 6691 Typically, one would confirm compatibility if intending to simultaneously iterate 6692 over a pair of vectors obtained from different DMs. 6693 6694 For example, two DMDA objects are compatible if they have the same local 6695 and global sizes and the same stencil width. They can have different numbers 6696 of degrees of freedom per node. Thus, one could use the node numbering from 6697 either DM in bounds for a loop over vectors derived from either DM. 6698 6699 Consider the operation of summing data living on a 2-dof DMDA to data living 6700 on a 1-dof DMDA, which should be compatible, as in the following snippet. 6701 .vb 6702 ... 6703 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 6704 if (set && compatible) { 6705 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 6706 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 6707 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n);CHKERRQ(ierr); 6708 for (j=y; j<y+n; ++j) { 6709 for (i=x; i<x+m, ++i) { 6710 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 6711 } 6712 } 6713 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 6714 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 6715 } else { 6716 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 6717 } 6718 ... 6719 .ve 6720 6721 Checking compatibility might be expensive for a given implementation of DM, 6722 or might be impossible to unambiguously confirm or deny. For this reason, 6723 this function may decline to determine compatibility, and hence users should 6724 always check the "set" output parameter. 6725 6726 A DM is always compatible with itself. 6727 6728 In the current implementation, DMs which live on "unequal" communicators 6729 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 6730 incompatible. 6731 6732 This function is labeled "Collective," as information about all subdomains 6733 is required on each rank. However, in DM implementations which store all this 6734 information locally, this function may be merely "Logically Collective". 6735 6736 Developer Notes: 6737 Compatibility is assumed to be a symmetric concept; if DM A is compatible with DM B, 6738 the DM B is compatible with DM A. Thus, this function checks the implementations 6739 of both dm and dm2 (if they are of different types), attempting to determine 6740 compatibility. It is left to DM implementers to ensure that symmetry is 6741 preserved. The simplest way to do this is, when implementing type-specific 6742 logic for this function, to check for existing logic in the implementation 6743 of other DM types and let *set = PETSC_FALSE if found; the logic of this 6744 function will then call that logic. 6745 6746 Level: advanced 6747 6748 .seealso: DM, DMDACreateCompatibleDMDA() 6749 @*/ 6750 6751 PetscErrorCode DMGetCompatibility(DM dm,DM dm2,PetscBool *compatible,PetscBool *set) 6752 { 6753 PetscErrorCode ierr; 6754 PetscMPIInt compareResult; 6755 DMType type,type2; 6756 PetscBool sameType; 6757 6758 PetscFunctionBegin; 6759 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6760 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 6761 6762 /* Declare a DM compatible with itself */ 6763 if (dm == dm2) { 6764 *set = PETSC_TRUE; 6765 *compatible = PETSC_TRUE; 6766 PetscFunctionReturn(0); 6767 } 6768 6769 /* Declare a DM incompatible with a DM that lives on an "unequal" 6770 communicator. Note that this does not preclude compatibility with 6771 DMs living on "congruent" or "similar" communicators, but this must be 6772 determined by the implementation-specific logic */ 6773 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 6774 if (compareResult == MPI_UNEQUAL) { 6775 *set = PETSC_TRUE; 6776 *compatible = PETSC_FALSE; 6777 PetscFunctionReturn(0); 6778 } 6779 6780 /* Pass to the implementation-specific routine, if one exists. */ 6781 if (dm->ops->getcompatibility) { 6782 ierr = (*dm->ops->getcompatibility)(dm,dm2,compatible,set);CHKERRQ(ierr); 6783 if (*set) { 6784 PetscFunctionReturn(0); 6785 } 6786 } 6787 6788 /* If dm and dm2 are of different types, then attempt to check compatibility 6789 with an implementation of this function from dm2 */ 6790 ierr = DMGetType(dm,&type);CHKERRQ(ierr); 6791 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 6792 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 6793 if (!sameType && dm2->ops->getcompatibility) { 6794 ierr = (*dm2->ops->getcompatibility)(dm2,dm,compatible,set);CHKERRQ(ierr); /* Note argument order */ 6795 } else { 6796 *set = PETSC_FALSE; 6797 } 6798 PetscFunctionReturn(0); 6799 } 6800