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