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