GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/multidomain/facet/cellcentered/upwindscheme.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 39 57 68.4%
Functions: 12 12 100.0%
Branches: 38 60 63.3%

Line Branch Exec Source
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 //
7 /*!
8 * \file
9 * \ingroup FacetCoupling
10 * \brief Modified upwind scheme for models using cell-centered schemes
11 * with coupling across element facets.
12 */
13 #ifndef DUMUX_MIXEDDIMENSION_FACET_CC_UPWINDSCHEME_HH
14 #define DUMUX_MIXEDDIMENSION_FACET_CC_UPWINDSCHEME_HH
15
16 #include <dumux/common/properties.hh>
17 #include <dumux/common/parameters.hh>
18 #include <dumux/discretization/method.hh>
19
20 namespace Dumux {
21
22 /*!
23 * \ingroup FacetCoupling
24 * \brief The upwind scheme used for the advective fluxes.
25 * This is a modified scheme for models involving coupling
26 * with a lower-dimensional domain across the element facets.
27 */
28 template<class GridGeometry>
29 class CCFacetCouplingUpwindScheme
30 {
31 using GridView = typename GridGeometry::GridView;
32 static constexpr int dim = GridView::dimension;
33 static constexpr int dimWorld = GridView::dimensionworld;
34
35 public:
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 27587296 apply(const FluxVariables& fluxVars,
40 const UpwindTermFunction& upwindTerm,
41 Scalar flux, int phaseIdx)
42 {
43
4/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7875417 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
27587296 static const Scalar upwindWeight = getParam<Scalar>("Flux.UpwindWeight");
44
45 // the volume variables of the inside sub-control volume
46 27587296 const auto& scvf = fluxVars.scvFace();
47 27587296 const auto& elemVolVars = fluxVars.elemVolVars();
48 32916388 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
49
50 // check if this is an interior boundary
51
2/2
✓ Branch 0 taken 242700 times.
✓ Branch 1 taken 7632724 times.
27587296 const auto& cm = fluxVars.problem().couplingManager();
52
4/4
✓ Branch 0 taken 242700 times.
✓ Branch 1 taken 7632724 times.
✓ Branch 2 taken 242700 times.
✓ Branch 3 taken 7632724 times.
55174592 if (cm.isOnInteriorBoundary(fluxVars.element(), scvf))
53 {
54 919500 const auto& outsideVolVars = cm.getLowDimVolVars(fluxVars.element(), scvf);
55
4/4
✓ Branch 0 taken 57878 times.
✓ Branch 1 taken 184822 times.
✓ Branch 2 taken 57878 times.
✓ Branch 3 taken 184822 times.
1839000 if (std::signbit(flux))
56 436034 return flux*(upwindWeight*upwindTerm(outsideVolVars)
57 572298 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
58 else
59 483466 return flux*(upwindWeight*upwindTerm(insideVolVars)
60 597942 + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
61 }
62 else
63 {
64 // check if this is a branching point
65
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7632724 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7632724 times.
53335592 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 53335592 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
119
4/4
✓ Branch 0 taken 3659185 times.
✓ Branch 1 taken 3973539 times.
✓ Branch 2 taken 3659185 times.
✓ Branch 3 taken 3973539 times.
53335592 if (std::signbit(flux))
120 12851503 return flux*(upwindWeight*upwindTerm(outsideVolVars)
121 16645518 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
122 else
123 13816293 return flux*(upwindWeight*upwindTerm(insideVolVars)
124 17842634 + (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 39136373 apply(const FluxVariables& fluxVars,
133 const UpwindTermFunction& upwindTerm,
134 Scalar flux, int phaseIdx)
135 {
136
4/6
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 11102385 times.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
39136373 static const Scalar upwindWeight = getParam<Scalar>("Flux.UpwindWeight");
137
138 39136373 const auto& scvf = fluxVars.scvFace();
139 39136373 const auto& elemVolVars = fluxVars.elemVolVars();
140 49197906 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
141
142 // check if this is an interior boundary
143
2/2
✓ Branch 0 taken 307956 times.
✓ Branch 1 taken 10794452 times.
39136373 const auto& cm = fluxVars.problem().couplingManager();
144
4/4
✓ Branch 0 taken 307956 times.
✓ Branch 1 taken 10794452 times.
✓ Branch 2 taken 307956 times.
✓ Branch 3 taken 10794452 times.
78272746 if (cm.isOnInteriorBoundary(fluxVars.element(), scvf))
145 {
146 // upwind scheme
147 1604244 const auto& outsideVolVars = cm.getLowDimVolVars(fluxVars.element(), scvf);
148
4/4
✓ Branch 0 taken 56734 times.
✓ Branch 1 taken 251222 times.
✓ Branch 2 taken 56734 times.
✓ Branch 3 taken 251222 times.
3208488 if (std::signbit(flux))
149 750598 return flux*(upwindWeight*upwindTerm(outsideVolVars)
150 1255680 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
151 else
152 853646 return flux*(upwindWeight*upwindTerm(insideVolVars)
153 1304280 + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
154 }
155 else
156 {
157 75064258 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
158
159
4/4
✓ Branch 0 taken 5088676 times.
✓ Branch 1 taken 5705776 times.
✓ Branch 2 taken 5088676 times.
✓ Branch 3 taken 5705776 times.
75064258 if (std::signbit(flux)) // if sign of flux is negative
160 18141912 return flux*(upwindWeight*upwindTerm(outsideVolVars)
161 27479474 + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
162 else
163 19390217 return flux*(upwindWeight*upwindTerm(insideVolVars)
164 29279024 + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
165 }
166 }
167 };
168
169 } // end namespace Dumux
170
171 #endif
172