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