version 3.11-dev
Loading...
Searching...
No Matches
flux.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_NAVIERSTOKES_MOMENTUM_CVFE_FLUXVARIABLES_HH
13#define DUMUX_NAVIERSTOKES_MOMENTUM_CVFE_FLUXVARIABLES_HH
14
15#include <concepts>
16
17#include <dune/common/fmatrix.hh>
18#include <dune/istl/scaledidmatrix.hh>
19
20#include <dumux/common/math.hh>
23#include <dumux/common/concepts/ipdata_.hh>
24
26
28
29namespace Dumux {
30
40template<class Problem,
41 class ElementDiscretization,
42 class ElementVariables,
43 class ElementFluxVariablesCache>
45{
46 using Element = typename ElementDiscretization::Element;
47 using SubControlVolumeFace = typename ElementDiscretization::SubControlVolumeFace;
48public:
49
52 const Problem& problem,
53 const ElementDiscretization& elemDisc,
54 const ElementVariables& elemVars,
55 const ElementFluxVariablesCache& elemFluxVarsCache,
56 const SubControlVolumeFace& scvf
57 )
58 : problem_(problem)
59 , elemDisc_(elemDisc)
60 , elemVars_(elemVars)
61 , elemFluxVarsCache_(elemFluxVarsCache)
62 , scvf_(scvf)
63 {}
64
65 const Problem& problem() const
66 { return problem_; }
67
68 const Element& element() const
69 { return elemDisc_.element(); }
70
71 const SubControlVolumeFace& scvFace() const
72 { return scvf_; }
73
74 const ElementDiscretization& elemDisc() const
75 { return elemDisc_; }
76
77 const ElementVariables& elemVars() const
78 { return elemVars_; }
79
80 const ElementFluxVariablesCache& elemFluxVarsCache() const
81 { return elemFluxVarsCache_; }
82
83private:
84 const Problem& problem_;
85 const ElementDiscretization& elemDisc_;
86 const ElementVariables& elemVars_;
87 const ElementFluxVariablesCache& elemFluxVarsCache_;
88 const SubControlVolumeFace& scvf_;
89};
90
95template<class GridGeometry, class NumEqVector>
97{
98 using GridView = typename GridGeometry::GridView;
99 using Element = typename GridView::template Codim<0>::Entity;
100 using Scalar = typename NumEqVector::value_type;
101
102 using Extrusion = Extrusion_t<GridGeometry>;
103
104 static constexpr int dim = GridView::dimension;
105 static constexpr int dimWorld = GridView::dimensionworld;
106
107 using Tensor = Dune::FieldMatrix<Scalar, dim, dimWorld>;
108 static_assert(NumEqVector::dimension == dimWorld, "Wrong dimension of velocity vector");
109
110public:
118 template<class Context>
119 NumEqVector advectiveMomentumFlux(const Context& context) const
120 {
121 if (!context.problem().enableInertiaTerms())
122 return NumEqVector(0.0);
123
124 const auto& elemDisc = context.elemDisc();
125 const auto& elemVars = context.elemVars();
126 const auto& scvf = context.scvFace();
127 const auto& fluxVarCache = context.elemFluxVarsCache()[scvf];
128 const auto& shapeValues = fluxVarCache.shapeValues();
129
130 // interpolate velocity at scvf
131 NumEqVector v(0.0);
132 for (const auto& localDof : localDofs(elemDisc))
133 v.axpy(shapeValues[localDof.index()][0], elemVars[localDof.index()].velocity());
134
135 const auto vn = v*scvf.unitOuterNormal();
136 const auto& insideScv = elemDisc.scv(scvf.insideScvIdx());
137 const auto& outsideScv = elemDisc.scv(scvf.outsideScvIdx());
138 const auto& insideVars = elemVars[insideScv];
139 const auto& outsideVars = elemVars[outsideScv];
140 static const auto upwindWeight = getParamFromGroup<Scalar>(context.problem().paramGroup(), "Flux.UpwindWeight");
141 static const bool upwindMomentumDensity
142 = getParamFromGroup<bool>(context.problem().paramGroup(), "Flux.UpwindMomentumDensity", true);
143
144 NumEqVector advectiveTermIntegrand;
145 if (upwindMomentumDensity)
146 {
147 const NumEqVector insideMomentum = context.problem().density(context.element(), elemDisc, ipData(elemDisc, insideScv))*insideVars.velocity();
148 const NumEqVector outsideMomentum = context.problem().density(context.element(), elemDisc, ipData(elemDisc, outsideScv))*outsideVars.velocity();
149 const auto& upwindMomentum = vn > 0 ? insideMomentum : outsideMomentum;
150 const auto& downwindMomentum = vn > 0 ? outsideMomentum : insideMomentum;
151 advectiveTermIntegrand = vn * (upwindWeight * upwindMomentum + (1.0-upwindWeight)*downwindMomentum);
152 }
153 else
154 {
155 const Scalar density = context.problem().density(context.element(), elemDisc, fluxVarCache.ipData());
156 const auto& upwindVelocity = vn > 0 ? insideVars.velocity() : outsideVars.velocity();
157 const auto& downwindVelocity = vn > 0 ? outsideVars.velocity() : insideVars.velocity();
158 advectiveTermIntegrand = density*vn * (upwindWeight * upwindVelocity + (1.0-upwindWeight)*downwindVelocity);
159 }
160
161 return advectiveTermIntegrand * Extrusion::area(elemDisc, scvf) * insideVars.extrusionFactor();
162 }
163
167 template<class Context>
168 NumEqVector diffusiveMomentumFlux(const Context& context) const
169 {
170 const auto& element = context.element();
171 const auto& elemDisc = context.elemDisc();
172 const auto& elemVars = context.elemVars();
173 const auto& scvf = context.scvFace();
174 const auto& fluxVarCache = context.elemFluxVarsCache()[scvf];
175
176 // interpolate velocity gradient at scvf
177 Tensor gradV(0.0);
178 for (const auto& localDof : localDofs(elemDisc))
179 {
180 const auto& vars = elemVars[localDof];
181 for (int dir = 0; dir < dim; ++dir)
182 gradV[dir].axpy(vars.velocity(dir), fluxVarCache.gradN(localDof.index()));
183 }
184
185 // get viscosity from the problem
186 const auto mu = context.problem().effectiveViscosity(element, elemDisc, fluxVarCache.ipData());
187
188 static const bool enableUnsymmetrizedVelocityGradient
189 = getParamFromGroup<bool>(context.problem().paramGroup(), "FreeFlow.EnableUnsymmetrizedVelocityGradient", false);
190
191 // compute -mu*gradV*n*dA
192 NumEqVector diffusiveFlux = enableUnsymmetrizedVelocityGradient ?
193 mv(gradV, scvf.unitOuterNormal())
194 : mv(gradV + getTransposed(gradV),scvf.unitOuterNormal());
195
196 diffusiveFlux *= -mu;
197
198 static const bool enableDilatationTerm = getParamFromGroup<bool>(context.problem().paramGroup(), "FreeFlow.EnableDilatationTerm", false);
199 if (enableDilatationTerm)
200 diffusiveFlux += 2.0/3.0 * mu * trace(gradV) * scvf.unitOuterNormal();
201
202 diffusiveFlux *= Extrusion::area(elemDisc, scvf) * elemVars[elemDisc.scv(scvf.insideScvIdx())].extrusionFactor();
203 return diffusiveFlux;
204 }
205
206 template<class Context>
207 NumEqVector pressureContribution(const Context& context) const
208 {
209 const auto& element = context.element();
210 const auto& elemDisc = context.elemDisc();
211 const auto& elemVars = context.elemVars();
212 const auto& scvf = context.scvFace();
213 const auto& fluxVarCache = context.elemFluxVarsCache()[scvf];
214
215 // The pressure force needs to take the extruded scvf area into account
216 const auto pressure = context.problem().pressure(element, elemDisc, fluxVarCache.ipData());
217
218 // The pressure contribution calculated above might have a much larger numerical value compared to the viscous or inertial forces.
219 // This may lead to numerical inaccuracies due to loss of significance (cancellation) for the final residual value.
220 // In the end, we are only interested in a pressure gradient between the two relevant faces so we can
221 // subtract a constant reference value from the actual pressure contribution.
222 const auto referencePressure = context.problem().referencePressure();
223
224 NumEqVector pn(scvf.unitOuterNormal());
225 pn *= (pressure-referencePressure)*Extrusion::area(elemDisc, scvf)*elemVars[elemDisc.scv(scvf.insideScvIdx())].extrusionFactor();
226
227 return pn;
228 }
229};
230
231} // end namespace Dumux
232
233namespace Dumux::Experimental {
234
243template<class Scalar, class GridDiscretization>
245{
246 using GridView = typename GridDiscretization::GridView;
247 using Element = typename GridView::template Codim<0>::Entity;
248 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
249 using ElementDiscretization = typename GridDiscretization::LocalView;
250
251 static constexpr int dimWorld = GridView::dimensionworld;
252
253public:
254 using Tensor = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
255 using PressureTensor = Dune::ScaledIdentityMatrix<Scalar, dimWorld>;
256
264 template<class ElementVariables, Concept::IpData IpData>
265 static GlobalPosition velocity(const ElementDiscretization& elemDisc,
266 const ElementVariables& elemVars,
267 const IpData& ipData)
268 { return velocity(elemDisc, elemVars, cache(elemVars, ipData)); }
269
277 template<class ElementVariables, class IpCache>
278 static GlobalPosition velocity(const ElementDiscretization& elemDisc,
279 const ElementVariables& elemVars,
280 const IpCache& ipCache)
281 {
282 const auto& shapeValues = ipCache.shapeValues();
283
284 GlobalPosition velocity(0.0);
285 for (const auto& localDof : localDofs(elemDisc))
286 velocity.axpy(shapeValues[localDof.index()][0], elemVars[localDof.index()].velocity());
287
288 return velocity;
289 }
290
298 template<class ElementVariables, Concept::IpData IpData>
299 static Tensor velocityGradient(const ElementDiscretization& elemDisc,
300 const ElementVariables& elemVars,
301 const IpData& ipData)
302 { return velocityGradient(elemDisc, elemVars, cache(elemVars, ipData)); }
303
311 template<class ElementVariables, class IpCache>
312 static Tensor velocityGradient(const ElementDiscretization& elemDisc,
313 const ElementVariables& elemVars,
314 const IpCache& ipCache)
315 {
316 Tensor gradV(0.0);
317 for (const auto& localDof : localDofs(elemDisc))
318 {
319 const auto& vars = elemVars[localDof.index()];
320 for (int dir = 0; dir < dimWorld; ++dir)
321 gradV[dir].axpy(vars.velocity(dir), ipCache.gradN(localDof.index()));
322 }
323
324 return gradV;
325 }
326
336 template<class Problem, class ElementVariables, Concept::IpData IpData>
337 static Tensor diffusiveFluxTerm(const Problem& problem,
338 const Element& element,
339 const ElementDiscretization& elemDisc,
340 const ElementVariables& elemVars,
341 const IpData& ipData)
342 { return diffusiveFluxTerm(problem, element, elemDisc, elemVars, ipData, cache(elemVars, ipData)); }
343
354 template<class Problem, class ElementVariables, Concept::IpData IpData, class IpCache>
355 static Tensor diffusiveFluxTerm(const Problem& problem,
356 const Element& element,
357 const ElementDiscretization& elemDisc,
358 const ElementVariables& elemVars,
359 const IpData& ipData,
360 const IpCache& ipCache)
361 {
362 static const bool enableUnsymmetrizedVelocityGradient
363 = getParamFromGroup<bool>(problem.paramGroup(), "FreeFlow.EnableUnsymmetrizedVelocityGradient", false);
364 static const bool enableDilatationTerm
365 = getParamFromGroup<bool>(problem.paramGroup(), "FreeFlow.EnableDilatationTerm", false);
366
367 const auto gradV = velocityGradient(elemDisc, elemVars, ipCache);
368 const Scalar mu = problem.effectiveViscosity(element, elemDisc, ipData);
369
370 Tensor fluxTerm = enableUnsymmetrizedVelocityGradient ? gradV : gradV + getTransposed(gradV);
371 fluxTerm *= -mu;
372
373 if (enableDilatationTerm)
374 {
375 const Scalar dilatation = 2.0/3.0 * mu * trace(gradV);
376 for (int dir = 0; dir < dimWorld; ++dir)
377 fluxTerm[dir][dir] += dilatation;
378 }
379
380 return fluxTerm;
381 }
382
391 template<class Problem, Concept::IpData IpData>
393 const Element& element,
394 const ElementDiscretization& elemDisc,
395 const IpData& ipData)
396 { return PressureTensor(problem.pressure(element, elemDisc, ipData) - problem.referencePressure()); }
397
407 template<class ElementVariables, Concept::IpData IpData,
408 class TransportedMomentum, class TransportingVelocity>
409 requires std::invocable<TransportedMomentum, const ElementDiscretization&, const ElementVariables&, const IpData&>
410 && std::invocable<TransportingVelocity, const ElementDiscretization&, const ElementVariables&, const IpData&>
411 static Tensor advectiveFluxTerm(const ElementDiscretization& elemDisc,
412 const ElementVariables& elemVars,
413 const IpData& ipData,
414 const TransportedMomentum& transportedMomentum,
415 const TransportingVelocity& transportingVelocity)
416 {
417 const GlobalPosition momentum = transportedMomentum(elemDisc, elemVars, ipData);
418 const GlobalPosition velocity = transportingVelocity(elemDisc, elemVars, ipData);
419
420 Tensor fluxTerm(0.0);
421 for (int i = 0; i < dimWorld; ++i)
422 fluxTerm[i].axpy(momentum[i], velocity);
423
424 return fluxTerm;
425 }
426};
427
428} // end namespace Dumux::Experimental
429
430#endif
Momentum flux of the Navier-Stokes equations for control-volume finite element schemes,...
Definition flux.hh:245
static GlobalPosition velocity(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpData &ipData)
Returns the velocity at an interpolation point.
Definition flux.hh:265
Dune::FieldMatrix< Scalar, dimWorld, dimWorld > Tensor
Definition flux.hh:254
static Tensor diffusiveFluxTerm(const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpData &ipData, const IpCache &ipCache)
Returns the diffusive part of the flux tensor at an interpolation point.
Definition flux.hh:355
Dune::ScaledIdentityMatrix< Scalar, dimWorld > PressureTensor
Definition flux.hh:255
static Tensor velocityGradient(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpData &ipData)
Returns the velocity gradient at an interpolation point.
Definition flux.hh:299
static PressureTensor pressureFluxTerm(const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const IpData &ipData)
Returns the pressure part of the flux tensor at an interpolation point.
Definition flux.hh:392
static Tensor velocityGradient(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpCache &ipCache)
Returns the velocity gradient at an interpolation point.
Definition flux.hh:312
static GlobalPosition velocity(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpCache &ipCache)
Returns the velocity at an interpolation point.
Definition flux.hh:278
static Tensor advectiveFluxTerm(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpData &ipData, const TransportedMomentum &transportedMomentum, const TransportingVelocity &transportingVelocity)
Returns the advective part of the flux tensor at an interpolation point.
Definition flux.hh:411
static Tensor diffusiveFluxTerm(const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpData &ipData)
Returns the diffusive part of the flux tensor at an interpolation point.
Definition flux.hh:337
Base class for all standard finite volume or finite element problems.
Definition common/problem.hh:39
const std::string & paramGroup() const
The parameter group in which to retrieve runtime parameters.
Definition common/problem.hh:301
The flux variables class for the Navier-Stokes model using control-volume finite element schemes.
Definition flux.hh:97
NumEqVector advectiveMomentumFlux(const Context &context) const
Returns the advective momentum flux.
Definition flux.hh:119
NumEqVector diffusiveMomentumFlux(const Context &context) const
Returns the diffusive momentum flux due to viscous forces.
Definition flux.hh:168
NumEqVector pressureContribution(const Context &context) const
Definition flux.hh:207
const SubControlVolumeFace & scvFace() const
Definition flux.hh:71
const Element & element() const
Definition flux.hh:68
const Problem & problem() const
Definition flux.hh:65
NavierStokesMomentumFluxContext(const Problem &problem, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const ElementFluxVariablesCache &elemFluxVarsCache, const SubControlVolumeFace &scvf)
Initialize the flux variables storing some temporary pointers.
Definition flux.hh:51
const ElementFluxVariablesCache & elemFluxVarsCache() const
Definition flux.hh:80
const ElementDiscretization & elemDisc() const
Definition flux.hh:74
const ElementVariables & elemVars() const
Definition flux.hh:77
Some exceptions thrown in DuMux.
Helper classes to compute the integration elements.
typename NumEqVectorTraits< PrimaryVariables >::type NumEqVector
A vector with the same size as numbers of equations This is the default implementation and has to be ...
Definition numeqvector.hh:34
Dune::DenseVector< V >::derived_type mv(const Dune::DenseMatrix< MAT > &M, const Dune::DenseVector< V > &v)
Returns the result of the projection of a vector v with a Matrix M.
Definition math.hh:829
Dune::DenseMatrix< MatrixType >::field_type trace(const Dune::DenseMatrix< MatrixType > &M)
Trace of a dense matrix.
Definition math.hh:800
Dune::FieldMatrix< Scalar, n, m > getTransposed(const Dune::FieldMatrix< Scalar, m, n > &M)
Transpose a FieldMatrix.
Definition math.hh:712
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:165
Class representing dofs on elements for control-volume finite element schemes.
Define some often used mathematical functions.
Definition assembly/assembler.hh:46
Definition adapt.hh:17
auto localDofs(const FVElementGeometry &fvGeometry)
range over local dofs
Definition localdof.hh:50
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition extrusion.hh:257
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.