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