version 3.11-dev
Loading...
Searching...
No Matches
freeflow/navierstokes/momentum/cvfe/localresidual.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_LOCAL_RESIDUAL_HH
13#define DUMUX_NAVIERSTOKES_MOMENTUM_CVFE_LOCAL_RESIDUAL_HH
14
15#include <dune/common/hybridutilities.hh>
16#include <dune/geometry/quadraturerules.hh>
17
20#include <dumux/common/concepts/variables_.hh>
21#include <dumux/common/typetraits/localdofs_.hh>
24
31
34
35namespace Dumux {
36
37namespace Detail {
38
40template<class P, class FVG, class EV, class IPD>
42 std::declval<P>().source(std::declval<FVG>(), std::declval<EV>(), std::declval<IPD>())
43);
44
45template<class P, class FVG, class EV, class IPD>
47{ return Dune::Std::is_detected<SourceWithIpDataInterface, P, FVG, EV, IPD>::value; }
48
49} // end namespace Detail
50
55template<class TypeTag>
58{
60
62
63 using GridVariablesCache = Concept::GridVariablesCache_t<GridVariables>;
64 using ElementVariables = typename GridVariablesCache::LocalView;
65 using Variables = Concept::Variables_t<GridVariables>;
66
70 using ElementDiscretization = typename GridGeometry::LocalView;
71 using SubControlVolume = typename ElementDiscretization::SubControlVolume;
72 using SubControlVolumeFace = typename ElementDiscretization::SubControlVolumeFace;
73 using GridView = typename GridGeometry::GridView;
74 using Element = typename GridView::template Codim<0>::Entity;
78 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
79
80 using Extrusion = Extrusion_t<GridGeometry>;
81
83
84 static constexpr auto dim = GridView::dimension;
85
86 using LocalBasis = typename GridGeometry::FeCache::FiniteElementType::Traits::LocalBasisType;
87 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
91
93
94public:
96 using ElementResidualVector = typename ParentType::ElementResidualVector;
97 using ParentType::ParentType;
98
109 NumEqVector computeStorage(const Problem& problem,
110 const ElementDiscretization& elemDisc,
111 const SubControlVolume& scv,
112 const Variables& vars,
113 const bool isPreviousStorage) const
114 {
115 return problem.density(elemDisc.element(), elemDisc, ipData(elemDisc, scv), isPreviousStorage) * vars.velocity();
116 }
117
127 NumEqVector storageIntegral(const ElementDiscretization& elemDisc,
128 const ElementVariables& elemVars,
129 const SubControlVolume& scv,
130 bool isPreviousTimeLevel) const
131 {
132 const auto& vars = elemVars[scv];
133 // We apply mass lumping
134 NumEqVector storage = this->asImp().problem().density(elemDisc.element(), elemDisc, ipData(elemDisc, scv), isPreviousTimeLevel)
135 * vars.velocity();
136
137 storage *= Extrusion::volume(elemDisc, scv) * vars.extrusionFactor();
138
139 return storage;
140 }
141
153 NumEqVector computeSource(const Problem& problem,
154 const Element& element,
155 const ElementDiscretization& elemDisc,
156 const ElementVariables& elemVars,
157 const SubControlVolume& scv) const
158 {
159 NumEqVector source;
160
162 {
163 source = problem.source(elemDisc, elemVars, ipData(elemDisc, scv.center()));
164
165 // ToDo: point source data with ipData
166 // add contribution from possible point sources
167 if (!problem.pointSourceMap().empty())
168 source += problem.scvPointSources(element, elemDisc, elemVars, scv);
169 }
170 else
171 source = ParentType::computeSource(problem, element, elemDisc, elemVars, scv);
172
173
174 // add rho*g (note that gravity might be zero in case it's disabled in the problem)
175 const auto& data = ipData(elemDisc, scv);
176 source += problem.density(element, elemDisc, data) * problem.gravity();
177
178 // Axisymmetric problems in 2D feature an extra source term arising from the transformation to cylindrical coordinates.
179 // See Ferziger/Peric: Computational methods for Fluid Dynamics (2020)
180 // https://doi.org/10.1007/978-3-319-99693-6
181 // Chapter 9.9 and Eq. (9.81) and comment on finite volume methods
182 if constexpr (dim == 2 && isRotationalExtrusion<Extrusion>)
183 {
184 // the radius with respect to the rotation axis
185 const auto& gridDiscretization = Dumux::gridDiscretization(elemDisc);
186 const auto r = scv.center()[Extrusion::radialAxis] - gridDiscretization.bBoxMin()[Extrusion::radialAxis];
187
188 // The velocity term is new with respect to Cartesian coordinates and handled below as a source term
189 // It only enters the balance of the momentum balance in radial direction
190 source[Extrusion::radialAxis] += -2.0*problem.effectiveViscosity(element, elemDisc, data)
191 * elemVars[scv].velocity(Extrusion::radialAxis) / (r*r);
192
193 // Pressure term (needed because we incorporate pressure in terms of a surface integral).
194 // grad(p) becomes div(pI) + (p/r)*n_r in cylindrical coordinates. The second term
195 // is new with respect to Cartesian coordinates and handled below as a source term.
196 source[Extrusion::radialAxis] += problem.pressure(element, elemDisc, data)/r;
197 }
198
199 return source;
200 }
201
210 NumEqVector sourceIntegral(const ElementDiscretization& elemDisc,
211 const ElementVariables& elemVars,
212 const SubControlVolume& scv) const
213 {
214 static_assert(!(dim == 2 && isRotationalExtrusion<Extrusion>), "Rotational extrusion source terms are not implemented for integral interface.");
215
216 const auto& problem = this->asImp().problem();
217
218 NumEqVector source(0.0);
219 for (const auto& qpData : CVFE::quadratureRule(elemDisc, scv))
220 {
221 source += qpData.weight() * (problem.source(elemDisc, elemVars, qpData.ipData())
222 + problem.density(elemDisc.element(), elemDisc, qpData.ipData()) * problem.gravity());
223 }
224
225 source *= elemVars[scv].extrusionFactor();
226
227 // add contribution from possible point sources
228 const auto& pointSources = problem.pointSources();
229 if (!pointSources.empty())
230 for (const auto& context : pointSources.contexts(elemDisc, scv))
231 {
232 auto psValues = pointSources.eval(elemDisc, elemVars, context);
233 source += psValues;
234 }
235
236 return source;
237 }
238
249 template<class ElementFluxVariablesCache>
250 NumEqVector computeFlux(const Problem& problem,
251 const Element& element,
252 const ElementDiscretization& elemDisc,
253 const ElementVariables& elemVars,
254 const SubControlVolumeFace& scvf,
255 const ElementFluxVariablesCache& elemFluxVarsCache) const
256 {
258 FluxContext context(problem, elemDisc, elemVars, elemFluxVarsCache, scvf);
259 FluxHelper fluxHelper;
260
261 NumEqVector flux(0.0);
262 flux += fluxHelper.advectiveMomentumFlux(context);
263 flux += fluxHelper.diffusiveMomentumFlux(context);
264 flux += fluxHelper.pressureContribution(context);
265 return flux;
266 }
267
276 NumEqVector fluxIntegral(const ElementDiscretization& elemDisc,
277 const ElementVariables& elemVars,
278 const SubControlVolumeFace& scvf) const
279 {
280 const auto& problem = this->asImp().problem();
281 const auto& element = elemDisc.element();
282
283 NumEqVector flux(0.0);
284 GlobalPosition velocityIntegral(0.0);
285 for (const auto& qpData : CVFE::quadratureRule(elemDisc, scvf))
286 {
287 const auto& faceIpData = qpData.ipData();
288 const auto& ipCache = cache(elemVars, faceIpData);
289 if (problem.enableInertiaTerms())
290 velocityIntegral.axpy(qpData.weight(), FluxTerms::velocity(elemDisc, elemVars, ipCache));
291
292 const auto& normal = faceIpData.unitOuterNormal();
293 FluxTerms::diffusiveFluxTerm(problem, element, elemDisc, elemVars, faceIpData, ipCache).usmv(qpData.weight(), normal, flux);
294 FluxTerms::pressureFluxTerm(problem, element, elemDisc, faceIpData).usmv(qpData.weight(), normal, flux);
295 }
296
297 // the transported momentum is upwinded on the integrated volume flux over the face
298 if (problem.enableInertiaTerms())
299 {
300 static const auto upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight");
301
302 static const bool upwindMomentumDensity = getParamFromGroup<bool>(problem.paramGroup(), "Flux.UpwindMomentumDensity", true);
303
304 const auto& insideScv = elemDisc.scv(scvf.insideScvIdx());
305 const auto& outsideScv = elemDisc.scv(scvf.outsideScvIdx());
306 const auto& insideVars = elemVars[insideScv];
307 const auto& outsideVars = elemVars[outsideScv];
308 const bool insideIsUpwind = velocityIntegral*scvf.unitOuterNormal() > 0;
309 const auto faceIpData = ipData(elemDisc, scvf);
310
311 GlobalPosition momentum(0.0);
312 if (upwindMomentumDensity)
313 {
314 // momentum densities at the dofs of both sides, each with the density at its own dof
315 const GlobalPosition insideMomentum = problem.density(element, elemDisc, ipData(elemDisc, insideScv))*insideVars.velocity();
316 const GlobalPosition outsideMomentum = problem.density(element, elemDisc, ipData(elemDisc, outsideScv))*outsideVars.velocity();
317 const auto& upwindMomentum = insideIsUpwind ? insideMomentum : outsideMomentum;
318 const auto& downwindMomentum = insideIsUpwind ? outsideMomentum : insideMomentum;
319 momentum = upwindWeight*upwindMomentum + (1.0 - upwindWeight)*downwindMomentum;
320 }
321 else
322 {
323 const auto& upwindVelocity = insideIsUpwind ? insideVars.velocity() : outsideVars.velocity();
324 const auto& downwindVelocity = insideIsUpwind ? outsideVars.velocity() : insideVars.velocity();
325 // both are face quantities here, the density is evaluated at the face center
326 const Scalar density = problem.density(element, elemDisc, faceIpData);
327 momentum = density*(upwindWeight*upwindVelocity + (1.0 - upwindWeight)*downwindVelocity);
328 }
329
330 const auto momentumAtIp = [&](const auto&, const auto&, const auto&) { return momentum; };
331 const auto transportingVelocity = [&](const auto&, const auto&, const auto&) { return velocityIntegral; };
332 FluxTerms::advectiveFluxTerm(elemDisc, elemVars, faceIpData, momentumAtIp, transportingVelocity)
333 .umv(scvf.unitOuterNormal(), flux);
334 }
335
336 flux *= elemVars[elemDisc.scv(scvf.insideScvIdx())].extrusionFactor();
337
338 return flux;
339 }
340
342 const Problem& problem,
343 const Element& element,
344 const ElementDiscretization& elemDisc,
345 const ElementVariables& elemVars,
346 bool isPreviousTimeLevel) const
347 {
348 FeResidual::addStorageTerms(storage, problem, elemDisc, elemVars, isPreviousTimeLevel);
349 }
350
352 const Problem& problem,
353 const Element& element,
354 const ElementDiscretization& elemDisc,
355 const ElementVariables& elemVars) const
356 {
358 residual, problem, elemDisc, elemVars
359 );
360 }
361
362};
363
364} // end namespace Dumux
365
366#endif
Boundary flag to store e.g. in sub control volume faces.
An interpolation point related to an element that includes global and local positions.
Definition cvfe/interpolationpointdata.hh:31
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)
Definition flux.hh:265
static PressureTensor pressureFluxTerm(const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const IpData &ipData)
Definition flux.hh:392
static Tensor advectiveFluxTerm(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpData &ipData, const TransportedMomentum &transportedMomentum, const TransportingVelocity &transportingVelocity)
Definition flux.hh:411
static Tensor diffusiveFluxTerm(const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const IpData &ipData)
Definition flux.hh:337
Element-wise calculation of the Navier-Stokes residual for models using CVFE discretizations.
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:58
NumEqVector computeSource(const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolume &scv) const
Calculate the source term of the equation.
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:153
NumEqVector computeStorage(const Problem &problem, const ElementDiscretization &elemDisc, const SubControlVolume &scv, const Variables &vars, const bool isPreviousStorage) const
Calculate the storage term of the equation.
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:109
NumEqVector sourceIntegral(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolume &scv) const
Calculate the source integral.
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:210
void addToElementStorage(ElementResidualVector &storage, const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, bool isPreviousTimeLevel) const
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:341
NumEqVector computeFlux(const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolumeFace &scvf, const ElementFluxVariablesCache &elemFluxVarsCache) const
Evaluates the mass flux over a face of a sub control volume.
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:250
typename ParentType::ElementResidualVector ElementResidualVector
Use the parent type's constructor.
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:96
NumEqVector storageIntegral(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolume &scv, bool isPreviousTimeLevel) const
Calculate the storage integral.
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:127
NumEqVector fluxIntegral(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolumeFace &scvf) const
Calculates the flux integral over a sub control volume face.
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:276
void addToElementFluxAndSourceResidual(ElementResidualVector &residual, const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars) const
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:351
Helper class for evaluating FE-based local residuals.
Definition momentum/cvfe/felocalresidual.hh:32
static void addStorageTerms(ResidualVector &storage, const Problem &problem, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const bool isPreviousTimeLevel)
Add the storage of non-CV local dofs at one time level.
Definition momentum/cvfe/felocalresidual.hh:46
static void addFluxAndSourceTerms(ResidualVector &residual, const Problem &problem, const ElementDiscretization &elemDisc, const ElementVariables &elemVars)
Add flux and source residual contribution for non-CV local dofs.
Definition momentum/cvfe/felocalresidual.hh:100
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
Context for computing fluxes.
Definition flux.hh:45
Defines all properties used in Dumux.
Classes representing interpolation point data for control-volume finite element schemes.
The default local operator than can be specialized for each discretization scheme.
Helper classes to compute the integration elements.
Shape functions and gradients at an interpolation point.
The flux variables class for the Navier-Stokes model using control-volume finite element schemes.
Type traits for classes providing a grid discretization.
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
Vector normal(const Vector &v)
Create a vector normal to the given one (v is expected to be non-zero).
Definition normal.hh:26
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:165
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:296
decltype(auto) gridDiscretization(const T &t, Args &&... args)
The grid discretization.
Definition griddiscretization.hh:65
The available discretization methods in Dumux.
Helper functions for assembling FE-based local residuals.
auto quadratureRule(const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolume &scv, QuadratureRules::MidpointQuadrature)
Midpoint quadrature for scv.
Definition quadraturerules.hh:160
Definition cvfelocalresidual.hh:25
decltype( std::declval< P >().source(std::declval< FVG >(), std::declval< EV >(), std::declval< IPD >())) SourceWithIpDataInterface
helper struct detecting if a problem has new source interface
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:41
constexpr bool hasProblemSourceWithIpDataInterface()
Definition freeflow/navierstokes/momentum/cvfe/localresidual.hh:46
Definition adapt.hh:17
constexpr bool isRotationalExtrusion
Convenience trait to check whether the extrusion is rotational.
Definition extrusion.hh:263
typename Detail::DiscretizationDefaultLocalOperator< TypeTag >::type DiscretizationDefaultLocalOperator
Definition defaultlocaloperator.hh:26
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition extrusion.hh:257
A helper to deduce a vector with the same size as numbers of equations.
Quadrature rules over sub-control volumes and sub-control volume faces.