3.4
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
flux/upwindscheme.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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_DISCRETIZATION_UPWINDSCHEME_HH
25#define DUMUX_DISCRETIZATION_UPWINDSCHEME_HH
26
29
30namespace Dumux {
31
33template<class GridGeometry, DiscretizationMethod discMethod>
35
41template<class GridGeometry>
43
44namespace Detail {
45
47template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
48Scalar upwindSchemeMultiplier(const ElemVolVars& elemVolVars,
49 const SubControlVolumeFace& scvf,
50 const UpwindTermFunction& upwindTerm,
51 Scalar flux, int phaseIdx)
52{
53 // TODO: pass this from outside?
54 static const Scalar upwindWeight = getParamFromGroup<Scalar>(elemVolVars.gridVolVars().problem().paramGroup(), "Flux.UpwindWeight");
55
56 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
57 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
58
59 using std::signbit;
60 if (signbit(flux)) // if sign of flux is negative
61 return (upwindWeight*upwindTerm(outsideVolVars)
62 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
63 else
64 return (upwindWeight*upwindTerm(insideVolVars)
65 + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
66}
67
68} // end namespace Detail
69
71template<class GridGeometry>
73{
74public:
76 template<class FluxVariables, class UpwindTermFunction, class Scalar>
77 static Scalar apply(const FluxVariables& fluxVars,
78 const UpwindTermFunction& upwindTerm,
79 Scalar flux, int phaseIdx)
80 {
81 return apply(fluxVars.elemVolVars(), fluxVars.scvFace(), upwindTerm, flux, phaseIdx);
82 }
83
85 template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
86 static Scalar apply(const ElemVolVars& elemVolVars,
87 const SubControlVolumeFace& scvf,
88 const UpwindTermFunction& upwindTerm,
89 Scalar flux, int phaseIdx)
90 {
91 return flux*multiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
92 }
93
95 template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
96 static Scalar multiplier(const ElemVolVars& elemVolVars,
97 const SubControlVolumeFace& scvf,
98 const UpwindTermFunction& upwindTerm,
99 Scalar flux, int phaseIdx)
100 {
101 return Detail::upwindSchemeMultiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
102 }
103};
104
106template<class GridGeometry>
108{
109 using GridView = typename GridGeometry::GridView;
110 static constexpr int dim = GridView::dimension;
111 static constexpr int dimWorld = GridView::dimensionworld;
112
113public:
115 template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
116 static Scalar multiplier(const ElemVolVars& elemVolVars,
117 const SubControlVolumeFace& scvf,
118 const UpwindTermFunction& upwindTerm,
119 Scalar flux, int phaseIdx)
120 {
121 static_assert(dim == dimWorld, "Multiplier cannot be computed on surface grids using cell-centered scheme!");
122 return Detail::upwindSchemeMultiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
123 }
124
126 template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
127 static Scalar apply(const ElemVolVars& elemVolVars,
128 const SubControlVolumeFace& scvf,
129 const UpwindTermFunction& upwindTerm,
130 Scalar flux, int phaseIdx)
131 {
132 static_assert(dim == dimWorld, "This upwind scheme cannot be used on surface grids using cell-centered schemes!");
133 return flux*multiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
134 }
135
136 // For surface and network grids (dim < dimWorld) we have to do a special upwind scheme
137 template<class FluxVariables, class UpwindTermFunction, class Scalar>
138 static Scalar apply(const FluxVariables& fluxVars,
139 const UpwindTermFunction& upwindTerm,
140 Scalar flux, int phaseIdx)
141 {
142 const auto& scvf = fluxVars.scvFace();
143 const auto& elemVolVars = fluxVars.elemVolVars();
144
145 // standard scheme
146 if constexpr (dim == dimWorld)
147 return apply(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
148
149 // on non-branching points the standard scheme works
150 if (scvf.numOutsideScvs() == 1)
151 return flux*Detail::upwindSchemeMultiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
152
153 // handle branching points with a more complicated upwind scheme
154 // we compute a flux-weighted average of all inflowing branches
155 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
156
157 Scalar branchingPointUpwindTerm = 0.0;
158 Scalar sumUpwindFluxes = 0.0;
159
160 // if the inside flux is positive (outflow) do fully upwind and return flux
161 using std::signbit;
162 if (!signbit(flux))
163 return upwindTerm(insideVolVars)*flux;
164 else
165 sumUpwindFluxes += flux;
166
167 for (unsigned int i = 0; i < scvf.numOutsideScvs(); ++i)
168 {
169 // compute the outside flux
170 const auto& fvGeometry = fluxVars.fvGeometry();
171 const auto outsideScvIdx = scvf.outsideScvIdx(i);
172 const auto outsideElement = fvGeometry.gridGeometry().element(outsideScvIdx);
173 const auto& flippedScvf = fvGeometry.flipScvf(scvf.index(), i);
174
175 using AdvectionType = typename FluxVariables::AdvectionType;
176 const auto outsideFlux = AdvectionType::flux(fluxVars.problem(),
177 outsideElement,
178 fvGeometry,
179 elemVolVars,
180 flippedScvf,
181 phaseIdx,
182 fluxVars.elemFluxVarsCache());
183
184 if (!signbit(outsideFlux))
185 branchingPointUpwindTerm += upwindTerm(elemVolVars[outsideScvIdx])*outsideFlux;
186 else
187 sumUpwindFluxes += outsideFlux;
188 }
189
190 // the flux might be zero
191 if (sumUpwindFluxes != 0.0)
192 branchingPointUpwindTerm /= -sumUpwindFluxes;
193 else
194 branchingPointUpwindTerm = 0.0;
195
196 // upwind scheme (always do fully upwind at branching points)
197 // a weighting here would lead to an error since the derivation is based on a fully upwind scheme
198 // TODO How to implement a weight of e.g. 0.5
199 if (signbit(flux))
200 return flux*branchingPointUpwindTerm;
201 else
202 return flux*upwindTerm(insideVolVars);
203 }
204};
205
207template<class GridGeometry>
209: public UpwindSchemeImpl<GridGeometry, DiscretizationMethod::cctpfa> {};
210
211} // end namespace Dumux
212
213#endif
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The available discretization methods in Dumux.
DiscretizationMethod
The available discretization methods in Dumux.
Definition: method.hh:37
Definition: adapt.hh:29
Scalar upwindSchemeMultiplier(const ElemVolVars &elemVolVars, const SubControlVolumeFace &scvf, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
returns the upwind factor which is multiplied to the advective flux across the given scvf
Definition: flux/upwindscheme.hh:48
Forward declaration of the upwind scheme implementation.
Definition: flux/upwindscheme.hh:34
static Scalar multiplier(const ElemVolVars &elemVolVars, const SubControlVolumeFace &scvf, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
returns the upwind factor which is multiplied to the advective flux across the given scvf
Definition: flux/upwindscheme.hh:96
static Scalar apply(const ElemVolVars &elemVolVars, const SubControlVolumeFace &scvf, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
applies a simple upwind scheme to the precalculated advective flux across the given scvf
Definition: flux/upwindscheme.hh:86
static Scalar apply(const FluxVariables &fluxVars, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
applies a simple upwind scheme to the precalculated advective flux
Definition: flux/upwindscheme.hh:77
static Scalar apply(const ElemVolVars &elemVolVars, const SubControlVolumeFace &scvf, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
applies a simple upwind scheme to the precalculated advective flux across the given scvf
Definition: flux/upwindscheme.hh:127
static Scalar multiplier(const ElemVolVars &elemVolVars, const SubControlVolumeFace &scvf, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
returns the upwind factor which is multiplied to the advective flux across the given scvf
Definition: flux/upwindscheme.hh:116
static Scalar apply(const FluxVariables &fluxVars, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
Definition: flux/upwindscheme.hh:138