32 double const t,
double const dt, std::vector<double>
const& local_x,
33 std::vector<double>
const& local_x_prev, std::vector<double>& local_M_data,
34 std::vector<double>& local_K_data, std::vector<double>& local_b_data)
36 auto const local_matrix_size = local_x.size();
38 assert(local_matrix_size == ShapeFunction::NPOINTS *
NUM_NODAL_DOF);
41 local_M_data, local_matrix_size, local_matrix_size);
43 local_K_data, local_matrix_size, local_matrix_size);
45 local_b_data, local_matrix_size);
48 auto Mvv = local_M.template block<velocity_size, velocity_size>(
51 auto Mhp = local_M.template block<enthalpy_size, pressure_size>(
53 auto Mhh = local_M.template block<enthalpy_size, enthalpy_size>(
56 auto Kpv = local_K.template block<pressure_size, velocity_size>(
59 auto Kvp = local_K.template block<velocity_size, pressure_size>(
61 auto Kvv = local_K.template block<velocity_size, velocity_size>(
64 auto Khh = local_K.template block<enthalpy_size, enthalpy_size>(
71 unsigned const n_integration_points =
83 auto const& liquid_phase =
89 auto const t_ca =
_process_data.wellbore.casing_thickness(t, pos)[0];
91 auto const r_w =
_process_data.wellbore.diameter(t, pos)[0] / 2;
94 auto const t_p =
_process_data.wellbore.pipe_thickness(t, pos)[0];
99 auto const r_o = r_w - t_ca;
101 auto const r_i = r_o - t_p;
105 _process_data.reservoir_properties.temperature.getNodalValuesOnElement(
108 _process_data.reservoir_properties.pressure.getNodalValuesOnElement(
113 _process_data.reservoir_properties.thermal_conductivity(t, pos)[0];
114 auto const rho_r =
_process_data.reservoir_properties.density(t, pos)[0];
116 _process_data.reservoir_properties.specific_heat_capacity(t, pos)[0];
118 for (
unsigned ip(0); ip < n_integration_points; ip++)
121 auto const& N = ip_data.N;
122 auto const& dNdx = ip_data.dNdx;
123 auto const& w = ip_data.integration_weight;
124 auto& mix_density = ip_data.mix_density;
125 auto& temperature = ip_data.temperature;
126 auto& steam_mass_frac = ip_data.dryness;
127 auto& vapor_volume_frac = ip_data.vapor_volume_fraction;
128 auto& vapor_mass_flowrate = ip_data.vapor_mass_flow_rate;
129 auto& liquid_mass_flowrate = ip_data.liquid_mass_flow_rate;
137 double p_int_pt = 0.0;
138 double v_int_pt = 0.0;
139 double h_int_pt = 0.0;
144 double p_prev_int_pt = 0.0;
145 double v_prev_int_pt = 0.0;
146 double h_prev_int_pt = 0.0;
149 v_prev_int_pt, h_prev_int_pt);
151 double vdot_int_pt = (v_int_pt - v_prev_int_pt) / dt;
155 const double pi = std::numbers::pi;
171 double T_int_pt = 0.;
172 double liquid_water_density = 0.;
173 double vapour_water_density = 0.;
175 std::optional<MaterialPropertyLib::DriftFluxState> drift_flux_state;
183 .template value<double>(vars, pos, t, dt);
188 "the compressed liquid state of the WellboreSimulator "
191 liquid_water_density =
194 .template value<double>(vars, pos, t, dt);
198 liquid_water_density =
202 .template value<double>(vars, pos, t, dt);
203 vapour_water_density =
207 .template value<double>(vars, pos, t, dt);
209 double const h_sat_liq_w =
213 .template value<double>(vars, pos, t, dt);
214 double const h_sat_vap_w =
218 .template value<double>(vars, pos, t, dt);
228 .template value<double>(vars, pos, t, dt)
231 saturation_temperature)
232 .template value<double>(vars, pos, t, dt);
244 dryness, T_int_pt, vapour_water_density, liquid_water_density,
248 auto const alpha_solution =
255 "The drift-flux closure of the WellboreSimulator process "
256 "has no admissible vapour void fraction in element {:d}, "
257 "integration point {:d}: pressure {:g} Pa, mixture "
258 "velocity {:g} m/s, specific enthalpy {:g} J/kg, "
259 "temperature {:g} K, {}",
260 _element.getID(), ip, p_int_pt, v_int_pt, h_int_pt,
263 *drift_flux_state)));
266 alpha = *alpha_solution;
270 liquid_water_density =
273 .template value<double>(vars, pos, t, dt);
277 steam_mass_frac = dryness;
278 temperature = T_int_pt;
279 vapor_volume_frac = alpha;
282 vapour_water_density * alpha + liquid_water_density * (1 - alpha);
284 auto& mix_density_prev = ip_data.mix_density_prev;
287 auto const rho_dot = (mix_density - mix_density_prev) / dt;
289 double const liquid_water_velocity_act =
290 (alpha == 0) ? v_int_pt
292 : (1 - dryness) * mix_density * v_int_pt /
293 (1 - alpha) / liquid_water_density;
294 double const vapor_water_velocity_act =
296 : dryness * mix_density * v_int_pt /
297 (alpha * vapour_water_density);
299 vapor_mass_flowrate = vapor_water_velocity_act * vapour_water_density *
300 pi * r_i * r_i * alpha;
302 liquid_mass_flowrate = liquid_water_velocity_act *
303 liquid_water_density * pi * r_i * r_i *
306 double const gamma = drift_flux_state
308 alpha, *drift_flux_state)
313 .template value<double>(vars, pos, t, dt);
314 double const Re = mix_density * v_int_pt * 2 * r_i / miu;
322 if (Re > 10 && Re <= 2400)
328 f = std::pow(std::log(xi / 3.7 / r_i) -
329 5.02 / Re * std::log(xi / 3.7 / r_i + 13 / Re),
335 double const T_r_int_pt = N.dot(T_r);
342 const double alpha_r = k_r / rho_r / c_r;
343 const double t_d = alpha_r * t / (r_i * r_i);
348 beta = 1 / std::sqrt(pi * t_d) + 0.5 -
349 0.25 * std::sqrt(t_d / pi) + 0.125 * t_d;
353 beta = 2 * (1 / (std::log(4 * t_d) - 2 * 0.57722) -
355 std::pow((std::log(4 * t_d) - 2 * 0.57722), 2));
358 const double P_c = 2 * pi * r_i;
359 Q_hx = P_c * k_r * (T_r_int_pt - T_int_pt) / r_i * beta;
363 double const p_r_int_pt = N.dot(p_r);
364 double const PI_int_pt = N.dot(
PI);
365 double Q_mx = PI_int_pt * (p_int_pt - p_r_int_pt);
373 Q_mom = Q_mx * v_int_pt;
378 double const h_fres =
381 .template value<double>(vars, pos, t, dt);
382 Q_ene = Q_mx * h_fres;
386 Mvv.noalias() += w * N.transpose() * mix_density * N;
388 Mhp.noalias() += -w * N.transpose() * N;
389 Mhh.noalias() += w * N.transpose() * mix_density * N;
392 Kpv.noalias() += w * dNdx.transpose() * N * mix_density;
394 Kvp.noalias() += w * N.transpose() * dNdx;
395 Kvv.noalias() += w * N.transpose() * rho_dot * N;
397 Khh.noalias() += w * N.transpose() * mix_density * v_int_pt * dNdx;
400 Bp.noalias() += w * N.transpose() * rho_dot + w * N.transpose() * Q_mx;
403 w * dNdx.transpose() * mix_density * v_int_pt * v_int_pt +
404 w * dNdx.transpose() * gamma -
405 w * N.transpose() * f * mix_density * std::abs(v_int_pt) *
406 v_int_pt / (4 * r_i) -
407 w * N.transpose() * Q_mom;
410 -1 / 2 * w * N.transpose() * rho_dot * v_int_pt * v_int_pt -
411 w * N.transpose() * mix_density * v_int_pt * vdot_int_pt +
412 1 / 2 * w * dNdx.transpose() * mix_density * v_int_pt * v_int_pt *
414 w * N.transpose() * (Q_hx / pi / r_i / r_i) -
415 w * N.transpose() * Q_ene;
422 Bv.noalias() += gravity_operator * mix_density;
423 Bh.noalias() += gravity_operator * mix_density * v_int_pt;