version 3.8
shallowwaterviscousflux.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-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_FLUX_SHALLOW_WATER_VISCOUS_FLUX_HH
13#define DUMUX_FLUX_SHALLOW_WATER_VISCOUS_FLUX_HH
14
15#include <cmath>
16#include <algorithm>
17#include <utility>
18#include <type_traits>
19#include <array>
20
21#include <dune/common/std/type_traits.hh>
22#include <dune/common/exceptions.hh>
23
27
28namespace Dumux {
29
30#ifndef DOXYGEN
31namespace Detail {
32// helper struct detecting if the user-defined spatial params class has a frictionLaw function
33template <typename T, typename ...Ts>
34using FrictionLawDetector = decltype(std::declval<T>().frictionLaw(std::declval<Ts>()...));
35
36template<class T, typename ...Args>
37static constexpr bool implementsFrictionLaw()
38{ return Dune::Std::is_detected<FrictionLawDetector, T, Args...>::value; }
39} // end namespace Detail
40#endif
41
63template<class NumEqVector, typename std::enable_if_t<NumEqVector::size() == 3, int> = 0>
65{
66
67public:
68
76 template<class Problem, class FVElementGeometry, class ElementVolumeVariables>
77 static NumEqVector flux(const Problem& problem,
78 const typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity& element,
79 const FVElementGeometry& fvGeometry,
80 const ElementVolumeVariables& elemVolVars,
81 const typename FVElementGeometry::SubControlVolumeFace& scvf)
82 {
83 using Scalar = typename NumEqVector::value_type;
84 using FluidSystem = typename ElementVolumeVariables::VolumeVariables::FluidSystem;
85
86 NumEqVector localFlux(0.0);
87
88 // Get the inside and outside volume variables
89 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
90 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
91
92 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
93 const auto& outsideScv = fvGeometry.scv(scvf.outsideScvIdx());
94
95 const auto gradVelocity = [&]()
96 {
97 // The left (inside) and right (outside) states
98 const auto velocityXLeft = insideVolVars.velocity(0);
99 const auto velocityYLeft = insideVolVars.velocity(1);
100 const auto velocityXRight = outsideVolVars.velocity(0);
101 const auto velocityYRight = outsideVolVars.velocity(1);
102
103 // Compute the velocity gradients normal to the face
104 // Factor that takes the direction of the unit vector into account
105 const auto& cellCenterToCellCenter = outsideScv.center() - insideScv.center();
106 const auto distance = cellCenterToCellCenter.two_norm();
107 const auto& unitNormal = scvf.unitOuterNormal();
108 const auto direction = (unitNormal*cellCenterToCellCenter)/distance;
109 return std::array<Scalar, 2>{
110 (velocityXRight-velocityXLeft)*direction/distance,
111 (velocityYRight-velocityYLeft)*direction/distance
112 };
113 }();
114
115 // Use a harmonic average of the depth at the interface.
116 const auto waterDepthLeft = insideVolVars.waterDepth();
117 const auto waterDepthRight = outsideVolVars.waterDepth();
118 const auto averageDepth = 2.0*(waterDepthLeft*waterDepthRight)/(waterDepthLeft + waterDepthRight);
119
120 const Scalar effectiveKinematicViscosity = [&]()
121 {
122 // The background viscosity, per default this is just the fluid viscosity (e.g. for the viscous flow regime)
123 // The default may be overwritten by the user, by setting the parameter "ShallowWater.TurbulentViscosity" to
124 // enable setting a background viscosity that already contains some effects of turbulence
125 static const auto backgroundKinematicViscosity = getParamFromGroup<Scalar>(
126 problem.paramGroup(), "ShallowWater.TurbulentViscosity", insideVolVars.viscosity()/insideVolVars.density()
127 );
128
129 // Check whether the mixing-length turbulence model is used
130 static const auto useMixingLengthTurbulenceModel = getParamFromGroup<bool>(
131 problem.paramGroup(), "ShallowWater.UseMixingLengthTurbulenceModel", false
132 );
133
134 // constant eddy viscosity equal to the prescribed background eddy viscosity
135 if (!useMixingLengthTurbulenceModel)
136 return backgroundKinematicViscosity;
137
138 using SpatialParams = typename Problem::SpatialParams;
139 using E = typename FVElementGeometry::GridGeometry::GridView::template Codim<0>::Entity;
140 using SCV = typename FVElementGeometry::SubControlVolume;
141 if constexpr (!Detail::implementsFrictionLaw<SpatialParams, E, SCV>())
142 DUNE_THROW(Dune::IOError, "Mixing length turbulence model enabled but spatial parameters do not implement the frictionLaw interface!");
143 else
144 {
145 // turbulence model based on mixing length
146 // Compute the turbulent viscosity using a combined horizontal/vertical mixing length approach
147 // Turbulence coefficients: vertical (Elder like) and horizontal (Smagorinsky like)
148 static const auto turbConstV = getParamFromGroup<Scalar>(problem.paramGroup(), "ShallowWater.VerticalCoefficientOfMixingLengthModel", 1.0);
149 static const auto turbConstH = getParamFromGroup<Scalar>(problem.paramGroup(), "ShallowWater.HorizontalCoefficientOfMixingLengthModel", 0.1);
150
157 constexpr Scalar kappa = 0.41;
158 // Compute the average shear velocity on the face
159 const Scalar ustar = [&]()
160 {
161 // Get the bottom shear stress in the two adjacent cells
162 // Note that element is not needed in spatialParams().frictionLaw (should be removed). For now we simply pass the same element twice
163 const auto& bottomShearStressInside = problem.spatialParams().frictionLaw(element, insideScv).bottomShearStress(insideVolVars);
164 const auto& bottomShearStressOutside = problem.spatialParams().frictionLaw(element, outsideScv).bottomShearStress(outsideVolVars);
165 const auto bottomShearStressInsideMag = bottomShearStressInside.two_norm();
166 const auto bottomShearStressOutsideMag = bottomShearStressOutside.two_norm();
167
168 // Use a harmonic average of the viscosity and the depth at the interface.
169 using std::max;
170 const auto averageBottomShearStress = 2.0*(bottomShearStressInsideMag*bottomShearStressOutsideMag)
171 / max(1.0e-8,bottomShearStressInsideMag + bottomShearStressOutsideMag);
172
173 // Shear velocity possibly needed in mixing-length turbulence model in the computation of the diffusion flux
174 using std::sqrt;
175 static_assert(!FluidSystem::isCompressible(0),
176 "The shallow water model assumes incompressible fluids"
177 );
178 // Since the shallow water equations are incompressible, the density is constant.
179 // Therefore, insideVolVars.density() is equal to outsideVolVars.density().
180 return sqrt(averageBottomShearStress/insideVolVars.density());
181 }();
182
183 const auto turbViscosityV = turbConstV * (kappa/6.0) * ustar * averageDepth;
184
209 using std::sqrt;
210 const auto [gradU, gradV] = gradVelocity;
211 const auto mixingLengthSquared = turbConstH * turbConstH * averageDepth * averageDepth;
212 const auto turbViscosityH = mixingLengthSquared * sqrt(2.0*gradU*gradU + 2.0*gradV*gradV);
213
214 // Total turbulent viscosity
215 return backgroundKinematicViscosity + sqrt(turbViscosityV*turbViscosityV + turbViscosityH*turbViscosityH);
216 }
217 }();
218
219 // Compute the viscous momentum fluxes with connecting water depth at the interface
220 using std::min;
221 using std::max;
222 const auto freeSurfaceInside = insideVolVars.waterDepth() + insideVolVars.bedSurface();
223 const auto freeSurfaceOutside = outsideVolVars.waterDepth() + outsideVolVars.bedSurface();
224 const auto interfaceWaterDepth = max(min(freeSurfaceInside , freeSurfaceOutside) - max(insideVolVars.bedSurface(),outsideVolVars.bedSurface()),0.0);
225 const auto& [gradU, gradV] = gradVelocity;
226 const auto uViscousFlux = effectiveKinematicViscosity * interfaceWaterDepth * gradU;
227 const auto vViscousFlux = effectiveKinematicViscosity * interfaceWaterDepth * gradV;
228
229 localFlux[0] = 0.0;
230 localFlux[1] = -uViscousFlux * scvf.area();
231 localFlux[2] = -vViscousFlux * scvf.area();
232
233 return localFlux;
234 }
235};
236
237} // end namespace Dumux
238
239#endif
Compute the shallow water viscous momentum flux due to viscosity.
Definition: shallowwaterviscousflux.hh:65
Function to limit the fluxes.
Classes related to flux variables caching.
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
static NumEqVector flux(const Problem &problem, const typename FVElementGeometry::GridGeometry::GridView::template Codim< 0 >::Entity &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const typename FVElementGeometry::SubControlVolumeFace &scvf)
Compute the viscous momentum flux contribution from the interface shear stress.
Definition: shallowwaterviscousflux.hh:77
static ctype distance(const Dune::FieldVector< ctype, dimWorld > &a, const Dune::FieldVector< ctype, dimWorld > &b)
Compute the shortest distance between two points.
Definition: distance.hh:282
Vector unitNormal(const Vector &v)
Create a vector normal to the given one (v is expected to be non-zero)
Definition: normal.hh:58
Definition: adapt.hh:17
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The empty filler class corresponding to EmptyCache.
Definition: fluxvariablescaching.hh:20
Definition: fluxvariablescaching.hh:55