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