include/meltpooldg/compressible_flow/multiphase_interface_kernels.hpp Source File

Developer Documentation: include/meltpooldg/compressible_flow/multiphase_interface_kernels.hpp Source File
Developer Documentation
multiphase_interface_kernels.hpp
Go to the documentation of this file.
1
15#pragma once
16
17#include <deal.II/base/tensor.h>
18#include <deal.II/base/vectorization.h>
19
26
27#include <tuple>
28#include <utility>
29
31{
35
58 template <int dim,
59 typename number,
60 typename ConservedVariablesType,
61 typename ConservedVariablesGradType>
62 inline DEAL_II_ALWAYS_INLINE //
63 std::pair<ConservedVariablesType, ConservedVariablesType>
65 const ConservedVariablesType &u_liquid,
66 const ConservedVariablesType &u_gas,
67 const ConservedVariablesGradType &grad_u_liquid,
68 const ConservedVariablesGradType &grad_u_gas,
70 const number &m_dot_evap,
71 const number &laser_heat_source)
72 {
73 AssertThrow(dim == 1,
74 dealii::ExcNotImplemented(
75 "Currently, only dim=1 is enabled for "
76 "enforcing interface jump conditions with the penalty method."));
77
78 // enumeration for conserved variables component indices
79 using Idx = std::conditional_t<
80 dim == 1,
81 CompressibleFlow::Idx1D,
82 std::conditional_t<dim == 2,
83 CompressibleFlow::Idx2D,
84 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
85
86 ConservedVariablesType total_flux_liquid;
87 ConservedVariablesType total_flux_gas;
88
89 // TODO: investigate weighting factors!
90 const dealii::VectorizedArray<number> omega_mass_1 = 0.5;
91 const dealii::VectorizedArray<number> omega_mass_2 = 1. - omega_mass_1;
92
94 // mass conservation //
96
97 const dealii::VectorizedArray<number> interface_mass_flux_conservation_term =
98 (u_liquid[Idx::density] / u_gas[Idx::density] * u_gas[Idx::momentum_x] -
99 u_gas[Idx::density] / u_liquid[Idx::density] * u_liquid[Idx::momentum_x] +
100 (u_gas[Idx::density] * u_gas[Idx::density] -
101 u_liquid[Idx::density] * u_liquid[Idx::density]) /
102 (u_liquid[Idx::density] * u_gas[Idx::density]) * m_dot_evap);
103
104 total_flux_liquid[Idx::density] = omega_mass_1 * interface_mass_flux_conservation_term;
105 total_flux_gas[Idx::density] = omega_mass_2 * interface_mass_flux_conservation_term;
106
107 const dealii::VectorizedArray<number> weighted_average_momentum =
109 u_gas[Idx::momentum_x],
110 omega_mass_2,
111 u_liquid[Idx::momentum_x]);
112
113 total_flux_liquid[Idx::density] += weighted_average_momentum;
114 total_flux_gas[Idx::density] -= weighted_average_momentum;
115
116 // penalty approach for density constraint in gas phase
117 // TODO: compute target density in gas phase from Hertz-Knudsen theory
118 const dealii::VectorizedArray<number> penalty_gas_density =
119 multiphase_scratch_data.phase_coupling.penalty.coefficients.density *
120 (u_gas[Idx::density] -
121 multiphase_scratch_data.phase_coupling.penalty.target_values.density_gas_phase);
122
123 total_flux_gas[Idx::density] += penalty_gas_density;
124
126 // momentum conservation //
128
129 // TODO: investigate weighting factors!
130 const dealii::VectorizedArray<number> omega_mom_1_conv = 0.5;
131 const dealii::VectorizedArray<number> omega_mom_2_conv = 1. - omega_mom_1_conv;
132
133 const dealii::VectorizedArray<number> omega_mom_1_visc =
134 multiphase_scratch_data.material_liquid.data.dynamic_viscosity /
135 (multiphase_scratch_data.material_liquid.data.dynamic_viscosity +
136 multiphase_scratch_data.material_gas.data.dynamic_viscosity);
137 const dealii::VectorizedArray<number> omega_mom_2_visc = 1. - omega_mom_1_visc;
138
139 // compute stress tensor (pressure and viscous contributions) and convert to type
140 // dealii::VectorizedArray<number>
141 const auto grad_vel_liquid =
142 CompressibleFlow::calculate_grad_velocity<dim, number>(u_liquid, grad_u_liquid);
143 const auto grad_vel_gas =
144 CompressibleFlow::calculate_grad_velocity<dim, number>(u_gas, grad_u_gas);
145
146 const dealii::Tensor<2, dim, dealii::VectorizedArray<number>> viscous_stress_tensor_liquid =
147 CompressibleFlow::viscous_stress_tensor<dim, number>(
148 grad_vel_liquid, multiphase_scratch_data.material_liquid.data.dynamic_viscosity);
149 const dealii::Tensor<2, dim, dealii::VectorizedArray<number>> viscous_stress_tensor_gas =
150 CompressibleFlow::viscous_stress_tensor<dim, number>(
151 grad_vel_gas, multiphase_scratch_data.material_gas.data.dynamic_viscosity);
152
153 const dealii::VectorizedArray<number> stress_tensor_liquid =
154 multiphase_scratch_data.material_liquid.eos_utils->calculate_stress_tensor(
155 u_liquid, viscous_stress_tensor_liquid)[0][0];
156 const dealii::VectorizedArray<number> stress_tensor_gas =
157 multiphase_scratch_data.material_gas.eos_utils->calculate_stress_tensor(
158 u_gas, viscous_stress_tensor_gas)[0][0];
159
160 const dealii::VectorizedArray<number> jump_momentum_term_liquid =
161 u_liquid[Idx::momentum_x] * u_liquid[Idx::momentum_x] / u_liquid[Idx::density];
162 const dealii::VectorizedArray<number> jump_momentum_term_gas =
163 u_gas[Idx::momentum_x] * u_gas[Idx::momentum_x] / u_gas[Idx::density];
164
165 total_flux_liquid[Idx::momentum_x] +=
166 omega_mom_1_conv * (jump_momentum_term_liquid - jump_momentum_term_gas);
167 total_flux_gas[Idx::momentum_x] +=
168 omega_mom_2_conv * (jump_momentum_term_liquid - jump_momentum_term_gas);
169
170 const dealii::VectorizedArray<number> average_momentum_term_1 =
172 jump_momentum_term_liquid,
173 omega_mom_1_conv,
174 jump_momentum_term_gas);
175
176 total_flux_liquid[Idx::momentum_x] += average_momentum_term_1;
177 total_flux_gas[Idx::momentum_x] -= average_momentum_term_1;
178
179 const dealii::VectorizedArray<number> jump_momentum_term_2 =
180 -(u_liquid[Idx::momentum_x] / u_liquid[Idx::density] -
181 u_gas[Idx::momentum_x] / u_gas[Idx::density]) *
182 m_dot_evap;
183
184 const dealii::VectorizedArray<number> average_momentum_term_2 =
186 -stress_tensor_liquid,
187 omega_mom_1_visc,
188 -stress_tensor_gas);
189
190 total_flux_liquid[Idx::momentum_x] +=
191 jump_momentum_term_2 * omega_mom_1_visc + average_momentum_term_2;
192 total_flux_gas[Idx::momentum_x] +=
193 jump_momentum_term_2 * omega_mom_2_visc - average_momentum_term_2;
194
196 // energy conservation //
198
199 // TODO: investigate weighting factors!
200 const dealii::VectorizedArray<number> omega_energy_1_conv = 0.5;
201 const dealii::VectorizedArray<number> omega_energy_2_conv = 1. - omega_energy_1_conv;
202
203 const dealii::VectorizedArray<number> omega_energy_1_visc =
204 multiphase_scratch_data.material_liquid.data.dynamic_viscosity /
205 (multiphase_scratch_data.material_liquid.data.dynamic_viscosity +
206 multiphase_scratch_data.material_gas.data.dynamic_viscosity);
207 const dealii::VectorizedArray<number> omega_energy_2_visc = 1. - omega_energy_1_visc;
208
209 // compute velocities and convert to VectorizedArray<number>
210 const dealii::VectorizedArray<number> vel_liquid =
211 MeltPoolDG::CompressibleFlow::calculate_velocity<dim, number>(u_liquid)[0];
212 const dealii::VectorizedArray<number> vel_gas =
213 MeltPoolDG::CompressibleFlow::calculate_velocity<dim, number>(u_gas)[0];
214
215 const dealii::VectorizedArray<number> jump_energy_term_1 =
216 (u_liquid[Idx::energy] * vel_liquid - u_gas[Idx::energy] * vel_gas);
217
218 const dealii::VectorizedArray<number> average_energy_term_1 =
220 u_liquid[Idx::energy] *
221 vel_liquid,
222 omega_energy_1_conv,
223 u_gas[Idx::energy] * vel_gas);
224
225 total_flux_liquid[Idx::energy] =
226 jump_energy_term_1 * omega_energy_1_conv + average_energy_term_1;
227 total_flux_gas[Idx::energy] = jump_energy_term_1 * omega_energy_2_conv - average_energy_term_1;
228
229 const dealii::VectorizedArray<number> jump_energy_term_2 =
230 -m_dot_evap * (u_liquid[Idx::energy] / u_liquid[Idx::density] -
231 u_gas[Idx::energy] / u_gas[Idx::density]) -
232 laser_heat_source +
233 m_dot_evap * multiphase_scratch_data.phase_change.liquid_gas.latent_heat_of_vaporization;
234
235 total_flux_liquid[Idx::energy] += jump_energy_term_2 * omega_energy_1_visc;
236 total_flux_gas[Idx::energy] += jump_energy_term_2 * omega_energy_2_visc;
237
238 const dealii::VectorizedArray<number> weighted_average_energy_term_liquid =
239 -stress_tensor_liquid * vel_liquid -
240 multiphase_scratch_data.material_liquid.data.thermal_conductivity *
241 multiphase_scratch_data.material_liquid.eos_utils->calculate_grad_T(u_liquid,
242 grad_u_liquid)[0];
243 const dealii::VectorizedArray<number> weighted_average_energy_term_gas =
244 -stress_tensor_gas * vel_gas -
245 multiphase_scratch_data.material_gas.data.thermal_conductivity *
246 multiphase_scratch_data.material_gas.eos_utils->calculate_grad_T(u_gas, grad_u_gas)[0];
247 const dealii::VectorizedArray<number> weighted_average_energy_term =
249 omega_energy_2_visc,
250 weighted_average_energy_term_liquid,
251 omega_energy_1_visc,
252 weighted_average_energy_term_gas);
253
254 total_flux_liquid[Idx::energy] += weighted_average_energy_term;
255 total_flux_gas[Idx::energy] -= weighted_average_energy_term;
256
257 // penalty approach for gas temperature constraint
258 const dealii::VectorizedArray<number> temperature_gas =
259 multiphase_scratch_data.material_gas.eos_utils->calculate_temperature(u_gas);
260 // TODO: compute target temperature in gas phase from Hertz-Knudsen theory
261 const dealii::VectorizedArray<number> penalty_gas_temperature =
262 multiphase_scratch_data.phase_coupling.penalty.coefficients.temperature *
263 (temperature_gas -
264 multiphase_scratch_data.phase_coupling.penalty.target_values.temperature_gas_phase);
265
266 total_flux_gas[Idx::energy] += penalty_gas_temperature;
267
268 return {total_flux_liquid, total_flux_gas};
269 }
270
274
301 template <int dim,
302 typename number,
303 typename ConservedVariablesType,
304 typename ConservedVariablesGradType,
306 ConvectiveKernel>
307 inline DEAL_II_ALWAYS_INLINE //
308 std::tuple<ConservedVariablesGradType,
309 ConservedVariablesGradType,
310 dealii::VectorizedArray<number>>
312 const ConservedVariablesType &u_liquid,
313 const ConservedVariablesType &u_gas,
314 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
315 const ConvectiveKernel &convective_kernel_liquid,
316 const ConvectiveKernel &convective_kernel_gas,
318 const number &m_dot_evap)
319 {
320 // Note: Variables, that are relevant for both the liquid and the gas phase, are considered as
321 // arrays of length 2 in the following. The first element refers to the liquid phase and the
322 // second element to the gas phase.
323 constexpr int liquid = 0;
324 constexpr int gas = 1;
325
326 // enumeration for conserved variables component indices
327 using Idx = std::conditional_t<
328 dim == 1,
329 CompressibleFlow::Idx1D,
330 std::conditional_t<dim == 2,
331 CompressibleFlow::Idx2D,
332 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
333
334 // 0) preliminaries
335
336 std::array<ConservedVariablesType, 2> u = {{u_liquid, u_gas}};
337 std::array<dealii::Tensor<1, dim, dealii::VectorizedArray<number>>, 2> vel;
338 std::array<dealii::VectorizedArray<number>, 2> pressure;
339 std::array<dealii::VectorizedArray<number>, 2> rho;
340 std::array<dealii::VectorizedArray<number>, 2> rho_E;
341 std::array<dealii::VectorizedArray<number>, 2> speed_of_sound;
342 for (unsigned int i : {0, 1})
343 {
344 vel[i] = CompressibleFlow::calculate_velocity<dim>(u[i]);
345 rho[i] = u[i][Idx::density];
346 rho_E[i] = u[i][Idx::energy];
347 }
348 pressure[liquid] =
349 multiphase_scratch_data.material_liquid.eos_utils->calculate_thermodynamic_pressure(
350 u[liquid]);
351 pressure[gas] =
352 multiphase_scratch_data.material_gas.eos_utils->calculate_thermodynamic_pressure(u[gas]);
353 speed_of_sound[liquid] =
354 multiphase_scratch_data.material_liquid.eos_utils->calculate_speed_of_sound(u[liquid]);
355 speed_of_sound[gas] =
356 multiphase_scratch_data.material_gas.eos_utils->calculate_speed_of_sound(u[gas]);
357
358 // 1) project velocity and kinetic energy into normal direction of the interface
359
360 std::array<dealii::VectorizedArray<number>, 2> vel_n;
361 std::array<dealii::VectorizedArray<number>, 2> E_n;
362 for (unsigned int i : {0, 1})
363 {
364 vel_n[i] = vel[i] * normal;
365 E_n[i] = rho_E[i] / rho[i] - 0.5 * (vel[i] * vel[i] - vel_n[i] * vel_n[i]);
366 }
367
368 // 2) shock speed estimation
369
370 std::array<dealii::VectorizedArray<number>, 2> shock_speed;
371 shock_speed[liquid] = vel_n[liquid] - speed_of_sound[liquid];
372 shock_speed[gas] = vel_n[gas] + speed_of_sound[gas];
373
374 // 3) calculate helpers using Rankine-Hugoniot conditions
375
376 std::array<dealii::VectorizedArray<number>, 2> m_hat;
377 std::array<dealii::VectorizedArray<number>, 2> I_hat;
378 std::array<dealii::VectorizedArray<number>, 2> E_hat;
379 for (unsigned int i : {0, 1})
380 {
381 m_hat[i] = rho[i] * (vel_n[i] - shock_speed[i]);
382 I_hat[i] = m_hat[i] * vel_n[i] + pressure[i];
383 E_hat[i] = m_hat[i] * E_n[i] + pressure[i] * vel_n[i];
384 }
385
386 // 4) calculate intermediate velocity states
387
388 // TODO: consider surface tension for dim>1 here
389 const dealii::VectorizedArray<number> delta_p = 0.;
390
391 // TODO: consider Hertz-Knudsen theory for evaporation mass flux here
392 std::array<dealii::VectorizedArray<number>, 2> tmp_1;
393 std::array<dealii::VectorizedArray<number>, 2> tmp_2;
394 for (unsigned int i : {0, 1})
395 {
396 tmp_1[i] = m_dot_evap / m_hat[i];
397 tmp_2[i] = m_dot_evap - m_hat[i];
398 }
399
400 std::array<dealii::VectorizedArray<number>, 2> numerator;
401 std::array<dealii::VectorizedArray<number>, 2> denominator;
402
403 numerator[liquid] = tmp_2[gas] *
404 (tmp_1[liquid] * shock_speed[liquid] - tmp_1[gas] * shock_speed[gas]) /
405 (1. - tmp_1[gas]) -
406 I_hat[liquid] - delta_p + I_hat[gas];
407 numerator[gas] = tmp_2[liquid] *
408 (tmp_1[gas] * shock_speed[gas] - tmp_1[liquid] * shock_speed[liquid]) /
409 (1. - tmp_1[liquid]) -
410 I_hat[gas] + delta_p + I_hat[liquid];
411 denominator[liquid] = tmp_2[liquid] - (1. - tmp_1[liquid]) / (1. - tmp_1[gas]) * tmp_2[gas];
412 denominator[gas] = tmp_2[gas] - (1. - tmp_1[gas]) / (1. - tmp_1[liquid]) * tmp_2[liquid];
413
414 std::array<dealii::VectorizedArray<number>, 2> vel_n_star;
415 for (unsigned int i : {0, 1})
416 vel_n_star[i] = numerator[i] / denominator[i];
417
418 // 5) calculate intermediate pressure
419
420 std::array<dealii::VectorizedArray<number>, 2> pressure_star;
421 for (unsigned int i : {0, 1})
422 pressure_star[i] = I_hat[i] - m_hat[i] * vel_n_star[i];
423
424 // 6) re-project normal velocity to Cartesian coordinates
425
426 std::array<dealii::Tensor<1, dim, dealii::VectorizedArray<number>>, 2> vel_star_cartesian;
427
428 std::vector<dealii::Tensor<1, dim, dealii::VectorizedArray<number>>> tangent;
429 tangent.resize(dim - 1);
430
431 // compute tangential vector for dim=2 and dim=3
432 if constexpr (dim == 2)
433 {
434 tangent[0][0] = normal[1];
435 tangent[0][1] = -normal[0];
436 }
437 else if constexpr (dim == 3)
438 {
439 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> temp_vec;
440 temp_vec[0] = 1.;
441 // if normal vector is identical with unit vector choose different unit vector to
442 // compute the tangent
443 dealii::VectorizedArray<number> tolerance = 1.e-10;
444 dealii::VectorizedArray<number> norm_diff = (temp_vec - normal).norm();
445 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> temp_vec_y;
446 temp_vec_y[1] = 1.;
447 for (int i = 0; i < 3; ++i)
448 {
449 temp_vec[i] = compare_and_apply_mask<dealii::SIMDComparison::less_than>(norm_diff,
450 tolerance,
451 temp_vec_y[i],
452 temp_vec[i]);
453 }
454 tangent[0] = temp_vec - (temp_vec * normal) * normal;
455 tangent[1] = dealii::cross_product_3d(normal, tangent[0]);
456 }
457
458 for (unsigned int i : {0, 1})
459 {
460 vel_star_cartesian[i] = vel_n_star[i] * normal;
461 for (unsigned int j = 0; j < dim - 1; ++j)
462 vel_star_cartesian[i] += (vel[i] * tangent[j]) * tangent[j];
463 }
464
465 // 7) calculate conservative variable state vectors of inner states
466
467 std::array<ConservedVariablesType, 2> u_star;
468 for (unsigned int i : {0, 1})
469 {
470 u_star[i][Idx::density] = m_hat[i] / (vel_n_star[i] - shock_speed[i]);
471 for (unsigned int j = 1; j < dim + 1; j++)
472 u_star[i][j] = u_star[i][Idx::density] * vel_star_cartesian[i][0][j - 1];
473 u_star[i][Idx::energy] =
474 (E_hat[i] - pressure_star[i] * vel_n_star[i]) / (vel_n_star[i] - shock_speed[i]) -
475 0.5 * u_star[i][Idx::density] * vel_n_star[i] * vel_n_star[i] +
476 0.5 * u_star[i][Idx::density] * vel_star_cartesian[i] * vel_star_cartesian[i];
477 }
478
479 // 8) calculate phase interface velocity
480
481 dealii::VectorizedArray<number> numerator_normal_vel =
482 vel_n_star[liquid] * u_star[liquid][Idx::density] -
483 vel_n_star[gas] * u_star[gas][Idx::density];
484 dealii::VectorizedArray<number> denominator_normal_vel =
485 u_star[liquid][Idx::density] - u_star[gas][Idx::density];
486 // avoid division by zero
487 dealii::VectorizedArray<number> normal_velocity_interface =
488 compare_and_apply_mask<dealii::SIMDComparison::greater_than>(std::abs(denominator_normal_vel),
489 1.e-12,
490 numerator_normal_vel /
491 denominator_normal_vel,
492 vel_n_star[liquid]);
493
494 // 9) calculate fluxes for the two phases
495
496 std::array<ConservedVariablesGradType, 2> flux;
497 std::array<ConservedVariablesGradType, 2> conv_flux;
498 std::array<ConservedVariablesGradType, 2> shock_flux;
499
500 conv_flux[liquid] = convective_kernel_liquid.flux(u[liquid]);
501 conv_flux[gas] = convective_kernel_gas.flux(u[gas]);
502
503 for (unsigned int i : {0, 1})
504 {
505 shock_flux[i] = dyadic_product(shock_speed[i] * (u_star[i] - u[i]), normal);
506 flux[i] = conv_flux[i];
507 }
508
509 const auto zero_vec = dealii::make_vectorized_array(0.);
510 const auto one_vec = dealii::make_vectorized_array(1.);
511
512 flux[liquid] +=
513 shock_flux[liquid] * compare_and_apply_mask<dealii::SIMDComparison::greater_than>(
514 shock_speed[liquid], zero_vec, zero_vec, one_vec);
515 flux[gas] +=
516 shock_flux[gas] * compare_and_apply_mask<dealii::SIMDComparison::less_than_or_equal>(
517 shock_speed[gas], zero_vec, zero_vec, one_vec);
518
519 return {flux[liquid], flux[gas], normal_velocity_interface};
520 }
521
525
545 template <int dim,
546 typename number,
547 typename ConservedVariablesType>
548 inline DEAL_II_ALWAYS_INLINE //
549 ConservedVariablesType
551 const ConservedVariablesType &u_liquid_cons,
552 const ConservedVariablesType &u_gas_cons,
554 const number &m_dot_evap,
555 const number &delta_T)
556 {
557 // enumeration for conserved variables component indices
558 using Idx = std::conditional_t<
559 dim == 1,
560 CompressibleFlow::Idx1D,
561 std::conditional_t<dim == 2,
562 CompressibleFlow::Idx2D,
563 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
564
565 auto u_liquid_prim = multiphase_scratch_data.material_liquid.eos_utils
566 ->convert_conservative_into_primitive_variables(u_liquid_cons);
567
568 auto u_gas_prim =
569 multiphase_scratch_data.material_gas.eos_utils->convert_conservative_into_primitive_variables(
570 u_gas_cons);
571
572 // TODO: consider surface tension here
573 const dealii::VectorizedArray<number> delta_p = 0.;
574
575 // TODO: extend to general case dim>1
576 ConservedVariablesType J_Dir;
577
578 J_Dir[Idx::density] = delta_p - m_dot_evap * (u_liquid_prim[1] - u_gas_prim[1]);
579 J_Dir[Idx::momentum_x] = m_dot_evap * (1. / u_liquid_cons[0] - 1. / u_gas_cons[0]);
580 J_Dir[Idx::energy] = delta_T;
581
582 const auto u_liquid_prim_tmp = u_liquid_prim;
583 u_liquid_prim = u_gas_prim + J_Dir;
584 u_gas_prim = u_liquid_prim_tmp - J_Dir;
585
586 const auto u_liquid_cons_star =
587 multiphase_scratch_data.material_liquid.eos_utils
588 ->convert_primitive_into_conservative_variables(u_liquid_prim);
589
590 const auto u_gas_cons_star =
591 multiphase_scratch_data.material_gas.eos_utils->convert_primitive_into_conservative_variables(
592 u_gas_prim);
593
594 J_Dir = u_liquid_cons_star - u_gas_cons_star;
595
596 return J_Dir;
597 }
598
634 template <int dim,
635 typename number,
636 typename ConservedVariablesType,
637 typename ConservedVariablesGradType,
639 DiffusiveKernel>
640 inline DEAL_II_ALWAYS_INLINE //
641 std::pair<ConservedVariablesType, ConservedVariablesType>
643 const ConservedVariablesType &u_liquid,
644 const ConservedVariablesType &u_gas,
645 const ConservedVariablesGradType &grad_u_liquid,
646 const ConservedVariablesGradType &grad_u_gas,
647 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
648 const number &visc_ave_weight_phase_liquid,
649 const number &visc_ave_weight_phase_gas,
650 const number &tau,
651 const DiffusiveKernel &diffusive_kernel_liquid,
652 const DiffusiveKernel &diffusive_kernel_gas,
654 const number &cell_size,
655 const number &m_dot_evap,
656 const number &delta_T,
657 const number &laser_heat_source)
658 {
659 // enumeration for conserved variables component indices
660 using Idx = std::conditional_t<
661 dim == 1,
662 CompressibleFlow::Idx1D,
663 std::conditional_t<dim == 2,
664 CompressibleFlow::Idx2D,
665 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
666
667 // TODO: add contributions for surface tension, interface heat source (laser energy) and
668 // Marangoni forces
669
670 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> vel_liquid =
671 CompressibleFlow::calculate_velocity<dim>(u_liquid);
672 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> vel_gas =
673 CompressibleFlow::calculate_velocity<dim>(u_gas);
674
675 const dealii::VectorizedArray<number> vel_n_liquid = vel_liquid * normal;
676 const dealii::VectorizedArray<number> vel_n_gas = vel_gas * normal;
677
678 const auto pressure_liquid =
679 multiphase_scratch_data.material_liquid.eos_utils->calculate_thermodynamic_pressure(u_liquid);
680 const auto pressure_gas =
681 multiphase_scratch_data.material_gas.eos_utils->calculate_thermodynamic_pressure(u_gas);
682
683 // compute Robin-type viscous interface jump conditions
684
685 ConservedVariablesType J_Rob;
686
687 // TODO: Add entries for case dim>1
688 J_Rob[Idx::energy] =
689 (pressure_liquid * vel_n_liquid - pressure_gas * vel_n_gas) +
690 m_dot_evap * (u_liquid[Idx::energy] / u_liquid[Idx::density] -
691 u_gas[Idx::energy] / u_gas[Idx::density]) +
692 laser_heat_source -
693 m_dot_evap * multiphase_scratch_data.phase_change.liquid_gas.latent_heat_of_vaporization;
694
695 const ConservedVariablesGradType viscous_flux_liquid =
696 diffusive_kernel_liquid.flux(u_liquid, grad_u_liquid);
697
698 const ConservedVariablesGradType viscous_flux_gas =
699 diffusive_kernel_gas.flux(u_gas, grad_u_gas);
700
701 ConservedVariablesGradType total_flux_liquid = dyadic_product(J_Rob, normal);
702 total_flux_liquid += viscous_flux_gas;
703 total_flux_liquid *= visc_ave_weight_phase_liquid;
704 total_flux_liquid += visc_ave_weight_phase_gas * viscous_flux_liquid;
705
706 ConservedVariablesGradType total_flux_gas =
707 dyadic_product(J_Rob, -normal); // opposite normal direction for phase 2
708 total_flux_gas += viscous_flux_liquid;
709 total_flux_gas *= visc_ave_weight_phase_gas;
710 total_flux_gas += visc_ave_weight_phase_liquid * viscous_flux_gas;
711
712 // penalty term
713
714 const auto J_Dir_cons =
715 calculate_Dirichlet_jump_in_conservative_variables<dim, number, ConservedVariablesType>(
716 u_liquid, u_gas, multiphase_scratch_data, m_dot_evap, delta_T);
717
718 const number penalty_parameter =
719 std::min(multiphase_scratch_data.material_liquid.data.dynamic_viscosity /
720 multiphase_scratch_data.material_liquid.data.reference_density,
721 multiphase_scratch_data.material_gas.data.dynamic_viscosity /
722 multiphase_scratch_data.material_gas.data.reference_density) *
723 (multiphase_scratch_data.flow_data.fe.degree + 1.) *
724 (multiphase_scratch_data.flow_data.fe.degree + 1.) / cell_size * tau;
725
726 ConservedVariablesGradType penalty_flux_liquid;
727 const auto tmp_m = u_liquid - (u_gas + J_Dir_cons);
728 penalty_flux_liquid = dyadic_product(tmp_m, normal);
729 penalty_flux_liquid *= penalty_parameter;
730
731 ConservedVariablesGradType penalty_flux_gas;
732 const auto tmp_p = u_gas - (u_liquid - J_Dir_cons);
733 penalty_flux_gas = dyadic_product(tmp_p, -normal);
734 penalty_flux_gas *= penalty_parameter;
735
736 total_flux_liquid -= penalty_flux_liquid;
737 total_flux_gas -= penalty_flux_gas;
738
739 return {contract_tensor_with_vector<CompressibleFlow::n_conserved_variables<dim>, dim, number>(
740 total_flux_liquid, normal),
741 contract_tensor_with_vector<CompressibleFlow::n_conserved_variables<dim>, dim, number>(
742 total_flux_gas, normal)};
743 }
744
774 template <int dim,
775 typename number,
776 typename ConservedVariablesType,
777 typename ConservedVariablesGradType,
779 DiffusiveKernel>
780 inline DEAL_II_ALWAYS_INLINE //
781 std::pair<ConservedVariablesGradType, ConservedVariablesGradType>
783 const ConservedVariablesType &u_liquid,
784 const ConservedVariablesType &u_gas,
785 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
786 const number &visc_ave_weight_phase_liquid,
787 const number &visc_ave_weight_phase_gas,
788 const DiffusiveKernel &diffusive_kernel_liquid,
789 const DiffusiveKernel &diffusive_kernel_gas,
791 const number &m_dot_evap,
792 const number &delta_T)
793 {
794 const auto J_Dir_cons =
795 calculate_Dirichlet_jump_in_conservative_variables<dim, number, ConservedVariablesType>(
796 u_liquid, u_gas, multiphase_scratch_data, m_dot_evap, delta_T);
797
799 visc_ave_weight_phase_gas, u_liquid, visc_ave_weight_phase_liquid, u_gas + J_Dir_cons);
801 visc_ave_weight_phase_liquid, u_gas, visc_ave_weight_phase_gas, u_liquid - J_Dir_cons);
802
803 auto tmp_liquid = u_liquid_star - u_liquid;
804 auto tmp_gas = u_gas_star - u_gas;
805
806 ConservedVariablesGradType arg_liquid = dyadic_product(tmp_liquid, normal);
807 ConservedVariablesGradType arg_gas = dyadic_product(tmp_gas, -normal);
808
809 const ConservedVariablesGradType flux_grad_liquid =
810 diffusive_kernel_liquid.flux(u_liquid, arg_liquid);
811 const ConservedVariablesGradType flux_grad_gas = diffusive_kernel_gas.flux(u_gas, arg_gas);
812
813 return {flux_grad_liquid, flux_grad_gas};
814 }
815
819
853 template <int dim,
854 typename number,
855 typename ConservedVariablesType,
856 typename ConservedVariablesGradType,
858 DiffusiveKernel>
859 inline DEAL_II_ALWAYS_INLINE //
860 std::pair<ConservedVariablesType, ConservedVariablesType>
862 const ConservedVariablesType &u_liquid,
863 const ConservedVariablesType &u_gas,
864 const ConservedVariablesGradType &grad_u_liquid,
865 const ConservedVariablesGradType &grad_u_gas,
866 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
867 const number &visc_ave_weight_phase_liquid,
868 const number &visc_ave_weight_phase_gas,
869 const DiffusiveKernel &diffusive_kernel_liquid,
870 const DiffusiveKernel &diffusive_kernel_gas,
872 const number &cell_size,
873 const number &m_dot_evap,
874 const number &delta_T,
875 const number &laser_heat_source)
876 {
877 // enumeration for conserved variables component indices
878 using Idx = std::conditional_t<
879 dim == 1,
880 CompressibleFlow::Idx1D,
881 std::conditional_t<dim == 2,
882 CompressibleFlow::Idx2D,
883 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
884
885 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> vel_liquid =
886 CompressibleFlow::calculate_velocity<dim>(u_liquid);
887 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> vel_gas =
888 CompressibleFlow::calculate_velocity<dim>(u_gas);
889
890 const dealii::VectorizedArray<number> vel_n_liquid = vel_liquid * normal;
891 const dealii::VectorizedArray<number> vel_n_gas = vel_gas * normal;
892
893 const dealii::VectorizedArray<number> pressure_liquid =
894 multiphase_scratch_data.material_liquid.eos_utils->calculate_thermodynamic_pressure(u_liquid);
895 const dealii::VectorizedArray<number> pressure_gas =
896 multiphase_scratch_data.material_gas.eos_utils->calculate_thermodynamic_pressure(u_gas);
897
898 // compute Robin-type viscous interface jump conditions
899 // TODO: add contributions for surface tension and Marangoni forces (for dim>1)
900
901 ConservedVariablesType J_Rob;
902
903 J_Rob[Idx::energy] =
904 m_dot_evap * (u_liquid[Idx::energy] / u_liquid[Idx::density] -
905 u_gas[Idx::energy] / u_gas[Idx::density]) +
906 (pressure_liquid * vel_n_liquid - pressure_gas * vel_n_gas) + laser_heat_source -
907 m_dot_evap * multiphase_scratch_data.phase_change.liquid_gas.latent_heat_of_vaporization;
908
909 const ConservedVariablesGradType viscous_flux_liquid =
910 diffusive_kernel_liquid.flux(u_liquid, grad_u_liquid);
911
912 const ConservedVariablesGradType viscous_flux_gas =
913 diffusive_kernel_gas.flux(u_gas, grad_u_gas);
914
915 ConservedVariablesType penalty_term_dT;
916 penalty_term_dT[Idx::energy] =
917 multiphase_scratch_data.phase_coupling.hllp0_and_penalty.penalty_parameter_temperature_jump *
918 (multiphase_scratch_data.material_liquid.data.thermal_conductivity +
919 multiphase_scratch_data.material_gas.data.thermal_conductivity) /
920 (2. * cell_size) *
921 ((multiphase_scratch_data.material_liquid.eos_utils->calculate_temperature(u_liquid) -
922 multiphase_scratch_data.material_gas.eos_utils->calculate_temperature(u_gas)) -
923 delta_T);
924
925 const ConservedVariablesType weighted_viscous_flux =
927 visc_ave_weight_phase_gas,
928 contract_tensor_with_vector<CompressibleFlow::n_conserved_variables<dim>, dim, number>(
929 viscous_flux_liquid, normal),
930 visc_ave_weight_phase_liquid,
931 contract_tensor_with_vector<CompressibleFlow::n_conserved_variables<dim>, dim, number>(
932 viscous_flux_gas, normal));
933
934 const ConservedVariablesType total_viscous_flux_liquid =
935 -J_Rob * visc_ave_weight_phase_liquid - weighted_viscous_flux + penalty_term_dT;
936
937 const ConservedVariablesType total_viscous_flux_gas =
938 -J_Rob * visc_ave_weight_phase_gas + weighted_viscous_flux - penalty_term_dT;
939
940 return {total_viscous_flux_liquid, total_viscous_flux_gas};
941 }
942
951 template <typename number>
952 inline DEAL_II_ALWAYS_INLINE //
953 number
955 const number &time)
956 {
957 const auto &laser = phase_coupling_data.laser_heat_source;
958
959 if (laser.do_ramp and time < laser.ramp_time)
960 {
961 const number factor = 0.5 * (1. - std::cos(std::numbers::pi * time / laser.ramp_time));
962
963 return factor * laser.laser_power_density;
964 }
965
966 return laser.laser_power_density;
967 }
968
984 template <int dim,
985 typename number,
986 typename ConservedVariablesType>
987 inline DEAL_II_ALWAYS_INLINE //
988 std::tuple<number, number>
990 const ConservedVariablesType &u_liquid,
991 const ConservedVariablesType &u_gas,
992 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
994 Evaporation::EvaporationModelKnight<number> *evaporation_model_knight = nullptr)
995 {
996 number m_dot_evap = 0.;
997 number delta_T = 0.;
998
999 if (evaporation_model_knight)
1000 {
1001 const dealii::VectorizedArray<number> T_liquid =
1002 multiphase_scratch_data.material_liquid.eos_utils->calculate_temperature(u_liquid);
1003
1004 const dealii::VectorizedArray<number> vel_n_gas =
1005 CompressibleFlow::calculate_velocity<dim>(u_gas) * normal;
1006
1007 const dealii::VectorizedArray<number> speed_of_sound_g =
1008 multiphase_scratch_data.material_gas.eos_utils->calculate_speed_of_sound(u_gas);
1009
1010 const dealii::VectorizedArray<number> Ma_g = vel_n_gas / speed_of_sound_g;
1011
1012 // TODO: evaluate vectorized array for dim>1!
1013 evaporation_model_knight->reinit(T_liquid[0], Ma_g[0]);
1014 m_dot_evap = evaporation_model_knight->get_evaporative_mass_flux();
1015 delta_T = evaporation_model_knight->get_temperature_jump();
1016 }
1017 else if (multiphase_scratch_data.phase_coupling.evaporation_model ==
1018 EvaporationModelType::constant)
1019 {
1020 m_dot_evap = multiphase_scratch_data.phase_coupling.m_dot_evap;
1021
1022 switch (multiphase_scratch_data.phase_coupling.type)
1023 {
1024 case InterfaceNumericalMethod::HLLP0_and_SIPG:
1025 delta_T = multiphase_scratch_data.phase_coupling.hllp0_and_sipg.delta_T;
1026 break;
1027
1028 case InterfaceNumericalMethod::HLLP0_and_penalty:
1029 delta_T = multiphase_scratch_data.phase_coupling.hllp0_and_penalty.delta_T;
1030 break;
1031
1032 default:
1033 break;
1034 }
1035 }
1036 else
1037 {
1038 AssertThrow(false,
1039 dealii::ExcNotImplemented("The given evaporation model is not implemented."));
1040 }
1041
1042 return {m_dot_evap, delta_T};
1043 }
1044} // namespace MeltPoolDG::Multiphase
This class implements the evaporative mass flux and temperature jump for rapid evaporation according ...
Definition evaporation_model_knight.hpp:29
Definition data_types.hpp:196
A collection of functions for the computation of the interface terms for compressible two-phase flows...
Definition multiphase_interface_kernels.hpp:31
DEAL_II_ALWAYS_INLINE std::tuple< number, number > update_evaporative_mass_flux_and_temperature_jump(const ConservedVariablesType &u_liquid, const ConservedVariablesType &u_gas, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal, const CompressibleFlow::MultiphaseOperationScratchData< dim, number > &multiphase_scratch_data, Evaporation::EvaporationModelKnight< number > *evaporation_model_knight=nullptr)
Compute the current evaporative mass flux and temperature jump across the interface.
Definition multiphase_interface_kernels.hpp:989
DEAL_II_ALWAYS_INLINE number update_laser_heat_source(const CompressibleFlowPhaseCouplingData< number > &phase_coupling_data, const number &time)
Compute the current value of the laser heat source.
Definition multiphase_interface_kernels.hpp:954
DEAL_II_ALWAYS_INLINE std::tuple< ConservedVariablesGradType, ConservedVariablesGradType, dealii::VectorizedArray< number > > calculate_convective_interface_flux_HLLP0(const ConservedVariablesType &u_liquid, const ConservedVariablesType &u_gas, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal, const ConvectiveKernel &convective_kernel_liquid, const ConvectiveKernel &convective_kernel_gas, const CompressibleFlow::MultiphaseOperationScratchData< dim, number > &multiphase_scratch_data, const number &m_dot_evap)
HLLP0 Riemann solver ///.
Definition multiphase_interface_kernels.hpp:311
DEAL_II_ALWAYS_INLINE std::pair< ConservedVariablesGradType, ConservedVariablesGradType > calculate_viscous_interface_flux_gradient(const ConservedVariablesType &u_liquid, const ConservedVariablesType &u_gas, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal, const number &visc_ave_weight_phase_liquid, const number &visc_ave_weight_phase_gas, const DiffusiveKernel &diffusive_kernel_liquid, const DiffusiveKernel &diffusive_kernel_gas, const CompressibleFlow::MultiphaseOperationScratchData< dim, number > &multiphase_scratch_data, const number &m_dot_evap, const number &delta_T)
Calculate gradient-tested viscous interface flux for viscous phase coupling with the SIPG method.
Definition multiphase_interface_kernels.hpp:782
DEAL_II_ALWAYS_INLINE ConservedVariablesType calculate_Dirichlet_jump_in_conservative_variables(const ConservedVariablesType &u_liquid_cons, const ConservedVariablesType &u_gas_cons, const CompressibleFlow::MultiphaseOperationScratchData< dim, number > &multiphase_scratch_data, const number &m_dot_evap, const number &delta_T)
SIPG functions for method "HLLP and SIPG" ///.
Definition multiphase_interface_kernels.hpp:550
DEAL_II_ALWAYS_INLINE std::pair< ConservedVariablesType, ConservedVariablesType > calculate_convective_and_viscous_interface_flux_penalty(const ConservedVariablesType &u_liquid, const ConservedVariablesType &u_gas, const ConservedVariablesGradType &grad_u_liquid, const ConservedVariablesGradType &grad_u_gas, const CompressibleFlow::MultiphaseOperationScratchData< dim, number > &multiphase_scratch_data, const number &m_dot_evap, const number &laser_heat_source)
"penalty" method ///
Definition multiphase_interface_kernels.hpp:64
DEAL_II_ALWAYS_INLINE std::pair< ConservedVariablesType, ConservedVariablesType > calculate_viscous_interface_flux_method_3(const ConservedVariablesType &u_liquid, const ConservedVariablesType &u_gas, const ConservedVariablesGradType &grad_u_liquid, const ConservedVariablesGradType &grad_u_gas, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal, const number &visc_ave_weight_phase_liquid, const number &visc_ave_weight_phase_gas, const DiffusiveKernel &diffusive_kernel_liquid, const DiffusiveKernel &diffusive_kernel_gas, const CompressibleFlow::MultiphaseOperationScratchData< dim, number > &multiphase_scratch_data, const number &cell_size, const number &m_dot_evap, const number &delta_T, const number &laser_heat_source)
viscous terms for the method "HLLP0 and penalty" ///
Definition multiphase_interface_kernels.hpp:861
DEAL_II_ALWAYS_INLINE std::pair< ConservedVariablesType, ConservedVariablesType > calculate_viscous_interface_flux(const ConservedVariablesType &u_liquid, const ConservedVariablesType &u_gas, const ConservedVariablesGradType &grad_u_liquid, const ConservedVariablesGradType &grad_u_gas, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal, const number &visc_ave_weight_phase_liquid, const number &visc_ave_weight_phase_gas, const number &tau, const DiffusiveKernel &diffusive_kernel_liquid, const DiffusiveKernel &diffusive_kernel_gas, const CompressibleFlow::MultiphaseOperationScratchData< dim, number > &multiphase_scratch_data, const number &cell_size, const number &m_dot_evap, const number &delta_T, const number &laser_heat_source)
Calculate the viscous interface flux for viscous phase coupling with the SIPG method.
Definition multiphase_interface_kernels.hpp:642
TypeTerm calculate_arithmetic_phase_weighted_average(const TypeWeight &weight_a, const TypeTerm &term_a, const TypeWeight &weight_b, const TypeTerm &term_b)
Definition utility_functions.hpp:167
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
Scratch data structure for compressible multiphase flow solvers.
Definition operation_scratch_data.hpp:153
const Multiphase::CompressibleFlowPhaseCouplingData< number > phase_coupling
Parameters for the coupling of two compressible (or nearly incompressible) phases.
Definition operation_scratch_data.hpp:216
const Material< dim, number > material_gas
Material parameters and thermodynamic relations for the gas phase.
Definition operation_scratch_data.hpp:204
const OperationData< number > flow_data
General parameters for the compressible Navier-Stokes operators.
Definition operation_scratch_data.hpp:198
const Material< dim, number > material_liquid
Material parameters and thermodynamic relations for the liquid phase.
Definition operation_scratch_data.hpp:207
const Multiphase::PhaseChangeData< number > phase_change
Parameters related to liquid-gas and solid-liquid phase transitions.
Definition operation_scratch_data.hpp:210
number laser_power_density
Laser power density (SI: W/m^2)
Definition phase_coupling_data.hpp:40
Data structure, which contains parameters specifically for the phase coupling of compressible multiph...
Definition phase_coupling_data.hpp:23
struct MeltPoolDG::Multiphase::CompressibleFlowPhaseCouplingData::LaserHeatSource laser_heat_source