version 3.10-dev
multidomain/facet/cellcentered/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-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
13#ifndef DUMUX_MIXEDDIMENSION_FACET_CC_UPWINDSCHEME_HH
14#define DUMUX_MIXEDDIMENSION_FACET_CC_UPWINDSCHEME_HH
15
19
20namespace Dumux {
21
28template<class GridGeometry>
30{
31 using GridView = typename GridGeometry::GridView;
32 static constexpr int dim = GridView::dimension;
33 static constexpr int dimWorld = GridView::dimensionworld;
34
35public:
36 // For surface and network grids (dim < dimWorld) we have to do a special upwind scheme
37 template<class FluxVariables, class UpwindTermFunction, class Scalar, int d = dim, int dw = dimWorld>
38 static typename std::enable_if<(d < dw), Scalar>::type
39 apply(const FluxVariables& fluxVars,
40 const UpwindTermFunction& upwindTerm,
41 Scalar flux, int phaseIdx)
42 {
43 static const Scalar upwindWeight = getParam<Scalar>("Flux.UpwindWeight");
44
45 // the volume variables of the inside sub-control volume
46 const auto& scvf = fluxVars.scvFace();
47 const auto& elemVolVars = fluxVars.elemVolVars();
48 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
49
50 // check if this is an interior boundary
51 const auto& cm = fluxVars.problem().couplingManager();
52 if (cm.isOnInteriorBoundary(fluxVars.element(), scvf))
53 {
54 const auto& outsideVolVars = cm.getLowDimVolVars(fluxVars.element(), scvf);
55 if (std::signbit(flux))
56 return flux*(upwindWeight*upwindTerm(outsideVolVars)
57 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
58 else
59 return flux*(upwindWeight*upwindTerm(insideVolVars)
60 + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
61 }
62 else
63 {
64 // check if this is a branching point
65 if (scvf.numOutsideScvs() > 1)
66 {
67 // more complicated upwind scheme
68 // we compute a flux-weighted average of all inflowing branches
69 Scalar branchingPointUpwindTerm = 0.0;
70 Scalar sumUpwindFluxes = 0.0;
71
72 // if the inside flux is positive (outflow) do fully upwind and return flux
73 if (!std::signbit(flux))
74 return upwindTerm(insideVolVars)*flux;
75 else
76 sumUpwindFluxes += flux;
77
78 for (unsigned int i = 0; i < scvf.numOutsideScvs(); ++i)
79 {
80 // compute the outside flux
81 const auto& fvGeometry = fluxVars.fvGeometry();
82 const auto outsideScvIdx = scvf.outsideScvIdx(i);
83 const auto outsideElement = fvGeometry.gridGeometry().element(outsideScvIdx);
84 const auto& flippedScvf = fvGeometry.flipScvf(scvf.index(), i);
85
86 using AdvectionType = typename FluxVariables::AdvectionType;
87 const auto outsideFlux = AdvectionType::flux(fluxVars.problem(),
88 outsideElement,
89 fvGeometry,
90 elemVolVars,
91 flippedScvf,
92 phaseIdx,
93 fluxVars.elemFluxVarsCache());
94
95 if (!std::signbit(outsideFlux))
96 branchingPointUpwindTerm += upwindTerm(elemVolVars[outsideScvIdx])*outsideFlux;
97 else
98 sumUpwindFluxes += outsideFlux;
99 }
100
101 // the flux might be zero
102 if (sumUpwindFluxes != 0.0)
103 branchingPointUpwindTerm /= -sumUpwindFluxes;
104 else
105 branchingPointUpwindTerm = 0.0;
106
107 // upwind scheme (always do fully upwind at branching points)
108 // a weighting here would lead to an error since the derivation is based on a fully upwind scheme
109 // TODO How to implement a weight of e.g. 0.5
110 if (std::signbit(flux))
111 return flux*branchingPointUpwindTerm;
112 else
113 return flux*upwindTerm(insideVolVars);
114 }
115 // non-branching points and boundaries
116 else
117 {
118 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
119 if (std::signbit(flux))
120 return flux*(upwindWeight*upwindTerm(outsideVolVars)
121 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
122 else
123 return flux*(upwindWeight*upwindTerm(insideVolVars)
124 + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
125 }
126 }
127 }
128
129 // For grids with dim == dimWorld we use a simple upwinding scheme
130 template<class FluxVariables, class UpwindTermFunction, class Scalar, int d = dim, int dw = dimWorld>
131 static typename std::enable_if<(d == dw), Scalar>::type
132 apply(const FluxVariables& fluxVars,
133 const UpwindTermFunction& upwindTerm,
134 Scalar flux, int phaseIdx)
135 {
136 static const Scalar upwindWeight = getParam<Scalar>("Flux.UpwindWeight");
137
138 const auto& scvf = fluxVars.scvFace();
139 const auto& elemVolVars = fluxVars.elemVolVars();
140 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
141
142 // check if this is an interior boundary
143 const auto& cm = fluxVars.problem().couplingManager();
144 if (cm.isOnInteriorBoundary(fluxVars.element(), scvf))
145 {
146 // upwind scheme
147 const auto& outsideVolVars = cm.getLowDimVolVars(fluxVars.element(), scvf);
148 if (std::signbit(flux))
149 return flux*(upwindWeight*upwindTerm(outsideVolVars)
150 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
151 else
152 return flux*(upwindWeight*upwindTerm(insideVolVars)
153 + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
154 }
155 else
156 {
157 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
158
159 if (std::signbit(flux)) // if sign of flux is negative
160 return flux*(upwindWeight*upwindTerm(outsideVolVars)
161 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
162 else
163 return flux*(upwindWeight*upwindTerm(insideVolVars)
164 + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
165 }
166 }
167};
168
169} // end namespace Dumux
170
171#endif
The upwind scheme used for the advective fluxes. This is a modified scheme for models involving coupl...
Definition: multidomain/facet/cellcentered/upwindscheme.hh:30
static std::enable_if<(d< dw), Scalar >::type apply(const FluxVariables &fluxVars, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
Definition: multidomain/facet/cellcentered/upwindscheme.hh:39
static std::enable_if<(d==dw), Scalar >::type apply(const FluxVariables &fluxVars, const UpwindTermFunction &upwindTerm, Scalar flux, int phaseIdx)
Definition: multidomain/facet/cellcentered/upwindscheme.hh:132
Defines all properties used in Dumux.
The available discretization methods in Dumux.
Definition: adapt.hh:17
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.