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