OGS
LiquidFlowLocalAssembler-impl.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
13
14namespace ProcessLib
15{
16namespace LiquidFlow
17{
18template <typename ShapeFunction, int GlobalDim>
20 double const t, double const dt, std::vector<double> const& local_x,
21 std::vector<double> const& /*local_x_prev*/,
22 std::vector<double>& local_M_data, std::vector<double>& local_K_data,
23 std::vector<double>& local_b_data)
24{
25 // Dummy integration point
26 unsigned const ip = 0;
27 // auto const& ip_data = _ip_data[ip];
28 auto const& Ns = _process_data.shape_matrix_cache
29 .NsHigherOrder<typename ShapeFunction::MeshElement>();
30 auto const& N = Ns[ip];
31
33 std::nullopt, _element.getID(),
36 _element, N))};
37
38 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
40 vars.temperature =
42 .template value<double>(vars, pos, t, dt);
43 vars.liquid_phase_pressure = std::numeric_limits<double>::quiet_NaN();
44 GlobalDimMatrixType const permeability =
47 vars, pos, t, dt));
48 // Note: For Inclined 1D in 2D/3D or 2D element in 3D, the first item in
49 // the assert must be changed to permeability.rows() ==
50 // _element->getDimension()
51 assert(permeability.rows() == GlobalDim || permeability.rows() == 1);
52
53 if (permeability.size() == 1)
54 { // isotropic or 1D problem.
56 t, dt, local_x, local_M_data, local_K_data, local_b_data);
57 }
58 else
59 {
61 t, dt, local_x, local_M_data, local_K_data, local_b_data);
62 }
63}
64
65template <typename ShapeFunction, int GlobalDim>
67 MathLib::Point3d const& p_local_coords, double const t,
68 std::vector<double> const& local_x) const
69{
70 // TODO (tf) Temporary value not used by current material models. Need
71 // extension of getFlux interface
72 double const dt = std::numeric_limits<double>::quiet_NaN();
73
74 // Note: Axial symmetry is set to false here, because we only need dNdx
75 // here, which is not affected by axial symmetry.
76 auto const shape_matrices =
78 GlobalDim>(_element,
79 false /*is_axially_symmetric*/,
80 std::array{p_local_coords})[0];
81
82 // create pos object to access the correct media property
84 pos.setElementID(_element.getID());
85
86 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
87 auto const& fluid_phase = fluidPhase(medium);
88
90
91 double pressure = 0.0;
92 NumLib::shapeFunctionInterpolate(local_x, shape_matrices.N, pressure);
93 vars.liquid_phase_pressure = pressure;
94
95 GlobalDimMatrixType const intrinsic_permeability =
98 vars, pos, t, dt));
99 auto const viscosity =
101 .template value<double>(vars, pos, t, dt);
102
103 Eigen::Vector3d flux(0.0, 0.0, 0.0);
104 flux.head<GlobalDim>() =
105 -intrinsic_permeability / viscosity * shape_matrices.dNdx *
106 Eigen::Map<const NodalVectorType>(local_x.data(), local_x.size());
107
108 return flux;
109}
110
111template <typename ShapeFunction, int GlobalDim>
112template <typename LaplacianGravityVelocityCalculator>
114 assembleMatrixAndVector(double const t, double const dt,
115 std::vector<double> const& local_x,
116 std::vector<double>& local_M_data,
117 std::vector<double>& local_K_data,
118 std::vector<double>& local_b_data)
119{
120 auto const local_matrix_size = local_x.size();
121 assert(local_matrix_size == ShapeFunction::NPOINTS);
122
124 local_M_data, local_matrix_size, local_matrix_size);
126 local_K_data, local_matrix_size, local_matrix_size);
128 local_b_data, local_matrix_size);
129 const auto local_p_vec =
130 MathLib::toVector<NodalVectorType>(local_x, local_matrix_size);
131
132 unsigned const n_integration_points =
133 _integration_method.getNumberOfPoints();
134
136 pos.setElementID(_element.getID());
137
138 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
139 auto const& fluid_phase = fluidPhase(medium);
140
142 auto& phase_pressure = medium.hasPhase(MaterialPropertyLib::PhaseName::Gas)
143 ? vars.gas_phase_pressure
145
146 GlobalDimVectorType const projected_body_force_vector =
147 _process_data.element_rotation_matrices[_element.getID()] *
148 _process_data.element_rotation_matrices[_element.getID()].transpose() *
149 _process_data.specific_body_force;
150
151 auto const& Ns = _process_data.shape_matrix_cache
152 .NsHigherOrder<typename ShapeFunction::MeshElement>();
153
154 for (unsigned ip = 0; ip < n_integration_points; ip++)
155 {
156 auto const& ip_data = _ip_data[ip];
157 auto const& N = Ns[ip];
158
159 phase_pressure = N.dot(local_p_vec);
161 std::nullopt, _element.getID(),
164 _element, N))};
165
166 vars.temperature =
168 .template value<double>(vars, pos, t, dt);
169
170 auto const [fluid_density, viscosity] =
172 fluid_phase, vars);
173
174 auto const porosity =
176 .template value<double>(vars, pos, t, dt);
177 auto const specific_storage =
179 .template value<double>(vars, pos, t, dt);
180
181 auto const get_drho_dp = [&]()
182 {
184 .template dValue<double>(vars, _process_data.phase_variable,
185 pos, t, dt);
186 };
187 auto const storage =
188 _process_data.is_volume_balance_equation_type
189 ? specific_storage
190 : specific_storage + porosity * get_drho_dp() / fluid_density;
191
192 double const scaling_factor =
193 _process_data.is_volume_balance_equation_type ? 1.0 : fluid_density;
194 // Assemble mass matrix, M
195 local_M.noalias() += scaling_factor * storage * N.transpose() * N *
196 ip_data.integration_weight;
197
198 GlobalDimMatrixType const permeability =
201 vars, pos, t, dt));
202
203 // Assemble Laplacian, K, and RHS by the gravitational term
204 LaplacianGravityVelocityCalculator::calculateLaplacianAndGravityTerm(
205 local_K, local_b, ip_data, scaling_factor * permeability, viscosity,
206 fluid_density, projected_body_force_vector,
207 _process_data.has_gravity);
208 }
209}
210
211template <typename ShapeFunction, int GlobalDim>
212template <typename VelocityCacheType>
214 bool const is_scalar_permeability, const double t, const double dt,
215 std::vector<double> const& local_x,
217 VelocityCacheType& darcy_velocity_at_ips) const
218{
219 if (is_scalar_permeability)
220 { // isotropic or 1D problem.
222 t, dt, local_x, pos, darcy_velocity_at_ips);
223 }
224 else
225 {
227 t, dt, local_x, pos, darcy_velocity_at_ips);
228 }
229}
230
231template <typename ShapeFunction, int GlobalDim>
232std::vector<double> const&
234 const double t,
235 std::vector<GlobalVector*> const& x,
236 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
237 std::vector<double>& velocity_cache) const
238{
239 // TODO (tf) Temporary value not used by current material models. Need
240 // extension of secondary variable interface.
241 double const dt = std::numeric_limits<double>::quiet_NaN();
242
243 constexpr int process_id = 0;
244 auto const indices =
245 NumLib::getIndices(_element.getID(), *dof_tables[process_id]);
246 auto const local_x = x[process_id]->get(indices);
247 auto const n_integration_points = _integration_method.getNumberOfPoints();
248 velocity_cache.clear();
249
250 // Dummy integration point
251 unsigned const ip = 0;
252 // auto const& ip_data = _ip_data[ip];
253 auto const& Ns = _process_data.shape_matrix_cache
254 .NsHigherOrder<typename ShapeFunction::MeshElement>();
255 auto const& N = Ns[ip];
256
258 std::nullopt, _element.getID(),
261 _element, N))};
262
263 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
265 vars.temperature =
267 .template value<double>(vars, pos, t, dt);
268 vars.liquid_phase_pressure = std::numeric_limits<double>::quiet_NaN();
269
270 GlobalDimMatrixType const permeability =
273 vars, pos, t, dt));
274
275 assert(permeability.rows() == GlobalDim || permeability.rows() == 1);
276
277 bool const is_scalar_permeability = (permeability.size() == 1);
278
279 auto velocity_cache_vectors = MathLib::createZeroedMatrix<
280 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
281 velocity_cache, GlobalDim, n_integration_points);
282
283 computeDarcyVelocity(is_scalar_permeability, t, dt, local_x, pos,
284 velocity_cache_vectors);
285
286 return velocity_cache;
287}
288
289template <typename ShapeFunction, int GlobalDim>
290template <typename LaplacianGravityVelocityCalculator,
291 typename VelocityCacheType>
294 const double t, const double dt, std::vector<double> const& local_x,
295 ParameterLib::SpatialPosition const& /* TODO{naumov) delete */,
296 VelocityCacheType& darcy_velocity_at_ips) const
297{
298 auto const local_matrix_size = local_x.size();
299 assert(local_matrix_size == ShapeFunction::NPOINTS);
300
301 const auto local_p_vec =
302 MathLib::toVector<NodalVectorType>(local_x, local_matrix_size);
303
304 unsigned const n_integration_points =
305 _integration_method.getNumberOfPoints();
306
307 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
308 auto const& fluid_phase = fluidPhase(medium);
309
311 auto& phase_pressure = medium.hasPhase(MaterialPropertyLib::PhaseName::Gas)
312 ? vars.gas_phase_pressure
314
315 GlobalDimVectorType const projected_body_force_vector =
316 _process_data.element_rotation_matrices[_element.getID()] *
317 _process_data.element_rotation_matrices[_element.getID()].transpose() *
318 _process_data.specific_body_force;
319
320 auto const& Ns = _process_data.shape_matrix_cache
321 .NsHigherOrder<typename ShapeFunction::MeshElement>();
322
323 for (unsigned ip = 0; ip < n_integration_points; ip++)
324 {
325 auto const& ip_data = _ip_data[ip];
326 auto const& N = Ns[ip];
327
328 phase_pressure = N.dot(local_p_vec);
330 std::nullopt, _element.getID(),
333 _element, N))};
334
335 vars.temperature =
337 .template value<double>(vars, pos, t, dt);
338 auto const [fluid_density, viscosity] =
340 fluid_phase, vars);
341
342 GlobalDimMatrixType const permeability =
345 vars, pos, t, dt));
346
347 darcy_velocity_at_ips.col(ip) =
348 LaplacianGravityVelocityCalculator::calculateVelocity(
349 local_p_vec, ip_data, permeability, viscosity, fluid_density,
350 projected_body_force_vector, _process_data.has_gravity);
351 }
352}
353
354template <typename ShapeFunction, int GlobalDim>
357 Eigen::Map<NodalMatrixType>& local_K,
358 Eigen::Map<NodalVectorType>& local_b,
360 GlobalDimMatrixType const& permeability_with_density_factor,
361 double const mu, double const rho_L,
362 GlobalDimVectorType const& specific_body_force, bool const has_gravity)
363{
364 const double K = permeability_with_density_factor(0, 0) / mu;
365 const double fac = K * ip_data.integration_weight;
366 local_K.noalias() += fac * ip_data.dNdx.transpose() * ip_data.dNdx;
367
368 if (has_gravity)
369 {
370 local_b.noalias() +=
371 (fac * rho_L) * ip_data.dNdx.transpose() * specific_body_force;
372 }
373}
374
375template <typename ShapeFunction, int GlobalDim>
376Eigen::Matrix<double, GlobalDim, 1>
379 Eigen::Map<const NodalVectorType> const& local_p,
381 GlobalDimMatrixType const& permeability, double const mu,
382 double const rho_L, GlobalDimVectorType const& specific_body_force,
383 bool const has_gravity)
384{
385 const double K = permeability(0, 0) / mu;
386 // Compute the velocity
387 GlobalDimVectorType velocity = -K * ip_data.dNdx * local_p;
388 // gravity term
389 if (has_gravity)
390 {
391 velocity += (K * rho_L) * specific_body_force;
392 }
393 return velocity;
394}
395
396template <typename ShapeFunction, int GlobalDim>
399 Eigen::Map<NodalMatrixType>& local_K,
400 Eigen::Map<NodalVectorType>& local_b,
402 GlobalDimMatrixType const& permeability_with_density_factor,
403 double const mu, double const rho_L,
404 GlobalDimVectorType const& specific_body_force, bool const has_gravity)
405{
406 const double fac = ip_data.integration_weight / mu;
407 local_K.noalias() += fac * ip_data.dNdx.transpose() *
408 permeability_with_density_factor * ip_data.dNdx;
409
410 if (has_gravity)
411 {
412 local_b.noalias() += (fac * rho_L) * ip_data.dNdx.transpose() *
413 permeability_with_density_factor *
414 specific_body_force;
415 }
416}
417
418template <typename ShapeFunction, int GlobalDim>
419Eigen::Matrix<double, GlobalDim, 1>
422 Eigen::Map<const NodalVectorType> const& local_p,
424 GlobalDimMatrixType const& permeability, double const mu,
425 double const rho_L, GlobalDimVectorType const& specific_body_force,
426 bool const has_gravity)
427{
428 // Compute the velocity
429 GlobalDimVectorType velocity = -permeability * ip_data.dNdx * local_p / mu;
430
431 // gravity term
432 if (has_gravity)
433 {
434 velocity += (rho_L / mu) * permeability * specific_body_force;
435 }
436 return velocity;
437}
438
439} // namespace LiquidFlow
440} // namespace ProcessLib
void setElementID(std::size_t element_id)
Eigen::Vector3d getFlux(MathLib::Point3d const &p_local_coords, double const t, std::vector< double > const &local_x) const override
std::vector< IntegrationPointData< GlobalDimNodalMatrixType > > _ip_data
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatricesType
void computeProjectedDarcyVelocity(const double t, const double dt, std::vector< double > const &local_x, ParameterLib::SpatialPosition const &pos, VelocityCacheType &darcy_velocity_at_ips) const
void assemble(double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data) override
NumLib::GenericIntegrationMethod const & _integration_method
void assembleMatrixAndVector(double const t, double const dt, std::vector< double > const &local_x, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data)
void computeDarcyVelocity(bool const is_scalar_permeability, const double t, const double dt, std::vector< double > const &local_x, ParameterLib::SpatialPosition const &pos, VelocityCacheType &darcy_velocity_at_ips) const
typename ShapeMatricesType::GlobalDimMatrixType GlobalDimMatrixType
std::vector< double > const & getIntPtDarcyVelocity(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &velocity_cache) const override
std::tuple< double, double > getFluidDensityAndViscosity(double const t, double const dt, ParameterLib::SpatialPosition const &pos, MaterialPropertyLib::Phase const &fluid_phase, MaterialPropertyLib::VariableArray &vars)
It computes fluid density and viscosity for single phase flow model.
constexpr Eigen::Matrix< double, GlobalDim, GlobalDim > formEigenTensor(MaterialPropertyLib::PropertyDataType const &values)
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
Eigen::Map< const Vector > toVector(std::vector< double > const &data, Eigen::VectorXd::Index size)
Creates an Eigen mapped vector from the given data vector.
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
void shapeFunctionInterpolate(const NodalValues &, const ShapeMatrix &)
std::vector< GlobalIndexType > getIndices(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > computeShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, PointContainer const &points)
std::array< double, 3 > interpolateCoordinates(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
static void calculateLaplacianAndGravityTerm(Eigen::Map< NodalMatrixType > &local_K, Eigen::Map< NodalVectorType > &local_b, IntegrationPointData< GlobalDimNodalMatrixType > const &ip_data, GlobalDimMatrixType const &permeability_with_density_factor, double const mu, double const rho_L, GlobalDimVectorType const &specific_body_force, bool const has_gravity)
static Eigen::Matrix< double, GlobalDim, 1 > calculateVelocity(Eigen::Map< const NodalVectorType > const &local_p, IntegrationPointData< GlobalDimNodalMatrixType > const &ip_data, GlobalDimMatrixType const &permeability, double const mu, double const rho_L, GlobalDimVectorType const &specific_body_force, bool const has_gravity)
static void calculateLaplacianAndGravityTerm(Eigen::Map< NodalMatrixType > &local_K, Eigen::Map< NodalVectorType > &local_b, IntegrationPointData< GlobalDimNodalMatrixType > const &ip_data, GlobalDimMatrixType const &permeability_with_density_factor, double const mu, double const rho_L, GlobalDimVectorType const &specific_body_force, bool const has_gravity)
static Eigen::Matrix< double, GlobalDim, 1 > calculateVelocity(Eigen::Map< const NodalVectorType > const &local_p, IntegrationPointData< GlobalDimNodalMatrixType > const &ip_data, GlobalDimMatrixType const &permeability, double const mu, double const rho_L, GlobalDimVectorType const &specific_body_force, bool const has_gravity)