8#include <compile_time_options.h>
17#include <deal.II/base/point.h>
18#include <deal.II/base/tensor.h>
27 typename Number = double,
28 typename MemorySpace = dealii::MemorySpace::Host>
29 class WaveSpeedEstimatorView;
40 template <
typename ScalarNumber =
double>
64 typename Number = double,
65 typename MemorySpace = dealii::MemorySpace::Host>
78 const std::string &subsection =
"/WaveSpeedEstimator")
79 : ParameterAcceptor(subsection)
80 , parameters_(
"euler_wave_speed_estimator_parameters",
82 , hyperbolic_system_(&hyperbolic_system)
92 auto ¶meters = *parameters_.view();
94 if constexpr (std::is_same<ScalarNumber, double>::value)
95 parameters.newton_tolerance = 1.e-10;
97 parameters.newton_tolerance = 1.e-4;
98 add_parameter(
"newton tolerance",
99 parameters.newton_tolerance,
100 "Tolerance for the quadratic newton stopping criterion");
102 parameters.newton_max_iterations = 0;
103 add_parameter(
"newton max iterations",
104 parameters.newton_max_iterations,
105 "Maximal number of quadratic newton iterations performed "
114 ParameterAcceptor::parse_parameters_call_back.connect(
115 [
this] { parameters_.view(); });
127 typename MemorySpace = dealii::MemorySpace::Host>
131 hyperbolic_system_->template view<dim, Number, MemorySpace>(),
150 dealii::ObserverPointer<const HyperbolicSystem> hyperbolic_system_;
154 template <
int,
typename,
typename>
167 template <
int dim,
typename Number,
typename MemorySpace>
172 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
173 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
174 "Unexpected memory space");
220 wave_speed_estimator.parameters_.template view<MemorySpace>())
235 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int
238 return parameters_->newton_max_iterations;
246 DEAL_II_HOST_DEVICE Number
257 DEAL_II_HOST_DEVICE Number
261 const unsigned int i,
262 const unsigned int *js,
263 const dealii::Tensor<1, dim, Number> &n_ij)
const;
279 const Number p_star)
const;
288 const Number &p_star)
const;
298 const Number p_in)
const;
308 const Number &p)
const;
325 DEAL_II_HOST_DEVICE Number
345 const primitive_type &primitive_state,
const Number p_star)
const;
358 DEAL_II_HOST_DEVICE std::array<Number, 2>
362 const Number p_2)
const;
374 DEAL_II_HOST_DEVICE Number
377 const Number p_star)
const;
388 DEAL_II_HOST_DEVICE Number
400 DEAL_II_HOST_DEVICE Number
414 const dealii::Tensor<1, dim, Number> &n_ij)
const;
437 template <
int dim,
typename Number,
typename MemorySpace>
438 DEAL_II_HOST_DEVICE Number
490 const auto &[rho_i, u_i, p_i, a_i] = riemann_data_i;
491 const auto &[rho_j, u_j, p_j, a_j] = riemann_data_j;
493#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
494 std::cout <<
"rho_left: " << rho_i << std::endl;
495 std::cout <<
"u_left: " << u_i << std::endl;
496 std::cout <<
"p_left: " << p_i << std::endl;
497 std::cout <<
"a_left: " << a_i << std::endl;
498 std::cout <<
"rho_right: " << rho_j << std::endl;
499 std::cout <<
"u_right: " << u_j << std::endl;
500 std::cout <<
"p_right: " << p_j << std::endl;
501 std::cout <<
"a_right: " << a_j << std::endl;
504 const Number p_max = std::max(p_i, p_j);
506 const Number rarefaction =
507 p_star_two_rarefaction(riemann_data_i, riemann_data_j);
508 const Number failsafe = p_star_failsafe(riemann_data_i, riemann_data_j);
509 const Number p_star_tilde = std::min(rarefaction, failsafe);
511 const Number phi_p_max = phi_of_p_max(riemann_data_i, riemann_data_j);
514 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
518 std::min(p_max, p_star_tilde));
520#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
521 std::cout <<
" p^*_tilde = " << p_2 <<
"\n";
522 std::cout <<
" phi(p_*_t) = "
523 << phi(riemann_data_i, riemann_data_j, p_2) << std::endl;
530 if (newton_max_iterations() == 0) {
531 const auto lambda_max =
532 compute_lambda(riemann_data_i, riemann_data_j, p_2);
534#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
535 std::cout <<
"-> lambda_max = " << lambda_max << std::endl;
546 const Number p_min = std::min(riemann_data_i[2], riemann_data_j[2]);
549 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
550 phi_p_max, Number(0.), p_max, p_min);
553 dealii::SIMDComparison::less_than_or_equal>(p_1, p_2, p_1, p_2);
561 auto [gap, lambda_max] =
562 compute_gap(riemann_data_i, riemann_data_j, p_1, p_2);
564#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
565 std::cout << std::fixed << std::setprecision(16);
566 std::cout <<
"p_1: (start) " << p_1 << std::endl;
567 std::cout <<
"p_2: (start) " << p_2 << std::endl;
568 std::cout <<
"gap: (start) " << gap << std::endl;
569 std::cout <<
"l_m: (start) " << lambda_max << std::endl;
572 for (
unsigned int i = 0; i < newton_max_iterations(); ++i) {
575 const Number tolerance(newton_tolerance());
576 if (std::max(Number(0.), gap - tolerance) == Number(0.)) {
577#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
578 std::cout <<
"converged after " << i <<
" iterations." << std::endl;
584 const Number phi_p_1 = phi(riemann_data_i, riemann_data_j, p_1);
585 const Number phi_p_2 = phi(riemann_data_i, riemann_data_j, p_2);
586 const Number dphi_p_1 = dphi(riemann_data_i, riemann_data_j, p_1);
587 const Number dphi_p_2 = dphi(riemann_data_i, riemann_data_j, p_2);
592 auto [gap_new, lambda_max_new] =
593 compute_gap(riemann_data_i, riemann_data_j, p_1, p_2);
595 lambda_max = lambda_max_new;
597#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
598 std::cout <<
"phi_p_1: " << phi_p_1 << std::endl;
599 std::cout <<
"phi_p_2: " << phi_p_2 << std::endl;
600 std::cout <<
"dphi_p_1: " << dphi_p_1 << std::endl;
601 std::cout <<
"dphi_p_2: " << dphi_p_2 << std::endl;
602 std::cout <<
"p_1: ( " << i <<
" ) " << p_1 << std::endl;
603 std::cout <<
"p_2: ( " << i <<
" ) " << p_2 << std::endl;
604 std::cout <<
"gap: " << gap << std::endl;
605 std::cout <<
"l_m: " << lambda_max << std::endl;
609#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
610 std::cout <<
"-> lambda_max = " << lambda_max << std::endl;
617 template <
int dim,
typename Number,
typename MemorySpace>
618 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
624 const unsigned int * ,
625 const dealii::Tensor<1, dim, Number> &n_ij)
const
627 const auto riemann_data_i = riemann_data_from_state(U_i, n_ij);
628 const auto riemann_data_j = riemann_data_from_state(U_j, n_ij);
630 return compute(riemann_data_i, riemann_data_j);
634 template <
int dim,
typename Number,
typename MemorySpace>
635 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
639 const auto &gamma = view_.gamma();
641 const auto &[rho, u, p, a] = riemann_data;
643 const Number Az =
ScalarNumber(2.) / (rho * (gamma + Number(1.)));
646 const Number radicand = Az / (p_star + Bz);
647 const Number true_value = (p_star - p) * std::sqrt(radicand);
649 const auto exponent =
651 const Number factor =
ryujin::pow(p_star / p, exponent) - Number(1.);
652 const auto false_value =
656 dealii::SIMDComparison::greater_than_or_equal>(
657 p_star, p, true_value, false_value);
661 template <
int dim,
typename Number,
typename MemorySpace>
662 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
667 const auto &gamma = view_.gamma();
668 const auto &gamma_inverse = view_.gamma_inverse();
669 const auto &gamma_minus_one_inverse = view_.gamma_minus_one_inverse();
670 const auto &gamma_plus_one_inverse = view_.gamma_plus_one_inverse();
672 const auto &[rho, u, p, a] = riemann_data;
674 const Number radicand_inverse =
ScalarNumber(0.5) * rho *
677 const Number denominator =
678 (p_star + (gamma -
ScalarNumber(1.)) * gamma_plus_one_inverse * p);
679 const Number true_value =
681 (denominator * std::sqrt(radicand_inverse));
683 const auto exponent =
686 gamma_inverse *
ryujin::pow(p_star / p, exponent) /
688 const auto false_value =
689 factor *
ScalarNumber(2.) * a * gamma_minus_one_inverse;
692 dealii::SIMDComparison::greater_than_or_equal>(
693 p_star, p, true_value, false_value);
697 template <
int dim,
typename Number,
typename MemorySpace>
698 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
702 const Number p_in)
const
704 const Number &u_i = riemann_data_i[1];
705 const Number &u_j = riemann_data_j[1];
707 return f(riemann_data_i, p_in) + f(riemann_data_j, p_in) + u_j - u_i;
711 template <
int dim,
typename Number,
typename MemorySpace>
712 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
716 const Number &p)
const
718 return df(riemann_data_i, p) + df(riemann_data_j, p);
734 template <
int dim,
typename Number,
typename MemorySpace>
735 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
740 const auto &gamma = view_.gamma();
742 const auto &[rho_i, u_i, p_i, a_i] = riemann_data_i;
743 const auto &[rho_j, u_j, p_j, a_j] = riemann_data_j;
745 const Number p_max = std::max(p_i, p_j);
747 const Number radicand_inverse_i =
ScalarNumber(0.5) * rho_i *
751 const Number value_i = (p_max - p_i) / std::sqrt(radicand_inverse_i);
753 const Number radicand_inverse_j =
ScalarNumber(0.5) * rho_j *
757 const Number value_j = (p_max - p_j) / std::sqrt(radicand_inverse_j);
759 return value_i + value_j + u_j - u_i;
775 template <
int dim,
typename Number,
typename MemorySpace>
776 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
780 const auto &gamma = view_.gamma();
781 const auto &gamma_inverse = view_.gamma_inverse();
785 const auto &[rho, u, p, a] = riemann_data;
790 return u - a * std::sqrt(
ScalarNumber(1.0) + factor * tmp);
799 template <
int dim,
typename Number,
typename MemorySpace>
800 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
804 const auto &gamma = view_.gamma();
805 const auto &gamma_inverse = view_.gamma_inverse();
806 const Number factor =
809 const auto &[rho, u, p, a] = primitive_state;
813 return u + a * std::sqrt(Number(1.0) + factor * tmp);
826 template <
int dim,
typename Number,
typename MemorySpace>
827 DEAL_II_HOST_DEVICE_ALWAYS_INLINE std::array<Number, 2>
829 const std::array<Number, 4> &riemann_data_i,
830 const std::array<Number, 4> &riemann_data_j,
832 const Number p_2)
const
834 const Number nu_11 = lambda1_minus(riemann_data_i, p_2 );
835 const Number nu_12 = lambda1_minus(riemann_data_i, p_1 );
837 const Number nu_31 = lambda3_plus(riemann_data_j, p_1);
838 const Number nu_32 = lambda3_plus(riemann_data_j, p_2);
840 const Number lambda_max =
844 std::max(std::abs(nu_32 - nu_31), std::abs(nu_12 - nu_11));
846 return {{gap, lambda_max}};
861 template <
int dim,
typename Number,
typename MemorySpace>
862 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
866 const Number p_star)
const
868 const Number nu_11 = lambda1_minus(riemann_data_i, p_star);
869 const Number nu_32 = lambda3_plus(riemann_data_j, p_star);
883 template <
int dim,
typename Number,
typename MemorySpace>
884 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
889 const auto &gamma = view_.gamma();
890 const auto &gamma_inverse = view_.gamma_inverse();
891 const auto &gamma_minus_one_inverse = view_.gamma_minus_one_inverse();
893 const auto &[rho_i, u_i, p_i, a_i] = riemann_data_i;
894 const auto &[rho_j, u_j, p_j, a_j] = riemann_data_j;
914 const Number numerator =
positive_part(a_i + a_j - factor * (u_j - u_i));
915 const Number denominator =
916 a_i *
ryujin::pow(p_i * inv_p_j, -factor * gamma_inverse) + a_j;
918 const auto exponent =
ScalarNumber(2.0) * gamma * gamma_minus_one_inverse;
920 const auto p_1_tilde =
921 p_j *
ryujin::pow(numerator / denominator, exponent);
923#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
924 std::cout <<
"p_star_two_rarefaction = " << p_1_tilde << std::endl;
938 template <
int dim,
typename Number,
typename MemorySpace>
939 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
944 const auto &gamma = view_.gamma();
946 const auto &[rho_i, u_i, p_i, a_i] = riemann_data_i;
947 const auto &[rho_j, u_j, p_j, a_j] = riemann_data_j;
955 const Number p_max = std::max(p_i, p_j);
959 rho_i * ((gamma + Number(1.)) * p_max + (gamma - Number(1.)) * p_i);
961 const Number x_i = std::sqrt(radicand_i);
965 rho_j * ((gamma + Number(1.)) * p_max + (gamma - Number(1.)) * p_j);
967 const Number x_j = std::sqrt(radicand_j);
969 const Number a = x_i + x_j;
970 const Number b = u_j - u_i;
971 const Number c = -p_i * x_i - p_j * x_j;
973 const Number base = (-b + std::sqrt(b * b -
ScalarNumber(4.) * a * c)) /
975 const Number p_2_tilde = base * base;
977#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
978 std::cout <<
"p_star_failsafe = " << p_2_tilde << std::endl;
984 template <
int dim,
typename Number,
typename MemorySpace>
985 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
987 const state_type &U,
const dealii::Tensor<1, dim, Number> &n_ij)
const
990 const auto rho = view_.density(U);
991 const auto rho_inverse = Number(1.0) / rho;
993 const auto m = view_.momentum(U);
994 const auto proj_m = n_ij * m;
995 const auto perp = m - proj_m * n_ij;
997 const auto E = view_.total_energy(U) -
998 Number(0.5) * perp.norm_square() * rho_inverse;
1004 const auto gamma = view_.gamma();
1005 const auto internal_energy =
1006 E -
ScalarNumber(0.5) * (proj_m * proj_m) * rho_inverse;
1007 const auto p = (gamma -
ScalarNumber(1.)) * internal_energy;
1008 const auto a = std::sqrt(gamma * p * rho_inverse);
1010 return {{rho, proj_m * rho_inverse, p, a}};
Vectors::MultiComponentVectorView< ScalarNumber, n_precomputed_values, dealii::VectorizedArray< ScalarNumber >::size(), MemorySpace, false > PrecomputedVectorView
dealii::Tensor< 1, problem_dimension, Number > state_type
std::array< Number, n_precomputed_values > precomputed_type
static constexpr unsigned int problem_dimension
typename get_value_type< Number >::type ScalarNumber
HyperbolicSystemView< dim, Number, MemorySpace > View
DEAL_II_HOST_DEVICE Number compute_lambda(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_star) const
typename View::PrecomputedVectorView PrecomputedVectorView
std::array< Number, riemann_data_size > primitive_type
DEAL_II_HOST_DEVICE Number compute(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE Number phi(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_in) const
DEAL_II_HOST_DEVICE primitive_type riemann_data_from_state(const state_type &U, const dealii::Tensor< 1, dim, Number > &n_ij) const
typename View::precomputed_type precomputed_type
static constexpr auto problem_dimension
DEAL_II_HOST_DEVICE Number p_star_failsafe(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber newton_tolerance() const
DEAL_II_HOST_DEVICE Number lambda1_minus(const primitive_type &riemann_data, const Number p_star) const
DEAL_II_HOST_DEVICE std::array< Number, 2 > compute_gap(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_1, const Number p_2) const
DEAL_II_HOST_DEVICE Number lambda3_plus(const primitive_type &primitive_state, const Number p_star) const
DEAL_II_HOST_DEVICE Number p_star_two_rarefaction(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
static constexpr unsigned int riemann_data_size
typename View::ScalarNumber ScalarNumber
WaveSpeedEstimatorView(const View &view, const WaveSpeedEstimator< ScalarNumber > &wave_speed_estimator)
DEAL_II_HOST_DEVICE Number dphi(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number &p) const
DEAL_II_HOST_DEVICE Number phi_of_p_max(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE unsigned int newton_max_iterations() const
typename View::state_type state_type
DEAL_II_HOST_DEVICE Number df(const primitive_type &riemann_data, const Number &p_star) const
DEAL_II_HOST_DEVICE Number f(const primitive_type &riemann_data, const Number p_star) const
WaveSpeedEstimator(const HyperbolicSystem &hyperbolic_system, const std::string &subsection="/WaveSpeedEstimator")
@ implicit_transfers_host_resident
DEAL_II_HOST_DEVICE_ALWAYS_INLINE void quadratic_newton_step(Number &p_1, Number &p_2, const Number phi_p_1, const Number phi_p_2, const Number dphi_p_1, const Number dphi_p_2, const Number sign=Number(1.0))
DEAL_II_HOST_DEVICE T pow(const T x, const T b)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number positive_part(const Number number)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number negative_part(const Number number)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number compare_and_apply_mask(const Number &left, const Number &right, const Number &true_value, const Number &false_value)
unsigned int newton_max_iterations