8#include <compile_time_options.h>
16#include <deal.II/base/parameter_acceptor.h>
17#include <deal.II/base/tensor.h>
25 template <
int dim,
typename Number>
26 class HyperbolicSystemView;
45 "Compressible Euler equations (polytropic gas EOS, optimized)";
58 template <
int dim,
typename Number>
71 double reference_density_;
72 double vacuum_state_relaxation_small_;
73 double vacuum_state_relaxation_large_;
75 double gamma_inverse_;
76 double gamma_minus_one_inverse_;
77 double gamma_minus_one_over_gamma_plus_one_;
78 double gamma_plus_one_inverse_;
80 template <
int dim,
typename Number>
102 template <
int dim,
typename Number>
111 : hyperbolic_system_(hyperbolic_system)
118 template <
int dim2,
typename Number2>
136 return hyperbolic_system_.gamma_;
141 return hyperbolic_system_.reference_density_;
147 return hyperbolic_system_.vacuum_state_relaxation_small_;
153 return hyperbolic_system_.vacuum_state_relaxation_large_;
173 return ScalarNumber(hyperbolic_system_.gamma_plus_one_inverse_);
178 return ScalarNumber(hyperbolic_system_.gamma_minus_one_inverse_);
185 hyperbolic_system_.gamma_minus_one_over_gamma_plus_one_);
222 using state_type = dealii::Tensor<1, problem_dimension, Number>;
234 []() -> std::array<std::string, problem_dimension> {
235 if constexpr (dim == 1)
236 return {
"rho",
"m",
"E"};
237 else if constexpr (dim == 2)
238 return {
"rho",
"m_1",
"m_2",
"E"};
239 else if constexpr (dim == 3)
240 return {
"rho",
"m_1",
"m_2",
"m_3",
"E"};
249 []() -> std::array<std::string, problem_dimension> {
250 if constexpr (dim == 1)
251 return {
"rho",
"v",
"p"};
252 else if constexpr (dim == 2)
253 return {
"rho",
"v_1",
"v_2",
"p"};
254 else if constexpr (dim == 3)
255 return {
"rho",
"v_1",
"v_2",
"v_3",
"p"};
263 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
285 std::array<Number, n_precomputed_initial_values>;
298 std::array<std::string, n_precomputed_initial_values>{};
320 std::array<std::string, n_precomputed_values>{
"s",
"eta_h"};
331 template <
typename DISPATCH,
typename SPARSITY>
333 const DISPATCH &dispatch_check,
335 const SPARSITY &sparsity_simd,
338 unsigned int right)
const;
464 template <
int component>
467 const dealii::Tensor<1, dim, Number> &normal)
const;
475 template <
int component>
479 const dealii::Tensor<1, dim, Number> &normal)
const;
499 template <
typename Lambda>
503 const dealii::Tensor<1, dim, Number> &normal,
504 const Lambda &get_dirichlet_data)
const;
546 const unsigned int i,
552 const unsigned int *js,
562 const dealii::Tensor<1, dim, Number> &c_ij)
const;
570 const dealii::Tensor<1, dim, Number> &c_ij)
const =
delete;
582 const unsigned int i,
587 const unsigned int *js,
607 template <
typename ST>
623 template <
typename ST>
643 template <
typename Lambda>
645 const Lambda &lambda)
const;
658 : ParameterAcceptor(subsection)
661 add_parameter(
"gamma", gamma_,
"The ratio of specific heats");
663 reference_density_ = 1.;
664 add_parameter(
"reference density",
666 "Problem specific density reference");
668 vacuum_state_relaxation_small_ = 1.e2;
669 add_parameter(
"vacuum state relaxation small",
670 vacuum_state_relaxation_small_,
671 "Problem specific vacuum relaxation parameter");
673 vacuum_state_relaxation_large_ = 1.e4;
674 add_parameter(
"vacuum state relaxation large",
675 vacuum_state_relaxation_large_,
676 "Problem specific vacuum relaxation parameter");
682 const auto compute_inverses = [
this] {
683 gamma_inverse_ = 1. / gamma_;
684 gamma_plus_one_inverse_ = 1. / (gamma_ + 1.);
685 gamma_minus_one_inverse_ = 1. / (gamma_ - 1.);
686 gamma_minus_one_over_gamma_plus_one_ = (gamma_ - 1.) / (gamma_ + 1.);
690 ParameterAcceptor::parse_parameters_call_back.connect(compute_inverses);
694 template <
int dim,
typename Number>
695 template <
typename DISPATCH,
typename SPARSITY>
696 DEAL_II_ALWAYS_INLINE
inline void
698 unsigned int cycle [[maybe_unused]],
699 const DISPATCH &dispatch_check,
701 const SPARSITY &sparsity_simd,
704 unsigned int right)
const
706 Assert(cycle == 0, dealii::ExcInternalError());
710 unsigned int stride_size = get_stride_size<Number>;
713 for (
unsigned int i = left; i < right; i += stride_size) {
716 const unsigned int row_length = sparsity_simd.row_length(i);
722 const auto U_i = U.template get_tensor<Number>(i);
724 harten_entropy(U_i)};
725 precomputed_values.template write_tensor<Number>(prec_i, i);
730 template <
int dim,
typename Number>
731 DEAL_II_ALWAYS_INLINE
inline Number
738 template <
int dim,
typename Number>
739 DEAL_II_ALWAYS_INLINE
inline Number
741 const Number &rho)
const
743 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
744 const Number rho_cutoff_large =
745 reference_density() * vacuum_state_relaxation_large() * eps;
747 return dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
748 std::abs(rho), rho_cutoff_large, Number(0.), rho);
752 template <
int dim,
typename Number>
753 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
756 dealii::Tensor<1, dim, Number> result;
757 for (
unsigned int i = 0; i < dim; ++i)
758 result[i] = U[1 + i];
763 template <
int dim,
typename Number>
764 DEAL_II_ALWAYS_INLINE
inline Number
771 template <
int dim,
typename Number>
772 DEAL_II_ALWAYS_INLINE
inline Number
778 const Number rho_inverse =
ScalarNumber(1.) / density(U);
779 const auto m = momentum(U);
780 const Number E = total_energy(U);
781 return E -
ScalarNumber(0.5) * m.norm_square() * rho_inverse;
785 template <
int dim,
typename Number>
786 DEAL_II_ALWAYS_INLINE
inline auto
797 const Number rho_inverse =
ScalarNumber(1.) / density(U);
798 const auto u = momentum(U) * rho_inverse;
803 for (
unsigned int i = 0; i < dim; ++i) {
804 result[1 + i] = -u[i];
812 template <
int dim,
typename Number>
813 DEAL_II_ALWAYS_INLINE
inline Number
817 return (gamma() -
ScalarNumber(1.)) * internal_energy(U);
821 template <
int dim,
typename Number>
822 DEAL_II_ALWAYS_INLINE
inline Number
826 const Number rho_inverse =
ScalarNumber(1.) / density(U);
827 const Number p = pressure(U);
828 return std::sqrt(gamma() * p * rho_inverse);
832 template <
int dim,
typename Number>
833 DEAL_II_ALWAYS_INLINE
inline Number
839 return internal_energy(U) *
ryujin::pow(rho_inverse, gamma());
843 template <
int dim,
typename Number>
844 DEAL_II_ALWAYS_INLINE
inline Number
849 const Number rho = density(U);
850 const auto m = momentum(U);
851 const Number E = total_energy(U);
853 const Number rho_rho_e = rho * E -
ScalarNumber(0.5) * m.norm_square();
854 return ryujin::pow(rho_rho_e, gamma_plus_one_inverse());
858 template <
int dim,
typename Number>
859 DEAL_II_ALWAYS_INLINE
inline auto
874 const Number rho = density(U);
875 const auto m = momentum(U);
876 const Number E = total_energy(U);
878 const Number rho_rho_e = rho * E -
ScalarNumber(0.5) * m.norm_square();
881 gamma_plus_one_inverse() *
882 ryujin::pow(rho_rho_e, -gamma() * gamma_plus_one_inverse());
886 result[0] = factor * E;
887 for (
unsigned int i = 0; i < dim; ++i)
888 result[1 + i] = -factor * m[i];
889 result[dim + 1] = factor * rho;
895 template <
int dim,
typename Number>
896 DEAL_II_ALWAYS_INLINE
inline Number
901 const auto p = pressure(U);
906 template <
int dim,
typename Number>
907 DEAL_II_ALWAYS_INLINE
inline auto
923 const Number rho = density(U);
925 const auto u = momentum(U) * rho_inverse;
926 const auto p = pressure(U);
928 const auto factor = (gamma() -
ScalarNumber(1.0)) * gamma_inverse() *
933 result[0] = factor *
ScalarNumber(0.5) * u.norm_square();
934 result[dim + 1] = factor;
935 for (
unsigned int i = 0; i < dim; ++i) {
936 result[1 + i] = -factor * u[i];
943 template <
int dim,
typename Number>
944 DEAL_II_ALWAYS_INLINE
inline bool
947 const auto rho_new = density(U);
948 const auto e_new = internal_energy(U);
949 const auto s_new = specific_entropy(U);
951 constexpr auto gt = dealii::SIMDComparison::greater_than;
954 dealii::compare_and_apply_mask<gt>(rho_new, T(0.), T(0.), T(-1.)) +
955 dealii::compare_and_apply_mask<gt>(e_new, T(0.), T(0.), T(-1.)) +
956 dealii::compare_and_apply_mask<gt>(s_new, T(0.), T(0.), T(-1.));
959 if (!(test == Number(0.))) {
960 std::cout << std::fixed << std::setprecision(16);
961 std::cout <<
"Bounds violation: Negative state [rho, e, s] detected!\n";
962 std::cout <<
"\t\trho: " << rho_new <<
"\n";
963 std::cout <<
"\t\tint: " << e_new <<
"\n";
964 std::cout <<
"\t\tent: " << s_new <<
"\n" << std::endl;
968 return (test == Number(0.));
972 template <
int dim,
typename Number>
973 template <
int component>
974 DEAL_II_ALWAYS_INLINE
inline auto
976 const state_type &U,
const dealii::Tensor<1, dim, Number> &normal)
const
977 -> std::array<state_type, 2>
979 static_assert(component == 1 || component == problem_dimension,
980 "Only first and last eigenvectors implemented");
982 const auto rho = density(U);
983 const auto m = momentum(U);
984 const auto v = m / rho;
985 const auto a = speed_of_sound(U);
986 const auto gamma = this->gamma();
991 const auto e_k = 0.5 * v.norm_square();
995 b[0] = (gamma - 1.) * e_k + a * v * normal;
996 for (
unsigned int i = 0; i < dim; ++i)
997 b[1 + i] = (1. - gamma) * v[i] - a * normal[i];
998 b[dim + 1] = gamma - 1.;
1002 for (
unsigned int i = 0; i < dim; ++i)
1003 c[1 + i] = v[i] - a * normal[i];
1004 c[dim + 1] = a * a / (gamma - 1) + e_k - a * (v * normal);
1008 case problem_dimension:
1009 b[0] = (gamma - 1.) * e_k - a * v * normal;
1010 for (
unsigned int i = 0; i < dim; ++i)
1011 b[1 + i] = (1. - gamma) * v[i] + a * normal[i];
1012 b[dim + 1] = gamma - 1.;
1016 for (
unsigned int i = 0; i < dim; ++i)
1017 c[1 + i] = v[i] + a * normal[i];
1018 c[dim + 1] = a * a / (gamma - 1) + e_k + a * (v * normal);
1023 __builtin_unreachable();
1027 template <
int dim,
typename Number>
1028 template <
int component>
1029 DEAL_II_ALWAYS_INLINE
inline auto
1033 const dealii::Tensor<1, dim, Number> &normal)
const ->
state_type
1035 static_assert(component == 1 || component == 2,
1036 "component has to be 1 or 2");
1038 const auto m = momentum(U);
1039 const auto rho = density(U);
1040 const auto a = speed_of_sound(U);
1041 const auto vn = m * normal / rho;
1043 const auto m_bar = momentum(U_bar);
1044 const auto rho_bar = density(U_bar);
1045 const auto a_bar = speed_of_sound(U_bar);
1046 const auto vn_bar = m_bar * normal / rho_bar;
1050 const auto R_1 = component == 1
1056 const auto R_2 = component == 2
1060 const auto p = pressure(U);
1063 const auto vperp = m / rho - vn * normal;
1065 const auto vn_new = 0.5 * (R_1 + R_2);
1067 auto rho_new = 1. / (gamma() * s) *
1068 ryujin::fixed_power<2>(
ScalarNumber((gamma() - 1.) / 4.) *
1070 rho_new =
ryujin::pow(rho_new, 1. / (gamma() - 1.));
1072 const auto p_new = s *
std::pow(rho_new, gamma());
1076 for (
unsigned int d = 0; d < dim; ++d) {
1077 U_new[1 + d] = rho_new * (vn_new * normal + vperp)[d];
1080 0.5 * rho_new * (vn_new * vn_new + vperp.norm_square());
1086 template <
int dim,
typename Number>
1087 template <
typename Lambda>
1088 DEAL_II_ALWAYS_INLINE
inline auto
1090 dealii::types::boundary_id
id,
1092 const dealii::Tensor<1, dim, Number> &normal,
1093 const Lambda &get_dirichlet_data)
const ->
state_type
1098 result = get_dirichlet_data();
1101 auto m = momentum(U);
1102 m -= 1. * (m * normal) * normal;
1103 for (
unsigned int k = 0; k < dim; ++k)
1104 result[k + 1] = m[k];
1107 for (
unsigned int k = 0; k < dim; ++k)
1108 result[k + 1] = Number(0.);
1123 const auto m = momentum(U);
1124 const auto rho = density(U);
1125 const auto a = speed_of_sound(U);
1126 const auto vn = m * normal / rho;
1130 result = get_dirichlet_data();
1134 if (vn >= -a && vn <= 0.) {
1135 const auto U_dirichlet = get_dirichlet_data();
1136 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
1140 if (vn > 0. && vn <= a) {
1141 const auto U_dirichlet = get_dirichlet_data();
1142 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
1152 template <
int dim,
typename Number>
1153 DEAL_II_ALWAYS_INLINE
inline auto
1156 const auto rho_inverse =
ScalarNumber(1.) / density(U);
1157 const auto m = momentum(U);
1158 const auto p = pressure(U);
1159 const auto E = total_energy(U);
1164 for (
unsigned int i = 0; i < dim; ++i) {
1165 result[1 + i] = m * (m[i] * rho_inverse);
1166 result[1 + i][i] += p;
1168 result[dim + 1] = m * (rho_inverse * (E + p));
1174 template <
int dim,
typename Number>
1175 DEAL_II_ALWAYS_INLINE
inline auto
1179 const unsigned int ,
1186 template <
int dim,
typename Number>
1187 DEAL_II_ALWAYS_INLINE
inline auto
1191 const unsigned int * ,
1198 template <
int dim,
typename Number>
1199 DEAL_II_ALWAYS_INLINE
inline auto
1203 const dealii::Tensor<1, dim, Number> &c_ij)
const ->
state_type
1209 template <
int dim,
typename Number>
1210 template <
typename ST>
1214 using T =
typename ST::value_type;
1215 static_assert(std::is_same_v<Number, T>,
"template mismatch");
1217 constexpr auto dim2 = ST::dimension - 2;
1218 static_assert(dim >= dim2,
1219 "the space dimension of the argument state must not be "
1220 "larger than the one of the target state");
1223 result[0] = state[0];
1224 result[dim + 1] = state[dim2 + 1];
1225 for (
unsigned int i = 1; i < dim2 + 1; ++i)
1226 result[i] = state[i];
1232 template <
int dim,
typename Number>
1233 template <
typename ST>
1234 DEAL_II_ALWAYS_INLINE
inline auto
1238 const auto primitive_state = expand_state(initial_state);
1239 return from_primitive_state(primitive_state);
1243 template <
int dim,
typename Number>
1244 DEAL_II_ALWAYS_INLINE
inline auto
1248 const auto &rho = primitive_state[0];
1250 const auto u = momentum(primitive_state);
1251 const auto &p = primitive_state[dim + 1];
1253 auto state = primitive_state;
1255 for (
unsigned int i = 1; i < dim + 1; ++i)
1259 p / (
ScalarNumber(gamma() - 1.)) + Number(0.5) * rho * u * u;
1265 template <
int dim,
typename Number>
1266 DEAL_II_ALWAYS_INLINE
inline auto
1270 const auto &rho = state[0];
1271 const auto rho_inverse = Number(1.) / rho;
1272 const auto p = pressure(state);
1274 auto primitive_state = state;
1276 for (
unsigned int i = 1; i < dim + 1; ++i)
1277 primitive_state[i] *= rho_inverse;
1279 primitive_state[dim + 1] = p;
1281 return primitive_state;
1285 template <
int dim,
typename Number>
1286 template <
typename Lambda>
1290 auto result = state;
1291 const auto M = lambda(momentum(state));
1292 for (
unsigned int d = 0; d < dim; ++d)
1293 result[1 + d] = M[d];
typename get_value_type< Number >::type ScalarNumber
static constexpr bool have_eos_interpolation_b
state_type from_initial_state(const ST &initial_state) const
std::array< Number, n_precomputed_initial_values > precomputed_initial_state_type
static Number internal_energy(const state_type &U)
state_type from_primitive_state(const state_type &primitive_state) const
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
static constexpr unsigned int n_precomputed_initial_values
Number harten_entropy(const state_type &U) const
std::array< Number, n_precomputed_values > precomputed_state_type
static const auto primitive_component_names
state_type high_order_flux_divergence(const flux_contribution_type &flux_i, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &c_ij) const =delete
DEAL_II_ALWAYS_INLINE ScalarNumber reference_density() const
state_type harten_entropy_derivative(const state_type &U) const
static constexpr unsigned int n_precomputation_cycles
flux_contribution_type flux_contribution(const precomputed_vector_type &pv, const precomputed_initial_vector_type &piv, const unsigned int i, const state_type &U_i) const
static constexpr bool have_high_order_flux
static const auto precomputed_names
state_type expand_state(const ST &state) const
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
static constexpr unsigned int problem_dimension
dealii::Tensor< 1, problem_dimension, Number > state_type
flux_type f(const state_type &U) const
static constexpr unsigned int n_precomputed_values
state_type prescribe_riemann_characteristic(const state_type &U, const state_type &U_bar, const dealii::Tensor< 1, dim, Number > &normal) const
Number pressure(const state_type &U) const
state_type apply_galilei_transform(const state_type &state, const Lambda &lambda) const
Number mathematical_entropy(const state_type &U) const
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_inverse() const
DEAL_II_ALWAYS_INLINE ScalarNumber gamma() const
static Number total_energy(const state_type &U)
DEAL_II_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_small() const
static const auto component_names
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_minus_one_inverse() const
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_plus_one_inverse() const
static Number density(const state_type &U)
state_type nodal_source(const precomputed_vector_type &pv, const unsigned int *js, const state_type &U_j, const ScalarNumber tau) const =delete
Number filter_vacuum_density(const Number &rho) const
DEAL_II_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_large() const
static state_type internal_energy_derivative(const state_type &U)
static constexpr bool have_source_terms
state_type flux_divergence(const flux_contribution_type &flux_i, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &c_ij) const
std::array< state_type, 2 > linearized_eigenvector(const state_type &U, const dealii::Tensor< 1, dim, Number > &normal) const
state_type nodal_source(const precomputed_vector_type &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_minus_one_over_gamma_plus_one() const
static const auto precomputed_initial_names
flux_type flux_contribution_type
state_type mathematical_entropy_derivative(const state_type &U) const
static constexpr bool have_gamma
state_type apply_boundary_conditions(const dealii::types::boundary_id id, const state_type &U, const dealii::Tensor< 1, dim, Number > &normal, const Lambda &get_dirichlet_data) const
state_type to_primitive_state(const state_type &state) const
void precomputation_loop(unsigned int cycle, const DISPATCH &dispatch_check, precomputed_vector_type &precomputed_values, const SPARSITY &sparsity_simd, const vector_type &U, unsigned int left, unsigned int right) const
static dealii::Tensor< 1, dim, Number > momentum(const state_type &U)
Number speed_of_sound(const state_type &U) const
bool is_admissible(const state_type &U) const
Number specific_entropy(const state_type &U) const
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
static const std::string problem_name
T pow(const T x, const T b)
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)