version 3.10-dev
scalarfluxhelper.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_NAVIERSTOKES_SCALAR_BOUNDARY_FLUXHELPER_HH
13#define DUMUX_NAVIERSTOKES_SCALAR_BOUNDARY_FLUXHELPER_HH
14
15#include <dune/common/float_cmp.hh>
16#include <dune/common/std/type_traits.hh>
17#include <dumux/common/math.hh>
20
21namespace Dumux {
22
23#ifndef DOXYGEN
24namespace Detail {
25// helper structs and functions detecting if the VolumeVariables belong to a non-isothermal model
26template <class Indices>
27using NonisothermalDetector = decltype(std::declval<Indices>().energyEqIdx);
28
29template<class Indices>
30static constexpr bool isNonIsothermal()
31{ return Dune::Std::is_detected<NonisothermalDetector, Indices>::value; }
32
33} // end namespace Detail
34#endif
35
40template<class AdvectiveFlux>
42{
46 template<class VolumeVariables, class SubControlVolumeFace, class Scalar, class UpwindTerm>
47 static Scalar advectiveScalarUpwindFlux(const VolumeVariables& insideVolVars,
48 const VolumeVariables& outsideVolVars,
49 const SubControlVolumeFace& scvf,
50 const Scalar volumeFlux,
51 const Scalar upwindWeight,
52 UpwindTerm upwindTerm)
53 {
54 using std::signbit;
55 const bool insideIsUpstream = !signbit(volumeFlux);
56
57 const auto& upstreamVolVars = insideIsUpstream ? insideVolVars : outsideVolVars;
58 const auto& downstreamVolVars = insideIsUpstream ? outsideVolVars : insideVolVars;
59
60 return (upwindWeight * upwindTerm(upstreamVolVars) +
61 (1.0 - upwindWeight) * upwindTerm(downstreamVolVars))
62 * volumeFlux;
63 }
64
65 template<class Indices, class NumEqVector, class UpwindFunction>
67 const UpwindFunction& upwind)
68 {
69 // add advective fluxes based on physical type of model
70 AdvectiveFlux::addAdvectiveFlux(flux, upwind);
71
72 // for non-isothermal models, add the energy flux
73 if constexpr (Detail::isNonIsothermal<Indices>())
74 {
75 auto upwindTerm = [](const auto& volVars) { return volVars.density()*volVars.enthalpy(); };
76 flux[Indices::energyEqIdx] = upwind(upwindTerm);
77 }
78 }
79
84 template<class Problem, class Element, class FVElementGeometry, class ElementVolumeVariables>
85 static auto scalarOutflowFlux(const Problem& problem,
86 const Element& element,
87 const FVElementGeometry& fvGeometry,
88 const typename FVElementGeometry::SubControlVolumeFace& scvf,
89 const ElementVolumeVariables& elemVolVars,
90 typename ElementVolumeVariables::VolumeVariables::PrimaryVariables&& outsideBoundaryPriVars,
91 const typename ElementVolumeVariables::VolumeVariables::PrimaryVariables::value_type upwindWeight = 1.0)
92 {
93 using VolumeVariables = typename ElementVolumeVariables::VolumeVariables;
94 using PrimaryVariables = typename VolumeVariables::PrimaryVariables;
95 using NumEqVector = PrimaryVariables;
96 NumEqVector flux;
97 const auto velocity = problem.faceVelocity(element,fvGeometry, scvf);
98 const auto volumeFlux = velocity * scvf.unitOuterNormal();
99 using std::signbit;
100 const bool insideIsUpstream = !signbit(volumeFlux);
101 const VolumeVariables& insideVolVars = elemVolVars[scvf.insideScvIdx()];
102 const VolumeVariables& outsideVolVars = [&]()
103 {
104 // only use the inside volVars for "true" outflow conditions (avoid constructing the outside volVars)
105 if (insideIsUpstream && Dune::FloatCmp::eq(upwindWeight, 1.0, 1e-6))
106 return insideVolVars;
107 else
108 {
109 // construct outside volVars from the given priVars for situations of flow reversal
110 VolumeVariables boundaryVolVars;
111 boundaryVolVars.update(elementSolution<FVElementGeometry>(std::forward<PrimaryVariables>(outsideBoundaryPriVars)),
112 problem,
113 element,
114 fvGeometry.scv(scvf.insideScvIdx()));
115 return boundaryVolVars;
116 }
117 }();
118
119 auto upwindFuntion = [&](const auto& upwindTerm)
120 {
121 return advectiveScalarUpwindFlux(insideVolVars, outsideVolVars, scvf, volumeFlux, upwindWeight, upwindTerm);
122 };
123
124 addModelSpecificAdvectiveFlux<typename VolumeVariables::Indices>(flux, upwindFuntion);
125
126 return flux;
127 }
128
134 template<class Problem, class Element, class FVElementGeometry, class ElementVolumeVariables>
135 static auto scalarOutflowFlux(const Problem& problem,
136 const Element& element,
137 const FVElementGeometry& fvGeometry,
138 const typename FVElementGeometry::SubControlVolumeFace& scvf,
139 const ElementVolumeVariables& elemVolVars)
140 {
141 using VolumeVariables = typename ElementVolumeVariables::VolumeVariables;
142 using NumEqVector = typename VolumeVariables::PrimaryVariables;
143 NumEqVector flux;
144 const auto velocity = problem.faceVelocity(element,fvGeometry, scvf);
145 const auto volumeFlux = velocity * scvf.unitOuterNormal();
146 using std::signbit;
147 const bool insideIsUpstream = !signbit(volumeFlux);
148 const VolumeVariables& insideVolVars = elemVolVars[scvf.insideScvIdx()];
149
150 if constexpr (VolumeVariables::FluidSystem::isCompressible(0/*phaseIdx*/) /*TODO viscosityIsConstant*/ || NumEqVector::size() > 1)
151 {
152 static const bool verbose = getParamFromGroup<bool>(problem.paramGroup(), "Flux.EnableOutflowReversalWarning", true);
153 using std::abs;
154 if (verbose && !insideIsUpstream && abs(volumeFlux) > 1e-10)
155 {
156 std::cout << "velo " << velocity << ", flux " << volumeFlux << std::endl;
157 std::cout << "\n ********** WARNING ********** \n\n"
158 "Outflow condition set at " << scvf.center() << " might be invalid due to flow reversal. "
159 "Consider using \n"
160 "scalarOutflowFlux(problem, element, fvGeometry, scvf, elemVolVars, outsideBoundaryPriVars, upwindWeight) \n"
161 "instead where you can specify primary variables for inflow situations.\n"
162 "\n ***************************** \n" << std::endl;
163 }
164 }
165
166 auto upwindFuntion = [&](const auto& upwindTerm)
167 {
168 return advectiveScalarUpwindFlux(insideVolVars, insideVolVars, scvf, volumeFlux, 1.0 /*upwindWeight*/, upwindTerm);
169 };
170
171 addModelSpecificAdvectiveFlux<typename VolumeVariables::Indices>(flux, upwindFuntion);
172
173 return flux;
174 }
175};
176
177} // end namespace Dumux
178
179#endif
Element solution classes and factory functions.
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
Define some often used mathematical functions.
Definition: adapt.hh:17
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Navier Stokes scalar boundary flux helper.
Definition: scalarfluxhelper.hh:42
static Scalar advectiveScalarUpwindFlux(const VolumeVariables &insideVolVars, const VolumeVariables &outsideVolVars, const SubControlVolumeFace &scvf, const Scalar volumeFlux, const Scalar upwindWeight, UpwindTerm upwindTerm)
Return the area-specific, weighted advective flux of a scalar quantity.
Definition: scalarfluxhelper.hh:47
static auto scalarOutflowFlux(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars)
Return the area-specific outflow fluxes for all scalar balance equations. This should only be used if...
Definition: scalarfluxhelper.hh:135
static auto scalarOutflowFlux(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, typename ElementVolumeVariables::VolumeVariables::PrimaryVariables &&outsideBoundaryPriVars, const typename ElementVolumeVariables::VolumeVariables::PrimaryVariables::value_type upwindWeight=1.0)
Return the area-specific outflow fluxes for all scalar balance equations. The values specified in out...
Definition: scalarfluxhelper.hh:85
static void addModelSpecificAdvectiveFlux(NumEqVector &flux, const UpwindFunction &upwind)
Definition: scalarfluxhelper.hh:66