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