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