ryujin 2.1.1 revision 0348cbb53a3e4b1da2a4c037e81f88f2d21ce219
initial_values.template.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2020 - 2023 by the ryujin authors
4//
5
6#pragma once
7
8#include "initial_values.h"
9#include "simd.h"
10
11#include <deal.II/numerics/vector_tools.h>
12#include <deal.II/numerics/vector_tools.templates.h>
13
14#include <random>
15
16namespace ryujin
17{
18 using namespace dealii;
19
20 template <typename Description, int dim, typename Number>
22 const HyperbolicSystem &hyperbolic_system,
23 const OfflineData<dim, Number> &offline_data,
24 const std::string &subsection)
25 : ParameterAcceptor(subsection)
26 , hyperbolic_system_(&hyperbolic_system)
27 , offline_data_(&offline_data)
28 {
29 ParameterAcceptor::parse_parameters_call_back.connect(std::bind(
31 this));
32
33 configuration_ = "uniform";
34 add_parameter("configuration",
35 configuration_,
36 "The initial state configuration. Valid names are given by "
37 "any of the subsections defined below.");
38
39 initial_direction_[0] = 1.;
40 add_parameter(
41 "direction",
42 initial_direction_,
43 "Initial direction of initial configuration (Galilei transform)");
44
45 initial_position_[0] = 1.;
46 add_parameter(
47 "position",
48 initial_position_,
49 "Initial position of initial configuration (Galilei transform)");
50
51 perturbation_ = 0.;
52 add_parameter("perturbation",
53 perturbation_,
54 "Add a random perturbation of the specified magnitude to the "
55 "initial state.");
56
57 /*
58 * And finally populate the initial state list with all initial state
59 * configurations defined in the InitialStateLibrary namespace:
60 */
62 initial_state_list_, *hyperbolic_system_, subsection);
63 }
64
65 namespace
66 {
70 template <int dim>
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)
75 {
76 auto direction = x - initial_position;
77
78 /* Roll third component of initial_direction onto xy-plane: */
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);
83 n_x /= norm;
84 n_z /= norm;
85 auto new_direction = direction;
86 if (norm > 1.0e-14) {
87 new_direction[0] = n_x * direction[0] + n_z * direction[2];
88 new_direction[2] = -n_z * direction[0] + n_x * direction[2];
89 }
90 direction = new_direction;
91 }
92
93 /* Roll second component of initial_direction onto x-axis: */
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);
98 n_x /= norm;
99 n_y /= norm;
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];
104 }
105 direction = new_direction;
106 }
107
108 return Point<dim>() + direction;
109 }
110
111
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)
119 {
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);
124 n_x /= norm;
125 n_y /= norm;
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];
130 }
131 direction = new_direction;
132 }
133
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);
138 n_x /= norm;
139 n_z /= norm;
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];
144 }
145 direction = new_direction;
146 }
147
148 return direction;
149 }
150 } /* namespace */
151
152
153 template <typename Description, int dim, typename Number>
155 {
156 /* First, let's normalize the direction: */
157
158 AssertThrow(initial_direction_.norm() != 0.,
159 ExcMessage("Initial direction is set to the zero vector."));
160 initial_direction_ /= initial_direction_.norm();
161
162 /* Populate std::function object: */
163
164 {
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,
169 Number t) {
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>();
174 state =
175 view.apply_galilei_transform(state, [&](const auto &momentum) {
176 return affine_transform_vector(initial_direction_, momentum);
177 });
178 return state;
179 };
180
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);
185 };
186
187 initialized = true;
188 break;
189 }
190
191 AssertThrow(
192 initialized,
193 ExcMessage(
194 "Could not find an initial state description with name \"" +
195 configuration_ + "\""));
196 }
197
198 /* Add a random perturbation to the original function object: */
199
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);
205
206 if (t > 0.)
207 return state;
208
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());
215
216 return state;
217 };
218 }
219 }
220
221
222 template <typename Description, int dim, typename Number>
224 Number t) const -> HyperbolicVector
225 {
226#ifdef DEBUG_OUTPUT
227 std::cout << "InitialValues<dim, Number>::"
228 << "interpolate_hyperbolic_vector(t = " << t << ")" << std::endl;
229#endif
230
232 U.reinit(offline_data_->hyperbolic_vector_partitioner());
233
235
236 const auto callable = [&](const auto &p) { return initial_state(p, t); };
237
238 ScalarVector temp;
239 const auto scalar_partitioner = offline_data_->scalar_partitioner();
240 temp.reinit(scalar_partitioner);
241
242 for (unsigned int d = 0; d < problem_dimension; ++d) {
243 VectorTools::interpolate(offline_data_->dof_handler(),
244 to_function<dim, Number>(callable, d),
245 temp);
246 U.insert_component(temp, d);
247 }
248
249 U.update_ghost_values();
250
251 return U;
252 }
253
254
255 template <typename Description, int dim, typename Number>
258 {
259#ifdef DEBUG_OUTPUT
260 std::cout << "InitialValues<dim, Number>::"
261 << "interpolate_initial_precomputed_vector()" << std::endl;
262#endif
263
264 const auto scalar_partitioner = offline_data_->scalar_partitioner();
265
266 InitialPrecomputedVector precomputed;
267 precomputed.reinit_with_scalar_partitioner(scalar_partitioner);
268
269 if constexpr (n_initial_precomputed_values == 0)
270 return precomputed;
271
273
274 const auto callable = [&](const auto &p) { return initial_precomputed(p); };
275
276 ScalarVector temp;
277 temp.reinit(scalar_partitioner);
278
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),
282 temp);
283 precomputed.insert_component(temp, d);
284 }
285
286 precomputed.update_ghost_values();
287 return precomputed;
288 }
289
290} /* namespace ryujin */
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
typename Description::HyperbolicSystem HyperbolicSystem
HyperbolicVector interpolate_hyperbolic_vector(Number t=0) const
typename View::HyperbolicVector HyperbolicVector
Vectors::ScalarVector< Number > ScalarVector
Definition: offline_data.h:58
dealii::LinearAlgebra::distributed::Vector< Number > ScalarVector
Definition: state_vector.h:31