1 #include <petsc/private/petscfvimpl.h> /*I "petscfv.h" I*/ 2 #include <petsc/private/dmpleximpl.h> /* For CellRefiner */ 3 #include <petscds.h> 4 5 PetscClassId PETSCLIMITER_CLASSID = 0; 6 7 PetscFunctionList PetscLimiterList = NULL; 8 PetscBool PetscLimiterRegisterAllCalled = PETSC_FALSE; 9 10 PetscBool Limitercite = PETSC_FALSE; 11 const char LimiterCitation[] = "@article{BergerAftosmisMurman2005,\n" 12 " title = {Analysis of slope limiters on irregular grids},\n" 13 " journal = {AIAA paper},\n" 14 " author = {Marsha Berger and Michael J. Aftosmis and Scott M. Murman},\n" 15 " volume = {490},\n" 16 " year = {2005}\n}\n"; 17 18 /*@C 19 PetscLimiterRegister - Adds a new PetscLimiter implementation 20 21 Not Collective 22 23 Input Parameters: 24 + name - The name of a new user-defined creation routine 25 - create_func - The creation routine itself 26 27 Notes: 28 PetscLimiterRegister() may be called multiple times to add several user-defined PetscLimiters 29 30 Sample usage: 31 .vb 32 PetscLimiterRegister("my_lim", MyPetscLimiterCreate); 33 .ve 34 35 Then, your PetscLimiter type can be chosen with the procedural interface via 36 .vb 37 PetscLimiterCreate(MPI_Comm, PetscLimiter *); 38 PetscLimiterSetType(PetscLimiter, "my_lim"); 39 .ve 40 or at runtime via the option 41 .vb 42 -petsclimiter_type my_lim 43 .ve 44 45 Level: advanced 46 47 .seealso: PetscLimiterRegisterAll(), PetscLimiterRegisterDestroy() 48 49 @*/ 50 PetscErrorCode PetscLimiterRegister(const char sname[], PetscErrorCode (*function)(PetscLimiter)) 51 { 52 PetscErrorCode ierr; 53 54 PetscFunctionBegin; 55 ierr = PetscFunctionListAdd(&PetscLimiterList, sname, function);CHKERRQ(ierr); 56 PetscFunctionReturn(0); 57 } 58 59 /*@C 60 PetscLimiterSetType - Builds a particular PetscLimiter 61 62 Collective on lim 63 64 Input Parameters: 65 + lim - The PetscLimiter object 66 - name - The kind of limiter 67 68 Options Database Key: 69 . -petsclimiter_type <type> - Sets the PetscLimiter type; use -help for a list of available types 70 71 Level: intermediate 72 73 .seealso: PetscLimiterGetType(), PetscLimiterCreate() 74 @*/ 75 PetscErrorCode PetscLimiterSetType(PetscLimiter lim, PetscLimiterType name) 76 { 77 PetscErrorCode (*r)(PetscLimiter); 78 PetscBool match; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 83 ierr = PetscObjectTypeCompare((PetscObject) lim, name, &match);CHKERRQ(ierr); 84 if (match) PetscFunctionReturn(0); 85 86 ierr = PetscLimiterRegisterAll();CHKERRQ(ierr); 87 ierr = PetscFunctionListFind(PetscLimiterList, name, &r);CHKERRQ(ierr); 88 if (!r) SETERRQ1(PetscObjectComm((PetscObject) lim), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscLimiter type: %s", name); 89 90 if (lim->ops->destroy) { 91 ierr = (*lim->ops->destroy)(lim);CHKERRQ(ierr); 92 lim->ops->destroy = NULL; 93 } 94 ierr = (*r)(lim);CHKERRQ(ierr); 95 ierr = PetscObjectChangeTypeName((PetscObject) lim, name);CHKERRQ(ierr); 96 PetscFunctionReturn(0); 97 } 98 99 /*@C 100 PetscLimiterGetType - Gets the PetscLimiter type name (as a string) from the object. 101 102 Not Collective 103 104 Input Parameter: 105 . lim - The PetscLimiter 106 107 Output Parameter: 108 . name - The PetscLimiter type name 109 110 Level: intermediate 111 112 .seealso: PetscLimiterSetType(), PetscLimiterCreate() 113 @*/ 114 PetscErrorCode PetscLimiterGetType(PetscLimiter lim, PetscLimiterType *name) 115 { 116 PetscErrorCode ierr; 117 118 PetscFunctionBegin; 119 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 120 PetscValidPointer(name, 2); 121 ierr = PetscLimiterRegisterAll();CHKERRQ(ierr); 122 *name = ((PetscObject) lim)->type_name; 123 PetscFunctionReturn(0); 124 } 125 126 /*@C 127 PetscLimiterViewFromOptions - View from Options 128 129 Collective on PetscLimiter 130 131 Input Parameters: 132 + A - the PetscLimiter object to view 133 . obj - Optional object 134 - name - command line option 135 136 Level: intermediate 137 .seealso: PetscLimiter, PetscLimiterView, PetscObjectViewFromOptions(), PetscLimiterCreate() 138 @*/ 139 PetscErrorCode PetscLimiterViewFromOptions(PetscLimiter A,PetscObject obj,const char name[]) 140 { 141 PetscErrorCode ierr; 142 143 PetscFunctionBegin; 144 PetscValidHeaderSpecific(A,PETSCLIMITER_CLASSID,1); 145 ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr); 146 PetscFunctionReturn(0); 147 } 148 149 /*@C 150 PetscLimiterView - Views a PetscLimiter 151 152 Collective on lim 153 154 Input Parameter: 155 + lim - the PetscLimiter object to view 156 - v - the viewer 157 158 Level: beginner 159 160 .seealso: PetscLimiterDestroy() 161 @*/ 162 PetscErrorCode PetscLimiterView(PetscLimiter lim, PetscViewer v) 163 { 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 168 if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) lim), &v);CHKERRQ(ierr);} 169 if (lim->ops->view) {ierr = (*lim->ops->view)(lim, v);CHKERRQ(ierr);} 170 PetscFunctionReturn(0); 171 } 172 173 /*@ 174 PetscLimiterSetFromOptions - sets parameters in a PetscLimiter from the options database 175 176 Collective on lim 177 178 Input Parameter: 179 . lim - the PetscLimiter object to set options for 180 181 Level: intermediate 182 183 .seealso: PetscLimiterView() 184 @*/ 185 PetscErrorCode PetscLimiterSetFromOptions(PetscLimiter lim) 186 { 187 const char *defaultType; 188 char name[256]; 189 PetscBool flg; 190 PetscErrorCode ierr; 191 192 PetscFunctionBegin; 193 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 194 if (!((PetscObject) lim)->type_name) defaultType = PETSCLIMITERSIN; 195 else defaultType = ((PetscObject) lim)->type_name; 196 ierr = PetscLimiterRegisterAll();CHKERRQ(ierr); 197 198 ierr = PetscObjectOptionsBegin((PetscObject) lim);CHKERRQ(ierr); 199 ierr = PetscOptionsFList("-petsclimiter_type", "Finite volume slope limiter", "PetscLimiterSetType", PetscLimiterList, defaultType, name, 256, &flg);CHKERRQ(ierr); 200 if (flg) { 201 ierr = PetscLimiterSetType(lim, name);CHKERRQ(ierr); 202 } else if (!((PetscObject) lim)->type_name) { 203 ierr = PetscLimiterSetType(lim, defaultType);CHKERRQ(ierr); 204 } 205 if (lim->ops->setfromoptions) {ierr = (*lim->ops->setfromoptions)(lim);CHKERRQ(ierr);} 206 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 207 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) lim);CHKERRQ(ierr); 208 ierr = PetscOptionsEnd();CHKERRQ(ierr); 209 ierr = PetscLimiterViewFromOptions(lim, NULL, "-petsclimiter_view");CHKERRQ(ierr); 210 PetscFunctionReturn(0); 211 } 212 213 /*@C 214 PetscLimiterSetUp - Construct data structures for the PetscLimiter 215 216 Collective on lim 217 218 Input Parameter: 219 . lim - the PetscLimiter object to setup 220 221 Level: intermediate 222 223 .seealso: PetscLimiterView(), PetscLimiterDestroy() 224 @*/ 225 PetscErrorCode PetscLimiterSetUp(PetscLimiter lim) 226 { 227 PetscErrorCode ierr; 228 229 PetscFunctionBegin; 230 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 231 if (lim->ops->setup) {ierr = (*lim->ops->setup)(lim);CHKERRQ(ierr);} 232 PetscFunctionReturn(0); 233 } 234 235 /*@ 236 PetscLimiterDestroy - Destroys a PetscLimiter object 237 238 Collective on lim 239 240 Input Parameter: 241 . lim - the PetscLimiter object to destroy 242 243 Level: beginner 244 245 .seealso: PetscLimiterView() 246 @*/ 247 PetscErrorCode PetscLimiterDestroy(PetscLimiter *lim) 248 { 249 PetscErrorCode ierr; 250 251 PetscFunctionBegin; 252 if (!*lim) PetscFunctionReturn(0); 253 PetscValidHeaderSpecific((*lim), PETSCLIMITER_CLASSID, 1); 254 255 if (--((PetscObject)(*lim))->refct > 0) {*lim = 0; PetscFunctionReturn(0);} 256 ((PetscObject) (*lim))->refct = 0; 257 258 if ((*lim)->ops->destroy) {ierr = (*(*lim)->ops->destroy)(*lim);CHKERRQ(ierr);} 259 ierr = PetscHeaderDestroy(lim);CHKERRQ(ierr); 260 PetscFunctionReturn(0); 261 } 262 263 /*@ 264 PetscLimiterCreate - Creates an empty PetscLimiter object. The type can then be set with PetscLimiterSetType(). 265 266 Collective 267 268 Input Parameter: 269 . comm - The communicator for the PetscLimiter object 270 271 Output Parameter: 272 . lim - The PetscLimiter object 273 274 Level: beginner 275 276 .seealso: PetscLimiterSetType(), PETSCLIMITERSIN 277 @*/ 278 PetscErrorCode PetscLimiterCreate(MPI_Comm comm, PetscLimiter *lim) 279 { 280 PetscLimiter l; 281 PetscErrorCode ierr; 282 283 PetscFunctionBegin; 284 PetscValidPointer(lim, 2); 285 ierr = PetscCitationsRegister(LimiterCitation,&Limitercite);CHKERRQ(ierr); 286 *lim = NULL; 287 ierr = PetscFVInitializePackage();CHKERRQ(ierr); 288 289 ierr = PetscHeaderCreate(l, PETSCLIMITER_CLASSID, "PetscLimiter", "Finite Volume Slope Limiter", "PetscLimiter", comm, PetscLimiterDestroy, PetscLimiterView);CHKERRQ(ierr); 290 291 *lim = l; 292 PetscFunctionReturn(0); 293 } 294 295 /*@ 296 PetscLimiterLimit - Limit the flux 297 298 Input Parameters: 299 + lim - The PetscLimiter 300 - flim - The input field 301 302 Output Parameter: 303 . phi - The limited field 304 305 Note: Limiters given in symmetric form following Berger, Aftosmis, and Murman 2005 306 $ The classical flux-limited formulation is psi(r) where 307 $ 308 $ r = (u[0] - u[-1]) / (u[1] - u[0]) 309 $ 310 $ The second order TVD region is bounded by 311 $ 312 $ psi_minmod(r) = min(r,1) and psi_superbee(r) = min(2, 2r, max(1,r)) 313 $ 314 $ where all limiters are implicitly clipped to be non-negative. A more convenient slope-limited form is psi(r) = 315 $ phi(r)(r+1)/2 in which the reconstructed interface values are 316 $ 317 $ u(v) = u[0] + phi(r) (grad u)[0] v 318 $ 319 $ where v is the vector from centroid to quadrature point. In these variables, the usual limiters become 320 $ 321 $ phi_minmod(r) = 2 min(1/(1+r),r/(1+r)) phi_superbee(r) = 2 min(2/(1+r), 2r/(1+r), max(1,r)/(1+r)) 322 $ 323 $ For a nicer symmetric formulation, rewrite in terms of 324 $ 325 $ f = (u[0] - u[-1]) / (u[1] - u[-1]) 326 $ 327 $ where r(f) = f/(1-f). Not that r(1-f) = (1-f)/f = 1/r(f) so the symmetry condition 328 $ 329 $ phi(r) = phi(1/r) 330 $ 331 $ becomes 332 $ 333 $ w(f) = w(1-f). 334 $ 335 $ The limiters below implement this final form w(f). The reference methods are 336 $ 337 $ w_minmod(f) = 2 min(f,(1-f)) w_superbee(r) = 4 min((1-f), f) 338 339 Level: beginner 340 341 .seealso: PetscLimiterSetType(), PetscLimiterCreate() 342 @*/ 343 PetscErrorCode PetscLimiterLimit(PetscLimiter lim, PetscReal flim, PetscReal *phi) 344 { 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 349 PetscValidPointer(phi, 3); 350 ierr = (*lim->ops->limit)(lim, flim, phi);CHKERRQ(ierr); 351 PetscFunctionReturn(0); 352 } 353 354 static PetscErrorCode PetscLimiterDestroy_Sin(PetscLimiter lim) 355 { 356 PetscLimiter_Sin *l = (PetscLimiter_Sin *) lim->data; 357 PetscErrorCode ierr; 358 359 PetscFunctionBegin; 360 ierr = PetscFree(l);CHKERRQ(ierr); 361 PetscFunctionReturn(0); 362 } 363 364 static PetscErrorCode PetscLimiterView_Sin_Ascii(PetscLimiter lim, PetscViewer viewer) 365 { 366 PetscViewerFormat format; 367 PetscErrorCode ierr; 368 369 PetscFunctionBegin; 370 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 371 ierr = PetscViewerASCIIPrintf(viewer, "Sin Slope Limiter:\n");CHKERRQ(ierr); 372 PetscFunctionReturn(0); 373 } 374 375 static PetscErrorCode PetscLimiterView_Sin(PetscLimiter lim, PetscViewer viewer) 376 { 377 PetscBool iascii; 378 PetscErrorCode ierr; 379 380 PetscFunctionBegin; 381 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 382 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 383 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 384 if (iascii) {ierr = PetscLimiterView_Sin_Ascii(lim, viewer);CHKERRQ(ierr);} 385 PetscFunctionReturn(0); 386 } 387 388 static PetscErrorCode PetscLimiterLimit_Sin(PetscLimiter lim, PetscReal f, PetscReal *phi) 389 { 390 PetscFunctionBegin; 391 *phi = PetscSinReal(PETSC_PI*PetscMax(0, PetscMin(f, 1))); 392 PetscFunctionReturn(0); 393 } 394 395 static PetscErrorCode PetscLimiterInitialize_Sin(PetscLimiter lim) 396 { 397 PetscFunctionBegin; 398 lim->ops->view = PetscLimiterView_Sin; 399 lim->ops->destroy = PetscLimiterDestroy_Sin; 400 lim->ops->limit = PetscLimiterLimit_Sin; 401 PetscFunctionReturn(0); 402 } 403 404 /*MC 405 PETSCLIMITERSIN = "sin" - A PetscLimiter object 406 407 Level: intermediate 408 409 .seealso: PetscLimiterType, PetscLimiterCreate(), PetscLimiterSetType() 410 M*/ 411 412 PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Sin(PetscLimiter lim) 413 { 414 PetscLimiter_Sin *l; 415 PetscErrorCode ierr; 416 417 PetscFunctionBegin; 418 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 419 ierr = PetscNewLog(lim, &l);CHKERRQ(ierr); 420 lim->data = l; 421 422 ierr = PetscLimiterInitialize_Sin(lim);CHKERRQ(ierr); 423 PetscFunctionReturn(0); 424 } 425 426 static PetscErrorCode PetscLimiterDestroy_Zero(PetscLimiter lim) 427 { 428 PetscLimiter_Zero *l = (PetscLimiter_Zero *) lim->data; 429 PetscErrorCode ierr; 430 431 PetscFunctionBegin; 432 ierr = PetscFree(l);CHKERRQ(ierr); 433 PetscFunctionReturn(0); 434 } 435 436 static PetscErrorCode PetscLimiterView_Zero_Ascii(PetscLimiter lim, PetscViewer viewer) 437 { 438 PetscViewerFormat format; 439 PetscErrorCode ierr; 440 441 PetscFunctionBegin; 442 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 443 ierr = PetscViewerASCIIPrintf(viewer, "Zero Slope Limiter:\n");CHKERRQ(ierr); 444 PetscFunctionReturn(0); 445 } 446 447 static PetscErrorCode PetscLimiterView_Zero(PetscLimiter lim, PetscViewer viewer) 448 { 449 PetscBool iascii; 450 PetscErrorCode ierr; 451 452 PetscFunctionBegin; 453 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 454 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 455 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 456 if (iascii) {ierr = PetscLimiterView_Zero_Ascii(lim, viewer);CHKERRQ(ierr);} 457 PetscFunctionReturn(0); 458 } 459 460 static PetscErrorCode PetscLimiterLimit_Zero(PetscLimiter lim, PetscReal f, PetscReal *phi) 461 { 462 PetscFunctionBegin; 463 *phi = 0.0; 464 PetscFunctionReturn(0); 465 } 466 467 static PetscErrorCode PetscLimiterInitialize_Zero(PetscLimiter lim) 468 { 469 PetscFunctionBegin; 470 lim->ops->view = PetscLimiterView_Zero; 471 lim->ops->destroy = PetscLimiterDestroy_Zero; 472 lim->ops->limit = PetscLimiterLimit_Zero; 473 PetscFunctionReturn(0); 474 } 475 476 /*MC 477 PETSCLIMITERZERO = "zero" - A PetscLimiter object 478 479 Level: intermediate 480 481 .seealso: PetscLimiterType, PetscLimiterCreate(), PetscLimiterSetType() 482 M*/ 483 484 PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Zero(PetscLimiter lim) 485 { 486 PetscLimiter_Zero *l; 487 PetscErrorCode ierr; 488 489 PetscFunctionBegin; 490 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 491 ierr = PetscNewLog(lim, &l);CHKERRQ(ierr); 492 lim->data = l; 493 494 ierr = PetscLimiterInitialize_Zero(lim);CHKERRQ(ierr); 495 PetscFunctionReturn(0); 496 } 497 498 static PetscErrorCode PetscLimiterDestroy_None(PetscLimiter lim) 499 { 500 PetscLimiter_None *l = (PetscLimiter_None *) lim->data; 501 PetscErrorCode ierr; 502 503 PetscFunctionBegin; 504 ierr = PetscFree(l);CHKERRQ(ierr); 505 PetscFunctionReturn(0); 506 } 507 508 static PetscErrorCode PetscLimiterView_None_Ascii(PetscLimiter lim, PetscViewer viewer) 509 { 510 PetscViewerFormat format; 511 PetscErrorCode ierr; 512 513 PetscFunctionBegin; 514 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 515 ierr = PetscViewerASCIIPrintf(viewer, "None Slope Limiter:\n");CHKERRQ(ierr); 516 PetscFunctionReturn(0); 517 } 518 519 static PetscErrorCode PetscLimiterView_None(PetscLimiter lim, PetscViewer viewer) 520 { 521 PetscBool iascii; 522 PetscErrorCode ierr; 523 524 PetscFunctionBegin; 525 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 526 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 527 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 528 if (iascii) {ierr = PetscLimiterView_None_Ascii(lim, viewer);CHKERRQ(ierr);} 529 PetscFunctionReturn(0); 530 } 531 532 static PetscErrorCode PetscLimiterLimit_None(PetscLimiter lim, PetscReal f, PetscReal *phi) 533 { 534 PetscFunctionBegin; 535 *phi = 1.0; 536 PetscFunctionReturn(0); 537 } 538 539 static PetscErrorCode PetscLimiterInitialize_None(PetscLimiter lim) 540 { 541 PetscFunctionBegin; 542 lim->ops->view = PetscLimiterView_None; 543 lim->ops->destroy = PetscLimiterDestroy_None; 544 lim->ops->limit = PetscLimiterLimit_None; 545 PetscFunctionReturn(0); 546 } 547 548 /*MC 549 PETSCLIMITERNONE = "none" - A PetscLimiter object 550 551 Level: intermediate 552 553 .seealso: PetscLimiterType, PetscLimiterCreate(), PetscLimiterSetType() 554 M*/ 555 556 PETSC_EXTERN PetscErrorCode PetscLimiterCreate_None(PetscLimiter lim) 557 { 558 PetscLimiter_None *l; 559 PetscErrorCode ierr; 560 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 563 ierr = PetscNewLog(lim, &l);CHKERRQ(ierr); 564 lim->data = l; 565 566 ierr = PetscLimiterInitialize_None(lim);CHKERRQ(ierr); 567 PetscFunctionReturn(0); 568 } 569 570 static PetscErrorCode PetscLimiterDestroy_Minmod(PetscLimiter lim) 571 { 572 PetscLimiter_Minmod *l = (PetscLimiter_Minmod *) lim->data; 573 PetscErrorCode ierr; 574 575 PetscFunctionBegin; 576 ierr = PetscFree(l);CHKERRQ(ierr); 577 PetscFunctionReturn(0); 578 } 579 580 static PetscErrorCode PetscLimiterView_Minmod_Ascii(PetscLimiter lim, PetscViewer viewer) 581 { 582 PetscViewerFormat format; 583 PetscErrorCode ierr; 584 585 PetscFunctionBegin; 586 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 587 ierr = PetscViewerASCIIPrintf(viewer, "Minmod Slope Limiter:\n");CHKERRQ(ierr); 588 PetscFunctionReturn(0); 589 } 590 591 static PetscErrorCode PetscLimiterView_Minmod(PetscLimiter lim, PetscViewer viewer) 592 { 593 PetscBool iascii; 594 PetscErrorCode ierr; 595 596 PetscFunctionBegin; 597 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 598 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 599 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 600 if (iascii) {ierr = PetscLimiterView_Minmod_Ascii(lim, viewer);CHKERRQ(ierr);} 601 PetscFunctionReturn(0); 602 } 603 604 static PetscErrorCode PetscLimiterLimit_Minmod(PetscLimiter lim, PetscReal f, PetscReal *phi) 605 { 606 PetscFunctionBegin; 607 *phi = 2*PetscMax(0, PetscMin(f, 1-f)); 608 PetscFunctionReturn(0); 609 } 610 611 static PetscErrorCode PetscLimiterInitialize_Minmod(PetscLimiter lim) 612 { 613 PetscFunctionBegin; 614 lim->ops->view = PetscLimiterView_Minmod; 615 lim->ops->destroy = PetscLimiterDestroy_Minmod; 616 lim->ops->limit = PetscLimiterLimit_Minmod; 617 PetscFunctionReturn(0); 618 } 619 620 /*MC 621 PETSCLIMITERMINMOD = "minmod" - A PetscLimiter object 622 623 Level: intermediate 624 625 .seealso: PetscLimiterType, PetscLimiterCreate(), PetscLimiterSetType() 626 M*/ 627 628 PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Minmod(PetscLimiter lim) 629 { 630 PetscLimiter_Minmod *l; 631 PetscErrorCode ierr; 632 633 PetscFunctionBegin; 634 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 635 ierr = PetscNewLog(lim, &l);CHKERRQ(ierr); 636 lim->data = l; 637 638 ierr = PetscLimiterInitialize_Minmod(lim);CHKERRQ(ierr); 639 PetscFunctionReturn(0); 640 } 641 642 static PetscErrorCode PetscLimiterDestroy_VanLeer(PetscLimiter lim) 643 { 644 PetscLimiter_VanLeer *l = (PetscLimiter_VanLeer *) lim->data; 645 PetscErrorCode ierr; 646 647 PetscFunctionBegin; 648 ierr = PetscFree(l);CHKERRQ(ierr); 649 PetscFunctionReturn(0); 650 } 651 652 static PetscErrorCode PetscLimiterView_VanLeer_Ascii(PetscLimiter lim, PetscViewer viewer) 653 { 654 PetscViewerFormat format; 655 PetscErrorCode ierr; 656 657 PetscFunctionBegin; 658 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 659 ierr = PetscViewerASCIIPrintf(viewer, "Van Leer Slope Limiter:\n");CHKERRQ(ierr); 660 PetscFunctionReturn(0); 661 } 662 663 static PetscErrorCode PetscLimiterView_VanLeer(PetscLimiter lim, PetscViewer viewer) 664 { 665 PetscBool iascii; 666 PetscErrorCode ierr; 667 668 PetscFunctionBegin; 669 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 670 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 671 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 672 if (iascii) {ierr = PetscLimiterView_VanLeer_Ascii(lim, viewer);CHKERRQ(ierr);} 673 PetscFunctionReturn(0); 674 } 675 676 static PetscErrorCode PetscLimiterLimit_VanLeer(PetscLimiter lim, PetscReal f, PetscReal *phi) 677 { 678 PetscFunctionBegin; 679 *phi = PetscMax(0, 4*f*(1-f)); 680 PetscFunctionReturn(0); 681 } 682 683 static PetscErrorCode PetscLimiterInitialize_VanLeer(PetscLimiter lim) 684 { 685 PetscFunctionBegin; 686 lim->ops->view = PetscLimiterView_VanLeer; 687 lim->ops->destroy = PetscLimiterDestroy_VanLeer; 688 lim->ops->limit = PetscLimiterLimit_VanLeer; 689 PetscFunctionReturn(0); 690 } 691 692 /*MC 693 PETSCLIMITERVANLEER = "vanleer" - A PetscLimiter object 694 695 Level: intermediate 696 697 .seealso: PetscLimiterType, PetscLimiterCreate(), PetscLimiterSetType() 698 M*/ 699 700 PETSC_EXTERN PetscErrorCode PetscLimiterCreate_VanLeer(PetscLimiter lim) 701 { 702 PetscLimiter_VanLeer *l; 703 PetscErrorCode ierr; 704 705 PetscFunctionBegin; 706 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 707 ierr = PetscNewLog(lim, &l);CHKERRQ(ierr); 708 lim->data = l; 709 710 ierr = PetscLimiterInitialize_VanLeer(lim);CHKERRQ(ierr); 711 PetscFunctionReturn(0); 712 } 713 714 static PetscErrorCode PetscLimiterDestroy_VanAlbada(PetscLimiter lim) 715 { 716 PetscLimiter_VanAlbada *l = (PetscLimiter_VanAlbada *) lim->data; 717 PetscErrorCode ierr; 718 719 PetscFunctionBegin; 720 ierr = PetscFree(l);CHKERRQ(ierr); 721 PetscFunctionReturn(0); 722 } 723 724 static PetscErrorCode PetscLimiterView_VanAlbada_Ascii(PetscLimiter lim, PetscViewer viewer) 725 { 726 PetscViewerFormat format; 727 PetscErrorCode ierr; 728 729 PetscFunctionBegin; 730 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 731 ierr = PetscViewerASCIIPrintf(viewer, "Van Albada Slope Limiter:\n");CHKERRQ(ierr); 732 PetscFunctionReturn(0); 733 } 734 735 static PetscErrorCode PetscLimiterView_VanAlbada(PetscLimiter lim, PetscViewer viewer) 736 { 737 PetscBool iascii; 738 PetscErrorCode ierr; 739 740 PetscFunctionBegin; 741 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 742 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 743 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 744 if (iascii) {ierr = PetscLimiterView_VanAlbada_Ascii(lim, viewer);CHKERRQ(ierr);} 745 PetscFunctionReturn(0); 746 } 747 748 static PetscErrorCode PetscLimiterLimit_VanAlbada(PetscLimiter lim, PetscReal f, PetscReal *phi) 749 { 750 PetscFunctionBegin; 751 *phi = PetscMax(0, 2*f*(1-f) / (PetscSqr(f) + PetscSqr(1-f))); 752 PetscFunctionReturn(0); 753 } 754 755 static PetscErrorCode PetscLimiterInitialize_VanAlbada(PetscLimiter lim) 756 { 757 PetscFunctionBegin; 758 lim->ops->view = PetscLimiterView_VanAlbada; 759 lim->ops->destroy = PetscLimiterDestroy_VanAlbada; 760 lim->ops->limit = PetscLimiterLimit_VanAlbada; 761 PetscFunctionReturn(0); 762 } 763 764 /*MC 765 PETSCLIMITERVANALBADA = "vanalbada" - A PetscLimiter object 766 767 Level: intermediate 768 769 .seealso: PetscLimiterType, PetscLimiterCreate(), PetscLimiterSetType() 770 M*/ 771 772 PETSC_EXTERN PetscErrorCode PetscLimiterCreate_VanAlbada(PetscLimiter lim) 773 { 774 PetscLimiter_VanAlbada *l; 775 PetscErrorCode ierr; 776 777 PetscFunctionBegin; 778 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 779 ierr = PetscNewLog(lim, &l);CHKERRQ(ierr); 780 lim->data = l; 781 782 ierr = PetscLimiterInitialize_VanAlbada(lim);CHKERRQ(ierr); 783 PetscFunctionReturn(0); 784 } 785 786 static PetscErrorCode PetscLimiterDestroy_Superbee(PetscLimiter lim) 787 { 788 PetscLimiter_Superbee *l = (PetscLimiter_Superbee *) lim->data; 789 PetscErrorCode ierr; 790 791 PetscFunctionBegin; 792 ierr = PetscFree(l);CHKERRQ(ierr); 793 PetscFunctionReturn(0); 794 } 795 796 static PetscErrorCode PetscLimiterView_Superbee_Ascii(PetscLimiter lim, PetscViewer viewer) 797 { 798 PetscViewerFormat format; 799 PetscErrorCode ierr; 800 801 PetscFunctionBegin; 802 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 803 ierr = PetscViewerASCIIPrintf(viewer, "Superbee Slope Limiter:\n");CHKERRQ(ierr); 804 PetscFunctionReturn(0); 805 } 806 807 static PetscErrorCode PetscLimiterView_Superbee(PetscLimiter lim, PetscViewer viewer) 808 { 809 PetscBool iascii; 810 PetscErrorCode ierr; 811 812 PetscFunctionBegin; 813 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 814 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 815 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 816 if (iascii) {ierr = PetscLimiterView_Superbee_Ascii(lim, viewer);CHKERRQ(ierr);} 817 PetscFunctionReturn(0); 818 } 819 820 static PetscErrorCode PetscLimiterLimit_Superbee(PetscLimiter lim, PetscReal f, PetscReal *phi) 821 { 822 PetscFunctionBegin; 823 *phi = 4*PetscMax(0, PetscMin(f, 1-f)); 824 PetscFunctionReturn(0); 825 } 826 827 static PetscErrorCode PetscLimiterInitialize_Superbee(PetscLimiter lim) 828 { 829 PetscFunctionBegin; 830 lim->ops->view = PetscLimiterView_Superbee; 831 lim->ops->destroy = PetscLimiterDestroy_Superbee; 832 lim->ops->limit = PetscLimiterLimit_Superbee; 833 PetscFunctionReturn(0); 834 } 835 836 /*MC 837 PETSCLIMITERSUPERBEE = "superbee" - A PetscLimiter object 838 839 Level: intermediate 840 841 .seealso: PetscLimiterType, PetscLimiterCreate(), PetscLimiterSetType() 842 M*/ 843 844 PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Superbee(PetscLimiter lim) 845 { 846 PetscLimiter_Superbee *l; 847 PetscErrorCode ierr; 848 849 PetscFunctionBegin; 850 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 851 ierr = PetscNewLog(lim, &l);CHKERRQ(ierr); 852 lim->data = l; 853 854 ierr = PetscLimiterInitialize_Superbee(lim);CHKERRQ(ierr); 855 PetscFunctionReturn(0); 856 } 857 858 static PetscErrorCode PetscLimiterDestroy_MC(PetscLimiter lim) 859 { 860 PetscLimiter_MC *l = (PetscLimiter_MC *) lim->data; 861 PetscErrorCode ierr; 862 863 PetscFunctionBegin; 864 ierr = PetscFree(l);CHKERRQ(ierr); 865 PetscFunctionReturn(0); 866 } 867 868 static PetscErrorCode PetscLimiterView_MC_Ascii(PetscLimiter lim, PetscViewer viewer) 869 { 870 PetscViewerFormat format; 871 PetscErrorCode ierr; 872 873 PetscFunctionBegin; 874 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 875 ierr = PetscViewerASCIIPrintf(viewer, "MC Slope Limiter:\n");CHKERRQ(ierr); 876 PetscFunctionReturn(0); 877 } 878 879 static PetscErrorCode PetscLimiterView_MC(PetscLimiter lim, PetscViewer viewer) 880 { 881 PetscBool iascii; 882 PetscErrorCode ierr; 883 884 PetscFunctionBegin; 885 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 886 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 887 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 888 if (iascii) {ierr = PetscLimiterView_MC_Ascii(lim, viewer);CHKERRQ(ierr);} 889 PetscFunctionReturn(0); 890 } 891 892 /* aka Barth-Jespersen */ 893 static PetscErrorCode PetscLimiterLimit_MC(PetscLimiter lim, PetscReal f, PetscReal *phi) 894 { 895 PetscFunctionBegin; 896 *phi = PetscMin(1, 4*PetscMax(0, PetscMin(f, 1-f))); 897 PetscFunctionReturn(0); 898 } 899 900 static PetscErrorCode PetscLimiterInitialize_MC(PetscLimiter lim) 901 { 902 PetscFunctionBegin; 903 lim->ops->view = PetscLimiterView_MC; 904 lim->ops->destroy = PetscLimiterDestroy_MC; 905 lim->ops->limit = PetscLimiterLimit_MC; 906 PetscFunctionReturn(0); 907 } 908 909 /*MC 910 PETSCLIMITERMC = "mc" - A PetscLimiter object 911 912 Level: intermediate 913 914 .seealso: PetscLimiterType, PetscLimiterCreate(), PetscLimiterSetType() 915 M*/ 916 917 PETSC_EXTERN PetscErrorCode PetscLimiterCreate_MC(PetscLimiter lim) 918 { 919 PetscLimiter_MC *l; 920 PetscErrorCode ierr; 921 922 PetscFunctionBegin; 923 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1); 924 ierr = PetscNewLog(lim, &l);CHKERRQ(ierr); 925 lim->data = l; 926 927 ierr = PetscLimiterInitialize_MC(lim);CHKERRQ(ierr); 928 PetscFunctionReturn(0); 929 } 930 931 PetscClassId PETSCFV_CLASSID = 0; 932 933 PetscFunctionList PetscFVList = NULL; 934 PetscBool PetscFVRegisterAllCalled = PETSC_FALSE; 935 936 /*@C 937 PetscFVRegister - Adds a new PetscFV implementation 938 939 Not Collective 940 941 Input Parameters: 942 + name - The name of a new user-defined creation routine 943 - create_func - The creation routine itself 944 945 Notes: 946 PetscFVRegister() may be called multiple times to add several user-defined PetscFVs 947 948 Sample usage: 949 .vb 950 PetscFVRegister("my_fv", MyPetscFVCreate); 951 .ve 952 953 Then, your PetscFV type can be chosen with the procedural interface via 954 .vb 955 PetscFVCreate(MPI_Comm, PetscFV *); 956 PetscFVSetType(PetscFV, "my_fv"); 957 .ve 958 or at runtime via the option 959 .vb 960 -petscfv_type my_fv 961 .ve 962 963 Level: advanced 964 965 .seealso: PetscFVRegisterAll(), PetscFVRegisterDestroy() 966 967 @*/ 968 PetscErrorCode PetscFVRegister(const char sname[], PetscErrorCode (*function)(PetscFV)) 969 { 970 PetscErrorCode ierr; 971 972 PetscFunctionBegin; 973 ierr = PetscFunctionListAdd(&PetscFVList, sname, function);CHKERRQ(ierr); 974 PetscFunctionReturn(0); 975 } 976 977 /*@C 978 PetscFVSetType - Builds a particular PetscFV 979 980 Collective on fvm 981 982 Input Parameters: 983 + fvm - The PetscFV object 984 - name - The kind of FVM space 985 986 Options Database Key: 987 . -petscfv_type <type> - Sets the PetscFV type; use -help for a list of available types 988 989 Level: intermediate 990 991 .seealso: PetscFVGetType(), PetscFVCreate() 992 @*/ 993 PetscErrorCode PetscFVSetType(PetscFV fvm, PetscFVType name) 994 { 995 PetscErrorCode (*r)(PetscFV); 996 PetscBool match; 997 PetscErrorCode ierr; 998 999 PetscFunctionBegin; 1000 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1001 ierr = PetscObjectTypeCompare((PetscObject) fvm, name, &match);CHKERRQ(ierr); 1002 if (match) PetscFunctionReturn(0); 1003 1004 ierr = PetscFVRegisterAll();CHKERRQ(ierr); 1005 ierr = PetscFunctionListFind(PetscFVList, name, &r);CHKERRQ(ierr); 1006 if (!r) SETERRQ1(PetscObjectComm((PetscObject) fvm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscFV type: %s", name); 1007 1008 if (fvm->ops->destroy) { 1009 ierr = (*fvm->ops->destroy)(fvm);CHKERRQ(ierr); 1010 fvm->ops->destroy = NULL; 1011 } 1012 ierr = (*r)(fvm);CHKERRQ(ierr); 1013 ierr = PetscObjectChangeTypeName((PetscObject) fvm, name);CHKERRQ(ierr); 1014 PetscFunctionReturn(0); 1015 } 1016 1017 /*@C 1018 PetscFVGetType - Gets the PetscFV type name (as a string) from the object. 1019 1020 Not Collective 1021 1022 Input Parameter: 1023 . fvm - The PetscFV 1024 1025 Output Parameter: 1026 . name - The PetscFV type name 1027 1028 Level: intermediate 1029 1030 .seealso: PetscFVSetType(), PetscFVCreate() 1031 @*/ 1032 PetscErrorCode PetscFVGetType(PetscFV fvm, PetscFVType *name) 1033 { 1034 PetscErrorCode ierr; 1035 1036 PetscFunctionBegin; 1037 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1038 PetscValidPointer(name, 2); 1039 ierr = PetscFVRegisterAll();CHKERRQ(ierr); 1040 *name = ((PetscObject) fvm)->type_name; 1041 PetscFunctionReturn(0); 1042 } 1043 1044 /*@C 1045 PetscFVViewFromOptions - View from Options 1046 1047 Collective on PetscFV 1048 1049 Input Parameters: 1050 + A - the PetscFV object 1051 . obj - Optional object 1052 - name - command line option 1053 1054 Level: intermediate 1055 .seealso: PetscFV, PetscFVView, PetscObjectViewFromOptions(), PetscFVCreate() 1056 @*/ 1057 PetscErrorCode PetscFVViewFromOptions(PetscFV A,PetscObject obj,const char name[]) 1058 { 1059 PetscErrorCode ierr; 1060 1061 PetscFunctionBegin; 1062 PetscValidHeaderSpecific(A,PETSCFV_CLASSID,1); 1063 ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr); 1064 PetscFunctionReturn(0); 1065 } 1066 1067 /*@C 1068 PetscFVView - Views a PetscFV 1069 1070 Collective on fvm 1071 1072 Input Parameter: 1073 + fvm - the PetscFV object to view 1074 - v - the viewer 1075 1076 Level: beginner 1077 1078 .seealso: PetscFVDestroy() 1079 @*/ 1080 PetscErrorCode PetscFVView(PetscFV fvm, PetscViewer v) 1081 { 1082 PetscErrorCode ierr; 1083 1084 PetscFunctionBegin; 1085 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1086 if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) fvm), &v);CHKERRQ(ierr);} 1087 if (fvm->ops->view) {ierr = (*fvm->ops->view)(fvm, v);CHKERRQ(ierr);} 1088 PetscFunctionReturn(0); 1089 } 1090 1091 /*@ 1092 PetscFVSetFromOptions - sets parameters in a PetscFV from the options database 1093 1094 Collective on fvm 1095 1096 Input Parameter: 1097 . fvm - the PetscFV object to set options for 1098 1099 Options Database Key: 1100 . -petscfv_compute_gradients <bool> - Determines whether cell gradients are calculated 1101 1102 Level: intermediate 1103 1104 .seealso: PetscFVView() 1105 @*/ 1106 PetscErrorCode PetscFVSetFromOptions(PetscFV fvm) 1107 { 1108 const char *defaultType; 1109 char name[256]; 1110 PetscBool flg; 1111 PetscErrorCode ierr; 1112 1113 PetscFunctionBegin; 1114 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1115 if (!((PetscObject) fvm)->type_name) defaultType = PETSCFVUPWIND; 1116 else defaultType = ((PetscObject) fvm)->type_name; 1117 ierr = PetscFVRegisterAll();CHKERRQ(ierr); 1118 1119 ierr = PetscObjectOptionsBegin((PetscObject) fvm);CHKERRQ(ierr); 1120 ierr = PetscOptionsFList("-petscfv_type", "Finite volume discretization", "PetscFVSetType", PetscFVList, defaultType, name, 256, &flg);CHKERRQ(ierr); 1121 if (flg) { 1122 ierr = PetscFVSetType(fvm, name);CHKERRQ(ierr); 1123 } else if (!((PetscObject) fvm)->type_name) { 1124 ierr = PetscFVSetType(fvm, defaultType);CHKERRQ(ierr); 1125 1126 } 1127 ierr = PetscOptionsBool("-petscfv_compute_gradients", "Compute cell gradients", "PetscFVSetComputeGradients", fvm->computeGradients, &fvm->computeGradients, NULL);CHKERRQ(ierr); 1128 if (fvm->ops->setfromoptions) {ierr = (*fvm->ops->setfromoptions)(fvm);CHKERRQ(ierr);} 1129 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1130 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) fvm);CHKERRQ(ierr); 1131 ierr = PetscLimiterSetFromOptions(fvm->limiter);CHKERRQ(ierr); 1132 ierr = PetscOptionsEnd();CHKERRQ(ierr); 1133 ierr = PetscFVViewFromOptions(fvm, NULL, "-petscfv_view");CHKERRQ(ierr); 1134 PetscFunctionReturn(0); 1135 } 1136 1137 /*@ 1138 PetscFVSetUp - Construct data structures for the PetscFV 1139 1140 Collective on fvm 1141 1142 Input Parameter: 1143 . fvm - the PetscFV object to setup 1144 1145 Level: intermediate 1146 1147 .seealso: PetscFVView(), PetscFVDestroy() 1148 @*/ 1149 PetscErrorCode PetscFVSetUp(PetscFV fvm) 1150 { 1151 PetscErrorCode ierr; 1152 1153 PetscFunctionBegin; 1154 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1155 ierr = PetscLimiterSetUp(fvm->limiter);CHKERRQ(ierr); 1156 if (fvm->ops->setup) {ierr = (*fvm->ops->setup)(fvm);CHKERRQ(ierr);} 1157 PetscFunctionReturn(0); 1158 } 1159 1160 /*@ 1161 PetscFVDestroy - Destroys a PetscFV object 1162 1163 Collective on fvm 1164 1165 Input Parameter: 1166 . fvm - the PetscFV object to destroy 1167 1168 Level: beginner 1169 1170 .seealso: PetscFVView() 1171 @*/ 1172 PetscErrorCode PetscFVDestroy(PetscFV *fvm) 1173 { 1174 PetscInt i; 1175 PetscErrorCode ierr; 1176 1177 PetscFunctionBegin; 1178 if (!*fvm) PetscFunctionReturn(0); 1179 PetscValidHeaderSpecific((*fvm), PETSCFV_CLASSID, 1); 1180 1181 if (--((PetscObject)(*fvm))->refct > 0) {*fvm = 0; PetscFunctionReturn(0);} 1182 ((PetscObject) (*fvm))->refct = 0; 1183 1184 for (i = 0; i < (*fvm)->numComponents; i++) { 1185 ierr = PetscFree((*fvm)->componentNames[i]);CHKERRQ(ierr); 1186 } 1187 ierr = PetscFree((*fvm)->componentNames);CHKERRQ(ierr); 1188 ierr = PetscLimiterDestroy(&(*fvm)->limiter);CHKERRQ(ierr); 1189 ierr = PetscDualSpaceDestroy(&(*fvm)->dualSpace);CHKERRQ(ierr); 1190 ierr = PetscFree((*fvm)->fluxWork);CHKERRQ(ierr); 1191 ierr = PetscQuadratureDestroy(&(*fvm)->quadrature);CHKERRQ(ierr); 1192 ierr = PetscTabulationDestroy(&(*fvm)->T);CHKERRQ(ierr); 1193 1194 if ((*fvm)->ops->destroy) {ierr = (*(*fvm)->ops->destroy)(*fvm);CHKERRQ(ierr);} 1195 ierr = PetscHeaderDestroy(fvm);CHKERRQ(ierr); 1196 PetscFunctionReturn(0); 1197 } 1198 1199 /*@ 1200 PetscFVCreate - Creates an empty PetscFV object. The type can then be set with PetscFVSetType(). 1201 1202 Collective 1203 1204 Input Parameter: 1205 . comm - The communicator for the PetscFV object 1206 1207 Output Parameter: 1208 . fvm - The PetscFV object 1209 1210 Level: beginner 1211 1212 .seealso: PetscFVSetType(), PETSCFVUPWIND 1213 @*/ 1214 PetscErrorCode PetscFVCreate(MPI_Comm comm, PetscFV *fvm) 1215 { 1216 PetscFV f; 1217 PetscErrorCode ierr; 1218 1219 PetscFunctionBegin; 1220 PetscValidPointer(fvm, 2); 1221 *fvm = NULL; 1222 ierr = PetscFVInitializePackage();CHKERRQ(ierr); 1223 1224 ierr = PetscHeaderCreate(f, PETSCFV_CLASSID, "PetscFV", "Finite Volume", "PetscFV", comm, PetscFVDestroy, PetscFVView);CHKERRQ(ierr); 1225 ierr = PetscMemzero(f->ops, sizeof(struct _PetscFVOps));CHKERRQ(ierr); 1226 1227 ierr = PetscLimiterCreate(comm, &f->limiter);CHKERRQ(ierr); 1228 f->numComponents = 1; 1229 f->dim = 0; 1230 f->computeGradients = PETSC_FALSE; 1231 f->fluxWork = NULL; 1232 ierr = PetscCalloc1(f->numComponents,&f->componentNames);CHKERRQ(ierr); 1233 1234 *fvm = f; 1235 PetscFunctionReturn(0); 1236 } 1237 1238 /*@ 1239 PetscFVSetLimiter - Set the limiter object 1240 1241 Logically collective on fvm 1242 1243 Input Parameters: 1244 + fvm - the PetscFV object 1245 - lim - The PetscLimiter 1246 1247 Level: intermediate 1248 1249 .seealso: PetscFVGetLimiter() 1250 @*/ 1251 PetscErrorCode PetscFVSetLimiter(PetscFV fvm, PetscLimiter lim) 1252 { 1253 PetscErrorCode ierr; 1254 1255 PetscFunctionBegin; 1256 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1257 PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 2); 1258 ierr = PetscLimiterDestroy(&fvm->limiter);CHKERRQ(ierr); 1259 ierr = PetscObjectReference((PetscObject) lim);CHKERRQ(ierr); 1260 fvm->limiter = lim; 1261 PetscFunctionReturn(0); 1262 } 1263 1264 /*@ 1265 PetscFVGetLimiter - Get the limiter object 1266 1267 Not collective 1268 1269 Input Parameter: 1270 . fvm - the PetscFV object 1271 1272 Output Parameter: 1273 . lim - The PetscLimiter 1274 1275 Level: intermediate 1276 1277 .seealso: PetscFVSetLimiter() 1278 @*/ 1279 PetscErrorCode PetscFVGetLimiter(PetscFV fvm, PetscLimiter *lim) 1280 { 1281 PetscFunctionBegin; 1282 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1283 PetscValidPointer(lim, 2); 1284 *lim = fvm->limiter; 1285 PetscFunctionReturn(0); 1286 } 1287 1288 /*@ 1289 PetscFVSetNumComponents - Set the number of field components 1290 1291 Logically collective on fvm 1292 1293 Input Parameters: 1294 + fvm - the PetscFV object 1295 - comp - The number of components 1296 1297 Level: intermediate 1298 1299 .seealso: PetscFVGetNumComponents() 1300 @*/ 1301 PetscErrorCode PetscFVSetNumComponents(PetscFV fvm, PetscInt comp) 1302 { 1303 PetscErrorCode ierr; 1304 1305 PetscFunctionBegin; 1306 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1307 if (fvm->numComponents != comp) { 1308 PetscInt i; 1309 1310 for (i = 0; i < fvm->numComponents; i++) { 1311 ierr = PetscFree(fvm->componentNames[i]);CHKERRQ(ierr); 1312 } 1313 ierr = PetscFree(fvm->componentNames);CHKERRQ(ierr); 1314 ierr = PetscCalloc1(comp,&fvm->componentNames);CHKERRQ(ierr); 1315 } 1316 fvm->numComponents = comp; 1317 ierr = PetscFree(fvm->fluxWork);CHKERRQ(ierr); 1318 ierr = PetscMalloc1(comp, &fvm->fluxWork);CHKERRQ(ierr); 1319 PetscFunctionReturn(0); 1320 } 1321 1322 /*@ 1323 PetscFVGetNumComponents - Get the number of field components 1324 1325 Not collective 1326 1327 Input Parameter: 1328 . fvm - the PetscFV object 1329 1330 Output Parameter: 1331 , comp - The number of components 1332 1333 Level: intermediate 1334 1335 .seealso: PetscFVSetNumComponents() 1336 @*/ 1337 PetscErrorCode PetscFVGetNumComponents(PetscFV fvm, PetscInt *comp) 1338 { 1339 PetscFunctionBegin; 1340 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1341 PetscValidPointer(comp, 2); 1342 *comp = fvm->numComponents; 1343 PetscFunctionReturn(0); 1344 } 1345 1346 /*@C 1347 PetscFVSetComponentName - Set the name of a component (used in output and viewing) 1348 1349 Logically collective on fvm 1350 Input Parameters: 1351 + fvm - the PetscFV object 1352 . comp - the component number 1353 - name - the component name 1354 1355 Level: intermediate 1356 1357 .seealso: PetscFVGetComponentName() 1358 @*/ 1359 PetscErrorCode PetscFVSetComponentName(PetscFV fvm, PetscInt comp, const char *name) 1360 { 1361 PetscErrorCode ierr; 1362 1363 PetscFunctionBegin; 1364 ierr = PetscFree(fvm->componentNames[comp]);CHKERRQ(ierr); 1365 ierr = PetscStrallocpy(name,&fvm->componentNames[comp]);CHKERRQ(ierr); 1366 PetscFunctionReturn(0); 1367 } 1368 1369 /*@C 1370 PetscFVGetComponentName - Get the name of a component (used in output and viewing) 1371 1372 Logically collective on fvm 1373 Input Parameters: 1374 + fvm - the PetscFV object 1375 - comp - the component number 1376 1377 Output Parameter: 1378 . name - the component name 1379 1380 Level: intermediate 1381 1382 .seealso: PetscFVSetComponentName() 1383 @*/ 1384 PetscErrorCode PetscFVGetComponentName(PetscFV fvm, PetscInt comp, const char **name) 1385 { 1386 PetscFunctionBegin; 1387 *name = fvm->componentNames[comp]; 1388 PetscFunctionReturn(0); 1389 } 1390 1391 /*@ 1392 PetscFVSetSpatialDimension - Set the spatial dimension 1393 1394 Logically collective on fvm 1395 1396 Input Parameters: 1397 + fvm - the PetscFV object 1398 - dim - The spatial dimension 1399 1400 Level: intermediate 1401 1402 .seealso: PetscFVGetSpatialDimension() 1403 @*/ 1404 PetscErrorCode PetscFVSetSpatialDimension(PetscFV fvm, PetscInt dim) 1405 { 1406 PetscFunctionBegin; 1407 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1408 fvm->dim = dim; 1409 PetscFunctionReturn(0); 1410 } 1411 1412 /*@ 1413 PetscFVGetSpatialDimension - Get the spatial dimension 1414 1415 Logically collective on fvm 1416 1417 Input Parameter: 1418 . fvm - the PetscFV object 1419 1420 Output Parameter: 1421 . dim - The spatial dimension 1422 1423 Level: intermediate 1424 1425 .seealso: PetscFVSetSpatialDimension() 1426 @*/ 1427 PetscErrorCode PetscFVGetSpatialDimension(PetscFV fvm, PetscInt *dim) 1428 { 1429 PetscFunctionBegin; 1430 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1431 PetscValidPointer(dim, 2); 1432 *dim = fvm->dim; 1433 PetscFunctionReturn(0); 1434 } 1435 1436 /*@ 1437 PetscFVSetComputeGradients - Toggle computation of cell gradients 1438 1439 Logically collective on fvm 1440 1441 Input Parameters: 1442 + fvm - the PetscFV object 1443 - computeGradients - Flag to compute cell gradients 1444 1445 Level: intermediate 1446 1447 .seealso: PetscFVGetComputeGradients() 1448 @*/ 1449 PetscErrorCode PetscFVSetComputeGradients(PetscFV fvm, PetscBool computeGradients) 1450 { 1451 PetscFunctionBegin; 1452 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1453 fvm->computeGradients = computeGradients; 1454 PetscFunctionReturn(0); 1455 } 1456 1457 /*@ 1458 PetscFVGetComputeGradients - Return flag for computation of cell gradients 1459 1460 Not collective 1461 1462 Input Parameter: 1463 . fvm - the PetscFV object 1464 1465 Output Parameter: 1466 . computeGradients - Flag to compute cell gradients 1467 1468 Level: intermediate 1469 1470 .seealso: PetscFVSetComputeGradients() 1471 @*/ 1472 PetscErrorCode PetscFVGetComputeGradients(PetscFV fvm, PetscBool *computeGradients) 1473 { 1474 PetscFunctionBegin; 1475 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1476 PetscValidPointer(computeGradients, 2); 1477 *computeGradients = fvm->computeGradients; 1478 PetscFunctionReturn(0); 1479 } 1480 1481 /*@ 1482 PetscFVSetQuadrature - Set the quadrature object 1483 1484 Logically collective on fvm 1485 1486 Input Parameters: 1487 + fvm - the PetscFV object 1488 - q - The PetscQuadrature 1489 1490 Level: intermediate 1491 1492 .seealso: PetscFVGetQuadrature() 1493 @*/ 1494 PetscErrorCode PetscFVSetQuadrature(PetscFV fvm, PetscQuadrature q) 1495 { 1496 PetscErrorCode ierr; 1497 1498 PetscFunctionBegin; 1499 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1500 ierr = PetscQuadratureDestroy(&fvm->quadrature);CHKERRQ(ierr); 1501 ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr); 1502 fvm->quadrature = q; 1503 PetscFunctionReturn(0); 1504 } 1505 1506 /*@ 1507 PetscFVGetQuadrature - Get the quadrature object 1508 1509 Not collective 1510 1511 Input Parameter: 1512 . fvm - the PetscFV object 1513 1514 Output Parameter: 1515 . lim - The PetscQuadrature 1516 1517 Level: intermediate 1518 1519 .seealso: PetscFVSetQuadrature() 1520 @*/ 1521 PetscErrorCode PetscFVGetQuadrature(PetscFV fvm, PetscQuadrature *q) 1522 { 1523 PetscFunctionBegin; 1524 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1525 PetscValidPointer(q, 2); 1526 if (!fvm->quadrature) { 1527 /* Create default 1-point quadrature */ 1528 PetscReal *points, *weights; 1529 PetscErrorCode ierr; 1530 1531 ierr = PetscQuadratureCreate(PETSC_COMM_SELF, &fvm->quadrature);CHKERRQ(ierr); 1532 ierr = PetscCalloc1(fvm->dim, &points);CHKERRQ(ierr); 1533 ierr = PetscMalloc1(1, &weights);CHKERRQ(ierr); 1534 weights[0] = 1.0; 1535 ierr = PetscQuadratureSetData(fvm->quadrature, fvm->dim, 1, 1, points, weights);CHKERRQ(ierr); 1536 } 1537 *q = fvm->quadrature; 1538 PetscFunctionReturn(0); 1539 } 1540 1541 /*@ 1542 PetscFVGetDualSpace - Returns the PetscDualSpace used to define the inner product 1543 1544 Not collective 1545 1546 Input Parameter: 1547 . fvm - The PetscFV object 1548 1549 Output Parameter: 1550 . sp - The PetscDualSpace object 1551 1552 Note: A simple dual space is provided automatically, and the user typically will not need to override it. 1553 1554 Level: intermediate 1555 1556 .seealso: PetscFVCreate() 1557 @*/ 1558 PetscErrorCode PetscFVGetDualSpace(PetscFV fvm, PetscDualSpace *sp) 1559 { 1560 PetscFunctionBegin; 1561 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1562 PetscValidPointer(sp, 2); 1563 if (!fvm->dualSpace) { 1564 DM K; 1565 PetscInt dim, Nc, c; 1566 PetscErrorCode ierr; 1567 1568 ierr = PetscFVGetSpatialDimension(fvm, &dim);CHKERRQ(ierr); 1569 ierr = PetscFVGetNumComponents(fvm, &Nc);CHKERRQ(ierr); 1570 ierr = PetscDualSpaceCreate(PetscObjectComm((PetscObject) fvm), &fvm->dualSpace);CHKERRQ(ierr); 1571 ierr = PetscDualSpaceSetType(fvm->dualSpace, PETSCDUALSPACESIMPLE);CHKERRQ(ierr); 1572 ierr = PetscDualSpaceCreateReferenceCell(fvm->dualSpace, dim, PETSC_FALSE, &K);CHKERRQ(ierr); /* TODO: The reference cell type should be held by the discretization object */ 1573 ierr = PetscDualSpaceSetNumComponents(fvm->dualSpace, Nc);CHKERRQ(ierr); 1574 ierr = PetscDualSpaceSetDM(fvm->dualSpace, K);CHKERRQ(ierr); 1575 ierr = DMDestroy(&K);CHKERRQ(ierr); 1576 ierr = PetscDualSpaceSimpleSetDimension(fvm->dualSpace, Nc);CHKERRQ(ierr); 1577 /* Should we be using PetscFVGetQuadrature() here? */ 1578 for (c = 0; c < Nc; ++c) { 1579 PetscQuadrature qc; 1580 PetscReal *points, *weights; 1581 PetscErrorCode ierr; 1582 1583 ierr = PetscQuadratureCreate(PETSC_COMM_SELF, &qc);CHKERRQ(ierr); 1584 ierr = PetscCalloc1(dim, &points);CHKERRQ(ierr); 1585 ierr = PetscCalloc1(Nc, &weights);CHKERRQ(ierr); 1586 weights[c] = 1.0; 1587 ierr = PetscQuadratureSetData(qc, dim, Nc, 1, points, weights);CHKERRQ(ierr); 1588 ierr = PetscDualSpaceSimpleSetFunctional(fvm->dualSpace, c, qc);CHKERRQ(ierr); 1589 ierr = PetscQuadratureDestroy(&qc);CHKERRQ(ierr); 1590 } 1591 } 1592 *sp = fvm->dualSpace; 1593 PetscFunctionReturn(0); 1594 } 1595 1596 /*@ 1597 PetscFVSetDualSpace - Sets the PetscDualSpace used to define the inner product 1598 1599 Not collective 1600 1601 Input Parameters: 1602 + fvm - The PetscFV object 1603 - sp - The PetscDualSpace object 1604 1605 Level: intermediate 1606 1607 Note: A simple dual space is provided automatically, and the user typically will not need to override it. 1608 1609 .seealso: PetscFVCreate() 1610 @*/ 1611 PetscErrorCode PetscFVSetDualSpace(PetscFV fvm, PetscDualSpace sp) 1612 { 1613 PetscErrorCode ierr; 1614 1615 PetscFunctionBegin; 1616 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1617 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2); 1618 ierr = PetscDualSpaceDestroy(&fvm->dualSpace);CHKERRQ(ierr); 1619 fvm->dualSpace = sp; 1620 ierr = PetscObjectReference((PetscObject) fvm->dualSpace);CHKERRQ(ierr); 1621 PetscFunctionReturn(0); 1622 } 1623 1624 /*@C 1625 PetscFVGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points 1626 1627 Not collective 1628 1629 Input Parameter: 1630 . fvm - The PetscFV object 1631 1632 Output Parameter: 1633 . T - The basis function values and derviatives at quadrature points 1634 1635 Note: 1636 $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c 1637 $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d 1638 $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e 1639 1640 Level: intermediate 1641 1642 .seealso: PetscFEGetCellTabulation(), PetscFVCreateTabulation(), PetscFVGetQuadrature(), PetscQuadratureGetData() 1643 @*/ 1644 PetscErrorCode PetscFVGetCellTabulation(PetscFV fvm, PetscTabulation *T) 1645 { 1646 PetscInt npoints; 1647 const PetscReal *points; 1648 PetscErrorCode ierr; 1649 1650 PetscFunctionBegin; 1651 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1652 PetscValidPointer(T, 2); 1653 ierr = PetscQuadratureGetData(fvm->quadrature, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr); 1654 if (!fvm->T) {ierr = PetscFVCreateTabulation(fvm, 1, npoints, points, 1, &fvm->T);CHKERRQ(ierr);} 1655 *T = fvm->T; 1656 PetscFunctionReturn(0); 1657 } 1658 1659 /*@C 1660 PetscFVCreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided. 1661 1662 Not collective 1663 1664 Input Parameters: 1665 + fvm - The PetscFV object 1666 . nrepl - The number of replicas 1667 . npoints - The number of tabulation points in a replica 1668 . points - The tabulation point coordinates 1669 - K - The order of derivative to tabulate 1670 1671 Output Parameter: 1672 . T - The basis function values and derviative at tabulation points 1673 1674 Note: 1675 $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c 1676 $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d 1677 $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e 1678 1679 Level: intermediate 1680 1681 .seealso: PetscFECreateTabulation(), PetscTabulationDestroy(), PetscFEGetCellTabulation() 1682 @*/ 1683 PetscErrorCode PetscFVCreateTabulation(PetscFV fvm, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T) 1684 { 1685 PetscInt pdim = 1; /* Dimension of approximation space P */ 1686 PetscInt cdim; /* Spatial dimension */ 1687 PetscInt Nc; /* Field components */ 1688 PetscInt k, p, d, c, e; 1689 PetscErrorCode ierr; 1690 1691 PetscFunctionBegin; 1692 if (!npoints || K < 0) { 1693 *T = NULL; 1694 PetscFunctionReturn(0); 1695 } 1696 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1697 PetscValidPointer(points, 4); 1698 PetscValidPointer(T, 6); 1699 ierr = PetscFVGetSpatialDimension(fvm, &cdim);CHKERRQ(ierr); 1700 ierr = PetscFVGetNumComponents(fvm, &Nc);CHKERRQ(ierr); 1701 ierr = PetscMalloc1(1, T);CHKERRQ(ierr); 1702 (*T)->K = !cdim ? 0 : K; 1703 (*T)->Nr = nrepl; 1704 (*T)->Np = npoints; 1705 (*T)->Nb = pdim; 1706 (*T)->Nc = Nc; 1707 (*T)->cdim = cdim; 1708 ierr = PetscMalloc1((*T)->K+1, &(*T)->T);CHKERRQ(ierr); 1709 for (k = 0; k <= (*T)->K; ++k) { 1710 ierr = PetscMalloc1(nrepl*npoints*pdim*Nc*PetscPowInt(cdim, k), &(*T)->T[k]);CHKERRQ(ierr); 1711 } 1712 if (K >= 0) {for (p = 0; p < nrepl*npoints; ++p) for (d = 0; d < pdim; ++d) for (c = 0; c < Nc; ++c) (*T)->T[0][(p*pdim + d)*Nc + c] = 1.0;} 1713 if (K >= 1) {for (p = 0; p < nrepl*npoints; ++p) for (d = 0; d < pdim; ++d) for (c = 0; c < Nc; ++c) for (e = 0; e < cdim; ++e) (*T)->T[1][((p*pdim + d)*Nc + c)*cdim + e] = 0.0;} 1714 if (K >= 2) {for (p = 0; p < nrepl*npoints; ++p) for (d = 0; d < pdim; ++d) for (c = 0; c < Nc; ++c) for (e = 0; e < cdim*cdim; ++e) (*T)->T[2][((p*pdim + d)*Nc + c)*cdim*cdim + e] = 0.0;} 1715 PetscFunctionReturn(0); 1716 } 1717 1718 /*@C 1719 PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell 1720 1721 Input Parameters: 1722 + fvm - The PetscFV object 1723 . numFaces - The number of cell faces which are not constrained 1724 - dx - The vector from the cell centroid to the neighboring cell centroid for each face 1725 1726 Level: advanced 1727 1728 .seealso: PetscFVCreate() 1729 @*/ 1730 PetscErrorCode PetscFVComputeGradient(PetscFV fvm, PetscInt numFaces, PetscScalar dx[], PetscScalar grad[]) 1731 { 1732 PetscErrorCode ierr; 1733 1734 PetscFunctionBegin; 1735 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1736 if (fvm->ops->computegradient) {ierr = (*fvm->ops->computegradient)(fvm, numFaces, dx, grad);CHKERRQ(ierr);} 1737 PetscFunctionReturn(0); 1738 } 1739 1740 /*@C 1741 PetscFVIntegrateRHSFunction - Produce the cell residual vector for a chunk of elements by quadrature integration 1742 1743 Not collective 1744 1745 Input Parameters: 1746 + fvm - The PetscFV object for the field being integrated 1747 . prob - The PetscDS specifing the discretizations and continuum functions 1748 . field - The field being integrated 1749 . Nf - The number of faces in the chunk 1750 . fgeom - The face geometry for each face in the chunk 1751 . neighborVol - The volume for each pair of cells in the chunk 1752 . uL - The state from the cell on the left 1753 - uR - The state from the cell on the right 1754 1755 Output Parameter 1756 + fluxL - the left fluxes for each face 1757 - fluxR - the right fluxes for each face 1758 1759 Level: developer 1760 1761 .seealso: PetscFVCreate() 1762 @*/ 1763 PetscErrorCode PetscFVIntegrateRHSFunction(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, 1764 PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[]) 1765 { 1766 PetscErrorCode ierr; 1767 1768 PetscFunctionBegin; 1769 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1770 if (fvm->ops->integraterhsfunction) {ierr = (*fvm->ops->integraterhsfunction)(fvm, prob, field, Nf, fgeom, neighborVol, uL, uR, fluxL, fluxR);CHKERRQ(ierr);} 1771 PetscFunctionReturn(0); 1772 } 1773 1774 /*@ 1775 PetscFVRefine - Create a "refined" PetscFV object that refines the reference cell into smaller copies. This is typically used 1776 to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more 1777 sparsity). It is also used to create an interpolation between regularly refined meshes. 1778 1779 Input Parameter: 1780 . fv - The initial PetscFV 1781 1782 Output Parameter: 1783 . fvRef - The refined PetscFV 1784 1785 Level: advanced 1786 1787 .seealso: PetscFVType, PetscFVCreate(), PetscFVSetType() 1788 @*/ 1789 PetscErrorCode PetscFVRefine(PetscFV fv, PetscFV *fvRef) 1790 { 1791 PetscDualSpace Q, Qref; 1792 DM K, Kref; 1793 PetscQuadrature q, qref; 1794 CellRefiner cellRefiner; 1795 PetscReal *v0; 1796 PetscReal *jac, *invjac; 1797 PetscInt numComp, numSubelements, s; 1798 PetscErrorCode ierr; 1799 1800 PetscFunctionBegin; 1801 ierr = PetscFVGetDualSpace(fv, &Q);CHKERRQ(ierr); 1802 ierr = PetscFVGetQuadrature(fv, &q);CHKERRQ(ierr); 1803 ierr = PetscDualSpaceGetDM(Q, &K);CHKERRQ(ierr); 1804 /* Create dual space */ 1805 ierr = PetscDualSpaceDuplicate(Q, &Qref);CHKERRQ(ierr); 1806 ierr = DMRefine(K, PetscObjectComm((PetscObject) fv), &Kref);CHKERRQ(ierr); 1807 ierr = PetscDualSpaceSetDM(Qref, Kref);CHKERRQ(ierr); 1808 ierr = DMDestroy(&Kref);CHKERRQ(ierr); 1809 ierr = PetscDualSpaceSetUp(Qref);CHKERRQ(ierr); 1810 /* Create volume */ 1811 ierr = PetscFVCreate(PetscObjectComm((PetscObject) fv), fvRef);CHKERRQ(ierr); 1812 ierr = PetscFVSetDualSpace(*fvRef, Qref);CHKERRQ(ierr); 1813 ierr = PetscFVGetNumComponents(fv, &numComp);CHKERRQ(ierr); 1814 ierr = PetscFVSetNumComponents(*fvRef, numComp);CHKERRQ(ierr); 1815 ierr = PetscFVSetUp(*fvRef);CHKERRQ(ierr); 1816 /* Create quadrature */ 1817 ierr = DMPlexGetCellRefiner_Internal(K, &cellRefiner);CHKERRQ(ierr); 1818 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubelements, &v0, &jac, &invjac);CHKERRQ(ierr); 1819 ierr = PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref);CHKERRQ(ierr); 1820 ierr = PetscDualSpaceSimpleSetDimension(Qref, numSubelements);CHKERRQ(ierr); 1821 for (s = 0; s < numSubelements; ++s) { 1822 PetscQuadrature qs; 1823 const PetscReal *points, *weights; 1824 PetscReal *p, *w; 1825 PetscInt dim, Nc, npoints, np; 1826 1827 ierr = PetscQuadratureCreate(PETSC_COMM_SELF, &qs);CHKERRQ(ierr); 1828 ierr = PetscQuadratureGetData(q, &dim, &Nc, &npoints, &points, &weights);CHKERRQ(ierr); 1829 np = npoints/numSubelements; 1830 ierr = PetscMalloc1(np*dim,&p);CHKERRQ(ierr); 1831 ierr = PetscMalloc1(np*Nc,&w);CHKERRQ(ierr); 1832 ierr = PetscArraycpy(p, &points[s*np*dim], np*dim);CHKERRQ(ierr); 1833 ierr = PetscArraycpy(w, &weights[s*np*Nc], np*Nc);CHKERRQ(ierr); 1834 ierr = PetscQuadratureSetData(qs, dim, Nc, np, p, w);CHKERRQ(ierr); 1835 ierr = PetscDualSpaceSimpleSetFunctional(Qref, s, qs);CHKERRQ(ierr); 1836 ierr = PetscQuadratureDestroy(&qs);CHKERRQ(ierr); 1837 } 1838 ierr = CellRefinerRestoreAffineTransforms_Internal(cellRefiner, &numSubelements, &v0, &jac, &invjac);CHKERRQ(ierr); 1839 ierr = PetscFVSetQuadrature(*fvRef, qref);CHKERRQ(ierr); 1840 ierr = PetscQuadratureDestroy(&qref);CHKERRQ(ierr); 1841 ierr = PetscDualSpaceDestroy(&Qref);CHKERRQ(ierr); 1842 PetscFunctionReturn(0); 1843 } 1844 1845 static PetscErrorCode PetscFVDestroy_Upwind(PetscFV fvm) 1846 { 1847 PetscFV_Upwind *b = (PetscFV_Upwind *) fvm->data; 1848 PetscErrorCode ierr; 1849 1850 PetscFunctionBegin; 1851 ierr = PetscFree(b);CHKERRQ(ierr); 1852 PetscFunctionReturn(0); 1853 } 1854 1855 static PetscErrorCode PetscFVView_Upwind_Ascii(PetscFV fv, PetscViewer viewer) 1856 { 1857 PetscInt Nc, c; 1858 PetscViewerFormat format; 1859 PetscErrorCode ierr; 1860 1861 PetscFunctionBegin; 1862 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 1863 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1864 ierr = PetscViewerASCIIPrintf(viewer, "Upwind Finite Volume:\n");CHKERRQ(ierr); 1865 ierr = PetscViewerASCIIPrintf(viewer, " num components: %d\n", Nc);CHKERRQ(ierr); 1866 for (c = 0; c < Nc; c++) { 1867 if (fv->componentNames[c]) { 1868 ierr = PetscViewerASCIIPrintf(viewer, " component %d: %s\n", c, fv->componentNames[c]);CHKERRQ(ierr); 1869 } 1870 } 1871 PetscFunctionReturn(0); 1872 } 1873 1874 static PetscErrorCode PetscFVView_Upwind(PetscFV fv, PetscViewer viewer) 1875 { 1876 PetscBool iascii; 1877 PetscErrorCode ierr; 1878 1879 PetscFunctionBegin; 1880 PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1); 1881 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1882 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1883 if (iascii) {ierr = PetscFVView_Upwind_Ascii(fv, viewer);CHKERRQ(ierr);} 1884 PetscFunctionReturn(0); 1885 } 1886 1887 static PetscErrorCode PetscFVSetUp_Upwind(PetscFV fvm) 1888 { 1889 PetscFunctionBegin; 1890 PetscFunctionReturn(0); 1891 } 1892 1893 /* 1894 neighborVol[f*2+0] contains the left geom 1895 neighborVol[f*2+1] contains the right geom 1896 */ 1897 static PetscErrorCode PetscFVIntegrateRHSFunction_Upwind(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, 1898 PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[]) 1899 { 1900 void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *); 1901 void *rctx; 1902 PetscScalar *flux = fvm->fluxWork; 1903 const PetscScalar *constants; 1904 PetscInt dim, numConstants, pdim, totDim, Nc, off, f, d; 1905 PetscErrorCode ierr; 1906 1907 PetscFunctionBegin; 1908 ierr = PetscDSGetTotalComponents(prob, &Nc);CHKERRQ(ierr); 1909 ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 1910 ierr = PetscDSGetFieldOffset(prob, field, &off);CHKERRQ(ierr); 1911 ierr = PetscDSGetRiemannSolver(prob, field, &riemann);CHKERRQ(ierr); 1912 ierr = PetscDSGetContext(prob, field, &rctx);CHKERRQ(ierr); 1913 ierr = PetscDSGetConstants(prob, &numConstants, &constants);CHKERRQ(ierr); 1914 ierr = PetscFVGetSpatialDimension(fvm, &dim);CHKERRQ(ierr); 1915 ierr = PetscFVGetNumComponents(fvm, &pdim);CHKERRQ(ierr); 1916 for (f = 0; f < Nf; ++f) { 1917 (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f*Nc], &uR[f*Nc], numConstants, constants, flux, rctx); 1918 for (d = 0; d < pdim; ++d) { 1919 fluxL[f*totDim+off+d] = flux[d] / neighborVol[f*2+0]; 1920 fluxR[f*totDim+off+d] = flux[d] / neighborVol[f*2+1]; 1921 } 1922 } 1923 PetscFunctionReturn(0); 1924 } 1925 1926 static PetscErrorCode PetscFVInitialize_Upwind(PetscFV fvm) 1927 { 1928 PetscFunctionBegin; 1929 fvm->ops->setfromoptions = NULL; 1930 fvm->ops->setup = PetscFVSetUp_Upwind; 1931 fvm->ops->view = PetscFVView_Upwind; 1932 fvm->ops->destroy = PetscFVDestroy_Upwind; 1933 fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_Upwind; 1934 PetscFunctionReturn(0); 1935 } 1936 1937 /*MC 1938 PETSCFVUPWIND = "upwind" - A PetscFV object 1939 1940 Level: intermediate 1941 1942 .seealso: PetscFVType, PetscFVCreate(), PetscFVSetType() 1943 M*/ 1944 1945 PETSC_EXTERN PetscErrorCode PetscFVCreate_Upwind(PetscFV fvm) 1946 { 1947 PetscFV_Upwind *b; 1948 PetscErrorCode ierr; 1949 1950 PetscFunctionBegin; 1951 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 1952 ierr = PetscNewLog(fvm,&b);CHKERRQ(ierr); 1953 fvm->data = b; 1954 1955 ierr = PetscFVInitialize_Upwind(fvm);CHKERRQ(ierr); 1956 PetscFunctionReturn(0); 1957 } 1958 1959 #include <petscblaslapack.h> 1960 1961 static PetscErrorCode PetscFVDestroy_LeastSquares(PetscFV fvm) 1962 { 1963 PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *) fvm->data; 1964 PetscErrorCode ierr; 1965 1966 PetscFunctionBegin; 1967 ierr = PetscObjectComposeFunction((PetscObject) fvm, "PetscFVLeastSquaresSetMaxFaces_C", NULL);CHKERRQ(ierr); 1968 ierr = PetscFree4(ls->B, ls->Binv, ls->tau, ls->work);CHKERRQ(ierr); 1969 ierr = PetscFree(ls);CHKERRQ(ierr); 1970 PetscFunctionReturn(0); 1971 } 1972 1973 static PetscErrorCode PetscFVView_LeastSquares_Ascii(PetscFV fv, PetscViewer viewer) 1974 { 1975 PetscInt Nc, c; 1976 PetscViewerFormat format; 1977 PetscErrorCode ierr; 1978 1979 PetscFunctionBegin; 1980 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 1981 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1982 ierr = PetscViewerASCIIPrintf(viewer, "Finite Volume with Least Squares Reconstruction:\n");CHKERRQ(ierr); 1983 ierr = PetscViewerASCIIPrintf(viewer, " num components: %d\n", Nc);CHKERRQ(ierr); 1984 for (c = 0; c < Nc; c++) { 1985 if (fv->componentNames[c]) { 1986 ierr = PetscViewerASCIIPrintf(viewer, " component %d: %s\n", c, fv->componentNames[c]);CHKERRQ(ierr); 1987 } 1988 } 1989 PetscFunctionReturn(0); 1990 } 1991 1992 static PetscErrorCode PetscFVView_LeastSquares(PetscFV fv, PetscViewer viewer) 1993 { 1994 PetscBool iascii; 1995 PetscErrorCode ierr; 1996 1997 PetscFunctionBegin; 1998 PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1); 1999 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2000 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 2001 if (iascii) {ierr = PetscFVView_LeastSquares_Ascii(fv, viewer);CHKERRQ(ierr);} 2002 PetscFunctionReturn(0); 2003 } 2004 2005 static PetscErrorCode PetscFVSetUp_LeastSquares(PetscFV fvm) 2006 { 2007 PetscFunctionBegin; 2008 PetscFunctionReturn(0); 2009 } 2010 2011 /* Overwrites A. Can only handle full-rank problems with m>=n */ 2012 static PetscErrorCode PetscFVLeastSquaresPseudoInverse_Static(PetscInt m,PetscInt mstride,PetscInt n,PetscScalar *A,PetscScalar *Ainv,PetscScalar *tau,PetscInt worksize,PetscScalar *work) 2013 { 2014 PetscBool debug = PETSC_FALSE; 2015 PetscErrorCode ierr; 2016 PetscBLASInt M,N,K,lda,ldb,ldwork,info; 2017 PetscScalar *R,*Q,*Aback,Alpha; 2018 2019 PetscFunctionBegin; 2020 if (debug) { 2021 ierr = PetscMalloc1(m*n,&Aback);CHKERRQ(ierr); 2022 ierr = PetscArraycpy(Aback,A,m*n);CHKERRQ(ierr); 2023 } 2024 2025 ierr = PetscBLASIntCast(m,&M);CHKERRQ(ierr); 2026 ierr = PetscBLASIntCast(n,&N);CHKERRQ(ierr); 2027 ierr = PetscBLASIntCast(mstride,&lda);CHKERRQ(ierr); 2028 ierr = PetscBLASIntCast(worksize,&ldwork);CHKERRQ(ierr); 2029 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 2030 LAPACKgeqrf_(&M,&N,A,&lda,tau,work,&ldwork,&info); 2031 ierr = PetscFPTrapPop();CHKERRQ(ierr); 2032 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"xGEQRF error"); 2033 R = A; /* Upper triangular part of A now contains R, the rest contains the elementary reflectors */ 2034 2035 /* Extract an explicit representation of Q */ 2036 Q = Ainv; 2037 ierr = PetscArraycpy(Q,A,mstride*n);CHKERRQ(ierr); 2038 K = N; /* full rank */ 2039 PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&M,&N,&K,Q,&lda,tau,work,&ldwork,&info)); 2040 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"xORGQR/xUNGQR error"); 2041 2042 /* Compute A^{-T} = (R^{-1} Q^T)^T = Q R^{-T} */ 2043 Alpha = 1.0; 2044 ldb = lda; 2045 BLAStrsm_("Right","Upper","ConjugateTranspose","NotUnitTriangular",&M,&N,&Alpha,R,&lda,Q,&ldb); 2046 /* Ainv is Q, overwritten with inverse */ 2047 2048 if (debug) { /* Check that pseudo-inverse worked */ 2049 PetscScalar Beta = 0.0; 2050 PetscBLASInt ldc; 2051 K = N; 2052 ldc = N; 2053 BLASgemm_("ConjugateTranspose","Normal",&N,&K,&M,&Alpha,Ainv,&lda,Aback,&ldb,&Beta,work,&ldc); 2054 ierr = PetscScalarView(n*n,work,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 2055 ierr = PetscFree(Aback);CHKERRQ(ierr); 2056 } 2057 PetscFunctionReturn(0); 2058 } 2059 2060 /* Overwrites A. Can handle degenerate problems and m<n. */ 2061 static PetscErrorCode PetscFVLeastSquaresPseudoInverseSVD_Static(PetscInt m,PetscInt mstride,PetscInt n,PetscScalar *A,PetscScalar *Ainv,PetscScalar *tau,PetscInt worksize,PetscScalar *work) 2062 { 2063 PetscBool debug = PETSC_FALSE; 2064 PetscScalar *Brhs, *Aback; 2065 PetscScalar *tmpwork; 2066 PetscReal rcond; 2067 #if defined (PETSC_USE_COMPLEX) 2068 PetscInt rworkSize; 2069 PetscReal *rwork; 2070 #endif 2071 PetscInt i, j, maxmn; 2072 PetscBLASInt M, N, lda, ldb, ldwork; 2073 PetscBLASInt nrhs, irank, info; 2074 PetscErrorCode ierr; 2075 2076 PetscFunctionBegin; 2077 if (debug) { 2078 ierr = PetscMalloc1(m*n,&Aback);CHKERRQ(ierr); 2079 ierr = PetscArraycpy(Aback,A,m*n);CHKERRQ(ierr); 2080 } 2081 2082 /* initialize to identity */ 2083 tmpwork = Ainv; 2084 Brhs = work; 2085 maxmn = PetscMax(m,n); 2086 for (j=0; j<maxmn; j++) { 2087 for (i=0; i<maxmn; i++) Brhs[i + j*maxmn] = 1.0*(i == j); 2088 } 2089 2090 ierr = PetscBLASIntCast(m,&M);CHKERRQ(ierr); 2091 ierr = PetscBLASIntCast(n,&N);CHKERRQ(ierr); 2092 ierr = PetscBLASIntCast(mstride,&lda);CHKERRQ(ierr); 2093 ierr = PetscBLASIntCast(maxmn,&ldb);CHKERRQ(ierr); 2094 ierr = PetscBLASIntCast(worksize,&ldwork);CHKERRQ(ierr); 2095 rcond = -1; 2096 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 2097 nrhs = M; 2098 #if defined(PETSC_USE_COMPLEX) 2099 rworkSize = 5 * PetscMin(M,N); 2100 ierr = PetscMalloc1(rworkSize,&rwork);CHKERRQ(ierr); 2101 LAPACKgelss_(&M,&N,&nrhs,A,&lda,Brhs,&ldb, (PetscReal *) tau,&rcond,&irank,tmpwork,&ldwork,rwork,&info); 2102 ierr = PetscFPTrapPop();CHKERRQ(ierr); 2103 ierr = PetscFree(rwork);CHKERRQ(ierr); 2104 #else 2105 nrhs = M; 2106 LAPACKgelss_(&M,&N,&nrhs,A,&lda,Brhs,&ldb, (PetscReal *) tau,&rcond,&irank,tmpwork,&ldwork,&info); 2107 ierr = PetscFPTrapPop();CHKERRQ(ierr); 2108 #endif 2109 if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"xGELSS error"); 2110 /* The following check should be turned into a diagnostic as soon as someone wants to do this intentionally */ 2111 if (irank < PetscMin(M,N)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Rank deficient least squares fit, indicates an isolated cell with two colinear points"); 2112 2113 /* Brhs shaped (M,nrhs) column-major coldim=mstride was overwritten by Ainv shaped (N,nrhs) column-major coldim=maxmn. 2114 * Here we transpose to (N,nrhs) row-major rowdim=mstride. */ 2115 for (i=0; i<n; i++) { 2116 for (j=0; j<nrhs; j++) Ainv[i*mstride+j] = Brhs[i + j*maxmn]; 2117 } 2118 PetscFunctionReturn(0); 2119 } 2120 2121 #if 0 2122 static PetscErrorCode PetscFVLeastSquaresDebugCell_Static(PetscFV fvm, PetscInt cell, DM dm, DM dmFace, PetscScalar *fgeom, DM dmCell, PetscScalar *cgeom) 2123 { 2124 PetscReal grad[2] = {0, 0}; 2125 const PetscInt *faces; 2126 PetscInt numFaces, f; 2127 PetscErrorCode ierr; 2128 2129 PetscFunctionBegin; 2130 ierr = DMPlexGetConeSize(dm, cell, &numFaces);CHKERRQ(ierr); 2131 ierr = DMPlexGetCone(dm, cell, &faces);CHKERRQ(ierr); 2132 for (f = 0; f < numFaces; ++f) { 2133 const PetscInt *fcells; 2134 const CellGeom *cg1; 2135 const FaceGeom *fg; 2136 2137 ierr = DMPlexGetSupport(dm, faces[f], &fcells);CHKERRQ(ierr); 2138 ierr = DMPlexPointLocalRead(dmFace, faces[f], fgeom, &fg);CHKERRQ(ierr); 2139 for (i = 0; i < 2; ++i) { 2140 PetscScalar du; 2141 2142 if (fcells[i] == c) continue; 2143 ierr = DMPlexPointLocalRead(dmCell, fcells[i], cgeom, &cg1);CHKERRQ(ierr); 2144 du = cg1->centroid[0] + 3*cg1->centroid[1] - (cg->centroid[0] + 3*cg->centroid[1]); 2145 grad[0] += fg->grad[!i][0] * du; 2146 grad[1] += fg->grad[!i][1] * du; 2147 } 2148 } 2149 PetscPrintf(PETSC_COMM_SELF, "cell[%d] grad (%g, %g)\n", cell, grad[0], grad[1]);CHKERRQ(ierr); 2150 PetscFunctionReturn(0); 2151 } 2152 #endif 2153 2154 /* 2155 PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell 2156 2157 Input Parameters: 2158 + fvm - The PetscFV object 2159 . numFaces - The number of cell faces which are not constrained 2160 . dx - The vector from the cell centroid to the neighboring cell centroid for each face 2161 2162 Level: developer 2163 2164 .seealso: PetscFVCreate() 2165 */ 2166 static PetscErrorCode PetscFVComputeGradient_LeastSquares(PetscFV fvm, PetscInt numFaces, const PetscScalar dx[], PetscScalar grad[]) 2167 { 2168 PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *) fvm->data; 2169 const PetscBool useSVD = PETSC_TRUE; 2170 const PetscInt maxFaces = ls->maxFaces; 2171 PetscInt dim, f, d; 2172 PetscErrorCode ierr; 2173 2174 PetscFunctionBegin; 2175 if (numFaces > maxFaces) { 2176 if (maxFaces < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Reconstruction has not been initialized, call PetscFVLeastSquaresSetMaxFaces()"); 2177 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input faces %D > %D maxfaces", numFaces, maxFaces); 2178 } 2179 ierr = PetscFVGetSpatialDimension(fvm, &dim);CHKERRQ(ierr); 2180 for (f = 0; f < numFaces; ++f) { 2181 for (d = 0; d < dim; ++d) ls->B[d*maxFaces+f] = dx[f*dim+d]; 2182 } 2183 /* Overwrites B with garbage, returns Binv in row-major format */ 2184 if (useSVD) {ierr = PetscFVLeastSquaresPseudoInverseSVD_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work);CHKERRQ(ierr);} 2185 else {ierr = PetscFVLeastSquaresPseudoInverse_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work);CHKERRQ(ierr);} 2186 for (f = 0; f < numFaces; ++f) { 2187 for (d = 0; d < dim; ++d) grad[f*dim+d] = ls->Binv[d*maxFaces+f]; 2188 } 2189 PetscFunctionReturn(0); 2190 } 2191 2192 /* 2193 neighborVol[f*2+0] contains the left geom 2194 neighborVol[f*2+1] contains the right geom 2195 */ 2196 static PetscErrorCode PetscFVIntegrateRHSFunction_LeastSquares(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, 2197 PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[]) 2198 { 2199 void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *); 2200 void *rctx; 2201 PetscScalar *flux = fvm->fluxWork; 2202 const PetscScalar *constants; 2203 PetscInt dim, numConstants, pdim, Nc, totDim, off, f, d; 2204 PetscErrorCode ierr; 2205 2206 PetscFunctionBegin; 2207 ierr = PetscDSGetTotalComponents(prob, &Nc);CHKERRQ(ierr); 2208 ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 2209 ierr = PetscDSGetFieldOffset(prob, field, &off);CHKERRQ(ierr); 2210 ierr = PetscDSGetRiemannSolver(prob, field, &riemann);CHKERRQ(ierr); 2211 ierr = PetscDSGetContext(prob, field, &rctx);CHKERRQ(ierr); 2212 ierr = PetscDSGetConstants(prob, &numConstants, &constants);CHKERRQ(ierr); 2213 ierr = PetscFVGetSpatialDimension(fvm, &dim);CHKERRQ(ierr); 2214 ierr = PetscFVGetNumComponents(fvm, &pdim);CHKERRQ(ierr); 2215 for (f = 0; f < Nf; ++f) { 2216 (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f*Nc], &uR[f*Nc], numConstants, constants, flux, rctx); 2217 for (d = 0; d < pdim; ++d) { 2218 fluxL[f*totDim+off+d] = flux[d] / neighborVol[f*2+0]; 2219 fluxR[f*totDim+off+d] = flux[d] / neighborVol[f*2+1]; 2220 } 2221 } 2222 PetscFunctionReturn(0); 2223 } 2224 2225 static PetscErrorCode PetscFVLeastSquaresSetMaxFaces_LS(PetscFV fvm, PetscInt maxFaces) 2226 { 2227 PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *) fvm->data; 2228 PetscInt dim, m, n, nrhs, minwork; 2229 PetscErrorCode ierr; 2230 2231 PetscFunctionBegin; 2232 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 2233 ierr = PetscFVGetSpatialDimension(fvm, &dim);CHKERRQ(ierr); 2234 ierr = PetscFree4(ls->B, ls->Binv, ls->tau, ls->work);CHKERRQ(ierr); 2235 ls->maxFaces = maxFaces; 2236 m = ls->maxFaces; 2237 n = dim; 2238 nrhs = ls->maxFaces; 2239 minwork = 3*PetscMin(m,n) + PetscMax(2*PetscMin(m,n), PetscMax(PetscMax(m,n), nrhs)); /* required by LAPACK */ 2240 ls->workSize = 5*minwork; /* We can afford to be extra generous */ 2241 ierr = PetscMalloc4(ls->maxFaces*dim,&ls->B,ls->workSize,&ls->Binv,ls->maxFaces,&ls->tau,ls->workSize,&ls->work);CHKERRQ(ierr); 2242 PetscFunctionReturn(0); 2243 } 2244 2245 PetscErrorCode PetscFVInitialize_LeastSquares(PetscFV fvm) 2246 { 2247 PetscFunctionBegin; 2248 fvm->ops->setfromoptions = NULL; 2249 fvm->ops->setup = PetscFVSetUp_LeastSquares; 2250 fvm->ops->view = PetscFVView_LeastSquares; 2251 fvm->ops->destroy = PetscFVDestroy_LeastSquares; 2252 fvm->ops->computegradient = PetscFVComputeGradient_LeastSquares; 2253 fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_LeastSquares; 2254 PetscFunctionReturn(0); 2255 } 2256 2257 /*MC 2258 PETSCFVLEASTSQUARES = "leastsquares" - A PetscFV object 2259 2260 Level: intermediate 2261 2262 .seealso: PetscFVType, PetscFVCreate(), PetscFVSetType() 2263 M*/ 2264 2265 PETSC_EXTERN PetscErrorCode PetscFVCreate_LeastSquares(PetscFV fvm) 2266 { 2267 PetscFV_LeastSquares *ls; 2268 PetscErrorCode ierr; 2269 2270 PetscFunctionBegin; 2271 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 2272 ierr = PetscNewLog(fvm, &ls);CHKERRQ(ierr); 2273 fvm->data = ls; 2274 2275 ls->maxFaces = -1; 2276 ls->workSize = -1; 2277 ls->B = NULL; 2278 ls->Binv = NULL; 2279 ls->tau = NULL; 2280 ls->work = NULL; 2281 2282 ierr = PetscFVSetComputeGradients(fvm, PETSC_TRUE);CHKERRQ(ierr); 2283 ierr = PetscFVInitialize_LeastSquares(fvm);CHKERRQ(ierr); 2284 ierr = PetscObjectComposeFunction((PetscObject) fvm, "PetscFVLeastSquaresSetMaxFaces_C", PetscFVLeastSquaresSetMaxFaces_LS);CHKERRQ(ierr); 2285 PetscFunctionReturn(0); 2286 } 2287 2288 /*@ 2289 PetscFVLeastSquaresSetMaxFaces - Set the maximum number of cell faces for gradient reconstruction 2290 2291 Not collective 2292 2293 Input parameters: 2294 + fvm - The PetscFV object 2295 - maxFaces - The maximum number of cell faces 2296 2297 Level: intermediate 2298 2299 .seealso: PetscFVCreate(), PETSCFVLEASTSQUARES 2300 @*/ 2301 PetscErrorCode PetscFVLeastSquaresSetMaxFaces(PetscFV fvm, PetscInt maxFaces) 2302 { 2303 PetscErrorCode ierr; 2304 2305 PetscFunctionBegin; 2306 PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1); 2307 ierr = PetscTryMethod(fvm, "PetscFVLeastSquaresSetMaxFaces_C", (PetscFV,PetscInt), (fvm,maxFaces));CHKERRQ(ierr); 2308 PetscFunctionReturn(0); 2309 } 2310