GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/test/freeflow/navierstokes/channel/3d/problem.hh
Date: 2026-10-17 21:47:00
Exec Total Coverage
Lines: 42 44 95.5%
Functions: 9 11 81.8%
Branches: 56 108 51.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 NavierStokesTests
10 * \brief Channel flow test for the staggered grid (Navier-)Stokes model.
11 *
12 * The channel is either modeled in 3D or in 2D, using an additional wall friction term
13 * to mimic the 3D behavior of the flow.
14 */
15
16 #ifndef DUMUX_TEST_FREEFLOW_NAVIERSTOKES_3D_CHANNEL_PROBLEM_HH
17 #define DUMUX_TEST_FREEFLOW_NAVIERSTOKES_3D_CHANNEL_PROBLEM_HH
18
19 #include <dune/common/float_cmp.hh>
20
21 #include <dumux/common/properties.hh>
22 #include <dumux/common/parameters.hh>
23
24 #include <dumux/freeflow/navierstokes/momentum/fluxhelper.hh>
25 #include <dumux/freeflow/navierstokes/scalarfluxhelper.hh>
26 #include <dumux/freeflow/navierstokes/mass/1p/advectiveflux.hh>
27
28 namespace Dumux {
29
30 /*!
31 * \brief Test problem for the one-phase (Navier-) Stokes model in a 3D or pseudo 3D channel.
32 *
33 * Flow from left to right in a three-dimensional channel is considered. At the inlet (left)
34 * and outlet (right) fixed values for pressure are set.
35 * The channel is confined by solid walls at all other sides of the domain which corresponds
36 * to no-slip/no-flow conditions.
37 * The value of an analytical solution for the given flow configuration is furthermore provided.
38 * For sake of efficiency, the 3D problem can be reduced to a two-dimensional one by including
39 * an additional wall friction term to the momentum balance (Flekkoy et al., 1995 \cite flekkoy1995a).
40 */
41 template <class TypeTag, class BaseProblem>
42 8 class ThreeDChannelTestProblem : public BaseProblem
43 {
44 using ParentType = BaseProblem;
45
46 using BoundaryTypes = typename ParentType::BoundaryTypes;
47 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
48 using FVElementGeometry = typename GridGeometry::LocalView;
49 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
50 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
51 using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
52 using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>;
53 using InitialValues = typename ParentType::InitialValues;
54 using Sources = typename ParentType::Sources;
55 using DirichletValues = typename ParentType::DirichletValues;
56 using BoundaryFluxes = typename ParentType::BoundaryFluxes;
57 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
58 using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
59
60 static constexpr auto dimWorld = GridGeometry::GridView::dimensionworld;
61 using Element = typename GridGeometry::GridView::template Codim<0>::Entity;
62 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
63 using VelocityVector = Dune::FieldVector<Scalar, dimWorld>;
64
65 using CouplingManager = GetPropType<TypeTag, Properties::CouplingManager>;
66 static constexpr int dim = GridGeometry::GridView::dimension;
67 static constexpr bool enablePseudoThreeDWallFriction = dim != 3;
68
69 public:
70 16 ThreeDChannelTestProblem(std::shared_ptr<const GridGeometry> gridGeometry, std::shared_ptr<CouplingManager> couplingManager)
71
2/6
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
64 : ParentType(gridGeometry, couplingManager)
72 {
73
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 deltaP_ = getParam<Scalar>("Problem.DeltaP");
74
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 rho_ = getParam<Scalar>("Component.LiquidDensity");
75
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 nu_ = getParam<Scalar>("Component.LiquidKinematicViscosity");
76
77
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
16 height_ = getParam<Scalar>("Problem.Height");
78
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
12 if(dim == 3 && !Dune::FloatCmp::eq(height_, this->gridGeometry().bBoxMax()[2]))
79 ✗ DUNE_THROW(Dune::InvalidStateException, "z-dimension must equal height");
80
81
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 refPressure_ = getParam<Scalar>("Problem.RefPressure", 1e5);
82 16 }
83
84 /*!
85 * \name Problem parameters
86 */
87 // \{
88
89 /*!
90 * \brief Evaluates the source term for all phases within a given
91 * sub-control volume
92 */
93 template<class ElementVolumeVariables>
94
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 659736 times.
679384 Sources source(const Element& element,
95 const FVElementGeometry& fvGeometry,
96 const ElementVolumeVariables& elemVolVars,
97 const SubControlVolume& scv) const
98 {
99 19648 auto source = Sources(0.0);
100
101 if constexpr (ParentType::isMomentumProblem() && enablePseudoThreeDWallFriction)
102 {
103
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19647 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
19648 static const Scalar height = getParam<Scalar>("Problem.Height");
104
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19647 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
19648 static const Scalar factor = getParam<Scalar>("Problem.PseudoWallFractionFactor", 8.0);
105 19648 source[scv.dofAxis()] = this->pseudo3DWallFriction(element, fvGeometry, elemVolVars, scv, height, factor);
106 }
107
108 19648 return source;
109 }
110
111 // \}
112
113 /*!
114 * \name Boundary conditions
115 */
116 // \{
117
118 /*!
119 * \brief Specifies which kind of boundary condition should be
120 * used for which equation on a given boundary control volume.
121 *
122 * \param globalPos The position of the center of the finite volume
123 */
124
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 121478 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22096 times.
143574 BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
125 {
126
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 121478 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22096 times.
✗ Branch 4 not taken.
826138 BoundaryTypes values;
127
128 if constexpr (ParentType::isMomentumProblem())
129 {
130 682564 values.setAllDirichlet();
131
4/4
✓ Branch 0 taken 418972 times.
✓ Branch 1 taken 263592 times.
✓ Branch 2 taken 331174 times.
✓ Branch 3 taken 87798 times.
682564 if (isOutlet_(globalPos) || isInlet_(globalPos))
132 682564 values.setAllNeumann();
133 }
134 else
135 values.setNeumann(Indices::conti0EqIdx);
136
137 682564 return values;
138 }
139
140 /*!
141 * \brief Evaluates the boundary conditions for a Dirichlet control volume.
142 *
143 * \param globalPos The center of the finite volume which ought to be set.
144 */
145 ✗ DirichletValues dirichletAtPos(const GlobalPosition &globalPos) const
146 {
147 // no-flow/no-slip
148
2/4
✓ Branch 1 taken 3610 times.
✓ Branch 2 taken 3610 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
454010 return DirichletValues(0.0);
149 }
150
151 /*!
152 * \brief Evaluates the boundary conditions for a Neumann control volume.
153 *
154 * \param element The element for which the Neumann boundary condition is set
155 * \param fvGeometry The fvGeometry
156 * \param elemVolVars The element volume variables
157 * \param elemFaceVars The element face variables
158 * \param scvf The boundary sub control volume face
159 */
160 template<class ElementVolumeVariables, class ElementFluxVariablesCache>
161
6/6
✓ Branch 0 taken 33354 times.
✓ Branch 1 taken 26424 times.
✓ Branch 2 taken 133416 times.
✓ Branch 3 taken 105696 times.
✓ Branch 4 taken 149502 times.
✓ Branch 5 taken 118324 times.
585060 BoundaryFluxes neumann(const Element& element,
162 const FVElementGeometry& fvGeometry,
163 const ElementVolumeVariables& elemVolVars,
164 const ElementFluxVariablesCache& elemFluxVarsCache,
165 const SubControlVolumeFace& scvf) const
166 {
167
3/5
✓ Branch 0 taken 7312 times.
✓ Branch 1 taken 125070 times.
✓ Branch 3 taken 3720 times.
✗ Branch 4 not taken.
✗ Branch 2 not taken.
136102 BoundaryFluxes values(0.0);
168 702818 const auto& globalPos = scvf.ipGlobal();
169
170 if constexpr (ParentType::isMomentumProblem())
171 {
172 581340 const auto p = isInlet_(globalPos) ? refPressure_ + deltaP_ : refPressure_;
173 581340 values = NavierStokesMomentumBoundaryFlux<typename GridGeometry::DiscretizationMethod>::fixedPressureMomentumFlux(
174 *this, fvGeometry, scvf, elemVolVars, elemFluxVarsCache, p
175 );
176 }
177 else
178 {
179
1/2
✓ Branch 1 taken 121478 times.
✗ Branch 2 not taken.
121478 values = NavierStokesScalarBoundaryFluxHelper<AdvectiveFlux<ModelTraits>>::scalarOutflowFlux(
180 *this, element, fvGeometry, scvf, elemVolVars
181 );
182 }
183
184
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
121478 return values;
185 }
186
187 // \}
188
189 /*!
190 * \brief Returns a reference pressure at a given sub control volume face.
191 * This pressure is subtracted from the actual pressure for the momentum balance
192 * which potentially helps to improve numerical accuracy by avoiding issues related do floating point arithmetic.
193 */
194 699248 Scalar referencePressure(const Element& element,
195 const FVElementGeometry& fvGeometry,
196 const SubControlVolumeFace& scvf) const
197
1/2
✓ Branch 1 taken 62626 times.
✗ Branch 2 not taken.
699248 { return refPressure_; }
198
199 //! Returns the analytical solution for the flux through the rectangular channel
200 4 Scalar analyticalFlux() const
201 {
202 4 const Scalar h = height_;
203 4 const Scalar w = this->gridGeometry().bBoxMax()[1];
204 4 const Scalar L = this->gridGeometry().bBoxMax()[0];
205
206 4 const Scalar mu = nu_*rho_;
207
208 4 return h*h*h * w * deltaP_ / (12*mu*L) * (1.0 - 0.630 * h/w);
209 }
210
211 private:
212
213
6/6
✓ Branch 0 taken 40666 times.
✓ Branch 1 taken 33736 times.
✓ Branch 2 taken 133416 times.
✓ Branch 3 taken 105696 times.
✓ Branch 4 taken 149502 times.
✓ Branch 5 taken 118324 times.
581340 bool isInlet_(const GlobalPosition& globalPos) const
214
6/6
✓ Branch 0 taken 40666 times.
✓ Branch 1 taken 33736 times.
✓ Branch 2 taken 133416 times.
✓ Branch 3 taken 105696 times.
✓ Branch 4 taken 149502 times.
✓ Branch 5 taken 118324 times.
581340 { return globalPos[0] < eps_; }
215
216
2/2
✓ Branch 0 taken 418972 times.
✓ Branch 1 taken 263592 times.
682564 bool isOutlet_(const GlobalPosition& globalPos) const
217
2/2
✓ Branch 0 taken 418972 times.
✓ Branch 1 taken 263592 times.
682564 { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; }
218
219 static constexpr Scalar eps_=1e-6;
220 Scalar deltaP_;
221 Scalar height_;
222 Scalar rho_;
223 Scalar nu_;
224 Scalar refPressure_;
225 };
226
227 } // end namespace Dumux
228
229 #endif
230