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 ShallowWaterTests | ||
10 | * \brief A test for the Shallow water model (wet dam break). | ||
11 | */ | ||
12 | #ifndef DUMUX_DAM_BREAK_TEST_PROBLEM_HH | ||
13 | #define DUMUX_DAM_BREAK_TEST_PROBLEM_HH | ||
14 | |||
15 | #include <dumux/common/boundarytypes.hh> | ||
16 | #include <dumux/common/parameters.hh> | ||
17 | #include <dumux/common/properties.hh> | ||
18 | #include <dumux/common/numeqvector.hh> | ||
19 | |||
20 | #include <dumux/freeflow/shallowwater/problem.hh> | ||
21 | #include <dumux/flux/shallowwater/riemannproblem.hh> | ||
22 | #include <dumux/flux/shallowwater/exactriemann.hh> | ||
23 | |||
24 | namespace Dumux { | ||
25 | |||
26 | /*! | ||
27 | * \ingroup Shallow water equations model | ||
28 | * \ingroup ImplicitTestProblems | ||
29 | * | ||
30 | * \brief A simple dam break test (1D wet dam break). | ||
31 | * | ||
32 | * The domain is a long rectangle with a gate in the middle. On the left | ||
33 | * side the water depth is larger than on the right side. | ||
34 | * All boundaries are set to no-flow. | ||
35 | * | ||
36 | * This problem uses the \ref ShallowWaterModel. | ||
37 | * | ||
38 | */ | ||
39 | template <class TypeTag> | ||
40 | class DamBreakProblem : public ShallowWaterProblem<TypeTag> | ||
41 | { | ||
42 | using ParentType = ShallowWaterProblem<TypeTag>; | ||
43 | using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; | ||
44 | using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>; | ||
45 | using Scalar = GetPropType<TypeTag, Properties::Scalar>; | ||
46 | using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices; | ||
47 | using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; | ||
48 | using NeumannFluxes = Dumux::NumEqVector<PrimaryVariables>; | ||
49 | |||
50 | using GridVariables = GetPropType<TypeTag, Properties::GridVariables>; | ||
51 | using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView; | ||
52 | using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; | ||
53 | using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView; | ||
54 | using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; | ||
55 | using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView; | ||
56 | using Element = typename GridView::template Codim<0>::Entity; | ||
57 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
58 | |||
59 | public: | ||
60 | 3 | DamBreakProblem(std::shared_ptr<const GridGeometry> gridGeometry) | |
61 |
9/26✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 3 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 3 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
|
9 | : ParentType(gridGeometry) |
62 | { | ||
63 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
|
3 | name_ = getParam<std::string>("Problem.Name"); |
64 |
3/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
6 | exactWaterDepth_.resize(gridGeometry->numDofs(), 0.0); |
65 |
3/8✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
6 | exactVelocityX_.resize(gridGeometry->numDofs(), 0.0); |
66 | 3 | } | |
67 | |||
68 | //! Get the analytical water depth | ||
69 | const std::vector<Scalar>& getExactWaterDepth() | ||
70 | { | ||
71 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | return exactWaterDepth_; |
72 | } | ||
73 | |||
74 | //! Get the analytical velocity | ||
75 | const std::vector<Scalar>& getExactVelocityX() | ||
76 | { | ||
77 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | return exactVelocityX_; |
78 | } | ||
79 | |||
80 | //! Update the analytical solution | ||
81 | template<class SolutionVector, class GridVariables> | ||
82 | 603 | void updateAnalyticalSolution(const SolutionVector& curSol, | |
83 | const GridVariables& gridVariables, | ||
84 | const Scalar time) | ||
85 | { | ||
86 | //compute solution for all elements | ||
87 |
2/4✓ Branch 1 taken 603 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 603 times.
✗ Branch 5 not taken.
|
1206 | auto fvGeometry = localView(this->gridGeometry()); |
88 |
2/4✓ Branch 1 taken 603 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 603 times.
✗ Branch 5 not taken.
|
1206 | auto elemVolVars = localView(gridVariables.curGridVolVars()); |
89 |
4/8✓ Branch 1 taken 603 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 603 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 603 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1015653 times.
✗ Branch 10 not taken.
|
2032512 | for (const auto& element : elements(this->gridGeometry().gridView())) |
90 | { | ||
91 | 1015050 | fvGeometry.bindElement(element); | |
92 |
1/2✓ Branch 1 taken 1015050 times.
✗ Branch 2 not taken.
|
1015050 | elemVolVars.bindElement(element, fvGeometry, curSol); |
93 | |||
94 | 1015050 | const auto& globalPos = element.geometry().center(); | |
95 | |||
96 | //compute the position s and the initial water depth at the gate, velocities are zero | ||
97 | 1015050 | const Scalar s = (globalPos[0] - gatePosition_)/time; | |
98 | 1015050 | const Scalar waterDepthLeft = initialWaterDepthLeft_; | |
99 | 1015050 | const Scalar waterDepthRight = initialWaterDepthRight_; | |
100 | 1015050 | const auto gravity = this->spatialParams().gravity(globalPos); | |
101 | |||
102 | 1015050 | auto riemannResult = ShallowWater::exactRiemann(waterDepthLeft, | |
103 | waterDepthRight, | ||
104 | 0.0, | ||
105 | 0.0, | ||
106 | 0.0, | ||
107 | 0.0, | ||
108 | gravity, | ||
109 | s); | ||
110 | |||
111 | 3045150 | const auto eIdx = this->gridGeometry().elementMapper().index(element); | |
112 | 1015050 | exactWaterDepth_[eIdx] = riemannResult.waterDepth; | |
113 | 2030100 | exactVelocityX_[eIdx] = riemannResult.velocityX; | |
114 | } | ||
115 | 603 | } | |
116 | |||
117 | /*! | ||
118 | * \name Problem parameters | ||
119 | */ | ||
120 | // \{ | ||
121 | |||
122 | /*! | ||
123 | * \brief The problem name | ||
124 | * | ||
125 | * This is used as a prefix for files generated by the simulation. | ||
126 | */ | ||
127 | const std::string& name() const | ||
128 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | { return name_; } |
129 | |||
130 | |||
131 | // \} | ||
132 | |||
133 | /*! | ||
134 | * \name Boundary conditions | ||
135 | */ | ||
136 | // \{ | ||
137 | |||
138 | /*! | ||
139 | * \brief Specifies which kind of boundary condition should be | ||
140 | * used for which equation on a given boundary segment. | ||
141 | * | ||
142 | * \param globalPos The position for which the boundary type is set | ||
143 | */ | ||
144 | ✗ | BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const | |
145 | { | ||
146 | 1446210 | BoundaryTypes bcTypes; | |
147 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 403704 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1042506 times.
|
1446210 | bcTypes.setAllNeumann(); |
148 | ✗ | return bcTypes; | |
149 | } | ||
150 | |||
151 | /*! | ||
152 | * \brief Specifies the neumann boundary | ||
153 | * \param element | ||
154 | * \param fvGeometry | ||
155 | * \param elemVolVars | ||
156 | * \param elemFluxVarsCache | ||
157 | * \param scvf | ||
158 | */ | ||
159 | 1042506 | NeumannFluxes neumann(const Element& element, | |
160 | const FVElementGeometry& fvGeometry, | ||
161 | const ElementVolumeVariables& elemVolVars, | ||
162 | const ElementFluxVariablesCache& elemFluxVarsCache, | ||
163 | const SubControlVolumeFace& scvf) const | ||
164 | { | ||
165 | 1042506 | NeumannFluxes values(0.0); | |
166 | |||
167 | // we need the Riemann invariants to compute the values depending of the boundary type | ||
168 | // since we use a weak imposition we do not have a dirichlet value. We impose fluxes | ||
169 | // based on q,h, etc. computed with the Riemann invariants | ||
170 | 2085012 | const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); | |
171 | 1042506 | const auto& insideVolVars = elemVolVars[insideScv]; | |
172 | 1042506 | const auto& nxy = scvf.unitOuterNormal(); | |
173 | 2085012 | const auto gravity = this->spatialParams().gravity(scvf.center()); | |
174 | |||
175 | 3127518 | auto riemannFlux = ShallowWater::riemannProblem(insideVolVars.waterDepth(), | |
176 | insideVolVars.waterDepth(), | ||
177 | insideVolVars.velocity(0), | ||
178 | 2085012 | -insideVolVars.velocity(0), | |
179 | insideVolVars.velocity(1), | ||
180 | 2085012 | -insideVolVars.velocity(1), | |
181 | insideVolVars.bedSurface(), | ||
182 | insideVolVars.bedSurface(), | ||
183 | gravity, | ||
184 | nxy); | ||
185 | |||
186 | 2085012 | values[Indices::massBalanceIdx] = riemannFlux[0]; | |
187 | 3127518 | values[Indices::velocityXIdx] = riemannFlux[1]; | |
188 | 3127518 | values[Indices::velocityYIdx] = riemannFlux[2]; | |
189 | |||
190 | 1042506 | return values; | |
191 | } | ||
192 | |||
193 | // \} | ||
194 | |||
195 | /*! | ||
196 | * \name Volume terms | ||
197 | */ | ||
198 | // \{ | ||
199 | |||
200 | /*! | ||
201 | * \brief Evaluate the initial values for a control volume. | ||
202 | * | ||
203 | * For this method, the \a values parameter stores primary | ||
204 | * variables. | ||
205 | * | ||
206 | * \param globalPos The position for which the boundary type is set | ||
207 | */ | ||
208 | ✗ | PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const | |
209 | { | ||
210 | |||
211 | ✗ | PrimaryVariables values(0.0); | |
212 | |||
213 | ✗ | values[0] = initialWaterDepthRight_; | |
214 | ✗ | values[1] = 0.0; | |
215 | ✗ | values[2] = 0.0; | |
216 | |||
217 | // water level on the left side of the gate | ||
218 | ✗ | if (globalPos[0] < 10.0 + eps_) | |
219 | { | ||
220 | ✗ | values[0] = initialWaterDepthLeft_; | |
221 | } | ||
222 | |||
223 | //water level on the right side of the gate | ||
224 | else | ||
225 | { | ||
226 | values[0] = initialWaterDepthRight_; | ||
227 | } | ||
228 | |||
229 | ✗ | return values; | |
230 | }; | ||
231 | |||
232 | // \} | ||
233 | |||
234 | private: | ||
235 | |||
236 | std::vector<Scalar> exactWaterDepth_; | ||
237 | std::vector<Scalar> exactVelocityX_; | ||
238 | |||
239 | static constexpr Scalar initialWaterDepthLeft_ = 4.0; | ||
240 | static constexpr Scalar initialWaterDepthRight_ = 1.0; | ||
241 | static constexpr Scalar channelLenght_ = 20.0; | ||
242 | static constexpr Scalar gatePosition_ = 10.0; | ||
243 | |||
244 | static constexpr Scalar eps_ = 1.0e-6; | ||
245 | std::string name_; | ||
246 | }; | ||
247 | |||
248 | } //end namespace Dumux | ||
249 | |||
250 | #endif | ||
251 |