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 = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr); 135 ierr = DMSetDefaultSection(ncdm, cs);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 { 2962 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 2963 2964 /* 2965 Order of precedence: 2966 1) See if a specialized converter is known to the current DM. 2967 2) See if a specialized converter is known to the desired DM class. 2968 3) See if a good general converter is registered for the desired class 2969 4) See if a good general converter is known for the current matrix. 2970 5) Use a really basic converter. 2971 */ 2972 2973 /* 1) See if a specialized converter is known to the current DM and the desired class */ 2974 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2975 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2976 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2977 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2978 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2979 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 2980 if (conv) goto foundconv; 2981 2982 /* 2) See if a specialized converter is known to the desired DM class. */ 2983 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 2984 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 2985 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2986 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2987 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2988 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2989 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2990 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 2991 if (conv) { 2992 ierr = DMDestroy(&B);CHKERRQ(ierr); 2993 goto foundconv; 2994 } 2995 2996 #if 0 2997 /* 3) See if a good general converter is registered for the desired class */ 2998 conv = B->ops->convertfrom; 2999 ierr = DMDestroy(&B);CHKERRQ(ierr); 3000 if (conv) goto foundconv; 3001 3002 /* 4) See if a good general converter is known for the current matrix */ 3003 if (dm->ops->convert) { 3004 conv = dm->ops->convert; 3005 } 3006 if (conv) goto foundconv; 3007 #endif 3008 3009 /* 5) Use a really basic converter. */ 3010 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3011 3012 foundconv: 3013 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3014 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3015 /* Things that are independent of DM type: We should consult DMClone() here */ 3016 if (dm->maxCell) { 3017 const PetscReal *maxCell, *L; 3018 const DMBoundaryType *bd; 3019 ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr); 3020 ierr = DMSetPeriodicity(*M, maxCell, L, bd);CHKERRQ(ierr); 3021 } 3022 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3023 } 3024 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3025 PetscFunctionReturn(0); 3026 } 3027 3028 /*--------------------------------------------------------------------------------------------------------------------*/ 3029 3030 #undef __FUNCT__ 3031 #define __FUNCT__ "DMRegister" 3032 /*@C 3033 DMRegister - Adds a new DM component implementation 3034 3035 Not Collective 3036 3037 Input Parameters: 3038 + name - The name of a new user-defined creation routine 3039 - create_func - The creation routine itself 3040 3041 Notes: 3042 DMRegister() may be called multiple times to add several user-defined DMs 3043 3044 3045 Sample usage: 3046 .vb 3047 DMRegister("my_da", MyDMCreate); 3048 .ve 3049 3050 Then, your DM type can be chosen with the procedural interface via 3051 .vb 3052 DMCreate(MPI_Comm, DM *); 3053 DMSetType(DM,"my_da"); 3054 .ve 3055 or at runtime via the option 3056 .vb 3057 -da_type my_da 3058 .ve 3059 3060 Level: advanced 3061 3062 .keywords: DM, register 3063 .seealso: DMRegisterAll(), DMRegisterDestroy() 3064 3065 @*/ 3066 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3067 { 3068 PetscErrorCode ierr; 3069 3070 PetscFunctionBegin; 3071 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3072 PetscFunctionReturn(0); 3073 } 3074 3075 #undef __FUNCT__ 3076 #define __FUNCT__ "DMLoad" 3077 /*@C 3078 DMLoad - Loads a DM that has been stored in binary with DMView(). 3079 3080 Collective on PetscViewer 3081 3082 Input Parameters: 3083 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3084 some related function before a call to DMLoad(). 3085 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3086 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3087 3088 Level: intermediate 3089 3090 Notes: 3091 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3092 3093 Notes for advanced users: 3094 Most users should not need to know the details of the binary storage 3095 format, since DMLoad() and DMView() completely hide these details. 3096 But for anyone who's interested, the standard binary matrix storage 3097 format is 3098 .vb 3099 has not yet been determined 3100 .ve 3101 3102 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3103 @*/ 3104 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3105 { 3106 PetscBool isbinary, ishdf5; 3107 PetscErrorCode ierr; 3108 3109 PetscFunctionBegin; 3110 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3111 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3112 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3113 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3114 if (isbinary) { 3115 PetscInt classid; 3116 char type[256]; 3117 3118 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3119 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3120 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3121 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3122 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3123 } else if (ishdf5) { 3124 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3125 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3126 PetscFunctionReturn(0); 3127 } 3128 3129 /******************************** FEM Support **********************************/ 3130 3131 #undef __FUNCT__ 3132 #define __FUNCT__ "DMPrintCellVector" 3133 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3134 { 3135 PetscInt f; 3136 PetscErrorCode ierr; 3137 3138 PetscFunctionBegin; 3139 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3140 for (f = 0; f < len; ++f) { 3141 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3142 } 3143 PetscFunctionReturn(0); 3144 } 3145 3146 #undef __FUNCT__ 3147 #define __FUNCT__ "DMPrintCellMatrix" 3148 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3149 { 3150 PetscInt f, g; 3151 PetscErrorCode ierr; 3152 3153 PetscFunctionBegin; 3154 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3155 for (f = 0; f < rows; ++f) { 3156 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3157 for (g = 0; g < cols; ++g) { 3158 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3159 } 3160 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3161 } 3162 PetscFunctionReturn(0); 3163 } 3164 3165 #undef __FUNCT__ 3166 #define __FUNCT__ "DMPrintLocalVec" 3167 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3168 { 3169 PetscMPIInt rank, numProcs; 3170 PetscInt p; 3171 PetscErrorCode ierr; 3172 3173 PetscFunctionBegin; 3174 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 3175 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 3176 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr); 3177 for (p = 0; p < numProcs; ++p) { 3178 if (p == rank) { 3179 Vec x; 3180 3181 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3182 ierr = VecCopy(X, x);CHKERRQ(ierr); 3183 ierr = VecChop(x, tol);CHKERRQ(ierr); 3184 ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3185 ierr = VecDestroy(&x);CHKERRQ(ierr); 3186 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3187 } 3188 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 3189 } 3190 PetscFunctionReturn(0); 3191 } 3192 3193 #undef __FUNCT__ 3194 #define __FUNCT__ "DMGetDefaultSection" 3195 /*@ 3196 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3197 3198 Input Parameter: 3199 . dm - The DM 3200 3201 Output Parameter: 3202 . section - The PetscSection 3203 3204 Level: intermediate 3205 3206 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3207 3208 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3209 @*/ 3210 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3211 { 3212 PetscErrorCode ierr; 3213 3214 PetscFunctionBegin; 3215 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3216 PetscValidPointer(section, 2); 3217 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3218 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3219 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3220 } 3221 *section = dm->defaultSection; 3222 PetscFunctionReturn(0); 3223 } 3224 3225 #undef __FUNCT__ 3226 #define __FUNCT__ "DMSetDefaultSection" 3227 /*@ 3228 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3229 3230 Input Parameters: 3231 + dm - The DM 3232 - section - The PetscSection 3233 3234 Level: intermediate 3235 3236 Note: Any existing Section will be destroyed 3237 3238 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3239 @*/ 3240 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3241 { 3242 PetscInt numFields = 0; 3243 PetscInt f; 3244 PetscErrorCode ierr; 3245 3246 PetscFunctionBegin; 3247 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3248 if (section) { 3249 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3250 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3251 } 3252 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3253 dm->defaultSection = section; 3254 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3255 if (numFields) { 3256 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3257 for (f = 0; f < numFields; ++f) { 3258 PetscObject disc; 3259 const char *name; 3260 3261 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3262 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3263 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3264 } 3265 } 3266 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3267 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3268 PetscFunctionReturn(0); 3269 } 3270 3271 #undef __FUNCT__ 3272 #define __FUNCT__ "DMGetDefaultConstraints" 3273 /*@ 3274 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3275 3276 not collective 3277 3278 Input Parameter: 3279 . dm - The DM 3280 3281 Output Parameter: 3282 + 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. 3283 - 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. 3284 3285 Level: advanced 3286 3287 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3288 3289 .seealso: DMSetDefaultConstraints() 3290 @*/ 3291 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3292 { 3293 PetscErrorCode ierr; 3294 3295 PetscFunctionBegin; 3296 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3297 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3298 if (section) {*section = dm->defaultConstraintSection;} 3299 if (mat) {*mat = dm->defaultConstraintMat;} 3300 PetscFunctionReturn(0); 3301 } 3302 3303 #undef __FUNCT__ 3304 #define __FUNCT__ "DMSetDefaultConstraints" 3305 /*@ 3306 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3307 3308 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(). 3309 3310 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. 3311 3312 collective on dm 3313 3314 Input Parameters: 3315 + dm - The DM 3316 + 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). 3317 - 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). 3318 3319 Level: advanced 3320 3321 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3322 3323 .seealso: DMGetDefaultConstraints() 3324 @*/ 3325 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3326 { 3327 PetscMPIInt result; 3328 PetscErrorCode ierr; 3329 3330 PetscFunctionBegin; 3331 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3332 if (section) { 3333 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3334 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3335 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3336 } 3337 if (mat) { 3338 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3339 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3340 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3341 } 3342 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3343 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3344 dm->defaultConstraintSection = section; 3345 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3346 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3347 dm->defaultConstraintMat = mat; 3348 PetscFunctionReturn(0); 3349 } 3350 3351 #ifdef PETSC_USE_DEBUG 3352 #undef __FUNCT__ 3353 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal" 3354 /* 3355 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3356 3357 Input Parameters: 3358 + dm - The DM 3359 . localSection - PetscSection describing the local data layout 3360 - globalSection - PetscSection describing the global data layout 3361 3362 Level: intermediate 3363 3364 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3365 */ 3366 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3367 { 3368 MPI_Comm comm; 3369 PetscLayout layout; 3370 const PetscInt *ranges; 3371 PetscInt pStart, pEnd, p, nroots; 3372 PetscMPIInt size, rank; 3373 PetscBool valid = PETSC_TRUE, gvalid; 3374 PetscErrorCode ierr; 3375 3376 PetscFunctionBegin; 3377 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3378 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3379 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3380 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3381 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3382 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3383 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3384 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3385 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3386 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3387 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3388 for (p = pStart; p < pEnd; ++p) { 3389 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3390 3391 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3392 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3393 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3394 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3395 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3396 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3397 if (!gdof) continue; /* Censored point */ 3398 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;} 3399 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;} 3400 if (gdof < 0) { 3401 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3402 for (d = 0; d < gsize; ++d) { 3403 PetscInt offset = -(goff+1) + d, r; 3404 3405 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3406 if (r < 0) r = -(r+2); 3407 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;} 3408 } 3409 } 3410 } 3411 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3412 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3413 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3414 if (!gvalid) { 3415 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3416 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3417 } 3418 PetscFunctionReturn(0); 3419 } 3420 #endif 3421 3422 #undef __FUNCT__ 3423 #define __FUNCT__ "DMGetDefaultGlobalSection" 3424 /*@ 3425 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3426 3427 Collective on DM 3428 3429 Input Parameter: 3430 . dm - The DM 3431 3432 Output Parameter: 3433 . section - The PetscSection 3434 3435 Level: intermediate 3436 3437 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3438 3439 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3440 @*/ 3441 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3442 { 3443 PetscErrorCode ierr; 3444 3445 PetscFunctionBegin; 3446 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3447 PetscValidPointer(section, 2); 3448 if (!dm->defaultGlobalSection) { 3449 PetscSection s; 3450 3451 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3452 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3453 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3454 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3455 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3456 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3457 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3458 } 3459 *section = dm->defaultGlobalSection; 3460 PetscFunctionReturn(0); 3461 } 3462 3463 #undef __FUNCT__ 3464 #define __FUNCT__ "DMSetDefaultGlobalSection" 3465 /*@ 3466 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3467 3468 Input Parameters: 3469 + dm - The DM 3470 - section - The PetscSection, or NULL 3471 3472 Level: intermediate 3473 3474 Note: Any existing Section will be destroyed 3475 3476 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3477 @*/ 3478 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3479 { 3480 PetscErrorCode ierr; 3481 3482 PetscFunctionBegin; 3483 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3484 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3485 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3486 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3487 dm->defaultGlobalSection = section; 3488 #ifdef PETSC_USE_DEBUG 3489 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3490 #endif 3491 PetscFunctionReturn(0); 3492 } 3493 3494 #undef __FUNCT__ 3495 #define __FUNCT__ "DMGetDefaultSF" 3496 /*@ 3497 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3498 it is created from the default PetscSection layouts in the DM. 3499 3500 Input Parameter: 3501 . dm - The DM 3502 3503 Output Parameter: 3504 . sf - The PetscSF 3505 3506 Level: intermediate 3507 3508 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3509 3510 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3511 @*/ 3512 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3513 { 3514 PetscInt nroots; 3515 PetscErrorCode ierr; 3516 3517 PetscFunctionBegin; 3518 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3519 PetscValidPointer(sf, 2); 3520 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3521 if (nroots < 0) { 3522 PetscSection section, gSection; 3523 3524 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3525 if (section) { 3526 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3527 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3528 } else { 3529 *sf = NULL; 3530 PetscFunctionReturn(0); 3531 } 3532 } 3533 *sf = dm->defaultSF; 3534 PetscFunctionReturn(0); 3535 } 3536 3537 #undef __FUNCT__ 3538 #define __FUNCT__ "DMSetDefaultSF" 3539 /*@ 3540 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3541 3542 Input Parameters: 3543 + dm - The DM 3544 - sf - The PetscSF 3545 3546 Level: intermediate 3547 3548 Note: Any previous SF is destroyed 3549 3550 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3551 @*/ 3552 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3553 { 3554 PetscErrorCode ierr; 3555 3556 PetscFunctionBegin; 3557 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3558 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3559 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3560 dm->defaultSF = sf; 3561 PetscFunctionReturn(0); 3562 } 3563 3564 #undef __FUNCT__ 3565 #define __FUNCT__ "DMCreateDefaultSF" 3566 /*@C 3567 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3568 describing the data layout. 3569 3570 Input Parameters: 3571 + dm - The DM 3572 . localSection - PetscSection describing the local data layout 3573 - globalSection - PetscSection describing the global data layout 3574 3575 Level: intermediate 3576 3577 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3578 @*/ 3579 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3580 { 3581 MPI_Comm comm; 3582 PetscLayout layout; 3583 const PetscInt *ranges; 3584 PetscInt *local; 3585 PetscSFNode *remote; 3586 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3587 PetscMPIInt size, rank; 3588 PetscErrorCode ierr; 3589 3590 PetscFunctionBegin; 3591 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3592 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3593 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3594 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3595 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3596 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3597 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3598 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3599 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3600 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3601 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3602 for (p = pStart; p < pEnd; ++p) { 3603 PetscInt gdof, gcdof; 3604 3605 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3606 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3607 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)); 3608 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3609 } 3610 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3611 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3612 for (p = pStart, l = 0; p < pEnd; ++p) { 3613 const PetscInt *cind; 3614 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3615 3616 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3617 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3618 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3619 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3620 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3621 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3622 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3623 if (!gdof) continue; /* Censored point */ 3624 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3625 if (gsize != dof-cdof) { 3626 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); 3627 cdof = 0; /* Ignore constraints */ 3628 } 3629 for (d = 0, c = 0; d < dof; ++d) { 3630 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3631 local[l+d-c] = off+d; 3632 } 3633 if (gdof < 0) { 3634 for (d = 0; d < gsize; ++d, ++l) { 3635 PetscInt offset = -(goff+1) + d, r; 3636 3637 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3638 if (r < 0) r = -(r+2); 3639 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); 3640 remote[l].rank = r; 3641 remote[l].index = offset - ranges[r]; 3642 } 3643 } else { 3644 for (d = 0; d < gsize; ++d, ++l) { 3645 remote[l].rank = rank; 3646 remote[l].index = goff+d - ranges[rank]; 3647 } 3648 } 3649 } 3650 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3651 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3652 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3653 PetscFunctionReturn(0); 3654 } 3655 3656 #undef __FUNCT__ 3657 #define __FUNCT__ "DMGetPointSF" 3658 /*@ 3659 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3660 3661 Input Parameter: 3662 . dm - The DM 3663 3664 Output Parameter: 3665 . sf - The PetscSF 3666 3667 Level: intermediate 3668 3669 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3670 3671 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3672 @*/ 3673 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3674 { 3675 PetscFunctionBegin; 3676 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3677 PetscValidPointer(sf, 2); 3678 *sf = dm->sf; 3679 PetscFunctionReturn(0); 3680 } 3681 3682 #undef __FUNCT__ 3683 #define __FUNCT__ "DMSetPointSF" 3684 /*@ 3685 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3686 3687 Input Parameters: 3688 + dm - The DM 3689 - sf - The PetscSF 3690 3691 Level: intermediate 3692 3693 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3694 @*/ 3695 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3696 { 3697 PetscErrorCode ierr; 3698 3699 PetscFunctionBegin; 3700 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3701 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3702 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3703 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3704 dm->sf = sf; 3705 PetscFunctionReturn(0); 3706 } 3707 3708 #undef __FUNCT__ 3709 #define __FUNCT__ "DMGetDS" 3710 /*@ 3711 DMGetDS - Get the PetscDS 3712 3713 Input Parameter: 3714 . dm - The DM 3715 3716 Output Parameter: 3717 . prob - The PetscDS 3718 3719 Level: developer 3720 3721 .seealso: DMSetDS() 3722 @*/ 3723 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3724 { 3725 PetscFunctionBegin; 3726 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3727 PetscValidPointer(prob, 2); 3728 *prob = dm->prob; 3729 PetscFunctionReturn(0); 3730 } 3731 3732 #undef __FUNCT__ 3733 #define __FUNCT__ "DMSetDS" 3734 /*@ 3735 DMSetDS - Set the PetscDS 3736 3737 Input Parameters: 3738 + dm - The DM 3739 - prob - The PetscDS 3740 3741 Level: developer 3742 3743 .seealso: DMGetDS() 3744 @*/ 3745 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3746 { 3747 PetscErrorCode ierr; 3748 3749 PetscFunctionBegin; 3750 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3751 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3752 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3753 dm->prob = prob; 3754 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3755 PetscFunctionReturn(0); 3756 } 3757 3758 #undef __FUNCT__ 3759 #define __FUNCT__ "DMGetNumFields" 3760 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3761 { 3762 PetscErrorCode ierr; 3763 3764 PetscFunctionBegin; 3765 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3766 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3767 PetscFunctionReturn(0); 3768 } 3769 3770 #undef __FUNCT__ 3771 #define __FUNCT__ "DMSetNumFields" 3772 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3773 { 3774 PetscInt Nf, f; 3775 PetscErrorCode ierr; 3776 3777 PetscFunctionBegin; 3778 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3779 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3780 for (f = Nf; f < numFields; ++f) { 3781 PetscContainer obj; 3782 3783 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3784 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3785 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3786 } 3787 PetscFunctionReturn(0); 3788 } 3789 3790 #undef __FUNCT__ 3791 #define __FUNCT__ "DMGetField" 3792 /*@ 3793 DMGetField - Return the discretization object for a given DM field 3794 3795 Not collective 3796 3797 Input Parameters: 3798 + dm - The DM 3799 - f - The field number 3800 3801 Output Parameter: 3802 . field - The discretization object 3803 3804 Level: developer 3805 3806 .seealso: DMSetField() 3807 @*/ 3808 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3809 { 3810 PetscErrorCode ierr; 3811 3812 PetscFunctionBegin; 3813 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3814 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3815 PetscFunctionReturn(0); 3816 } 3817 3818 #undef __FUNCT__ 3819 #define __FUNCT__ "DMSetField" 3820 /*@ 3821 DMSetField - Set the discretization object for a given DM field 3822 3823 Logically collective on DM 3824 3825 Input Parameters: 3826 + dm - The DM 3827 . f - The field number 3828 - field - The discretization object 3829 3830 Level: developer 3831 3832 .seealso: DMGetField() 3833 @*/ 3834 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3835 { 3836 PetscErrorCode ierr; 3837 3838 PetscFunctionBegin; 3839 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3840 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3841 PetscFunctionReturn(0); 3842 } 3843 3844 #undef __FUNCT__ 3845 #define __FUNCT__ "DMRestrictHook_Coordinates" 3846 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3847 { 3848 DM dm_coord,dmc_coord; 3849 PetscErrorCode ierr; 3850 Vec coords,ccoords; 3851 Mat inject; 3852 PetscFunctionBegin; 3853 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3854 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3855 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3856 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3857 if (coords && !ccoords) { 3858 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3859 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3860 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3861 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3862 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3863 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3864 } 3865 PetscFunctionReturn(0); 3866 } 3867 3868 #undef __FUNCT__ 3869 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3870 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3871 { 3872 DM dm_coord,subdm_coord; 3873 PetscErrorCode ierr; 3874 Vec coords,ccoords,clcoords; 3875 VecScatter *scat_i,*scat_g; 3876 PetscFunctionBegin; 3877 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3878 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3879 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3880 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3881 if (coords && !ccoords) { 3882 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3883 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3884 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 3885 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3886 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3887 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3888 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3889 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3890 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3891 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3892 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3893 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3894 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3895 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3896 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3897 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3898 } 3899 PetscFunctionReturn(0); 3900 } 3901 3902 #undef __FUNCT__ 3903 #define __FUNCT__ "DMGetDimension" 3904 /*@ 3905 DMGetDimension - Return the topological dimension of the DM 3906 3907 Not collective 3908 3909 Input Parameter: 3910 . dm - The DM 3911 3912 Output Parameter: 3913 . dim - The topological dimension 3914 3915 Level: beginner 3916 3917 .seealso: DMSetDimension(), DMCreate() 3918 @*/ 3919 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 3920 { 3921 PetscFunctionBegin; 3922 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3923 PetscValidPointer(dim, 2); 3924 *dim = dm->dim; 3925 PetscFunctionReturn(0); 3926 } 3927 3928 #undef __FUNCT__ 3929 #define __FUNCT__ "DMSetDimension" 3930 /*@ 3931 DMSetDimension - Set the topological dimension of the DM 3932 3933 Collective on dm 3934 3935 Input Parameters: 3936 + dm - The DM 3937 - dim - The topological dimension 3938 3939 Level: beginner 3940 3941 .seealso: DMGetDimension(), DMCreate() 3942 @*/ 3943 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 3944 { 3945 PetscFunctionBegin; 3946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3947 PetscValidLogicalCollectiveInt(dm, dim, 2); 3948 dm->dim = dim; 3949 PetscFunctionReturn(0); 3950 } 3951 3952 #undef __FUNCT__ 3953 #define __FUNCT__ "DMGetDimPoints" 3954 /*@ 3955 DMGetDimPoints - Get the half-open interval for all points of a given dimension 3956 3957 Collective on DM 3958 3959 Input Parameters: 3960 + dm - the DM 3961 - dim - the dimension 3962 3963 Output Parameters: 3964 + pStart - The first point of the given dimension 3965 . pEnd - The first point following points of the given dimension 3966 3967 Note: 3968 The points are vertices in the Hasse diagram encoding the topology. This is explained in 3969 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 3970 then the interval is empty. 3971 3972 Level: intermediate 3973 3974 .keywords: point, Hasse Diagram, dimension 3975 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 3976 @*/ 3977 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3978 { 3979 PetscInt d; 3980 PetscErrorCode ierr; 3981 3982 PetscFunctionBegin; 3983 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3984 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3985 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 3986 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3987 PetscFunctionReturn(0); 3988 } 3989 3990 #undef __FUNCT__ 3991 #define __FUNCT__ "DMSetCoordinates" 3992 /*@ 3993 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3994 3995 Collective on DM 3996 3997 Input Parameters: 3998 + dm - the DM 3999 - c - coordinate vector 4000 4001 Note: 4002 The coordinates do include those for ghost points, which are in the local vector 4003 4004 Level: intermediate 4005 4006 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4007 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 4008 @*/ 4009 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4010 { 4011 PetscErrorCode ierr; 4012 4013 PetscFunctionBegin; 4014 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4015 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4016 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4017 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4018 dm->coordinates = c; 4019 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4020 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4021 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4022 PetscFunctionReturn(0); 4023 } 4024 4025 #undef __FUNCT__ 4026 #define __FUNCT__ "DMSetCoordinatesLocal" 4027 /*@ 4028 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4029 4030 Collective on DM 4031 4032 Input Parameters: 4033 + dm - the DM 4034 - c - coordinate vector 4035 4036 Note: 4037 The coordinates of ghost points can be set using DMSetCoordinates() 4038 followed by DMGetCoordinatesLocal(). This is intended to enable the 4039 setting of ghost coordinates outside of the domain. 4040 4041 Level: intermediate 4042 4043 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4044 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4045 @*/ 4046 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4047 { 4048 PetscErrorCode ierr; 4049 4050 PetscFunctionBegin; 4051 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4052 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4053 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4054 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4055 4056 dm->coordinatesLocal = c; 4057 4058 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4059 PetscFunctionReturn(0); 4060 } 4061 4062 #undef __FUNCT__ 4063 #define __FUNCT__ "DMGetCoordinates" 4064 /*@ 4065 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4066 4067 Not Collective 4068 4069 Input Parameter: 4070 . dm - the DM 4071 4072 Output Parameter: 4073 . c - global coordinate vector 4074 4075 Note: 4076 This is a borrowed reference, so the user should NOT destroy this vector 4077 4078 Each process has only the local coordinates (does NOT have the ghost coordinates). 4079 4080 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4081 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4082 4083 Level: intermediate 4084 4085 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4086 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4087 @*/ 4088 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4089 { 4090 PetscErrorCode ierr; 4091 4092 PetscFunctionBegin; 4093 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4094 PetscValidPointer(c,2); 4095 if (!dm->coordinates && dm->coordinatesLocal) { 4096 DM cdm = NULL; 4097 4098 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4099 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4100 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4101 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4102 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4103 } 4104 *c = dm->coordinates; 4105 PetscFunctionReturn(0); 4106 } 4107 4108 #undef __FUNCT__ 4109 #define __FUNCT__ "DMGetCoordinatesLocal" 4110 /*@ 4111 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4112 4113 Collective on DM 4114 4115 Input Parameter: 4116 . dm - the DM 4117 4118 Output Parameter: 4119 . c - coordinate vector 4120 4121 Note: 4122 This is a borrowed reference, so the user should NOT destroy this vector 4123 4124 Each process has the local and ghost coordinates 4125 4126 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4127 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4128 4129 Level: intermediate 4130 4131 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4132 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4133 @*/ 4134 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4135 { 4136 PetscErrorCode ierr; 4137 4138 PetscFunctionBegin; 4139 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4140 PetscValidPointer(c,2); 4141 if (!dm->coordinatesLocal && dm->coordinates) { 4142 DM cdm = NULL; 4143 4144 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4145 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4146 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4147 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4148 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4149 } 4150 *c = dm->coordinatesLocal; 4151 PetscFunctionReturn(0); 4152 } 4153 4154 #undef __FUNCT__ 4155 #define __FUNCT__ "DMGetCoordinateDM" 4156 /*@ 4157 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4158 4159 Collective on DM 4160 4161 Input Parameter: 4162 . dm - the DM 4163 4164 Output Parameter: 4165 . cdm - coordinate DM 4166 4167 Level: intermediate 4168 4169 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4170 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4171 @*/ 4172 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4173 { 4174 PetscErrorCode ierr; 4175 4176 PetscFunctionBegin; 4177 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4178 PetscValidPointer(cdm,2); 4179 if (!dm->coordinateDM) { 4180 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4181 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4182 } 4183 *cdm = dm->coordinateDM; 4184 PetscFunctionReturn(0); 4185 } 4186 4187 #undef __FUNCT__ 4188 #define __FUNCT__ "DMSetCoordinateDM" 4189 /*@ 4190 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4191 4192 Logically Collective on DM 4193 4194 Input Parameters: 4195 + dm - the DM 4196 - cdm - coordinate DM 4197 4198 Level: intermediate 4199 4200 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4201 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4202 @*/ 4203 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4204 { 4205 PetscErrorCode ierr; 4206 4207 PetscFunctionBegin; 4208 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4209 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4210 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4211 dm->coordinateDM = cdm; 4212 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 4213 PetscFunctionReturn(0); 4214 } 4215 4216 #undef __FUNCT__ 4217 #define __FUNCT__ "DMGetCoordinateDim" 4218 /*@ 4219 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4220 4221 Not Collective 4222 4223 Input Parameter: 4224 . dm - The DM object 4225 4226 Output Parameter: 4227 . dim - The embedding dimension 4228 4229 Level: intermediate 4230 4231 .keywords: mesh, coordinates 4232 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4233 @*/ 4234 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4235 { 4236 PetscFunctionBegin; 4237 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4238 PetscValidPointer(dim, 2); 4239 if (dm->dimEmbed == PETSC_DEFAULT) { 4240 dm->dimEmbed = dm->dim; 4241 } 4242 *dim = dm->dimEmbed; 4243 PetscFunctionReturn(0); 4244 } 4245 4246 #undef __FUNCT__ 4247 #define __FUNCT__ "DMSetCoordinateDim" 4248 /*@ 4249 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4250 4251 Not Collective 4252 4253 Input Parameters: 4254 + dm - The DM object 4255 - dim - The embedding dimension 4256 4257 Level: intermediate 4258 4259 .keywords: mesh, coordinates 4260 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4261 @*/ 4262 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4263 { 4264 PetscFunctionBegin; 4265 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4266 dm->dimEmbed = dim; 4267 PetscFunctionReturn(0); 4268 } 4269 4270 #undef __FUNCT__ 4271 #define __FUNCT__ "DMGetCoordinateSection" 4272 /*@ 4273 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4274 4275 Not Collective 4276 4277 Input Parameter: 4278 . dm - The DM object 4279 4280 Output Parameter: 4281 . section - The PetscSection object 4282 4283 Level: intermediate 4284 4285 .keywords: mesh, coordinates 4286 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4287 @*/ 4288 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4289 { 4290 DM cdm; 4291 PetscErrorCode ierr; 4292 4293 PetscFunctionBegin; 4294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4295 PetscValidPointer(section, 2); 4296 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4297 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4298 PetscFunctionReturn(0); 4299 } 4300 4301 #undef __FUNCT__ 4302 #define __FUNCT__ "DMSetCoordinateSection" 4303 /*@ 4304 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4305 4306 Not Collective 4307 4308 Input Parameters: 4309 + dm - The DM object 4310 . dim - The embedding dimension, or PETSC_DETERMINE 4311 - section - The PetscSection object 4312 4313 Level: intermediate 4314 4315 .keywords: mesh, coordinates 4316 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4317 @*/ 4318 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4319 { 4320 DM cdm; 4321 PetscErrorCode ierr; 4322 4323 PetscFunctionBegin; 4324 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4325 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4326 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4327 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4328 if (dim == PETSC_DETERMINE) { 4329 PetscInt d = dim; 4330 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4331 4332 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4333 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4334 pStart = PetscMax(vStart, pStart); 4335 pEnd = PetscMin(vEnd, pEnd); 4336 for (v = pStart; v < pEnd; ++v) { 4337 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4338 if (dd) {d = dd; break;} 4339 } 4340 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4341 } 4342 PetscFunctionReturn(0); 4343 } 4344 4345 #undef __FUNCT__ 4346 #define __FUNCT__ "DMGetPeriodicity" 4347 /*@C 4348 DMSetPeriodicity - Set the description of mesh periodicity 4349 4350 Input Parameters: 4351 + dm - The DM object 4352 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4353 . L - If we assume the mesh is a torus, this is the length of each coordinate 4354 - bd - This describes the type of periodicity in each topological dimension 4355 4356 Level: developer 4357 4358 .seealso: DMGetPeriodicity() 4359 @*/ 4360 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4361 { 4362 PetscFunctionBegin; 4363 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4364 if (L) *L = dm->L; 4365 if (maxCell) *maxCell = dm->maxCell; 4366 if (bd) *bd = dm->bdtype; 4367 PetscFunctionReturn(0); 4368 } 4369 4370 #undef __FUNCT__ 4371 #define __FUNCT__ "DMSetPeriodicity" 4372 /*@C 4373 DMSetPeriodicity - Set the description of mesh periodicity 4374 4375 Input Parameters: 4376 + dm - The DM object 4377 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4378 . L - If we assume the mesh is a torus, this is the length of each coordinate 4379 - bd - This describes the type of periodicity in each topological dimension 4380 4381 Level: developer 4382 4383 .seealso: DMGetPeriodicity() 4384 @*/ 4385 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4386 { 4387 PetscInt dim, d; 4388 PetscErrorCode ierr; 4389 4390 PetscFunctionBegin; 4391 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4392 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4393 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4394 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4395 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4396 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4397 PetscFunctionReturn(0); 4398 } 4399 4400 #undef __FUNCT__ 4401 #define __FUNCT__ "DMLocalizeCoordinate" 4402 /*@ 4403 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. 4404 4405 Input Parameters: 4406 + dm - The DM 4407 - in - The input coordinate point (dim numbers) 4408 4409 Output Parameter: 4410 . out - The localized coordinate point 4411 4412 Level: developer 4413 4414 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4415 @*/ 4416 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscScalar out[]) 4417 { 4418 PetscInt dim, d; 4419 PetscErrorCode ierr; 4420 4421 PetscFunctionBegin; 4422 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4423 if (!dm->maxCell) { 4424 for (d = 0; d < dim; ++d) out[d] = in[d]; 4425 } else { 4426 for (d = 0; d < dim; ++d) { 4427 out[d] = in[d] - dm->L[d]*floor(PetscRealPart(in[d])/dm->L[d]); 4428 } 4429 } 4430 PetscFunctionReturn(0); 4431 } 4432 4433 #undef __FUNCT__ 4434 #define __FUNCT__ "DMLocalizeCoordinate_Internal" 4435 /* 4436 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. 4437 4438 Input Parameters: 4439 + dm - The DM 4440 . dim - The spatial dimension 4441 . anchor - The anchor point, the input point can be no more than maxCell away from it 4442 - in - The input coordinate point (dim numbers) 4443 4444 Output Parameter: 4445 . out - The localized coordinate point 4446 4447 Level: developer 4448 4449 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 4450 4451 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4452 */ 4453 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4454 { 4455 PetscInt d; 4456 4457 PetscFunctionBegin; 4458 if (!dm->maxCell) { 4459 for (d = 0; d < dim; ++d) out[d] = in[d]; 4460 } else { 4461 for (d = 0; d < dim; ++d) { 4462 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 4463 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4464 } else { 4465 out[d] = in[d]; 4466 } 4467 } 4468 } 4469 PetscFunctionReturn(0); 4470 } 4471 #undef __FUNCT__ 4472 #define __FUNCT__ "DMLocalizeCoordinateReal_Internal" 4473 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 4474 { 4475 PetscInt d; 4476 4477 PetscFunctionBegin; 4478 if (!dm->maxCell) { 4479 for (d = 0; d < dim; ++d) out[d] = in[d]; 4480 } else { 4481 for (d = 0; d < dim; ++d) { 4482 if (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d]) { 4483 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4484 } else { 4485 out[d] = in[d]; 4486 } 4487 } 4488 } 4489 PetscFunctionReturn(0); 4490 } 4491 4492 #undef __FUNCT__ 4493 #define __FUNCT__ "DMLocalizeAddCoordinate_Internal" 4494 /* 4495 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. 4496 4497 Input Parameters: 4498 + dm - The DM 4499 . dim - The spatial dimension 4500 . anchor - The anchor point, the input point can be no more than maxCell away from it 4501 . in - The input coordinate delta (dim numbers) 4502 - out - The input coordinate point (dim numbers) 4503 4504 Output Parameter: 4505 . out - The localized coordinate in + out 4506 4507 Level: developer 4508 4509 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 4510 4511 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 4512 */ 4513 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4514 { 4515 PetscInt d; 4516 4517 PetscFunctionBegin; 4518 if (!dm->maxCell) { 4519 for (d = 0; d < dim; ++d) out[d] += in[d]; 4520 } else { 4521 for (d = 0; d < dim; ++d) { 4522 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 4523 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4524 } else { 4525 out[d] += in[d]; 4526 } 4527 } 4528 } 4529 PetscFunctionReturn(0); 4530 } 4531 4532 PETSC_EXTERN PetscErrorCode DMPlexGetDepthStratum(DM, PetscInt, PetscInt *, PetscInt *); 4533 PETSC_EXTERN PetscErrorCode DMPlexGetHeightStratum(DM, PetscInt, PetscInt *, PetscInt *); 4534 PETSC_EXTERN PetscErrorCode DMPlexVecGetClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]); 4535 PETSC_EXTERN PetscErrorCode DMPlexVecRestoreClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]); 4536 4537 #undef __FUNCT__ 4538 #define __FUNCT__ "DMGetCoordinatesLocalized" 4539 /*@ 4540 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 4541 4542 Input Parameter: 4543 . dm - The DM 4544 4545 Output Parameter: 4546 areLocalized - True if localized 4547 4548 Level: developer 4549 4550 .seealso: DMLocalizeCoordinates() 4551 @*/ 4552 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 4553 { 4554 DM cdm; 4555 PetscSection coordSection; 4556 PetscInt cStart, cEnd, c, sStart, sEnd, dof; 4557 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4558 PetscErrorCode ierr; 4559 4560 PetscFunctionBegin; 4561 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4562 if (!dm->maxCell) PetscFunctionReturn(0); 4563 /* We need some generic way of refering to cells/vertices */ 4564 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4565 { 4566 PetscBool isplex; 4567 4568 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4569 if (isplex) { 4570 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4571 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4572 } 4573 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4574 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4575 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4576 for (c = cStart; c < cEnd; ++c) { 4577 if (c < sStart || c >= sEnd) { 4578 alreadyLocalized = PETSC_FALSE; 4579 break; 4580 } 4581 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4582 if (!dof) { 4583 alreadyLocalized = PETSC_FALSE; 4584 break; 4585 } 4586 } 4587 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4588 *areLocalized = alreadyLocalizedGlobal; 4589 PetscFunctionReturn(0); 4590 } 4591 4592 4593 #undef __FUNCT__ 4594 #define __FUNCT__ "DMLocalizeCoordinates" 4595 /*@ 4596 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for each cell 4597 4598 Input Parameter: 4599 . dm - The DM 4600 4601 Level: developer 4602 4603 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 4604 @*/ 4605 PetscErrorCode DMLocalizeCoordinates(DM dm) 4606 { 4607 DM cdm; 4608 PetscSection coordSection, cSection; 4609 Vec coordinates, cVec; 4610 PetscScalar *coords, *coords2, *anchor; 4611 PetscInt Nc, cStart, cEnd, c, vStart, vEnd, v, sStart, sEnd, dof, d, off, off2, bs, coordSize; 4612 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4613 PetscErrorCode ierr; 4614 4615 PetscFunctionBegin; 4616 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4617 if (!dm->maxCell) PetscFunctionReturn(0); 4618 /* We need some generic way of refering to cells/vertices */ 4619 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4620 { 4621 PetscBool isplex; 4622 4623 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4624 if (isplex) { 4625 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4626 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4627 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4628 } 4629 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4630 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4631 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4632 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4633 for (c = cStart; c < cEnd; ++c) { 4634 if (c < sStart || c >= sEnd) { 4635 alreadyLocalized = PETSC_FALSE; 4636 break; 4637 } 4638 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4639 if (!dof) { 4640 alreadyLocalized = PETSC_FALSE; 4641 break; 4642 } 4643 } 4644 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4645 if (alreadyLocalizedGlobal) PetscFunctionReturn(0); 4646 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 4647 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 4648 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 4649 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 4650 ierr = PetscSectionSetChart(cSection, cStart, vEnd);CHKERRQ(ierr); 4651 for (v = vStart; v < vEnd; ++v) { 4652 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4653 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 4654 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 4655 } 4656 for (c = cStart; c < cEnd; ++c) { 4657 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, NULL);CHKERRQ(ierr); 4658 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 4659 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 4660 } 4661 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 4662 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 4663 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cVec);CHKERRQ(ierr); 4664 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4665 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 4666 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 4667 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4668 ierr = VecSetType(cVec,VECSTANDARD);CHKERRQ(ierr); 4669 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4670 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 4671 for (v = vStart; v < vEnd; ++v) { 4672 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4673 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4674 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 4675 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 4676 } 4677 ierr = DMGetWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4678 for (c = cStart; c < cEnd; ++c) { 4679 PetscScalar *cellCoords = NULL; 4680 PetscInt b; 4681 4682 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4683 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 4684 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4685 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 4686 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4687 } 4688 ierr = DMRestoreWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4689 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4690 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 4691 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 4692 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 4693 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 4694 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4695 PetscFunctionReturn(0); 4696 } 4697 4698 #undef __FUNCT__ 4699 #define __FUNCT__ "DMLocatePoints" 4700 /*@ 4701 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 4702 4703 Not collective 4704 4705 Input Parameters: 4706 + dm - The DM 4707 - v - The Vec of points 4708 4709 Output Parameter: 4710 . cells - The local cell numbers for cells which contain the points 4711 4712 Level: developer 4713 4714 .keywords: point location, mesh 4715 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4716 @*/ 4717 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 4718 { 4719 PetscErrorCode ierr; 4720 4721 PetscFunctionBegin; 4722 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4723 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4724 PetscValidPointer(cells,3); 4725 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4726 if (dm->ops->locatepoints) { 4727 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 4728 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4729 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4730 PetscFunctionReturn(0); 4731 } 4732 4733 #undef __FUNCT__ 4734 #define __FUNCT__ "DMGetOutputDM" 4735 /*@ 4736 DMGetOutputDM - Retrieve the DM associated with the layout for output 4737 4738 Input Parameter: 4739 . dm - The original DM 4740 4741 Output Parameter: 4742 . odm - The DM which provides the layout for output 4743 4744 Level: intermediate 4745 4746 .seealso: VecView(), DMGetDefaultGlobalSection() 4747 @*/ 4748 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4749 { 4750 PetscSection section; 4751 PetscBool hasConstraints; 4752 PetscErrorCode ierr; 4753 4754 PetscFunctionBegin; 4755 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4756 PetscValidPointer(odm,2); 4757 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4758 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4759 if (!hasConstraints) { 4760 *odm = dm; 4761 PetscFunctionReturn(0); 4762 } 4763 if (!dm->dmBC) { 4764 PetscSection newSection, gsection; 4765 PetscSF sf; 4766 4767 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4768 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4769 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4770 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4771 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4772 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4773 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4774 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4775 } 4776 *odm = dm->dmBC; 4777 PetscFunctionReturn(0); 4778 } 4779 4780 #undef __FUNCT__ 4781 #define __FUNCT__ "DMGetOutputSequenceNumber" 4782 /*@ 4783 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4784 4785 Input Parameter: 4786 . dm - The original DM 4787 4788 Output Parameters: 4789 + num - The output sequence number 4790 - val - The output sequence value 4791 4792 Level: intermediate 4793 4794 Note: This is intended for output that should appear in sequence, for instance 4795 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4796 4797 .seealso: VecView() 4798 @*/ 4799 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4800 { 4801 PetscFunctionBegin; 4802 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4803 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4804 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4805 PetscFunctionReturn(0); 4806 } 4807 4808 #undef __FUNCT__ 4809 #define __FUNCT__ "DMSetOutputSequenceNumber" 4810 /*@ 4811 DMSetOutputSequenceNumber - Set the sequence number/value for output 4812 4813 Input Parameters: 4814 + dm - The original DM 4815 . num - The output sequence number 4816 - val - The output sequence value 4817 4818 Level: intermediate 4819 4820 Note: This is intended for output that should appear in sequence, for instance 4821 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4822 4823 .seealso: VecView() 4824 @*/ 4825 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4826 { 4827 PetscFunctionBegin; 4828 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4829 dm->outputSequenceNum = num; 4830 dm->outputSequenceVal = val; 4831 PetscFunctionReturn(0); 4832 } 4833 4834 #undef __FUNCT__ 4835 #define __FUNCT__ "DMOutputSequenceLoad" 4836 /*@C 4837 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4838 4839 Input Parameters: 4840 + dm - The original DM 4841 . name - The sequence name 4842 - num - The output sequence number 4843 4844 Output Parameter: 4845 . val - The output sequence value 4846 4847 Level: intermediate 4848 4849 Note: This is intended for output that should appear in sequence, for instance 4850 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4851 4852 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4853 @*/ 4854 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4855 { 4856 PetscBool ishdf5; 4857 PetscErrorCode ierr; 4858 4859 PetscFunctionBegin; 4860 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4861 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4862 PetscValidPointer(val,4); 4863 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4864 if (ishdf5) { 4865 #if defined(PETSC_HAVE_HDF5) 4866 PetscScalar value; 4867 4868 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4869 *val = PetscRealPart(value); 4870 #endif 4871 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4872 PetscFunctionReturn(0); 4873 } 4874 4875 #undef __FUNCT__ 4876 #define __FUNCT__ "DMGetUseNatural" 4877 /*@ 4878 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 4879 4880 Not collective 4881 4882 Input Parameter: 4883 . dm - The DM 4884 4885 Output Parameter: 4886 . useNatural - The flag to build the mapping to a natural order during distribution 4887 4888 Level: beginner 4889 4890 .seealso: DMSetUseNatural(), DMCreate() 4891 @*/ 4892 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 4893 { 4894 PetscFunctionBegin; 4895 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4896 PetscValidPointer(useNatural, 2); 4897 *useNatural = dm->useNatural; 4898 PetscFunctionReturn(0); 4899 } 4900 4901 #undef __FUNCT__ 4902 #define __FUNCT__ "DMSetUseNatural" 4903 /*@ 4904 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 4905 4906 Collective on dm 4907 4908 Input Parameters: 4909 + dm - The DM 4910 - useNatural - The flag to build the mapping to a natural order during distribution 4911 4912 Level: beginner 4913 4914 .seealso: DMGetUseNatural(), DMCreate() 4915 @*/ 4916 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 4917 { 4918 PetscFunctionBegin; 4919 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4920 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 4921 dm->useNatural = useNatural; 4922 PetscFunctionReturn(0); 4923 } 4924 4925 #undef __FUNCT__ 4926 #define __FUNCT__ 4927 4928 #undef __FUNCT__ 4929 #define __FUNCT__ "DMCreateLabel" 4930 /*@C 4931 DMCreateLabel - Create a label of the given name if it does not already exist 4932 4933 Not Collective 4934 4935 Input Parameters: 4936 + dm - The DM object 4937 - name - The label name 4938 4939 Level: intermediate 4940 4941 .keywords: mesh 4942 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4943 @*/ 4944 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 4945 { 4946 DMLabelLink next = dm->labels->next; 4947 PetscBool flg = PETSC_FALSE; 4948 PetscErrorCode ierr; 4949 4950 PetscFunctionBegin; 4951 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4952 PetscValidCharPointer(name, 2); 4953 while (next) { 4954 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 4955 if (flg) break; 4956 next = next->next; 4957 } 4958 if (!flg) { 4959 DMLabelLink tmpLabel; 4960 4961 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 4962 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 4963 tmpLabel->output = PETSC_TRUE; 4964 tmpLabel->next = dm->labels->next; 4965 dm->labels->next = tmpLabel; 4966 } 4967 PetscFunctionReturn(0); 4968 } 4969 4970 #undef __FUNCT__ 4971 #define __FUNCT__ "DMGetLabelValue" 4972 /*@C 4973 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 4974 4975 Not Collective 4976 4977 Input Parameters: 4978 + dm - The DM object 4979 . name - The label name 4980 - point - The mesh point 4981 4982 Output Parameter: 4983 . value - The label value for this point, or -1 if the point is not in the label 4984 4985 Level: beginner 4986 4987 .keywords: mesh 4988 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 4989 @*/ 4990 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 4991 { 4992 DMLabel label; 4993 PetscErrorCode ierr; 4994 4995 PetscFunctionBegin; 4996 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4997 PetscValidCharPointer(name, 2); 4998 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4999 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr); 5000 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5001 PetscFunctionReturn(0); 5002 } 5003 5004 #undef __FUNCT__ 5005 #define __FUNCT__ "DMSetLabelValue" 5006 /*@C 5007 DMSetLabelValue - Add a point to a Sieve Label with given value 5008 5009 Not Collective 5010 5011 Input Parameters: 5012 + dm - The DM object 5013 . name - The label name 5014 . point - The mesh point 5015 - value - The label value for this point 5016 5017 Output Parameter: 5018 5019 Level: beginner 5020 5021 .keywords: mesh 5022 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5023 @*/ 5024 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5025 { 5026 DMLabel label; 5027 PetscErrorCode ierr; 5028 5029 PetscFunctionBegin; 5030 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5031 PetscValidCharPointer(name, 2); 5032 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5033 if (!label) { 5034 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5035 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5036 } 5037 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5038 PetscFunctionReturn(0); 5039 } 5040 5041 #undef __FUNCT__ 5042 #define __FUNCT__ "DMClearLabelValue" 5043 /*@C 5044 DMClearLabelValue - Remove a point from a Sieve Label with given value 5045 5046 Not Collective 5047 5048 Input Parameters: 5049 + dm - The DM object 5050 . name - The label name 5051 . point - The mesh point 5052 - value - The label value for this point 5053 5054 Output Parameter: 5055 5056 Level: beginner 5057 5058 .keywords: mesh 5059 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5060 @*/ 5061 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5062 { 5063 DMLabel label; 5064 PetscErrorCode ierr; 5065 5066 PetscFunctionBegin; 5067 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5068 PetscValidCharPointer(name, 2); 5069 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5070 if (!label) PetscFunctionReturn(0); 5071 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5072 PetscFunctionReturn(0); 5073 } 5074 5075 #undef __FUNCT__ 5076 #define __FUNCT__ "DMGetLabelSize" 5077 /*@C 5078 DMGetLabelSize - Get the number of different integer ids in a Label 5079 5080 Not Collective 5081 5082 Input Parameters: 5083 + dm - The DM object 5084 - name - The label name 5085 5086 Output Parameter: 5087 . size - The number of different integer ids, or 0 if the label does not exist 5088 5089 Level: beginner 5090 5091 .keywords: mesh 5092 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5093 @*/ 5094 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5095 { 5096 DMLabel label; 5097 PetscErrorCode ierr; 5098 5099 PetscFunctionBegin; 5100 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5101 PetscValidCharPointer(name, 2); 5102 PetscValidPointer(size, 3); 5103 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5104 *size = 0; 5105 if (!label) PetscFunctionReturn(0); 5106 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5107 PetscFunctionReturn(0); 5108 } 5109 5110 #undef __FUNCT__ 5111 #define __FUNCT__ "DMGetLabelIdIS" 5112 /*@C 5113 DMGetLabelIdIS - Get the integer ids in a label 5114 5115 Not Collective 5116 5117 Input Parameters: 5118 + mesh - The DM object 5119 - name - The label name 5120 5121 Output Parameter: 5122 . ids - The integer ids, or NULL if the label does not exist 5123 5124 Level: beginner 5125 5126 .keywords: mesh 5127 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5128 @*/ 5129 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5130 { 5131 DMLabel label; 5132 PetscErrorCode ierr; 5133 5134 PetscFunctionBegin; 5135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5136 PetscValidCharPointer(name, 2); 5137 PetscValidPointer(ids, 3); 5138 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5139 *ids = NULL; 5140 if (!label) PetscFunctionReturn(0); 5141 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5142 PetscFunctionReturn(0); 5143 } 5144 5145 #undef __FUNCT__ 5146 #define __FUNCT__ "DMGetStratumSize" 5147 /*@C 5148 DMGetStratumSize - Get the number of points in a label stratum 5149 5150 Not Collective 5151 5152 Input Parameters: 5153 + dm - The DM object 5154 . name - The label name 5155 - value - The stratum value 5156 5157 Output Parameter: 5158 . size - The stratum size 5159 5160 Level: beginner 5161 5162 .keywords: mesh 5163 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5164 @*/ 5165 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5166 { 5167 DMLabel label; 5168 PetscErrorCode ierr; 5169 5170 PetscFunctionBegin; 5171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5172 PetscValidCharPointer(name, 2); 5173 PetscValidPointer(size, 4); 5174 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5175 *size = 0; 5176 if (!label) PetscFunctionReturn(0); 5177 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5178 PetscFunctionReturn(0); 5179 } 5180 5181 #undef __FUNCT__ 5182 #define __FUNCT__ "DMGetStratumIS" 5183 /*@C 5184 DMGetStratumIS - Get the points in a label stratum 5185 5186 Not Collective 5187 5188 Input Parameters: 5189 + dm - The DM object 5190 . name - The label name 5191 - value - The stratum value 5192 5193 Output Parameter: 5194 . points - The stratum points, or NULL if the label does not exist or does not have that value 5195 5196 Level: beginner 5197 5198 .keywords: mesh 5199 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5200 @*/ 5201 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5202 { 5203 DMLabel label; 5204 PetscErrorCode ierr; 5205 5206 PetscFunctionBegin; 5207 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5208 PetscValidCharPointer(name, 2); 5209 PetscValidPointer(points, 4); 5210 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5211 *points = NULL; 5212 if (!label) PetscFunctionReturn(0); 5213 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5214 PetscFunctionReturn(0); 5215 } 5216 5217 #undef __FUNCT__ 5218 #define __FUNCT__ "DMClearLabelStratum" 5219 /*@C 5220 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5221 5222 Not Collective 5223 5224 Input Parameters: 5225 + dm - The DM object 5226 . name - The label name 5227 - value - The label value for this point 5228 5229 Output Parameter: 5230 5231 Level: beginner 5232 5233 .keywords: mesh 5234 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5235 @*/ 5236 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5237 { 5238 DMLabel label; 5239 PetscErrorCode ierr; 5240 5241 PetscFunctionBegin; 5242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5243 PetscValidCharPointer(name, 2); 5244 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5245 if (!label) PetscFunctionReturn(0); 5246 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5247 PetscFunctionReturn(0); 5248 } 5249 5250 #undef __FUNCT__ 5251 #define __FUNCT__ "DMGetNumLabels" 5252 /*@ 5253 DMGetNumLabels - Return the number of labels defined by the mesh 5254 5255 Not Collective 5256 5257 Input Parameter: 5258 . dm - The DM object 5259 5260 Output Parameter: 5261 . numLabels - the number of Labels 5262 5263 Level: intermediate 5264 5265 .keywords: mesh 5266 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5267 @*/ 5268 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5269 { 5270 DMLabelLink next = dm->labels->next; 5271 PetscInt n = 0; 5272 5273 PetscFunctionBegin; 5274 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5275 PetscValidPointer(numLabels, 2); 5276 while (next) {++n; next = next->next;} 5277 *numLabels = n; 5278 PetscFunctionReturn(0); 5279 } 5280 5281 #undef __FUNCT__ 5282 #define __FUNCT__ "DMGetLabelName" 5283 /*@C 5284 DMGetLabelName - Return the name of nth label 5285 5286 Not Collective 5287 5288 Input Parameters: 5289 + dm - The DM object 5290 - n - the label number 5291 5292 Output Parameter: 5293 . name - the label name 5294 5295 Level: intermediate 5296 5297 .keywords: mesh 5298 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5299 @*/ 5300 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5301 { 5302 DMLabelLink next = dm->labels->next; 5303 PetscInt l = 0; 5304 5305 PetscFunctionBegin; 5306 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5307 PetscValidPointer(name, 3); 5308 while (next) { 5309 if (l == n) { 5310 *name = next->label->name; 5311 PetscFunctionReturn(0); 5312 } 5313 ++l; 5314 next = next->next; 5315 } 5316 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5317 } 5318 5319 #undef __FUNCT__ 5320 #define __FUNCT__ "DMHasLabel" 5321 /*@C 5322 DMHasLabel - Determine whether the mesh has a label of a given name 5323 5324 Not Collective 5325 5326 Input Parameters: 5327 + dm - The DM object 5328 - name - The label name 5329 5330 Output Parameter: 5331 . hasLabel - PETSC_TRUE if the label is present 5332 5333 Level: intermediate 5334 5335 .keywords: mesh 5336 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5337 @*/ 5338 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5339 { 5340 DMLabelLink next = dm->labels->next; 5341 PetscErrorCode ierr; 5342 5343 PetscFunctionBegin; 5344 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5345 PetscValidCharPointer(name, 2); 5346 PetscValidPointer(hasLabel, 3); 5347 *hasLabel = PETSC_FALSE; 5348 while (next) { 5349 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5350 if (*hasLabel) break; 5351 next = next->next; 5352 } 5353 PetscFunctionReturn(0); 5354 } 5355 5356 #undef __FUNCT__ 5357 #define __FUNCT__ "DMGetLabel" 5358 /*@C 5359 DMGetLabel - Return the label of a given name, or NULL 5360 5361 Not Collective 5362 5363 Input Parameters: 5364 + dm - The DM object 5365 - name - The label name 5366 5367 Output Parameter: 5368 . label - The DMLabel, or NULL if the label is absent 5369 5370 Level: intermediate 5371 5372 .keywords: mesh 5373 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5374 @*/ 5375 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5376 { 5377 DMLabelLink next = dm->labels->next; 5378 PetscBool hasLabel; 5379 PetscErrorCode ierr; 5380 5381 PetscFunctionBegin; 5382 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5383 PetscValidCharPointer(name, 2); 5384 PetscValidPointer(label, 3); 5385 *label = NULL; 5386 while (next) { 5387 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5388 if (hasLabel) { 5389 *label = next->label; 5390 break; 5391 } 5392 next = next->next; 5393 } 5394 PetscFunctionReturn(0); 5395 } 5396 5397 #undef __FUNCT__ 5398 #define __FUNCT__ "DMGetLabelByNum" 5399 /*@C 5400 DMGetLabelByNum - Return the nth label 5401 5402 Not Collective 5403 5404 Input Parameters: 5405 + dm - The DM object 5406 - n - the label number 5407 5408 Output Parameter: 5409 . label - the label 5410 5411 Level: intermediate 5412 5413 .keywords: mesh 5414 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5415 @*/ 5416 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5417 { 5418 DMLabelLink next = dm->labels->next; 5419 PetscInt l = 0; 5420 5421 PetscFunctionBegin; 5422 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5423 PetscValidPointer(label, 3); 5424 while (next) { 5425 if (l == n) { 5426 *label = next->label; 5427 PetscFunctionReturn(0); 5428 } 5429 ++l; 5430 next = next->next; 5431 } 5432 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5433 } 5434 5435 #undef __FUNCT__ 5436 #define __FUNCT__ "DMAddLabel" 5437 /*@C 5438 DMAddLabel - Add the label to this mesh 5439 5440 Not Collective 5441 5442 Input Parameters: 5443 + dm - The DM object 5444 - label - The DMLabel 5445 5446 Level: developer 5447 5448 .keywords: mesh 5449 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5450 @*/ 5451 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5452 { 5453 DMLabelLink tmpLabel; 5454 PetscBool hasLabel; 5455 PetscErrorCode ierr; 5456 5457 PetscFunctionBegin; 5458 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5459 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5460 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5461 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5462 tmpLabel->label = label; 5463 tmpLabel->output = PETSC_TRUE; 5464 tmpLabel->next = dm->labels->next; 5465 dm->labels->next = tmpLabel; 5466 PetscFunctionReturn(0); 5467 } 5468 5469 #undef __FUNCT__ 5470 #define __FUNCT__ "DMRemoveLabel" 5471 /*@C 5472 DMRemoveLabel - Remove the label from this mesh 5473 5474 Not Collective 5475 5476 Input Parameters: 5477 + dm - The DM object 5478 - name - The label name 5479 5480 Output Parameter: 5481 . label - The DMLabel, or NULL if the label is absent 5482 5483 Level: developer 5484 5485 .keywords: mesh 5486 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5487 @*/ 5488 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5489 { 5490 DMLabelLink next = dm->labels->next; 5491 DMLabelLink last = NULL; 5492 PetscBool hasLabel; 5493 PetscErrorCode ierr; 5494 5495 PetscFunctionBegin; 5496 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5497 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5498 *label = NULL; 5499 if (!hasLabel) PetscFunctionReturn(0); 5500 while (next) { 5501 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5502 if (hasLabel) { 5503 if (last) last->next = next->next; 5504 else dm->labels->next = next->next; 5505 next->next = NULL; 5506 *label = next->label; 5507 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5508 if (hasLabel) { 5509 dm->depthLabel = NULL; 5510 } 5511 ierr = PetscFree(next);CHKERRQ(ierr); 5512 break; 5513 } 5514 last = next; 5515 next = next->next; 5516 } 5517 PetscFunctionReturn(0); 5518 } 5519 5520 #undef __FUNCT__ 5521 #define __FUNCT__ "DMGetLabelOutput" 5522 /*@C 5523 DMGetLabelOutput - Get the output flag for a given label 5524 5525 Not Collective 5526 5527 Input Parameters: 5528 + dm - The DM object 5529 - name - The label name 5530 5531 Output Parameter: 5532 . output - The flag for output 5533 5534 Level: developer 5535 5536 .keywords: mesh 5537 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5538 @*/ 5539 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5540 { 5541 DMLabelLink next = dm->labels->next; 5542 PetscErrorCode ierr; 5543 5544 PetscFunctionBegin; 5545 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5546 PetscValidPointer(name, 2); 5547 PetscValidPointer(output, 3); 5548 while (next) { 5549 PetscBool flg; 5550 5551 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5552 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5553 next = next->next; 5554 } 5555 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5556 } 5557 5558 #undef __FUNCT__ 5559 #define __FUNCT__ "DMSetLabelOutput" 5560 /*@C 5561 DMSetLabelOutput - Set the output flag for a given label 5562 5563 Not Collective 5564 5565 Input Parameters: 5566 + dm - The DM object 5567 . name - The label name 5568 - output - The flag for output 5569 5570 Level: developer 5571 5572 .keywords: mesh 5573 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5574 @*/ 5575 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5576 { 5577 DMLabelLink next = dm->labels->next; 5578 PetscErrorCode ierr; 5579 5580 PetscFunctionBegin; 5581 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5582 PetscValidPointer(name, 2); 5583 while (next) { 5584 PetscBool flg; 5585 5586 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5587 if (flg) {next->output = output; PetscFunctionReturn(0);} 5588 next = next->next; 5589 } 5590 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5591 } 5592 5593 5594 #undef __FUNCT__ 5595 #define __FUNCT__ "DMCopyLabels" 5596 /*@ 5597 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5598 5599 Collective on DM 5600 5601 Input Parameter: 5602 . dmA - The DM object with initial labels 5603 5604 Output Parameter: 5605 . dmB - The DM object with copied labels 5606 5607 Level: intermediate 5608 5609 Note: This is typically used when interpolating or otherwise adding to a mesh 5610 5611 .keywords: mesh 5612 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5613 @*/ 5614 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5615 { 5616 PetscInt numLabels, l; 5617 PetscErrorCode ierr; 5618 5619 PetscFunctionBegin; 5620 if (dmA == dmB) PetscFunctionReturn(0); 5621 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5622 for (l = 0; l < numLabels; ++l) { 5623 DMLabel label, labelNew; 5624 const char *name; 5625 PetscBool flg; 5626 5627 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5628 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5629 if (flg) continue; 5630 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5631 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5632 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5633 } 5634 PetscFunctionReturn(0); 5635 } 5636 5637 #undef __FUNCT__ 5638 #define __FUNCT__ "DMGetCoarseDM" 5639 /*@ 5640 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5641 5642 Input Parameter: 5643 . dm - The DM object 5644 5645 Output Parameter: 5646 . cdm - The coarse DM 5647 5648 Level: intermediate 5649 5650 .seealso: DMSetCoarseDM() 5651 @*/ 5652 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5653 { 5654 PetscFunctionBegin; 5655 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5656 PetscValidPointer(cdm, 2); 5657 *cdm = dm->coarseMesh; 5658 PetscFunctionReturn(0); 5659 } 5660 5661 #undef __FUNCT__ 5662 #define __FUNCT__ "DMSetCoarseDM" 5663 /*@ 5664 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5665 5666 Input Parameters: 5667 + dm - The DM object 5668 - cdm - The coarse DM 5669 5670 Level: intermediate 5671 5672 .seealso: DMGetCoarseDM() 5673 @*/ 5674 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5675 { 5676 PetscErrorCode ierr; 5677 5678 PetscFunctionBegin; 5679 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5680 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5681 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5682 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5683 dm->coarseMesh = cdm; 5684 PetscFunctionReturn(0); 5685 } 5686 5687 #undef __FUNCT__ 5688 #define __FUNCT__ "DMGetFineDM" 5689 /*@ 5690 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 5691 5692 Input Parameter: 5693 . dm - The DM object 5694 5695 Output Parameter: 5696 . fdm - The fine DM 5697 5698 Level: intermediate 5699 5700 .seealso: DMSetFineDM() 5701 @*/ 5702 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 5703 { 5704 PetscFunctionBegin; 5705 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5706 PetscValidPointer(fdm, 2); 5707 *fdm = dm->fineMesh; 5708 PetscFunctionReturn(0); 5709 } 5710 5711 #undef __FUNCT__ 5712 #define __FUNCT__ "DMSetFineDM" 5713 /*@ 5714 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 5715 5716 Input Parameters: 5717 + dm - The DM object 5718 - fdm - The fine DM 5719 5720 Level: intermediate 5721 5722 .seealso: DMGetFineDM() 5723 @*/ 5724 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 5725 { 5726 PetscErrorCode ierr; 5727 5728 PetscFunctionBegin; 5729 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5730 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 5731 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 5732 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 5733 dm->fineMesh = fdm; 5734 PetscFunctionReturn(0); 5735 } 5736 5737 /*=== DMBoundary code ===*/ 5738 5739 #undef __FUNCT__ 5740 #define __FUNCT__ "DMBoundaryDuplicate" 5741 PetscErrorCode DMBoundaryDuplicate(DMBoundaryLinkList bd, DMBoundaryLinkList *boundary) 5742 { 5743 DMBoundary b = bd->next, b2, bold = NULL; 5744 PetscErrorCode ierr; 5745 5746 PetscFunctionBegin; 5747 ierr = PetscNew(boundary);CHKERRQ(ierr); 5748 (*boundary)->refct = 1; 5749 (*boundary)->next = NULL; 5750 for (; b; b = b->next, bold = b2) { 5751 ierr = PetscNew(&b2);CHKERRQ(ierr); 5752 ierr = PetscStrallocpy(b->name, (char **) &b2->name);CHKERRQ(ierr); 5753 ierr = PetscStrallocpy(b->labelname, (char **) &b2->labelname);CHKERRQ(ierr); 5754 ierr = PetscMalloc1(b->numids, &b2->ids);CHKERRQ(ierr); 5755 ierr = PetscMemcpy(b2->ids, b->ids, b->numids*sizeof(PetscInt));CHKERRQ(ierr); 5756 ierr = PetscMalloc1(b->numcomps, &b2->comps);CHKERRQ(ierr); 5757 ierr = PetscMemcpy(b2->comps, b->comps, b->numcomps*sizeof(PetscInt));CHKERRQ(ierr); 5758 b2->label = NULL; 5759 b2->essential = b->essential; 5760 b2->field = b->field; 5761 b2->numcomps = b->numcomps; 5762 b2->func = b->func; 5763 b2->numids = b->numids; 5764 b2->ctx = b->ctx; 5765 b2->next = NULL; 5766 if (!(*boundary)->next) (*boundary)->next = b2; 5767 if (bold) bold->next = b2; 5768 } 5769 PetscFunctionReturn(0); 5770 } 5771 5772 #undef __FUNCT__ 5773 #define __FUNCT__ "DMBoundaryDestroy" 5774 PetscErrorCode DMBoundaryDestroy(DMBoundaryLinkList *boundary) 5775 { 5776 DMBoundary b, next; 5777 PetscErrorCode ierr; 5778 5779 PetscFunctionBegin; 5780 if (!boundary) PetscFunctionReturn(0); 5781 if (--((*boundary)->refct)) { 5782 *boundary = NULL; 5783 PetscFunctionReturn(0); 5784 } 5785 b = (*boundary)->next; 5786 for (; b; b = next) { 5787 next = b->next; 5788 ierr = PetscFree(b->comps);CHKERRQ(ierr); 5789 ierr = PetscFree(b->ids);CHKERRQ(ierr); 5790 ierr = PetscFree(b->name);CHKERRQ(ierr); 5791 ierr = PetscFree(b->labelname);CHKERRQ(ierr); 5792 ierr = PetscFree(b);CHKERRQ(ierr); 5793 } 5794 ierr = PetscFree(*boundary);CHKERRQ(ierr); 5795 PetscFunctionReturn(0); 5796 } 5797 5798 #undef __FUNCT__ 5799 #define __FUNCT__ "DMCopyBoundary" 5800 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 5801 { 5802 DMBoundary b; 5803 PetscErrorCode ierr; 5804 5805 PetscFunctionBegin; 5806 ierr = DMBoundaryDestroy(&dmNew->boundary);CHKERRQ(ierr); 5807 ierr = DMBoundaryDuplicate(dm->boundary, &dmNew->boundary);CHKERRQ(ierr); 5808 for (b = dmNew->boundary->next; b; b = b->next) { 5809 if (b->labelname) { 5810 ierr = DMGetLabel(dmNew, b->labelname, &b->label);CHKERRQ(ierr); 5811 if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 5812 } 5813 } 5814 PetscFunctionReturn(0); 5815 } 5816 5817 #undef __FUNCT__ 5818 #define __FUNCT__ "DMAddBoundary" 5819 /*@C 5820 DMAddBoundary - Add a boundary condition to the model 5821 5822 Input Parameters: 5823 + dm - The mesh object 5824 . isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition 5825 . name - The BC name 5826 . labelname - The label defining constrained points 5827 . field - The field to constrain 5828 . numcomps - The number of constrained field components 5829 . comps - An array of constrained component numbers 5830 . bcFunc - A pointwise function giving boundary values 5831 . numids - The number of DMLabel ids for constrained points 5832 . ids - An array of ids for constrained points 5833 - ctx - An optional user context for bcFunc 5834 5835 Options Database Keys: 5836 + -bc_<boundary name> <num> - Overrides the boundary ids 5837 - -bc_<boundary name>_comp <num> - Overrides the boundary components 5838 5839 Level: developer 5840 5841 .seealso: DMGetBoundary() 5842 @*/ 5843 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) 5844 { 5845 DMBoundary b; 5846 PetscErrorCode ierr; 5847 5848 PetscFunctionBegin; 5849 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5850 ierr = PetscNew(&b);CHKERRQ(ierr); 5851 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 5852 ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); 5853 ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr); 5854 if (numcomps) {ierr = PetscMemcpy(b->comps, comps, numcomps*sizeof(PetscInt));CHKERRQ(ierr);} 5855 ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); 5856 if (numids) {ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr);} 5857 if (b->labelname) { 5858 ierr = DMGetLabel(dm, b->labelname, &b->label);CHKERRQ(ierr); 5859 if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 5860 } 5861 b->essential = isEssential; 5862 b->field = field; 5863 b->numcomps = numcomps; 5864 b->func = bcFunc; 5865 b->numids = numids; 5866 b->ctx = ctx; 5867 b->next = dm->boundary->next; 5868 dm->boundary->next = b; 5869 PetscFunctionReturn(0); 5870 } 5871 5872 #undef __FUNCT__ 5873 #define __FUNCT__ "DMGetNumBoundary" 5874 /*@ 5875 DMGetNumBoundary - Get the number of registered BC 5876 5877 Input Parameters: 5878 . dm - The mesh object 5879 5880 Output Parameters: 5881 . numBd - The number of BC 5882 5883 Level: intermediate 5884 5885 .seealso: DMAddBoundary(), DMGetBoundary() 5886 @*/ 5887 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 5888 { 5889 DMBoundary b = dm->boundary->next; 5890 5891 PetscFunctionBegin; 5892 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5893 PetscValidPointer(numBd, 2); 5894 *numBd = 0; 5895 while (b) {++(*numBd); b = b->next;} 5896 PetscFunctionReturn(0); 5897 } 5898 5899 #undef __FUNCT__ 5900 #define __FUNCT__ "DMGetBoundary" 5901 /*@C 5902 DMGetBoundary - Add a boundary condition to the model 5903 5904 Input Parameters: 5905 + dm - The mesh object 5906 - bd - The BC number 5907 5908 Output Parameters: 5909 + isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition 5910 . name - The BC name 5911 . labelname - The label defining constrained points 5912 . field - The field to constrain 5913 . numcomps - The number of constrained field components 5914 . comps - An array of constrained component numbers 5915 . bcFunc - A pointwise function giving boundary values 5916 . numids - The number of DMLabel ids for constrained points 5917 . ids - An array of ids for constrained points 5918 - ctx - An optional user context for bcFunc 5919 5920 Options Database Keys: 5921 + -bc_<boundary name> <num> - Overrides the boundary ids 5922 - -bc_<boundary name>_comp <num> - Overrides the boundary components 5923 5924 Level: developer 5925 5926 .seealso: DMAddBoundary() 5927 @*/ 5928 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) 5929 { 5930 DMBoundary b = dm->boundary->next; 5931 PetscInt n = 0; 5932 5933 PetscFunctionBegin; 5934 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5935 while (b) { 5936 if (n == bd) break; 5937 b = b->next; 5938 ++n; 5939 } 5940 if (n != bd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 5941 if (isEssential) { 5942 PetscValidPointer(isEssential, 3); 5943 *isEssential = b->essential; 5944 } 5945 if (name) { 5946 PetscValidPointer(name, 4); 5947 *name = b->name; 5948 } 5949 if (labelname) { 5950 PetscValidPointer(labelname, 5); 5951 *labelname = b->labelname; 5952 } 5953 if (field) { 5954 PetscValidPointer(field, 6); 5955 *field = b->field; 5956 } 5957 if (numcomps) { 5958 PetscValidPointer(numcomps, 7); 5959 *numcomps = b->numcomps; 5960 } 5961 if (comps) { 5962 PetscValidPointer(comps, 8); 5963 *comps = b->comps; 5964 } 5965 if (func) { 5966 PetscValidPointer(func, 9); 5967 *func = b->func; 5968 } 5969 if (numids) { 5970 PetscValidPointer(numids, 10); 5971 *numids = b->numids; 5972 } 5973 if (ids) { 5974 PetscValidPointer(ids, 11); 5975 *ids = b->ids; 5976 } 5977 if (ctx) { 5978 PetscValidPointer(ctx, 12); 5979 *ctx = b->ctx; 5980 } 5981 PetscFunctionReturn(0); 5982 } 5983 5984 #undef __FUNCT__ 5985 #define __FUNCT__ "DMIsBoundaryPoint" 5986 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 5987 { 5988 DMBoundary b = dm->boundary->next; 5989 PetscErrorCode ierr; 5990 5991 PetscFunctionBegin; 5992 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5993 PetscValidPointer(isBd, 3); 5994 *isBd = PETSC_FALSE; 5995 while (b && !(*isBd)) { 5996 if (b->label) { 5997 PetscInt i; 5998 5999 for (i = 0; i < b->numids && !(*isBd); ++i) { 6000 ierr = DMLabelStratumHasPoint(b->label, b->ids[i], point, isBd);CHKERRQ(ierr); 6001 } 6002 } 6003 b = b->next; 6004 } 6005 PetscFunctionReturn(0); 6006 } 6007 6008 #undef __FUNCT__ 6009 #define __FUNCT__ "DMProjectFunction" 6010 /*@C 6011 DMProjectFunction - This projects the given function into the function space provided. 6012 6013 Input Parameters: 6014 + dm - The DM 6015 . time - The time 6016 . funcs - The coordinate functions to evaluate, one per field 6017 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6018 - mode - The insertion mode for values 6019 6020 Output Parameter: 6021 . X - vector 6022 6023 Calling sequence of func: 6024 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6025 6026 + dim - The spatial dimension 6027 . x - The coordinates 6028 . Nf - The number of fields 6029 . u - The output field values 6030 - ctx - optional user-defined function context 6031 6032 Level: developer 6033 6034 .seealso: DMComputeL2Diff() 6035 @*/ 6036 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6037 { 6038 Vec localX; 6039 PetscErrorCode ierr; 6040 6041 PetscFunctionBegin; 6042 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6043 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6044 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6045 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6046 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6047 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6048 PetscFunctionReturn(0); 6049 } 6050 6051 #undef __FUNCT__ 6052 #define __FUNCT__ "DMProjectFunctionLocal" 6053 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6054 { 6055 PetscErrorCode ierr; 6056 6057 PetscFunctionBegin; 6058 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6059 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6060 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6061 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6062 PetscFunctionReturn(0); 6063 } 6064 6065 #undef __FUNCT__ 6066 #define __FUNCT__ "DMProjectFieldLocal" 6067 PetscErrorCode DMProjectFieldLocal(DM dm, Vec localU, 6068 void (**funcs)(PetscInt, PetscInt, PetscInt, 6069 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6070 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6071 PetscReal, const PetscReal[], PetscScalar[]), 6072 InsertMode mode, Vec localX) 6073 { 6074 PetscErrorCode ierr; 6075 6076 PetscFunctionBegin; 6077 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6078 PetscValidHeaderSpecific(localU,VEC_CLASSID,2); 6079 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6080 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name); 6081 ierr = (dm->ops->projectfieldlocal) (dm, localU, funcs, mode, localX);CHKERRQ(ierr); 6082 PetscFunctionReturn(0); 6083 } 6084 6085 #undef __FUNCT__ 6086 #define __FUNCT__ "DMProjectFunctionLabelLocal" 6087 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) 6088 { 6089 PetscErrorCode ierr; 6090 6091 PetscFunctionBegin; 6092 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6093 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6094 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6095 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6096 PetscFunctionReturn(0); 6097 } 6098 6099 #undef __FUNCT__ 6100 #define __FUNCT__ "DMComputeL2Diff" 6101 /*@C 6102 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6103 6104 Input Parameters: 6105 + dm - The DM 6106 . time - The time 6107 . funcs - The functions to evaluate for each field component 6108 . ctxs - Optional array of contexts to pass to each function, or NULL. 6109 - X - The coefficient vector u_h 6110 6111 Output Parameter: 6112 . diff - The diff ||u - u_h||_2 6113 6114 Level: developer 6115 6116 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6117 @*/ 6118 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6119 { 6120 PetscErrorCode ierr; 6121 6122 PetscFunctionBegin; 6123 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6124 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6125 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2Diff",((PetscObject)dm)->type_name); 6126 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6127 PetscFunctionReturn(0); 6128 } 6129 6130 #undef __FUNCT__ 6131 #define __FUNCT__ "DMComputeL2GradientDiff" 6132 /*@C 6133 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6134 6135 Input Parameters: 6136 + dm - The DM 6137 , time - The time 6138 . funcs - The gradient functions to evaluate for each field component 6139 . ctxs - Optional array of contexts to pass to each function, or NULL. 6140 . X - The coefficient vector u_h 6141 - n - The vector to project along 6142 6143 Output Parameter: 6144 . diff - The diff ||(grad u - grad u_h) . n||_2 6145 6146 Level: developer 6147 6148 .seealso: DMProjectFunction(), DMComputeL2Diff() 6149 @*/ 6150 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) 6151 { 6152 PetscErrorCode ierr; 6153 6154 PetscFunctionBegin; 6155 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6156 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6157 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6158 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6159 PetscFunctionReturn(0); 6160 } 6161 6162 #undef __FUNCT__ 6163 #define __FUNCT__ "DMComputeL2FieldDiff" 6164 /*@C 6165 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6166 6167 Input Parameters: 6168 + dm - The DM 6169 . time - The time 6170 . funcs - The functions to evaluate for each field component 6171 . ctxs - Optional array of contexts to pass to each function, or NULL. 6172 - X - The coefficient vector u_h 6173 6174 Output Parameter: 6175 . diff - The array of differences, ||u^f - u^f_h||_2 6176 6177 Level: developer 6178 6179 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6180 @*/ 6181 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6182 { 6183 PetscErrorCode ierr; 6184 6185 PetscFunctionBegin; 6186 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6187 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6188 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6189 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6190 PetscFunctionReturn(0); 6191 } 6192 6193