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