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