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 initial_precomputed_ = [
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);
194 "Could not find an initial state description with name \"" +
195 configuration_ +
"\""));
200 if (perturbation_ != 0.) {
201 initial_state_ = [old_state = this->initial_state_,
202 perturbation = this->perturbation_](
203 const dealii::Point<dim> &point, Number t) {
204 auto state = old_state(point, t);
209 static std::default_random_engine generator =
210 std::default_random_engine(std::random_device()());
211 static std::uniform_real_distribution<Number> distribution(-1., 1.);
212 static auto draw = std::bind(distribution, generator);
213 for (
unsigned int i = 0; i < problem_dimension; ++i)
214 state[i] *= (Number(1.) + perturbation * draw());
222 template <
typename Description,
int dim,
typename Number>
227 std::cout <<
"InitialValues<dim, Number>::"
228 <<
"interpolate_hyperbolic_vector(t = " << t <<
")" << std::endl;
232 U.reinit(offline_data_->hyperbolic_vector_partitioner());
236 const auto callable = [&](
const auto &p) {
return initial_state(p, t); };
239 const auto scalar_partitioner = offline_data_->scalar_partitioner();
240 temp.reinit(scalar_partitioner);
242 for (
unsigned int d = 0; d < problem_dimension; ++d) {
243 VectorTools::interpolate(offline_data_->dof_handler(),
244 to_function<dim, Number>(callable, d),
246 U.insert_component(temp, d);
249 U.update_ghost_values();
255 template <
typename Description,
int dim,
typename Number>
260 std::cout <<
"InitialValues<dim, Number>::"
261 <<
"interpolate_initial_precomputed_vector()" << std::endl;
264 const auto scalar_partitioner = offline_data_->scalar_partitioner();
267 precomputed.reinit_with_scalar_partitioner(scalar_partitioner);
269 if constexpr (n_initial_precomputed_values == 0)
274 const auto callable = [&](
const auto &p) {
return initial_precomputed(p); };
277 temp.reinit(scalar_partitioner);
279 for (
unsigned int d = 0; d < n_initial_precomputed_values; ++d) {
280 VectorTools::interpolate(offline_data_->dof_handler(),
281 to_function<dim, Number>(callable, d),
283 precomputed.insert_component(temp, d);
286 precomputed.update_ghost_values();
static void populate_initial_state_list(initial_state_list_type &initial_state_list, const HyperbolicSystem &h, const std::string &s)
InitialPrecomputedVector interpolate_initial_precomputed_vector() const
InitialValues(const HyperbolicSystem &hyperbolic_system, const OfflineData< dim, Number > &offline_data, const std::string &subsection="/InitialValues")
typename View::InitialPrecomputedVector InitialPrecomputedVector
void parse_parameters_callback()
typename Description::HyperbolicSystem HyperbolicSystem
HyperbolicVector interpolate_hyperbolic_vector(Number t=0) const
typename View::HyperbolicVector HyperbolicVector
Vectors::ScalarVector< Number > ScalarVector
dealii::LinearAlgebra::distributed::Vector< Number > ScalarVector