11#include <deal.II/base/config.h>
19#include <deal.II/base/parameter_acceptor.h>
20#include <deal.II/base/tensor.h>
26 namespace ScalarConservation
28 template <
int dim,
typename Number>
29 class HyperbolicSystemView;
43 static inline std::string
problem_name =
"Scalar conservation equation";
56 template <
int dim,
typename Number>
71 std::shared_ptr<Flux> selected_flux_;
73 template <
int dim,
typename Number>
84 template <
int dim,
typename Number>
93 : hyperbolic_system_(hyperbolic_system)
100 template <
int dim2,
typename Number2>
116 DEAL_II_ALWAYS_INLINE
inline const std::string &
flux()
const
118 return hyperbolic_system_.flux_;
124 const auto &
flux = hyperbolic_system_.selected_flux_;
137 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
143 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
170 using state_type = dealii::Tensor<1, problem_dimension, Number>;
176 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
188 std::array<std::string, problem_dimension>{
"u"};
195 std::array<std::string, problem_dimension>{
"u"};
211 []() -> std::array<std::string, n_precomputed_values> {
212 if constexpr (dim == 1)
214 else if constexpr (dim == 2)
215 return {
"f_1",
"f_2",
"df_1",
"df_2"};
216 else if constexpr (dim == 3)
217 return {
"f_1",
"f_2",
"f_3",
"df_1",
"df_2",
"df_3"};
230 std::array<Number, n_initial_precomputed_values>;
236 std::array<std::string, n_initial_precomputed_values>{};
242 StateVector<ScalarNumber, problem_dimension, n_precomputed_values>;
280 template <
typename DISPATCH,
typename SPARSITY>
282 const DISPATCH &dispatch_check,
283 const SPARSITY &sparsity_simd,
287 const bool skip_constrained_dofs =
true)
const;
356 template <
typename Lambda>
360 const dealii::Tensor<1, dim, Number> &normal,
361 const Lambda &get_dirichlet_data)
const;
373 dealii::Tensor<1, dim, Number>
406 const unsigned int i,
412 const unsigned int *js,
422 const dealii::Tensor<1, dim, Number> &c_ij)
const;
430 const dealii::Tensor<1, dim, Number> &c_ij)
const =
delete;
442 const unsigned int i,
447 const unsigned int *js,
467 template <
typename ST>
479 return primitive_state;
496 template <
typename Lambda>
498 const Lambda & )
const
514 : ParameterAcceptor(subsection)
517 add_parameter(
"flux",
519 "The scalar flux. Valid names are given by any of the "
520 "subsections defined below");
528 const auto populate_functions = [
this]() {
529 bool initialized =
false;
530 for (
auto &it : flux_list_)
533 if (it->name() == flux_) {
535 it->parse_parameters_call_back();
536 problem_name =
"Scalar conservation equation (" + it->name() +
537 ": " + it->flux_formula() +
")";
542 AssertThrow(initialized,
544 "Could not find a flux description with name \"" +
548 ParameterAcceptor::parse_parameters_call_back.connect(populate_functions);
549 populate_functions();
553 template <
int dim,
typename Number>
554 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
557 const auto &flux = hyperbolic_system_.selected_flux_;
558 dealii::Tensor<1, dim, Number> result;
561 for (
unsigned int k = 0; k < dim; ++k) {
562 if constexpr (std::is_same_v<ScalarNumber, Number>) {
563 result[k] = flux->value(u, k);
565 for (
unsigned int s = 0; s < Number::size(); ++s) {
566 result[k][s] = flux->value(u[s], k);
575 template <
int dim,
typename Number>
576 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
578 const Number &u)
const
580 const auto &flux = hyperbolic_system_.selected_flux_;
581 dealii::Tensor<1, dim, Number> result;
584 for (
unsigned int k = 0; k < dim; ++k) {
585 if constexpr (std::is_same_v<ScalarNumber, Number>) {
586 result[k] = flux->gradient(u, k);
588 for (
unsigned int s = 0; s < Number::size(); ++s) {
589 result[k][s] = flux->gradient(u[s], k);
598 template <
int dim,
typename Number>
599 template <
typename DISPATCH,
typename SPARSITY>
600 DEAL_II_ALWAYS_INLINE
inline void
602 unsigned int cycle [[maybe_unused]],
603 const DISPATCH &dispatch_check,
604 const SPARSITY &sparsity_simd,
608 const bool skip_constrained_dofs )
const
610 Assert(cycle == 0, dealii::ExcInternalError());
612 const auto &U = std::get<0>(state_vector);
613 auto &precomputed = std::get<1>(state_vector);
617 unsigned int stride_size = get_stride_size<Number>;
620 for (
unsigned int i = left; i < right; i += stride_size) {
623 const unsigned int row_length = sparsity_simd.row_length(i);
624 if (skip_constrained_dofs && row_length == 1)
629 const auto U_i = U.template get_tensor<Number>(i);
630 const auto u_i = state(U_i);
632 const auto f_i = flux_function(u_i);
633 const auto df_i = flux_gradient_function(u_i);
637 for (
unsigned int k = 0; k < n_precomputed_values / 2; ++k) {
639 prec_i[dim + k] = df_i[k];
642 precomputed.template write_tensor<Number>(prec_i, i);
647 template <
int dim,
typename Number>
648 DEAL_II_ALWAYS_INLINE
inline Number
655 template <
int dim,
typename Number>
656 DEAL_II_ALWAYS_INLINE
inline Number
663 template <
int dim,
typename Number>
664 DEAL_II_ALWAYS_INLINE
inline Number
666 const Number &u)
const
672 template <
int dim,
typename Number>
673 DEAL_II_ALWAYS_INLINE
inline Number
675 const Number &u)
const
677 return std::abs(k - u);
681 template <
int dim,
typename Number>
682 DEAL_II_ALWAYS_INLINE
inline Number
684 const Number &k,
const Number &u)
const
686 constexpr auto gte = dealii::SIMDComparison::greater_than_or_equal;
688 return dealii::compare_and_apply_mask<gte>(u, k, Number(1.), Number(-1.));
692 template <
int dim,
typename Number>
693 template <
typename Lambda>
694 DEAL_II_ALWAYS_INLINE
inline auto
696 dealii::types::boundary_id
id,
698 const dealii::Tensor<1, dim, Number> & ,
699 const Lambda &get_dirichlet_data)
const ->
state_type
704 result = get_dirichlet_data();
709 "Invalid boundary ID »Boundary::dirichlet_momentum«, "
710 "enforcing Dirichlet boundary conditions on a momentum "
711 "is not possible for scalar conservation equations."));
716 dealii::ExcMessage(
"Invalid boundary ID »Boundary::slip«, slip "
717 "boundary conditions are unavailable for scalar "
718 "conservation equations."));
724 dealii::ExcMessage(
"Invalid boundary ID »Boundary::no_slip«, "
725 "no-slip boundary conditions are unavailable "
726 "for scalar conservation equations."));
732 dealii::ExcMessage(
"Invalid boundary ID »Boundary::dynamic«, "
733 "dynamic boundary conditions are unavailable "
734 "for scalar conservation equations."));
738 AssertThrow(
false, dealii::ExcNotImplemented());
745 template <
int dim,
typename Number>
746 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
750 dealii::Tensor<1, dim, Number> result;
752 if constexpr (dim == 1) {
753 const auto &[f, df] = precomputed;
756 }
else if constexpr (dim == 2) {
757 const auto &[f_1, f_2, df_1, df_2] = precomputed;
761 }
else if constexpr (dim == 3) {
762 const auto &[f_1, f_2, f_3, df_1, df_2, df_3] = precomputed;
772 template <
int dim,
typename Number>
773 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<1, dim, Number>
777 dealii::Tensor<1, dim, Number> result;
779 if constexpr (dim == 1) {
780 const auto &[f, df] = precomputed;
783 }
else if constexpr (dim == 2) {
784 const auto &[f_1, f_2, df_1, df_2] = precomputed;
788 }
else if constexpr (dim == 3) {
789 const auto &[f_1, f_2, f_3, df_1, df_2, df_3] = precomputed;
799 template <
int dim,
typename Number>
800 DEAL_II_ALWAYS_INLINE
inline auto
804 const unsigned int i,
809 result[0] = construct_flux_tensor(
810 pv.template get_tensor<Number, precomputed_type>(i));
815 template <
int dim,
typename Number>
816 DEAL_II_ALWAYS_INLINE
inline auto
820 const unsigned int *js,
825 result[0] = construct_flux_tensor(
826 pv.template get_tensor<Number, precomputed_type>(js));
831 template <
int dim,
typename Number>
832 DEAL_II_ALWAYS_INLINE
inline auto
836 const dealii::Tensor<1, dim, Number> &c_ij)
const ->
state_type
dealii::Tensor< 1, problem_dimension, Number > state_type
std::array< Number, n_precomputed_values > precomputed_type
Vectors::StateVector< ScalarNumber, problem_dimension, n_precomputed_values > StateVector
static const auto initial_precomputed_names
flux_contribution_type flux_contribution(const PrecomputedVector &pv, const InitialPrecomputedVector &, const unsigned int i, const state_type &) const
state_type apply_galilei_transform(const state_type &state, const Lambda &) const
static constexpr unsigned int n_precomputation_cycles
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
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
state_type nodal_source(const PrecomputedVector &pv, const unsigned int *js, const state_type &U_j, const ScalarNumber tau) const =delete
void precomputation_loop(unsigned int cycle, const DISPATCH &dispatch_check, const SPARSITY &sparsity_simd, StateVector &state_vector, unsigned int left, unsigned int right, const bool skip_constrained_dofs=true) const
typename get_value_type< Number >::type ScalarNumber
static Number state(const state_type &U)
Number kruzkov_entropy(const Number &k, const Number &u) const
state_type nodal_source(const PrecomputedVector &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
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 flux_divergence(const flux_contribution_type &flux_i, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &c_ij) const
static constexpr bool have_source_terms
static std::string problem_name
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
std::set< std::shared_ptr< Flux > > flux_list_type
void populate_flux_list(flux_list_type &flux_list, const std::string &subsection)
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)