8#include <compile_time_options.h>
20#include <deal.II/base/parameter_acceptor.h>
21#include <deal.II/base/tensor.h>
27 namespace ScalarConservation
29 template <
int dim,
typename Number>
30 class HyperbolicSystemView;
44 static inline std::string
problem_name =
"Scalar conservation equation";
55 template <
int dim,
typename Number =
double>
64 template <
int dim,
typename Number>
78 template <
int dim,
typename ScalarNumber>
83 const bool skip_constrained_dofs =
true)
const;
102 std::shared_ptr<Flux> selected_flux_;
104 template <
int dim,
typename Number>
118 template <
int dim,
typename Number>
140 using state_type = dealii::Tensor<1, problem_dimension, Number>;
146 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
158 std::array<std::string, problem_dimension>{
"u"};
165 std::array<std::string, problem_dimension>{
"u"};
181 []() -> std::array<std::string, n_precomputed_values> {
182 if constexpr (dim == 1)
184 else if constexpr (dim == 2)
185 return {
"f_1",
"f_2",
"df_1",
"df_2"};
186 else if constexpr (dim == 3)
187 return {
"f_1",
"f_2",
"f_3",
"df_1",
"df_2",
"df_3"};
200 std::array<Number, n_initial_precomputed_values>;
206 std::array<std::string, n_initial_precomputed_values>{};
212 StateVector<ScalarNumber, problem_dimension, n_precomputed_values>;
233 dealii::VectorizedArray<ScalarNumber>::size(),
234 dealii::MemorySpace::Host,
252 dealii::VectorizedArray<ScalarNumber>::size(),
253 dealii::MemorySpace::Host,
267 : hyperbolic_system_(hyperbolic_system)
277 DEAL_II_ALWAYS_INLINE
inline const std::string &
flux()
const
279 return hyperbolic_system_.flux_;
285 const auto &
flux = hyperbolic_system_.selected_flux_;
298 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
304 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
374 template <
typename Lambda>
378 const dealii::Tensor<1, dim, Number> &normal,
379 const Lambda &get_dirichlet_data)
const;
391 dealii::Tensor<1, dim, Number>
424 const unsigned int i,
430 const unsigned int *js,
440 const dealii::Tensor<1, dim, Number> &c_ij)
const;
448 const dealii::Tensor<1, dim, Number> &c_ij)
const =
delete;
460 const unsigned int i,
465 const unsigned int *js,
485 template <
typename ST>
497 return primitive_state;
514 template <
typename Lambda>
516 const Lambda & )
const
542 : ParameterAcceptor(subsection)
545 add_parameter(
"flux",
547 "The scalar flux. Valid names are given by any of the "
548 "subsections defined below");
556 const auto populate_functions = [
this]() {
557 bool initialized =
false;
558 for (
auto &it : flux_list_)
561 if (it->name() == flux_) {
563 it->parse_parameters_call_back();
564 problem_name =
"Scalar conservation equation (" + it->name() +
565 ": " + it->flux_formula() +
")";
570 AssertThrow(initialized,
572 "Could not find a flux description with name \"" +
576 ParameterAcceptor::parse_parameters_call_back.connect(populate_functions);
577 populate_functions();
581 template <
int dim,
typename ScalarNumber>
586 const bool skip_constrained_dofs)
const
590 const auto sparsity_simd_view =
592 using VA = dealii::VectorizedArray<ScalarNumber>;
594 const auto U_view = std::get<0>(state_vector).view();
595 const auto precomputed_view = std::get<1>(state_vector).view();
597 const auto body = [&](
auto sentinel,
unsigned int i) {
598 using T =
decltype(sentinel);
602 const unsigned int row_length = sparsity_simd_view.row_length(i);
603 if (skip_constrained_dofs && row_length == 1)
606 const auto U_i = U_view.template read_tensor<T>(i);
607 const auto view = this->view<dim, T>();
608 const auto u_i =
view.state(U_i);
609 const auto f_i =
view.flux_function(u_i);
610 const auto df_i =
view.flux_gradient_function(u_i);
612 precomputed_type prec_i;
615 prec_i[dim + k] = df_i[k];
618 precomputed_view.template write_tensor<T>(prec_i, i);
621 cpu_simd_loop<ScalarNumber>(
"time_step_1", body, 0, n_internal, n_owned);
625 template <
int dim,
typename Number>
626 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
629 const auto &flux = hyperbolic_system_.selected_flux_;
630 dealii::Tensor<1, dim, Number> result;
633 for (
unsigned int k = 0; k < dim; ++k) {
634 if constexpr (std::is_same_v<ScalarNumber, Number>) {
635 result[k] = flux->value(u, k);
637 for (
unsigned int s = 0; s < Number::size(); ++s) {
638 result[k][s] = flux->value(u[s], k);
646 template <
int dim,
typename Number>
647 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
649 const Number &u)
const
651 const auto &flux = hyperbolic_system_.selected_flux_;
652 dealii::Tensor<1, dim, Number> result;
655 for (
unsigned int k = 0; k < dim; ++k) {
656 if constexpr (std::is_same_v<ScalarNumber, Number>) {
657 result[k] = flux->gradient(u, k);
659 for (
unsigned int s = 0; s < Number::size(); ++s) {
660 result[k][s] = flux->gradient(u[s], k);
669 template <
int dim,
typename Number>
670 DEAL_II_ALWAYS_INLINE
inline Number
677 template <
int dim,
typename Number>
678 DEAL_II_ALWAYS_INLINE
inline Number
685 template <
int dim,
typename Number>
686 DEAL_II_ALWAYS_INLINE
inline Number
688 const Number &u)
const
694 template <
int dim,
typename Number>
695 DEAL_II_ALWAYS_INLINE
inline Number
697 const Number &u)
const
699 return std::abs(k - u);
703 template <
int dim,
typename Number>
704 DEAL_II_ALWAYS_INLINE
inline Number
706 const Number &k,
const Number &u)
const
708 constexpr auto gte = dealii::SIMDComparison::greater_than_or_equal;
710 return dealii::compare_and_apply_mask<gte>(u, k, Number(1.), Number(-1.));
714 template <
int dim,
typename Number>
715 template <
typename Lambda>
716 DEAL_II_ALWAYS_INLINE
inline auto
718 dealii::types::boundary_id
id,
720 const dealii::Tensor<1, dim, Number> & ,
721 const Lambda &get_dirichlet_data)
const ->
state_type
726 result = get_dirichlet_data();
731 "Invalid boundary ID »Boundary::dirichlet_momentum«, "
732 "enforcing Dirichlet boundary conditions on a momentum "
733 "is not possible for scalar conservation equations."));
738 "Invalid boundary ID »Boundary::dirichlet_velocity«, "
739 "enforcing Dirichlet boundary conditions on a momentum "
740 "is not possible for scalar conservation equations."));
745 dealii::ExcMessage(
"Invalid boundary ID »Boundary::slip«, slip "
746 "boundary conditions are unavailable for scalar "
747 "conservation equations."));
753 dealii::ExcMessage(
"Invalid boundary ID »Boundary::no_slip«, "
754 "no-slip boundary conditions are unavailable "
755 "for scalar conservation equations."));
761 dealii::ExcMessage(
"Invalid boundary ID »Boundary::dynamic«, "
762 "dynamic boundary conditions are unavailable "
763 "for scalar conservation equations."));
767 AssertThrow(
false, dealii::ExcNotImplemented());
774 template <
int dim,
typename Number>
775 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
779 dealii::Tensor<1, dim, Number> result;
781 if constexpr (dim == 1) {
782 const auto &[f, df] = precomputed;
785 }
else if constexpr (dim == 2) {
786 const auto &[f_1, f_2, df_1, df_2] = precomputed;
790 }
else if constexpr (dim == 3) {
791 const auto &[f_1, f_2, f_3, df_1, df_2, df_3] = precomputed;
801 template <
int dim,
typename Number>
802 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
806 dealii::Tensor<1, dim, Number> result;
808 if constexpr (dim == 1) {
809 const auto &[f, df] = precomputed;
812 }
else if constexpr (dim == 2) {
813 const auto &[f_1, f_2, df_1, df_2] = precomputed;
817 }
else if constexpr (dim == 3) {
818 const auto &[f_1, f_2, f_3, df_1, df_2, df_3] = precomputed;
828 template <
int dim,
typename Number>
829 DEAL_II_ALWAYS_INLINE
inline auto
833 const unsigned int i,
838 result[0] = construct_flux_tensor(
839 pv.template read_tensor<Number, precomputed_type>(i));
844 template <
int dim,
typename Number>
845 DEAL_II_ALWAYS_INLINE
inline auto
849 const unsigned int *js,
854 result[0] = construct_flux_tensor(
855 pv.template read_tensor<Number, precomputed_type>(js));
860 template <
int dim,
typename Number>
861 DEAL_II_ALWAYS_INLINE
inline auto
865 const dealii::Tensor<1, dim, Number> &c_ij)
const ->
state_type
dealii::Tensor< 1, problem_dimension, Number > state_type
const auto & n_locally_owned() const
const auto & sparsity_pattern_simd() const
const auto & n_locally_internal() const
static const auto initial_precomputed_names
state_type apply_galilei_transform(const state_type &state, const Lambda &) const
Number kruzkov_entropy_derivative(const Number &k, const Number &u) const
DEAL_II_ALWAYS_INLINE const std::string & flux() const
static constexpr unsigned int problem_dimension
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
DEAL_II_ALWAYS_INLINE dealii::Tensor< 1, dim, Number > flux_function(const Number &u) const
state_type nodal_source(const PrecomputedVectorView &pv, const unsigned int *js, const state_type &U_j, const ScalarNumber tau) const =delete
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
state_type from_primitive_state(const state_type &primitive_state) const
std::array< Number, n_precomputed_values > precomputed_type
static const auto component_names
Number square_entropy_derivative(const Number &u) const
dealii::Tensor< 1, dim, Number > construct_flux_gradient_tensor(const precomputed_type &precomputed_state) const
state_type to_primitive_state(const state_type &state) const
DEAL_II_ALWAYS_INLINE ScalarNumber derivative_approximation_delta() const
Number square_entropy(const Number &u) const
static const auto primitive_component_names
static constexpr bool have_high_order_flux
typename get_value_type< Number >::type ScalarNumber
static Number state(const state_type &U)
Number kruzkov_entropy(const Number &k, 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_initial_precomputed_values
static constexpr unsigned int n_precomputed_values
dealii::Tensor< 1, problem_dimension, Number > state_type
bool is_admissible(const state_type &) const
state_type expand_state(const ST &state) const
static const auto precomputed_names
state_type high_order_flux_divergence(const flux_contribution_type &, const flux_contribution_type &, const dealii::Tensor< 1, dim, Number > &c_ij) const =delete
flux_type flux_contribution_type
Vectors::StateVector< ScalarNumber, problem_dimension, n_precomputed_values > StateVector
dealii::Tensor< 1, dim, Number > construct_flux_tensor(const precomputed_type &precomputed_state) 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
state_type nodal_source(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
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
flux_contribution_type flux_contribution(const PrecomputedVectorView &pv, const InitialPrecomputedVectorView &, const unsigned int i, const state_type &) const
static constexpr bool have_source_terms
static std::string problem_name
void fill_precomputed_values(const OfflineData< dim, ScalarNumber > &offline_data, typename HyperbolicSystemView< dim, ScalarNumber >::StateVector &state_vector, const bool skip_constrained_dofs=true) const
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
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)
void populate_flux_list(flux_list_type &flux_list, const std::string &subsection)
std::set< std::shared_ptr< Flux > > flux_list_type