14#ifndef DUMUX_FLUX_FORCHHEIMER_VELOCITY_HH
15#define DUMUX_FLUX_FORCHHEIMER_VELOCITY_HH
17#include <dune/common/fvector.hh>
18#include <dune/common/fmatrix.hh>
37template<
class Scalar,
class Gr
idGeometry,
class FluxVariables>
40 using FVElementGeometry =
typename GridGeometry::LocalView;
41 using SubControlVolumeFace =
typename GridGeometry::SubControlVolumeFace;
42 using GridView =
typename GridGeometry::GridView;
43 using Element =
typename GridView::template Codim<0>::Entity;
45 static constexpr int dim = GridView::dimension;
46 static constexpr int dimWorld = GridView::dimensionworld;
47 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
54 template<
class ElementVolumeVariables>
56 const ElementVolumeVariables& elemVolVars,
57 const SubControlVolumeFace& scvf,
62 const auto& problem = elemVolVars.gridVolVars().problem();
65 const Scalar forchCoeff = problem.spatialParams().forchCoeff(scvf);
75 static const Scalar epsilon = getParamFromGroup<Scalar>(problem.paramGroup(),
"Forchheimer.NewtonTolerance", 1e-12);
76 static const std::size_t maxNumIter = getParamFromGroup<std::size_t>(problem.paramGroup(),
"Forchheimer.MaxIterations", 30);
77 for (
int k = 0; residual.two_norm() > epsilon ; ++k)
80 DUNE_THROW(
NumericalProblem,
"could not determine forchheimer velocity within "
81 << k <<
" iterations");
84 forchheimerResidual_(residual,
94 forchheimerDerivative_(gradF,
103 gradF.solve(deltaV, residual);
109 auto upwindTerm = [phaseIdx](
const auto& volVars){
return volVars.mobility(phaseIdx); };
110 const Scalar forchheimerUpwindMobility = UpwindScheme::multiplier(elemVolVars, scvf, upwindTerm,
velocity * scvf.unitOuterNormal(), phaseIdx);
113 if (forchheimerUpwindMobility > 0.0)
114 velocity /= forchheimerUpwindMobility;
123 template<
class Problem,
class ElementVolumeVariables,
124 bool scalarPerm = std::is_same<typename Problem::SpatialParams::PermeabilityType, Scalar>::value,
125 std::enable_if_t<scalarPerm, int> = 0>
127 const ElementVolumeVariables& elemVolVars,
128 const SubControlVolumeFace& scvf)
131 Scalar harmonicMeanSqrtK(0.0);
133 const auto insideScvIdx = scvf.insideScvIdx();
134 const auto& insideVolVars = elemVolVars[insideScvIdx];
135 const Scalar Ki = getPermeability_(problem, insideVolVars, scvf.ipGlobal());
136 const Scalar sqrtKi = sqrt(Ki);
138 if (!scvf.boundary())
140 const auto outsideScvIdx = scvf.outsideScvIdx();
141 const auto& outsideVolVars = elemVolVars[outsideScvIdx];
142 const Scalar Kj = getPermeability_(problem, outsideVolVars, scvf.ipGlobal());
143 const Scalar sqrtKj = sqrt(Kj);
147 harmonicMeanSqrtK = sqrtKi;
151 for (
int i = 0; i < dimWorld; ++i)
152 result[i][i] = harmonicMeanSqrtK;
161 template<
class Problem,
class ElementVolumeVariables,
162 bool scalarPerm = std::is_same<typename Problem::SpatialParams::PermeabilityType, Scalar>::value,
163 std::enable_if_t<!scalarPerm, int> = 0>
165 const ElementVolumeVariables& elemVolVars,
166 const SubControlVolumeFace& scvf)
173 const auto insideScvIdx = scvf.insideScvIdx();
174 const auto& insideVolVars = elemVolVars[insideScvIdx];
175 const auto& Ki = getPermeability_(problem, insideVolVars, scvf.ipGlobal());
178 if (!isDiagonal_(Ki))
179 DUNE_THROW(Dune::NotImplemented,
"Only diagonal permeability tensors are supported.");
181 for (
int i = 0; i < dim; ++i)
182 sqrtKi[i][i] = sqrt(Ki[i][i]);
184 if (!scvf.boundary())
186 const auto outsideScvIdx = scvf.outsideScvIdx();
187 const auto& outsideVolVars = elemVolVars[outsideScvIdx];
188 const auto& Kj = getPermeability_(problem, outsideVolVars, scvf.ipGlobal());
190 if (!isDiagonal_(Kj))
191 DUNE_THROW(Dune::NotImplemented,
"Only diagonal permeability tensors are supported.");
193 for (
int i = 0; i < dim; ++i)
194 sqrtKj[i][i] = sqrt(Kj[i][i]);
199 harmonicMeanSqrtK = sqrtKi;
201 return harmonicMeanSqrtK;
207 template<
class ElementVolumeVariables>
209 const Scalar forchCoeff,
213 const ElementVolumeVariables& elemVolVars,
214 const SubControlVolumeFace& scvf,
217 residual = oldVelocity;
219 residual -= darcyVelocity;
221 auto upwindTerm = [phaseIdx](
const auto& volVars){
return volVars.density(phaseIdx) / volVars.viscosity(phaseIdx); };
222 const Scalar rhoOverMu = UpwindScheme::multiplier(elemVolVars, scvf, upwindTerm, oldVelocity * scvf.unitOuterNormal(), phaseIdx);
223 sqrtK.usmv(forchCoeff * rhoOverMu * oldVelocity.two_norm(), oldVelocity, residual);
227 template<
class ElementVolumeVariables>
229 const Scalar forchCoeff,
232 const ElementVolumeVariables& elemVolVars,
233 const SubControlVolumeFace& scvf,
239 auto upwindTerm = [phaseIdx](
const auto& volVars){
return volVars.density(phaseIdx) / volVars.viscosity(phaseIdx); };
241 const Scalar absV =
velocity.two_norm();
251 const Scalar rhoOverMu = UpwindScheme::multiplier(elemVolVars, scvf, upwindTerm,
velocity * scvf.unitOuterNormal(), phaseIdx);
254 for (
int i = 0; i < dim; i++)
256 for (
int k = 0; k <= i; k++)
262 derivative[k][i] = derivative[i][k];
269 for (
int i = 0; i < dim; i++)
270 derivative[i][i] += (1.0 + (sqrtK[i][i]*forchCoeff * absV * rhoOverMu));
284 for (
int i = 0; i < dim; i++)
285 for (
int k = 0; k < dim; k++)
286 if ((i != k) && (abs(K[i][k]) >= 1e-25))
291 template<
class Problem,
class VolumeVariables>
292 static decltype(
auto) getPermeability_(
const Problem& problem,
293 const VolumeVariables& volVars,
294 const GlobalPosition& scvfIpGlobal)
296 if constexpr (Problem::SpatialParams::evaluatePermeabilityAtScvfIP())
297 return problem.spatialParams().permeabilityAtPos(scvfIpGlobal);
299 return volVars.permeability();
Forchheimer's law For a detailed description see dumux/flow/forchheimerslaw.hh.
Definition: forchheimervelocity.hh:39
typename FluxVariables::UpwindScheme UpwindScheme
Definition: forchheimervelocity.hh:49
static DimWorldMatrix calculateHarmonicMeanSqrtPermeability(const Problem &problem, const ElementVolumeVariables &elemVolVars, const SubControlVolumeFace &scvf)
Returns the harmonic mean of and .
Definition: forchheimervelocity.hh:126
Dune::FieldVector< Scalar, dimWorld > DimWorldVector
Definition: forchheimervelocity.hh:50
static DimWorldVector velocity(const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolumeFace &scvf, const int phaseIdx, const DimWorldMatrix sqrtK, const DimWorldVector darcyVelocity)
Definition: forchheimervelocity.hh:55
Dune::FieldMatrix< Scalar, dimWorld, dimWorld > DimWorldMatrix
Definition: forchheimervelocity.hh:51
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:27
Defines all properties used in Dumux.
A free function to average a Tensor at an interface.
UpwindSchemeImpl< GridGeometry, typename GridGeometry::DiscretizationMethod > UpwindScheme
The upwind scheme used for the advective fluxes. This depends on the chosen discretization method.
Definition: flux/upwindscheme.hh:30
Define some often used mathematical functions.
Scalar faceTensorAverage(const Scalar T1, const Scalar T2, const Dune::FieldVector< Scalar, dim > &normal)
Average of a discontinuous scalar field at discontinuity interface (for compatibility reasons with th...
Definition: facetensoraverage.hh:29
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.