include/meltpooldg/compressible_flow/convective_kernels.hpp Source File

Developer Documentation: include/meltpooldg/compressible_flow/convective_kernels.hpp Source File
Developer Documentation
convective_kernels.hpp
Go to the documentation of this file.
1
5#pragma once
6
7#include <deal.II/base/config.h>
8
9#include <deal.II/base/exceptions.h>
10#include <deal.II/base/tensor.h>
11#include <deal.II/base/vectorization.h>
12
19
20#include <algorithm>
21#include <cmath>
22#include <utility>
23
24
26{
37 template <int dim, typename number>
39 {
42
51
59 inline DEAL_II_ALWAYS_INLINE //
61 calculate_convective_flux(const ConservedVariables &conserved_variables) const;
62
72 inline DEAL_II_ALWAYS_INLINE //
75 const ConservedVariables &u_m,
76 const ConservedVariables &u_p,
77 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal) const;
78
89 inline DEAL_II_ALWAYS_INLINE //
92 const std::pair<ConservedVariables, ConservedVariables> &w_q,
93 const std::pair<ConservedVariables, ConservedVariables> &delta_w_q,
94 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal) const;
95
105 inline DEAL_II_ALWAYS_INLINE //
108 const ConservedVariables &delta_w_q) const;
109
110 private:
113
116
118 number rs_div_c;
119
134 const std::pair<ConservedVariables, ConservedVariables> &w_q,
135 const std::pair<ConservedVariables, ConservedVariables> &delta_w_q,
136 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal) const;
137 };
138
139 /********************************************************************************************
140 * Inlined function definitions
141 * *************************************************************************************+****/
142 template <int dim, typename number>
144 const Material<dim, number> &material_in)
145 : flow_data(flow_data_in)
146 , material(material_in)
147 {
148 // Currently, only relevant for the single phase (gas) solver
149 rs_div_c = material.data.gamma - 1.0;
150 }
151
152 template <int dim, typename number>
153 inline DEAL_II_ALWAYS_INLINE //
154 auto
156 const ConservedVariables &conserved_variables) const -> ConservedVariablesGradient
157 {
158 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> velocity =
159 calculate_velocity<dim, number>(conserved_variables);
160 const dealii::VectorizedArray<number> pressure =
161 material.eos_utils->calculate_thermodynamic_pressure(conserved_variables);
162
164 for (unsigned int d = 0; d < dim; ++d)
165 {
166 flux[0][d] = conserved_variables[1 + d];
167 for (unsigned int e = 0; e < dim; ++e)
168 flux[e + 1][d] = conserved_variables[e + 1] * velocity[d];
169 flux[d + 1][d] += pressure;
170 flux[dim + 1][d] = velocity[d] * (conserved_variables[dim + 1] + pressure);
171 }
172 return flux;
173 }
174
175 template <int dim, typename number>
176 inline DEAL_II_ALWAYS_INLINE //
177 auto
179 const ConservedVariables &u_m,
180 const ConservedVariables &u_p,
181 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal) const
183 {
184 const auto velocity_m = calculate_velocity<dim, number>(u_m);
185 const auto velocity_p = calculate_velocity<dim, number>(u_p);
186
187 const auto flux_m = calculate_convective_flux(u_m);
188 const auto flux_p = calculate_convective_flux(u_p);
189
190 const auto sound_speed_p = material.eos_utils->calculate_speed_of_sound(u_p);
191 const auto sound_speed_m = material.eos_utils->calculate_speed_of_sound(u_m);
192
193 switch (flow_data.numerical_flux_type)
194 {
195 case NumericalFluxType::lax_friedrichs_modified: {
196 const auto sound_speed_p2 = sound_speed_p * sound_speed_p;
197 const auto sound_speed_m2 = sound_speed_m * sound_speed_m;
198
199 const auto lambda =
200 0.5 * std::sqrt(std::max(velocity_p.norm_square() + sound_speed_p2,
201 velocity_m.norm_square() + sound_speed_m2));
202
203 return contract_average_tensor_with_vector<n_conserved_variables<dim>,
204 dim,
205 dealii::VectorizedArray<number>>(flux_m,
206 flux_p,
207 normal) +
208 0.5 * lambda * (u_m - u_p);
209 }
210 case NumericalFluxType::lax_friedrichs_exact: {
211 const auto lambda = std::max(std::abs(velocity_p * normal) + sound_speed_p,
212 std::abs(velocity_m * normal) + sound_speed_m);
213
214 return contract_average_tensor_with_vector<n_conserved_variables<dim>,
215 dim,
216 dealii::VectorizedArray<number>>(flux_m,
217 flux_p,
218 normal) +
219 0.5 * lambda * (u_m - u_p);
220 }
221 case NumericalFluxType::harten_lax_vanleer: {
222 const auto avg_velocity_normal = 0.5 * ((velocity_m + velocity_p) * normal);
223 const auto avg_c = std::abs(0.5 * (sound_speed_m + sound_speed_p));
224 const dealii::VectorizedArray<number> s_pos =
225 std::max(dealii::VectorizedArray<number>(), avg_velocity_normal + avg_c);
226 const dealii::VectorizedArray<number> s_neg =
227 std::min(dealii::VectorizedArray<number>(), avg_velocity_normal - avg_c);
228 const dealii::VectorizedArray<number> inverse_s =
229 dealii::VectorizedArray<number>(1.) / (s_pos - s_neg);
230
231 return inverse_s *
232 (s_pos *
233 contract_tensor_with_vector<n_conserved_variables<dim>, dim, number>(flux_m,
234 normal) -
235 s_neg *
236 contract_tensor_with_vector<n_conserved_variables<dim>, dim, number>(flux_p,
237 normal) -
238 s_pos * s_neg * (u_m - u_p));
239 }
240 default: {
241 Assert(false, dealii::ExcNotImplemented());
242 return {};
243 }
244 }
245 }
246
247 template <int dim, typename number>
248 inline DEAL_II_ALWAYS_INLINE //
249 auto
251 const std::pair<ConservedVariables, ConservedVariables> &w_q,
252 const std::pair<ConservedVariables, ConservedVariables> &delta_w_q,
253 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal) const
255 {
256 // For now only the exact and modified Lax-Friedrichs flux are supported
257 AssertThrow(flow_data.numerical_flux_type == NumericalFluxType::lax_friedrichs_exact or
258 flow_data.numerical_flux_type == NumericalFluxType::lax_friedrichs_modified,
259 dealii::ExcMessage(
260 "The chosen convective numerical flux type is not supported within the "
261 "analytic Jacobian computation."));
262
263 // average
265 calculate_jacobian_convective_flux(w_q.second, delta_w_q.second);
267 calculate_jacobian_convective_flux(w_q.first, delta_w_q.first);
268
270 for (unsigned int i = 0; i < n_conserved_variables<dim>; ++i)
271 flux[i] = 0.5 * (flux_p[i] + flux_m[i]);
272
273 flux += calculate_jacobian_convective_numerical_flux_jump_term(w_q, delta_w_q, normal);
274
275 return flux;
276 }
277
278 template <int dim, typename number>
279 inline DEAL_II_ALWAYS_INLINE //
280 auto
282 const ConservedVariables &w_q,
283 const ConservedVariables &delta_w_q) const -> ConservedVariablesGradient
284 {
285 ConservedVariablesGradient convective_differential_change;
286
287 // precompute values
288 dealii::VectorizedArray<number> rho_inv = 1.0 / w_q[0];
289 dealii::VectorizedArray<number> momentum_norm_squared = 0.0;
290 dealii::VectorizedArray<number> momentum_times_delta_momentum_squared = 0.0;
291 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> momentum;
292 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> delta_momentum;
293 for (unsigned int i = 1; i < dim + 1; ++i)
294 {
295 momentum_norm_squared += w_q[i] * w_q[i];
296 momentum_times_delta_momentum_squared += delta_w_q[i] * w_q[i];
297 momentum[i - 1] = w_q[i];
298 delta_momentum[i - 1] = delta_w_q[i];
299 }
300
301 //** change in density flux **//
302 for (unsigned int dimension = 0; dimension < dim; ++dimension)
303 convective_differential_change[0][dimension] = delta_w_q[dimension + 1];
304
305 //** change in momentum flux **//
306 dealii::Tensor<1, dim, dealii::Tensor<1, dim, dealii::VectorizedArray<number>>> helper;
307 // density direction
308 helper -= rho_inv * rho_inv * delta_w_q[0] *
309 dyadic_product<dim, dim, dealii::VectorizedArray<number>>(&w_q[1], &w_q[1]);
310 helper += rho_inv * rho_inv * rs_div_c * momentum_norm_squared * delta_w_q[0] * 0.5 *
311 identity<dim, dealii::VectorizedArray<number>>();
312 // momentum direction
313 helper +=
314 rho_inv * dyadic_product<dim, dim, dealii::VectorizedArray<number>>(&delta_w_q[1], &w_q[1]);
315 helper +=
316 rho_inv * dyadic_product<dim, dim, dealii::VectorizedArray<number>>(&w_q[1], &delta_w_q[1]);
317 helper -= rs_div_c * rho_inv * momentum_times_delta_momentum_squared *
318 identity<dim, dealii::VectorizedArray<number>>();
319 // energy direction
320 helper += rs_div_c * delta_w_q[dim + 1] * identity<dim, dealii::VectorizedArray<number>>();
321
322 for (unsigned int i = 0; i < dim; ++i)
323 {
324 convective_differential_change[i + 1] += helper[i];
325 }
326
327 //** change in energy density flux **//
328 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> helper_energy;
329 // density part
330 helper_energy -= (w_q[dim + 1] + rs_div_c * (w_q[dim + 1] - rho_inv * momentum_norm_squared)) *
331 rho_inv * rho_inv * delta_w_q[0] * momentum;
332 // momentum part
333 helper_energy +=
334 (w_q[dim + 1] + rs_div_c * (w_q[dim + 1] - 0.5 * rho_inv * momentum_norm_squared)) * rho_inv *
335 delta_momentum;
336 helper_energy -=
337 rs_div_c * momentum_times_delta_momentum_squared * rho_inv * rho_inv * momentum;
338 // energy part
339 helper_energy += (1 + rs_div_c) * delta_w_q[dim + 1] * rho_inv * momentum;
340 convective_differential_change[dim + 1] = helper_energy;
341
342 return convective_differential_change;
343 }
344
345 template <int dim, typename number>
346 inline DEAL_II_ALWAYS_INLINE //
347 auto
349 const std::pair<ConservedVariables, ConservedVariables> &w_q,
350 const std::pair<ConservedVariables, ConservedVariables> &delta_w_q,
351 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal) const
353 {
354 // define aliases
355 const ConservedVariables &w_m = w_q.first;
356 const ConservedVariables &w_p = w_q.second;
357 const ConservedVariables &delta_w_m = delta_w_q.first;
358 const ConservedVariables &delta_w_p = delta_w_q.second;
359 // jump
360 std::function<
362 const ConservedVariables &,
363 const ConservedVariables &,
364 const ConservedVariables &,
365 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &)>
366 compute_lambda_times_jump;
368
369 switch (flow_data.numerical_flux_type)
370 {
371 case NumericalFluxType::lax_friedrichs_exact: {
372 compute_lambda_times_jump =
373 [&material =
374 material](const ConservedVariables &w_p,
375 const ConservedVariables &w_m,
376 const ConservedVariables &delta_w_p,
377 const ConservedVariables &delta_w_m,
378 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal)
380 const auto velocity_m = calculate_velocity<dim, number>(w_m);
381 const auto velocity_p = calculate_velocity<dim, number>(w_p);
382
383 const auto lambda = std::max(std::abs(velocity_p * normal) +
384 material.eos_utils->calculate_speed_of_sound(w_p),
385 std::abs(velocity_m * normal) +
386 material.eos_utils->calculate_speed_of_sound(w_m));
387 return lambda * (delta_w_m - delta_w_p);
388 };
389 break;
390 }
391 case NumericalFluxType::lax_friedrichs_modified: {
392 compute_lambda_times_jump =
393 [this](const ConservedVariables &w_p,
394 const ConservedVariables &w_m,
395 const ConservedVariables &delta_w_p,
396 const ConservedVariables &delta_w_m,
397 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &)
399 const auto velocity_m = calculate_velocity<dim, number>(w_m);
400 const auto velocity_p = calculate_velocity<dim, number>(w_p);
401
402 const auto pressure_m = material.eos_utils->calculate_thermodynamic_pressure(w_m);
403 const auto pressure_p = material.eos_utils->calculate_thermodynamic_pressure(w_p);
404
405 const auto lambda =
406 0.5 * std::sqrt(std::max(velocity_p.norm_square() +
407 std::abs(material.data.gamma * pressure_p / w_p[0]),
408 velocity_m.norm_square() +
409 std::abs(material.data.gamma * pressure_m / w_m[0])));
410 return lambda * (delta_w_m - delta_w_p);
411 };
412 break;
413 }
414 default:
415 DEAL_II_ASSERT_UNREACHABLE();
416 }
417
418 // We do not ue the square root of machine precision here as this prevents the Newton solver to
419 // convergence
420 constexpr number epsilon = 1e-3;
421 constexpr number epsilon_inv = 1e3;
422 switch (flow_data.linearization_jump_convective_flux)
423 {
424 case LinearizedConvectiveFluxJumpType::complete_fd: {
425 flux -= dyadic_product(0.5 * epsilon_inv *
426 compute_lambda_times_jump(w_p, w_m, w_p, w_m, normal),
427 normal);
428 flux += dyadic_product(0.5 * epsilon_inv *
429 compute_lambda_times_jump(w_p + epsilon * delta_w_p,
430 w_m + epsilon * delta_w_m,
431 w_p + epsilon * delta_w_p,
432 w_m + epsilon * delta_w_m,
433 normal),
434 normal);
435 break;
436 }
437 case LinearizedConvectiveFluxJumpType::lambda_fd: {
438 flux += dyadic_product(
439 0.5 * compute_lambda_times_jump(w_p, w_m, delta_w_p, delta_w_m, normal), normal);
440
441 auto helper = compute_lambda_times_jump(
442 w_p + epsilon * delta_w_p, w_m + epsilon * delta_w_m, w_p, w_m, normal);
443 helper -= compute_lambda_times_jump(w_p, w_m, w_p, w_m, normal);
444 flux += dyadic_product(0.5 / epsilon * helper, normal);
445 break;
446 }
447 case LinearizedConvectiveFluxJumpType::analytic: {
448 flux += dyadic_product(
449 0.5 * compute_lambda_times_jump(w_p, w_m, delta_w_p, delta_w_m, normal), normal);
450
451 const auto linearize_speed_of_sound =
452 [this](const ConservedVariables &w_q,
453 const ConservedVariables &delta_w_q,
454 const dealii::VectorizedArray<number> &c,
455 const dealii::VectorizedArray<number> &) -> dealii::VectorizedArray<number> {
456 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> m_q;
457 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> delta_m_q;
458 for (unsigned int i = 0; i < dim; ++i)
459 {
460 m_q[i] = w_q[i + 1];
461 delta_m_q[i] = delta_w_q[i + 1];
462 }
463 dealii::VectorizedArray<number> rho_inv = 1. / w_q[0];
464 dealii::VectorizedArray<number> lin_c =
465 delta_w_q[0] / (2.0 * c) * material.data.gamma * rho_inv * rho_inv * rs_div_c *
466 (rho_inv * m_q * m_q - w_q[dim + 1]);
467 lin_c -=
468 material.data.gamma / (2.0 * c) * rho_inv * rho_inv * rs_div_c * m_q * delta_m_q;
469 lin_c += material.data.gamma / (2.0 * c) * rho_inv * rs_div_c * delta_w_q[dim + 1];
470 return lin_c;
471 };
472
473 const auto norm_lin_velocity =
474 [this](const ConservedVariables &w_q,
475 const ConservedVariables &delta_w_q,
476 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal)
477 -> dealii::VectorizedArray<number> {
478 auto rho_inv = 1. / w_q[dim + 1];
479 auto u = calculate_velocity<dim, number>(w_q);
480 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> delta_m_q;
481 for (unsigned int i = 0; i < dim; ++i)
482 delta_m_q[i] = delta_w_q[i + 1];
483 auto lin_velocity = delta_m_q * rho_inv - u * rho_inv * delta_w_q[0];
484 return lin_velocity * normal;
485 };
486
487 const auto signum =
488 [](
489 const dealii::VectorizedArray<number> &a) -> const dealii::VectorizedArray<number> {
490 return dealii::compare_and_apply_mask<dealii::SIMDComparison::greater_than>(
491 a, dealii::VectorizedArray<number>(0.0), 1.0, -1.0);
492 };
493
494 const auto velocity_m = calculate_velocity<dim, number>(w_m);
495 const auto velocity_p = calculate_velocity<dim, number>(w_p);
496
497 const auto pressure_m = material.eos_utils->calculate_thermodynamic_pressure(w_m);
498 const auto pressure_p = material.eos_utils->calculate_thermodynamic_pressure(w_p);
499
500 const auto speed_of_sound_m = material.eos_utils->calculate_speed_of_sound(w_m);
501 const auto speed_of_sound_p = material.eos_utils->calculate_speed_of_sound(w_p);
502
503 const auto lin_lambda_p =
504 signum(velocity_p * normal) * norm_lin_velocity(w_p, delta_w_p, normal) +
505 linearize_speed_of_sound(w_p, delta_w_p, speed_of_sound_p, pressure_p);
506 const auto lin_lambda_m =
507 signum(velocity_m * normal) * norm_lin_velocity(w_m, delta_w_m, normal) +
508 linearize_speed_of_sound(w_m, delta_w_m, speed_of_sound_m, pressure_m);
509
510 const auto lin_lambda =
511 dealii::compare_and_apply_mask<dealii::SIMDComparison::greater_than>(
512 velocity_p.norm() + speed_of_sound_p,
513 velocity_m.norm() + speed_of_sound_m,
514 lin_lambda_p,
515 lin_lambda_m);
516
517 for (unsigned int i = 0; i < n_conserved_variables<dim>; ++i)
518 flux[i] += 0.5 * lin_lambda * (w_m[i] - w_p[i]) * normal;
519
520 break;
521 }
522 default: {
523 AssertThrow(
524 false,
525 dealii::ExcMessage(
526 "The provided linearization scheme of the jump operator term in the convective"
527 " numerical flux is not supported."));
528 }
529 }
530 return flux;
531 }
532} // namespace MeltPoolDG::CompressibleFlow
A class which provides all relevant material properties for a specific phase.
Definition material_data.hpp:18
This file contains various functions that can be used to set and evaluate boundary conditions for the...
Definition boundary_condition_functions.hpp:17
dealii::Tensor< 1, n_conserved_variables< dim, n_species >, dealii::Tensor< 1, dim, VectorizedArrayType > > ConservedVariablesGradientType
Definition data_types.hpp:44
dealii::Tensor< 1, n_conserved_variables< dim, n_species >, VectorizedArrayType > ConservedVariablesType
Definition data_types.hpp:35
dealii::Tensor< 1, T1_dim, dealii::Tensor< 1, T2_dim, number > > dyadic_product(const number *a_start, const number *b_start)
Definition dealii_tensor.hpp:203
dealii::Tensor< 1, dim_1, dealii::VectorizedArray< number > > contract_tensor_with_vector(const dealii::Tensor< 1, dim_1, dealii::Tensor< 1, dim_2, dealii::VectorizedArray< number > > > &tensor, const dealii::Tensor< 1, dim_2, dealii::VectorizedArray< number > > &vector)
Definition dealii_tensor.hpp:120
Convective kernel operations for compressible flow solvers.
Definition convective_kernels.hpp:39
DEAL_II_ALWAYS_INLINE ConservedVariablesGradient calculate_convective_flux(const ConservedVariables &conserved_variables) const
Calculate the convective flux F_c.
Definition convective_kernels.hpp:155
ConservedVariablesGradient calculate_jacobian_convective_numerical_flux_jump_term(const std::pair< ConservedVariables, ConservedVariables > &w_q, const std::pair< ConservedVariables, ConservedVariables > &delta_w_q, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal) const
Compute the jump term in the convective numerical flux.
Definition convective_kernels.hpp:348
DEAL_II_ALWAYS_INLINE ConservedVariablesGradient calculate_jacobian_convective_flux(const ConservedVariables &w_q, const ConservedVariables &delta_w_q) const
Compute the linearization of the convective flux with respect to the primary variables.
Definition convective_kernels.hpp:281
DEAL_II_ALWAYS_INLINE ConservedVariablesGradient calculate_jacobian_convective_numerical_flux(const std::pair< ConservedVariables, ConservedVariables > &w_q, const std::pair< ConservedVariables, ConservedVariables > &delta_w_q, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal) const
Compute the linearization of the convective numerical flux with respect to the primary variables.
Definition convective_kernels.hpp:250
const OperationData< number > & flow_data
Flow-related parameters.
Definition convective_kernels.hpp:112
ConservedVariablesGradientType< dim, number > ConservedVariablesGradient
Definition convective_kernels.hpp:41
ConvectiveKernels(const OperationData< number > &flow_data, const Material< dim, number > &material)
Constructor initializing the convective kernel with flow and material properties.
Definition convective_kernels.hpp:143
DEAL_II_ALWAYS_INLINE ConservedVariables calculate_convective_numerical_flux(const ConservedVariables &u_m, const ConservedVariables &u_p, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal) const
Calculate the convective numerical flux F_c^*.
Definition convective_kernels.hpp:178
number rs_div_c
precomputed constant
Definition convective_kernels.hpp:118
const Material< dim, number > & material
Material-related parameters.
Definition convective_kernels.hpp:115
ConservedVariablesType< dim, number > ConservedVariables
Definition convective_kernels.hpp:40
Collection of parameters required by the compressible Navier-Stokes operator.
Definition operation_data.hpp:35