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