52 const std::string subsection)
55 , hyperbolic_system_(hyperbolic_system)
58 if constexpr (!View::have_gamma) {
59 this->add_parameter(
"gamma", gamma_,
"The ratio of specific heats");
62 primitive_left_[0] = 1.4;
63 primitive_left_[1] = 0.0;
64 primitive_left_[2] = 1.0;
65 this->add_parameter(
"primitive state left",
67 "1d primitive state [rho, u, p] (for the "
68 "polytropic gas EOS) on the left");
70 primitive_right_[0] = 1.4;
71 primitive_right_[1] = 0.0;
72 primitive_right_[2] = 1.0;
73 this->add_parameter(
"primitive state right",
75 "1d primitive state [rho, u, p] (for the "
76 "polytropic gas EOS) on the right");
79 const auto prepare_riemann_data = [&]() {
80 const auto view = hyperbolic_system_.template view<dim, Number>();
81 if constexpr (View::have_gamma) {
82 gamma_ = view.gamma();
85 const Number p_L = primitive_left_[2];
86 const Number p_R = primitive_right_[2];
88 p_star_ = compute_pstar(p_L, p_R, primitive_left_, primitive_right_);
90 const Number u_L = primitive_left_[1];
91 u_star_ = u_L - fZofP(p_star_, primitive_left_);
94 const Number u_R = primitive_right_[1];
95 std::cout <<
"left data = " << primitive_left_
96 <<
"\nright data = " << primitive_right_
97 <<
"\np_star = " << p_star_
98 <<
"\nu_star = " << u_star_
99 <<
"\nVerifying u_star = "
100 << u_R + fZofP(p_star_, primitive_right_) << std::endl;
103 lambda_left_minus_ = lambda(p_star_, primitive_left_, -1.);
105 lambda_intermediate(p_star_, primitive_left_, -1.);
106 lambda_right_minus_ =
107 lambda_intermediate(p_star_, primitive_right_, 1.);
108 lambda_right_plus_ = lambda(p_star_, primitive_right_, 1.);
112 std::cout <<
"lambda_left_minus = " << lambda_left_minus_
113 <<
"\nlambda_left_plus = " << lambda_left_plus_
114 <<
"\nlambda_right_minus = " << lambda_right_minus_
115 <<
"\nlambda_right_plus = " << lambda_right_plus_
120 this->parse_parameters_call_back.connect(prepare_riemann_data);
121 prepare_riemann_data();
127 const auto view = hyperbolic_system_.template view<dim, Number>();
129 const double &x = point[0];
131 const Number xi = x / t;
133 dealii::Tensor<1, 3, Number> primitive_state;
135 if (t < 1.e-14 && x < 0.) {
136 primitive_state = primitive_left_;
138 std::cout <<
"Left primitive state: " << primitive_state << std::endl;
141 }
else if (t < 1.e-14 && x > 0.) {
142 primitive_state = primitive_right_;
144 std::cout <<
"Right primitive state: " << primitive_state
148 }
else if (xi < lambda_left_minus_) {
150 primitive_state = primitive_left_;
152 std::cout <<
"Left primitive state: " << primitive_state << std::endl;
155 }
else if (xi < lambda_left_plus_) {
157 expansion_solution(p_star_, xi, primitive_left_, -1.);
158 primitive_state = c_LL;
160 std::cout <<
"Left expansion state: " << primitive_state << std::endl;
163 }
else if (xi < u_star_) {
164 primitive_state = cstar_solution(p_star_, u_star_, primitive_left_);
166 const Number p_L = primitive_left_[2];
168 primitive_state = expansion_solution(
169 p_star_, lambda_left_plus_, primitive_left_, -1.);
171 std::cout <<
"Left cstar state: " << primitive_state << std::endl;
174 }
else if (xi < lambda_right_minus_) {
175 primitive_state = cstar_solution(p_star_, u_star_, primitive_right_);
177 const Number p_R = primitive_right_[2];
179 primitive_state = expansion_solution(
180 p_star_, lambda_right_minus_, primitive_right_, 1.);
182 std::cout <<
"Right cstar state: " << primitive_state << std::endl;
185 }
else if (xi < lambda_right_plus_) {
187 expansion_solution(p_star_, xi, primitive_right_, 1.);
189 std::cout <<
"Right expansion state: " << primitive_state
195 primitive_state = primitive_right_;
197 std::cout <<
"Right primitive state: " << primitive_state
202 using state_type_1d =
204 static_assert(state_type_1d::dimension <=
205 dealii::Tensor<1, 3, Number>::dimension);
207 state_type_1d result;
208 for (
unsigned int i = 0; i < state_type_1d::dimension; ++i)
209 result[i] = primitive_state[i];
210 return view.from_initial_state(result);
222 dealii::Tensor<1, 3, Number> primitive_left_;
223 dealii::Tensor<1, 3, Number> primitive_right_;
235 Number lambda_left_minus_;
236 Number lambda_left_plus_;
237 Number lambda_right_minus_;
238 Number lambda_right_plus_;
246 Number fZofP(
const Number &p_in,
247 const dealii::Tensor<1, 3, Number> &data_in)
const
250 const Number rho_Z = data_in[0];
251 const Number p_Z = data_in[2];
253 const Number c_Z = std::sqrt(gamma_ * p_Z / rho_Z);
255 const Number A_Z = 2. / (gamma_ + 1.) / rho_Z;
256 const Number B_Z = (gamma_ - 1.) / (gamma_ + 1.) * p_Z;
258 const Number exp = 0.5 * (gamma_ - 1.) / gamma_;
259 Number left_brach = 2. * c_Z / (gamma_ - 1.);
260 left_brach *= (std::pow(p_in / p_Z, exp) - 1.);
262 Number f_of_p = (p_in - p_Z) * std::sqrt(A_Z / (p_in + B_Z));
271 Number dfZofP(
const Number &p_in,
272 const dealii::Tensor<1, 3, Number> &data_in)
const
275 const Number rho_Z = data_in[0];
276 const Number p_Z = data_in[2];
278 const Number c_Z = std::sqrt(gamma_ * p_Z / rho_Z);
280 const Number A_Z = 2. / (gamma_ + 1.) / rho_Z;
281 const Number B_Z = (gamma_ - 1.) / (gamma_ + 1.) * p_Z;
283 Number exp = 0.5 * (gamma_ - 1.) / gamma_;
284 Number left_brach = 2. * c_Z / (gamma_ - 1.) * exp;
287 left_brach *= std::pow(p_in / p_Z, exp - 1.) / p_Z;
289 Number right_branch = std::pow(A_Z / (p_in + B_Z), 1.5);
290 right_branch *= (2. * B_Z + p_in + p_Z) / (2. * A_Z);
292 Number df_of_p = right_branch;
295 df_of_p = left_brach;
301 Number dphi(
const Number &p_in,
302 const dealii::Tensor<1, 3, Number> &data_left,
303 const dealii::Tensor<1, 3, Number> &data_right)
const
305 return dfZofP(p_in, data_left) + dfZofP(p_in, data_right);
309 Number phi(
const Number &p_in,
310 const dealii::Tensor<1, 3, Number> &data_left,
311 const dealii::Tensor<1, 3, Number> &data_right)
const
313 const Number u_L = data_left[1];
314 const Number u_R = data_right[1];
316 return fZofP(p_in, data_right) + fZofP(p_in, data_left) + u_R - u_L;
320 Number lambda(
const Number &p_in,
321 const dealii::Tensor<1, 3, Number> &data_in,
322 const Number &sign)
const
325 const Number rho_Z = data_in[0];
326 const Number u_Z = data_in[1];
327 const Number p_Z = data_in[2];
329 const Number c_Z = std::sqrt(gamma_ * p_Z / rho_Z);
331 const Number radicand =
332 1. + 0.5 * (gamma_ + 1.) / gamma_ * std::max(p_in / p_Z - 1., 0.);
334 return u_Z + sign * c_Z * std::sqrt(radicand);
338 Number lambda_intermediate(
const Number &p_in,
339 const dealii::Tensor<1, 3, Number> &data_in,
340 const Number &sign)
const
342 const Number rho_Z = data_in[0];
343 const Number u_Z = data_in[1];
344 const Number p_Z = data_in[2];
346 const Number c_Z = std::sqrt(gamma_ * p_Z / rho_Z);
348 const auto lambda_value = lambda(p_in, data_in, sign);
350 const Number f_of_p = fZofP(p_in, data_in);
352 const Number exp = 0.5 * (gamma_ - 1.) / gamma_;
353 const Number expansion_speed =
354 u_Z + sign * (f_of_p + c_Z * std::pow(p_in / p_Z, exp));
356 Number result = lambda_value;
358 result = expansion_speed;
364 dealii::Tensor<1, 3, Number>
365 cstar_solution(
const Number &p_star,
366 const Number &u_star,
367 const dealii::Tensor<1, 3, Number> &data_in)
const
369 const Number rho_Z = data_in[0];
370 const Number p_Z = data_in[2];
373 const Number p_ratio = p_star / p_Z;
374 const Number gamma_ratio = (gamma_ - 1.) / (gamma_ + 1.);
376 const Number numerator = rho_Z * (p_ratio + gamma_ratio);
377 const Number denominator = gamma_ratio * p_ratio + 1.;
379 Number rho_star = numerator / denominator;
381 auto result = data_in;
382 result[0] = rho_star;
390 dealii::Tensor<1, 3, Number>
391 expansion_solution(
const Number & ,
393 const dealii::Tensor<1, 3, Number> &data_in,
394 const Number &sign)
const
396 const Number rho_Z = data_in[0];
397 const Number u_Z = data_in[1];
398 const Number p_Z = data_in[2];
400 const Number c_Z = std::sqrt(gamma_ * p_Z / rho_Z);
403 const Number gamma_ratio = (gamma_ - 1.) / (gamma_ + 1.);
405 const Number first = 2. / (gamma_ + 1.);
406 const Number second = gamma_ratio / c_Z * (u_Z - xi);
407 const Number exp = 2. / (gamma_ - 1.);
409 Number rho_expansion = rho_Z * std::pow(first - sign * second, exp);
412 const Number factor = p_Z / std::pow(rho_Z, gamma_);
413 const Number p_expansion = factor * std::pow(rho_expansion, gamma_);
416 const Number u_expansion = u_Z + sign * fZofP(p_expansion, data_in);
418 auto result = data_in;
419 result[0] = rho_expansion;
420 result[1] = u_expansion;
421 result[2] = p_expansion;
430 double compute_pstar(
double p_1,
432 dealii::Tensor<1, 3, Number> data_1,
433 dealii::Tensor<1, 3, Number> data_2)
435 constexpr Number eps = std::numeric_limits<Number>::epsilon();
441 std::swap(data_1, data_2);
446 const double phi_1 = phi(p_1, data_1, data_2);
447 const double phi_2 = phi(p_2, data_1, data_2);
448 Assert(phi_1 * phi_2 <= 0.,
450 "Euler::ExactRiemannSolver: failed to compute p_star."));
461 std::cout <<
"Computing p_star with a bisection method." << std::endl;
464 unsigned int iter = 0;
465 for (; iter < 200; ++iter) {
468 if (std::abs(p_2 - p_1) < 10. * eps * std::max(p_1, p_2)) {
472 const double phi_2 = phi(p_2, data_1, data_2);
475 const double phi_1 = phi(p_1, data_1, data_2);
477 std::cout <<
"\niter: " << iter <<
"\n";
478 std::cout <<
"p_1: " << p_1 <<
"\n";
479 std::cout <<
"p_2: " << p_2 <<
"\n";
480 std::cout <<
"phi_1: " << phi_1 <<
"\n";
481 std::cout <<
"phi_2: " << phi_2 <<
"\n";
484 const auto p_m = 0.5 * (p_2 + p_1);
485 const double phi_m = phi(p_m, data_1, data_2);
487 if (phi_m * phi_2 >= 0.) {
495 const double phi_2 = phi(p_2, data_1, data_2);
496 std::cout <<
"After " << iter <<
" iterations:"
497 <<
"\np_star = " << p_2 <<
"\nphi(p_star) = " << phi_2
498 <<
"\n|p_2 - p_1| = " << std::abs(p_2 - p_1) << std::endl;