13#ifndef DUMUX_NAVIERSTOKES_MOMENTUM_BOUNDARY_FLUXHELPER_HH
14#define DUMUX_NAVIERSTOKES_MOMENTUM_BOUNDARY_FLUXHELPER_HH
43 template<
class Problem,
class FVElementGeometry,
class ElementVolumeVariables,
class ElementFluxVariablesCache,
class Scalar>
45 const FVElementGeometry& fvGeometry,
46 const typename FVElementGeometry::SubControlVolumeFace& scvf,
47 const ElementVolumeVariables& elemVolVars,
48 const ElementFluxVariablesCache& elemFluxVarsCache,
50 const bool zeroNormalVelocityGradient =
true)
54 using MomentumFlux =
typename Problem::MomentumFluxType;
55 constexpr std::size_t dim =
static_cast<std::size_t
>(FVElementGeometry::GridGeometry::GridView::dimension);
57 MomentumFlux::size() == dim,
58 "Expects momentum flux to have as many entries as dimensions."
61 const auto& element = fvGeometry.element();
64 std::decay_t<
decltype(problem.dirichlet(element, scvf))>::size() == dim,
65 "Expects problem.dirichlet to return an array with as many entries as dimensions."
70 MomentumFlux flux(0.0);
73 flux[scvf.normalAxis()] = (
pressure - problem.referencePressure(element, fvGeometry, scvf)) * scvf.directionSign();
76 if (problem.enableInertiaTerms())
78 const auto v = elemVolVars[scvf.insideScvIdx()].velocity();
79 flux[scvf.normalAxis()] += v*v * problem.density(element, fvGeometry, scvf) * scvf.directionSign();
84 else if (scvf.isLateral())
87 if (!zeroNormalVelocityGradient)
88 return MomentumFlux(0.0);
93 const auto& scv = fvGeometry.scv(scvf.insideScvIdx());
94 if (scv.boundary() && problem.onSlipBoundary(fvGeometry, fvGeometry.frontalScvfOnBoundary(scv)))
98 MomentumFlux flux(0.0);
99 const Scalar mu = problem.effectiveViscosity(element, fvGeometry, scvf);
104 * scvf.directionSign();
106 else if (scvf.boundary())
108 * scvf.directionSign();
111 if (problem.enableInertiaTerms())
113 const auto transportingVelocity = [&]()
115 const auto& orthogonalScvf = fvGeometry.lateralOrthogonalScvf(scvf);
116 const auto innerTransportingVelocity = elemVolVars[orthogonalScvf.insideScvIdx()].velocity();
118 static const bool useOldScheme = getParam<bool>(
"FreeFlow.UseOldTransportingVelocity",
true);
124 if (problem.boundaryTypes(element, scvf).isDirichlet(scvf.normalAxis()))
125 return problem.dirichlet(element, scvf)[scvf.normalAxis()];
128 return innerTransportingVelocity;
134 if (problem.boundaryTypes(element, scvf).isDirichlet(scvf.normalAxis()))
135 return 0.5*(problem.dirichlet(element, scvf)[scvf.normalAxis()] + innerTransportingVelocity);
138 if (orthogonalScvf.boundary())
140 if (problem.boundaryTypes(element, orthogonalScvf).isDirichlet(scvf.normalAxis()))
141 return 0.5*(problem.dirichlet(element, scvf)[scvf.normalAxis()] + innerTransportingVelocity);
143 return innerTransportingVelocity;
147 const auto insideVolume = fvGeometry.scv(orthogonalScvf.insideScvIdx()).
volume();
148 const auto outsideVolume = fvGeometry.scv(orthogonalScvf.outsideScvIdx()).
volume();
149 const auto outerTransportingVelocity = elemVolVars[orthogonalScvf.outsideScvIdx()].velocity();
150 return (insideVolume*innerTransportingVelocity + outsideVolume*outerTransportingVelocity) / (insideVolume + outsideVolume);
156 const auto innerVelocity = elemVolVars[scvf.insideScvIdx()].velocity();
157 const auto outerVelocity = elemVolVars[scvf.outsideScvIdx()].velocity();
159 const auto rho = problem.insideAndOutsideDensity(element, fvGeometry, scvf);
160 const bool selfIsUpstream = scvf.directionSign() ==
sign(transportingVelocity);
162 const auto insideMomentum = innerVelocity * rho.first;
163 const auto outsideMomentum = outerVelocity * rho.second;
165 static const auto upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(),
"Flux.UpwindWeight");
167 const auto transportedMomentum = selfIsUpstream ? (upwindWeight * insideMomentum + (1.0 - upwindWeight) * outsideMomentum)
168 : (upwindWeight * outsideMomentum + (1.0 - upwindWeight) * insideMomentum);
170 flux[scv.dofAxis()] += transportingVelocity * transportedMomentum * scvf.directionSign();
174 else if (scvf.boundary())
176 const auto insideDensity = problem.density(element, fvGeometry.scv(scvf.insideScvIdx()));
177 const auto innerVelocity = elemVolVars[scvf.insideScvIdx()].velocity();
178 flux[scv.dofAxis()] += innerVelocity * transportingVelocity * insideDensity * scvf.directionSign();
185 DUNE_THROW(Dune::InvalidStateException,
"Face is neither lateral nor frontal.");
198 template<
class Problem,
class FVElementGeometry,
class ElementVolumeVariables,
class ElementFluxVariablesCache,
class TangentialVelocityGradient =
double>
200 const FVElementGeometry& fvGeometry,
201 const typename FVElementGeometry::SubControlVolumeFace& scvf,
202 const ElementVolumeVariables& elemVolVars,
203 const ElementFluxVariablesCache& elemFluxVarsCache,
204 const TangentialVelocityGradient& tangentialVelocityGradient = TangentialVelocityGradient(0.0))
207 using MomentumFlux =
typename Problem::MomentumFluxType;
208 constexpr std::size_t dim =
static_cast<std::size_t
>(FVElementGeometry::GridGeometry::GridView::dimension);
210 MomentumFlux::size() == dim,
211 "Expects momentum flux to have as many entries as dimensions."
214 MomentumFlux flux(0.0);
217 if (scvf.isFrontal())
220 using Scalar = std::decay_t<
decltype(flux[0])>;
221 const auto& scv = fvGeometry.scv(scvf.insideScvIdx());
222 const auto& orthogonalScvf = fvGeometry.lateralOrthogonalScvf(scvf);
223 const auto& orthogonalScv = fvGeometry.scv(orthogonalScvf.insideScvIdx());
225 if (scvf.boundary() && problem.onSlipBoundary(fvGeometry, fvGeometry.frontalScvfOnBoundary(orthogonalScv)))
242 const Scalar velI = elemVolVars[scvf.insideScvIdx()].velocity();
245 const Scalar mu = problem.effectiveViscosity(fvGeometry.element(), fvGeometry, scvf);
246 const Scalar
distance = (scv.dofPosition()- scvf.ipGlobal()).two_norm();
247 const Scalar velGradJI = [&]
249 if (elemVolVars.hasVolVars(orthogonalScvf.outsideScvIdx()))
252 return tangentialVelocityGradient;
255 const Scalar slipVelocity = problem.beaversJosephVelocity(fvGeometry, scvf, elemVolVars, velGradJI)[scv.dofAxis()];
256 const Scalar velGradIJ = (slipVelocity - velI) /
distance * scvf.directionSign();
258 flux[scv.dofAxis()] -= (mu * (velGradIJ + velGradJI))*scvf.directionSign();
261 if (problem.enableInertiaTerms())
264 const auto transportingVelocity = [&]()
266 const auto innerTransportingVelocity = elemVolVars[orthogonalScvf.insideScvIdx()].velocity();
268 if (!elemVolVars.hasVolVars(orthogonalScvf.outsideScvIdx()))
269 return innerTransportingVelocity;
271 const auto outerTransportingVelocity = elemVolVars[orthogonalScvf.outsideScvIdx()].velocity();
274 if (orthogonalScvf.boundary())
275 return outerTransportingVelocity;
277 static const bool useOldScheme = getParam<bool>(
"FreeFlow.UseOldTransportingVelocity",
true);
279 return innerTransportingVelocity;
283 const auto insideVolume = fvGeometry.scv(orthogonalScvf.insideScvIdx()).volume();
284 const auto outsideVolume = fvGeometry.scv(orthogonalScvf.outsideScvIdx()).volume();
285 const auto outerTransportingVelocity = elemVolVars[orthogonalScvf.outsideScvIdx()].velocity();
286 return (insideVolume*innerTransportingVelocity + outsideVolume*outerTransportingVelocity) / (insideVolume + outsideVolume);
292 const auto rho = problem.insideAndOutsideDensity(fvGeometry.element(), fvGeometry, scvf);
293 const auto transportedMomentum = slipVelocity * rho.second;
295 flux[scv.dofAxis()] += transportingVelocity * transportedMomentum * scvf.directionSign();
298 else if (scv.boundary() && problem.onSlipBoundary(fvGeometry, fvGeometry.frontalScvfOnBoundary(scv)))
320 const Scalar velJ = elemVolVars[orthogonalScvf.insideScvIdx()].velocity();
323 const Scalar mu = problem.effectiveViscosity(fvGeometry.element(), fvGeometry, scvf);
324 const Scalar
distance = (fvGeometry.scv(orthogonalScvf.insideScvIdx()).dofPosition()- scvf.ipGlobal()).two_norm();
326 const Scalar velGradIJ = [&]
328 if (elemVolVars.hasVolVars(scvf.outsideScvIdx()))
331 return tangentialVelocityGradient;
334 const Scalar slipVelocity = problem.beaversJosephVelocity(fvGeometry, orthogonalScvf, elemVolVars, velGradIJ)[scvf.normalAxis()];
335 const Scalar velGradJI = (slipVelocity - velJ) /
distance * orthogonalScvf.directionSign();
337 flux[scv.dofAxis()] -= (mu * (velGradIJ + velGradJI))*scvf.directionSign();
340 if (problem.enableInertiaTerms())
343 const auto transportingVelocity = slipVelocity;
346 if (scvf.boundary() && elemVolVars.hasVolVars(scvf.outsideScvIdx()))
348 flux[scv.dofAxis()] += problem.density(fvGeometry.element(), scv)
349 * elemVolVars[scvf.outsideScvIdx()].velocity() * transportingVelocity * scvf.directionSign();
353 const auto innerVelocity = elemVolVars[scvf.insideScvIdx()].velocity();
354 const auto outerVelocity = [&]
356 if (!elemVolVars.hasVolVars(scvf.outsideScvIdx()))
357 return innerVelocity;
359 return elemVolVars[scvf.outsideScvIdx()].velocity();
362 const auto rho = problem.insideAndOutsideDensity(fvGeometry.element(), fvGeometry, scvf);
363 const bool selfIsUpstream = scvf.directionSign() ==
sign(transportingVelocity);
365 const auto insideMomentum = innerVelocity * rho.first;
366 const auto outsideMomentum = outerVelocity * rho.second;
368 static const auto upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(),
"Flux.UpwindWeight");
370 const auto transportedMomentum = selfIsUpstream ? (upwindWeight * insideMomentum + (1.0 - upwindWeight) * outsideMomentum)
371 : (upwindWeight * outsideMomentum + (1.0 - upwindWeight) * insideMomentum);
373 flux[scv.dofAxis()] += transportingVelocity * transportedMomentum * scvf.directionSign();
static auto velocityGradJI(const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolumeFace &scvf, const ElemVolVars &elemVolVars)
Returns the velocity gradient in line with our current scvf.
Definition: momentum/velocitygradients.hh:222
static auto velocityGradIJ(const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolumeFace &scvf, const ElemVolVars &elemVolVars)
Returns the velocity gradient perpendicular to the orientation of our current scvf.
Definition: momentum/velocitygradients.hh:181
constexpr int sign(const ValueType &value) noexcept
Sign or signum function.
Definition: math.hh:629
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
auto volume(const Geometry &geo, unsigned int integrationOrder=4)
The volume of a given geometry.
Definition: volume.hh:159
Define some often used mathematical functions.
The available discretization methods in Dumux.
constexpr FCStaggered fcstaggered
Definition: method.hh:151
std::string pressure(int phaseIdx) noexcept
I/O name of pressure for multiphase systems.
Definition: name.hh:22
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Struct containing flux helper functions to be used in the momentum problem's Neumann function.
Definition: fluxhelper.hh:28
static auto slipVelocityMomentumFlux(const Problem &problem, const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const TangentialVelocityGradient &tangentialVelocityGradient=TangentialVelocityGradient(0.0))
Returns the momentum flux for a boundary with a slip condition.
Definition: fluxhelper.hh:199
static auto fixedPressureMomentumFlux(const Problem &problem, const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const Scalar pressure, const bool zeroNormalVelocityGradient=true)
Returns the momentum flux a fixed-pressure boundary.
Definition: fluxhelper.hh:44