8#include <ryujin/base/compile_time_options.h>
20#include <deal.II/base/memory_space.h>
21#include <deal.II/base/parameter_acceptor.h>
22#include <deal.II/base/tensor.h>
31 namespace EulerBarotropic
35 typename MemorySpace = dealii::MemorySpace::Host>
36 class HyperbolicSystemView;
75 typename Number = double,
76 typename MemorySpace = dealii::MemorySpace::Host>
88 typename MemorySpace = dealii::MemorySpace::Host>
107 template <
typename MemorySpace = dealii::MemorySpace::Host,
109 typename ScalarNumber>
113 const bool skip_constrained_dofs =
true)
const;
125 void update_parameters();
129 std::string barotropic_equation_of_state_;
131 std::vector<std::unique_ptr<BarotropicEquationOfState>>
132 barotropic_equation_of_state_list_;
137 template <
int,
typename,
typename>
165 template <
int dim,
typename Number,
typename MemorySpace>
170 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
171 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
172 "Unexpected memory space");
192 using state_type = dealii::Tensor<1, problem_dimension, Number>;
198 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
224 std::array<Number, n_initial_precomputed_values>;
226 template <
int n_comp>
255 hyperbolic_system.parameters_.template view<MemorySpace>())
256 , barotropic_equation_of_state_(
257 hyperbolic_system.selected_barotropic_equation_of_state_)
272 DEAL_II_ALWAYS_INLINE
inline const std::string &
275 return barotropic_equation_of_state_->name();
310 DEAL_II_ALWAYS_INLINE
inline Number
313 const auto &beos = barotropic_equation_of_state_;
315 if constexpr (std::is_same_v<ScalarNumber, Number>) {
316 return ScalarNumber(beos->specific_internal_energy(rho));
319 for (
unsigned int k = 0; k < Number::size(); ++k) {
320 e[k] =
ScalarNumber(beos->specific_internal_energy(rho[k]));
331 const auto &beos = barotropic_equation_of_state_;
333 if constexpr (std::is_same_v<ScalarNumber, Number>) {
337 for (
unsigned int k = 0; k < Number::size(); ++k) {
348 DEAL_II_ALWAYS_INLINE
inline Number
351 const auto &beos = barotropic_equation_of_state_;
353 if constexpr (std::is_same_v<ScalarNumber, Number>) {
357 for (
unsigned int k = 0; k < Number::size(); ++k) {
398 static DEAL_II_HOST_DEVICE dealii::Tensor<1, dim, Number>
409 const state_type &U,
const Number &specific_internal_energy)
const;
418 const Number &specific_internal_energy,
419 const Number &pressure)
const;
443 template <
int component>
449 const dealii::Tensor<1, dim, Number> &normal)
const;
473 template <
typename Lambda>
477 const dealii::Tensor<1, dim, Number> &normal,
478 const Lambda &get_dirichlet_data)
const;
496 const Number &p)
const;
521 const unsigned int i,
528 const unsigned int *js,
539 const dealii::Tensor<1, dim, Number> &c_ij)
const;
550 const dealii::Tensor<1, dim, Number> &c_ij)
const =
delete;
563 const unsigned int i,
569 const unsigned int *js,
589 template <
typename ST>
604 template <
typename ST>
626 template <
typename Lambda>
655 "Compressible Euler equations "
656 "(barotropic EOS, optimized barotropic)",
658 {
"rho",
"m_1",
"m_2"},
659 {
"rho",
"m_1",
"m_2",
"m_3"}}},
661 {
"rho",
"v_1",
"v_2"},
662 {
"rho",
"v_1",
"v_2",
"v_3"}}},
663 {{{
"e",
"p",
"a"}, {
"e",
"p",
"a"}, {
"e",
"p",
"a"}}},
666 , parameters_(
"euler_barotropic_hyperbolic_system_parameters",
670 auto ¶meters = *parameters_.view();
672 barotropic_equation_of_state_list_ =
675 barotropic_equation_of_state_ =
"isothermal";
676 add_parameter(
"barotropic equation of state",
677 barotropic_equation_of_state_,
678 "The barotropic equation of state. Valid names are given "
679 "by any of the subsections defined below",
682 barotropic_equation_of_state_list_));
684 parameters.reference_density = 1.;
685 add_parameter(
"reference density",
686 parameters.reference_density,
687 "Problem specific density reference");
689 parameters.vacuum_state_relaxation_small = 1.e2;
690 add_parameter(
"vacuum state relaxation small",
691 parameters.vacuum_state_relaxation_small,
692 "Problem specific vacuum relaxation parameter");
694 parameters.vacuum_state_relaxation_large = 1.e4;
695 add_parameter(
"vacuum state relaxation large",
696 parameters.vacuum_state_relaxation_large,
697 "Problem specific vacuum relaxation parameter");
699 ParameterAcceptor::parse_parameters_call_back.connect(
700 [
this] { update_parameters(); });
706 inline void HyperbolicSystem::update_parameters()
708 selected_barotropic_equation_of_state_ =
710 barotropic_equation_of_state_list_,
711 barotropic_equation_of_state_);
713 selected_barotropic_equation_of_state_->name() +
714 " EOS, optimized barotropic)";
721 template <
typename MemorySpace,
int dim,
typename ScalarNumber>
725 const bool skip_constrained_dofs)
const
727 using HostSpace = dealii::MemorySpace::Host;
729 const unsigned int n_internal = offline_data.n_locally_internal();
730 const unsigned int n_owned = offline_data.n_locally_owned();
734 auto &U = state_vector.
state;
745 constexpr bool transfer =
747 !std::is_same_v<MemorySpace, dealii::MemorySpace::Host>;
749 [[maybe_unused]]
const bool host_resident =
750 U.template is_resident<HostSpace>();
752 if constexpr (transfer) {
753 U.template copy_to_memory_space<HostSpace>();
754 precomputed.template move_to_memory_space<HostSpace>();
758 const auto sparsity_simd_view =
759 offline_data.sparsity_pattern_simd().template view<HostSpace>();
764 .template view<ScalarView::problem_dimension, HostSpace>();
765 const auto precomputed_view =
767 .template view<ScalarView::n_precomputed_values, HostSpace>();
769 const auto hyperbolic_system_views =
770 make_select_view<dim, ScalarNumber, HostSpace>(*
this);
772 const auto body = [=](
auto sentinel,
unsigned int i) {
773 using T =
decltype(sentinel);
777 const unsigned int row_length = sparsity_simd_view.row_length(i);
778 if (skip_constrained_dofs && row_length == 1)
781 const auto view = hyperbolic_system_views.template view<T>();
783 const auto U_i = U_view.template read_tensor<T>(i);
784 const auto rho_i =
view.density(U_i);
787 const auto e_i =
view.beos_specific_internal_energy(rho_i);
788 const auto p_i =
view.beos_pressure(rho_i);
789 const auto a_i =
view.beos_speed_of_sound(rho_i);
791 const precomputed_type prec_i{e_i, p_i, a_i};
792 precomputed_view.template write_tensor<T>(prec_i, i);
795 loop<HostSpace, ScalarNumber>(
796 "hyperbolic_kernel_01b", body, 0, n_internal, n_owned);
799 if constexpr (transfer) {
802 U.template move_to_memory_space<MemorySpace>();
803 precomputed.template move_to_memory_space<MemorySpace>();
808 template <
int dim,
typename Number,
typename MemorySpace>
809 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
816 template <
int dim,
typename Number,
typename MemorySpace>
817 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
819 const Number &rho)
const
821 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
822 const Number rho_cutoff_large =
823 reference_density() * vacuum_state_relaxation_large() * eps;
825 return ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
826 std::abs(rho), rho_cutoff_large, Number(0.), rho);
830 template <
int dim,
typename Number,
typename MemorySpace>
831 DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
835 dealii::Tensor<1, dim, Number> result;
836 for (
unsigned int i = 0; i < dim; ++i)
837 result[i] = U[1 + i];
842 template <
int dim,
typename Number,
typename MemorySpace>
843 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
845 const state_type &U,
const Number &specific_internal_energy)
const
847 const auto rho = density(U);
849 const auto m = momentum(U);
851 return rho * specific_internal_energy +
856 template <
int dim,
typename Number,
typename MemorySpace>
857 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
860 const Number &specific_internal_energy,
863 const auto rho = density(U);
865 const auto m = momentum(U);
870 specific_internal_energy + rho_inverse * pressure -
871 ScalarNumber(0.5) * rho_inverse * rho_inverse * m.norm_square();
872 for (
unsigned int i = 0; i < dim; ++i)
873 result[1 + i] = rho_inverse * m[i];
879 template <
int dim,
typename Number,
typename MemorySpace>
880 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
bool
884 const auto rho = density(U);
885 constexpr auto gt = dealii::SIMDComparison::greater_than;
888 ryujin::compare_and_apply_mask<gt>(rho, T(0.), T(0.), T(-1.));
891 if (!(test == Number(0.))) {
892 std::cout << std::fixed << std::setprecision(16);
893 std::cout <<
"Bounds violation: Negative state [rho, e] detected!\n";
894 std::cout <<
"\t\trho: " << rho <<
"\n";
898 return (test == Number(0.));
902 template <
int dim,
typename Number,
typename MemorySpace>
903 template <
int component>
904 DEAL_II_ALWAYS_INLINE
inline auto
911 const dealii::Tensor<1, dim, Number> & )
const
915 AssertThrow(
false, dealii::ExcNotImplemented());
921 template <
int dim,
typename Number,
typename MemorySpace>
922 template <
typename Lambda>
923 DEAL_II_ALWAYS_INLINE
inline auto
925 dealii::types::boundary_id
id,
927 const dealii::Tensor<1, dim, Number> &normal,
928 const Lambda &get_dirichlet_data)
const ->
state_type
933 result = get_dirichlet_data();
937 auto m_dirichlet = momentum(get_dirichlet_data());
938 for (
unsigned int k = 0; k < dim; ++k)
939 result[k + 1] = m_dirichlet[k];
943 const auto U_dirichlet = get_dirichlet_data();
944 const auto rho_dirichlet = density(U_dirichlet);
945 const auto v_dirichlet = momentum(U_dirichlet) / rho_dirichlet;
946 const auto rho = density(result);
947 for (
unsigned int k = 0; k < dim; ++k)
948 result[k + 1] = rho * v_dirichlet[k];
951 auto m = momentum(U);
952 m -= 1. * (m * normal) * normal;
953 for (
unsigned int k = 0; k < dim; ++k)
954 result[k + 1] = m[k];
957 for (
unsigned int k = 0; k < dim; ++k)
958 result[k + 1] = Number(0.);
973 const auto m = momentum(U);
974 const auto rho = density(U);
980 const auto p = beos_pressure(rho);
981 const auto a = beos_speed_of_sound(rho);
982 const auto vn = m * normal / rho;
986 result = get_dirichlet_data();
990 if (vn >= -a && vn <= 0.) {
991 const auto U_dirichlet = get_dirichlet_data();
992 const auto rho_dirichlet = density(U_dirichlet);
993 const auto p_dirichlet = beos_pressure(rho_dirichlet);
995 result = prescribe_riemann_characteristic<2>(
996 U_dirichlet, p_dirichlet, U, p, normal);
1000 if (vn > 0. && vn <= a) {
1001 const auto U_dirichlet = get_dirichlet_data();
1002 const auto rho_dirichlet = density(U_dirichlet);
1003 const auto p_dirichlet = beos_pressure(rho_dirichlet);
1005 result = prescribe_riemann_characteristic<1>(
1006 U, p, U_dirichlet, p_dirichlet, normal);
1011 AssertThrow(
false, dealii::ExcNotImplemented());
1018 template <
int dim,
typename Number,
typename MemorySpace>
1019 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1021 const Number &p)
const
1024 const auto rho_inverse =
ScalarNumber(1.) / density(U);
1025 const auto m = momentum(U);
1030 for (
unsigned int i = 0; i < dim; ++i) {
1031 result[1 + i] = m * (m[i] * rho_inverse);
1032 result[1 + i][i] += p;
1039 template <
int dim,
typename Number,
typename MemorySpace>
1040 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1044 const unsigned int i,
1047 const auto &[e_i, p_i, a_i] =
1048 pv.template read_tensor<Number, precomputed_type>(i);
1053 template <
int dim,
typename Number,
typename MemorySpace>
1054 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1058 const unsigned int *js,
1061 const auto &[e_j, p_j, a_j] =
1062 pv.template read_tensor<Number, precomputed_type>(js);
1067 template <
int dim,
typename Number,
typename MemorySpace>
1068 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1072 const dealii::Tensor<1, dim, Number> &c_ij)
const ->
state_type
1078 template <
int dim,
typename Number,
typename MemorySpace>
1079 template <
typename ST>
1080 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1084 using T =
typename ST::value_type;
1085 static_assert(std::is_same_v<Number, T>,
"template mismatch");
1087 constexpr auto dim2 = ST::dimension - 1;
1088 static_assert(dim >= dim2,
1089 "the space dimension of the argument state must not be "
1090 "larger than the one of the target state");
1093 result[0] =
state[0];
1094 for (
unsigned int i = 1; i < dim2 + 1; ++i)
1095 result[i] =
state[i];
1101 template <
int dim,
typename Number,
typename MemorySpace>
1102 template <
typename ST>
1103 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1107 const auto primitive_state = expand_state(initial_state);
1108 return from_primitive_state(primitive_state);
1112 template <
int dim,
typename Number,
typename MemorySpace>
1113 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1117 const auto rho = density(primitive_state);
1119 auto state = primitive_state;
1121 for (
unsigned int i = 1; i < dim + 1; ++i)
1128 template <
int dim,
typename Number,
typename MemorySpace>
1129 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1133 const auto rho = density(
state);
1134 const auto rho_inverse = Number(1.) / rho;
1136 auto primitive_state =
state;
1138 for (
unsigned int i = 1; i < dim + 1; ++i)
1139 primitive_state[i] *= rho_inverse;
1141 return primitive_state;
1145 template <
int dim,
typename Number,
typename MemorySpace>
1146 template <
typename Lambda>
1147 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
1151 auto result =
state;
1152 const auto M = lambda(momentum(
state));
1153 for (
unsigned int d = 0; d < dim; ++d)
1154 result[1 + d] = M[d];
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
DEAL_II_HOST_DEVICE bool is_admissible(const state_type &U) const
DEAL_II_HOST_DEVICE Number total_energy(const state_type &U, const Number &specific_internal_energy) const
DEAL_II_HOST_DEVICE flux_contribution_type flux_contribution(const PrecomputedVectorView &pv, const InitialPrecomputedVectorView &piv, const unsigned int i, const state_type &U_i) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_small() const
static constexpr bool have_covolume_constant
DEAL_II_HOST_DEVICE state_type nodal_source(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
static constexpr unsigned int problem_dimension
state_type prescribe_riemann_characteristic(const state_type &U, const Number &p, const state_type &U_bar, const Number &p_bar, const dealii::Tensor< 1, dim, Number > &normal) const
DEAL_II_ALWAYS_INLINE Number beos_pressure(const Number &rho) const
static constexpr unsigned int n_initial_precomputed_values
DEAL_II_HOST_DEVICE state_type from_primitive_state(const state_type &primitive_state) const
static DEAL_II_HOST_DEVICE Number density(const state_type &U)
std::array< Number, n_precomputed_values > precomputed_type
static constexpr bool have_energy_equation
dealii::Tensor< 1, problem_dimension, Number > state_type
DEAL_II_HOST_DEVICE state_type from_initial_state(const ST &initial_state) const
typename get_value_type< Number >::type ScalarNumber
static constexpr bool have_high_order_flux
DEAL_II_HOST_DEVICE Number filter_vacuum_density(const Number &rho) const
static constexpr bool have_source_terms
static constexpr unsigned int n_precomputed_values
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
DEAL_II_ALWAYS_INLINE Number beos_specific_internal_energy(const Number &rho) const
DEAL_II_HOST_DEVICE state_type total_energy_derivative(const state_type &U, const Number &specific_internal_energy, const Number &pressure) const
DEAL_II_HOST_DEVICE state_type apply_galilei_transform(const state_type &state, const Lambda &lambda) const
DEAL_II_HOST_DEVICE 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
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber reference_density() const
static constexpr bool have_gamma
static DEAL_II_HOST_DEVICE dealii::Tensor< 1, dim, Number > momentum(const state_type &U)
DEAL_II_HOST_DEVICE state_type to_primitive_state(const state_type &state) const
DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const
flux_type flux_contribution_type
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_large() const
DEAL_II_ALWAYS_INLINE Number beos_speed_of_sound(const Number &rho) const
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
DEAL_II_HOST_DEVICE flux_type f(const state_type &U, const Number &p) const
DEAL_II_HOST_DEVICE state_type nodal_source(const PrecomputedVectorView &pv, const unsigned int *js, const state_type &U_j, const ScalarNumber tau) const =delete
DEAL_II_ALWAYS_INLINE const std::string & barotropic_equation_of_state() const
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
DEAL_II_HOST_DEVICE 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
void fill_precomputed_values(const OfflineData< dim, ScalarNumber > &offline_data, StateVector< ScalarNumber > &state_vector, const bool skip_constrained_dofs=true) const
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
dealii::Tensor< 1, problem_dimension, Number > state_type
std::string problem_name_
static Base & select(const std::vector< std::unique_ptr< Base > > &objects, const std::string &name)
static std::vector< std::unique_ptr< Base > > create(Args... args)
static dealii::Patterns::Selection selection(const std::vector< std::unique_ptr< Base > > &objects)
constexpr bool have_separate_memory_spaces
@ implicit_transfers_host_resident
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)
double vacuum_state_relaxation_large
double vacuum_state_relaxation_small
MultiComponentVector< Number > state
MultiComponentVector< Number > precomputed