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