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