https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ConservativeAdvection.C
Go to the documentation of this file.
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
11#include "SystemBase.h"
12
15
16template <bool is_ad>
19{
21 params.addClassDescription("Conservative form of $\\nabla \\cdot \\vec{v} u$ which in its weak "
22 "form is given by: $(-\\nabla \\psi_i, \\vec{v} u)$. Velocity can be "
23 "given as 1) a variable, for which the gradient is automatically "
24 "taken, 2) a vector variable, or a 3) vector material.");
25 params.addParam<MaterialPropertyName>(
26 "velocity_scalar_coef",
27 "1.0",
28 "Name of material property multiplied against the velocity to scale advection strength.");
29 MooseEnum upwinding_type("none full", "none");
30 params.addParam<MooseEnum>("upwinding_type",
31 upwinding_type,
32 "Type of upwinding used. None: Typically results in overshoots and "
33 "undershoots, but numerical diffusion is minimized. Full: Overshoots "
34 "and undershoots are avoided, but numerical diffusion is large");
35 params.addParam<MaterialPropertyName>("advected_quantity",
36 "An optional material property to be advected. If not "
37 "supplied, then the variable will be used.");
38 params.addCoupledVar(
39 "velocity_as_variable_gradient",
40 "Gradient of this coupled variable is used to define the advection velocity. "
41 "Can be supplied instead of velocity material or velocity variable.");
42 return params;
43}
44
45template <>
48{
49 InputParameters params = generalParams();
50 params.addCoupledVar("velocity", "Velocity vector");
51 params.deprecateCoupledVar("velocity", "velocity_variable", "12/31/2025");
52 params.addParam<MaterialPropertyName>("velocity_material", "Velocity vector given as a material");
53 return params;
54}
55
56template <>
59{
60 InputParameters params = generalParams();
61 params.addCoupledVar("velocity_variable", "Velocity vector given as a variable");
62 params.addParam<MaterialPropertyName>("velocity", "Velocity vector given as a material");
63 params.deprecateParam("velocity", "velocity_material", "12/31/2025");
64 return params;
65}
66
67template <bool is_ad>
69 : GenericKernel<is_ad>(parameters),
70 _scalar(this->template getGenericMaterialProperty<Real, is_ad>("velocity_scalar_coef")),
71 _coupled_variable_present(isParamValid("velocity_as_variable_gradient")),
72 _coupled_variable_var(_coupled_variable_present ? coupled("velocity_as_variable_gradient") : 0),
73 _velocity(
74 _coupled_variable_present
75 ? &this->template coupledGenericGradient<is_ad>("velocity_as_variable_gradient")
76 : (this->isParamValid("velocity_variable")
77 ? &this->template coupledGenericVectorValue<is_ad>("velocity_variable")
78 : (this->isParamValid("velocity_material")
79 ? &this->template getGenericMaterialProperty<RealVectorValue, is_ad>(
80 "velocity_material")
81 .get()
82 : nullptr))),
83 _user_supplied_adv_quant(isParamValid("advected_quantity")),
84 _adv_quant(
85 _user_supplied_adv_quant
86 ? this->template getGenericMaterialProperty<Real, is_ad>("advected_quantity").get()
87 : _u),
88 _upwinding(
89 this->template getParam<MooseEnum>("upwinding_type").template getEnum<UpwindingType>()),
90 _u_nodal(_var.template genericDofValues<is_ad>()),
91 _upwind_node(0),
92 _dtotal_mass_out(0)
93{
95 paramError("velocity_as_variable_gradient",
96 "Use a different kernel (i.e., diffusion) if the gradient used as the velocity is "
97 "the same as the member variable");
98 if (_upwinding != UpwindingType::none && this->isParamValid("advected_quantity"))
100 "advected_quantity",
101 "Upwinding is not compatible with an advected quantity that is not the primary variable.");
102
103 if (!_velocity || (_coupled_variable_present && this->isParamValid("velocity_material")) ||
104 (_coupled_variable_present && this->isParamValid("velocity_variable")) ||
105 (this->isParamValid("velocity_variable") && this->isParamValid("velocity_material")))
107 "velocity_as_variable_gradient",
108 "One and only one of the following input variables must be specified: velocity_variable, "
109 "velocity_material, or velocity_as_variable_gradient.");
110
111 if (this->_has_diag_save_in)
112 paramError("diag_save_in",
113 "_local_ke not computed for global AD indexing. Save-in is deprecated anyway. Use "
114 "the tagging system instead.");
115}
116
117template <bool is_ad>
120{
121 return -_grad_test[_i][_qp] * (*_velocity)[_qp] * _scalar[_qp];
122}
123
124template <bool is_ad>
127{
128 // This is the no-upwinded version
129 // It gets called via GenericKernel<is_ad>::computeResidual()
130 return negSpeedQp() * _adv_quant[_qp];
131}
132
133template <>
134Real
136{
137 // This is the no-upwinded version
138 // It gets called via GenericKernel<false>::computeJacobian()
139 if (!_user_supplied_adv_quant)
140 return negSpeedQp() * _phi[_j][_qp];
141 return 0.0;
142}
143
144template <>
145Real
147{
148 mooseError("Internal error, should never get here when using AD");
149 return 0.0;
150}
151
152template <>
153Real
155{
156 // This is the non-upwinded version
157 // It gets called via GenericKernel<false>::computeOffDiagJacobian()
158 if (_coupled_variable_present && _coupled_variable_var == jvar)
159 return -_grad_test[_i][_qp] * _grad_phi[_j][_qp] * _adv_quant[_qp] * _scalar[_qp];
160 else
161 return 0.0;
162}
163
164template <>
165Real
167{
168 mooseError("Internal error, should never get here when using AD");
169 return 0.0;
170}
171
172template <bool is_ad>
173void
175{
176 switch (_upwinding)
177 {
178 case UpwindingType::none:
180 break;
181 case UpwindingType::full:
182 fullUpwind(JacRes::CALCULATE_RESIDUAL);
183 break;
184 }
185}
186
187template <bool is_ad>
188void
190{
191 switch (_upwinding)
192 {
193 case UpwindingType::none:
195 break;
196 case UpwindingType::full:
197 fullUpwind(JacRes::CALCULATE_JACOBIAN);
198 break;
199 }
200}
201
202template <bool is_ad>
203void
205{
206 // The number of nodes in the element
207 const unsigned int num_nodes = _test.size();
208
209 // Even if we are computing the Jacobian we still need to compute the outflow from each node to
210 // see which nodes are upwind and which are downwind
211 _my_local_re.resize(_var.dofIndices().size());
212
213 if (!is_ad && (res_or_jac == JacRes::CALCULATE_JACOBIAN))
214 prepareMatrixTag(this->_assembly, _var.number(), _var.number());
215
216 // Compute the outflux from each node and store in _my_local_re
217 // If _my_local_re is positive at the node, mass (or whatever the Variable represents) is flowing
218 // out of the node
219 _upwind_node.resize(num_nodes);
220 for (_i = 0; _i < num_nodes; ++_i)
221 {
222 for (_qp = 0; _qp < this->_qrule->n_points(); _qp++)
223 _my_local_re(_i) += this->_JxW[_qp] * this->_coord[_qp] * negSpeedQp();
224 _upwind_node[_i] = (MetaPhysicL::raw_value(_my_local_re(_i)) >= 0.0);
225 }
226
227 // Variables used to ensure mass conservation
228 GenericReal<is_ad> total_mass_out = 0.0;
229 GenericReal<is_ad> total_in = 0.0;
230 if (res_or_jac == JacRes::CALCULATE_JACOBIAN)
231 _dtotal_mass_out.assign(num_nodes, 0.0);
232
233 for (const auto n : make_range(num_nodes))
234 {
235 if (_upwind_node[n])
236 {
237 if constexpr (!is_ad)
238 if (res_or_jac == JacRes::CALCULATE_JACOBIAN)
239 {
240 if (_test.size() == _phi.size())
241 /* u at node=n depends only on the u at node=n, by construction. For
242 * linear-lagrange variables, this means that Jacobian entries involving the derivative
243 * will only be nonzero for derivatives wrt variable at node=n. Hence the
244 * (n, n) in the line below. The above "if" statement catches other variable types
245 * (eg constant monomials)
246 */
247 _local_ke(n, n) += _my_local_re(n);
248
249 _dtotal_mass_out[n] += _local_ke(n, n);
250 }
251 _my_local_re(n) *= getUNodal(n);
252 total_mass_out += _my_local_re(n);
253 }
254 else // downwind node
255 total_in -= _my_local_re(n); // note the -= means the result is positive
256 }
257
258 // Conserve mass over all phases by proportioning the total_mass_out mass to the inflow nodes,
259 // weighted by their local_re values
260 for (const auto n : make_range(num_nodes))
261 if (!_upwind_node[n]) // downwind node
262 {
263 if constexpr (!is_ad)
264 if (res_or_jac == JacRes::CALCULATE_JACOBIAN)
265 for (_j = 0; _j < _phi.size(); _j++)
266 _local_ke(n, _j) += _my_local_re(n) * _dtotal_mass_out[_j] / total_in;
267 _my_local_re(n) *= total_mass_out / total_in;
268 }
269
270 // Add the result to the residual and jacobian
271 if (res_or_jac == JacRes::CALCULATE_RESIDUAL)
272 {
273 this->addResiduals(this->_assembly, _my_local_re, _var.dofIndices(), _var.scalingFactor());
274
275 if (this->_has_save_in)
276 for (const auto & var : this->_save_in)
277 var->sys().solution().add_vector(MetaPhysicL::raw_value(_my_local_re), var->dofIndices());
278 }
279
280 if (res_or_jac == JacRes::CALCULATE_JACOBIAN)
281 {
282 if constexpr (is_ad)
283 this->addJacobian(this->_assembly, _my_local_re, _var.dofIndices(), _var.scalingFactor());
284 else
285 accumulateTaggedLocalMatrix();
286 }
287}
288
registerMooseObject("MooseApp", ConservativeAdvection)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
Moose::GenericType< Real, is_ad > GenericReal
Definition MooseTypes.h:698
Advection of the variable by the velocity provided by the user.
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
For coupling standard variables.
const unsigned int _coupled_variable_var
Coupled variable variable number.
JacRes
enum to make the code clearer
static InputParameters generalParams()
virtual GenericReal< is_ad > negSpeedQp() const
Returns - _grad_test * velocity.
virtual void computeJacobian() override
Compute this Kernel's contribution to the diagonal Jacobian entries.
virtual void computeResidual() override
Compute this Kernel's contribution to the residual.
const bool _coupled_variable_present
Flag to determine if coupled variable is present.
ConservativeAdvectionTempl(const InputParameters &parameters)
virtual Real computeQpJacobian() override
Compute this Kernel's contribution to the Jacobian at the current quadrature point.
static InputParameters validParams()
void fullUpwind(JacRes res_or_jac)
Calculates the fully-upwind Residual and Jacobian (depending on res_or_jac)
virtual GenericReal< is_ad > computeQpResidual() override
Compute this Kernel's contribution to the residual at the current quadrature point.
const MooseArray< GenericRealVectorValue< is_ad > > * _velocity
advection velocity
enum ConservativeAdvectionTempl::UpwindingType _upwinding
static InputParameters validParams()
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void deprecateCoupledVar(const std::string &old_name, const std::string &new_name, const std::string &removal_date)
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
void deprecateParam(const std::string &old_name, const std::string &new_name, const std::string &removal_date)
void addCoupledVar(const std::string &name, const std::string &doc_string)
This method adds a coupled variable name pair.
bool _has_diag_save_in
The aux variables to save the diagonal Jacobian contributions to.
Definition KernelBase.h:69
MooseVariable & _var
This is a regular kernel so we cast to a regular MooseVariable.
Definition Kernel.h:72
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
unsigned int number() const
Get variable number coming from libMesh.
virtual void computeResidual()=0
Compute this object's contribution to the residual.
virtual void computeJacobian()=0
Compute this object's contribution to the diagonal Jacobian entries.
auto raw_value(const Eigen::Map< T > &in)