ryujin 2.1.1 revision a15074459a388761bd8df6bd4ef7e6abe9d8077b
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
62 using state_type = typename View::state_type;
63
67 static constexpr unsigned int n_precomputed_values =
69
74
79
84
103
107 static constexpr unsigned int n_bounds = 2;
108
112 using Bounds = std::array<Number, n_bounds>;
113
117 Limiter(const HyperbolicSystem &hyperbolic_system,
118 const Parameters &parameters,
120 &precomputed_values)
121 : hyperbolic_system(hyperbolic_system)
122 , parameters(parameters)
123 , precomputed_values(precomputed_values)
124 {
125 }
126
130 void reset(const unsigned int i,
131 const state_type &U_i,
132 const flux_contribution_type &flux_i);
133
138 void accumulate(const unsigned int *js,
139 const state_type &U_j,
140 const flux_contribution_type &flux_j,
141 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
142 const Number beta_ij);
143
147 Bounds bounds(const Number hd_i) const;
148
149 //*}
152
159 std::tuple<Number, bool> limit(const Bounds &bounds,
160 const state_type &U,
161 const state_type &P,
162 const Number t_min = Number(0.),
163 const Number t_max = Number(1.));
164
165 //*}
170
177 static bool
178 is_in_invariant_domain(const HyperbolicSystem & /*hyperbolic_system*/,
179 const Bounds & /*bounds*/,
180 const state_type & /*U*/);
181
182 private:
184
186
187 const HyperbolicSystem &hyperbolic_system;
188 const Parameters &parameters;
189
191 &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 void
213 Limiter<dim, Number>::reset(const unsigned int /*i*/,
214 const state_type &new_U_i,
215 const flux_contribution_type &new_flux_i)
216 {
217 U_i = new_U_i;
218 flux_i = new_flux_i;
219
220 /* Bounds: */
221
222 auto &[u_min, u_max] = bounds_;
223
224 u_min = Number(std::numeric_limits<ScalarNumber>::max());
225 u_max = Number(0.);
226
227 /* Relaxation: */
228
229 u_relaxation_numerator = Number(0.);
230 u_relaxation_denominator = Number(0.);
231 }
232
233
234 template <int dim, typename Number>
235 DEAL_II_ALWAYS_INLINE inline void Limiter<dim, Number>::accumulate(
236 const unsigned int * /*js*/,
237 const state_type &U_j,
238 const flux_contribution_type &flux_j,
239 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
240 const Number beta_ij)
241 {
242 const auto view = hyperbolic_system.view<dim, Number>();
243
244 /* Bounds: */
245 auto &[u_min, u_max] = bounds_;
246
247 const auto u_i = view.state(U_i);
248 const auto u_j = view.state(U_j);
249
250 const auto U_ij_bar =
251 ScalarNumber(0.5) * (U_i + U_j) -
252 ScalarNumber(0.5) * contract(add(flux_j, -flux_i), scaled_c_ij);
253
254 const auto u_ij_bar = view.state(U_ij_bar);
255
256 /* Bounds: */
257
258 u_min = std::min(u_min, u_ij_bar);
259 u_max = std::max(u_max, u_ij_bar);
260
261 /* Relaxation: */
262
263 u_relaxation_numerator += beta_ij * (u_i + u_j);
264 u_relaxation_denominator += std::abs(beta_ij);
265 }
266
267
268 template <int dim, typename Number>
269 DEAL_II_ALWAYS_INLINE inline auto
270 Limiter<dim, Number>::bounds(const Number hd_i) const -> Bounds
271 {
272 auto relaxed_bounds = bounds_;
273 auto &[u_min, u_max] = relaxed_bounds;
274
275 /* Use r_i = factor * (m_i / |Omega|) ^ (1.5 / d): */
276
277 Number r_i = std::sqrt(hd_i); // in 3D: ^ 3/6
278 if constexpr (dim == 2) //
279 r_i = dealii::Utilities::fixed_power<3>(std::sqrt(r_i)); // in 2D: ^ 3/4
280 else if constexpr (dim == 1) //
281 r_i = dealii::Utilities::fixed_power<3>(r_i); // in 1D: ^ 3/2
282 r_i *= parameters.relaxation_factor();
283
284 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
285 const Number u_relaxation =
286 std::abs(u_relaxation_numerator) /
287 (std::abs(u_relaxation_denominator) + Number(eps));
288
289 u_min = std::max((Number(1.) - r_i) * u_min,
290 u_min - ScalarNumber(2.) * u_relaxation);
291
292 u_max = std::min((Number(1.) + r_i) * u_max,
293 u_max + ScalarNumber(2.) * u_relaxation);
294
295 return relaxed_bounds;
296 }
297
298
299 template <int dim, typename Number>
300 DEAL_II_ALWAYS_INLINE inline bool
302 const HyperbolicSystem & /*hyperbolic_system*/,
303 const Bounds & /*bounds*/,
304 const state_type & /*U*/)
305 {
306 AssertThrow(false, dealii::ExcNotImplemented());
307 __builtin_trap();
308 return true;
309 }
310
311
312 } // namespace ScalarConservation
313} // namespace ryujin
static constexpr unsigned int n_precomputed_values
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:112
Limiter(const HyperbolicSystem &hyperbolic_system, const Parameters &parameters, const MultiComponentVector< ScalarNumber, n_precomputed_values > &precomputed_values)
Definition: limiter.h:117
static bool is_in_invariant_domain(const HyperbolicSystem &, const Bounds &, const state_type &)
Definition: limiter.h:301
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 Number beta_ij)
Definition: limiter.h:235
typename View::state_type state_type
Definition: limiter.h:62
void reset(const unsigned int i, const state_type &U_i, const flux_contribution_type &flux_i)
Definition: limiter.h:213
static constexpr unsigned int n_bounds
Definition: limiter.h:107
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 get_value_type< Number >::type ScalarNumber
Definition: limiter.h:78
Bounds bounds(const Number hd_i) const
Definition: limiter.h:270
static constexpr unsigned int n_precomputed_values
Definition: limiter.h:67
typename View::flux_contribution_type flux_contribution_type
Definition: limiter.h:73
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)