8#include <compile_time_options.h>
17#include <deal.II/base/parameter_acceptor.h>
18#include <deal.II/base/tensor.h>
26 template <
int dim,
typename Number>
27 class HyperbolicSystemView;
46 "Compressible Euler equations (polytropic gas EOS, optimized)";
59 template <
int dim,
typename Number>
72 double reference_density_;
73 double vacuum_state_relaxation_small_;
74 double vacuum_state_relaxation_large_;
76 double gamma_inverse_;
77 double gamma_minus_one_inverse_;
78 double gamma_minus_one_over_gamma_plus_one_;
79 double gamma_plus_one_inverse_;
81 template <
int dim,
typename Number>
103 template <
int dim,
typename Number>
112 : hyperbolic_system_(hyperbolic_system)
119 template <
int dim2,
typename Number2>
137 return hyperbolic_system_.gamma_;
142 return hyperbolic_system_.reference_density_;
148 return hyperbolic_system_.vacuum_state_relaxation_small_;
154 return hyperbolic_system_.vacuum_state_relaxation_large_;
174 return ScalarNumber(hyperbolic_system_.gamma_plus_one_inverse_);
179 return ScalarNumber(hyperbolic_system_.gamma_minus_one_inverse_);
186 hyperbolic_system_.gamma_minus_one_over_gamma_plus_one_);
223 using state_type = dealii::Tensor<1, problem_dimension, Number>;
229 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
241 []() -> std::array<std::string, problem_dimension> {
242 if constexpr (dim == 1)
243 return {
"rho",
"m",
"E"};
244 else if constexpr (dim == 2)
245 return {
"rho",
"m_1",
"m_2",
"E"};
246 else if constexpr (dim == 3)
247 return {
"rho",
"m_1",
"m_2",
"m_3",
"E"};
256 []() -> std::array<std::string, problem_dimension> {
257 if constexpr (dim == 1)
258 return {
"rho",
"v",
"p"};
259 else if constexpr (dim == 2)
260 return {
"rho",
"v_1",
"v_2",
"p"};
261 else if constexpr (dim == 3)
262 return {
"rho",
"v_1",
"v_2",
"v_3",
"p"};
280 std::array<std::string, n_precomputed_values>{
"s",
"eta_h"};
291 std::array<Number, n_initial_precomputed_values>;
297 std::array<std::string, n_initial_precomputed_values>{};
303 StateVector<ScalarNumber, problem_dimension, n_precomputed_values>;
340 template <
typename DISPATCH,
typename SPARSITY>
342 const DISPATCH &dispatch_check,
343 const SPARSITY &sparsity_simd,
346 unsigned int right)
const;
472 template <
int component>
475 const dealii::Tensor<1, dim, Number> &normal)
const;
483 template <
int component>
487 const dealii::Tensor<1, dim, Number> &normal)
const;
507 template <
typename Lambda>
511 const dealii::Tensor<1, dim, Number> &normal,
512 const Lambda &get_dirichlet_data)
const;
554 const unsigned int i,
560 const unsigned int *js,
570 const dealii::Tensor<1, dim, Number> &c_ij)
const;
578 const dealii::Tensor<1, dim, Number> &c_ij)
const =
delete;
590 const unsigned int i,
595 const unsigned int *js,
615 template <
typename ST>
631 template <
typename ST>
651 template <
typename Lambda>
653 const Lambda &lambda)
const;
666 : ParameterAcceptor(subsection)
669 add_parameter(
"gamma", gamma_,
"The ratio of specific heats");
671 reference_density_ = 1.;
672 add_parameter(
"reference density",
674 "Problem specific density reference");
676 vacuum_state_relaxation_small_ = 1.e2;
677 add_parameter(
"vacuum state relaxation small",
678 vacuum_state_relaxation_small_,
679 "Problem specific vacuum relaxation parameter");
681 vacuum_state_relaxation_large_ = 1.e4;
682 add_parameter(
"vacuum state relaxation large",
683 vacuum_state_relaxation_large_,
684 "Problem specific vacuum relaxation parameter");
690 const auto compute_inverses = [
this] {
691 gamma_inverse_ = 1. / gamma_;
692 gamma_plus_one_inverse_ = 1. / (gamma_ + 1.);
693 gamma_minus_one_inverse_ = 1. / (gamma_ - 1.);
694 gamma_minus_one_over_gamma_plus_one_ = (gamma_ - 1.) / (gamma_ + 1.);
698 ParameterAcceptor::parse_parameters_call_back.connect(compute_inverses);
702 template <
int dim,
typename Number>
703 template <
typename DISPATCH,
typename SPARSITY>
704 DEAL_II_ALWAYS_INLINE
inline void
706 unsigned int cycle [[maybe_unused]],
707 const DISPATCH &dispatch_check,
708 const SPARSITY &sparsity_simd,
711 unsigned int right)
const
713 Assert(cycle == 0, dealii::ExcInternalError());
715 const auto &U = std::get<0>(state_vector);
716 auto &precomputed = std::get<1>(state_vector);
720 unsigned int stride_size = get_stride_size<Number>;
723 for (
unsigned int i = left; i < right; i += stride_size) {
726 const unsigned int row_length = sparsity_simd.row_length(i);
732 const auto U_i = U.template get_tensor<Number>(i);
734 harten_entropy(U_i)};
735 precomputed.template write_tensor<Number>(prec_i, i);
740 template <
int dim,
typename Number>
741 DEAL_II_ALWAYS_INLINE
inline Number
748 template <
int dim,
typename Number>
749 DEAL_II_ALWAYS_INLINE
inline Number
751 const Number &rho)
const
753 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
754 const Number rho_cutoff_large =
755 reference_density() * vacuum_state_relaxation_large() * eps;
757 return dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
758 std::abs(rho), rho_cutoff_large, Number(0.), rho);
762 template <
int dim,
typename Number>
763 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
766 dealii::Tensor<1, dim, Number> result;
767 for (
unsigned int i = 0; i < dim; ++i)
768 result[i] = U[1 + i];
773 template <
int dim,
typename Number>
774 DEAL_II_ALWAYS_INLINE
inline Number
781 template <
int dim,
typename Number>
782 DEAL_II_ALWAYS_INLINE
inline Number
788 const Number rho_inverse =
ScalarNumber(1.) / density(U);
789 const auto m = momentum(U);
790 const Number E = total_energy(U);
791 return E -
ScalarNumber(0.5) * m.norm_square() * rho_inverse;
795 template <
int dim,
typename Number>
796 DEAL_II_ALWAYS_INLINE
inline auto
807 const Number rho_inverse =
ScalarNumber(1.) / density(U);
808 const auto u = momentum(U) * rho_inverse;
813 for (
unsigned int i = 0; i < dim; ++i) {
814 result[1 + i] = -u[i];
822 template <
int dim,
typename Number>
823 DEAL_II_ALWAYS_INLINE
inline Number
827 return (gamma() -
ScalarNumber(1.)) * internal_energy(U);
831 template <
int dim,
typename Number>
832 DEAL_II_ALWAYS_INLINE
inline Number
836 const Number rho_inverse =
ScalarNumber(1.) / density(U);
837 const Number p = pressure(U);
838 return std::sqrt(gamma() * p * rho_inverse);
842 template <
int dim,
typename Number>
843 DEAL_II_ALWAYS_INLINE
inline Number
849 return internal_energy(U) *
ryujin::pow(rho_inverse, gamma());
853 template <
int dim,
typename Number>
854 DEAL_II_ALWAYS_INLINE
inline Number
859 const Number rho = density(U);
860 const auto m = momentum(U);
861 const Number E = total_energy(U);
863 const Number rho_rho_e = rho * E -
ScalarNumber(0.5) * m.norm_square();
864 return ryujin::pow(rho_rho_e, gamma_plus_one_inverse());
868 template <
int dim,
typename Number>
869 DEAL_II_ALWAYS_INLINE
inline auto
884 const Number rho = density(U);
885 const auto m = momentum(U);
886 const Number E = total_energy(U);
888 const Number rho_rho_e = rho * E -
ScalarNumber(0.5) * m.norm_square();
891 gamma_plus_one_inverse() *
892 ryujin::pow(rho_rho_e, -gamma() * gamma_plus_one_inverse());
896 result[0] = factor * E;
897 for (
unsigned int i = 0; i < dim; ++i)
898 result[1 + i] = -factor * m[i];
899 result[dim + 1] = factor * rho;
905 template <
int dim,
typename Number>
906 DEAL_II_ALWAYS_INLINE
inline Number
911 const auto p = pressure(U);
916 template <
int dim,
typename Number>
917 DEAL_II_ALWAYS_INLINE
inline auto
933 const Number rho = density(U);
935 const auto u = momentum(U) * rho_inverse;
936 const auto p = pressure(U);
938 const auto factor = (gamma() -
ScalarNumber(1.0)) * gamma_inverse() *
943 result[0] = factor *
ScalarNumber(0.5) * u.norm_square();
944 result[dim + 1] = factor;
945 for (
unsigned int i = 0; i < dim; ++i) {
946 result[1 + i] = -factor * u[i];
953 template <
int dim,
typename Number>
954 DEAL_II_ALWAYS_INLINE
inline bool
957 const auto rho_new = density(U);
958 const auto e_new = internal_energy(U);
959 const auto s_new = specific_entropy(U);
961 constexpr auto gt = dealii::SIMDComparison::greater_than;
964 dealii::compare_and_apply_mask<gt>(rho_new, T(0.), T(0.), T(-1.)) +
965 dealii::compare_and_apply_mask<gt>(e_new, T(0.), T(0.), T(-1.)) +
966 dealii::compare_and_apply_mask<gt>(s_new, T(0.), T(0.), T(-1.));
969 if (!(test == Number(0.))) {
970 std::cout << std::fixed << std::setprecision(16);
971 std::cout <<
"Bounds violation: Negative state [rho, e, s] detected!\n";
972 std::cout <<
"\t\trho: " << rho_new <<
"\n";
973 std::cout <<
"\t\tint: " << e_new <<
"\n";
974 std::cout <<
"\t\tent: " << s_new <<
"\n" << std::endl;
978 return (test == Number(0.));
982 template <
int dim,
typename Number>
983 template <
int component>
984 DEAL_II_ALWAYS_INLINE
inline auto
986 const state_type &U,
const dealii::Tensor<1, dim, Number> &normal)
const
987 -> std::array<state_type, 2>
989 static_assert(component == 1 || component == problem_dimension,
990 "Only first and last eigenvectors implemented");
992 const auto rho = density(U);
993 const auto m = momentum(U);
994 const auto v = m / rho;
995 const auto a = speed_of_sound(U);
996 const auto gamma = this->gamma();
1001 const auto e_k = 0.5 * v.norm_square();
1003 switch (component) {
1005 b[0] = (gamma - 1.) * e_k + a * v * normal;
1006 for (
unsigned int i = 0; i < dim; ++i)
1007 b[1 + i] = (1. - gamma) * v[i] - a * normal[i];
1008 b[dim + 1] = gamma - 1.;
1012 for (
unsigned int i = 0; i < dim; ++i)
1013 c[1 + i] = v[i] - a * normal[i];
1014 c[dim + 1] = a * a / (gamma - 1) + e_k - a * (v * normal);
1018 case problem_dimension:
1019 b[0] = (gamma - 1.) * e_k - a * v * normal;
1020 for (
unsigned int i = 0; i < dim; ++i)
1021 b[1 + i] = (1. - gamma) * v[i] + a * normal[i];
1022 b[dim + 1] = gamma - 1.;
1026 for (
unsigned int i = 0; i < dim; ++i)
1027 c[1 + i] = v[i] + a * normal[i];
1028 c[dim + 1] = a * a / (gamma - 1) + e_k + a * (v * normal);
1033 __builtin_unreachable();
1037 template <
int dim,
typename Number>
1038 template <
int component>
1039 DEAL_II_ALWAYS_INLINE
inline auto
1043 const dealii::Tensor<1, dim, Number> &normal)
const ->
state_type
1045 static_assert(component == 1 || component == 2,
1046 "component has to be 1 or 2");
1048 const auto m = momentum(U);
1049 const auto rho = density(U);
1050 const auto a = speed_of_sound(U);
1051 const auto vn = m * normal / rho;
1053 const auto m_bar = momentum(U_bar);
1054 const auto rho_bar = density(U_bar);
1055 const auto a_bar = speed_of_sound(U_bar);
1056 const auto vn_bar = m_bar * normal / rho_bar;
1060 const auto R_1 = component == 1
1066 const auto R_2 = component == 2
1070 const auto p = pressure(U);
1073 const auto vperp = m / rho - vn * normal;
1075 const auto vn_new = 0.5 * (R_1 + R_2);
1077 auto rho_new = 1. / (gamma() * s) *
1078 ryujin::fixed_power<2>(
ScalarNumber((gamma() - 1.) / 4.) *
1080 rho_new =
ryujin::pow(rho_new, 1. / (gamma() - 1.));
1082 const auto p_new = s *
std::pow(rho_new, gamma());
1086 for (
unsigned int d = 0; d < dim; ++d) {
1087 U_new[1 + d] = rho_new * (vn_new * normal + vperp)[d];
1090 0.5 * rho_new * (vn_new * vn_new + vperp.norm_square());
1096 template <
int dim,
typename Number>
1097 template <
typename Lambda>
1098 DEAL_II_ALWAYS_INLINE
inline auto
1100 dealii::types::boundary_id
id,
1102 const dealii::Tensor<1, dim, Number> &normal,
1103 const Lambda &get_dirichlet_data)
const ->
state_type
1108 result = get_dirichlet_data();
1112 auto m_dirichlet = momentum(get_dirichlet_data());
1113 for (
unsigned int k = 0; k < dim; ++k)
1114 result[k + 1] = m_dirichlet[k];
1117 auto m = momentum(U);
1118 m -= 1. * (m * normal) * normal;
1119 for (
unsigned int k = 0; k < dim; ++k)
1120 result[k + 1] = m[k];
1123 for (
unsigned int k = 0; k < dim; ++k)
1124 result[k + 1] = Number(0.);
1139 const auto m = momentum(U);
1140 const auto rho = density(U);
1141 const auto a = speed_of_sound(U);
1142 const auto vn = m * normal / rho;
1146 result = get_dirichlet_data();
1150 if (vn >= -a && vn <= 0.) {
1151 const auto U_dirichlet = get_dirichlet_data();
1152 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
1156 if (vn > 0. && vn <= a) {
1157 const auto U_dirichlet = get_dirichlet_data();
1158 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
1164 AssertThrow(
false, dealii::ExcNotImplemented());
1171 template <
int dim,
typename Number>
1172 DEAL_II_ALWAYS_INLINE
inline auto
1175 const auto rho_inverse =
ScalarNumber(1.) / density(U);
1176 const auto m = momentum(U);
1177 const auto p = pressure(U);
1178 const auto E = total_energy(U);
1183 for (
unsigned int i = 0; i < dim; ++i) {
1184 result[1 + i] = m * (m[i] * rho_inverse);
1185 result[1 + i][i] += p;
1187 result[dim + 1] = m * (rho_inverse * (E + p));
1193 template <
int dim,
typename Number>
1194 DEAL_II_ALWAYS_INLINE
inline auto
1198 const unsigned int ,
1205 template <
int dim,
typename Number>
1206 DEAL_II_ALWAYS_INLINE
inline auto
1210 const unsigned int * ,
1217 template <
int dim,
typename Number>
1218 DEAL_II_ALWAYS_INLINE
inline auto
1222 const dealii::Tensor<1, dim, Number> &c_ij)
const ->
state_type
1228 template <
int dim,
typename Number>
1229 template <
typename ST>
1233 using T =
typename ST::value_type;
1234 static_assert(std::is_same_v<Number, T>,
"template mismatch");
1236 constexpr auto dim2 = ST::dimension - 2;
1237 static_assert(dim >= dim2,
1238 "the space dimension of the argument state must not be "
1239 "larger than the one of the target state");
1242 result[0] = state[0];
1243 result[dim + 1] = state[dim2 + 1];
1244 for (
unsigned int i = 1; i < dim2 + 1; ++i)
1245 result[i] = state[i];
1251 template <
int dim,
typename Number>
1252 template <
typename ST>
1253 DEAL_II_ALWAYS_INLINE
inline auto
1257 const auto primitive_state = expand_state(initial_state);
1258 return from_primitive_state(primitive_state);
1262 template <
int dim,
typename Number>
1263 DEAL_II_ALWAYS_INLINE
inline auto
1267 const auto &rho = primitive_state[0];
1269 const auto u = momentum(primitive_state);
1270 const auto &p = primitive_state[dim + 1];
1272 auto state = primitive_state;
1274 for (
unsigned int i = 1; i < dim + 1; ++i)
1278 p / (
ScalarNumber(gamma() - 1.)) + Number(0.5) * rho * u * u;
1284 template <
int dim,
typename Number>
1285 DEAL_II_ALWAYS_INLINE
inline auto
1289 const auto &rho = state[0];
1290 const auto rho_inverse = Number(1.) / rho;
1291 const auto p = pressure(state);
1293 auto primitive_state = state;
1295 for (
unsigned int i = 1; i < dim + 1; ++i)
1296 primitive_state[i] *= rho_inverse;
1298 primitive_state[dim + 1] = p;
1300 return primitive_state;
1304 template <
int dim,
typename Number>
1305 template <
typename Lambda>
1309 auto result = state;
1310 const auto M = lambda(momentum(state));
1311 for (
unsigned int d = 0; d < dim; ++d)
1312 result[1 + d] = M[d];
typename get_value_type< Number >::type ScalarNumber
static constexpr unsigned int n_initial_precomputed_values
static constexpr bool have_eos_interpolation_b
state_type from_initial_state(const ST &initial_state) const
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
Number harten_entropy(const state_type &U) const
flux_contribution_type flux_contribution(const PrecomputedVector &pv, const InitialPrecomputedVector &ipv, const unsigned int i, const state_type &U_i) const
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
static const auto initial_precomputed_names
static constexpr bool have_high_order_flux
state_type nodal_source(const PrecomputedVector &pv, const unsigned int *js, const state_type &U_j, const ScalarNumber tau) const =delete
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
void precomputation_loop(unsigned int cycle, const DISPATCH &dispatch_check, const SPARSITY &sparsity_simd, StateVector &state_vector, unsigned int left, unsigned int right) const
static constexpr unsigned int n_precomputed_values
state_type nodal_source(const PrecomputedVector &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
std::array< Number, n_precomputed_values > precomputed_type
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
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)
Number filter_vacuum_density(const Number &rho) const
DEAL_II_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_large() const
Vectors::StateVector< ScalarNumber, problem_dimension, n_precomputed_values > StateVector
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
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_minus_one_over_gamma_plus_one() const
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
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)