Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
HllMethod.hpp
Go to the documentation of this file.
1 // Copyright (c) 2019 Maikel Nadolski
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #ifndef FUB_IDEAL_GAS_FLUX_HLL_METHOD_HPP
22 #define FUB_IDEAL_GAS_FLUX_HLL_METHOD_HPP
23 
24 #include "fub/Direction.hpp"
25 #include "fub/Duration.hpp"
26 #include "fub/Equation.hpp"
27 #include "fub/ForEach.hpp"
28 #include "fub/core/span.hpp"
30 
31 #include <numeric>
32 
33 namespace fub {
34 
35 template <typename Eq, typename SignalSpeeds> class HllBase {
36 public:
37  using Equation = Eq;
38  using Complete = typename Equation::Complete;
39  using Conservative = typename Equation::Conservative;
40 
41  HllBase(const Equation& eq, const SignalSpeeds& signals = SignalSpeeds())
42  : equation_{eq}, signal_speeds_{signals} {}
43 
44  /// \brief Returns the stencil width of this method
45  static constexpr int GetStencilWidth() noexcept { return 1; }
46 
47  /// @{
48  /// \brief Returns the strategy object which computes the signal speeds for
49  /// this method.
50  const SignalSpeeds& GetSignalSpeeds() const noexcept {
51  return signal_speeds_;
52  }
53  SignalSpeeds& GetSignalSpeeds() noexcept { return signal_speeds_; }
54  /// @}
55 
56  /// @{
57  /// \brief Returns the underlying equations object.
58  const Equation& GetEquation() const noexcept { return equation_; }
59  Equation& GetEquation() noexcept { return equation_; }
60  /// @}
61 
62  /// \brief Computes an approximate solution to the rieman problem defined by
63  /// left and right states.
64  ///
65  /// \param[out] solution The solution to the riemann problem will be stored
66  /// here.
67  /// \param[in] left The left state of the riemann problem
68  /// \param[in] right The right state of the riemann problem.
69  /// \param[in] dir The direction in which the riemann problem will be solved.
70  void SolveRiemannProblem(Complete& solution, const Complete& left,
71  const Complete& right, Direction dir);
72 
73  void ComputeNumericFlux(Conservative& numeric_flux,
75  double dx, Direction dir);
76 
77  double ComputeStableDt(span<const Complete, 2> states, double dx,
78  Direction dir);
79 
80 private:
82  SignalSpeeds signal_speeds_;
85 };
86 
87 template <typename Eq, typename SignalSpeeds, bool Simdify> class HllArrayBase;
88 
89 template <typename Equation, typename SignalSpeeds>
90 class HllArrayBase<Equation, SignalSpeeds, true>
91  : public HllBase<Equation, SignalSpeeds> {
92 public:
96 
97  using Base::HllBase;
98 
99  using Base::GetEquation;
100  using Base::GetSignalSpeeds;
101 
102  using Base::SolveRiemannProblem;
103  void SolveRiemannProblem(CompleteArray& solution, const CompleteArray& left,
104  const CompleteArray& right, Direction dir);
105 
106  using Base::ComputeNumericFlux;
107  void ComputeNumericFlux(ConservativeArray& numeric_flux,
109  double dx, Direction dir);
110 
111  void ComputeNumericFlux(ConservativeArray& numeric_flux,
112  Array1d face_fraction,
114  span<const Array1d, 2> volume_fraction, Duration dt,
115  double dx, Direction dir);
116 
117  using Base::ComputeStableDt;
118  Array1d ComputeStableDt(span<const CompleteArray, 2> states, double dx,
119  Direction dir);
120 
121  Array1d ComputeStableDt(span<const CompleteArray, 2> states,
122  Array1d face_fraction,
123  span<const Array1d, 2> volume_fraction, double dx,
124  Direction dir);
125 
126 private:
127  ConservativeArray flux_left_array_{Base::GetEquation()};
128  ConservativeArray flux_right_array_{Base::GetEquation()};
129 };
130 
131 template <typename Equation, typename SignalSpeeds>
132 class HllArrayBase<Equation, SignalSpeeds, false>
133  : public HllBase<Equation, SignalSpeeds> {
135 };
136 
137 template <typename Equation, typename SignalSpeeds>
138 class Hll : public HllArrayBase<Equation, SignalSpeeds,
139  HasVectorizedFlux<Equation>::value> {
140  using Base =
142  using Base::Base;
143 };
144 
145 template <typename Equation, typename Signals>
146 Hll(const Equation& eq, const Signals& signals)->Hll<Equation, Signals>;
147 
148 /// \ingroup FluxMethod
149 template <typename Equation, typename Signals>
150 struct HllMethod : public FluxMethod<Hll<Equation, Signals>> {
152 };
153 
154 template <typename Equation, typename Signals>
155 HllMethod(const Equation& eq, const Signals& signals)
156  ->HllMethod<Equation, Signals>;
157 
158 ///////////////////////////////////////////////////////////////////////////////
159 // Implementation of HllBase<Equation, SignalSpeeds>
160 
161 template <typename Equation, typename SignalSpeeds>
163  const Complete& left,
164  const Complete& right,
165  Direction dir) {
166  const auto signals = signal_speeds_(equation_, left, right, dir);
167  Flux(GetEquation(), flux_left_, left, dir);
168  Flux(GetEquation(), flux_right_, right, dir);
169  const double sL = signals[0];
170  const double sR = signals[1];
171  const double ds = sL != sR ? sR - sL : 1.0;
172  if (0.0 < sL) {
173  solution = left;
174  } else if (sR < 0.0) {
175  solution = right;
176  } else {
178  [&](double& sol, double fL, double fR, double qL, double qR) {
179  sol = (sR * qR - sL * qL + fL - fR) / ds;
180  },
181  AsCons(solution), flux_left_, flux_right_, AsCons(left), AsCons(right));
182  CompleteFromCons(GetEquation(), solution, solution);
183  }
184 }
185 
186 template <typename Equation, typename SignalSpeeds>
188  Conservative& numeric_flux, span<const Complete, 2> states,
189  Duration /* dt */, double /* dx */, Direction dir) {
190  const Complete& left = states[0];
191  const Complete& right = states[1];
192 
193  const auto signals = signal_speeds_(GetEquation(), left, right, dir);
194 
195  Flux(GetEquation(), flux_left_, left, dir);
196  Flux(GetEquation(), flux_right_, right, dir);
197 
198  const double sL = std::min(0.0, signals[0]);
199  const double sR = std::max(0.0, signals[1]);
200  const double sLsR = sL * sR;
201  const double ds = sR - sL;
202  FUB_ASSERT(ds > 0);
203 
205  [&](double& nf, double fL, double fR, double qL, double qR) {
206  nf = (sR * fL - sL * fR + sLsR * (qR - qL)) / ds;
207  },
208  numeric_flux, flux_left_, flux_right_, states[0], states[1]);
209 }
210 
211 template <typename Equation, typename SignalSpeeds>
212 double
214  double dx, Direction dir) {
215  const auto signals = signal_speeds_(GetEquation(), states[0], states[1], dir);
216  const double max = std::accumulate(
217  signals.begin(), signals.end(), 0.0,
218  [](double x, double y) { return std::max(x, std::abs(y)); });
219  FUB_ASSERT(max > 0.0);
220  return dx / max;
221 }
222 
223 ///////////////////////////////////////////////////////////////////////////////
224 // Implementation of HllArrayBase<Equation, SignalSpeeds>
225 
226 template <typename Equation, typename SignalSpeeds>
228  CompleteArray& solution, const CompleteArray& left,
229  const CompleteArray& right, Direction dir) {
230  const auto signals = GetSignalSpeeds()(GetEquation(), left, right, dir);
231  Flux(GetEquation(), flux_left_array_, left, dir);
232  Flux(GetEquation(), flux_right_array_, right, dir);
233  const Array1d sL = signals[0];
234  const Array1d sR = signals[1];
235  Array1d ds = sR - sL;
236  ds = (ds > 0.0).select(ds, Array1d::Constant(1.0));
238  [&](auto&& sol, Array1d fL, Array1d fR, Array1d qL, Array1d qR) {
239  sol = (sR * qR - sL * qL + fL - fR) / ds;
240  sol = (0.0 < sL).select(qL, (sR < 0.0).select(qR, sol));
241  },
242  AsCons(solution), flux_left_array_, flux_right_array_, AsCons(left),
243  AsCons(right));
244  // CompleteFromCons(GetEquation(), solution, solution);
245 }
246 
247 template <typename Equation, typename SignalSpeeds>
249  ConservativeArray& numeric_flux, span<const CompleteArray, 2> states,
250  Duration /* dt */, double /* dx */, Direction dir) {
251  const CompleteArray& left = states[0];
252  const CompleteArray& right = states[1];
253 
254  const auto signals = GetSignalSpeeds()(GetEquation(), left, right, dir);
255 
256  Flux(GetEquation(), flux_left_array_, left, dir);
257  Flux(GetEquation(), flux_right_array_, right, dir);
258 
259  const Array1d zero = Array1d::Zero();
260  const Array1d sL = signals[0].min(zero);
261  const Array1d sR = signals[1].max(zero);
262  const Array1d sLsR = sL * sR;
263  Array1d ds = sR - sL;
264  ds = (ds > 0.0).select(ds, Array1d::Constant(1.0));
265 
267  [&](auto&& nf, Array1d fL, Array1d fR, Array1d qL, Array1d qR) {
268  nf = (sR * fL - sL * fR + sLsR * (qR - qL)) / ds;
269  },
270  numeric_flux, flux_left_array_, flux_right_array_, AsCons(left),
271  AsCons(right));
272 }
273 
274 template <typename Equation, typename SignalSpeeds>
276  ConservativeArray& numeric_flux, Array1d face_fraction,
278  span<const Array1d, 2> /* volume_fractions */, Duration /* dt */,
279  double /* dx */, Direction dir) {
280  const CompleteArray& left = states[0];
281  const CompleteArray& right = states[1];
282 
283  MaskArray mask = face_fraction > 0.0;
284 
285  const auto signals = GetSignalSpeeds()(GetEquation(), left, right, mask, dir);
286 
287  Flux(GetEquation(), flux_left_array_, left, mask, dir);
288  Flux(GetEquation(), flux_right_array_, right, mask, dir);
289 
290  const Array1d zero = Array1d::Zero();
291  const Array1d sL = signals[0].min(zero);
292  const Array1d sR = signals[1].max(zero);
293  const Array1d sLsR = sL * sR;
294  const Array1d ds = sR - sL;
295 
296  const Array1d safe_ds = mask.select(ds, 1.0);
297  FUB_ASSERT((safe_ds > 0.0).all());
299  [&](auto&& nf, Array1d fL, Array1d fR, Array1d qL, Array1d qR) {
300  Array1d qL_s = mask.select(qL, 0.0);
301  Array1d qR_s = mask.select(qR, 0.0);
302  nf = (sR * fL - sL * fR + sLsR * (qR_s - qL_s)) / safe_ds;
303  },
304  numeric_flux, flux_left_array_, flux_right_array_, AsCons(left),
305  AsCons(right));
306 }
307 
308 template <typename Equation, typename SignalSpeeds>
310  span<const CompleteArray, 2> states, double dx, Direction dir) {
311  const auto signals =
312  GetSignalSpeeds()(GetEquation(), states[0], states[1], dir);
313  Array1d zero = Array1d::Zero();
314  const Array1d max =
315  std::accumulate(signals.begin(), signals.end(), zero,
316  [](Array1d x, Array1d y) { return x.max(y.abs()); });
317  return Array1d(dx) / max;
318 }
319 
320 template <typename Equation, typename SignalSpeeds>
322  span<const CompleteArray, 2> states, Array1d face_fraction,
323  span<const Array1d, 2>, double dx,
324  Direction dir) {
325  MaskArray mask = (face_fraction > 0.0);
326  const auto signals =
327  GetSignalSpeeds()(GetEquation(), states[0], states[1], mask, dir);
328  Array1d zero = Array1d::Zero();
329  const Array1d max =
330  std::accumulate(signals.begin(), signals.end(), zero,
331  [](Array1d x, Array1d y) { return x.max(y.abs()); });
332  const Array1d safe_max = mask.select(max, 1.0);
333  Array1d infs = Array1d::Constant(std::numeric_limits<double>::max());
334  Array1d stable_dts = Array1d(dx) / safe_max;
335  Array1d valid_stable_dts = mask.select(stable_dts, infs);
336  return valid_stable_dts;
337 }
338 
339 } // namespace fub
340 
341 #endif
#define FUB_ASSERT(x)
Definition: assert.hpp:39
This class applies a base flux nethod on a view of states.
Definition: flux_method/FluxMethod.hpp:57
Definition: HllMethod.hpp:87
Definition: HllMethod.hpp:35
SignalSpeeds signal_speeds_
Definition: HllMethod.hpp:82
typename Equation::Complete Complete
Definition: HllMethod.hpp:38
HllBase(const Equation &eq, const SignalSpeeds &signals=SignalSpeeds())
Definition: HllMethod.hpp:41
Conservative flux_left_
Definition: HllMethod.hpp:83
SignalSpeeds & GetSignalSpeeds() noexcept
Returns the strategy object which computes the signal speeds for this method.
Definition: HllMethod.hpp:53
typename Equation::Conservative Conservative
Definition: HllMethod.hpp:39
Equation equation_
Definition: HllMethod.hpp:81
Eq Equation
Definition: HllMethod.hpp:37
void SolveRiemannProblem(Complete &solution, const Complete &left, const Complete &right, Direction dir)
Computes an approximate solution to the rieman problem defined by left and right states.
Definition: HllMethod.hpp:162
const SignalSpeeds & GetSignalSpeeds() const noexcept
Returns the strategy object which computes the signal speeds for this method.
Definition: HllMethod.hpp:50
Conservative flux_right_
Definition: HllMethod.hpp:84
Equation & GetEquation() noexcept
Returns the underlying equations object.
Definition: HllMethod.hpp:59
double ComputeStableDt(span< const Complete, 2 > states, double dx, Direction dir)
Definition: HllMethod.hpp:213
static constexpr int GetStencilWidth() noexcept
Returns the stencil width of this method.
Definition: HllMethod.hpp:45
const Equation & GetEquation() const noexcept
Returns the underlying equations object.
Definition: HllMethod.hpp:58
void ComputeNumericFlux(Conservative &numeric_flux, span< const Complete, 2 > states, Duration dt, double dx, Direction dir)
Definition: HllMethod.hpp:187
Definition: HllMethod.hpp:139
A span is a view over a contiguous sequence of objects, the storage of which is owned by some other o...
Definition: span.hpp:81
void CompleteFromCons(Equation &&equation, Complete< std::decay_t< Equation >> &complete, const Conservative< std::decay_t< Equation >> &cons)
Definition: CompleteFromCons.hpp:42
std::decay_t< decltype(std::declval< T >().GetEquation())> Equation
A template typedef to detect the member function.
Definition: Meta.hpp:59
The fub namespace.
Definition: AnyBoundaryCondition.hpp:31
void Flux(Eq &&equation, Conservative< Equation > &flux, const Complete< Equation > &state, Direction dir, [[maybe_unused]] double x=0.0)
Definition: Equation.hpp:108
std::chrono::duration< double > Duration
Definition: Duration.hpp:31
Array< double, 1 > Array1d
Definition: Eigen.hpp:53
Hll(const Equation &eq, const Signals &signals) -> Hll< Equation, Signals >
Direction
This is a type safe type to denote a dimensional split direction.
Definition: Direction.hpp:30
HllMethod(const Equation &eq, const Signals &signals) -> HllMethod< Equation, Signals >
const Conservative< Eq > & AsCons(const Conservative< Eq > &x)
Definition: State.hpp:438
void ForEachComponent(F function, Ts &&... states)
Definition: State.hpp:624
Array< bool, 1 > MaskArray
Definition: Eigen.hpp:59
static constexpr all_type all
Definition: mdspan.hpp:741
Definition: HllMethod.hpp:150