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