OGS
WellboreSimulatorFEM.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
6#include <Eigen/Dense>
7#include <numeric>
8#include <vector>
9
23
24namespace ProcessLib
25{
26namespace WellboreSimulator
27{
28const unsigned NUM_NODAL_DOF = 3;
29
30template <typename ShapeFunction, int GlobalDim>
32{
35
36 using LocalMatrixType = typename ShapeMatricesType::template MatrixType<
37 NUM_NODAL_DOF * ShapeFunction::NPOINTS,
38 NUM_NODAL_DOF * ShapeFunction::NPOINTS>;
40 typename ShapeMatricesType::template VectorType<NUM_NODAL_DOF *
41 ShapeFunction::NPOINTS>;
42
45
50
51public:
53 MeshLib::Element const& element,
54 std::size_t const /*local_matrix_size*/,
55 NumLib::GenericIntegrationMethod const& integration_method,
56 bool const is_axially_symmetric,
57 WellboreSimulatorProcessData const& process_data)
58 : _element(element),
59 _integration_method(integration_method),
60 _is_axially_symmetric(is_axially_symmetric),
61 _process_data(process_data)
62 {
63 // calculate the element direction vector
64 auto const& p0 = element.getNode(0)->asEigenVector3d();
65 auto const& p1 = element.getNode(1)->asEigenVector3d();
66
67 _element_direction = (p1 - p0).normalized();
68
69 unsigned const n_integration_points =
70 _integration_method.getNumberOfPoints();
71 _ip_data.reserve(n_integration_points);
72
73 auto const shape_matrices =
75 GlobalDim>(element, is_axially_symmetric,
77
79 pos.setElementID(_element.getID());
80 auto const& medium =
81 *_process_data.media_map.getMedium(_element.getID());
82 auto const& liquid_phase =
84
85 for (unsigned ip = 0; ip < n_integration_points; ip++)
86 {
87 _ip_data.emplace_back(
88 shape_matrices[ip].N, shape_matrices[ip].dNdx,
89 _integration_method.getWeightedPoint(ip).getWeight() *
90 shape_matrices[ip].integralMeasure *
91 shape_matrices[ip].detJ);
92
94
95 NodalVectorType ref_p =
96 _process_data.well_ref_pressure.getNodalValuesOnElement(
97 _element, 0);
98 NodalVectorType ref_h =
99 _process_data.well_ref_enthalpy.getNodalValuesOnElement(
100 _element, 0);
101
102 vars.liquid_phase_pressure = _ip_data[ip].N.dot(ref_p);
103 vars.enthalpy = _ip_data[ip].N.dot(ref_h);
104
105 // .initialValue
106 _ip_data[ip].temperature =
107 liquid_phase
109 .template value<double>(vars, pos, 0, 0);
110 vars.temperature = _ip_data[ip].temperature;
111 _ip_data[ip].mix_density =
112 liquid_phase
114 .template value<double>(vars, pos, 0, 0);
115 _ip_data[ip].dryness = 0;
116 _ip_data[ip].vapor_volume_fraction = 0;
117 _ip_data[ip].vapor_mass_flow_rate = 0;
118 _ip_data[ip].liquid_mass_flow_rate = 0;
119 _ip_data[ip].pushBackState();
120 }
121 }
122
123 void assemble(double const t, double const dt,
124 std::vector<double> const& local_x,
125 std::vector<double> const& local_x_prev,
126 std::vector<double>& local_M_data,
127 std::vector<double>& local_K_data,
128 std::vector<double>& local_b_data) override;
129
130 static int const jacobian_residual_size = 1;
131 using ResidualVector = Eigen::Matrix<double, jacobian_residual_size, 1>;
133 Eigen::Matrix<double, jacobian_residual_size, jacobian_residual_size,
134 Eigen::RowMajor>;
135 using UnknownVector = Eigen::Matrix<double, jacobian_residual_size, 1>;
136
137 void calculateResidual(double const alpha, double const vapor_water_density,
138 double const liquid_water_density,
139 double const v_mix, double const dryness,
140 double const C_0, double const u_gu,
141 ResidualVector& res)
142 {
143 double const rho_mix =
144 alpha * vapor_water_density + (1 - alpha) * liquid_water_density;
145
146 res(0) =
147 dryness * liquid_water_density * rho_mix * v_mix -
148 alpha * C_0 * dryness * liquid_water_density * rho_mix * v_mix -
149 alpha * C_0 * (1 - dryness) * vapor_water_density * rho_mix *
150 v_mix -
151 alpha * vapor_water_density * liquid_water_density * u_gu;
152 }
153
154 void calculateJacobian(double const alpha, double const vapor_water_density,
155 double const liquid_water_density,
156 double const v_mix, double const dryness,
157 double const C_0, double const u_gu,
158 JacobianMatrix& Jac)
159 {
160 Jac(0) = dryness * liquid_water_density * v_mix *
161 (vapor_water_density - liquid_water_density) -
162 (C_0 * dryness * liquid_water_density +
163 C_0 * (1 - dryness) * vapor_water_density) *
164 (2 * alpha * vapor_water_density +
165 (1 - 2 * alpha) * liquid_water_density) *
166 v_mix -
167 vapor_water_density * liquid_water_density * u_gu;
168 }
169
170 Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix(
171 const unsigned integration_point) const override
172 {
173 auto const& N = _ip_data[integration_point].N;
174
175 // assumes N is stored contiguously in memory
176 return Eigen::Map<const Eigen::RowVectorXd>(N.data(), N.size());
177 }
178
180 double const /*t*/,
181 double const /*dt*/,
182 Eigen::VectorXd const& /*local_x*/,
183 Eigen::VectorXd const& /*local_x_dot*/) override
184 {
185 auto const n_integration_points =
186 _integration_method.getNumberOfPoints();
187 auto const ele_id = _element.getID();
188
189 (*_process_data.mesh_prop_density)[ele_id] =
190 std::accumulate(_ip_data.begin(), _ip_data.end(), 0.,
191 [](double const s, auto const& ip)
192 { return s + ip.mix_density; }) /
193 n_integration_points;
194 }
195
196 void postTimestepConcrete(Eigen::VectorXd const& /*local_x*/,
197 Eigen::VectorXd const& /*local_x_dot*/,
198 double const /*t*/, double const /*dt*/,
199 int const /*process_id*/) override
200 {
201 unsigned const n_integration_points =
202 _integration_method.getNumberOfPoints();
203
204 for (unsigned ip = 0; ip < n_integration_points; ip++)
205 {
206 _ip_data[ip].pushBackState();
207 }
208 }
209
210protected:
211 virtual std::vector<double> const& getIntPtVaporMassFlowRate(
212 const double /*t*/,
213 std::vector<GlobalVector*> const& /*x*/,
214 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
215 std::vector<double>& cache) const override
216 {
219 }
220
221 virtual std::vector<double> const& getIntPtLiquidMassFlowRate(
222 const double /*t*/,
223 std::vector<GlobalVector*> const& /*x*/,
224 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
225 std::vector<double>& cache) const override
226 {
229 }
230
231 virtual std::vector<double> const& getIntPtTemperature(
232 const double /*t*/,
233 std::vector<GlobalVector*> const& /*x*/,
234 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
235 std::vector<double>& cache) const override
236 {
239 }
240
241 virtual std::vector<double> const& getIntPtDryness(
242 const double /*t*/,
243 std::vector<GlobalVector*> const& /*x*/,
244 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
245 std::vector<double>& cache) const override
246 {
248 _ip_data, &IpData::dryness, cache);
249 }
250
251 virtual std::vector<double> const& getIntPtVaporVolumeFraction(
252 const double /*t*/,
253 std::vector<GlobalVector*> const& /*x*/,
254 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
255 std::vector<double>& cache) const override
256 {
259 }
260
265
266 Eigen::Vector3d _element_direction;
267
268 using IpData =
270 std::vector<IpData, Eigen::aligned_allocator<IpData>> _ip_data;
271
272protected:
273 static const int pressure_index = 0;
274 static const int velocity_index = ShapeFunction::NPOINTS;
275 static const int enthalpy_index = 2 * ShapeFunction::NPOINTS;
276
277 static const int pressure_size = ShapeFunction::NPOINTS;
278 static const int velocity_size = ShapeFunction::NPOINTS;
279 static const int enthalpy_size = ShapeFunction::NPOINTS;
280};
281
282} // namespace WellboreSimulator
283} // namespace ProcessLib
284
EigenFixedShapeMatrixPolicy< ShapeFunction, GlobalDim > ShapeMatrixPolicyType
virtual const Node * getNode(unsigned idx) const =0
void setElementID(std::size_t element_id)
virtual std::vector< double > const & getIntPtVaporVolumeFraction(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
typename ShapeMatricesType::NodalVectorType NodalVectorType
WellboreSimulatorFEM(MeshLib::Element const &element, std::size_t const, NumLib::GenericIntegrationMethod const &integration_method, bool const is_axially_symmetric, WellboreSimulatorProcessData const &process_data)
typename ShapeMatricesType::template MatrixType< NUM_NODAL_DOF *ShapeFunction::NPOINTS, NUM_NODAL_DOF *ShapeFunction::NPOINTS > LocalMatrixType
Eigen::Matrix< double, jacobian_residual_size, 1 > UnknownVector
typename ShapeMatricesType::GlobalDimMatrixType GlobalDimMatrixType
typename ShapeMatricesType::GlobalDimNodalMatrixType GlobalDimNodalMatrixType
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::Matrix< double, jacobian_residual_size, 1 > ResidualVector
NumLib::GenericIntegrationMethod const & _integration_method
Eigen::Matrix< double, jacobian_residual_size, jacobian_residual_size, Eigen::RowMajor > JacobianMatrix
typename ShapeMatricesType::ShapeMatrices ShapeMatrices
Eigen::Map< const Eigen::RowVectorXd > getShapeMatrix(const unsigned integration_point) const override
Provides the shape matrix at the given integration point.
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatricesType
typename ShapeMatricesType::NodalRowVectorType NodalRowVectorType
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
virtual std::vector< double > const & getIntPtLiquidMassFlowRate(const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
typename ShapeMatricesType::template VectorType< NUM_NODAL_DOF * ShapeFunction::NPOINTS > LocalVectorType
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 postTimestepConcrete(Eigen::VectorXd const &, Eigen::VectorXd const &, double const, double const, int const) override
void computeSecondaryVariableConcrete(double const, double const, Eigen::VectorXd const &, Eigen::VectorXd const &) 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)
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 & getIntPtVaporMassFlowRate(const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
IntegrationPointData< NodalRowVectorType, GlobalDimNodalMatrixType > IpData
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)
std::vector< double > const & getIntegrationPointScalarData(IntegrationPointDataVector const &ip_data_vector, MemberType IpData::*const member, std::vector< double > &cache)
NumLib::ShapeMatrices< NodalRowVectorType, DimNodalMatrixType, DimMatrixType, GlobalDimNodalMatrixType > ShapeMatrices
MatrixType< GlobalDim, ShapeFunction::NPOINTS > GlobalDimNodalMatrixType
MatrixType< GlobalDim, GlobalDim > GlobalDimMatrixType
VectorType< GlobalDim > GlobalDimVectorType
VectorType< ShapeFunction::NPOINTS > NodalVectorType
RowVectorType< ShapeFunction::NPOINTS > NodalRowVectorType