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 ScalarConservation
35 typename MemorySpace = dealii::MemorySpace::Host>
36 class HyperbolicSystemView;
66 typename Number = double,
67 typename MemorySpace = dealii::MemorySpace::Host>
79 typename MemorySpace = dealii::MemorySpace::Host>
98 template <
typename MemorySpace = dealii::MemorySpace::Host,
100 typename ScalarNumber>
104 const bool skip_constrained_dofs =
true)
const;
116 void update_parameters();
122 std::vector<std::unique_ptr<Flux>> flux_list_;
124 const Flux *selected_flux_ =
nullptr;
126 template <
int,
typename,
typename>
143 template <
int dim,
typename Number,
typename MemorySpace>
148 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
149 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
150 "Unexpected memory space");
170 using state_type = dealii::Tensor<1, problem_dimension, Number>;
176 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
202 std::array<Number, n_initial_precomputed_values>;
204 template <
int n_comp>
233 hyperbolic_system.parameters_.template view<MemorySpace>())
234 , flux_(hyperbolic_system.selected_flux_)
249 DEAL_II_ALWAYS_INLINE
inline const std::string &
flux()
const
251 return flux_->name();
273 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
279 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
311 DEAL_II_HOST_DEVICE Number
321 const Number &u)
const;
330 DEAL_II_HOST_DEVICE Number
338 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
bool
353 template <
typename Lambda>
357 const dealii::Tensor<1, dim, Number> &normal,
358 const Lambda &get_dirichlet_data)
const;
370 DEAL_II_HOST_DEVICE dealii::Tensor<1, dim, Number>
378 DEAL_II_HOST_DEVICE dealii::Tensor<1, dim, Number>
405 const unsigned int i,
412 const unsigned int *js,
423 const dealii::Tensor<1, dim, Number> &c_ij)
const;
431 const dealii::Tensor<1, dim, Number> &c_ij)
const =
delete;
443 const unsigned int i,
448 const unsigned int *js,
468 template <
typename ST>
482 return primitive_state;
500 template <
typename Lambda>
517 const Flux *
const flux_;
532 "Scalar conservation equation",
533 {{{
"u"}, {
"u"}, {
"u"}}},
534 {{{
"u"}, {
"u"}, {
"u"}}},
536 {
"f_1",
"f_2",
"df_1",
"df_2"},
537 {
"f_1",
"f_2",
"f_3",
"df_1",
"df_2",
"df_3"}}},
540 , parameters_(
"scalar_conservation_hyperbolic_system_parameters",
546 add_parameter(
"flux",
548 "The scalar flux. Valid names are given by any of the "
549 "subsections defined below",
558 ParameterAcceptor::parse_parameters_call_back.connect(
559 [
this] { update_parameters(); });
560 for (
auto &it : flux_list_)
561 it->parse_parameters_call_back.connect([this] { update_parameters(); });
567 inline void HyperbolicSystem::update_parameters()
571 selected_flux_->name() +
": " +
572 selected_flux_->flux_formula() +
")";
575 auto ¶meters = *parameters_.view();
577 parameters.derivative_approximation_delta =
578 selected_flux_->derivative_approximation_delta();
582 template <
typename MemorySpace,
int dim,
typename ScalarNumber>
586 const bool skip_constrained_dofs)
const
588 using HostSpace = dealii::MemorySpace::Host;
590 const unsigned int n_internal = offline_data.n_locally_internal();
591 const unsigned int n_owned = offline_data.n_locally_owned();
595 auto &U = state_vector.
state;
605 constexpr bool transfer =
607 !std::is_same_v<MemorySpace, dealii::MemorySpace::Host>;
609 [[maybe_unused]]
const bool host_resident =
610 U.template is_resident<HostSpace>();
612 if constexpr (transfer) {
613 U.template copy_to_memory_space<HostSpace>();
614 precomputed.template move_to_memory_space<HostSpace>();
618 const auto sparsity_simd_view =
619 offline_data.sparsity_pattern_simd().template view<HostSpace>();
624 .template view<ScalarView::problem_dimension, HostSpace>();
625 const auto precomputed_view =
627 .template view<ScalarView::n_precomputed_values, HostSpace>();
629 const auto hyperbolic_system_views =
630 make_select_view<dim, ScalarNumber, HostSpace>(*
this);
632 const auto body = [=](
auto sentinel,
unsigned int i) {
633 using T =
decltype(sentinel);
637 const unsigned int row_length = sparsity_simd_view.row_length(i);
638 if (skip_constrained_dofs && row_length == 1)
641 const auto view = hyperbolic_system_views.template view<T>();
643 const auto U_i = U_view.template read_tensor<T>(i);
644 const auto u_i =
view.state(U_i);
647 const auto f_i =
view.flux_function(u_i);
648 const auto df_i =
view.flux_gradient_function(u_i);
650 precomputed_type prec_i;
653 prec_i[dim + k] = df_i[k];
655 precomputed_view.template write_tensor<T>(prec_i, i);
658 loop<HostSpace, ScalarNumber>(
659 "hyperbolic_kernel_01b", body, 0, n_internal, n_owned);
662 if constexpr (transfer) {
665 U.template move_to_memory_space<MemorySpace>();
666 precomputed.template move_to_memory_space<MemorySpace>();
671 template <
int dim,
typename Number,
typename MemorySpace>
672 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
674 const Number &u)
const
676 const auto &flux = flux_;
677 dealii::Tensor<1, dim, Number> result;
680 for (
unsigned int k = 0; k < dim; ++k) {
681 if constexpr (std::is_same_v<ScalarNumber, Number>) {
682 result[k] = flux->value(u, k);
684 for (
unsigned int s = 0; s < Number::size(); ++s) {
685 result[k][s] = flux->value(u[s], k);
693 template <
int dim,
typename Number,
typename MemorySpace>
694 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
696 const Number &u)
const
698 const auto &flux = flux_;
699 dealii::Tensor<1, dim, Number> result;
702 for (
unsigned int k = 0; k < dim; ++k) {
703 if constexpr (std::is_same_v<ScalarNumber, Number>) {
704 result[k] = flux->gradient(u, k);
706 for (
unsigned int s = 0; s < Number::size(); ++s) {
707 result[k][s] = flux->gradient(u[s], k);
716 template <
int dim,
typename Number,
typename MemorySpace>
717 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
724 template <
int dim,
typename Number,
typename MemorySpace>
725 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
727 const Number &u)
const
733 template <
int dim,
typename Number,
typename MemorySpace>
734 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
736 const Number &u)
const
742 template <
int dim,
typename Number,
typename MemorySpace>
743 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
745 const Number &k,
const Number &u)
const
747 return std::abs(k - u);
751 template <
int dim,
typename Number,
typename MemorySpace>
752 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
754 const Number &k,
const Number &u)
const
756 constexpr auto gte = dealii::SIMDComparison::greater_than_or_equal;
758 return ryujin::compare_and_apply_mask<gte>(u, k, Number(1.), Number(-1.));
762 template <
int dim,
typename Number,
typename MemorySpace>
763 template <
typename Lambda>
764 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
766 dealii::types::boundary_id
id,
768 const dealii::Tensor<1, dim, Number> & ,
769 const Lambda &get_dirichlet_data)
const ->
state_type
774 result = get_dirichlet_data();
779 "Invalid boundary ID »Boundary::dirichlet_momentum«, "
780 "enforcing Dirichlet boundary conditions on a momentum "
781 "is not possible for scalar conservation equations."));
786 "Invalid boundary ID »Boundary::dirichlet_velocity«, "
787 "enforcing Dirichlet boundary conditions on a momentum "
788 "is not possible for scalar conservation equations."));
793 dealii::ExcMessage(
"Invalid boundary ID »Boundary::slip«, slip "
794 "boundary conditions are unavailable for scalar "
795 "conservation equations."));
800 dealii::ExcMessage(
"Invalid boundary ID »Boundary::no_slip«, "
801 "no-slip boundary conditions are unavailable "
802 "for scalar conservation equations."));
807 dealii::ExcMessage(
"Invalid boundary ID »Boundary::dynamic«, "
808 "dynamic boundary conditions are unavailable "
809 "for scalar conservation equations."));
813 Assert(
false, dealii::ExcNotImplemented());
820 template <
int dim,
typename Number,
typename MemorySpace>
821 DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
825 dealii::Tensor<1, dim, Number> result;
826 for (
unsigned int k = 0; k < dim; ++k)
832 template <
int dim,
typename Number,
typename MemorySpace>
833 DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
838 dealii::Tensor<1, dim, Number> result;
839 for (
unsigned int k = 0; k < dim; ++k)
845 template <
int dim,
typename Number,
typename MemorySpace>
846 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
850 const unsigned int i,
855 result[0] = construct_flux_tensor(
856 pv.template read_tensor<Number, precomputed_type>(i));
861 template <
int dim,
typename Number,
typename MemorySpace>
862 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
866 const unsigned int *js,
871 result[0] = construct_flux_tensor(
872 pv.template read_tensor<Number, precomputed_type>(js));
877 template <
int dim,
typename Number,
typename MemorySpace>
878 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
882 const dealii::Tensor<1, dim, Number> &c_ij)
const ->
state_type
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)
DEAL_II_HOST_DEVICE dealii::Tensor< 1, dim, Number > construct_flux_gradient_tensor(const precomputed_type &precomputed_state) const
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
DEAL_II_HOST_DEVICE_ALWAYS_INLINE state_type from_primitive_state(const state_type &primitive_state) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber derivative_approximation_delta() const
DEAL_II_HOST_DEVICE Number square_entropy_derivative(const Number &u) const
dealii::Tensor< 1, problem_dimension, Number > state_type
DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool is_admissible(const state_type &) const
std::array< Number, n_precomputed_values > precomputed_type
DEAL_II_HOST_DEVICE_ALWAYS_INLINE state_type apply_galilei_transform(const state_type &state, const Lambda &) const
DEAL_II_HOST_DEVICE flux_contribution_type flux_contribution(const PrecomputedVectorView &pv, const InitialPrecomputedVectorView &, const unsigned int i, const state_type &) const
DEAL_II_HOST_DEVICE Number square_entropy(const Number &u) const
DEAL_II_ALWAYS_INLINE dealii::Tensor< 1, dim, Number > flux_gradient_function(const Number &u) const
static constexpr unsigned int n_precomputed_values
flux_type flux_contribution_type
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
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 & flux() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE state_type expand_state(const ST &state) const
DEAL_II_HOST_DEVICE Number kruzkov_entropy(const Number &k, const Number &u) const
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
static DEAL_II_HOST_DEVICE Number state(const state_type &U)
DEAL_II_HOST_DEVICE dealii::Tensor< 1, dim, Number > construct_flux_tensor(const precomputed_type &precomputed_state) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE state_type to_primitive_state(const state_type &state) 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 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
static constexpr bool have_source_terms
DEAL_II_ALWAYS_INLINE dealii::Tensor< 1, dim, Number > flux_function(const Number &u) const
static constexpr bool have_high_order_flux
static constexpr unsigned int n_initial_precomputed_values
state_type high_order_flux_divergence(const flux_contribution_type &, const flux_contribution_type &, const dealii::Tensor< 1, dim, Number > &c_ij) const =delete
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
DEAL_II_HOST_DEVICE Number kruzkov_entropy_derivative(const Number &k, const Number &u) const
typename get_value_type< Number >::type ScalarNumber
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")
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 derivative_approximation_delta
MultiComponentVector< Number > state
MultiComponentVector< Number > precomputed