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