OGS
ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim > Class Template Reference

Detailed Description

template<typename ShapeFunction, int GlobalDim>
class ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >

Definition at line 38 of file WellboreSimulatorFEM.h.

#include <WellboreSimulatorFEM.h>

Inheritance diagram for ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >:
[legend]
Collaboration diagram for ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >:
[legend]

Public Types

using ResidualVector = Eigen::Matrix<double, jacobian_residual_size, 1>
 
using JacobianMatrix
 
using UnknownVector = Eigen::Matrix<double, jacobian_residual_size, 1>
 

Public Member Functions

 WellboreSimulatorFEM (MeshLib::Element const &element, std::size_t const, NumLib::GenericIntegrationMethod const &integration_method, bool const is_axially_symmetric, WellboreSimulatorProcessData const &process_data)
 
void assemble (double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &local_x_prev, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data) override
 
void calculateResidual (double const alpha, double const vapor_water_density, double const liquid_water_density, double const v_mix, double const dryness, double const C_0, double const u_gu, ResidualVector &res)
 
void calculateJacobian (double const alpha, double const vapor_water_density, double const liquid_water_density, double const v_mix, double const dryness, double const C_0, double const u_gu, JacobianMatrix &Jac)
 
Eigen::Map< const Eigen::RowVectorXd > getShapeMatrix (const unsigned integration_point) const override
 Provides the shape matrix at the given integration point.
 
void computeSecondaryVariableConcrete (double const, double const, Eigen::VectorXd const &, Eigen::VectorXd const &) override
 
void postTimestepConcrete (Eigen::VectorXd const &, Eigen::VectorXd const &, double const, double const, int const) override
 
- Public Member Functions inherited from ProcessLib::WellboreSimulator::WellboreSimulatorLocalAssemblerInterface
 WellboreSimulatorLocalAssemblerInterface ()=default
 
- Public Member Functions inherited from ProcessLib::LocalAssemblerInterface
virtual ~LocalAssemblerInterface ()=default
 
virtual void setInitialConditions (std::size_t const mesh_item_id, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, std::vector< GlobalVector * > const &x, double const t, int const process_id)
 
virtual void initialize (std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
 
virtual void preAssemble (double const, double const, std::vector< double > const &)
 
virtual void assembleForStaggeredScheme (double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, int const process_id, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data)
 
virtual void assembleWithJacobian (double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &local_x_prev, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data)
 
virtual void assembleWithJacobianForStaggeredScheme (double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, int const process_id, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data)
 
virtual void computeSecondaryVariable (std::size_t const mesh_item_id, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, double const t, double const dt, std::vector< GlobalVector * > const &x, GlobalVector const &x_prev, int const process_id)
 
virtual void preTimestep (std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table, GlobalVector const &x, double const t, double const delta_t)
 
virtual void postTimestep (std::size_t const mesh_item_id, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &x_prev, double const t, double const dt, int const process_id)
 
void postNonLinearSolver (std::size_t const mesh_item_id, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &x_prev, double const t, double const dt, int const process_id)
 
virtual Eigen::Vector3d getFlux (MathLib::Point3d const &, double const, std::vector< double > const &) const
 
virtual Eigen::Vector3d getFlux (MathLib::Point3d const &, double const, std::vector< std::vector< double > > const &) const
 Fits to staggered scheme.
 
- Public Member Functions inherited from NumLib::ExtrapolatableElement
virtual ~ExtrapolatableElement ()=default
 

Static Public Attributes

static int const jacobian_residual_size = 1
 

Protected Types

using IpData
 

Protected Member Functions

virtual std::vector< double > const & getIntPtVaporMassFlowRate (const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
 
virtual std::vector< double > const & getIntPtLiquidMassFlowRate (const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
 
virtual std::vector< double > const & getIntPtTemperature (const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
 
virtual std::vector< double > const & getIntPtDryness (const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
 
virtual std::vector< double > const & getIntPtVaporVolumeFraction (const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
 

Protected Attributes

MeshLib::Element const & _element
 
NumLib::GenericIntegrationMethod const & _integration_method
 
bool const _is_axially_symmetric
 
WellboreSimulatorProcessData const & _process_data
 
Eigen::Vector3d _element_direction
 
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
 

Static Protected Attributes

static const int pressure_index = 0
 
static const int velocity_index = ShapeFunction::NPOINTS
 
static const int enthalpy_index = 2 * ShapeFunction::NPOINTS
 
static const int pressure_size = ShapeFunction::NPOINTS
 
static const int velocity_size = ShapeFunction::NPOINTS
 
static const int enthalpy_size = ShapeFunction::NPOINTS
 

Private Types

using ShapeMatricesType = ShapeMatrixPolicyType<ShapeFunction, GlobalDim>
 
using ShapeMatrices = typename ShapeMatricesType::ShapeMatrices
 
using LocalMatrixType
 
using LocalVectorType
 
using NodalVectorType = typename ShapeMatricesType::NodalVectorType
 
using NodalRowVectorType = typename ShapeMatricesType::NodalRowVectorType
 
using GlobalDimVectorType = typename ShapeMatricesType::GlobalDimVectorType
 
using GlobalDimNodalMatrixType
 
using GlobalDimMatrixType = typename ShapeMatricesType::GlobalDimMatrixType
 

Member Typedef Documentation

◆ GlobalDimMatrixType

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::GlobalDimMatrixType = typename ShapeMatricesType::GlobalDimMatrixType
private

Definition at line 56 of file WellboreSimulatorFEM.h.

◆ GlobalDimNodalMatrixType

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::GlobalDimNodalMatrixType
private
Initial value:
MatrixType< GlobalDim, ShapeFunction::NPOINTS > GlobalDimNodalMatrixType

Definition at line 54 of file WellboreSimulatorFEM.h.

◆ GlobalDimVectorType

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::GlobalDimVectorType = typename ShapeMatricesType::GlobalDimVectorType
private

Definition at line 53 of file WellboreSimulatorFEM.h.

◆ IpData

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::IpData
protected
Initial value:
IntegrationPointData<NodalRowVectorType, GlobalDimNodalMatrixType>

Definition at line 275 of file WellboreSimulatorFEM.h.

◆ JacobianMatrix

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::JacobianMatrix
Initial value:

Definition at line 139 of file WellboreSimulatorFEM.h.

◆ LocalMatrixType

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::LocalMatrixType
private
Initial value:
typename ShapeMatricesType::template MatrixType<
NUM_NODAL_DOF * ShapeFunction::NPOINTS,
NUM_NODAL_DOF * ShapeFunction::NPOINTS>

Definition at line 43 of file WellboreSimulatorFEM.h.

◆ LocalVectorType

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::LocalVectorType
private
Initial value:
typename ShapeMatricesType::template VectorType<NUM_NODAL_DOF *
ShapeFunction::NPOINTS>

Definition at line 46 of file WellboreSimulatorFEM.h.

◆ NodalRowVectorType

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::NodalRowVectorType = typename ShapeMatricesType::NodalRowVectorType
private

Definition at line 51 of file WellboreSimulatorFEM.h.

◆ NodalVectorType

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::NodalVectorType = typename ShapeMatricesType::NodalVectorType
private

Definition at line 50 of file WellboreSimulatorFEM.h.

◆ ResidualVector

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::ResidualVector = Eigen::Matrix<double, jacobian_residual_size, 1>

Definition at line 138 of file WellboreSimulatorFEM.h.

◆ ShapeMatrices

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::ShapeMatrices = typename ShapeMatricesType::ShapeMatrices
private

Definition at line 41 of file WellboreSimulatorFEM.h.

◆ ShapeMatricesType

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::ShapeMatricesType = ShapeMatrixPolicyType<ShapeFunction, GlobalDim>
private

Definition at line 40 of file WellboreSimulatorFEM.h.

◆ UnknownVector

template<typename ShapeFunction , int GlobalDim>
using ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::UnknownVector = Eigen::Matrix<double, jacobian_residual_size, 1>

Definition at line 142 of file WellboreSimulatorFEM.h.

Constructor & Destructor Documentation

◆ WellboreSimulatorFEM()

template<typename ShapeFunction , int GlobalDim>
ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::WellboreSimulatorFEM ( MeshLib::Element const & element,
std::size_t const ,
NumLib::GenericIntegrationMethod const & integration_method,
bool const is_axially_symmetric,
WellboreSimulatorProcessData const & process_data )
inline

Definition at line 59 of file WellboreSimulatorFEM.h.

65 : _element(element),
66 _integration_method(integration_method),
67 _is_axially_symmetric(is_axially_symmetric),
68 _process_data(process_data)
69 {
70 // calculate the element direction vector
71 auto const& p0 = element.getNode(0)->asEigenVector3d();
72 auto const& p1 = element.getNode(1)->asEigenVector3d();
73
74 _element_direction = (p1 - p0).normalized();
75
76 unsigned const n_integration_points =
78 _ip_data.reserve(n_integration_points);
79
80 auto const shape_matrices =
82 GlobalDim>(element, is_axially_symmetric,
84
87 auto const& medium =
89 auto const& liquid_phase = medium.phase("AqueousLiquid");
90
91 for (unsigned ip = 0; ip < n_integration_points; ip++)
92 {
93 _ip_data.emplace_back(
94 shape_matrices[ip].N, shape_matrices[ip].dNdx,
96 shape_matrices[ip].integralMeasure *
97 shape_matrices[ip].detJ);
98
99 pos.setIntegrationPoint(ip);
101
102 NodalVectorType ref_p =
104 _element, 0);
105 NodalVectorType ref_h =
107 _element, 0);
108
109 vars.liquid_phase_pressure = _ip_data[ip].N.dot(ref_p);
110 vars.enthalpy = _ip_data[ip].N.dot(ref_h);
111
112 // .initialValue
113 _ip_data[ip].temperature =
114 liquid_phase
116 .template value<double>(vars, pos, 0, 0);
117 vars.temperature = _ip_data[ip].temperature;
118 _ip_data[ip].mix_density =
119 liquid_phase
121 .template value<double>(vars, pos, 0, 0);
122 _ip_data[ip].dryness = 0;
123 _ip_data[ip].vapor_volume_fraction = 0;
124 _ip_data[ip].vapor_mass_flow_rate = 0;
125 _ip_data[ip].liquid_mass_flow_rate = 0;
126 _ip_data[ip].pushBackState();
127 }
128 }
Phase const & phase(std::size_t index) const
Definition Medium.cpp:33
double getWeight() const
std::size_t getID() const
Returns the ID of the element.
Definition Element.h:89
MathLib::WeightedPoint const & getWeightedPoint(unsigned const igp) const
void setElementID(std::size_t element_id)
typename ShapeMatricesType::NodalVectorType NodalVectorType
NumLib::GenericIntegrationMethod const & _integration_method
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatricesType
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > initShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, IntegrationMethod const &integration_method)
virtual Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > getNodalValuesOnElement(MeshLib::Element const &element, double const t) const
Returns a matrix of values for all nodes of the given element.
Definition Parameter.h:164
MaterialPropertyLib::MaterialSpatialDistributionMap media_map

References ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_element, ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_element_direction, ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_integration_method, ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_ip_data, ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_process_data, MathLib::Point3d::asEigenVector3d(), MaterialPropertyLib::density, MaterialPropertyLib::VariableArray::enthalpy, MeshLib::Element::getID(), MaterialPropertyLib::MaterialSpatialDistributionMap::getMedium(), ParameterLib::Parameter< T >::getNodalValuesOnElement(), MeshLib::Element::getNode(), NumLib::GenericIntegrationMethod::getNumberOfPoints(), MathLib::WeightedPoint::getWeight(), NumLib::GenericIntegrationMethod::getWeightedPoint(), NumLib::initShapeMatrices(), MaterialPropertyLib::VariableArray::liquid_phase_pressure, ProcessLib::WellboreSimulator::WellboreSimulatorProcessData::media_map, MaterialPropertyLib::Medium::phase(), ParameterLib::SpatialPosition::setElementID(), MaterialPropertyLib::temperature, MaterialPropertyLib::VariableArray::temperature, ProcessLib::WellboreSimulator::WellboreSimulatorProcessData::well_ref_enthalpy, and ProcessLib::WellboreSimulator::WellboreSimulatorProcessData::well_ref_pressure.

Member Function Documentation

◆ assemble()

template<typename ShapeFunction , int GlobalDim>
void ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::assemble ( double const t,
double const dt,
std::vector< double > const & local_x,
std::vector< double > const & local_x_prev,
std::vector< double > & local_M_data,
std::vector< double > & local_K_data,
std::vector< double > & local_b_data )
overridevirtual

Reimplemented from ProcessLib::LocalAssemblerInterface.

Definition at line 28 of file WellboreSimulatorFEM-impl.h.

32{
33 auto const local_matrix_size = local_x.size();
34
35 assert(local_matrix_size == ShapeFunction::NPOINTS * NUM_NODAL_DOF);
36
37 auto local_M = MathLib::createZeroedMatrix<LocalMatrixType>(
38 local_M_data, local_matrix_size, local_matrix_size);
39 auto local_K = MathLib::createZeroedMatrix<LocalMatrixType>(
40 local_K_data, local_matrix_size, local_matrix_size);
41 auto local_b = MathLib::createZeroedVector<LocalVectorType>(
42 local_b_data, local_matrix_size);
43
44 // Get block matrices
45 auto Mvv = local_M.template block<velocity_size, velocity_size>(
47
48 auto Mhp = local_M.template block<enthalpy_size, pressure_size>(
50 auto Mhh = local_M.template block<enthalpy_size, enthalpy_size>(
52
53 auto Kpv = local_K.template block<pressure_size, velocity_size>(
55
56 auto Kvp = local_K.template block<velocity_size, pressure_size>(
58 auto Kvv = local_K.template block<velocity_size, velocity_size>(
60
61 auto Khh = local_K.template block<enthalpy_size, enthalpy_size>(
63
64 auto Bp = local_b.template segment<pressure_size>(pressure_index);
65 auto Bv = local_b.template segment<velocity_size>(velocity_index);
66 auto Bh = local_b.template segment<enthalpy_size>(enthalpy_index);
67
68 unsigned const n_integration_points =
70
73
74 auto const& b = _process_data.specific_body_force;
75
77
78 // Get material properties
79 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
80 auto const& liquid_phase = medium.phase("AqueousLiquid");
81 auto const& gas_phase = medium.phase("Gas");
82
83 // Get wellbore parameters
84 // casing thickness
85 auto const t_ca = _process_data.wellbore.casing_thickness(t, pos)[0];
86 // wellbore radius
87 auto const r_w = _process_data.wellbore.diameter(t, pos)[0] / 2;
88
89 // pipe thickness
90 auto const t_p = _process_data.wellbore.pipe_thickness(t, pos)[0];
91
92 // roughness of the wellbore
93 auto const xi = _process_data.wellbore.roughness(t, pos)[0];
94 // pipe outer radius
95 auto const r_o = r_w - t_ca;
96 // pipe inner radius
97 auto const r_i = r_o - t_p;
98
99 // get reservoir properties
100 NodalVectorType T_r =
102 _element, t);
103 NodalVectorType p_r =
105 _element, t);
108 auto const k_r =
110 auto const rho_r = _process_data.reservoir_properties.density(t, pos)[0];
111 auto const c_r =
113
114 for (unsigned ip(0); ip < n_integration_points; ip++)
115 {
116 pos.setIntegrationPoint(ip);
117
118 auto& ip_data = _ip_data[ip];
119 auto const& N = ip_data.N;
120 auto const& dNdx = ip_data.dNdx;
121 auto const& w = ip_data.integration_weight;
122 auto& mix_density = ip_data.mix_density;
123 auto& temperature = ip_data.temperature;
124 auto& steam_mass_frac = ip_data.dryness;
125 auto& vapor_volume_frac = ip_data.vapor_volume_fraction;
126 auto& vapor_mass_flowrate = ip_data.vapor_mass_flow_rate;
127 auto& liquid_mass_flowrate = ip_data.liquid_mass_flow_rate;
128
129 double p_int_pt = 0.0;
130 double v_int_pt = 0.0;
131 double h_int_pt = 0.0;
132
133 NumLib::shapeFunctionInterpolate(local_x, N, p_int_pt, v_int_pt,
134 h_int_pt);
135
136 double p_prev_int_pt = 0.0;
137 double v_prev_int_pt = 0.0;
138 double h_prev_int_pt = 0.0;
139
140 NumLib::shapeFunctionInterpolate(local_x_prev, N, p_prev_int_pt,
141 v_prev_int_pt, h_prev_int_pt);
142
143 double vdot_int_pt = (v_int_pt - v_prev_int_pt) / dt;
144
145 // calculate fluid properties
146
147 const double pi = std::numbers::pi;
148
149 vars.liquid_phase_pressure = p_int_pt;
150 vars.enthalpy = h_int_pt;
151
152 double liquid_water_density =
153 liquid_phase
155 .template value<double>(vars, pos, t, dt);
156 double const vapour_water_density =
157 gas_phase
159 .template value<double>(vars, pos, t, dt);
160
161 double const h_sat_liq_w =
162 liquid_phase
163 .property(
165 .template value<double>(vars, pos, t, dt);
166 double const h_sat_vap_w =
167 gas_phase
168 .property(
170 .template value<double>(vars, pos, t, dt);
171
172 // TODO add a function to calculate dryness with constrain of 0
173 // to 1.
174 double const dryness = std::max(
175 0., (h_int_pt - h_sat_liq_w) / (h_sat_vap_w - h_sat_liq_w));
176 steam_mass_frac = dryness;
177
178 double const T_int_pt =
179 (dryness == 0)
180 ? liquid_phase
182 .template value<double>(vars, pos, t, dt)
183 : gas_phase
186 .template value<double>(vars, pos, t, dt);
187 temperature = T_int_pt;
188 vars.temperature = T_int_pt;
189
190 // For the calculation of the void fraction of vapour,
191 // see Rohuani, Z., and E. Axelsson. "Calculation of volume void
192 // fraction in a subcooled and quality region." International
193 // Journal of Heat and Mass Transfer 17 (1970): 383-393.
194
195 // profile parameter of drift flux
196 double C_0 = 1 + 0.12 * (1 - dryness);
197
198 // For the surface tension calculation, see
199 // Cooper, J. R., and R. B. Dooley. "IAPWS release on surface
200 // tension of ordinary water substance." International Association
201 // for the Properties of Water and Steam (1994).
202 double const sigma_gl = 0.2358 *
203 std::pow((1 - T_int_pt / 647.096), 1.256) *
204 (1 - 0.625 * (1 - T_int_pt / 647.096));
205 // drift flux velocity
206 double const u_gu =
207 1.18 * (1 - dryness) *
208 std::pow((9.81) * sigma_gl *
209 (liquid_water_density - vapour_water_density),
210 0.25) /
211 std::pow(liquid_water_density, 0.5);
212
213 // solving void fraction of vapor: Rouhani-Axelsson
214 double alpha = 0;
215 if (dryness != 0)
216 {
217 // Local Newton solver
218 using LocalJacobianMatrix =
219 Eigen::Matrix<double, 1, 1, Eigen::RowMajor>;
220 using LocalResidualVector = Eigen::Matrix<double, 1, 1>;
221 using LocalUnknownVector = Eigen::Matrix<double, 1, 1>;
222 LocalJacobianMatrix J_loc;
223
224 Eigen::PartialPivLU<LocalJacobianMatrix> linear_solver(1);
225
226 auto const update_residual = [&](LocalResidualVector& residual)
227 {
228 calculateResidual(alpha, vapour_water_density,
229 liquid_water_density, v_int_pt, dryness, C_0,
230 u_gu, residual);
231 };
232
233 auto const update_jacobian = [&](LocalJacobianMatrix& jacobian)
234 {
236 alpha, vapour_water_density, liquid_water_density, v_int_pt,
237 dryness, C_0, u_gu,
238 jacobian); // for solution dependent Jacobians
239 };
240
241 auto const update_solution =
242 [&](LocalUnknownVector const& increment)
243 {
244 // increment solution vectors
245 alpha += increment[0];
246 };
247
248 const int maximum_iterations(20);
249 const double residuum_tolerance(1.e-10);
250 const double increment_tolerance(0);
251
252 auto newton_solver = NumLib::NewtonRaphson(
253 linear_solver, update_jacobian, update_residual,
254 update_solution,
255 {maximum_iterations, residuum_tolerance, increment_tolerance});
256
257 auto const success_iterations = newton_solver.solve(J_loc);
258
259 if (!success_iterations)
260 {
261 WARN(
262 "Attention! Steam void fraction has not been correctly "
263 "calculated!");
264 }
265 }
266
267 vapor_volume_frac = alpha;
268
269 if (alpha == 0)
270 {
271 liquid_water_density =
272 liquid_phase
274 .template value<double>(vars, pos, t, dt);
275 }
276
277 mix_density =
278 vapour_water_density * alpha + liquid_water_density * (1 - alpha);
279
280 auto& mix_density_prev = ip_data.mix_density_prev;
281 vars.density = mix_density;
282
283 auto const rho_dot = (mix_density - mix_density_prev) / dt;
284
285 double const liquid_water_velocity_act =
286 (alpha == 0) ? v_int_pt
287 : (1 - dryness) * mix_density * v_int_pt /
288 (1 - alpha) / liquid_water_density;
289 double const vapor_water_velocity_act =
290 (alpha == 0) ? 0
291 : dryness * mix_density * v_int_pt /
292 (alpha * vapour_water_density);
293
294 vapor_mass_flowrate = vapor_water_velocity_act * vapour_water_density *
295 pi * r_i * r_i * alpha;
296
297 liquid_mass_flowrate = liquid_water_velocity_act *
298 liquid_water_density * pi * r_i * r_i *
299 (1 - alpha);
300
301 // Slip parameter between two phases,
302 // see Akbar, Somaieh, N. Fathianpour, and Rafid Al Khoury. "A finite
303 // element model for high enthalpy two-phase flow in geothermal
304 // wellbores." Renewable Energy 94 (2016): 223-236.
305 double const gamma =
306 alpha * liquid_water_density * vapour_water_density * mix_density /
307 (1 - alpha) /
308 std::pow((alpha * C_0 * vapour_water_density +
309 (1 - alpha * C_0) * liquid_water_density),
310 2) *
311 std::pow((C_0 - 1) * v_int_pt + u_gu, 2);
312
313 double const miu =
315 .template value<double>(vars, pos, t, dt);
316 double const Re = mix_density * v_int_pt * 2 * r_i / miu;
317
318 // Wall friction coefficient,
319 // Musivand Arzanfudi, Mehdi, and Rafid Al‐Khoury. "A compressible
320 // two‐fluid multiphase model for CO2 leakage through a wellbore."
321 // International Journal for Numerical Methods in Fluids 77.8 (2015):
322 // 477-507.
323 double f = 0.0;
324 if (Re > 10 && Re <= 2400)
325 f = 16 / Re;
326 else if (Re > 2400)
327 f = std::pow(std::log(xi / 3.7 / r_i) -
328 5.02 / Re * std::log(xi / 3.7 / r_i + 13 / Re),
329 -2) /
330 16;
331
332 double Q_hx = 0;
333 double const T_r_int_pt = N.dot(T_r);
334 // conductive heat exchange between wellbore and formation
336 {
337 // See Zhang, Pan, Pruess, Finsterle (2011). A time-convolution
338 // approach for modeling heat exchange between a wellbore and
339 // surrounding formation. Geothermics 40, 261-266.
340 const double alpha_r = k_r / rho_r / c_r;
341 const double t_d = alpha_r * t / (r_i * r_i);
342
343 double beta;
344 if (t_d < 2.8)
345 beta = std::pow((pi * t_d), -0.5) + 0.5 -
346 0.25 * std::pow((t_d / pi), 0.5) + 0.125 * t_d;
347 else
348 beta = 2 * (1 / (std::log(4 * t_d) - 2 * 0.57722) -
349 0.57722 /
350 std::pow((std::log(4 * t_d) - 2 * 0.57722), 2));
351
352 const double P_c = 2 * pi * r_i;
353 Q_hx = P_c * k_r * (T_r_int_pt - T_int_pt) / r_i * beta;
354 }
355
356 // mass exchange with reservoir
357 double const p_r_int_pt = N.dot(p_r);
358 double const PI_int_pt = N.dot(PI);
359 double Q_mx = PI_int_pt * (p_int_pt - p_r_int_pt);
360
361 // advective momentum and energy exchange with reservoir due to the mass
362 // exchange
363 double Q_mom = 0;
364 double Q_ene = 0;
365 if (Q_mx != 0)
366 {
367 Q_mom = Q_mx * v_int_pt;
368 // Only single-phase liquid condition is considered now
369 // TODO: update the two-phase flowing enthalpy from the feed zone.
370 vars.liquid_phase_pressure = p_r_int_pt;
371 vars.temperature = T_r_int_pt;
372 double const h_fres =
373 liquid_phase
375 .template value<double>(vars, pos, t, dt);
376 Q_ene = Q_mx * h_fres;
377 }
378
379 // M matrix assembly
380 Mvv.noalias() += w * N.transpose() * mix_density * N;
381
382 Mhp.noalias() += -w * N.transpose() * N;
383 Mhh.noalias() += w * N.transpose() * mix_density * N;
384
385 // K matrix assembly
386 Kpv.noalias() += w * dNdx.transpose() * N * mix_density;
387
388 Kvp.noalias() += w * N.transpose() * dNdx;
389 Kvv.noalias() += w * N.transpose() * rho_dot * N;
390
391 Khh.noalias() += w * N.transpose() * mix_density * v_int_pt * dNdx;
392
393 // b matrix assembly
394 Bp.noalias() += w * N.transpose() * rho_dot + w * N.transpose() * Q_mx;
395
396 Bv.noalias() +=
397 w * dNdx.transpose() * mix_density * v_int_pt * v_int_pt +
398 w * dNdx.transpose() * gamma -
399 w * N.transpose() * f * mix_density * std::abs(v_int_pt) *
400 v_int_pt / (4 * r_i) -
401 w * N.transpose() * Q_mom;
402
403 Bh.noalias() +=
404 -1 / 2 * w * N.transpose() * rho_dot * v_int_pt * v_int_pt -
405 w * N.transpose() * mix_density * v_int_pt * vdot_int_pt +
406 1 / 2 * w * dNdx.transpose() * mix_density * v_int_pt * v_int_pt *
407 v_int_pt +
408 w * N.transpose() * (Q_hx / pi / r_i / r_i) -
409 w * N.transpose() * Q_ene;
410
412 {
413 NodalVectorType gravity_operator =
414 N.transpose() * b * w * _element_direction[2];
415
416 Bv.noalias() += gravity_operator * mix_density;
417 Bh.noalias() += gravity_operator * mix_density * v_int_pt;
418 }
419 }
420
421 // debugging
422 // std::string sep = "\n----------------------------------------\n";
423 // Eigen::IOFormat CleanFmt(6, 0, ", ", "\n", "[", "]");
424 // std::cout << local_M.format(CleanFmt) << sep;
425 // std::cout << local_K.format(CleanFmt) << sep;
426 // std::cout << local_b.format(CleanFmt) << sep;
427}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
const double PI
Definition QArrow.h:20
std::optional< int > solve(JacobianMatrix &jacobian) const
void setIntegrationPoint(unsigned integration_point)
void calculateJacobian(double const alpha, double const vapor_water_density, double const liquid_water_density, double const v_mix, double const dryness, double const C_0, double const u_gu, JacobianMatrix &Jac)
void calculateResidual(double const alpha, double const vapor_water_density, double const liquid_water_density, double const v_mix, double const dryness, double const C_0, double const u_gu, ResidualVector &res)
void shapeFunctionInterpolate(const NodalValues &, const ShapeMatrix &)
ParameterLib::Parameter< double > const & pressure
ParameterLib::Parameter< double > const & thermal_conductivity
ParameterLib::Parameter< double > const & temperature
ParameterLib::Parameter< double > const & density
ParameterLib::Parameter< double > const & specific_heat_capacity
ParameterLib::Parameter< double > const & casing_thickness
ParameterLib::Parameter< double > const & roughness
ParameterLib::Parameter< double > const & diameter
ParameterLib::Parameter< double > const & pipe_thickness

References MaterialPropertyLib::density, MaterialPropertyLib::VariableArray::density, MaterialPropertyLib::enthalpy, MaterialPropertyLib::VariableArray::enthalpy, MaterialPropertyLib::VariableArray::liquid_phase_pressure, ProcessLib::WellboreSimulator::NUM_NODAL_DOF, PI, MaterialPropertyLib::saturation_density, MaterialPropertyLib::saturation_enthalpy, ParameterLib::SpatialPosition::setElementID(), ParameterLib::SpatialPosition::setIntegrationPoint(), NumLib::detail::shapeFunctionInterpolate(), NumLib::NewtonRaphson< LinearSolver, JacobianMatrixUpdate, ResidualUpdate, SolutionUpdate >::solve(), MaterialPropertyLib::temperature, MaterialPropertyLib::VariableArray::temperature, MaterialPropertyLib::viscosity, and WARN().

◆ calculateJacobian()

template<typename ShapeFunction , int GlobalDim>
void ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::calculateJacobian ( double const alpha,
double const vapor_water_density,
double const liquid_water_density,
double const v_mix,
double const dryness,
double const C_0,
double const u_gu,
JacobianMatrix & Jac )
inline

Definition at line 161 of file WellboreSimulatorFEM.h.

166 {
167 Jac(0) = dryness * liquid_water_density * v_mix *
168 (vapor_water_density - liquid_water_density) -
169 (C_0 * dryness * liquid_water_density +
170 C_0 * (1 - dryness) * vapor_water_density) *
171 (2 * alpha * vapor_water_density +
172 (1 - 2 * alpha) * liquid_water_density) *
173 v_mix -
174 vapor_water_density * liquid_water_density * u_gu;
175 }

◆ calculateResidual()

template<typename ShapeFunction , int GlobalDim>
void ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::calculateResidual ( double const alpha,
double const vapor_water_density,
double const liquid_water_density,
double const v_mix,
double const dryness,
double const C_0,
double const u_gu,
ResidualVector & res )
inline

Definition at line 144 of file WellboreSimulatorFEM.h.

149 {
150 double const rho_mix =
151 alpha * vapor_water_density + (1 - alpha) * liquid_water_density;
152
153 res(0) =
154 dryness * liquid_water_density * rho_mix * v_mix -
155 alpha * C_0 * dryness * liquid_water_density * rho_mix * v_mix -
156 alpha * C_0 * (1 - dryness) * vapor_water_density * rho_mix *
157 v_mix -
158 alpha * vapor_water_density * liquid_water_density * u_gu;
159 }

◆ computeSecondaryVariableConcrete()

template<typename ShapeFunction , int GlobalDim>
void ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::computeSecondaryVariableConcrete ( double const ,
double const ,
Eigen::VectorXd const & ,
Eigen::VectorXd const &  )
inlineoverridevirtual

◆ getIntPtDryness()

template<typename ShapeFunction , int GlobalDim>
virtual std::vector< double > const & ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::getIntPtDryness ( const double ,
std::vector< GlobalVector * > const & ,
std::vector< NumLib::LocalToGlobalIndexMap const * > const & ,
std::vector< double > & cache ) const
inlineoverrideprotectedvirtual

◆ getIntPtLiquidMassFlowRate()

template<typename ShapeFunction , int GlobalDim>
virtual std::vector< double > const & ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::getIntPtLiquidMassFlowRate ( const double ,
std::vector< GlobalVector * > const & ,
std::vector< NumLib::LocalToGlobalIndexMap const * > const & ,
std::vector< double > & cache ) const
inlineoverrideprotectedvirtual

◆ getIntPtTemperature()

template<typename ShapeFunction , int GlobalDim>
virtual std::vector< double > const & ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::getIntPtTemperature ( const double ,
std::vector< GlobalVector * > const & ,
std::vector< NumLib::LocalToGlobalIndexMap const * > const & ,
std::vector< double > & cache ) const
inlineoverrideprotectedvirtual

◆ getIntPtVaporMassFlowRate()

template<typename ShapeFunction , int GlobalDim>
virtual std::vector< double > const & ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::getIntPtVaporMassFlowRate ( const double ,
std::vector< GlobalVector * > const & ,
std::vector< NumLib::LocalToGlobalIndexMap const * > const & ,
std::vector< double > & cache ) const
inlineoverrideprotectedvirtual

◆ getIntPtVaporVolumeFraction()

template<typename ShapeFunction , int GlobalDim>
virtual std::vector< double > const & ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::getIntPtVaporVolumeFraction ( const double ,
std::vector< GlobalVector * > const & ,
std::vector< NumLib::LocalToGlobalIndexMap const * > const & ,
std::vector< double > & cache ) const
inlineoverrideprotectedvirtual

◆ getShapeMatrix()

template<typename ShapeFunction , int GlobalDim>
Eigen::Map< const Eigen::RowVectorXd > ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::getShapeMatrix ( const unsigned integration_point) const
inlineoverridevirtual

Provides the shape matrix at the given integration point.

Implements NumLib::ExtrapolatableElement.

Definition at line 177 of file WellboreSimulatorFEM.h.

179 {
180 auto const& N = _ip_data[integration_point].N;
181
182 // assumes N is stored contiguously in memory
183 return Eigen::Map<const Eigen::RowVectorXd>(N.data(), N.size());
184 }

References ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_ip_data.

◆ postTimestepConcrete()

template<typename ShapeFunction , int GlobalDim>
void ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::postTimestepConcrete ( Eigen::VectorXd const & ,
Eigen::VectorXd const & ,
double const ,
double const ,
int const  )
inlineoverridevirtual

Reimplemented from ProcessLib::LocalAssemblerInterface.

Definition at line 203 of file WellboreSimulatorFEM.h.

207 {
208 unsigned const n_integration_points =
210
211 for (unsigned ip = 0; ip < n_integration_points; ip++)
212 {
213 _ip_data[ip].pushBackState();
214 }
215 }

References ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_integration_method, ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_ip_data, and NumLib::GenericIntegrationMethod::getNumberOfPoints().

Member Data Documentation

◆ _element

◆ _element_direction

template<typename ShapeFunction , int GlobalDim>
Eigen::Vector3d ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_element_direction
protected

◆ _integration_method

◆ _ip_data

◆ _is_axially_symmetric

template<typename ShapeFunction , int GlobalDim>
bool const ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::_is_axially_symmetric
protected

Definition at line 270 of file WellboreSimulatorFEM.h.

◆ _process_data

◆ enthalpy_index

template<typename ShapeFunction , int GlobalDim>
const int ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::enthalpy_index = 2 * ShapeFunction::NPOINTS
staticprotected

Definition at line 282 of file WellboreSimulatorFEM.h.

◆ enthalpy_size

template<typename ShapeFunction , int GlobalDim>
const int ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::enthalpy_size = ShapeFunction::NPOINTS
staticprotected

Definition at line 286 of file WellboreSimulatorFEM.h.

◆ jacobian_residual_size

template<typename ShapeFunction , int GlobalDim>
int const ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::jacobian_residual_size = 1
static

Definition at line 137 of file WellboreSimulatorFEM.h.

◆ pressure_index

template<typename ShapeFunction , int GlobalDim>
const int ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::pressure_index = 0
staticprotected

Definition at line 280 of file WellboreSimulatorFEM.h.

◆ pressure_size

template<typename ShapeFunction , int GlobalDim>
const int ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::pressure_size = ShapeFunction::NPOINTS
staticprotected

Definition at line 284 of file WellboreSimulatorFEM.h.

◆ velocity_index

template<typename ShapeFunction , int GlobalDim>
const int ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::velocity_index = ShapeFunction::NPOINTS
staticprotected

Definition at line 281 of file WellboreSimulatorFEM.h.

◆ velocity_size

template<typename ShapeFunction , int GlobalDim>
const int ProcessLib::WellboreSimulator::WellboreSimulatorFEM< ShapeFunction, GlobalDim >::velocity_size = ShapeFunction::NPOINTS
staticprotected

Definition at line 285 of file WellboreSimulatorFEM.h.


The documentation for this class was generated from the following files: