GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/freeflow/navierstokes/scalarfluxhelper.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 22 28 78.6%
Functions: 14 53 26.4%
Branches: 10 22 45.5%

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 NavierStokesModel
10 * \brief Navier Stokes scalar boundary flux helper
11 */
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>
18 #include <dumux/common/parameters.hh>
19 #include <dumux/discretization/elementsolution.hh>
20
21 namespace Dumux {
22
23 #ifndef DOXYGEN
24 namespace Detail {
25 // helper structs and functions detecting if the VolumeVariables belong to a non-isothermal model
26 template <class Indices>
27 using NonisothermalDetector = decltype(std::declval<Indices>().energyEqIdx);
28
29 template<class Indices>
30 static constexpr bool isNonIsothermal()
31 { return Dune::Std::is_detected<NonisothermalDetector, Indices>::value; }
32
33 } // end namespace Detail
34 #endif
35
36 /*!
37 * \ingroup NavierStokesModel
38 * \brief Navier Stokes scalar boundary flux helper
39 */
40 template<class AdvectiveFlux>
41 struct NavierStokesScalarBoundaryFluxHelper
42 {
43 /*!
44 * \brief Return the area-specific, weighted advective flux of a scalar quantity.
45 */
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
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
98700 const bool insideIsUpstream = !signbit(volumeFlux);
56
57
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
49350 const auto& upstreamVolVars = insideIsUpstream ? insideVolVars : outsideVolVars;
58
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
49350 const auto& downstreamVolVars = insideIsUpstream ? outsideVolVars : insideVolVars;
59
60 716889 return (upwindWeight * upwindTerm(upstreamVolVars) +
61 477926 (1.0 - upwindWeight) * upwindTerm(downstreamVolVars))
62 238963 * volumeFlux;
63 }
64
65 template<class Indices, class NumEqVector, class UpwindFunction>
66 26910 static void addModelSpecificAdvectiveFlux(NumEqVector& flux,
67 const UpwindFunction& upwind)
68 {
69 // add advective fluxes based on physical type of model
70 440126 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 80730 flux[Indices::energyEqIdx] = upwind(upwindTerm);
77 }
78 26910 }
79
80 /*!
81 * \brief Return the area-specific outflow fluxes for all scalar balance equations.
82 * The values specified in outsideBoundaryPriVars are used in case of flow reversal.
83 */
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
129 /*!
130 * \brief Return the area-specific outflow fluxes for all scalar balance equations.
131 * This should only be used if flow reversal never occurs.
132 * A (deactivable) warning is emitted otherwise.
133 */
134 template<class Problem, class Element, class FVElementGeometry, class ElementVolumeVariables>
135 238963 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 238963 NumEqVector flux;
144 238963 const auto velocity = problem.faceVelocity(element,fvGeometry, scvf);
145 406872 const auto volumeFlux = velocity * scvf.unitOuterNormal();
146 using std::signbit;
147 238963 const bool insideIsUpstream = !signbit(volumeFlux);
148 477926 const VolumeVariables& insideVolVars = elemVolVars[scvf.insideScvIdx()];
149
150 if constexpr (VolumeVariables::FluidSystem::isCompressible(0/*phaseIdx*/) /*TODO viscosityIsConstant*/ || NumEqVector::size() > 1)
151 {
152
5/8
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 49342 times.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 8 times.
✗ Branch 10 not taken.
49350 static const bool verbose = getParamFromGroup<bool>(problem.paramGroup(), "Flux.EnableOutflowReversalWarning", true);
153 using std::abs;
154
5/8
✓ Branch 0 taken 49350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11581 times.
✓ Branch 3 taken 37769 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11581 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11581 times.
49350 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 238963 auto upwindFuntion = [&](const auto& upwindTerm)
167 {
168 451676 return advectiveScalarUpwindFlux(insideVolVars, insideVolVars, scvf, volumeFlux, 1.0 /*upwindWeight*/, upwindTerm);
169 };
170
171 428576 addModelSpecificAdvectiveFlux<typename VolumeVariables::Indices>(flux, upwindFuntion);
172
173 238963 return flux;
174 }
175 };
176
177 } // end namespace Dumux
178
179 #endif
180