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 | #ifndef DUMUX_TEST_FREEFLOW_PIPE_PROBLEM_HH | ||
9 | #define DUMUX_TEST_FREEFLOW_PIPE_PROBLEM_HH | ||
10 | |||
11 | #include <dumux/common/parameters.hh> | ||
12 | #include <dumux/common/properties.hh> | ||
13 | |||
14 | #include <dumux/freeflow/navierstokes/momentum/fluxhelper.hh> | ||
15 | #include <dumux/freeflow/navierstokes/scalarfluxhelper.hh> | ||
16 | #include <dumux/freeflow/navierstokes/mass/1p/advectiveflux.hh> | ||
17 | |||
18 | namespace Dumux { | ||
19 | /*! | ||
20 | * \ingroup NavierStokesTests | ||
21 | * \brief Freeflow problem for pipe flow | ||
22 | * Simulation of a radially-symmetric pipe flow with circular cross-section | ||
23 | */ | ||
24 | template <class TypeTag, class BaseProblem> | ||
25 | class FreeFlowPipeProblem : public BaseProblem | ||
26 | { | ||
27 | using ParentType = BaseProblem; | ||
28 | using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; | ||
29 | using FVElementGeometry = typename GridGeometry::LocalView; | ||
30 | using SubControlVolume = typename FVElementGeometry::SubControlVolume; | ||
31 | using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; | ||
32 | using GridView = typename GridGeometry::GridView; | ||
33 | using Scalar = GetPropType<TypeTag, Properties::Scalar>; | ||
34 | using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>; | ||
35 | using Element = typename GridView::template Codim<0>::Entity; | ||
36 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
37 | using InitialValues = typename ParentType::InitialValues; | ||
38 | using Sources = typename ParentType::Sources; | ||
39 | using DirichletValues = typename ParentType::DirichletValues; | ||
40 | using BoundaryFluxes = typename ParentType::BoundaryFluxes; | ||
41 | using BoundaryTypes = typename ParentType::BoundaryTypes; | ||
42 | using CouplingManager = GetPropType<TypeTag, Properties::CouplingManager>; | ||
43 | |||
44 | public: | ||
45 | using Indices = typename ModelTraits::Indices; | ||
46 | |||
47 | 12 | FreeFlowPipeProblem(std::shared_ptr<const GridGeometry> gridGeometry, std::shared_ptr<CouplingManager> couplingManager) | |
48 |
8/24✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 6 times.
✓ Branch 18 taken 6 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 6 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
|
48 | : ParentType(gridGeometry, couplingManager) |
49 | |||
50 | { | ||
51 |
3/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
|
24 | name_ = getParamFromGroup<std::string>(this->paramGroup(), "Problem.Name"); |
52 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | meanInletVelocity_ = getParamFromGroup<Scalar>(this->paramGroup(), "Problem.MeanInletVelocity"); |
53 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | initialPressure_ = getParamFromGroup<Scalar>(this->paramGroup(), "Problem.InitialPressure"); |
54 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | const Scalar nu = getParam<Scalar>("Component.LiquidKinematicViscosity"); |
55 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | rho_ = getParam<Scalar>("Component.LiquidDensity"); |
56 | 12 | mu_ = nu*rho_; | |
57 | |||
58 | 72 | pipeRadius_ = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0]; | |
59 | 72 | pipeLength_ = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; | |
60 | 12 | eps_ = 1e-7*pipeRadius_; | |
61 | |||
62 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
24 | std::cout << "-- Reynolds number: " << 2*pipeRadius_*meanInletVelocity_/nu << std::endl; |
63 | 12 | } | |
64 | |||
65 | const std::string& name() const | ||
66 | { | ||
67 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
12 | return name_; |
68 | } | ||
69 | |||
70 | /*! | ||
71 | * \brief Specifies which kind of boundary condition should be | ||
72 | * used for which equation on a given boundary segment. | ||
73 | */ | ||
74 | 52408 | BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const | |
75 | { | ||
76 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 46340 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13860 times.
|
112608 | BoundaryTypes values; |
77 | |||
78 | if constexpr (ParentType::isMomentumProblem()) | ||
79 | { | ||
80 | 204872 | if (onLowerBoundary_(globalPos) || onOuterBoundary_(globalPos)) | |
81 | values.setAllDirichlet(); | ||
82 | 52408 | else if (onInnerBoundary_(globalPos)) | |
83 | { | ||
84 | 23824 | values.setDirichlet(Indices::velocityXIdx); | |
85 | 23824 | values.setNeumann(Indices::momentumYBalanceIdx); | |
86 | } | ||
87 | else | ||
88 | values.setAllNeumann(); | ||
89 | } | ||
90 | else | ||
91 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 46340 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13860 times.
|
60200 | values.setAllNeumann(); |
92 | |||
93 | 52408 | return values; | |
94 | } | ||
95 | |||
96 | /*! | ||
97 | * \brief Evaluates the boundary conditions for a Neumann control volume. | ||
98 | * | ||
99 | * \param element The element for which the Neumann boundary condition is set | ||
100 | * \param fvGeometry The fvGeometry | ||
101 | * \param elemVolVars The element volume variables | ||
102 | * \param elemFaceVars The element face variables | ||
103 | * \param scvf The boundary sub control volume face | ||
104 | */ | ||
105 | template<class ElementVolumeVariables, class ElementFluxVariablesCache> | ||
106 | 195592 | BoundaryFluxes neumann(const Element& element, | |
107 | const FVElementGeometry& fvGeometry, | ||
108 | const ElementVolumeVariables& elemVolVars, | ||
109 | const ElementFluxVariablesCache& elemFluxVarsCache, | ||
110 | const SubControlVolumeFace& scvf) const | ||
111 | { | ||
112 |
2/2✓ Branch 0 taken 44170 times.
✓ Branch 1 taken 2170 times.
|
195592 | BoundaryFluxes values(0.0); |
113 |
2/2✓ Branch 0 taken 86062 times.
✓ Branch 1 taken 11734 times.
|
195592 | const auto& globalPos = scvf.ipGlobal(); |
114 | |||
115 | if constexpr (ParentType::isMomentumProblem()) | ||
116 | { | ||
117 | 205824 | if (onInnerBoundary_(globalPos)) | |
118 | 83784 | return values; // zero shear stress at symmetry axis | |
119 | 38256 | if (onUpperBoundary_(globalPos)) | |
120 | 38256 | values = NavierStokesMomentumBoundaryFlux<typename GridGeometry::DiscretizationMethod>::fixedPressureMomentumFlux( | |
121 | *this, fvGeometry, scvf, elemVolVars, elemFluxVarsCache, analyticalPressure(globalPos), true /*zeroNormalVelocityGradient*/ | ||
122 | ); | ||
123 | } | ||
124 | else | ||
125 | { | ||
126 | using FluxHelper = NavierStokesScalarBoundaryFluxHelper<AdvectiveFlux<ModelTraits>>; | ||
127 | 362040 | if (onLowerBoundary_(globalPos) || onUpperBoundary_(globalPos)) | |
128 | 8680 | values = FluxHelper::scalarOutflowFlux(*this, element, fvGeometry, scvf, elemVolVars); | |
129 | } | ||
130 | |||
131 | 111808 | return values; | |
132 | } | ||
133 | |||
134 | /*! | ||
135 | * \brief Evaluates the initial value for a control volume. | ||
136 | * | ||
137 | * \param globalPos The global position | ||
138 | */ | ||
139 | ✗ | InitialValues initialAtPos(const GlobalPosition& globalPos) const | |
140 | { | ||
141 | 63770 | InitialValues values(0.0); | |
142 | if constexpr (ParentType::isMomentumProblem()) | ||
143 | 42770 | return values; | |
144 | else | ||
145 | 21000 | values[Indices::pressureIdx] = initialPressure_; | |
146 | |||
147 | ✗ | return values; | |
148 | } | ||
149 | |||
150 | DirichletValues dirichletAtPos(const GlobalPosition& globalPos) const | ||
151 | 16194 | { return analyticalSolution(globalPos); } | |
152 | |||
153 | ✗ | DirichletValues analyticalSolution(const GlobalPosition& globalPos, Scalar time = 0.0) const | |
154 | { | ||
155 |
2/2✓ Branch 1 taken 116 times.
✓ Branch 2 taken 83884 times.
|
84000 | DirichletValues values(0.0); |
156 | |||
157 | // paraboloid velocity profile | ||
158 | if constexpr (ParentType::isMomentumProblem()) | ||
159 | { | ||
160 | ✗ | const auto r = globalPos[0] - this->gridGeometry().bBoxMin()[0]; | |
161 | ✗ | values[Indices::velocityXIdx] = 0.0; | |
162 | ✗ | values[Indices::velocityYIdx] = 2.0*meanInletVelocity_*(1.0 - r*r/(pipeRadius_*pipeRadius_)); | |
163 | } | ||
164 | else | ||
165 | 168000 | values[Indices::pressureIdx] = analyticalPressure(globalPos); | |
166 | |||
167 | ✗ | return values; | |
168 | } | ||
169 | |||
170 | Scalar analyticalPressure(const GlobalPosition& globalPos) const | ||
171 | { | ||
172 |
2/2✓ Branch 2 taken 116 times.
✓ Branch 3 taken 83884 times.
|
93564 | const auto y = globalPos[1]; |
173 |
2/2✓ Branch 2 taken 116 times.
✓ Branch 3 taken 83884 times.
|
93564 | return (pipeLength_-y)*meanInletVelocity_*8.0*mu_/(pipeRadius_*pipeRadius_); |
174 | } | ||
175 | |||
176 | Scalar analyticalMassFlux() const | ||
177 | { | ||
178 | 3 | return meanInletVelocity_ * M_PI * pipeRadius_*pipeRadius_ * rho_; | |
179 | } | ||
180 | |||
181 | private: | ||
182 | bool onInnerBoundary_(const GlobalPosition &globalPos) const | ||
183 |
20/20✓ Branch 0 taken 41892 times.
✓ Branch 1 taken 9564 times.
✓ Branch 2 taken 41892 times.
✓ Branch 3 taken 9564 times.
✓ Branch 4 taken 41892 times.
✓ Branch 5 taken 9564 times.
✓ Branch 6 taken 41892 times.
✓ Branch 7 taken 9564 times.
✓ Branch 8 taken 41892 times.
✓ Branch 9 taken 9564 times.
✓ Branch 10 taken 1190 times.
✓ Branch 11 taken 11912 times.
✓ Branch 12 taken 1190 times.
✓ Branch 13 taken 11912 times.
✓ Branch 14 taken 1190 times.
✓ Branch 15 taken 11912 times.
✓ Branch 16 taken 1190 times.
✓ Branch 17 taken 11912 times.
✓ Branch 18 taken 1190 times.
✓ Branch 19 taken 11912 times.
|
322790 | { return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_; } |
184 | |||
185 | bool onOuterBoundary_(const GlobalPosition &globalPos) const | ||
186 |
10/10✓ Branch 0 taken 11912 times.
✓ Branch 1 taken 13102 times.
✓ Branch 2 taken 11912 times.
✓ Branch 3 taken 13102 times.
✓ Branch 4 taken 11912 times.
✓ Branch 5 taken 13102 times.
✓ Branch 6 taken 11912 times.
✓ Branch 7 taken 13102 times.
✓ Branch 8 taken 11912 times.
✓ Branch 9 taken 13102 times.
|
125070 | { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; } |
187 | |||
188 | bool onLowerBoundary_(const GlobalPosition &globalPos) const | ||
189 |
20/20✓ Branch 0 taken 44170 times.
✓ Branch 1 taken 2170 times.
✓ Branch 2 taken 44170 times.
✓ Branch 3 taken 2170 times.
✓ Branch 4 taken 44170 times.
✓ Branch 5 taken 2170 times.
✓ Branch 6 taken 44170 times.
✓ Branch 7 taken 2170 times.
✓ Branch 8 taken 44170 times.
✓ Branch 9 taken 2170 times.
✓ Branch 10 taken 25014 times.
✓ Branch 11 taken 1190 times.
✓ Branch 12 taken 25014 times.
✓ Branch 13 taken 1190 times.
✓ Branch 14 taken 25014 times.
✓ Branch 15 taken 1190 times.
✓ Branch 16 taken 25014 times.
✓ Branch 17 taken 1190 times.
✓ Branch 18 taken 25014 times.
✓ Branch 19 taken 1190 times.
|
362720 | { return globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_; } |
190 | |||
191 | bool onUpperBoundary_(const GlobalPosition &globalPos) const | ||
192 |
15/20✓ Branch 0 taken 9564 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9564 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9564 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9564 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9564 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2170 times.
✓ Branch 11 taken 42000 times.
✓ Branch 12 taken 2170 times.
✓ Branch 13 taken 42000 times.
✓ Branch 14 taken 2170 times.
✓ Branch 15 taken 42000 times.
✓ Branch 16 taken 2170 times.
✓ Branch 17 taken 42000 times.
✓ Branch 18 taken 2170 times.
✓ Branch 19 taken 42000 times.
|
268670 | { return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_; } |
193 | |||
194 | std::string name_; | ||
195 | Scalar initialPressure_; | ||
196 | Scalar meanInletVelocity_; | ||
197 | Scalar mu_; | ||
198 | Scalar rho_; | ||
199 | Scalar pipeRadius_, pipeLength_; | ||
200 | Scalar eps_; | ||
201 | }; | ||
202 | |||
203 | } // end namespace Dumux | ||
204 | |||
205 | #endif | ||
206 |