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