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