GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/freeflow/navierstokes/scalarfluxhelper.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 39 46 84.8%
Functions: 36 37 97.3%
Branches: 19 28 67.9%

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-FileCopyrightText: 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
2/2
✓ Branch 0 taken 9651 times.
✓ Branch 1 taken 88279 times.
543055 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 138621 const bool insideIsUpstream = !signbit(volumeFlux);
56
57
3/4
✓ Branch 0 taken 9651 times.
✓ Branch 1 taken 89080 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6050 times.
138621 const auto& upstreamVolVars = insideIsUpstream ? insideVolVars : outsideVolVars;
58 602265 const auto& downstreamVolVars = insideIsUpstream ? outsideVolVars : insideVolVars;
59
60 602265 return (upwindWeight * upwindTerm(upstreamVolVars) +
61 602265 (1.0 - upwindWeight) * upwindTerm(downstreamVolVars))
62 602265 * volumeFlux;
63 }
64
65 template<class Indices, class NumEqVector, class UpwindFunction>
66 476535 static void addModelSpecificAdvectiveFlux(NumEqVector& flux,
67 const UpwindFunction& upwind)
68 {
69 // add advective fluxes based on physical type of model
70 476535 AdvectiveFlux::addAdvectiveFlux(flux, upwind);
71
72 // for non-isothermal models, add the energy flux
73 if constexpr (Detail::isNonIsothermal<Indices>())
74 {
75 44240 auto upwindTerm = [](const auto& volVars) { return volVars.density()*volVars.enthalpy(); };
76 44240 flux[Indices::energyEqIdx] = upwind(upwindTerm);
77 }
78 32690 }
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 28251 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 28251 NumEqVector flux;
97 28251 const auto velocity = problem.faceVelocity(element,fvGeometry, scvf);
98 28251 const auto volumeFlux = velocity * scvf.unitOuterNormal();
99 using std::signbit;
100 28251 const bool insideIsUpstream = !signbit(volumeFlux);
101 28251 const VolumeVariables& insideVolVars = elemVolVars[scvf.insideScvIdx()];
102 84753 const VolumeVariables& outsideVolVars = [&]()
103 {
104 // only use the inside volVars for "true" outflow conditions (avoid constructing the outside volVars)
105
3/6
✓ Branch 0 taken 28251 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28251 times.
✓ Branch 4 taken 28251 times.
✗ Branch 5 not taken.
28251 if (insideIsUpstream && Dune::FloatCmp::eq(upwindWeight, 1.0, 1e-6))
106 28251 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 28251 }();
118
119 120932 auto upwindFuntion = [&](const auto& upwindTerm)
120 {
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6851 times.
60931 return advectiveScalarUpwindFlux(insideVolVars, outsideVolVars, scvf, volumeFlux, upwindWeight, upwindTerm);
122 };
123
124 28251 addModelSpecificAdvectiveFlux<typename VolumeVariables::Indices>(flux, upwindFuntion);
125
126 28251 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 448284 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 448284 NumEqVector flux;
144
2/2
✓ Branch 1 taken 769722 times.
✓ Branch 2 taken 256574 times.
1218006 const auto velocity = problem.faceVelocity(element,fvGeometry, scvf);
145 448284 const auto volumeFlux = velocity * scvf.unitOuterNormal();
146 using std::signbit;
147 448284 const bool insideIsUpstream = !signbit(volumeFlux);
148 448284 const VolumeVariables& insideVolVars = elemVolVars[scvf.insideScvIdx()];
149
150 if constexpr (VolumeVariables::FluidSystem::isCompressible(0/*phaseIdx*/) /*TODO viscosityIsConstant*/ || NumEqVector::size() > 1)
151 {
152
4/6
✓ 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.
49350 static const bool verbose = getParamFromGroup<bool>(problem.paramGroup(), "Flux.EnableOutflowReversalWarning", true);
153 using std::abs;
154
4/6
✓ 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.
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 49350 "\n ***************************** \n" << std::endl;
163 }
164 }
165
166 494364 auto upwindFuntion = [&](const auto& upwindTerm)
167 {
168 448284 return advectiveScalarUpwindFlux(insideVolVars, insideVolVars, scvf, volumeFlux, 1.0 /*upwindWeight*/, upwindTerm);
169 };
170
171 448284 addModelSpecificAdvectiveFlux<typename VolumeVariables::Indices>(flux, upwindFuntion);
172
173 448284 return flux;
174 }
175 };
176
177 } // end namespace Dumux
178
179 #endif
180