ryujin 2.1.1 revision 955e869188d49b3c97ca7b1cf4fd9ceb0e6f46ef
limiter.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2023 - 2024 by the ryujin authors
4//
5
6#pragma once
7
8#include "hyperbolic_system.h"
9
10#include <compile_time_options.h>
12#include <simd.h>
13
14namespace ryujin
15{
16 namespace ScalarConservation
17 {
18 template <typename ScalarNumber = double>
19 class LimiterParameters : public dealii::ParameterAcceptor
20 {
21 public:
22 LimiterParameters(const std::string &subsection = "/Limiter")
23 : ParameterAcceptor(subsection)
24 {
25 iterations_ = 2;
26 add_parameter(
27 "iterations", iterations_, "Number of limiter iterations");
28
29 relaxation_factor_ = ScalarNumber(1.);
30 add_parameter("relaxation factor",
31 relaxation_factor_,
32 "Factor for scaling the relaxation window with r_i = "
33 "factor * (m_i/|Omega|)^(1.5/d).");
34 }
35
36 ACCESSOR_READ_ONLY(iterations);
37 ACCESSOR_READ_ONLY(relaxation_factor);
38
39 private:
40 unsigned int iterations_;
41 ScalarNumber relaxation_factor_;
42 };
43
44
50 template <int dim, typename Number = double>
51 class Limiter
52 {
53 public:
58
60
62
64
65 using state_type = typename View::state_type;
66
68
70
72
74
76
79 //
81
85 static constexpr unsigned int n_bounds = 2;
86
90 using Bounds = std::array<Number, n_bounds>;
91
95 Limiter(const HyperbolicSystem &hyperbolic_system,
96 const Parameters &parameters,
97 const PrecomputedVector &precomputed_values)
98 : hyperbolic_system(hyperbolic_system)
99 , parameters(parameters)
100 , precomputed_values(precomputed_values)
101 {
102 }
103
109 const state_type &U_i) const;
110
116 Bounds combine_bounds(const Bounds &bounds_left,
117 const Bounds &bounds_right) const;
118
124 Bounds fully_relax_bounds(const Bounds &bounds, const Number &hd) const;
125
127
145
149 void reset(const unsigned int i,
150 const state_type &U_i,
151 const flux_contribution_type &flux_i);
152
157 void accumulate(const unsigned int *js,
158 const state_type &U_j,
159 const flux_contribution_type &flux_j,
160 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
161 const state_type &affine_shift);
162
166 Bounds bounds(const Number hd_i) const;
167
168 //*}
171
178 std::tuple<Number, bool> limit(const Bounds &bounds,
179 const state_type &U,
180 const state_type &P,
181 const Number t_min = Number(0.),
182 const Number t_max = Number(1.)) const;
183
184 private:
186
188
189 const HyperbolicSystem &hyperbolic_system;
190 const Parameters &parameters;
191 const PrecomputedVector &precomputed_values;
192
193 state_type U_i;
195
196 Bounds bounds_;
197
198 Number u_relaxation_numerator;
199 Number u_relaxation_denominator;
201 };
202
203
204 /*
205 * -------------------------------------------------------------------------
206 * Inline definitions
207 * -------------------------------------------------------------------------
208 */
209
210
211 template <int dim, typename Number>
212 DEAL_II_ALWAYS_INLINE inline auto
214 const unsigned int /*i*/, const state_type &U_i) const -> Bounds
215 {
216 const auto view = hyperbolic_system.view<dim, Number>();
217 const auto u_i = view.state(U_i);
218 return {/*u_min*/ u_i, /*u_max*/ u_i};
219 }
220
221
222 template <int dim, typename Number>
223 DEAL_II_ALWAYS_INLINE inline auto Limiter<dim, Number>::combine_bounds(
224 const Bounds &bounds_left, const Bounds &bounds_right) const -> Bounds
225 {
226 const auto &[u_min_l, u_max_l] = bounds_left;
227 const auto &[u_min_r, u_max_r] = bounds_right;
228
229 return {std::min(u_min_l, u_min_r), std::max(u_max_l, u_max_r)};
230 }
231
232
233 template <int dim, typename Number>
234 DEAL_II_ALWAYS_INLINE inline auto
236 const Number &hd) const -> Bounds
237 {
238 auto relaxed_bounds = bounds;
239 auto &[u_min, u_max] = relaxed_bounds;
240
241 /* Use r = factor * (m_i / |Omega|) ^ (1.5 / d): */
242
243 Number r = std::sqrt(hd); // in 3D: ^ 3/6
244 if constexpr (dim == 2) //
245 r = dealii::Utilities::fixed_power<3>(std::sqrt(r)); // in 2D: ^ 3/4
246 else if constexpr (dim == 1) //
247 r = dealii::Utilities::fixed_power<3>(r); // in 1D: ^ 3/2
248 r *= parameters.relaxation_factor();
249
250 u_min = std::min((Number(1.) - r) * u_min, (Number(1.) + r) * u_min);
251 u_max = std::max((Number(1.) + r) * u_max, (Number(1.) - r) * u_max);
252
253 return relaxed_bounds;
254 }
255
256
257 template <int dim, typename Number>
258 DEAL_II_ALWAYS_INLINE inline void
259 Limiter<dim, Number>::reset(const unsigned int /*i*/,
260 const state_type &new_U_i,
261 const flux_contribution_type &new_flux_i)
262 {
263 U_i = new_U_i;
264 flux_i = new_flux_i;
265
266 /* Bounds: */
267
268 auto &[u_min, u_max] = bounds_;
269
270 u_min = Number(std::numeric_limits<ScalarNumber>::max());
271 u_max = Number(std::numeric_limits<ScalarNumber>::lowest());
272
273 /* Relaxation: */
274
275 u_relaxation_numerator = Number(0.);
276 u_relaxation_denominator = Number(0.);
277 }
278
279
280 template <int dim, typename Number>
281 DEAL_II_ALWAYS_INLINE inline void Limiter<dim, Number>::accumulate(
282 const unsigned int * /*js*/,
283 const state_type &U_j,
284 const flux_contribution_type &flux_j,
285 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
286 const state_type &affine_shift)
287 {
288 const auto view = hyperbolic_system.view<dim, Number>();
289
290 /* Bounds: */
291 auto &[u_min, u_max] = bounds_;
292
293 const auto u_i = view.state(U_i);
294 const auto u_j = view.state(U_j);
295
296 const auto U_ij_bar =
297 ScalarNumber(0.5) * (U_i + U_j) -
298 ScalarNumber(0.5) * contract(add(flux_j, -flux_i), scaled_c_ij) +
299 affine_shift;
300
301 const auto u_ij_bar = view.state(U_ij_bar);
302
303 /* Bounds: */
304
305 u_min = std::min(u_min, u_ij_bar);
306 u_max = std::max(u_max, u_ij_bar);
307
308 /* Relaxation: */
309
310 /* Use a uniform weight. */
311 const auto beta_ij = Number(1.);
312 u_relaxation_numerator += beta_ij * (u_i + u_j);
313 u_relaxation_denominator += std::abs(beta_ij);
314 }
315
316
317 template <int dim, typename Number>
318 DEAL_II_ALWAYS_INLINE inline auto
319 Limiter<dim, Number>::bounds(const Number hd_i) const -> Bounds
320 {
321 const auto &[u_min, u_max] = bounds_;
322
323 auto relaxed_bounds = fully_relax_bounds(bounds_, hd_i);
324 auto &[u_min_relaxed, u_max_relaxed] = relaxed_bounds;
325
326 /* Apply a stricter window: */
327
328 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
329
330 const Number u_relaxation =
331 ScalarNumber(2. * parameters.relaxation_factor()) *
332 std::abs(u_relaxation_numerator) /
333 (std::abs(u_relaxation_denominator) + Number(eps));
334
335 u_min_relaxed = std::max(u_min_relaxed, u_min - u_relaxation);
336 u_max_relaxed = std::min(u_max_relaxed, u_max + u_relaxation);
337
338 return relaxed_bounds;
339 }
340 } // namespace ScalarConservation
341} // namespace ryujin
std::array< Number, n_precomputed_values > precomputed_type
Vectors::MultiComponentVector< ScalarNumber, n_precomputed_values > PrecomputedVector
typename get_value_type< Number >::type ScalarNumber
dealii::Tensor< 1, problem_dimension, Number > state_type
LimiterParameters(const std::string &subsection="/Limiter")
Definition: limiter.h:22
std::array< Number, n_bounds > Bounds
Definition: limiter.h:90
Limiter(const HyperbolicSystem &hyperbolic_system, const Parameters &parameters, const PrecomputedVector &precomputed_values)
Definition: limiter.h:95
typename View::PrecomputedVector PrecomputedVector
Definition: limiter.h:71
Bounds fully_relax_bounds(const Bounds &bounds, const Number &hd) const
Definition: limiter.h:235
typename View::state_type state_type
Definition: limiter.h:65
Bounds combine_bounds(const Bounds &bounds_left, const Bounds &bounds_right) const
Definition: limiter.h:223
Bounds projection_bounds_from_state(const unsigned int i, const state_type &U_i) const
Definition: limiter.h:213
void reset(const unsigned int i, const state_type &U_i, const flux_contribution_type &flux_i)
Definition: limiter.h:259
std::tuple< Number, bool > limit(const Bounds &bounds, const state_type &U, const state_type &P, const Number t_min=Number(0.), const Number t_max=Number(1.)) const
static constexpr unsigned int n_bounds
Definition: limiter.h:85
typename View::ScalarNumber ScalarNumber
Definition: limiter.h:61
static constexpr auto problem_dimension
Definition: limiter.h:63
Bounds bounds(const Number hd_i) const
Definition: limiter.h:319
typename View::flux_contribution_type flux_contribution_type
Definition: limiter.h:67
void accumulate(const unsigned int *js, const state_type &U_j, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &scaled_c_ij, const state_type &affine_shift)
Definition: limiter.h:281
typename View::precomputed_type precomputed_type
Definition: limiter.h:69
DEAL_II_ALWAYS_INLINE FT add(const FT &flux_left_ij, const FT &flux_right_ij)
DEAL_II_ALWAYS_INLINE dealii::Tensor< 1, problem_dim, T > contract(const FT &flux_ij, const TT &c_ij)