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
27
28#include <tuple>
29#include <utility>
30
32{
36
55 template <int dim,
56 typename number,
57 typename ConservedVariablesType,
58 typename DofValueAndGradientStateView>
59 inline DEAL_II_ALWAYS_INLINE //
60 std::pair<ConservedVariablesType, ConservedVariablesType>
62 const DofValueAndGradientStateView &liquid_state,
63 const DofValueAndGradientStateView &gas_state,
65 const number &m_dot_evap,
66 const number &laser_heat_source)
67 {
68 AssertThrow(dim == 1,
69 dealii::ExcNotImplemented(
70 "Currently, only dim=1 is enabled for "
71 "enforcing interface jump conditions with the penalty method."));
72
73 // enumeration for conserved variables component indices
74 using Idx = std::conditional_t<
75 dim == 1,
76 CompressibleFlow::Idx1D,
77 std::conditional_t<dim == 2,
78 CompressibleFlow::Idx2D,
79 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
80
81 ConservedVariablesType total_flux_liquid;
82 ConservedVariablesType total_flux_gas;
83
84 // TODO: investigate weighting factors!
85 const dealii::VectorizedArray<number> omega_mass_1 = 0.5;
86 const dealii::VectorizedArray<number> omega_mass_2 = 1. - omega_mass_1;
87
89 // mass conservation //
91
92 const dealii::VectorizedArray<number> interface_mass_flux_conservation_term =
93 (liquid_state.density() / gas_state.density() * gas_state.momentum(0) -
94 gas_state.density() / liquid_state.density() * liquid_state.momentum(0) +
95 (gas_state.density() * gas_state.density() -
96 liquid_state.density() * liquid_state.density()) /
97 (liquid_state.density() * gas_state.density()) * m_dot_evap);
98
99 total_flux_liquid[Idx::density] = omega_mass_1 * interface_mass_flux_conservation_term;
100 total_flux_gas[Idx::density] = omega_mass_2 * interface_mass_flux_conservation_term;
101
102 const dealii::VectorizedArray<number> weighted_average_momentum =
104 gas_state.momentum(0),
105 omega_mass_2,
106 liquid_state.momentum(0));
107
108 total_flux_liquid[Idx::density] += weighted_average_momentum;
109 total_flux_gas[Idx::density] -= weighted_average_momentum;
110
111 // penalty approach for density constraint in gas phase
112 // TODO: compute target density in gas phase from Hertz-Knudsen theory
113 const dealii::VectorizedArray<number> penalty_gas_density =
114 multiphase_scratch_data.phase_coupling.penalty.coefficients.density *
115 (gas_state.density() -
116 multiphase_scratch_data.phase_coupling.penalty.target_values.density_gas_phase);
117
118 total_flux_gas[Idx::density] += penalty_gas_density;
119
121 // momentum conservation //
123
124 // TODO: investigate weighting factors!
125 const dealii::VectorizedArray<number> omega_mom_1_conv = 0.5;
126 const dealii::VectorizedArray<number> omega_mom_2_conv = 1. - omega_mom_1_conv;
127
128 const dealii::VectorizedArray<number> omega_mom_1_visc =
129 liquid_state.dynamic_viscosity() /
130 (liquid_state.dynamic_viscosity() + gas_state.dynamic_viscosity());
131 const dealii::VectorizedArray<number> omega_mom_2_visc = 1. - omega_mom_1_visc;
132
133 // compute stress tensor (pressure and viscous contributions) and convert to type
134 // dealii::VectorizedArray<number>
135 const dealii::Tensor<2, dim, dealii::VectorizedArray<number>> viscous_stress_tensor_liquid =
136 CompressibleFlow::viscous_stress_tensor<dim, number>(liquid_state.grad_velocity(),
137 liquid_state.dynamic_viscosity());
138 const dealii::Tensor<2, dim, dealii::VectorizedArray<number>> viscous_stress_tensor_gas =
139 CompressibleFlow::viscous_stress_tensor<dim, number>(gas_state.grad_velocity(),
140 gas_state.dynamic_viscosity());
141
142 const dealii::VectorizedArray<number> stress_tensor_liquid =
144 viscous_stress_tensor_liquid)[0][0];
145 const dealii::VectorizedArray<number> stress_tensor_gas =
147 viscous_stress_tensor_gas)[0][0];
148
149 const dealii::VectorizedArray<number> jump_momentum_term_liquid =
150 liquid_state.momentum(0) * liquid_state.momentum(0) / liquid_state.density();
151 const dealii::VectorizedArray<number> jump_momentum_term_gas =
152 gas_state.momentum(0) * gas_state.momentum(0) / gas_state.density();
153
154 total_flux_liquid[Idx::momentum_x] +=
155 omega_mom_1_conv * (jump_momentum_term_liquid - jump_momentum_term_gas);
156 total_flux_gas[Idx::momentum_x] +=
157 omega_mom_2_conv * (jump_momentum_term_liquid - jump_momentum_term_gas);
158
159 const dealii::VectorizedArray<number> average_momentum_term_1 =
161 jump_momentum_term_liquid,
162 omega_mom_1_conv,
163 jump_momentum_term_gas);
164
165 total_flux_liquid[Idx::momentum_x] += average_momentum_term_1;
166 total_flux_gas[Idx::momentum_x] -= average_momentum_term_1;
167
168 const dealii::VectorizedArray<number> jump_momentum_term_2 =
169 -(liquid_state.momentum(0) / liquid_state.density() -
170 gas_state.momentum(0) / gas_state.density()) *
171 m_dot_evap;
172
173 const dealii::VectorizedArray<number> average_momentum_term_2 =
175 -stress_tensor_liquid,
176 omega_mom_1_visc,
177 -stress_tensor_gas);
178
179 total_flux_liquid[Idx::momentum_x] +=
180 jump_momentum_term_2 * omega_mom_1_visc + average_momentum_term_2;
181 total_flux_gas[Idx::momentum_x] +=
182 jump_momentum_term_2 * omega_mom_2_visc - average_momentum_term_2;
183
185 // energy conservation //
187
188 // TODO: investigate weighting factors!
189 const dealii::VectorizedArray<number> omega_energy_1_conv = 0.5;
190 const dealii::VectorizedArray<number> omega_energy_2_conv = 1. - omega_energy_1_conv;
191
192 const dealii::VectorizedArray<number> omega_energy_1_visc =
193 liquid_state.dynamic_viscosity() /
194 (liquid_state.dynamic_viscosity() + gas_state.dynamic_viscosity());
195 const dealii::VectorizedArray<number> omega_energy_2_visc = 1. - omega_energy_1_visc;
196
197 // compute velocities and convert to VectorizedArray<number>
198 const dealii::VectorizedArray<number> vel_liquid = liquid_state.velocity(0);
199 const dealii::VectorizedArray<number> vel_gas = gas_state.velocity(0);
200
201 const dealii::VectorizedArray<number> jump_energy_term_1 =
202 (liquid_state.total_energy() * vel_liquid - gas_state.total_energy() * vel_gas);
203
204 const dealii::VectorizedArray<number> average_energy_term_1 =
206 liquid_state.total_energy() *
207 vel_liquid,
208 omega_energy_1_conv,
209 gas_state.total_energy() *
210 vel_gas);
211
212 total_flux_liquid[Idx::energy] =
213 jump_energy_term_1 * omega_energy_1_conv + average_energy_term_1;
214 total_flux_gas[Idx::energy] = jump_energy_term_1 * omega_energy_2_conv - average_energy_term_1;
215
216 const dealii::VectorizedArray<number> jump_energy_term_2 =
217 -m_dot_evap * (liquid_state.total_energy() / liquid_state.density() -
218 gas_state.total_energy() / gas_state.density()) -
219 laser_heat_source +
220 m_dot_evap * multiphase_scratch_data.phase_change.liquid_gas.latent_heat_of_vaporization;
221
222 total_flux_liquid[Idx::energy] += jump_energy_term_2 * omega_energy_1_visc;
223 total_flux_gas[Idx::energy] += jump_energy_term_2 * omega_energy_2_visc;
224
225 const dealii::VectorizedArray<number> weighted_average_energy_term_liquid =
226 -stress_tensor_liquid * vel_liquid -
227 liquid_state.thermal_conductivity() * liquid_state.grad_temperature()[0];
228 const dealii::VectorizedArray<number> weighted_average_energy_term_gas =
229 -stress_tensor_gas * vel_gas -
230 gas_state.thermal_conductivity() * gas_state.grad_temperature()[0];
231 const dealii::VectorizedArray<number> weighted_average_energy_term =
233 omega_energy_2_visc,
234 weighted_average_energy_term_liquid,
235 omega_energy_1_visc,
236 weighted_average_energy_term_gas);
237
238 total_flux_liquid[Idx::energy] += weighted_average_energy_term;
239 total_flux_gas[Idx::energy] -= weighted_average_energy_term;
240
241 // penalty approach for gas temperature constraint
242 const dealii::VectorizedArray<number> temperature_gas = gas_state.temperature();
243 // TODO: compute target temperature in gas phase from Hertz-Knudsen theory
244 const dealii::VectorizedArray<number> penalty_gas_temperature =
245 multiphase_scratch_data.phase_coupling.penalty.coefficients.temperature *
246 (temperature_gas -
247 multiphase_scratch_data.phase_coupling.penalty.target_values.temperature_gas_phase);
248
249 total_flux_gas[Idx::energy] += penalty_gas_temperature;
250
251 return {total_flux_liquid, total_flux_gas};
252 }
253
257
282 template <int dim,
283 typename number,
284 typename ConservedVariablesType,
285 typename ConservedVariablesGradType,
286 typename DofStateView,
288 ConvectiveKernel>
289 inline DEAL_II_ALWAYS_INLINE //
290 std::
291 tuple<ConservedVariablesGradType, ConservedVariablesGradType, dealii::VectorizedArray<number>>
293 const DofStateView &liquid_state,
294 const DofStateView &gas_state,
295 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
296 const ConvectiveKernel &convective_kernel_liquid,
297 const ConvectiveKernel &convective_kernel_gas,
298 const number &m_dot_evap)
299 {
300 // Note: Variables, that are relevant for both the liquid and the gas phase, are considered as
301 // arrays of length 2 in the following. The first element refers to the liquid phase and the
302 // second element to the gas phase.
303 constexpr int liquid = 0;
304 constexpr int gas = 1;
305
306 // enumeration for conserved variables component indices
307 using Idx = std::conditional_t<
308 dim == 1,
309 CompressibleFlow::Idx1D,
310 std::conditional_t<dim == 2,
311 CompressibleFlow::Idx2D,
312 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
313
314 // 0) preliminaries
315
316 std::array<DofStateView, 2> state = {{liquid_state, gas_state}};
317 std::array<dealii::Tensor<1, dim, dealii::VectorizedArray<number>>, 2> vel;
318 std::array<dealii::VectorizedArray<number>, 2> pressure;
319 std::array<dealii::VectorizedArray<number>, 2> rho;
320 std::array<dealii::VectorizedArray<number>, 2> rho_E;
321 std::array<dealii::VectorizedArray<number>, 2> speed_of_sound;
322 for (unsigned int i : {0, 1})
323 {
324 vel[i] = state[i].velocity();
325 rho[i] = state[i].density();
326 rho_E[i] = state[i].total_energy();
327 pressure[i] = state[i].pressure();
328 speed_of_sound[i] = state[i].speed_of_sound();
329 }
330
331 // 1) project velocity and kinetic energy into normal direction of the interface
332
333 std::array<dealii::VectorizedArray<number>, 2> vel_n;
334 std::array<dealii::VectorizedArray<number>, 2> E_n;
335 for (unsigned int i : {0, 1})
336 {
337 vel_n[i] = vel[i] * normal;
338 E_n[i] = rho_E[i] / rho[i] - 0.5 * (vel[i] * vel[i] - vel_n[i] * vel_n[i]);
339 }
340
341 // 2) shock speed estimation
342
343 std::array<dealii::VectorizedArray<number>, 2> shock_speed;
344 shock_speed[liquid] = vel_n[liquid] - speed_of_sound[liquid];
345 shock_speed[gas] = vel_n[gas] + speed_of_sound[gas];
346
347 // 3) calculate helpers using Rankine-Hugoniot conditions
348
349 std::array<dealii::VectorizedArray<number>, 2> m_hat;
350 std::array<dealii::VectorizedArray<number>, 2> I_hat;
351 std::array<dealii::VectorizedArray<number>, 2> E_hat;
352 for (unsigned int i : {0, 1})
353 {
354 m_hat[i] = rho[i] * (vel_n[i] - shock_speed[i]);
355 I_hat[i] = m_hat[i] * vel_n[i] + pressure[i];
356 E_hat[i] = m_hat[i] * E_n[i] + pressure[i] * vel_n[i];
357 }
358
359 // 4) calculate intermediate velocity states
360
361 // TODO: consider surface tension for dim>1 here
362 const dealii::VectorizedArray<number> delta_p = 0.;
363
364 // TODO: consider Hertz-Knudsen theory for evaporation mass flux here
365 std::array<dealii::VectorizedArray<number>, 2> tmp_1;
366 std::array<dealii::VectorizedArray<number>, 2> tmp_2;
367 for (unsigned int i : {0, 1})
368 {
369 tmp_1[i] = m_dot_evap / m_hat[i];
370 tmp_2[i] = m_dot_evap - m_hat[i];
371 }
372
373 std::array<dealii::VectorizedArray<number>, 2> numerator;
374 std::array<dealii::VectorizedArray<number>, 2> denominator;
375
376 numerator[liquid] = tmp_2[gas] *
377 (tmp_1[liquid] * shock_speed[liquid] - tmp_1[gas] * shock_speed[gas]) /
378 (1. - tmp_1[gas]) -
379 I_hat[liquid] - delta_p + I_hat[gas];
380 numerator[gas] = tmp_2[liquid] *
381 (tmp_1[gas] * shock_speed[gas] - tmp_1[liquid] * shock_speed[liquid]) /
382 (1. - tmp_1[liquid]) -
383 I_hat[gas] + delta_p + I_hat[liquid];
384 denominator[liquid] = tmp_2[liquid] - (1. - tmp_1[liquid]) / (1. - tmp_1[gas]) * tmp_2[gas];
385 denominator[gas] = tmp_2[gas] - (1. - tmp_1[gas]) / (1. - tmp_1[liquid]) * tmp_2[liquid];
386
387 std::array<dealii::VectorizedArray<number>, 2> vel_n_star;
388 for (unsigned int i : {0, 1})
389 vel_n_star[i] = numerator[i] / denominator[i];
390
391 // 5) calculate intermediate pressure
392
393 std::array<dealii::VectorizedArray<number>, 2> pressure_star;
394 for (unsigned int i : {0, 1})
395 pressure_star[i] = I_hat[i] - m_hat[i] * vel_n_star[i];
396
397 // 6) re-project normal velocity to Cartesian coordinates
398
399 std::array<dealii::Tensor<1, dim, dealii::VectorizedArray<number>>, 2> vel_star_cartesian;
400
401 std::vector<dealii::Tensor<1, dim, dealii::VectorizedArray<number>>> tangent;
402 tangent.resize(dim - 1);
403
404 // compute tangential vector for dim=2 and dim=3
405 if constexpr (dim == 2)
406 {
407 tangent[0][0] = normal[1];
408 tangent[0][1] = -normal[0];
409 }
410 else if constexpr (dim == 3)
411 {
412 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> temp_vec;
413 temp_vec[0] = 1.;
414 // if normal vector is identical with unit vector choose different unit vector to
415 // compute the tangent
416 dealii::VectorizedArray<number> tolerance = 1.e-10;
417 dealii::VectorizedArray<number> norm_diff = (temp_vec - normal).norm();
418 dealii::Tensor<1, dim, dealii::VectorizedArray<number>> temp_vec_y;
419 temp_vec_y[1] = 1.;
420 for (int i = 0; i < 3; ++i)
421 {
422 temp_vec[i] = compare_and_apply_mask<dealii::SIMDComparison::less_than>(norm_diff,
423 tolerance,
424 temp_vec_y[i],
425 temp_vec[i]);
426 }
427 tangent[0] = temp_vec - (temp_vec * normal) * normal;
428 tangent[1] = dealii::cross_product_3d(normal, tangent[0]);
429 }
430
431 for (unsigned int i : {0, 1})
432 {
433 vel_star_cartesian[i] = vel_n_star[i] * normal;
434 for (unsigned int j = 0; j < dim - 1; ++j)
435 vel_star_cartesian[i] += (vel[i] * tangent[j]) * tangent[j];
436 }
437
438 // 7) calculate conservative variable state vectors of inner states
439
440 std::array<ConservedVariablesType, 2> u_star;
441 for (unsigned int i : {0, 1})
442 {
443 u_star[i][Idx::density] = m_hat[i] / (vel_n_star[i] - shock_speed[i]);
444 for (unsigned int j = 1; j < dim + 1; j++)
445 u_star[i][j] = u_star[i][Idx::density] * vel_star_cartesian[i][j - 1];
446 u_star[i][Idx::energy] =
447 (E_hat[i] - pressure_star[i] * vel_n_star[i]) / (vel_n_star[i] - shock_speed[i]) -
448 0.5 * u_star[i][Idx::density] * vel_n_star[i] * vel_n_star[i] +
449 0.5 * u_star[i][Idx::density] * vel_star_cartesian[i] * vel_star_cartesian[i];
450 }
451
452 // 8) calculate phase interface velocity
453
454 dealii::VectorizedArray<number> numerator_normal_vel =
455 vel_n_star[liquid] * u_star[liquid][Idx::density] -
456 vel_n_star[gas] * u_star[gas][Idx::density];
457 dealii::VectorizedArray<number> denominator_normal_vel =
458 u_star[liquid][Idx::density] - u_star[gas][Idx::density];
459 // avoid division by zero
460 dealii::VectorizedArray<number> normal_velocity_interface =
461 compare_and_apply_mask<dealii::SIMDComparison::greater_than>(std::abs(denominator_normal_vel),
462 1.e-12,
463 numerator_normal_vel /
464 denominator_normal_vel,
465 vel_n_star[liquid]);
466
467 // 9) calculate fluxes for the two phases
468
469 std::array<ConservedVariablesGradType, 2> flux;
470 std::array<ConservedVariablesGradType, 2> conv_flux;
471 std::array<ConservedVariablesGradType, 2> shock_flux;
472
473 conv_flux[liquid] = convective_kernel_liquid.flux(state[liquid].value());
474 conv_flux[gas] = convective_kernel_gas.flux(state[gas].value());
475
476 for (unsigned int i : {0, 1})
477 {
478 shock_flux[i] = dyadic_product(shock_speed[i] * (u_star[i] - state[i].value()), normal);
479 flux[i] = conv_flux[i];
480 }
481
482 const auto zero_vec = dealii::make_vectorized_array(0.);
483 const auto one_vec = dealii::make_vectorized_array(1.);
484
485 flux[liquid] +=
486 shock_flux[liquid] * compare_and_apply_mask<dealii::SIMDComparison::greater_than>(
487 shock_speed[liquid], zero_vec, zero_vec, one_vec);
488 flux[gas] +=
489 shock_flux[gas] * compare_and_apply_mask<dealii::SIMDComparison::less_than_or_equal>(
490 shock_speed[gas], zero_vec, zero_vec, one_vec);
491
492 return {flux[liquid], flux[gas], normal_velocity_interface};
493 }
494
498
518 template <int dim,
519 typename number,
520 typename ConservedVariablesType,
521 typename DofStateView,
522 typename DofValueView,
523 typename DofPrimitiveValueView,
524 typename DofPrimitiveStateView>
525 inline DEAL_II_ALWAYS_INLINE //
526 ConservedVariablesType
528 const DofStateView &liquid_cons_view,
529 const DofStateView &gas_cons_view,
531 const number &m_dot_evap,
532 const number &delta_T)
533 {
534 ConservedVariablesType liquid_prim_data;
535 ConservedVariablesType gas_prim_data;
536 DofPrimitiveValueView liquid_prim_view(liquid_prim_data);
537 DofPrimitiveValueView gas_prim_view(gas_prim_data);
538
539 CompressibleFlow::conservative_to_primitive<dim, DofStateView, DofPrimitiveValueView>(
540 liquid_cons_view, liquid_prim_view);
541 CompressibleFlow::conservative_to_primitive<dim, DofStateView, DofPrimitiveValueView>(
542 gas_cons_view, gas_prim_view);
543
544 // TODO: consider surface tension here
545 const dealii::VectorizedArray<number> delta_p = 0.;
546
547 // TODO: extend to general case dim>1
548 ConservedVariablesType J_Dir;
549
551
552 J_Dir[Idx::pressure] =
553 delta_p - m_dot_evap * (liquid_prim_view.velocity(0) - gas_prim_view.velocity(0));
554 J_Dir[Idx::velocity] =
555 m_dot_evap * (1. / liquid_cons_view.density() - 1. / gas_cons_view.density());
556 J_Dir[Idx::temperature] = delta_T;
557
558 const ConservedVariablesType liquid_prim_tmp = liquid_prim_view.value();
559
560 liquid_prim_view.value() = gas_prim_view.value() + J_Dir;
561 gas_prim_view.value() = liquid_prim_tmp - J_Dir;
562
563 ConservedVariablesType liquid_cons_star_data;
564 ConservedVariablesType gas_cons_star_data;
565 DofValueView liquid_cons_view_star(liquid_cons_star_data);
566 DofValueView gas_cons_view_star(gas_cons_star_data);
567
568 CompressibleFlow::primitive_to_conservative<dim, DofValueView, DofPrimitiveStateView>(
569 DofPrimitiveStateView(liquid_prim_view.value(), multiphase_scratch_data.material_liquid),
570 liquid_cons_view_star);
571 CompressibleFlow::primitive_to_conservative<dim, DofValueView, DofPrimitiveStateView>(
572 DofPrimitiveStateView(gas_prim_view.value(), multiphase_scratch_data.material_gas),
573 gas_cons_view_star);
574
575 J_Dir = liquid_cons_view_star.value() - gas_cons_view_star.value();
576
577 return J_Dir;
578 }
579
611 template <int dim,
612 typename number,
613 typename ConservedVariablesType,
614 typename ConservedVariablesGradType,
615 typename DofStateView,
616 typename DofValueView,
617 typename DofPrimitiveValueView,
618 typename DofPrimitiveStateView,
620 DiffusiveKernel>
621 inline DEAL_II_ALWAYS_INLINE //
622 std::pair<ConservedVariablesType, ConservedVariablesType>
624 const DofStateView &liquid_state,
625 const DofStateView &gas_state,
626 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
627 const number &visc_ave_weight_phase_liquid,
628 const number &visc_ave_weight_phase_gas,
629 const number &tau,
630 const DiffusiveKernel &diffusive_kernel_liquid,
631 const DiffusiveKernel &diffusive_kernel_gas,
633 const number &cell_size,
634 const number &m_dot_evap,
635 const number &delta_T,
636 const number &laser_heat_source)
637 {
638 // enumeration for conserved variables component indices
639 using Idx = std::conditional_t<
640 dim == 1,
641 CompressibleFlow::Idx1D,
642 std::conditional_t<dim == 2,
643 CompressibleFlow::Idx2D,
644 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
645
646 // TODO: add contributions for surface tension, interface heat source (laser energy) and
647 // Marangoni forces
648
649 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> vel_liquid =
650 liquid_state.velocity();
651 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> vel_gas = gas_state.velocity();
652
653 const dealii::VectorizedArray<number> vel_n_liquid = vel_liquid * normal;
654 const dealii::VectorizedArray<number> vel_n_gas = vel_gas * normal;
655
656 const auto pressure_liquid = liquid_state.pressure();
657 const auto pressure_gas = gas_state.pressure();
658
659 // compute Robin-type viscous interface jump conditions
660
661 ConservedVariablesType J_Rob;
662
663 // TODO: Add entries for case dim>1
664 J_Rob[Idx::energy] =
665 (pressure_liquid * vel_n_liquid - pressure_gas * vel_n_gas) +
666 m_dot_evap * (liquid_state.total_energy() / liquid_state.density() -
667 gas_state.total_energy() / gas_state.density()) +
668 laser_heat_source -
669 m_dot_evap * multiphase_scratch_data.phase_change.liquid_gas.latent_heat_of_vaporization;
670
671 const ConservedVariablesGradType viscous_flux_liquid =
672 diffusive_kernel_liquid.flux(liquid_state.value(), liquid_state.gradient_value());
673
674 const ConservedVariablesGradType viscous_flux_gas =
675 diffusive_kernel_gas.flux(gas_state.value(), gas_state.gradient_value());
676
677 ConservedVariablesGradType total_flux_liquid = dyadic_product(J_Rob, normal);
678 total_flux_liquid += viscous_flux_gas;
679 total_flux_liquid *= visc_ave_weight_phase_liquid;
680 total_flux_liquid += visc_ave_weight_phase_gas * viscous_flux_liquid;
681
682 ConservedVariablesGradType total_flux_gas =
683 dyadic_product(J_Rob, -normal); // opposite normal direction for phase 2
684 total_flux_gas += viscous_flux_liquid;
685 total_flux_gas *= visc_ave_weight_phase_gas;
686 total_flux_gas += visc_ave_weight_phase_liquid * viscous_flux_gas;
687
688 // penalty term
689
690 const auto J_Dir_cons =
692 number,
693 ConservedVariablesType,
694 DofStateView,
695 DofValueView,
696 DofPrimitiveValueView,
697 DofPrimitiveStateView>(
698 liquid_state, gas_state, multiphase_scratch_data, m_dot_evap, delta_T);
699
700 const number penalty_parameter =
701 std::min(liquid_state.dynamic_viscosity() /
702 multiphase_scratch_data.material_liquid.reference_density,
703 gas_state.dynamic_viscosity() /
704 multiphase_scratch_data.material_gas.reference_density) *
705 (multiphase_scratch_data.flow_data.fe.degree + 1.) *
706 (multiphase_scratch_data.flow_data.fe.degree + 1.) / cell_size * tau;
707
708 ConservedVariablesGradType penalty_flux_liquid;
709 const auto tmp_m = liquid_state.value() - (gas_state.value() + J_Dir_cons);
710 penalty_flux_liquid = dyadic_product(tmp_m, normal);
711 penalty_flux_liquid *= penalty_parameter;
712
713 ConservedVariablesGradType penalty_flux_gas;
714 const auto tmp_p = gas_state.value() - (liquid_state.value() - J_Dir_cons);
715 penalty_flux_gas = dyadic_product(tmp_p, -normal);
716 penalty_flux_gas *= penalty_parameter;
717
718 total_flux_liquid -= penalty_flux_liquid;
719 total_flux_gas -= penalty_flux_gas;
720
721 return {contract_tensor_with_vector<CompressibleFlow::n_conserved_variables<dim>, dim, number>(
722 total_flux_liquid, normal),
723 contract_tensor_with_vector<CompressibleFlow::n_conserved_variables<dim>, dim, number>(
724 total_flux_gas, normal)};
725 }
726
756 template <int dim,
757 typename number,
758 typename ConservedVariablesType,
759 typename ConservedVariablesGradType,
760 typename DofStateView,
761 typename DofValueView,
762 typename DofPrimitiveValueView,
763 typename DofPrimitiveStateView,
765 DiffusiveKernel>
766 inline DEAL_II_ALWAYS_INLINE //
767 std::pair<ConservedVariablesGradType, ConservedVariablesGradType>
769 const DofStateView &liquid_state,
770 const DofStateView &gas_state,
771 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
772 const number &visc_ave_weight_phase_liquid,
773 const number &visc_ave_weight_phase_gas,
774 const DiffusiveKernel &diffusive_kernel_liquid,
775 const DiffusiveKernel &diffusive_kernel_gas,
777 const number &m_dot_evap,
778 const number &delta_T)
779 {
780 const auto J_Dir_cons =
782 number,
783 ConservedVariablesType,
784 DofStateView,
785 DofValueView,
786 DofPrimitiveValueView,
787 DofPrimitiveStateView>(
788 liquid_state, gas_state, multiphase_scratch_data, m_dot_evap, delta_T);
789
790 const auto u_liquid_star =
792 liquid_state.value(),
793 visc_ave_weight_phase_liquid,
794 gas_state.value() + J_Dir_cons);
795 const auto u_gas_star =
797 gas_state.value(),
798 visc_ave_weight_phase_gas,
799 liquid_state.value() -
800 J_Dir_cons);
801
802 auto tmp_liquid = u_liquid_star - liquid_state.value();
803 auto tmp_gas = u_gas_star - gas_state.value();
804
805 ConservedVariablesGradType arg_liquid = dyadic_product(tmp_liquid, normal);
806 ConservedVariablesGradType arg_gas = dyadic_product(tmp_gas, -normal);
807
808 const ConservedVariablesGradType flux_grad_liquid =
809 diffusive_kernel_liquid.flux(liquid_state.value(), arg_liquid);
810 const ConservedVariablesGradType flux_grad_gas =
811 diffusive_kernel_gas.flux(gas_state.value(), arg_gas);
812
813 return {flux_grad_liquid, flux_grad_gas};
814 }
815
819
849 template <int dim,
850 typename number,
851 typename ConservedVariablesType,
852 typename ConservedVariablesGradType,
853 typename DofValueAndGradientStateView,
855 DiffusiveKernel>
856 inline DEAL_II_ALWAYS_INLINE //
857 std::pair<ConservedVariablesType, ConservedVariablesType>
859 const DofValueAndGradientStateView &liquid_state,
860 const DofValueAndGradientStateView &gas_state,
861 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
862 const number &visc_ave_weight_phase_liquid,
863 const number &visc_ave_weight_phase_gas,
864 const DiffusiveKernel &diffusive_kernel_liquid,
865 const DiffusiveKernel &diffusive_kernel_gas,
867 const number &cell_size,
868 const number &m_dot_evap,
869 const number &delta_T,
870 const number &laser_heat_source)
871 {
872 // enumeration for conserved variables component indices
873 using Idx = std::conditional_t<
874 dim == 1,
875 CompressibleFlow::Idx1D,
876 std::conditional_t<dim == 2,
877 CompressibleFlow::Idx2D,
878 std::conditional_t<dim == 3, CompressibleFlow::Idx3D, void>>>;
879
880 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> vel_liquid =
881 liquid_state.velocity();
882 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> vel_gas = gas_state.velocity();
883
884 const dealii::VectorizedArray<number> vel_n_liquid = vel_liquid * normal;
885 const dealii::VectorizedArray<number> vel_n_gas = vel_gas * normal;
886
887 const dealii::VectorizedArray<number> pressure_liquid = liquid_state.pressure();
888 const dealii::VectorizedArray<number> pressure_gas = gas_state.pressure();
889
890 // compute Robin-type viscous interface jump conditions
891 // TODO: add contributions for surface tension and Marangoni forces (for dim>1)
892
893 ConservedVariablesType J_Rob;
894
895 J_Rob[Idx::energy] =
896 m_dot_evap * (liquid_state.total_energy() / liquid_state.density() -
897 gas_state.total_energy() / gas_state.density()) +
898 (pressure_liquid * vel_n_liquid - pressure_gas * vel_n_gas) + laser_heat_source -
899 m_dot_evap * multiphase_scratch_data.phase_change.liquid_gas.latent_heat_of_vaporization;
900
901 const ConservedVariablesGradType viscous_flux_liquid =
902 diffusive_kernel_liquid.flux(liquid_state.value(), liquid_state.gradient_value());
903
904 const ConservedVariablesGradType viscous_flux_gas =
905 diffusive_kernel_gas.flux(gas_state.value(), gas_state.gradient_value());
906
907 ConservedVariablesType penalty_term_dT;
908 penalty_term_dT[Idx::energy] =
909 multiphase_scratch_data.phase_coupling.hllp0_and_penalty.penalty_parameter_temperature_jump *
910 (liquid_state.thermal_conductivity() + gas_state.thermal_conductivity()) / (2. * cell_size) *
911 ((liquid_state.temperature() - gas_state.temperature()) - delta_T);
912
913 const ConservedVariablesType weighted_viscous_flux =
915 visc_ave_weight_phase_gas,
916 contract_tensor_with_vector<CompressibleFlow::n_conserved_variables<dim>, dim, number>(
917 viscous_flux_liquid, normal),
918 visc_ave_weight_phase_liquid,
919 contract_tensor_with_vector<CompressibleFlow::n_conserved_variables<dim>, dim, number>(
920 viscous_flux_gas, normal));
921
922 const ConservedVariablesType total_viscous_flux_liquid =
923 -J_Rob * visc_ave_weight_phase_liquid - weighted_viscous_flux + penalty_term_dT;
924
925 const ConservedVariablesType total_viscous_flux_gas =
926 -J_Rob * visc_ave_weight_phase_gas + weighted_viscous_flux - penalty_term_dT;
927
928 return {total_viscous_flux_liquid, total_viscous_flux_gas};
929 }
930
939 template <typename number>
940 inline DEAL_II_ALWAYS_INLINE //
941 number
943 const number &time)
944 {
945 const auto &laser = phase_coupling_data.laser_heat_source;
946
947 if (laser.do_ramp and time < laser.ramp_time)
948 {
949 const number factor = 0.5 * (1. - std::cos(std::numbers::pi * time / laser.ramp_time));
950
951 return factor * laser.laser_power_density;
952 }
953
954 return laser.laser_power_density;
955 }
956
972 template <int dim,
973 typename number,
974 typename DofStateView>
975 inline DEAL_II_ALWAYS_INLINE //
976 std::tuple<number, number>
978 const DofStateView &liquid_state,
979 const DofStateView &gas_state,
980 const dealii::Tensor<1, dim, dealii::VectorizedArray<number>> &normal,
982 Evaporation::EvaporationModelKnight<number> *evaporation_model_knight = nullptr)
983 {
984 number m_dot_evap = 0.;
985 number delta_T = 0.;
986
987 if (evaporation_model_knight)
988 {
989 const dealii::VectorizedArray<number> T_liquid = liquid_state.temperature();
990
991 const dealii::VectorizedArray<number> vel_n_gas = gas_state.velocity() * normal;
992
993 const dealii::VectorizedArray<number> speed_of_sound_g = gas_state.temperature();
994
995 const dealii::VectorizedArray<number> Ma_g = vel_n_gas / speed_of_sound_g;
996
997 // TODO: evaluate vectorized array for dim>1!
998 evaporation_model_knight->reinit(T_liquid[0], Ma_g[0]);
999 m_dot_evap = evaporation_model_knight->get_evaporative_mass_flux();
1000 delta_T = evaporation_model_knight->get_temperature_jump();
1001 }
1002 else if (multiphase_scratch_data.phase_coupling.evaporation_model ==
1003 EvaporationModelType::constant)
1004 {
1005 m_dot_evap = multiphase_scratch_data.phase_coupling.m_dot_evap;
1006
1007 switch (multiphase_scratch_data.phase_coupling.type)
1008 {
1009 case InterfaceNumericalMethod::HLLP0_and_SIPG:
1010 delta_T = multiphase_scratch_data.phase_coupling.hllp0_and_sipg.delta_T;
1011 break;
1012
1013 case InterfaceNumericalMethod::HLLP0_and_penalty:
1014 delta_T = multiphase_scratch_data.phase_coupling.hllp0_and_penalty.delta_T;
1015 break;
1016
1017 default:
1018 break;
1019 }
1020 }
1021 else
1022 {
1023 AssertThrow(false,
1024 dealii::ExcNotImplemented("The given evaporation model is not implemented."));
1025 }
1026
1027 return {m_dot_evap, delta_T};
1028 }
1029} // 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:219
DEAL_II_ALWAYS_INLINE dealii::Tensor< 2, dim, dealii::VectorizedArray< number > > calculate_cauchy_stress_tensor(const dealii::VectorizedArray< number > &pressure, const dealii::Tensor< 2, dim, dealii::VectorizedArray< number > > &viscous_stress_tensor)
Calculate the total stress tensor (Cauchy stress tensor) from pressure contribution and viscous stres...
Definition utils.hpp:519
A collection of functions for the computation of the interface terms for compressible two-phase flows...
Definition multiphase_interface_kernels.hpp:32
DEAL_II_ALWAYS_INLINE std::tuple< number, number > update_evaporative_mass_flux_and_temperature_jump(const DofStateView &liquid_state, const DofStateView &gas_state, 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:977
DEAL_II_ALWAYS_INLINE std::pair< ConservedVariablesType, ConservedVariablesType > calculate_viscous_interface_flux(const DofStateView &liquid_state, const DofStateView &gas_state, 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:623
DEAL_II_ALWAYS_INLINE std::pair< ConservedVariablesGradType, ConservedVariablesGradType > calculate_viscous_interface_flux_gradient(const DofStateView &liquid_state, const DofStateView &gas_state, 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:768
DEAL_II_ALWAYS_INLINE ConservedVariablesType calculate_Dirichlet_jump_in_conservative_variables(const DofStateView &liquid_cons_view, const DofStateView &gas_cons_view, 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:527
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:942
DEAL_II_ALWAYS_INLINE std::pair< ConservedVariablesType, ConservedVariablesType > calculate_viscous_interface_flux_method_3(const DofValueAndGradientStateView &liquid_state, const DofValueAndGradientStateView &gas_state, 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:858
DEAL_II_ALWAYS_INLINE std::tuple< ConservedVariablesGradType, ConservedVariablesGradType, dealii::VectorizedArray< number > > calculate_convective_interface_flux_HLLP0(const DofStateView &liquid_state, const DofStateView &gas_state, const dealii::Tensor< 1, dim, dealii::VectorizedArray< number > > &normal, const ConvectiveKernel &convective_kernel_liquid, const ConvectiveKernel &convective_kernel_gas, const number &m_dot_evap)
HLLP0 Riemann solver ///.
Definition multiphase_interface_kernels.hpp:292
DEAL_II_ALWAYS_INLINE std::pair< ConservedVariablesType, ConservedVariablesType > calculate_convective_and_viscous_interface_flux_penalty(const DofValueAndGradientStateView &liquid_state, const DofValueAndGradientStateView &gas_state, 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:61
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
This file provides a collection of view types for the compressible Navier–Stokes solver....
Scratch data structure for compressible multiphase flow solvers.
Definition operation_scratch_data.hpp:152
const Multiphase::CompressibleFlowPhaseCouplingData< number > phase_coupling
Parameters for the coupling of two compressible (or nearly incompressible) phases.
Definition operation_scratch_data.hpp:214
const OperationData< number > flow_data
General parameters for the compressible Navier-Stokes operators.
Definition operation_scratch_data.hpp:196
const MaterialPhaseData< number > material_liquid
Material parameters for the liquid phase.
Definition operation_scratch_data.hpp:205
const MaterialPhaseData< number > material_gas
Material parameters for the gas phase.
Definition operation_scratch_data.hpp:202
const Multiphase::PhaseChangeData< number > phase_change
Parameters related to liquid-gas and solid-liquid phase transitions.
Definition operation_scratch_data.hpp:208
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