Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #include "WCNSFV2PInterfaceAreaSourceSink.h"
11 : #include "NS.h"
12 : #include "NonlinearSystemBase.h"
13 : #include "NavierStokesMethods.h"
14 :
15 : registerMooseObject("NavierStokesApp", WCNSFV2PInterfaceAreaSourceSink);
16 :
17 : InputParameters
18 57 : WCNSFV2PInterfaceAreaSourceSink::validParams()
19 : {
20 57 : InputParameters params = FVElementalKernel::validParams();
21 57 : params.addClassDescription(
22 : "Source and sink of interfacial area for two-phase flow mixture model.");
23 114 : params.addRequiredParam<MooseFunctorName>("u", "The velocity in the x direction.");
24 114 : params.addParam<MooseFunctorName>("v", "The velocity in the y direction.");
25 114 : params.addParam<MooseFunctorName>("w", "The velocity in the z direction.");
26 :
27 114 : params.addParam<MooseFunctorName>("L", 1.0, "The characteristic dissipation length.");
28 57 : params.addRequiredParam<MooseFunctorName>(NS::density, "Continuous phase density.");
29 114 : params.addRequiredParam<MooseFunctorName>(NS::density + std::string("_d"),
30 : "Dispersed phase density.");
31 57 : params.addRequiredParam<MooseFunctorName>(NS::pressure, "Continuous phase density.");
32 114 : params.addParam<MooseFunctorName>(
33 114 : "k_c", 0.0, "Mass exchange coefficients from continous to dispersed phases.");
34 114 : params.addParam<MooseFunctorName>("fd", 0.0, "Fraction dispersed phase.");
35 114 : params.addParam<Real>("fd_max", 1.0, "Maximum dispersed phase fraction.");
36 :
37 114 : params.addParam<MooseFunctorName>("sigma", 1.0, "Surface tension between phases.");
38 114 : params.addParam<MooseFunctorName>("particle_diameter", 1.0, "Maximum particle diameter.");
39 :
40 114 : params.addParam<Real>("cutoff_fraction",
41 114 : 0.1,
42 : "Void fraction at which the interface area density mass transfer model is "
43 : "activated. Below this fraction, spherical bubbles are assumed.");
44 :
45 57 : params.set<unsigned short>("ghost_layers") = 2;
46 :
47 57 : return params;
48 0 : }
49 :
50 30 : WCNSFV2PInterfaceAreaSourceSink::WCNSFV2PInterfaceAreaSourceSink(const InputParameters & params)
51 : : FVElementalKernel(params),
52 30 : _dim(_subproblem.mesh().dimension()),
53 60 : _u_var(getFunctor<ADReal>("u")),
54 90 : _v_var(params.isParamValid("v") ? &(getFunctor<ADReal>("v")) : nullptr),
55 30 : _w_var(params.isParamValid("w") ? &(getFunctor<ADReal>("w")) : nullptr),
56 60 : _characheristic_length(getFunctor<ADReal>("L")),
57 30 : _rho_mixture(getFunctor<ADReal>(NS::density)),
58 90 : _rho_d(getFunctor<ADReal>(NS::density + std::string("_d"))),
59 30 : _pressure(getFunctor<ADReal>(NS::pressure)),
60 60 : _mass_exchange_coefficient(getFunctor<ADReal>("k_c")),
61 60 : _f_d(getFunctor<ADReal>("fd")),
62 60 : _f_d_max(getParam<Real>("fd_max")),
63 60 : _sigma(getFunctor<ADReal>("sigma")),
64 60 : _particle_diameter(getFunctor<ADReal>("particle_diameter")),
65 90 : _cutoff_fraction(getParam<Real>("cutoff_fraction"))
66 : {
67 30 : if (_dim >= 2 && !_v_var)
68 0 : paramError("v", "In two or more dimensions, the v velocity must be supplied!");
69 :
70 30 : if (_dim >= 3 && !_w_var)
71 0 : paramError("w", "In three or more dimensions, the w velocity must be supplied!");
72 30 : }
73 :
74 : ADReal
75 63100 : WCNSFV2PInterfaceAreaSourceSink::computeQpResidual()
76 : {
77 : using std::max, std::pow, std::exp, std::sqrt;
78 :
79 : // Useful Arguments
80 63100 : const auto state = determineState();
81 63100 : const auto elem_arg = makeElemArg(_current_elem);
82 63100 : const bool is_transient = _subproblem.isTransient();
83 :
84 : // Current Variables
85 63100 : const auto u = _u_var(elem_arg, state);
86 63100 : const auto rho_d = _rho_d(elem_arg, state);
87 63100 : const auto rho_d_grad = _rho_d.gradient(elem_arg, state);
88 63100 : const auto xi = _var(elem_arg, state);
89 63100 : const auto rho_m = _rho_mixture(elem_arg, state);
90 63100 : const auto f_d = _f_d(elem_arg, state);
91 63100 : const auto sigma = _sigma(elem_arg, state);
92 63100 : const auto rho_l = (rho_m - f_d * rho_d) / (1.0 - f_d + libMesh::TOLERANCE);
93 126200 : const auto complement_fd = max(_f_d_max - f_d, libMesh::TOLERANCE);
94 63100 : const auto f_d_o_xi = f_d / (_var(elem_arg, state) + libMesh::TOLERANCE) + libMesh::TOLERANCE;
95 : const auto f_d_o_xi_old =
96 126200 : f_d / (raw_value(_var(elem_arg, state)) + libMesh::TOLERANCE) + libMesh::TOLERANCE;
97 :
98 : // Adding bubble compressibility term
99 : ADReal material_time_derivative_rho_d = u * rho_d_grad(0);
100 63100 : if (_dim > 1)
101 : {
102 126200 : material_time_derivative_rho_d += (*_v_var)(elem_arg, state) * rho_d_grad(1);
103 63100 : if (_dim > 2)
104 : {
105 0 : material_time_derivative_rho_d += (*_w_var)(elem_arg, state) * rho_d_grad(2);
106 : }
107 : }
108 63100 : if (is_transient)
109 : material_time_derivative_rho_d +=
110 90200 : raw_value(_rho_d(elem_arg, state) - _rho_d(elem_arg, Moose::oldState())) / _dt;
111 126200 : const auto bubble_compressibility = material_time_derivative_rho_d * xi / 3.0;
112 :
113 : // Adding area growth due to added mass
114 : ADReal bubble_added_mass;
115 63100 : if (f_d < _cutoff_fraction)
116 0 : bubble_added_mass = raw_value(_rho_d(elem_arg, state)) *
117 0 : (f_d * 6.0 / _particle_diameter(elem_arg, state) - _var(elem_arg, state));
118 : else
119 63100 : bubble_added_mass = 2. / 3. * _mass_exchange_coefficient(elem_arg, state) *
120 126200 : (1.0 / (f_d + libMesh::TOLERANCE) - 2.0);
121 :
122 : // Model parameters
123 63100 : const auto db = _shape_factor * f_d_o_xi_old + libMesh::TOLERANCE;
124 :
125 126200 : ADRealVectorValue velocity(u);
126 63100 : if (_v_var)
127 63100 : velocity(1) = (*_v_var)(elem_arg, state);
128 63100 : if (_w_var)
129 0 : velocity(2) = (*_w_var)(elem_arg, state);
130 :
131 63100 : const ADReal velocity_norm = NS::computeSpeed<ADReal>(velocity);
132 126200 : const auto pressure_gradient = raw_value(_pressure.gradient(elem_arg, state));
133 : const Real pressure_grad_norm =
134 63100 : MooseUtils::isZero(pressure_gradient) ? 1e-42 : pressure_gradient.norm();
135 :
136 : const auto u_eps =
137 126200 : pow(velocity_norm * _characheristic_length(elem_arg, state) * pressure_grad_norm / rho_m,
138 126200 : 1. / 3.);
139 :
140 : const auto interaction_prefactor =
141 126200 : Utility::pow<2>(f_d_o_xi) * u_eps / (pow(db, 11. / 3.) / complement_fd);
142 :
143 : // Adding coalescence term
144 63100 : const auto f_c = interaction_prefactor * _gamma_c * Utility::pow<2>(f_d);
145 126200 : const auto exp_c = exp(-_Kc * pow(db, 5. / 6.) * sqrt(rho_l / sigma) * u_eps);
146 : const auto s_rc = f_c * exp_c;
147 :
148 : // Adding breakage term
149 126200 : const auto f_b = interaction_prefactor * _gamma_b * f_d * (1. - f_d);
150 189300 : const auto exp_b = exp(-_Kb * sigma / (rho_l * pow(db, 5. / 3.) * Utility::pow<2>(u_eps)));
151 : const auto s_rb = f_b * exp_b;
152 :
153 126200 : return -bubble_added_mass + bubble_compressibility + s_rc - s_rb;
154 : }
|