ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
limiter.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0
3// [LANL Copyright Statement]
4// Copyright (C) 2023 - 2025 by the ryujin authors
5// Copyright (C) 2023 - 2024 by Triad National Security, LLC
6//
7
8#pragma once
9
10#include <compile_time_options.h>
11
12#include "hyperbolic_system.h"
13
15#include <newton.h>
16#include <observer_pointer.h>
17
18namespace ryujin
19{
20 namespace ShallowWater
21 {
22 template <int dim, typename Number = double>
23 class LimiterView;
24
30 template <typename ScalarNumber = double>
31 class Limiter : public dealii::ParameterAcceptor
32 {
33 public:
38
43 template <int dim, typename Number = double>
45
47
51
55 Limiter(const HyperbolicSystem &hyperbolic_system,
56 const std::string &subsection = "/Limiter")
57 : ParameterAcceptor(subsection)
58 , hyperbolic_system_(&hyperbolic_system)
59 {
60 iterations_ = 2;
61 add_parameter(
62 "iterations", iterations_, "Number of limiter iterations");
63
64 if constexpr (std::is_same_v<ScalarNumber, double>)
65 newton_tolerance_ = 1.e-10;
66 else
67 newton_tolerance_ = 1.e-4;
68 add_parameter("newton tolerance",
69 newton_tolerance_,
70 "Tolerance for the quadratic newton stopping criterion");
71
72 newton_max_iterations_ = 2;
73 add_parameter("newton max iterations",
74 newton_max_iterations_,
75 "Maximal number of quadratic newton iterations performed "
76 "during limiting");
77
78 relaxation_factor_ = ScalarNumber(1.);
79 add_parameter("relaxation factor",
80 relaxation_factor_,
81 "Factor for scaling the relaxation window with r_i = "
82 "factor * (m_i/|Omega|)^(1.5/d).");
83 }
84
90 template <int dim, typename Number>
91 auto view() const
92 {
93 return View<dim, Number>{
94 hyperbolic_system_->template view<dim, Number>(), *this};
95 }
96
97 private:
99
103
104 unsigned int iterations_;
105 ScalarNumber newton_tolerance_;
106 unsigned int newton_max_iterations_;
107 ScalarNumber relaxation_factor_;
108
110
114
115 dealii::ObserverPointer<const HyperbolicSystem> hyperbolic_system_;
116
118
119 template <int, typename>
120 friend class LimiterView;
121 };
122
123
132 template <int dim, typename Number>
134 {
135 public:
140
142
144
146
147 using state_type = typename View::state_type;
148
150
152
154
156
163 static constexpr unsigned int n_bounds = 3;
164
168 using Bounds = std::array<Number, n_bounds>;
169
174 LimiterView(const View &view, const Limiter<ScalarNumber> &limiter)
175 : view_(view)
176 , limiter_(limiter)
177 {
178 }
179
183 unsigned int iterations() const
184 {
185 return limiter_.iterations_;
186 }
187
192 {
193 return limiter_.newton_tolerance_;
194 }
195
199 unsigned int newton_max_iterations() const
200 {
201 return limiter_.newton_max_iterations_;
202 }
203
208 {
209 return limiter_.relaxation_factor_;
210 }
211
217 const unsigned int i,
218 const state_type &U_i) const;
219
225 Bounds combine_bounds(const Bounds &bounds_left,
226 const Bounds &bounds_right) const;
227
235 Bounds fully_relax_bounds(const Bounds &bounds, const Number &hd) const;
236
238
257
261 void reset(const PrecomputedVectorView &pv,
262 const unsigned int i,
263 const state_type &U_i,
264 const flux_contribution_type &flux_i);
265
270 void accumulate(const PrecomputedVectorView &pv,
271 const state_type &U_j,
272 const state_type &U_star_ij,
273 const state_type &U_star_ji,
274 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
275 const state_type &affine_shift);
276
280 Bounds bounds(const Number hd_i) const;
281
283
287
294 std::tuple<Number, bool> limit(const Bounds &bounds,
295 const state_type &U,
296 const state_type &P,
297 const Number t_min = Number(0.),
298 const Number t_max = Number(1.)) const;
299
300 private:
302
306
307 const View view_;
308 const Limiter<ScalarNumber> &limiter_;
309
310 state_type U_i_;
311
312 Bounds bounds_;
313
314 /* for relaxation */
315
316 Number h_relaxation_numerator_;
317 Number v2_relaxation_numerator_;
318 Number relaxation_denominator_;
319
321 };
322
323
324 /*
325 * -------------------------------------------------------------------------
326 * Inline definitions
327 * -------------------------------------------------------------------------
328 */
329
330
331 template <int dim, typename Number>
332 DEAL_II_ALWAYS_INLINE inline auto
334 const PrecomputedVectorView & /*pv*/,
335 const unsigned int /*i*/,
336 const state_type &U_i) const -> Bounds
337 {
338 const auto h_i = view_.water_depth(U_i);
339 const auto v_i =
340 view_.momentum(U_i) * view_.inverse_water_depth_mollified(U_i);
341 const auto v2_i = v_i.norm_square();
342
343 return {/*h_min*/ h_i, /*h_max*/ h_i, /*v2_max*/ v2_i};
344 }
345
346
347 template <int dim, typename Number>
348 DEAL_II_ALWAYS_INLINE inline auto LimiterView<dim, Number>::combine_bounds(
349 const Bounds &bounds_l, const Bounds &bounds_r) const -> Bounds
350 {
351 const auto &[h_min_l, h_max_l, v2_max_l] = bounds_l;
352 const auto &[h_min_r, h_max_r, v2_max_r] = bounds_r;
353
354 return {std::min(h_min_l, h_min_r),
355 std::max(h_max_l, h_max_r),
356 std::max(v2_max_l, v2_max_r)};
357 }
358
359
360 template <int dim, typename Number>
361 DEAL_II_ALWAYS_INLINE inline auto
363 const Number &hd) const
364 -> Bounds
365 {
366 auto relaxed_bounds = bounds;
367 auto &[h_min, h_max, v2_max] = relaxed_bounds;
368
369 /* Use r = factor * (m_i / |Omega|) ^ (1.5 / d): */
370
371 Number r = std::sqrt(hd); // in 3D: ^ 3/6
372 if constexpr (dim == 2) //
373 r = dealii::Utilities::fixed_power<3>(std::sqrt(r)); // in 2D: ^ 3/4
374 else if constexpr (dim == 1) //
375 r = dealii::Utilities::fixed_power<3>(r); // in 1D: ^ 3/2
376 r *= relaxation_factor();
377
378 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
379 h_min *= std::max((Number(1.) - r), Number(eps));
380 h_max *= (Number(1.) + r);
381 v2_max *= (Number(1.) + r);
382
383 return relaxed_bounds;
384 }
385
386
387 template <int dim, typename Number>
388 DEAL_II_ALWAYS_INLINE inline void
390 unsigned int /*i*/,
391 const state_type &U_i,
392 const flux_contribution_type & /*flux_i*/)
393 {
394 U_i_ = U_i;
395
396 auto &[h_min, h_max, v2_max] = bounds_;
397
398 h_min = Number(std::numeric_limits<ScalarNumber>::max());
399 h_max = Number(0.);
400 v2_max = Number(0.);
401
402 h_relaxation_numerator_ = Number(0.);
403 v2_relaxation_numerator_ = Number(0.);
404 relaxation_denominator_ = Number(0.);
405 }
406
407
408 template <int dim, typename Number>
409 DEAL_II_ALWAYS_INLINE inline void LimiterView<dim, Number>::accumulate(
410 const PrecomputedVectorView & /*pv*/,
411 const state_type &U_j,
412 const state_type &U_star_ij,
413 const state_type &U_star_ji,
414 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
415 const state_type &affine_shift)
416 {
417 /* The bar states: */
418
419 const auto f_star_ij = view_.f(U_star_ij);
420 const auto f_star_ji = view_.f(U_star_ji);
421
422 /* bar state shifted by an affine shift: */
423 const auto U_ij_bar =
424 ScalarNumber(0.5) *
425 (U_star_ij + U_star_ji +
426 contract(add(f_star_ij, -f_star_ji), scaled_c_ij)) +
427 affine_shift;
428
429 /* Bounds: */
430
431 auto &[h_min, h_max, v2_max] = bounds_;
432
433 const auto h_bar_ij = view_.water_depth(U_ij_bar);
434 h_min = std::min(h_min, h_bar_ij);
435 h_max = std::max(h_max, h_bar_ij);
436
437 const auto v_bar_ij = view_.momentum(U_ij_bar) *
438 view_.inverse_water_depth_mollified(U_ij_bar);
439 const auto v2_bar_ij = v_bar_ij.norm_square();
440 v2_max = std::max(v2_max, v2_bar_ij);
441
442 /* Relaxation: */
443
444 /* Use a uniform weight. */
445 const auto beta_ij = Number(1.);
446
447 relaxation_denominator_ += std::abs(beta_ij);
448
449 const auto h_i = view_.water_depth(U_i_);
450 const auto h_j = view_.water_depth(U_j);
451 h_relaxation_numerator_ += beta_ij * (h_i + h_j);
452
453 const auto vel_i =
454 view_.momentum(U_i_) * view_.inverse_water_depth_mollified(U_i_);
455 const auto vel_j =
456 view_.momentum(U_j) * view_.inverse_water_depth_mollified(U_j);
457 v2_relaxation_numerator_ +=
458 beta_ij * (-vel_i.norm_square() + vel_j.norm_square());
459 }
460
461
462 template <int dim, typename Number>
463 DEAL_II_ALWAYS_INLINE inline auto
464 LimiterView<dim, Number>::bounds(const Number hd_i) const -> Bounds
465 {
466 const auto &[h_min, h_max, v2_max] = bounds_;
467
468 auto relaxed_bounds = fully_relax_bounds(bounds_, hd_i);
469 auto &[h_min_relaxed, h_max_relaxed, v2_max_relaxed] = relaxed_bounds;
470
471 /* Apply a stricter window: */
472
473 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
474
475 const Number h_relaxed = ScalarNumber(2. * relaxation_factor()) *
476 std::abs(h_relaxation_numerator_) /
477 (relaxation_denominator_ + Number(eps));
478
479 const Number v2_relaxed = ScalarNumber(2. * relaxation_factor()) *
480 std::abs(v2_relaxation_numerator_) /
481 (relaxation_denominator_ + Number(eps));
482
483 h_min_relaxed = std::max(h_min_relaxed, h_min - h_relaxed);
484 h_max_relaxed = std::min(h_max_relaxed, h_max + h_relaxed);
485 v2_max_relaxed = std::min(v2_max_relaxed, v2_max + v2_relaxed);
486
487 return relaxed_bounds;
488 }
489 } // namespace ShallowWater
490} // namespace ryujin
typename get_value_type< Number >::type ScalarNumber
dealii::Tensor< 1, problem_dimension, Number > state_type
Vectors::MultiComponentVectorView< ScalarNumber, n_precomputed_values, dealii::VectorizedArray< ScalarNumber >::size(), dealii::MemorySpace::Host, false > PrecomputedVectorView
std::array< Number, n_precomputed_values > precomputed_type
static constexpr unsigned int problem_dimension
std::tuple< state_type, Number > flux_contribution_type
HyperbolicSystemView< dim, Number > View
Definition limiter.h:141
unsigned int newton_max_iterations() const
Definition limiter.h:199
typename View::PrecomputedVectorView PrecomputedVectorView
Definition limiter.h:153
typename View::ScalarNumber ScalarNumber
Definition limiter.h:143
Bounds projection_bounds_from_state(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i) const
Definition limiter.h:333
static constexpr auto problem_dimension
Definition limiter.h:145
void reset(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i, const flux_contribution_type &flux_i)
Definition limiter.h:389
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
Bounds bounds(const Number hd_i) const
Definition limiter.h:464
Bounds combine_bounds(const Bounds &bounds_left, const Bounds &bounds_right) const
Definition limiter.h:348
static constexpr unsigned int n_bounds
Definition limiter.h:163
ScalarNumber newton_tolerance() const
Definition limiter.h:191
LimiterView(const View &view, const Limiter< ScalarNumber > &limiter)
Definition limiter.h:174
void accumulate(const PrecomputedVectorView &pv, const state_type &U_j, const state_type &U_star_ij, const state_type &U_star_ji, const dealii::Tensor< 1, dim, Number > &scaled_c_ij, const state_type &affine_shift)
Definition limiter.h:409
typename View::state_type state_type
Definition limiter.h:147
std::array< Number, n_bounds > Bounds
Definition limiter.h:168
Bounds fully_relax_bounds(const Bounds &bounds, const Number &hd) const
Definition limiter.h:362
typename View::flux_contribution_type flux_contribution_type
Definition limiter.h:149
unsigned int iterations() const
Definition limiter.h:183
typename View::precomputed_type precomputed_type
Definition limiter.h:151
ScalarNumber relaxation_factor() const
Definition limiter.h:207
Limiter(const HyperbolicSystem &hyperbolic_system, const std::string &subsection="/Limiter")
Definition limiter.h:55
DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor< 1, problem_dim, T > contract(const FT &flux_ij, const TT &c_ij)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE FT add(const FT &flux_left_ij, const FT &flux_right_ij)