Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "FVAdvectedVanLeerWeightBased.h" 11 : 12 : #include "MathFVUtils.h" 13 : 14 : #include <algorithm> 15 : #include <limits> 16 : 17 : registerMooseObject("MooseApp", FVAdvectedVanLeerWeightBased); 18 : 19 : InputParameters 20 3759 : FVAdvectedVanLeerWeightBased::validParams() 21 : { 22 3759 : InputParameters params = FVInterpolationMethod::validParams(); 23 7518 : params.addClassDescription( 24 : "Van Leer interpolation for advected quantities implemented as limited blending weights " 25 : "(no MUSCL reconstruction, no deferred correction)."); 26 11277 : params.addParam<bool>( 27 : "limit_to_linear", 28 7518 : true, 29 : "Whether to limit the scheme to be no more downwind-biased than linear interpolation " 30 : "(blends between upwind and linear; avoids 'compressive' weights that can lead to " 31 : "downwind weighting and poor linear solver behavior)."); 32 15036 : params.addRangeCheckedParam<Real>( 33 : "blending_factor", 34 7518 : 1.0, 35 : "blending_factor>=0 & blending_factor<=1", 36 : "Scales the high-order blending strength; 0 gives pure upwind, 1 gives the full limited " 37 : "blending. Values < 1 can improve linear solver robustness for fully implicit assembly."); 38 3759 : return params; 39 0 : } 40 : 41 349 : FVAdvectedVanLeerWeightBased::FVAdvectedVanLeerWeightBased(const InputParameters & params) 42 : : FVInterpolationMethod(params), 43 349 : _limit_to_linear(getParam<bool>("limit_to_linear")), 44 1047 : _blending_factor(getParam<Real>("blending_factor")) 45 : { 46 349 : } 47 : 48 : FVAdvectedInterpolationMethod::AdvectedSystemContribution 49 10525036 : FVAdvectedVanLeerWeightBased::advectedInterpolate(const FaceInfo & face, 50 : Real elem_value, 51 : Real neighbor_value, 52 : const VectorValue<Real> * elem_grad, 53 : const VectorValue<Real> * neighbor_grad, 54 : Real mass_flux) const 55 : { 56 : mooseAssert(elem_grad && neighbor_grad, 57 : "Van Leer advected interpolation requires both element and neighbor gradients."); 58 : 59 10525036 : const bool upwind_is_elem = mass_flux >= 0.0; 60 : 61 10525036 : const Real phi_upwind = upwind_is_elem ? elem_value : neighbor_value; 62 10525036 : const Real phi_downwind = upwind_is_elem ? neighbor_value : elem_value; 63 : 64 10525036 : const VectorValue<Real> grad_upwind = upwind_is_elem ? *elem_grad : *neighbor_grad; 65 10525036 : const Point upwind_to_downwind = upwind_is_elem ? face.dCN() : Point(-face.dCN()); 66 : 67 10525036 : const auto r_f = Moose::FV::rF(phi_upwind, phi_downwind, grad_upwind, upwind_to_downwind); 68 10525036 : const Real beta = (r_f + std::abs(r_f)) / (1.0 + std::abs(r_f)); 69 : 70 : // Geometric weight associated with the upwind cell for this face. 71 10525036 : const Real w_f = upwind_is_elem ? face.gC() : (1.0 - face.gC()); 72 : 73 : // Following the Greenshields blending form: 74 : // phi_f = (1-g)*phi_upwind + g*phi_downwind, with g = beta*(1-w_f) 75 10525036 : const Real g_unclamped = _blending_factor * beta * (1.0 - w_f); 76 10525036 : const Real g_clamped = std::min(std::max(g_unclamped, 0.0), 1.0 - w_f); 77 : // Clamp to [0, 1-w_f] so the weights do not become more downwind-biased than linear. 78 10525036 : const Real g = _limit_to_linear ? g_clamped : g_unclamped; 79 : 80 10525036 : const Real w_upwind = 1.0 - g; 81 10525036 : const Real w_downwind = g; 82 : 83 : // Map (upwind, downwind) weights back to (elem, neighbor) ordering. 84 10525036 : const Real w_elem = upwind_is_elem ? w_upwind : w_downwind; 85 10525036 : const Real w_neighbor = upwind_is_elem ? w_downwind : w_upwind; 86 : 87 10525036 : AdvectedSystemContribution result; 88 10525036 : result.weights_matrix = std::make_pair(w_elem, w_neighbor); 89 : 90 21050072 : return result; 91 : } 92 : 93 : Real 94 0 : FVAdvectedVanLeerWeightBased::advectedInterpolateValue(const FaceInfo & face, 95 : Real elem_value, 96 : Real neighbor_value, 97 : const VectorValue<Real> * elem_grad, 98 : const VectorValue<Real> * neighbor_grad, 99 : Real mass_flux) const 100 : { 101 : const auto result = 102 0 : advectedInterpolate(face, elem_value, neighbor_value, elem_grad, neighbor_grad, mass_flux); 103 0 : return result.weights_matrix.first * elem_value + result.weights_matrix.second * neighbor_value; 104 : }