version 3.11-dev
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/typetraits/localdofs_.hh>
22
28
30
31namespace Dumux {
32
33namespace Detail {
34
36template<class P, class FVG, class EV, class IPD>
38 std::declval<P>().source(std::declval<FVG>(), std::declval<EV>(), std::declval<IPD>())
39);
40
41template<class P, class FVG, class EV, class IPD>
43{ return Dune::Std::is_detected<SourceWithIpDataInterface, P, FVG, EV, IPD>::value; }
44
45} // end namespace Detail
46
51template<class TypeTag>
53: public CVFELocalResidual<TypeTag>
54{
56
58
59 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
60 using ElementVolumeVariables = typename GridVolumeVariables::LocalView;
61 using VolumeVariables = typename GridVolumeVariables::VolumeVariables;
62
63 using GridFluxVariablesCache = typename GridVariables::GridFluxVariablesCache;
64 using ElementFluxVariablesCache = typename GridFluxVariablesCache::LocalView;
65
69 using FVElementGeometry = typename GridGeometry::LocalView;
70 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
71 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
72 using GridView = typename GridGeometry::GridView;
73 using Element = typename GridView::template Codim<0>::Entity;
77 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
78
79 using Extrusion = Extrusion_t<GridGeometry>;
80
82
83 static constexpr auto dim = GridView::dimension;
84
85 using LocalBasis = typename GridGeometry::FeCache::FiniteElementType::Traits::LocalBasisType;
86 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
94
95public:
98 using ParentType::ParentType;
99
110 NumEqVector computeStorage(const Problem& problem,
111 const FVElementGeometry& fvGeometry,
112 const SubControlVolume& scv,
113 const VolumeVariables& volVars,
114 const bool isPreviousStorage) const
115 {
116 return problem.density(fvGeometry.element(), fvGeometry, ipData(fvGeometry, scv), isPreviousStorage) * volVars.velocity();
117 }
118
130 NumEqVector computeSource(const Problem& problem,
131 const Element& element,
132 const FVElementGeometry& fvGeometry,
133 const ElementVolumeVariables& elemVolVars,
134 const SubControlVolume& scv) const
135 {
136 NumEqVector source;
137
138 if constexpr (Detail::hasProblemSourceWithIpDataInterface<Problem, FVElementGeometry, ElementVolumeVariables, BaseIpData>())
139 {
140 source = problem.source(fvGeometry, elemVolVars, ipData(fvGeometry, scv.center()));
141
142 // ToDo: point source data with ipData
143 // add contribution from possible point sources
144 if (!problem.pointSourceMap().empty())
145 source += problem.scvPointSources(element, fvGeometry, elemVolVars, scv);
146 }
147 else
148 source = ParentType::computeSource(problem, element, fvGeometry, elemVolVars, scv);
149
150
151 // add rho*g (note that gravity might be zero in case it's disabled in the problem)
152 const auto& data = ipData(fvGeometry, scv);
153 source += problem.density(element, fvGeometry, data) * problem.gravity();
154
155 // Axisymmetric problems in 2D feature an extra source term arising from the transformation to cylindrical coordinates.
156 // See Ferziger/Peric: Computational methods for Fluid Dynamics (2020)
157 // https://doi.org/10.1007/978-3-319-99693-6
158 // Chapter 9.9 and Eq. (9.81) and comment on finite volume methods
159 if constexpr (dim == 2 && isRotationalExtrusion<Extrusion>)
160 {
161 // the radius with respect to the rotation axis
162 const auto r = scv.center()[Extrusion::radialAxis] - fvGeometry.gridGeometry().bBoxMin()[Extrusion::radialAxis];
163
164 // The velocity term is new with respect to Cartesian coordinates and handled below as a source term
165 // It only enters the balance of the momentum balance in radial direction
166 source[Extrusion::radialAxis] += -2.0*problem.effectiveViscosity(element, fvGeometry, data)
167 * elemVolVars[scv].velocity(Extrusion::radialAxis) / (r*r);
168
169 // Pressure term (needed because we incorporate pressure in terms of a surface integral).
170 // grad(p) becomes div(pI) + (p/r)*n_r in cylindrical coordinates. The second term
171 // is new with respect to Cartesian coordinates and handled below as a source term.
172 source[Extrusion::radialAxis] += problem.pressure(element, fvGeometry, data)/r;
173 }
174
175 return source;
176 }
177
188 NumEqVector computeFlux(const Problem& problem,
189 const Element& element,
190 const FVElementGeometry& fvGeometry,
191 const ElementVolumeVariables& elemVolVars,
192 const SubControlVolumeFace& scvf,
193 const ElementFluxVariablesCache& elemFluxVarsCache) const
194 {
195 FluxContext context(problem, fvGeometry, elemVolVars, elemFluxVarsCache, scvf);
196 FluxHelper fluxHelper;
197
198 NumEqVector flux(0.0);
199 flux += fluxHelper.advectiveMomentumFlux(context);
200 flux += fluxHelper.diffusiveMomentumFlux(context);
201 flux += fluxHelper.pressureContribution(context);
202 return flux;
203 }
204
206 const Problem& problem,
207 const Element& element,
208 const FVElementGeometry& fvGeometry,
209 const ElementVolumeVariables& prevElemVolVars,
210 const ElementVolumeVariables& curElemVolVars) const
211 {
212 if constexpr (Detail::LocalDofs::hasNonCVLocalDofsInterface<FVElementGeometry>())
213 {
214 // Make sure we don't iterate over quadrature points if there are no hybrid dofs
215 if( nonCVLocalDofs(fvGeometry).empty() )
216 return;
217
218 static const auto intOrder
219 = getParamFromGroup<int>(problem.paramGroup(), "Assembly.FEIntegrationOrderStorage", 4);
220
221 const auto &localBasis = fvGeometry.feLocalBasis();
222 using RangeType = typename LocalBasis::Traits::RangeType;
223 std::vector<RangeType> integralShapeFunctions(localBasis.size(), RangeType(0.0));
224
225 // We apply mass lumping such that we only need to calculate the integral of basis functions
226 const auto& geometry = fvGeometry.elementGeometry();
227 const auto& quadRule = Dune::QuadratureRules<Scalar, dim>::rule(geometry.type(), intOrder);
228 for (const auto& quadPoint : quadRule)
229 {
230 const Scalar qWeight = quadPoint.weight()*Extrusion::integrationElement(geometry, quadPoint.position());
231 // Obtain and store shape function values and gradients at the current quad point
232 IpData ipData(geometry, quadPoint.position(), localBasis);
233
234 // get density from the problem
235 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
236 integralShapeFunctions[localDof.index()] += ipData.shapeValue(localDof.index())*qWeight;
237 }
238
239 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
240 {
241 const auto localDofIdx = localDof.index();
242 const auto& data = ipData(fvGeometry, localDof);
243 const auto curDensity = problem.density(element, fvGeometry, data, false);
244 const auto prevDensity = problem.density(element, fvGeometry, data, true);
245 const auto curVelocity = curElemVolVars[localDofIdx].velocity();
246 const auto prevVelocity = prevElemVolVars[localDofIdx].velocity();
247 auto timeDeriv = (curDensity*curVelocity - prevDensity*prevVelocity);
248 timeDeriv /= this->timeLoop().timeStepSize();
249
250 // add storage to residual
251 for (int eqIdx = 0; eqIdx < NumEqVector::dimension; ++eqIdx)
252 residual[localDofIdx][eqIdx] += integralShapeFunctions[localDofIdx]*timeDeriv[eqIdx];
253 }
254 }
255 }
256
258 const Problem& problem,
259 const Element& element,
260 const FVElementGeometry& fvGeometry,
261 const ElementVolumeVariables& elemVolVars,
262 const ElementFluxVariablesCache& elemFluxVarsCache,
263 const ElementBoundaryTypes &elemBcTypes) const
264 {
265 if constexpr (Detail::LocalDofs::hasNonCVLocalDofsInterface<FVElementGeometry>())
266 {
267 // Make sure we don't iterate over quadrature points if there are no hybrid dofs
268 if( nonCVLocalDofs(fvGeometry).empty() )
269 return;
270
271 static const bool enableUnsymmetrizedVelocityGradient
272 = getParamFromGroup<bool>(problem.paramGroup(), "FreeFlow.EnableUnsymmetrizedVelocityGradient", false);
273 static const auto intOrder
274 = getParamFromGroup<int>(problem.paramGroup(), "Assembly.FEIntegrationOrderFluxAndSource", 4);
275
276 const auto &localBasis = fvGeometry.feLocalBasis();
277
278 const auto& geometry = fvGeometry.elementGeometry();
279 const auto& quadRule = Dune::QuadratureRules<Scalar, dim>::rule(geometry.type(), intOrder);
280 for (const auto& quadPoint : quadRule)
281 {
282 const Scalar qWeight = quadPoint.weight()*Extrusion::integrationElement(geometry, quadPoint.position());
283
284 // Obtain and store shape function values and gradients at the current quad point
285 IpData ipData(geometry, quadPoint.position(), localBasis);
286 FluxFunctionContext context(problem, fvGeometry, elemVolVars, ipData);
287 const auto& v = context.velocity();
288 const auto& gradV = context.gradVelocity();
289
290 // get viscosity from the problem
291 const Scalar mu = problem.effectiveViscosity(element, fvGeometry, ipData);
292 // get density from the problem
293 const Scalar density = problem.density(element, fvGeometry, ipData);
294
295 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
296 {
297 const auto localDofIdx = localDof.index();
298 NumEqVector fluxAndSourceTerm(0.0);
299 // add advection term
300 if (problem.enableInertiaTerms())
301 fluxAndSourceTerm -= density*(v*ipData.gradN(localDofIdx))*v;
302
303 // add diffusion term
304 fluxAndSourceTerm += enableUnsymmetrizedVelocityGradient ?
305 mu*mv(gradV, ipData.gradN(localDofIdx))
306 : mu*mv(gradV + getTransposed(gradV), ipData.gradN(localDofIdx));
307
308 // add pressure term
309 fluxAndSourceTerm -= problem.pressure(element, fvGeometry, ipData) * ipData.gradN(localDofIdx);
310
311 // finally add source and Neumann term and add everything to residual
312 auto sourceAtIp = problem.source(fvGeometry, elemVolVars, ipData);
313 // add gravity term rho*g (note that gravity might be zero in case it's disabled in the problem)
314 sourceAtIp += density * problem.gravity();
315
316 for (int eqIdx = 0; eqIdx < NumEqVector::dimension; ++eqIdx)
317 {
318 fluxAndSourceTerm[eqIdx] -= ipData.shapeValue(localDofIdx) * sourceAtIp[eqIdx];
319 residual[localDofIdx][eqIdx] += qWeight*fluxAndSourceTerm[eqIdx];
320 }
321 }
322 }
323
324 if(elemBcTypes.hasNeumann())
325 residual += evalNeumannSegments_(problem, element, fvGeometry, elemVolVars, elemFluxVarsCache, elemBcTypes);
326 }
327 }
328
329private:
330 ElementResidualVector evalNeumannSegments_(const Problem& problem,
331 const Element& element,
332 const FVElementGeometry& fvGeometry,
333 const ElementVolumeVariables& elemVolVars,
334 const ElementFluxVariablesCache& elemFluxVarsCache,
335 const ElementBoundaryTypes &elemBcTypes) const
336 {
337 ElementResidualVector flux(0.0);
338
339 static const auto intOrder
340 = getParamFromGroup<int>(problem.paramGroup(), "Assembly.FEIntegrationOrderBoundary", 4);
341
342 const auto &localBasis = fvGeometry.feLocalBasis();
343
344 const auto& geometry = fvGeometry.elementGeometry();
345 for (const auto& intersection : intersections(fvGeometry.gridGeometry().gridView(), element))
346 {
347 if(!intersection.boundary())
348 continue;
349
350 const auto& bcTypes = elemBcTypes.get(fvGeometry, intersection);
351 if(!bcTypes.hasNeumann())
352 continue;
353
354 // select quadrature rule for intersection faces (dim-1)
355 auto isGeometry = intersection.geometry();
356 const auto& faceRule = Dune::QuadratureRules<Scalar, dim-1>::rule(isGeometry.type(), intOrder);
357 for (const auto& quadPoint : faceRule)
358 {
359 // position of quadrature point in local coordinates of inside element
360 auto local = geometry.local(isGeometry.global(quadPoint.position()));
361
362 // get quadrature rule weight for intersection
363 Scalar qWeight = quadPoint.weight() * Extrusion::integrationElement(isGeometry, quadPoint.position());
364 FaceIpData faceIpData(geometry, local, localBasis, intersection.centerUnitOuterNormal(), BoundaryFlag{ intersection });
365
366 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
367 {
368 const auto& boundaryFlux = qWeight*problem.boundaryFlux(fvGeometry, elemVolVars, elemFluxVarsCache, faceIpData);
369 // only add fluxes to equations for which Neumann is set
370 for (int eqIdx = 0; eqIdx < NumEqVector::dimension; ++eqIdx)
371 if (bcTypes.isNeumann(eqIdx))
372 flux[localDof.index()][eqIdx] += faceIpData.shapeValue(localDof.index()) * boundaryFlux[eqIdx];
373 }
374
375 }
376
377 }
378
379 return flux;
380 }
381};
382
383} // end namespace Dumux
384
385#endif
Boundary flag to store e.g. in sub control volume faces.
Boundary flag to store e.g. in sub control volume faces.
Definition: boundaryflag.hh:58
An interpolation point related to a face of an element.
Definition: cvfe/interpolationpointdata.hh:99
An interpolation point related to an element that includes global and local positions.
Definition: cvfe/interpolationpointdata.hh:25
The element-wise residual for control-volume finite element schemes.
Definition: cvfelocalresidual.hh:63
typename ParentType::ElementResidualVector ElementResidualVector
Definition: cvfelocalresidual.hh:88
Interpolation point data related to a face of an element.
Definition: fem/interpolationpointdata.hh:96
Definition: fem/interpolationpointdata.hh:21
const RangeType & shapeValue(int i) const
The shape value of a local dof at the quadrature point.
Definition: fem/interpolationpointdata.hh:63
const GlobalPosition & gradN(int i) const
The shape value gradient of a local dof at the quadrature point.
Definition: fem/interpolationpointdata.hh:71
The element-wise residual for finite volume schemes.
Definition: fvlocalresidual.hh:36
NumEqVector computeSource(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolume &scv) const
Calculate the source term of the equation.
Definition: fvlocalresidual.hh:209
const Problem & problem() const
the problem
Definition: fvlocalresidual.hh:474
const TimeLoop & timeLoop() const
Definition: fvlocalresidual.hh:479
Element-wise calculation of the Navier-Stokes residual for models using CVFE discretizations.
Definition: freeflow/navierstokes/momentum/cvfe/localresidual.hh:54
void addToElementFluxAndSourceResidual(ElementResidualVector &residual, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const ElementBoundaryTypes &elemBcTypes) const
Definition: freeflow/navierstokes/momentum/cvfe/localresidual.hh:257
NumEqVector computeStorage(const Problem &problem, const FVElementGeometry &fvGeometry, const SubControlVolume &scv, const VolumeVariables &volVars, const bool isPreviousStorage) const
Calculate the storage term of the equation.
Definition: freeflow/navierstokes/momentum/cvfe/localresidual.hh:110
void addToElementStorageResidual(ElementResidualVector &residual, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &prevElemVolVars, const ElementVolumeVariables &curElemVolVars) const
Definition: freeflow/navierstokes/momentum/cvfe/localresidual.hh:205
typename ParentType::ElementResidualVector ElementResidualVector
Use the parent type's constructor.
Definition: freeflow/navierstokes/momentum/cvfe/localresidual.hh:97
NumEqVector computeFlux(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, 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:188
NumEqVector computeSource(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolume &scv) const
Calculate the source term of the equation.
Definition: freeflow/navierstokes/momentum/cvfe/localresidual.hh:130
The flux variables class for the Navier-Stokes model using control-volume finite element schemes.
Definition: flux.hh:174
NumEqVector advectiveMomentumFlux(const Context &context) const
Returns the diffusive momentum flux due to viscous forces.
Definition: flux.hh:192
NumEqVector diffusiveMomentumFlux(const Context &context) const
Returns the diffusive momentum flux due to viscous forces.
Definition: flux.hh:226
NumEqVector pressureContribution(const Context &context) const
Definition: flux.hh:265
Context for computing fluxes.
Definition: flux.hh:39
Context for interpolating data on interpolation points.
Definition: flux.hh:99
Tensor gradVelocity() const
Definition: flux.hh:149
GlobalPosition velocity() const
Definition: flux.hh:139
virtual Scalar timeStepSize() const =0
Returns the suggested time step length .
Defines all properties used in Dumux.
Classes representing interpolation point data for control-volume finite element schemes.
Calculates the element-wise residual for control-volume finite element schemes.
Helper classes to compute the integration elements.
Shape functions and gradients at an interpolation point.
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::FieldMatrix< Scalar, n, m > getTransposed(const Dune::FieldMatrix< Scalar, m, n > &M)
Transpose a FieldMatrix.
Definition: math.hh:712
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
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
The available discretization methods in Dumux.
constexpr bool hasProblemSourceWithIpDataInterface()
Definition: freeflow/navierstokes/momentum/cvfe/localresidual.hh:42
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:39
std::string density(int phaseIdx) noexcept
I/O name of density for multiphase systems.
Definition: name.hh:53
Definition: adapt.hh:17
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition: extrusion.hh:166
A helper to deduce a vector with the same size as numbers of equations.