version 3.11-dev
Loading...
Searching...
No Matches
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// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_DISCRETIZATION_UPWINDSCHEME_HH
13#define DUMUX_DISCRETIZATION_UPWINDSCHEME_HH
14
17
18namespace Dumux {
19
21template<class GridGeometry, class DiscretizationMethod>
23
29template<class GridGeometry>
31
32namespace Detail {
33
35template<class Variables, class UpwindTermFunction, class Scalar>
36Scalar upwindSchemeMultiplier(const Variables& insideVars,
37 const Variables& outsideVars,
38 const UpwindTermFunction& upwindTerm,
39 Scalar flux, int phaseIdx, Scalar upwindWeight)
40{
41 using std::signbit;
42 if (signbit(flux)) // if sign of flux is negative
43 return (upwindWeight*upwindTerm(outsideVars)
44 + (1.0 - upwindWeight)*upwindTerm(insideVars));
45 else
46 return (upwindWeight*upwindTerm(insideVars)
47 + (1.0 - upwindWeight)*upwindTerm(outsideVars));
48}
49
51template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
52Scalar upwindSchemeMultiplier(const ElemVolVars& elemVolVars,
53 const SubControlVolumeFace& scvf,
54 const UpwindTermFunction& upwindTerm,
55 Scalar flux, int phaseIdx)
56{
57 static const Scalar upwindWeight = getParamFromGroup<Scalar>(elemVolVars.gridVolVars().problem().paramGroup(), "Flux.UpwindWeight");
58
59 return upwindSchemeMultiplier(elemVolVars[scvf.insideScvIdx()], elemVolVars[scvf.outsideScvIdx()],
60 upwindTerm, flux, phaseIdx, upwindWeight);
61}
62
63} // end namespace Detail
64
66template<class GridGeometry, class DM>
68{
69public:
71 template<class FluxVariables, class UpwindTermFunction, class Scalar>
72 static Scalar apply(const FluxVariables& fluxVars,
73 const UpwindTermFunction& upwindTerm,
74 Scalar flux, int phaseIdx)
75 {
76 return apply(fluxVars.elemVolVars(), fluxVars.scvFace(), upwindTerm, flux, phaseIdx);
77 }
78
80 template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
81 static Scalar apply(const ElemVolVars& elemVolVars,
82 const SubControlVolumeFace& scvf,
83 const UpwindTermFunction& upwindTerm,
84 Scalar flux, int phaseIdx)
85 {
86 return flux*multiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
87 }
88
90 template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
91 static Scalar multiplier(const ElemVolVars& elemVolVars,
92 const SubControlVolumeFace& scvf,
93 const UpwindTermFunction& upwindTerm,
94 Scalar flux, int phaseIdx)
95 {
96 return Detail::upwindSchemeMultiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
97 }
98};
99
101template<class GridGeometry>
102class UpwindSchemeImpl<GridGeometry, DiscretizationMethods::CCTpfa>
103{
104 using GridView = typename GridGeometry::GridView;
105 static constexpr int dim = GridView::dimension;
106 static constexpr int dimWorld = GridView::dimensionworld;
107
108public:
110 template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
111 static Scalar multiplier(const ElemVolVars& elemVolVars,
112 const SubControlVolumeFace& scvf,
113 const UpwindTermFunction& upwindTerm,
114 Scalar flux, int phaseIdx)
115 {
116 static_assert(dim == dimWorld, "Multiplier cannot be computed on surface grids using cell-centered scheme!");
117 return Detail::upwindSchemeMultiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
118 }
119
121 template<class ElemVolVars, class SubControlVolumeFace, class UpwindTermFunction, class Scalar>
122 static Scalar apply(const ElemVolVars& elemVolVars,
123 const SubControlVolumeFace& scvf,
124 const UpwindTermFunction& upwindTerm,
125 Scalar flux, int phaseIdx)
126 {
127 static_assert(dim == dimWorld, "This upwind scheme cannot be used on surface grids using cell-centered schemes!");
128 return flux*multiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
129 }
130
131 // For surface and network grids (dim < dimWorld) we have to do a special upwind scheme
132 template<class FluxVariables, class UpwindTermFunction, class Scalar>
133 static Scalar apply(const FluxVariables& fluxVars,
134 const UpwindTermFunction& upwindTerm,
135 Scalar flux, int phaseIdx)
136 {
137 const auto& scvf = fluxVars.scvFace();
138 const auto& elemVolVars = fluxVars.elemVolVars();
139
140 // standard scheme
141 if constexpr (dim == dimWorld)
142 return apply(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
143
144 // on non-branching points the standard scheme works
145 if (scvf.numOutsideScvs() == 1)
146 return flux*Detail::upwindSchemeMultiplier(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
147
148 // handle branching points with a more complicated upwind scheme
149 // we compute a flux-weighted average of all inflowing branches
150 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
151
152 Scalar branchingPointUpwindTerm = 0.0;
153 Scalar sumUpwindFluxes = 0.0;
154
155 // if the inside flux is positive (outflow) do fully upwind and return flux
156 using std::signbit;
157 if (!signbit(flux))
158 return upwindTerm(insideVolVars)*flux;
159 else
160 sumUpwindFluxes += flux;
161
162 for (unsigned int i = 0; i < scvf.numOutsideScvs(); ++i)
163 {
164 // compute the outside flux
165 const auto& fvGeometry = fluxVars.fvGeometry();
166 const auto outsideScvIdx = scvf.outsideScvIdx(i);
167 const auto outsideElement = fvGeometry.gridGeometry().element(outsideScvIdx);
168 const auto& flippedScvf = fvGeometry.flipScvf(scvf.index(), i);
169
170 using AdvectionType = typename FluxVariables::AdvectionType;
171 const auto outsideFlux = AdvectionType::flux(fluxVars.problem(),
172 outsideElement,
173 fvGeometry,
174 elemVolVars,
175 flippedScvf,
176 phaseIdx,
177 fluxVars.elemFluxVarsCache());
178
179 if (!signbit(outsideFlux))
180 branchingPointUpwindTerm += upwindTerm(elemVolVars[outsideScvIdx])*outsideFlux;
181 else
182 sumUpwindFluxes += outsideFlux;
183 }
184
185 // the flux might be zero
186 if (sumUpwindFluxes != 0.0)
187 branchingPointUpwindTerm /= -sumUpwindFluxes;
188 else
189 branchingPointUpwindTerm = 0.0;
190
191 // upwind scheme (always do fully upwind at branching points)
192 // a weighting here would lead to an error since the derivation is based on a fully upwind scheme
193 // TODO How to implement a weight of e.g. 0.5
194 if (signbit(flux))
195 return flux*branchingPointUpwindTerm;
196 else
197 return flux*upwindTerm(insideVolVars);
198 }
199};
200
202template<class GridGeometry>
204: public UpwindSchemeImpl<GridGeometry, DiscretizationMethods::CCTpfa> {};
205
206} // end namespace Dumux
207
208#endif
static Scalar apply(const FluxVariables &fluxVars, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
Definition flux/upwindscheme.hh:133
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:122
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:111
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:91
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:81
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:72
Forward declaration of the upwind scheme implementation.
Definition flux/upwindscheme.hh:22
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
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:165
The available discretization methods in Dumux.
Definition cellcentered/mpfa/elementvolumevariables.hh:24
Definition interpolate.hh:27
Definition cvfelocalresidual.hh:25
Scalar upwindSchemeMultiplier(const Variables &insideVars, const Variables &outsideVars, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx, Scalar upwindWeight)
returns the upwind factor which is multiplied to the advective flux between the two given variables
Definition flux/upwindscheme.hh:36
Definition method.hh:20
Definition adapt.hh:17
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.