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