GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/freeflow/staggeredupwindmethods.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 50 133 37.6%
Functions: 9 19 47.4%
Branches: 53 444 11.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-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 FreeflowModels
10 * \brief This file contains different higher order methods for approximating the velocity.
11 */
12
13 #ifndef DUMUX_UPWINDING_METHODS_HH
14 #define DUMUX_UPWINDING_METHODS_HH
15
16 #include <cmath>
17 #include <functional>
18 #include <iostream>
19 #include <string>
20
21 #include <dumux/common/exceptions.hh>
22 #include <dumux/common/parameters.hh>
23
24 namespace Dumux {
25
26 /*!
27 * \ingroup FreeflowModels
28 * \brief Available Tvd approaches
29 */
30 enum class TvdApproach
31 {
32 none, uniform, li, hou
33 };
34
35 /*!
36 * \ingroup FreeflowModels
37 * \brief Available differencing schemes
38 */
39 enum class DifferencingScheme
40 {
41 none, vanleer, vanalbada, minmod, superbee, umist, mclimiter, wahyd
42 };
43
44 /*!
45 * \ingroup FreeflowModels
46 * \brief This file contains different higher order methods for approximating the velocity.
47 */
48 template<class Scalar, int upwindSchemeOrder>
49 class StaggeredUpwindMethods
50 {
51 public:
52 50 StaggeredUpwindMethods(const std::string& paramGroup = "")
53 50 {
54
1/2
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
50 upwindWeight_ = getParamFromGroup<Scalar>(paramGroup, "Flux.UpwindWeight");
55
56 if (upwindSchemeOrder > 1)
57 {
58 // Read the runtime parameters
59
3/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
2 tvdApproach_ = tvdApproachFromString(getParamFromGroup<std::string>(paramGroup, "Flux.TvdApproach", "Uniform"));
60
3/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
2 differencingScheme_ = differencingSchemeFromString(getParamFromGroup<std::string>(paramGroup, "Flux.DifferencingScheme", "Minmod"));
61
62 // Assign the limiter_ depending on the differencing scheme
63
1/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 switch (differencingScheme_)
64 {
65 2 case DifferencingScheme::vanleer :
66 {
67 2 limiter_ = this->vanleer;
68 break;
69 }
70 case DifferencingScheme::vanalbada :
71 {
72 if (tvdApproach_ == TvdApproach::hou)
73 DUNE_THROW(ParameterException, "\nDifferencing scheme (Van Albada) is not implemented for the Tvd approach (Hou).");
74 else
75 limiter_ = this->vanalbada;
76 break;
77 }
78 case DifferencingScheme::minmod :
79 {
80 limiter_ = this->minmod;
81 break;
82 }
83 case DifferencingScheme::superbee :
84 {
85 limiter_ = this->superbee;
86 break;
87 }
88 case DifferencingScheme::umist :
89 {
90 limiter_ = this->umist;
91 break;
92 }
93 case DifferencingScheme::mclimiter :
94 {
95 limiter_ = this->mclimiter;
96 break;
97 }
98 case DifferencingScheme::wahyd :
99 {
100 limiter_ = this->wahyd;
101 break;
102 }
103 default:
104 {
105 DUNE_THROW(ParameterException, "\nDifferencing scheme " << static_cast<std::string>(differencingSchemeToString(differencingScheme_)) <<
106 " is not implemented.\n"); // should never be reached
107 break;
108 }
109 }
110
111
6/14
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
10 if (!hasParamInGroup(paramGroup, "Flux.TvdApproach"))
112 {
113 std::cout << "No TvdApproach specified. Defaulting to the Uniform method." << "\n";
114 std::cout << "Other available TVD approaches for uniform (and nonuniform) grids are as follows: \n"
115 << " " << tvdApproachToString(TvdApproach::uniform) << ": assumes a Uniform cell size distribution\n"
116 << " " << tvdApproachToString(TvdApproach::li) << ": Li's approach for nonuniform cell sizes\n"
117 << " " << tvdApproachToString(TvdApproach::hou) << ": Hou's approach for nonuniform cell sizes \n";
118 std::cout << "Each approach can be specified as written above in the Flux group under the title TvdApproach in your input file. \n";
119 }
120
6/14
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
10 if (!hasParamInGroup(paramGroup, "Flux.DifferencingScheme"))
121 {
122
123 std::cout << "No DifferencingScheme specified. Defaulting to the Minmod scheme." << "\n";
124 std::cout << "Other available Differencing Schemes are as follows: \n"
125 << " " << differencingSchemeToString(DifferencingScheme::vanleer) << ": The Vanleer flux limiter\n"
126 << " " << differencingSchemeToString(DifferencingScheme::vanalbada) << ": The Vanalbada flux limiter\n"
127 << " " << differencingSchemeToString(DifferencingScheme::minmod) << ": The Minmod flux limiter\n"
128 << " " << differencingSchemeToString(DifferencingScheme::superbee) << ": The Superbee flux limiter\n"
129 << " " << differencingSchemeToString(DifferencingScheme::umist) << ": The Umist flux limiter\n"
130 << " " << differencingSchemeToString(DifferencingScheme::mclimiter) << ": The Mclimiter flux limiter\n"
131 << " " << differencingSchemeToString(DifferencingScheme::wahyd) << ": The Wahyd flux limiter";
132 std::cout << "Each scheme can be specified as written above in the Flux group under the variable DifferencingScheme in your input file. \n";
133 }
134
135 std::cout << "Using the tvdApproach \"" << tvdApproachToString(tvdApproach_)
136
7/20
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
6 << "\" and the differencing Scheme \" " << differencingSchemeToString(differencingScheme_) << "\" \n";
137 }
138 else
139 {
140 // If the runtime parameters are not specified we will use upwind
141 48 tvdApproach_ = TvdApproach::none;
142 48 differencingScheme_ = DifferencingScheme::none;
143 }
144 50 }
145
146 /**
147 * \brief Convenience function to convert user input given as std::string
148 * to the corresponding enum class used for choosing the TVD Approach
149 */
150 2 TvdApproach tvdApproachFromString(const std::string& tvd)
151 {
152
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (tvd == "Uniform") return TvdApproach::uniform;
153
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (tvd == "Li") return TvdApproach::li;
154
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (tvd == "Hou") return TvdApproach::hou;
155 DUNE_THROW(ParameterException, "\nThis tvd approach : \"" << tvd << "\" is not implemented.\n"
156 << "The available TVD approaches for uniform (and nonuniform) grids are as follows: \n"
157 << tvdApproachToString(TvdApproach::uniform) << ": assumes a uniform cell size distribution\n"
158 << tvdApproachToString(TvdApproach::li) << ": li's approach for nonuniform cell sizes\n"
159 << tvdApproachToString(TvdApproach::hou) << ": hou's approach for nonuniform cell sizes");
160 }
161
162 /**
163 * \brief return the name of the TVD approach
164 */
165 2 std::string tvdApproachToString(TvdApproach tvd)
166 {
167
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 switch (tvd)
168 {
169 case TvdApproach::uniform: return "Uniform";
170 case TvdApproach::li: return "Li";
171 4 case TvdApproach::hou: return "Hou";
172 default: return "Invalid"; // should never be reached
173 }
174 }
175
176 /**
177 * \brief Convenience function to convert user input given as std::string
178 * to the corresponding enum class used for choosing the Discretization Method
179 */
180 2 DifferencingScheme differencingSchemeFromString(const std::string& differencingScheme)
181 {
182
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (differencingScheme == "Vanleer") return DifferencingScheme::vanleer;
183 if (differencingScheme == "Vanalbada") return DifferencingScheme::vanalbada;
184 if (differencingScheme == "Minmod") return DifferencingScheme::minmod;
185 if (differencingScheme == "Superbee") return DifferencingScheme::superbee;
186 if (differencingScheme == "Umist") return DifferencingScheme::umist;
187 if (differencingScheme == "Mclimiter") return DifferencingScheme::mclimiter;
188 if (differencingScheme == "Wahyd") return DifferencingScheme::wahyd;
189 DUNE_THROW(ParameterException, "\nThis differencing scheme: \"" << differencingScheme << "\" is not implemented.\n"
190 << "The available differencing schemes are as follows: \n"
191 << differencingSchemeToString(DifferencingScheme::vanleer) << ": The Vanleer flux limiter\n"
192 << differencingSchemeToString(DifferencingScheme::vanalbada) << ": The VanAlbada flux limiter\n"
193 << differencingSchemeToString(DifferencingScheme::minmod) << ": The Min-Mod flux limiter\n"
194 << differencingSchemeToString(DifferencingScheme::superbee) << ": The SuperBEE flux limiter\n"
195 << differencingSchemeToString(DifferencingScheme::umist) << ": The UMist flux limiter\n"
196 << differencingSchemeToString(DifferencingScheme::mclimiter) << ": The McLimiter flux limiter\n"
197 << differencingSchemeToString(DifferencingScheme::wahyd) << ": The Wahyd flux limiter");
198 }
199
200 /**
201 * \brief return the name of the Discretization Method
202 */
203 2 std::string differencingSchemeToString(DifferencingScheme differencingScheme)
204 {
205
1/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 switch (differencingScheme)
206 {
207 4 case DifferencingScheme::vanleer: return "Vanleer";
208 case DifferencingScheme::vanalbada: return "Vanalbada";
209 case DifferencingScheme::minmod: return "Minmod";
210 case DifferencingScheme::superbee: return "Superbee";
211 case DifferencingScheme::umist: return "Umist";
212 case DifferencingScheme::mclimiter: return "Mclimiter";
213 case DifferencingScheme::wahyd: return "Wahyd";
214 default: return "Invalid"; // should never be reached
215 }
216 }
217
218 /**
219 * \brief Upwind Method
220 */
221 Scalar upwind(const Scalar downstreamMomentum,
222 const Scalar upstreamMomentum) const
223 {
224 397507108 return (upwindWeight_ * upstreamMomentum + (1.0 - upwindWeight_) * downstreamMomentum);
225 }
226
227 /**
228 * \brief Tvd Scheme: Total Variation Diminishing
229 *
230 */
231 5775101 Scalar tvd(const std::array<Scalar,3>& momenta,
232 const std::array<Scalar,3>& distances,
233 const bool selfIsUpstream,
234 const TvdApproach tvdApproach) const
235 {
236 5775101 Scalar momentum = 0.0;
237
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 5775101 times.
✗ Branch 3 not taken.
5775101 switch(tvdApproach)
238 {
239 case TvdApproach::uniform :
240 {
241 momentum += tvdUniform(momenta, distances, selfIsUpstream);
242 break;
243 }
244 case TvdApproach::li :
245 {
246 momentum += tvdLi(momenta, distances, selfIsUpstream);
247 break;
248 }
249 5775101 case TvdApproach::hou :
250 {
251 5775101 momentum += tvdHou(momenta, distances, selfIsUpstream);
252 5775101 break;
253 }
254 default:
255 {
256 DUNE_THROW(ParameterException, "\nThis Tvd Approach is not implemented.\n");
257 break;
258 }
259 }
260 5775101 return momentum;
261 }
262
263 /**
264 * \brief Tvd Scheme: Total Variation Diminishing
265 *
266 * This function assumes the cell size distribution to be uniform.
267 */
268 Scalar tvdUniform(const std::array<Scalar,3>& momenta,
269 const std::array<Scalar,3>& distances,
270 const bool selfIsUpstream) const
271 {
272 using std::isfinite;
273 const Scalar downstreamMomentum = momenta[0];
274 const Scalar upstreamMomentum = momenta[1];
275 const Scalar upUpstreamMomentum = momenta[2];
276 const Scalar ratio = (upstreamMomentum - upUpstreamMomentum) / (downstreamMomentum - upstreamMomentum);
277
278 // If the velocity field is uniform (like at the first newton step) we get a NaN
279 if(ratio > 0.0 && isfinite(ratio))
280 {
281 const Scalar secondOrderTerm = 0.5 * limiter_(ratio, 2.0) * (downstreamMomentum - upstreamMomentum);
282 return (upstreamMomentum + secondOrderTerm);
283 }
284 else
285 return upstreamMomentum;
286 }
287
288 /**
289 * \brief Tvd Scheme: Total Variation Diminishing
290 *
291 * This function manages the non uniformities of the grid according to [Li, Liao 2007].
292 * It tries to reconstruct the value for the velocity at the upstream-upstream point
293 * if the grid was uniform.
294 */
295 Scalar tvdLi(const std::array<Scalar,3>& momenta,
296 const std::array<Scalar,3>& distances,
297 const bool selfIsUpstream) const
298 {
299 using std::isfinite;
300 const Scalar downstreamMomentum = momenta[0];
301 const Scalar upstreamMomentum = momenta[1];
302 const Scalar upUpstreamMomentum = momenta[2];
303 const Scalar upstreamToDownstreamDistance = distances[0];
304 const Scalar upUpstreamToUpstreamDistance = distances[1];
305
306 // selfIsUpstream is required to get the correct sign because upUpstreamToUpstreamDistance is always positive
307 const Scalar upUpstreamGradient = (upstreamMomentum - upUpstreamMomentum) / upUpstreamToUpstreamDistance * selfIsUpstream;
308
309 // Distance between the upUpstream node and the position where it should be if the grid were uniform.
310 const Scalar correctionDistance = upUpstreamToUpstreamDistance - upstreamToDownstreamDistance;
311 const Scalar reconstrutedUpUpstreamVelocity = upUpstreamMomentum + upUpstreamGradient * correctionDistance;
312 const Scalar ratio = (upstreamMomentum - reconstrutedUpUpstreamVelocity) / (downstreamMomentum - upstreamMomentum);
313
314 // If the velocity field is uniform (like at the first newton step) we get a NaN
315 if(ratio > 0.0 && isfinite(ratio))
316 {
317 const Scalar secondOrderTerm = 0.5 * limiter_(ratio, 2.0) * (downstreamMomentum - upstreamMomentum);
318 return (upstreamMomentum + secondOrderTerm);
319 }
320 else
321 return upstreamMomentum;
322 }
323
324 /**
325 * \brief Tvd Scheme: Total Variation Diminishing
326 *
327 * This function manages the non uniformities of the grid according to [Hou, Simons, Hinkelmann 2007].
328 * It should behave better then the Li's version in very stretched grids.
329 */
330 5775101 Scalar tvdHou(const std::array<Scalar,3>& momenta,
331 const std::array<Scalar,3>& distances,
332 const bool selfIsUpstream) const
333 {
334 using std::isfinite;
335
2/2
✓ Branch 0 taken 4728318 times.
✓ Branch 1 taken 1046783 times.
5775101 const Scalar downstreamMomentum = momenta[0];
336
2/2
✓ Branch 0 taken 4728318 times.
✓ Branch 1 taken 1046783 times.
5775101 const Scalar upstreamMomentum = momenta[1];
337
2/2
✓ Branch 0 taken 4728318 times.
✓ Branch 1 taken 1046783 times.
5775101 const Scalar upUpstreamMomentum = momenta[2];
338
2/2
✓ Branch 0 taken 4728318 times.
✓ Branch 1 taken 1046783 times.
5775101 const Scalar upstreamToDownstreamDistance = distances[0];
339
2/2
✓ Branch 0 taken 4728318 times.
✓ Branch 1 taken 1046783 times.
5775101 const Scalar upUpstreamToUpstreamDistance = distances[1];
340
2/2
✓ Branch 0 taken 4728318 times.
✓ Branch 1 taken 1046783 times.
5775101 const Scalar downstreamStaggeredCellSize = distances[2];
341 11550202 const Scalar ratio = (upstreamMomentum - upUpstreamMomentum) / (downstreamMomentum - upstreamMomentum)
342 5775101 * upstreamToDownstreamDistance / upUpstreamToUpstreamDistance;
343
344 // If the velocity field is uniform (like at the first newton step) we get a NaN
345
6/6
✓ Branch 0 taken 4728318 times.
✓ Branch 1 taken 1046783 times.
✓ Branch 2 taken 4725886 times.
✓ Branch 3 taken 2432 times.
✓ Branch 4 taken 4725886 times.
✓ Branch 5 taken 2432 times.
5775101 if(ratio > 0.0 && isfinite(ratio))
346 {
347 4725886 const Scalar upstreamStaggeredCellSize = 0.5 * (upstreamToDownstreamDistance + upUpstreamToUpstreamDistance);
348 4725886 const Scalar R = (upstreamStaggeredCellSize + downstreamStaggeredCellSize) / upstreamStaggeredCellSize;
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4725886 times.
4725886 const Scalar secondOrderTerm = limiter_(ratio, R) / R * (downstreamMomentum - upstreamMomentum);
350 4725886 return (upstreamMomentum + secondOrderTerm);
351 }
352 else
353 return upstreamMomentum;
354 }
355
356 /**
357 * \brief Van Leer flux limiter function [Van Leer 1974]
358 *
359 * With R != 2 is the modified Van Leer flux limiter function [Hou, Simons, Hinkelmann 2007]
360 */
361 4725886 static Scalar vanleer(const Scalar r, const Scalar R)
362 {
363 4725886 return R * r / (R - 1.0 + r);
364 }
365
366 /**
367 * \brief Van Albada flux limiter function [Van Albada et al. 1982]
368 */
369 static Scalar vanalbada(const Scalar r, const Scalar R)
370 {
371 return r * (r + 1.0) / (1.0 + r * r);
372 }
373
374 /**
375 * \brief MinMod flux limiter function [Roe 1985]
376 */
377 static Scalar minmod(const Scalar r, const Scalar R)
378 {
379 using std::min;
380 return min(r, 1.0);
381 }
382
383 /**
384 * \brief SUPERBEE flux limiter function [Roe 1985]
385 *
386 * With R != 2 is the modified SUPERBEE flux limiter function [Hou, Simons, Hinkelmann 2007]
387 */
388 static Scalar superbee(const Scalar r, const Scalar R)
389 {
390 using std::min;
391 using std::max;
392 return max(min(R * r, 1.0), min(r, R));
393 }
394
395 /**
396 * \brief UMIST flux limiter function [Lien and Leschziner 1993]
397 */
398 static Scalar umist(const Scalar r, const Scalar R)
399 {
400 using std::min;
401 return min({R * r, (r * (5.0 - R) + R - 1.0) / 4.0, (r * (R - 1.0) + 5.0 - R) / 4.0, R});
402 }
403
404 /*
405 * \brief Monotonized-Central limiter [Van Leer 1977]
406 */
407 static Scalar mclimiter(const Scalar r, const Scalar R)
408 {
409 using std::min;
410 return min({R * r, (r + 1.0) / 2.0, R});
411 }
412
413 /**
414 * \brief WAHYD Scheme [Hou, Simons, Hinkelmann 2007];
415 */
416 static Scalar wahyd(const Scalar r, const Scalar R)
417 {
418 using std::min;
419 return r > 1 ? min((r + R * r * r) / (R + r * r), R)
420 : vanleer(r, R);
421 }
422
423 //! Returns the Tvd approach
424 const TvdApproach& tvdApproach() const
425 {
426 return tvdApproach_;
427 }
428
429 //! Returns the differencing scheme
430 const DifferencingScheme& differencingScheme() const
431 {
432 return differencingScheme_;
433 }
434
435 private:
436 TvdApproach tvdApproach_;
437 DifferencingScheme differencingScheme_;
438 Scalar upwindWeight_;
439
440 std::function<Scalar(const Scalar, const Scalar)> limiter_;
441 };
442
443 } // end namespace Dumux
444
445 #endif
446