11#include <deal.II/numerics/vector_tools.h>
12#include <deal.II/numerics/vector_tools.templates.h>
18 using namespace dealii;
20 template <
typename Description,
int dim,
typename Number>
24 const std::string &subsection)
25 : ParameterAcceptor(subsection)
26 , hyperbolic_system_(&hyperbolic_system)
27 , offline_data_(&offline_data)
29 ParameterAcceptor::parse_parameters_call_back.connect(std::bind(
33 configuration_ =
"uniform";
34 add_parameter(
"configuration",
36 "The initial state configuration. Valid names are given by "
37 "any of the subsections defined below.");
39 initial_direction_[0] = 1.;
43 "Initial direction of initial configuration (Galilei transform)");
45 initial_position_[0] = 1.;
49 "Initial position of initial configuration (Galilei transform)");
52 add_parameter(
"perturbation",
54 "Add a random perturbation of the specified magnitude to the "
62 initial_state_list_, *hyperbolic_system_, subsection);
71 inline DEAL_II_ALWAYS_INLINE dealii::Point<dim>
72 affine_transform(
const dealii::Tensor<1, dim> initial_direction,
73 const dealii::Point<dim> initial_position,
74 const dealii::Point<dim> x)
76 auto direction = x - initial_position;
79 if constexpr (dim == 3) {
80 auto n_x = initial_direction[0];
81 auto n_z = initial_direction[2];
82 const auto norm = std::sqrt(n_x * n_x + n_z * n_z);
85 auto new_direction = direction;
87 new_direction[0] = n_x * direction[0] + n_z * direction[2];
88 new_direction[2] = -n_z * direction[0] + n_x * direction[2];
90 direction = new_direction;
94 if constexpr (dim >= 2) {
95 auto n_x = initial_direction[0];
96 auto n_y = initial_direction[1];
97 const auto norm = std::sqrt(n_x * n_x + n_y * n_y);
100 auto new_direction = direction;
101 if (norm > 1.0e-14) {
102 new_direction[0] = n_x * direction[0] + n_y * direction[1];
103 new_direction[1] = -n_y * direction[0] + n_x * direction[1];
105 direction = new_direction;
108 return Point<dim>() + direction;
115 template <
int dim,
typename Number>
116 inline DEAL_II_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
117 affine_transform_vector(
const dealii::Tensor<1, dim> initial_direction,
118 dealii::Tensor<1, dim, Number> direction)
120 if constexpr (dim >= 2) {
121 auto n_x = initial_direction[0];
122 auto n_y = initial_direction[1];
123 const auto norm = std::sqrt(n_x * n_x + n_y * n_y);
126 auto new_direction = direction;
127 if (norm > 1.0e-14) {
128 new_direction[0] = n_x * direction[0] - n_y * direction[1];
129 new_direction[1] = n_y * direction[0] + n_x * direction[1];
131 direction = new_direction;
134 if constexpr (dim == 3) {
135 auto n_x = initial_direction[0];
136 auto n_z = initial_direction[2];
137 const auto norm = std::sqrt(n_x * n_x + n_z * n_z);
140 auto new_direction = direction;
141 if (norm > 1.0e-14) {
142 new_direction[0] = n_x * direction[0] - n_z * direction[2];
143 new_direction[2] = n_z * direction[0] + n_x * direction[2];
145 direction = new_direction;
153 template <
typename Description,
int dim,
typename Number>
158 AssertThrow(initial_direction_.norm() != 0.,
159 ExcMessage(
"Initial direction is set to the zero vector."));
160 initial_direction_ /= initial_direction_.norm();
165 bool initialized =
false;
166 for (
auto &it : initial_state_list_)
167 if (it->name() == configuration_) {
168 initial_state_ = [
this, &it](
const dealii::Point<dim> &point,
170 const auto transformed_point =
171 affine_transform(initial_direction_, initial_position_, point);
172 auto state = it->compute(transformed_point, t);
173 const auto view = hyperbolic_system_->template view<dim, Number>();
175 view.apply_galilei_transform(state, [&](
const auto &momentum) {
176 return affine_transform_vector(initial_direction_, momentum);
181 flux_contributions_ = [
this, &it](
const dealii::Point<dim> &point) {
182 const auto transformed_point =
183 affine_transform(initial_direction_, initial_position_, point);
184 return it->initial_precomputations(transformed_point);
193 "Could not find an initial state description with name \"" +
194 configuration_ +
"\""));
199 if (perturbation_ != 0.) {
200 initial_state_ = [old_state = this->initial_state_,
201 perturbation = this->perturbation_](
202 const dealii::Point<dim> &point, Number t) {
203 auto state = old_state(point, t);
208 static std::default_random_engine generator =
209 std::default_random_engine(std::random_device()());
210 static std::uniform_real_distribution<Number> distribution(-1., 1.);
211 static auto draw = std::bind(distribution, generator);
212 for (
unsigned int i = 0; i < problem_dimension; ++i)
213 state[i] *= (Number(1.) + perturbation * draw());
221 template <
typename Description,
int dim,
typename Number>
226 std::cout <<
"InitialValues<dim, Number>::interpolate(t = " << t <<
")"
231 U.reinit(offline_data_->vector_partitioner());
235 const auto callable = [&](
const auto &p) {
return initial_state(p, t); };
238 const auto scalar_partitioner = offline_data_->scalar_partitioner();
239 temp.reinit(scalar_partitioner);
241 for (
unsigned int d = 0; d < problem_dimension; ++d) {
242 VectorTools::interpolate(offline_data_->dof_handler(),
243 to_function<dim, Number>(callable, d),
255 const auto &boundary_map = offline_data_->boundary_map();
256 const unsigned int n_owned = offline_data_->n_locally_owned();
258 for (
auto entry : boundary_map) {
259 const auto i = entry.first;
263 const auto normal = std::get<0>(entry.second);
264 const auto id = std::get<3>(entry.second);
268 const auto view = hyperbolic_system_->template view<dim, Number>();
269 U_i = view.apply_boundary_conditions(
270 id, U_i, normal, [&]() {
return U_i; });
275 U.update_ghost_values();
280 template <
typename Description,
int dim,
typename Number>
285 const auto scalar_partitioner = offline_data_->scalar_partitioner();
290 if constexpr (n_precomputed_values == 0)
295 const auto callable = [&](
const auto &p) {
return flux_contributions(p); };
298 temp.reinit(scalar_partitioner);
300 for (
unsigned int d = 0; d < n_precomputed_values; ++d) {
301 VectorTools::interpolate(offline_data_->dof_handler(),
302 to_function<dim, Number>(callable, d),
307 precomputed.update_ghost_values();
static void populate_initial_state_list(initial_state_list_type &initial_state_list, const HyperbolicSystem &h, const std::string &s)
InitialValues(const HyperbolicSystem &hyperbolic_system, const OfflineData< dim, Number > &offline_data, const std::string &subsection="/InitialValues")
void parse_parameters_callback()
typename Description::HyperbolicSystem HyperbolicSystem
vector_type interpolate(Number t=0) const
MultiComponentVector< Number, n_precomputed_values > interpolate_precomputed_initial_values() const
void reinit_with_scalar_partitioner(const std::shared_ptr< const dealii::Utilities::MPI::Partitioner > &scalar_partitioner)
void insert_component(const scalar_type &scalar_vector, unsigned int component)
Tensor get_tensor(const unsigned int i) const
void write_tensor(const Tensor &tensor, const unsigned int i)