ryujin 2.1.1 revision 0348cbb53a3e4b1da2a4c037e81f88f2d21ce219
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
120
138
142 void reset(const unsigned int i,
143 const state_type &U_i,
144 const flux_contribution_type &flux_i);
145
150 void accumulate(const unsigned int *js,
151 const state_type &U_j,
152 const flux_contribution_type &flux_j,
153 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
154 const state_type &affine_shift);
155
159 Bounds bounds(const Number hd_i) const;
160
161 //*}
164
171 std::tuple<Number, bool> limit(const Bounds &bounds,
172 const state_type &U,
173 const state_type &P,
174 const Number t_min = Number(0.),
175 const Number t_max = Number(1.));
176
177 private:
179
181
182 const HyperbolicSystem &hyperbolic_system;
183 const Parameters &parameters;
184 const PrecomputedVector &precomputed_values;
185
186 state_type U_i;
188
189 Bounds bounds_;
190
191 Number u_relaxation_numerator;
192 Number u_relaxation_denominator;
194 };
195
196
197 /*
198 * -------------------------------------------------------------------------
199 * Inline definitions
200 * -------------------------------------------------------------------------
201 */
202
203
204 template <int dim, typename Number>
205 DEAL_II_ALWAYS_INLINE inline auto
207 const unsigned int /*i*/, const state_type &U_i) const -> Bounds
208 {
209 const auto view = hyperbolic_system.view<dim, Number>();
210 const auto u_i = view.state(U_i);
211 return {/*u_min*/ u_i, /*u_max*/ u_i};
212 }
213
214
215 template <int dim, typename Number>
216 DEAL_II_ALWAYS_INLINE inline auto Limiter<dim, Number>::combine_bounds(
217 const Bounds &bounds_left, const Bounds &bounds_right) const -> Bounds
218 {
219 const auto &[u_min_l, u_max_l] = bounds_left;
220 const auto &[u_min_r, u_max_r] = bounds_right;
221
222 return {std::min(u_min_l, u_min_r), std::max(u_max_l, u_max_r)};
223 }
224
225
226 template <int dim, typename Number>
227 DEAL_II_ALWAYS_INLINE inline void
228 Limiter<dim, Number>::reset(const unsigned int /*i*/,
229 const state_type &new_U_i,
230 const flux_contribution_type &new_flux_i)
231 {
232 U_i = new_U_i;
233 flux_i = new_flux_i;
234
235 /* Bounds: */
236
237 auto &[u_min, u_max] = bounds_;
238
239 u_min = Number(std::numeric_limits<ScalarNumber>::max());
240 u_max = Number(std::numeric_limits<ScalarNumber>::lowest());
241
242 /* Relaxation: */
243
244 u_relaxation_numerator = Number(0.);
245 u_relaxation_denominator = Number(0.);
246 }
247
248
249 template <int dim, typename Number>
250 DEAL_II_ALWAYS_INLINE inline void Limiter<dim, Number>::accumulate(
251 const unsigned int * /*js*/,
252 const state_type &U_j,
253 const flux_contribution_type &flux_j,
254 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
255 const state_type &affine_shift)
256 {
257 const auto view = hyperbolic_system.view<dim, Number>();
258
259 /* Bounds: */
260 auto &[u_min, u_max] = bounds_;
261
262 const auto u_i = view.state(U_i);
263 const auto u_j = view.state(U_j);
264
265 const auto U_ij_bar =
266 ScalarNumber(0.5) * (U_i + U_j) -
267 ScalarNumber(0.5) * contract(add(flux_j, -flux_i), scaled_c_ij) +
268 affine_shift;
269
270 const auto u_ij_bar = view.state(U_ij_bar);
271
272 /* Bounds: */
273
274 u_min = std::min(u_min, u_ij_bar);
275 u_max = std::max(u_max, u_ij_bar);
276
277 /* Relaxation: */
278
279 /* Use a uniform weight. */
280 const auto beta_ij = Number(1.);
281 u_relaxation_numerator += beta_ij * (u_i + u_j);
282 u_relaxation_denominator += std::abs(beta_ij);
283 }
284
285
286 template <int dim, typename Number>
287 DEAL_II_ALWAYS_INLINE inline auto
288 Limiter<dim, Number>::bounds(const Number hd_i) const -> Bounds
289 {
290 auto relaxed_bounds = bounds_;
291 auto &[u_min, u_max] = relaxed_bounds;
292
293 /* Use r_i = factor * (m_i / |Omega|) ^ (1.5 / d): */
294
295 Number r_i = std::sqrt(hd_i); // in 3D: ^ 3/6
296 if constexpr (dim == 2) //
297 r_i = dealii::Utilities::fixed_power<3>(std::sqrt(r_i)); // in 2D: ^ 3/4
298 else if constexpr (dim == 1) //
299 r_i = dealii::Utilities::fixed_power<3>(r_i); // in 1D: ^ 3/2
300 r_i *= parameters.relaxation_factor();
301
302 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
303 const Number u_relaxation =
304 std::abs(u_relaxation_numerator) /
305 (std::abs(u_relaxation_denominator) + Number(eps));
306
307 u_min = std::max(
308 std::min((Number(1.) - r_i) * u_min, (Number(1.) + r_i) * u_min),
309 u_min - ScalarNumber(2.) * u_relaxation);
310
311 u_max = std::min(
312 std::max((Number(1.) + r_i) * u_max, (Number(1.) - r_i) * u_max),
313 u_max + ScalarNumber(2.) * u_relaxation);
314
315 return relaxed_bounds;
316 }
317 } // namespace ScalarConservation
318} // 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
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:216
Bounds projection_bounds_from_state(const unsigned int i, const state_type &U_i) const
Definition: limiter.h:206
void reset(const unsigned int i, const state_type &U_i, const flux_contribution_type &flux_i)
Definition: limiter.h:228
static constexpr unsigned int n_bounds
Definition: limiter.h:85
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.))
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:288
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:250
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)