OGS
LiquidFlowLocalAssembler-impl.h
Go to the documentation of this file.
1
13#pragma once
14
20
21namespace ProcessLib
22{
23namespace LiquidFlow
24{
25template <typename ShapeFunction, int GlobalDim>
27 double const t, double const dt, std::vector<double> const& local_x,
28 std::vector<double> const& /*local_x_prev*/,
29 std::vector<double>& local_M_data, std::vector<double>& local_K_data,
30 std::vector<double>& local_b_data)
31{
33 pos.setElementID(_element.getID());
34
35 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
37 vars.temperature =
39 .template value<double>(vars, pos, t, dt);
40 vars.liquid_phase_pressure = std::numeric_limits<double>::quiet_NaN();
41 GlobalDimMatrixType const permeability =
44 vars, pos, t, dt));
45 // Note: For Inclined 1D in 2D/3D or 2D element in 3D, the first item in
46 // the assert must be changed to permeability.rows() ==
47 // _element->getDimension()
48 assert(permeability.rows() == GlobalDim || permeability.rows() == 1);
49
50 if (permeability.size() == 1)
51 { // isotropic or 1D problem.
52 assembleMatrixAndVector<IsotropicCalculator>(
53 t, dt, local_x, local_M_data, local_K_data, local_b_data);
54 }
55 else
56 {
57 assembleMatrixAndVector<AnisotropicCalculator>(
58 t, dt, local_x, local_M_data, local_K_data, local_b_data);
59 }
60}
61
62template <typename ShapeFunction, int GlobalDim>
64 MathLib::Point3d const& p_local_coords, double const t,
65 std::vector<double> const& local_x) const
66{
67 // TODO (tf) Temporary value not used by current material models. Need
68 // extension of getFlux interface
69 double const dt = std::numeric_limits<double>::quiet_NaN();
70
71 // Note: Axial symmetry is set to false here, because we only need dNdx
72 // here, which is not affected by axial symmetry.
73 auto const shape_matrices =
75 GlobalDim>(_element,
76 false /*is_axially_symmetric*/,
77 std::array{p_local_coords})[0];
78
79 // create pos object to access the correct media property
81 pos.setElementID(_element.getID());
82
83 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
84 auto const& fluid_phase = fluidPhase(medium);
85
87
88 double pressure = 0.0;
89 NumLib::shapeFunctionInterpolate(local_x, shape_matrices.N, pressure);
90 vars.liquid_phase_pressure = pressure;
91
92 GlobalDimMatrixType const intrinsic_permeability =
95 vars, pos, t, dt));
96 auto const viscosity =
98 .template value<double>(vars, pos, t, dt);
99
100 Eigen::Vector3d flux(0.0, 0.0, 0.0);
101 flux.head<GlobalDim>() =
102 -intrinsic_permeability / viscosity * shape_matrices.dNdx *
103 Eigen::Map<const NodalVectorType>(local_x.data(), local_x.size());
104
105 return flux;
106}
107
108template <typename ShapeFunction, int GlobalDim>
109template <typename LaplacianGravityVelocityCalculator>
111 assembleMatrixAndVector(double const t, double const dt,
112 std::vector<double> const& local_x,
113 std::vector<double>& local_M_data,
114 std::vector<double>& local_K_data,
115 std::vector<double>& local_b_data)
116{
117 auto const local_matrix_size = local_x.size();
118 assert(local_matrix_size == ShapeFunction::NPOINTS);
119
121 local_M_data, local_matrix_size, local_matrix_size);
123 local_K_data, local_matrix_size, local_matrix_size);
125 local_b_data, local_matrix_size);
126 const auto local_p_vec =
127 MathLib::toVector<NodalVectorType>(local_x, local_matrix_size);
128
129 unsigned const n_integration_points =
130 _integration_method.getNumberOfPoints();
131
133 pos.setElementID(_element.getID());
134
135 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
136 auto const& fluid_phase = fluidPhase(medium);
137
139 auto& phase_pressure = medium.hasPhase("Gas") ? vars.gas_phase_pressure
141
142 vars.temperature =
144 .template value<double>(vars, pos, t, dt);
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);
160
161 auto const [fluid_density, viscosity] =
162 getFluidDensityAndViscosity(t, dt, pos, fluid_phase, vars);
163
164 auto const porosity =
166 .template value<double>(vars, pos, t, dt);
167 auto const specific_storage =
169 .template value<double>(vars, pos, t, dt);
170
171 auto const get_drho_dp = [&]()
172 {
174 .template dValue<double>(vars, _process_data.phase_variable,
175 pos, t, dt);
176 };
177 auto const storage =
178 _process_data.equation_balance_type == EquationBalanceType::volume
179 ? specific_storage
180 : specific_storage + porosity * get_drho_dp() / fluid_density;
181
182 double const scaling_factor =
183 _process_data.equation_balance_type == EquationBalanceType::volume
184 ? 1.0
185 : fluid_density;
186 // Assemble mass matrix, M
187 local_M.noalias() += scaling_factor * storage * N.transpose() * N *
188 ip_data.integration_weight;
189
190 pos.setIntegrationPoint(ip);
191 GlobalDimMatrixType const permeability =
194 vars, pos, t, dt));
195
196 // Assemble Laplacian, K, and RHS by the gravitational term
197 LaplacianGravityVelocityCalculator::calculateLaplacianAndGravityTerm(
198 local_K, local_b, ip_data, scaling_factor * permeability, viscosity,
199 fluid_density, projected_body_force_vector,
200 _process_data.has_gravity);
201 }
202}
203
204template <typename ShapeFunction, int GlobalDim>
205template <typename VelocityCacheType>
207 bool const is_scalar_permeability, const double t, const double dt,
208 std::vector<double> const& local_x,
210 VelocityCacheType& darcy_velocity_at_ips) const
211{
212 if (is_scalar_permeability)
213 { // isotropic or 1D problem.
214 computeProjectedDarcyVelocity<IsotropicCalculator>(
215 t, dt, local_x, pos, darcy_velocity_at_ips);
216 }
217 else
218 {
219 computeProjectedDarcyVelocity<AnisotropicCalculator>(
220 t, dt, local_x, pos, darcy_velocity_at_ips);
221 }
222}
223
224template <typename ShapeFunction, int GlobalDim>
225std::vector<double> const&
227 const double t,
228 std::vector<GlobalVector*> const& x,
229 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
230 std::vector<double>& velocity_cache) const
231{
232 // TODO (tf) Temporary value not used by current material models. Need
233 // extension of secondary variable interface.
234 double const dt = std::numeric_limits<double>::quiet_NaN();
235
236 constexpr int process_id = 0;
237 auto const indices =
238 NumLib::getIndices(_element.getID(), *dof_tables[process_id]);
239 auto const local_x = x[process_id]->get(indices);
240 auto const n_integration_points = _integration_method.getNumberOfPoints();
241 velocity_cache.clear();
242
244 pos.setElementID(_element.getID());
245
246 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
248 vars.temperature =
250 .template value<double>(vars, pos, t, dt);
251 vars.liquid_phase_pressure = std::numeric_limits<double>::quiet_NaN();
252
253 GlobalDimMatrixType const permeability =
256 vars, pos, t, dt));
257
258 assert(permeability.rows() == GlobalDim || permeability.rows() == 1);
259
260 bool const is_scalar_permeability = (permeability.size() == 1);
261
262 auto velocity_cache_vectors = MathLib::createZeroedMatrix<
263 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
264 velocity_cache, GlobalDim, n_integration_points);
265
266 computeDarcyVelocity(is_scalar_permeability, t, dt, local_x, pos,
267 velocity_cache_vectors);
268
269 return velocity_cache;
270}
271
272template <typename ShapeFunction, int GlobalDim>
273template <typename LaplacianGravityVelocityCalculator,
274 typename VelocityCacheType>
277 const double t, const double dt, std::vector<double> const& local_x,
279 VelocityCacheType& darcy_velocity_at_ips) const
280{
281 auto const local_matrix_size = local_x.size();
282 assert(local_matrix_size == ShapeFunction::NPOINTS);
283
284 const auto local_p_vec =
285 MathLib::toVector<NodalVectorType>(local_x, local_matrix_size);
286
287 unsigned const n_integration_points =
288 _integration_method.getNumberOfPoints();
289
290 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
291 auto const& fluid_phase = fluidPhase(medium);
292
294 auto& phase_pressure = medium.hasPhase("Gas") ? vars.gas_phase_pressure
296
297 vars.temperature =
299 .template value<double>(vars, pos, t, dt);
300
301 GlobalDimVectorType const projected_body_force_vector =
302 _process_data.element_rotation_matrices[_element.getID()] *
303 _process_data.element_rotation_matrices[_element.getID()].transpose() *
304 _process_data.specific_body_force;
305
306 auto const& Ns = _process_data.shape_matrix_cache
307 .NsHigherOrder<typename ShapeFunction::MeshElement>();
308
309 for (unsigned ip = 0; ip < n_integration_points; ip++)
310 {
311 auto const& ip_data = _ip_data[ip];
312 auto const& N = Ns[ip];
313
314 phase_pressure = N.dot(local_p_vec);
315
316 auto const [fluid_density, viscosity] =
317 getFluidDensityAndViscosity(t, dt, pos, fluid_phase, vars);
318
319 GlobalDimMatrixType const permeability =
322 vars, pos, t, dt));
323
324 darcy_velocity_at_ips.col(ip) =
325 LaplacianGravityVelocityCalculator::calculateVelocity(
326 local_p_vec, ip_data, permeability, viscosity, fluid_density,
327 projected_body_force_vector, _process_data.has_gravity);
328 }
329}
330
331template <typename ShapeFunction, int GlobalDim>
334 Eigen::Map<NodalMatrixType>& local_K,
335 Eigen::Map<NodalVectorType>& local_b,
337 GlobalDimMatrixType const& permeability_with_density_factor,
338 double const mu, double const rho_L,
339 GlobalDimVectorType const& specific_body_force, bool const has_gravity)
340{
341 const double K = permeability_with_density_factor(0, 0) / mu;
342 const double fac = K * ip_data.integration_weight;
343 local_K.noalias() += fac * ip_data.dNdx.transpose() * ip_data.dNdx;
344
345 if (has_gravity)
346 {
347 local_b.noalias() +=
348 (fac * rho_L) * ip_data.dNdx.transpose() * specific_body_force;
349 }
350}
351
352template <typename ShapeFunction, int GlobalDim>
353Eigen::Matrix<double, GlobalDim, 1>
356 Eigen::Map<const NodalVectorType> const& local_p,
358 GlobalDimMatrixType const& permeability, double const mu,
359 double const rho_L, GlobalDimVectorType const& specific_body_force,
360 bool const has_gravity)
361{
362 const double K = permeability(0, 0) / mu;
363 // Compute the velocity
364 GlobalDimVectorType velocity = -K * ip_data.dNdx * local_p;
365 // gravity term
366 if (has_gravity)
367 {
368 velocity += (K * rho_L) * specific_body_force;
369 }
370 return velocity;
371}
372
373template <typename ShapeFunction, int GlobalDim>
376 Eigen::Map<NodalMatrixType>& local_K,
377 Eigen::Map<NodalVectorType>& local_b,
379 GlobalDimMatrixType const& permeability_with_density_factor,
380 double const mu, double const rho_L,
381 GlobalDimVectorType const& specific_body_force, bool const has_gravity)
382{
383 const double fac = ip_data.integration_weight / mu;
384 local_K.noalias() += fac * ip_data.dNdx.transpose() *
385 permeability_with_density_factor * ip_data.dNdx;
386
387 if (has_gravity)
388 {
389 local_b.noalias() += (fac * rho_L) * ip_data.dNdx.transpose() *
390 permeability_with_density_factor *
391 specific_body_force;
392 }
393}
394
395template <typename ShapeFunction, int GlobalDim>
396Eigen::Matrix<double, GlobalDim, 1>
399 Eigen::Map<const NodalVectorType> const& local_p,
401 GlobalDimMatrixType const& permeability, double const mu,
402 double const rho_L, GlobalDimVectorType const& specific_body_force,
403 bool const has_gravity)
404{
405 // Compute the velocity
406 GlobalDimVectorType velocity = -permeability * ip_data.dNdx * local_p / mu;
407
408 // gravity term
409 if (has_gravity)
410 {
411 velocity += (rho_L / mu) * permeability * specific_body_force;
412 }
413 return velocity;
414}
415
416} // namespace LiquidFlow
417} // namespace ProcessLib
void setElementID(std::size_t element_id)
void setIntegrationPoint(unsigned integration_point)
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
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::tuple< double, double > getFluidDensityAndViscosity(double const t, double const dt, ParameterLib::SpatialPosition const &pos, MaterialPropertyLib::Phase const &fluid_phase, MaterialPropertyLib::VariableArray &vars)
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)