3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
staggeredupwindmethods.hh
Go to the documentation of this file.
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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
23#ifndef DUMUX_UPWINDING_METHODS_HH
24#define DUMUX_UPWINDING_METHODS_HH
25
26#include <cmath>
27#include <functional>
28#include <iostream>
29#include <string>
30
33
34namespace Dumux {
35
37enum class TvdApproach
38{
40};
41
44{
46};
47
51template<class Scalar, int upwindSchemeOrder>
53{
54public:
55 StaggeredUpwindMethods(const std::string& paramGroup = "")
56 {
57 upwindWeight_ = getParamFromGroup<Scalar>(paramGroup, "Flux.UpwindWeight");
58
59 if (upwindSchemeOrder > 1)
60 {
61 // Read the runtime parameters
62 tvdApproach_ = tvdApproachFromString(getParamFromGroup<std::string>(paramGroup, "Flux.TvdApproach", "Uniform"));
63 differencingScheme_ = differencingSchemeFromString(getParamFromGroup<std::string>(paramGroup, "Flux.DifferencingScheme", "Minmod"));
64
65 // Assign the limiter_ depending on the differencing scheme
66 switch (differencingScheme_)
67 {
69 {
70 limiter_ = this->vanleer;
71 break;
72 }
74 {
75 if (tvdApproach_ == TvdApproach::hou)
76 DUNE_THROW(ParameterException, "\nDifferencing scheme (Van Albada) is not implemented for the Tvd approach (Hou).");
77 else
78 limiter_ = this->vanalbada;
79 break;
80 }
82 {
83 limiter_ = this->minmod;
84 break;
85 }
87 {
88 limiter_ = this->superbee;
89 break;
90 }
92 {
93 limiter_ = this->umist;
94 break;
95 }
97 {
98 limiter_ = this->mclimiter;
99 break;
100 }
102 {
103 limiter_ = this->wahyd;
104 break;
105 }
106 default:
107 {
108 DUNE_THROW(ParameterException, "\nDifferencing scheme " << static_cast<std::string>(differencingSchemeToString(differencingScheme_)) <<
109 " is not implemented.\n"); // should never be reached
110 break;
111 }
112 }
113
114 if (!hasParamInGroup(paramGroup, "Flux.TvdApproach"))
115 {
116 std::cout << "No TvdApproach specified. Defaulting to the Uniform method." << "\n";
117 std::cout << "Other available TVD approaches for uniform (and nonuniform) grids are as follows: \n"
118 << " " << tvdApproachToString(TvdApproach::uniform) << ": assumes a Uniform cell size distribution\n"
119 << " " << tvdApproachToString(TvdApproach::li) << ": Li's approach for nonuniform cell sizes\n"
120 << " " << tvdApproachToString(TvdApproach::hou) << ": Hou's approach for nonuniform cell sizes \n";
121 std::cout << "Each approach can be specified as written above in the Flux group under the title TvdApproach in your input file. \n";
122 }
123 if (!hasParamInGroup(paramGroup, "Flux.DifferencingScheme"))
124 {
125
126 std::cout << "No DifferencingScheme specified. Defaulting to the Minmod scheme." << "\n";
127 std::cout << "Other available Differencing Schemes are as follows: \n"
128 << " " << differencingSchemeToString(DifferencingScheme::vanleer) << ": The Vanleer flux limiter\n"
129 << " " << differencingSchemeToString(DifferencingScheme::vanalbada) << ": The Vanalbada flux limiter\n"
130 << " " << differencingSchemeToString(DifferencingScheme::minmod) << ": The Minmod flux limiter\n"
131 << " " << differencingSchemeToString(DifferencingScheme::superbee) << ": The Superbee flux limiter\n"
132 << " " << differencingSchemeToString(DifferencingScheme::umist) << ": The Umist flux limiter\n"
133 << " " << differencingSchemeToString(DifferencingScheme::mclimiter) << ": The Mclimiter flux limiter\n"
134 << " " << differencingSchemeToString(DifferencingScheme::wahyd) << ": The Wahyd flux limiter";
135 std::cout << "Each scheme can be specified as written above in the Flux group under the variable DifferencingScheme in your input file. \n";
136 }
137
138 std::cout << "Using the tvdApproach \"" << tvdApproachToString(tvdApproach_)
139 << "\" and the differencing Scheme \" " << differencingSchemeToString(differencingScheme_) << "\" \n";
140 }
141 else
142 {
143 // If the runtime parameters are not specified we will use upwind
144 tvdApproach_ = TvdApproach::none;
145 differencingScheme_ = DifferencingScheme::none;
146 }
147 }
148
154 {
155 if (tvd == "Uniform") return TvdApproach::uniform;
156 if (tvd == "Li") return TvdApproach::li;
157 if (tvd == "Hou") return TvdApproach::hou;
158 DUNE_THROW(ParameterException, "\nThis tvd approach : \"" << tvd << "\" is not implemented.\n"
159 << "The available TVD approaches for uniform (and nonuniform) grids are as follows: \n"
160 << tvdApproachToString(TvdApproach::uniform) << ": assumes a uniform cell size distribution\n"
161 << tvdApproachToString(TvdApproach::li) << ": li's approach for nonuniform cell sizes\n"
162 << tvdApproachToString(TvdApproach::hou) << ": hou's approach for nonuniform cell sizes");
163 }
164
169 {
170 switch (tvd)
171 {
172 case TvdApproach::uniform: return "Uniform";
173 case TvdApproach::li: return "Li";
174 case TvdApproach::hou: return "Hou";
175 default: return "Invalid"; // should never be reached
176 }
177 }
178
184 {
185 if (differencingScheme == "Vanleer") return DifferencingScheme::vanleer;
186 if (differencingScheme == "Vanalbada") return DifferencingScheme::vanalbada;
187 if (differencingScheme == "Minmod") return DifferencingScheme::minmod;
188 if (differencingScheme == "Superbee") return DifferencingScheme::superbee;
189 if (differencingScheme == "Umist") return DifferencingScheme::umist;
190 if (differencingScheme == "Mclimiter") return DifferencingScheme::mclimiter;
191 if (differencingScheme == "Wahyd") return DifferencingScheme::wahyd;
192 DUNE_THROW(ParameterException, "\nThis differencing scheme: \"" << differencingScheme << "\" is not implemented.\n"
193 << "The available differencing schemes are as follows: \n"
194 << differencingSchemeToString(DifferencingScheme::vanleer) << ": The Vanleer flux limiter\n"
195 << differencingSchemeToString(DifferencingScheme::vanalbada) << ": The VanAlbada flux limiter\n"
196 << differencingSchemeToString(DifferencingScheme::minmod) << ": The Min-Mod flux limiter\n"
197 << differencingSchemeToString(DifferencingScheme::superbee) << ": The SuperBEE flux limiter\n"
198 << differencingSchemeToString(DifferencingScheme::umist) << ": The UMist flux limiter\n"
199 << differencingSchemeToString(DifferencingScheme::mclimiter) << ": The McLimiter flux limiter\n"
200 << differencingSchemeToString(DifferencingScheme::wahyd) << ": The Wahyd flux limiter");
201 }
202
207 {
208 switch (differencingScheme)
209 {
210 case DifferencingScheme::vanleer: return "Vanleer";
211 case DifferencingScheme::vanalbada: return "Vanalbada";
212 case DifferencingScheme::minmod: return "Minmod";
213 case DifferencingScheme::superbee: return "Superbee";
214 case DifferencingScheme::umist: return "Umist";
215 case DifferencingScheme::mclimiter: return "Mclimiter";
216 case DifferencingScheme::wahyd: return "Wahyd";
217 default: return "Invalid"; // should never be reached
218 }
219 }
220
224 Scalar upwind(const Scalar downstreamMomentum,
225 const Scalar upstreamMomentum) const
226 {
227 return (upwindWeight_ * upstreamMomentum + (1.0 - upwindWeight_) * downstreamMomentum);
228 }
229
234 Scalar tvd(const std::array<Scalar,3>& momenta,
235 const std::array<Scalar,3>& distances,
236 const bool selfIsUpstream,
237 const TvdApproach tvdApproach) const
238 {
239 Scalar momentum = 0.0;
240 switch(tvdApproach)
241 {
243 {
244 momentum += tvdUniform(momenta, distances, selfIsUpstream);
245 break;
246 }
247 case TvdApproach::li :
248 {
249 momentum += tvdLi(momenta, distances, selfIsUpstream);
250 break;
251 }
252 case TvdApproach::hou :
253 {
254 momentum += tvdHou(momenta, distances, selfIsUpstream);
255 break;
256 }
257 default:
258 {
259 DUNE_THROW(ParameterException, "\nThis Tvd Approach is not implemented.\n");
260 break;
261 }
262 }
263 return momentum;
264 }
265
271 Scalar tvdUniform(const std::array<Scalar,3>& momenta,
272 const std::array<Scalar,3>& distances,
273 const bool selfIsUpstream) const
274 {
275 using std::isfinite;
276 const Scalar downstreamMomentum = momenta[0];
277 const Scalar upstreamMomentum = momenta[1];
278 const Scalar upUpstreamMomentum = momenta[2];
279 const Scalar ratio = (upstreamMomentum - upUpstreamMomentum) / (downstreamMomentum - upstreamMomentum);
280
281 // If the velocity field is uniform (like at the first newton step) we get a NaN
282 if(ratio > 0.0 && isfinite(ratio))
283 {
284 const Scalar secondOrderTerm = 0.5 * limiter_(ratio, 2.0) * (downstreamMomentum - upstreamMomentum);
285 return (upstreamMomentum + secondOrderTerm);
286 }
287 else
288 return upstreamMomentum;
289 }
290
298 Scalar tvdLi(const std::array<Scalar,3>& momenta,
299 const std::array<Scalar,3>& distances,
300 const bool selfIsUpstream) const
301 {
302 using std::isfinite;
303 const Scalar downstreamMomentum = momenta[0];
304 const Scalar upstreamMomentum = momenta[1];
305 const Scalar upUpstreamMomentum = momenta[2];
306 const Scalar upstreamToDownstreamDistance = distances[0];
307 const Scalar upUpstreamToUpstreamDistance = distances[1];
308
309 // selfIsUpstream is required to get the correct sign because upUpstreamToUpstreamDistance is always positive
310 const Scalar upUpstreamGradient = (upstreamMomentum - upUpstreamMomentum) / upUpstreamToUpstreamDistance * selfIsUpstream;
311
312 // Distance between the upUpstream node and the position where it should be if the grid were uniform.
313 const Scalar correctionDistance = upUpstreamToUpstreamDistance - upstreamToDownstreamDistance;
314 const Scalar reconstrutedUpUpstreamVelocity = upUpstreamMomentum + upUpstreamGradient * correctionDistance;
315 const Scalar ratio = (upstreamMomentum - reconstrutedUpUpstreamVelocity) / (downstreamMomentum - upstreamMomentum);
316
317 // If the velocity field is uniform (like at the first newton step) we get a NaN
318 if(ratio > 0.0 && isfinite(ratio))
319 {
320 const Scalar secondOrderTerm = 0.5 * limiter_(ratio, 2.0) * (downstreamMomentum - upstreamMomentum);
321 return (upstreamMomentum + secondOrderTerm);
322 }
323 else
324 return upstreamMomentum;
325 }
326
333 Scalar tvdHou(const std::array<Scalar,3>& momenta,
334 const std::array<Scalar,3>& distances,
335 const bool selfIsUpstream) const
336 {
337 using std::isfinite;
338 const Scalar downstreamMomentum = momenta[0];
339 const Scalar upstreamMomentum = momenta[1];
340 const Scalar upUpstreamMomentum = momenta[2];
341 const Scalar upstreamToDownstreamDistance = distances[0];
342 const Scalar upUpstreamToUpstreamDistance = distances[1];
343 const Scalar downstreamStaggeredCellSize = distances[2];
344 const Scalar ratio = (upstreamMomentum - upUpstreamMomentum) / (downstreamMomentum - upstreamMomentum)
345 * upstreamToDownstreamDistance / upUpstreamToUpstreamDistance;
346
347 // If the velocity field is uniform (like at the first newton step) we get a NaN
348 if(ratio > 0.0 && isfinite(ratio))
349 {
350 const Scalar upstreamStaggeredCellSize = 0.5 * (upstreamToDownstreamDistance + upUpstreamToUpstreamDistance);
351 const Scalar R = (upstreamStaggeredCellSize + downstreamStaggeredCellSize) / upstreamStaggeredCellSize;
352 const Scalar secondOrderTerm = limiter_(ratio, R) / R * (downstreamMomentum - upstreamMomentum);
353 return (upstreamMomentum + secondOrderTerm);
354 }
355 else
356 return upstreamMomentum;
357 }
358
364 static Scalar vanleer(const Scalar r, const Scalar R)
365 {
366 return R * r / (R - 1.0 + r);
367 }
368
372 static Scalar vanalbada(const Scalar r, const Scalar R)
373 {
374 return r * (r + 1.0) / (1.0 + r * r);
375 }
376
380 static Scalar minmod(const Scalar r, const Scalar R)
381 {
382 using std::min;
383 return min(r, 1.0);
384 }
385
391 static Scalar superbee(const Scalar r, const Scalar R)
392 {
393 using std::min;
394 using std::max;
395 return max(min(R * r, 1.0), min(r, R));
396 }
397
401 static Scalar umist(const Scalar r, const Scalar R)
402 {
403 using std::min;
404 return min({R * r, (r * (5.0 - R) + R - 1.0) / 4.0, (r * (R - 1.0) + 5.0 - R) / 4.0, R});
405 }
406
407 /*
408 * \brief Monotonized-Central limiter [Van Leer 1977]
409 */
410 static Scalar mclimiter(const Scalar r, const Scalar R)
411 {
412 using std::min;
413 return min({R * r, (r + 1.0) / 2.0, R});
414 }
415
419 static Scalar wahyd(const Scalar r, const Scalar R)
420 {
421 using std::min;
422 return r > 1 ? min((r + R * r * r) / (R + r * r), R)
423 : vanleer(r, R);
424 }
425
428 {
429 return tvdApproach_;
430 }
431
434 {
435 return differencingScheme_;
436 }
437
438private:
439 TvdApproach tvdApproach_;
440 DifferencingScheme differencingScheme_;
441 Scalar upwindWeight_;
442
443 std::function<Scalar(const Scalar, const Scalar)> limiter_;
444};
445
446} // end namespace Dumux
447
448#endif // DUMUX_UPWINDING_METHODS_HH
Some exceptions thrown in DuMux
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
bool hasParamInGroup(const std::string &paramGroup, const std::string &param)
Check whether a key exists in the parameter tree with a model group prefix.
Definition: parameters.hh:454
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
TvdApproach
Available Tvd approaches.
Definition: staggeredupwindmethods.hh:38
DifferencingScheme
Available differencing schemes.
Definition: staggeredupwindmethods.hh:44
Exception thrown if a run-time parameter is not specified correctly.
Definition: exceptions.hh:60
This file contains different higher order methods for approximating the velocity.
Definition: staggeredupwindmethods.hh:53
TvdApproach tvdApproachFromString(const std::string &tvd)
Convenience function to convert user input given as std::string to the corresponding enum class used ...
Definition: staggeredupwindmethods.hh:153
static Scalar vanalbada(const Scalar r, const Scalar R)
Van Albada flux limiter function [Van Albada et al. 1982].
Definition: staggeredupwindmethods.hh:372
StaggeredUpwindMethods(const std::string &paramGroup="")
Definition: staggeredupwindmethods.hh:55
Scalar upwind(const Scalar downstreamMomentum, const Scalar upstreamMomentum) const
Upwind Method.
Definition: staggeredupwindmethods.hh:224
const DifferencingScheme & differencingScheme() const
Returns the differencing scheme.
Definition: staggeredupwindmethods.hh:433
std::string tvdApproachToString(TvdApproach tvd)
return the name of the TVD approach
Definition: staggeredupwindmethods.hh:168
static Scalar umist(const Scalar r, const Scalar R)
UMIST flux limiter function [Lien and Leschziner 1993].
Definition: staggeredupwindmethods.hh:401
Scalar tvdUniform(const std::array< Scalar, 3 > &momenta, const std::array< Scalar, 3 > &distances, const bool selfIsUpstream) const
Tvd Scheme: Total Variation Diminishing.
Definition: staggeredupwindmethods.hh:271
Scalar tvdLi(const std::array< Scalar, 3 > &momenta, const std::array< Scalar, 3 > &distances, const bool selfIsUpstream) const
Tvd Scheme: Total Variation Diminishing.
Definition: staggeredupwindmethods.hh:298
static Scalar mclimiter(const Scalar r, const Scalar R)
Definition: staggeredupwindmethods.hh:410
DifferencingScheme differencingSchemeFromString(const std::string &differencingScheme)
Convenience function to convert user input given as std::string to the corresponding enum class used ...
Definition: staggeredupwindmethods.hh:183
Scalar tvd(const std::array< Scalar, 3 > &momenta, const std::array< Scalar, 3 > &distances, const bool selfIsUpstream, const TvdApproach tvdApproach) const
Tvd Scheme: Total Variation Diminishing.
Definition: staggeredupwindmethods.hh:234
Scalar tvdHou(const std::array< Scalar, 3 > &momenta, const std::array< Scalar, 3 > &distances, const bool selfIsUpstream) const
Tvd Scheme: Total Variation Diminishing.
Definition: staggeredupwindmethods.hh:333
static Scalar vanleer(const Scalar r, const Scalar R)
Van Leer flux limiter function [Van Leer 1974].
Definition: staggeredupwindmethods.hh:364
const TvdApproach & tvdApproach() const
Returns the Tvd approach.
Definition: staggeredupwindmethods.hh:427
std::string differencingSchemeToString(DifferencingScheme differencingScheme)
return the name of the Discretization Method
Definition: staggeredupwindmethods.hh:206
static Scalar superbee(const Scalar r, const Scalar R)
SUPERBEE flux limiter function [Roe 1985].
Definition: staggeredupwindmethods.hh:391
static Scalar minmod(const Scalar r, const Scalar R)
MinMod flux limiter function [Roe 1985].
Definition: staggeredupwindmethods.hh:380
static Scalar wahyd(const Scalar r, const Scalar R)
WAHYD Scheme [Hou, Simons, Hinkelmann 2007];.
Definition: staggeredupwindmethods.hh:419