OGS
LiquidFlowLocalAssembler-impl.h
Go to the documentation of this file.
1
13#pragma once
14
21
22namespace ProcessLib
23{
24namespace LiquidFlow
25{
26template <typename ShapeFunction, int GlobalDim>
28 double const t, double const dt, std::vector<double> const& local_x,
29 std::vector<double> const& /*local_x_prev*/,
30 std::vector<double>& local_M_data, std::vector<double>& local_K_data,
31 std::vector<double>& local_b_data)
32{
33 // Dummy integration point
34 unsigned const ip = 0;
35 // auto const& ip_data = _ip_data[ip];
36 auto const& Ns = _process_data.shape_matrix_cache
37 .NsHigherOrder<typename ShapeFunction::MeshElement>();
38 auto const& N = Ns[ip];
39
41 std::nullopt, _element.getID(),
44 _element, N))};
45
46 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
48 vars.temperature =
50 .template value<double>(vars, pos, t, dt);
51 vars.liquid_phase_pressure = std::numeric_limits<double>::quiet_NaN();
52 GlobalDimMatrixType const permeability =
55 vars, pos, t, dt));
56 // Note: For Inclined 1D in 2D/3D or 2D element in 3D, the first item in
57 // the assert must be changed to permeability.rows() ==
58 // _element->getDimension()
59 assert(permeability.rows() == GlobalDim || permeability.rows() == 1);
60
61 if (permeability.size() == 1)
62 { // isotropic or 1D problem.
63 assembleMatrixAndVector<IsotropicCalculator>(
64 t, dt, local_x, local_M_data, local_K_data, local_b_data);
65 }
66 else
67 {
68 assembleMatrixAndVector<AnisotropicCalculator>(
69 t, dt, local_x, local_M_data, local_K_data, local_b_data);
70 }
71}
72
73template <typename ShapeFunction, int GlobalDim>
75 MathLib::Point3d const& p_local_coords, double const t,
76 std::vector<double> const& local_x) const
77{
78 // TODO (tf) Temporary value not used by current material models. Need
79 // extension of getFlux interface
80 double const dt = std::numeric_limits<double>::quiet_NaN();
81
82 // Note: Axial symmetry is set to false here, because we only need dNdx
83 // here, which is not affected by axial symmetry.
84 auto const shape_matrices =
86 GlobalDim>(_element,
87 false /*is_axially_symmetric*/,
88 std::array{p_local_coords})[0];
89
90 // create pos object to access the correct media property
92 pos.setElementID(_element.getID());
93
94 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
95 auto const& fluid_phase = fluidPhase(medium);
96
98
99 double pressure = 0.0;
100 NumLib::shapeFunctionInterpolate(local_x, shape_matrices.N, pressure);
101 vars.liquid_phase_pressure = pressure;
102
103 GlobalDimMatrixType const intrinsic_permeability =
106 vars, pos, t, dt));
107 auto const viscosity =
109 .template value<double>(vars, pos, t, dt);
110
111 Eigen::Vector3d flux(0.0, 0.0, 0.0);
112 flux.head<GlobalDim>() =
113 -intrinsic_permeability / viscosity * shape_matrices.dNdx *
114 Eigen::Map<const NodalVectorType>(local_x.data(), local_x.size());
115
116 return flux;
117}
118
119template <typename ShapeFunction, int GlobalDim>
120template <typename LaplacianGravityVelocityCalculator>
122 assembleMatrixAndVector(double const t, double const dt,
123 std::vector<double> const& local_x,
124 std::vector<double>& local_M_data,
125 std::vector<double>& local_K_data,
126 std::vector<double>& local_b_data)
127{
128 auto const local_matrix_size = local_x.size();
129 assert(local_matrix_size == ShapeFunction::NPOINTS);
130
132 local_M_data, local_matrix_size, local_matrix_size);
134 local_K_data, local_matrix_size, local_matrix_size);
136 local_b_data, local_matrix_size);
137 const auto local_p_vec =
138 MathLib::toVector<NodalVectorType>(local_x, local_matrix_size);
139
140 unsigned const n_integration_points =
141 _integration_method.getNumberOfPoints();
142
144 pos.setElementID(_element.getID());
145
146 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
147 auto const& fluid_phase = fluidPhase(medium);
148
150 auto& phase_pressure = medium.hasPhase("Gas") ? vars.gas_phase_pressure
152
153 GlobalDimVectorType const projected_body_force_vector =
154 _process_data.element_rotation_matrices[_element.getID()] *
155 _process_data.element_rotation_matrices[_element.getID()].transpose() *
156 _process_data.specific_body_force;
157
158 auto const& Ns = _process_data.shape_matrix_cache
159 .NsHigherOrder<typename ShapeFunction::MeshElement>();
160
161 for (unsigned ip = 0; ip < n_integration_points; ip++)
162 {
163 auto const& ip_data = _ip_data[ip];
164 auto const& N = Ns[ip];
165
166 phase_pressure = N.dot(local_p_vec);
168 std::nullopt, _element.getID(),
171 _element, N))};
172
173 vars.temperature =
175 .template value<double>(vars, pos, t, dt);
176
177 auto const [fluid_density, viscosity] =
179 fluid_phase, vars);
180
181 auto const porosity =
183 .template value<double>(vars, pos, t, dt);
184 auto const specific_storage =
186 .template value<double>(vars, pos, t, dt);
187
188 auto const get_drho_dp = [&]()
189 {
191 .template dValue<double>(vars, _process_data.phase_variable,
192 pos, t, dt);
193 };
194 auto const storage =
195 _process_data.equation_balance_type == EquationBalanceType::volume
196 ? specific_storage
197 : specific_storage + porosity * get_drho_dp() / fluid_density;
198
199 double const scaling_factor =
200 _process_data.equation_balance_type == EquationBalanceType::volume
201 ? 1.0
202 : fluid_density;
203 // Assemble mass matrix, M
204 local_M.noalias() += scaling_factor * storage * N.transpose() * N *
205 ip_data.integration_weight;
206
207 GlobalDimMatrixType const permeability =
210 vars, pos, t, dt));
211
212 // Assemble Laplacian, K, and RHS by the gravitational term
213 LaplacianGravityVelocityCalculator::calculateLaplacianAndGravityTerm(
214 local_K, local_b, ip_data, scaling_factor * permeability, viscosity,
215 fluid_density, projected_body_force_vector,
216 _process_data.has_gravity);
217 }
218}
219
220template <typename ShapeFunction, int GlobalDim>
221template <typename VelocityCacheType>
223 bool const is_scalar_permeability, const double t, const double dt,
224 std::vector<double> const& local_x,
226 VelocityCacheType& darcy_velocity_at_ips) const
227{
228 if (is_scalar_permeability)
229 { // isotropic or 1D problem.
230 computeProjectedDarcyVelocity<IsotropicCalculator>(
231 t, dt, local_x, pos, darcy_velocity_at_ips);
232 }
233 else
234 {
235 computeProjectedDarcyVelocity<AnisotropicCalculator>(
236 t, dt, local_x, pos, darcy_velocity_at_ips);
237 }
238}
239
240template <typename ShapeFunction, int GlobalDim>
241std::vector<double> const&
243 const double t,
244 std::vector<GlobalVector*> const& x,
245 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
246 std::vector<double>& velocity_cache) const
247{
248 // TODO (tf) Temporary value not used by current material models. Need
249 // extension of secondary variable interface.
250 double const dt = std::numeric_limits<double>::quiet_NaN();
251
252 constexpr int process_id = 0;
253 auto const indices =
254 NumLib::getIndices(_element.getID(), *dof_tables[process_id]);
255 auto const local_x = x[process_id]->get(indices);
256 auto const n_integration_points = _integration_method.getNumberOfPoints();
257 velocity_cache.clear();
258
259 // Dummy integration point
260 unsigned const ip = 0;
261 // auto const& ip_data = _ip_data[ip];
262 auto const& Ns = _process_data.shape_matrix_cache
263 .NsHigherOrder<typename ShapeFunction::MeshElement>();
264 auto const& N = Ns[ip];
265
267 std::nullopt, _element.getID(),
270 _element, N))};
271
272 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
274 vars.temperature =
276 .template value<double>(vars, pos, t, dt);
277 vars.liquid_phase_pressure = std::numeric_limits<double>::quiet_NaN();
278
279 GlobalDimMatrixType const permeability =
282 vars, pos, t, dt));
283
284 assert(permeability.rows() == GlobalDim || permeability.rows() == 1);
285
286 bool const is_scalar_permeability = (permeability.size() == 1);
287
288 auto velocity_cache_vectors = MathLib::createZeroedMatrix<
289 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
290 velocity_cache, GlobalDim, n_integration_points);
291
292 computeDarcyVelocity(is_scalar_permeability, t, dt, local_x, pos,
293 velocity_cache_vectors);
294
295 return velocity_cache;
296}
297
298template <typename ShapeFunction, int GlobalDim>
299template <typename LaplacianGravityVelocityCalculator,
300 typename VelocityCacheType>
303 const double t, const double dt, std::vector<double> const& local_x,
304 ParameterLib::SpatialPosition const& /* TODO{naumov) delete */,
305 VelocityCacheType& darcy_velocity_at_ips) const
306{
307 auto const local_matrix_size = local_x.size();
308 assert(local_matrix_size == ShapeFunction::NPOINTS);
309
310 const auto local_p_vec =
311 MathLib::toVector<NodalVectorType>(local_x, local_matrix_size);
312
313 unsigned const n_integration_points =
314 _integration_method.getNumberOfPoints();
315
316 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
317 auto const& fluid_phase = fluidPhase(medium);
318
320 auto& phase_pressure = medium.hasPhase("Gas") ? vars.gas_phase_pressure
322
323 GlobalDimVectorType const projected_body_force_vector =
324 _process_data.element_rotation_matrices[_element.getID()] *
325 _process_data.element_rotation_matrices[_element.getID()].transpose() *
326 _process_data.specific_body_force;
327
328 auto const& Ns = _process_data.shape_matrix_cache
329 .NsHigherOrder<typename ShapeFunction::MeshElement>();
330
331 for (unsigned ip = 0; ip < n_integration_points; ip++)
332 {
333 auto const& ip_data = _ip_data[ip];
334 auto const& N = Ns[ip];
335
336 phase_pressure = N.dot(local_p_vec);
338 std::nullopt, _element.getID(),
341 _element, N))};
342
343 vars.temperature =
345 .template value<double>(vars, pos, t, dt);
346 auto const [fluid_density, viscosity] =
348 fluid_phase, vars);
349
350 GlobalDimMatrixType const permeability =
353 vars, pos, t, dt));
354
355 darcy_velocity_at_ips.col(ip) =
356 LaplacianGravityVelocityCalculator::calculateVelocity(
357 local_p_vec, ip_data, permeability, viscosity, fluid_density,
358 projected_body_force_vector, _process_data.has_gravity);
359 }
360}
361
362template <typename ShapeFunction, int GlobalDim>
365 Eigen::Map<NodalMatrixType>& local_K,
366 Eigen::Map<NodalVectorType>& local_b,
368 GlobalDimMatrixType const& permeability_with_density_factor,
369 double const mu, double const rho_L,
370 GlobalDimVectorType const& specific_body_force, bool const has_gravity)
371{
372 const double K = permeability_with_density_factor(0, 0) / mu;
373 const double fac = K * ip_data.integration_weight;
374 local_K.noalias() += fac * ip_data.dNdx.transpose() * ip_data.dNdx;
375
376 if (has_gravity)
377 {
378 local_b.noalias() +=
379 (fac * rho_L) * ip_data.dNdx.transpose() * specific_body_force;
380 }
381}
382
383template <typename ShapeFunction, int GlobalDim>
384Eigen::Matrix<double, GlobalDim, 1>
387 Eigen::Map<const NodalVectorType> const& local_p,
389 GlobalDimMatrixType const& permeability, double const mu,
390 double const rho_L, GlobalDimVectorType const& specific_body_force,
391 bool const has_gravity)
392{
393 const double K = permeability(0, 0) / mu;
394 // Compute the velocity
395 GlobalDimVectorType velocity = -K * ip_data.dNdx * local_p;
396 // gravity term
397 if (has_gravity)
398 {
399 velocity += (K * rho_L) * specific_body_force;
400 }
401 return velocity;
402}
403
404template <typename ShapeFunction, int GlobalDim>
407 Eigen::Map<NodalMatrixType>& local_K,
408 Eigen::Map<NodalVectorType>& local_b,
410 GlobalDimMatrixType const& permeability_with_density_factor,
411 double const mu, double const rho_L,
412 GlobalDimVectorType const& specific_body_force, bool const has_gravity)
413{
414 const double fac = ip_data.integration_weight / mu;
415 local_K.noalias() += fac * ip_data.dNdx.transpose() *
416 permeability_with_density_factor * ip_data.dNdx;
417
418 if (has_gravity)
419 {
420 local_b.noalias() += (fac * rho_L) * ip_data.dNdx.transpose() *
421 permeability_with_density_factor *
422 specific_body_force;
423 }
424}
425
426template <typename ShapeFunction, int GlobalDim>
427Eigen::Matrix<double, GlobalDim, 1>
430 Eigen::Map<const NodalVectorType> const& local_p,
432 GlobalDimMatrixType const& permeability, double const mu,
433 double const rho_L, GlobalDimVectorType const& specific_body_force,
434 bool const has_gravity)
435{
436 // Compute the velocity
437 GlobalDimVectorType velocity = -permeability * ip_data.dNdx * local_p / mu;
438
439 // gravity term
440 if (has_gravity)
441 {
442 velocity += (rho_L / mu) * permeability * specific_body_force;
443 }
444 return velocity;
445}
446
447} // namespace LiquidFlow
448} // 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
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
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
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.
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)