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 = medium.phase("AqueousLiquid");
83
84 for (unsigned ip = 0; ip < n_integration_points; ip++)
85 {
86 _ip_data.emplace_back(
87 shape_matrices[ip].N, shape_matrices[ip].dNdx,
88 _integration_method.getWeightedPoint(ip).getWeight() *
89 shape_matrices[ip].integralMeasure *
90 shape_matrices[ip].detJ);
91
93
94 NodalVectorType ref_p =
95 _process_data.well_ref_pressure.getNodalValuesOnElement(
96 _element, 0);
97 NodalVectorType ref_h =
98 _process_data.well_ref_enthalpy.getNodalValuesOnElement(
99 _element, 0);
100
101 vars.liquid_phase_pressure = _ip_data[ip].N.dot(ref_p);
102 vars.enthalpy = _ip_data[ip].N.dot(ref_h);
103
104 // .initialValue
105 _ip_data[ip].temperature =
106 liquid_phase
108 .template value<double>(vars, pos, 0, 0);
109 vars.temperature = _ip_data[ip].temperature;
110 _ip_data[ip].mix_density =
111 liquid_phase
113 .template value<double>(vars, pos, 0, 0);
114 _ip_data[ip].dryness = 0;
115 _ip_data[ip].vapor_volume_fraction = 0;
116 _ip_data[ip].vapor_mass_flow_rate = 0;
117 _ip_data[ip].liquid_mass_flow_rate = 0;
118 _ip_data[ip].pushBackState();
119 }
120 }
121
122 void assemble(double const t, double const dt,
123 std::vector<double> const& local_x,
124 std::vector<double> const& local_x_prev,
125 std::vector<double>& local_M_data,
126 std::vector<double>& local_K_data,
127 std::vector<double>& local_b_data) override;
128
129 static int const jacobian_residual_size = 1;
130 using ResidualVector = Eigen::Matrix<double, jacobian_residual_size, 1>;
132 Eigen::Matrix<double, jacobian_residual_size, jacobian_residual_size,
133 Eigen::RowMajor>;
134 using UnknownVector = Eigen::Matrix<double, jacobian_residual_size, 1>;
135
136 void calculateResidual(double const alpha, double const vapor_water_density,
137 double const liquid_water_density,
138 double const v_mix, double const dryness,
139 double const C_0, double const u_gu,
140 ResidualVector& res)
141 {
142 double const rho_mix =
143 alpha * vapor_water_density + (1 - alpha) * liquid_water_density;
144
145 res(0) =
146 dryness * liquid_water_density * rho_mix * v_mix -
147 alpha * C_0 * dryness * liquid_water_density * rho_mix * v_mix -
148 alpha * C_0 * (1 - dryness) * vapor_water_density * rho_mix *
149 v_mix -
150 alpha * vapor_water_density * liquid_water_density * u_gu;
151 }
152
153 void calculateJacobian(double const alpha, double const vapor_water_density,
154 double const liquid_water_density,
155 double const v_mix, double const dryness,
156 double const C_0, double const u_gu,
157 JacobianMatrix& Jac)
158 {
159 Jac(0) = dryness * liquid_water_density * v_mix *
160 (vapor_water_density - liquid_water_density) -
161 (C_0 * dryness * liquid_water_density +
162 C_0 * (1 - dryness) * vapor_water_density) *
163 (2 * alpha * vapor_water_density +
164 (1 - 2 * alpha) * liquid_water_density) *
165 v_mix -
166 vapor_water_density * liquid_water_density * u_gu;
167 }
168
169 Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix(
170 const unsigned integration_point) const override
171 {
172 auto const& N = _ip_data[integration_point].N;
173
174 // assumes N is stored contiguously in memory
175 return Eigen::Map<const Eigen::RowVectorXd>(N.data(), N.size());
176 }
177
179 double const /*t*/,
180 double const /*dt*/,
181 Eigen::VectorXd const& /*local_x*/,
182 Eigen::VectorXd const& /*local_x_dot*/) override
183 {
184 auto const n_integration_points =
185 _integration_method.getNumberOfPoints();
186 auto const ele_id = _element.getID();
187
188 (*_process_data.mesh_prop_density)[ele_id] =
189 std::accumulate(_ip_data.begin(), _ip_data.end(), 0.,
190 [](double const s, auto const& ip)
191 { return s + ip.mix_density; }) /
192 n_integration_points;
193 }
194
195 void postTimestepConcrete(Eigen::VectorXd const& /*local_x*/,
196 Eigen::VectorXd const& /*local_x_dot*/,
197 double const /*t*/, double const /*dt*/,
198 int const /*process_id*/) override
199 {
200 unsigned const n_integration_points =
201 _integration_method.getNumberOfPoints();
202
203 for (unsigned ip = 0; ip < n_integration_points; ip++)
204 {
205 _ip_data[ip].pushBackState();
206 }
207 }
208
209protected:
210 virtual std::vector<double> const& getIntPtVaporMassFlowRate(
211 const double /*t*/,
212 std::vector<GlobalVector*> const& /*x*/,
213 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
214 std::vector<double>& cache) const override
215 {
218 }
219
220 virtual std::vector<double> const& getIntPtLiquidMassFlowRate(
221 const double /*t*/,
222 std::vector<GlobalVector*> const& /*x*/,
223 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
224 std::vector<double>& cache) const override
225 {
228 }
229
230 virtual std::vector<double> const& getIntPtTemperature(
231 const double /*t*/,
232 std::vector<GlobalVector*> const& /*x*/,
233 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
234 std::vector<double>& cache) const override
235 {
238 }
239
240 virtual std::vector<double> const& getIntPtDryness(
241 const double /*t*/,
242 std::vector<GlobalVector*> const& /*x*/,
243 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
244 std::vector<double>& cache) const override
245 {
247 _ip_data, &IpData::dryness, cache);
248 }
249
250 virtual std::vector<double> const& getIntPtVaporVolumeFraction(
251 const double /*t*/,
252 std::vector<GlobalVector*> const& /*x*/,
253 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
254 std::vector<double>& cache) const override
255 {
258 }
259
264
265 Eigen::Vector3d _element_direction;
266
267 using IpData =
269 std::vector<IpData, Eigen::aligned_allocator<IpData>> _ip_data;
270
271protected:
272 static const int pressure_index = 0;
273 static const int velocity_index = ShapeFunction::NPOINTS;
274 static const int enthalpy_index = 2 * ShapeFunction::NPOINTS;
275
276 static const int pressure_size = ShapeFunction::NPOINTS;
277 static const int velocity_size = ShapeFunction::NPOINTS;
278 static const int enthalpy_size = ShapeFunction::NPOINTS;
279};
280
281} // namespace WellboreSimulator
282} // namespace ProcessLib
283
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