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.phase_pressure = std::numeric_limits<double>::quiet_NaN();
41 GlobalDimMatrixType const permeability =
42 MaterialPropertyLib::formEigenTensor<GlobalDim>(
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& liquid_phase = medium.phase("AqueousLiquid");
85
87
88 double pressure = 0.0;
89 NumLib::shapeFunctionInterpolate(local_x, shape_matrices.N, pressure);
90 vars.phase_pressure = pressure;
91
92 GlobalDimMatrixType const intrinsic_permeability =
93 MaterialPropertyLib::formEigenTensor<GlobalDim>(
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
120 auto local_M = MathLib::createZeroedMatrix<NodalMatrixType>(
121 local_M_data, local_matrix_size, local_matrix_size);
122 auto local_K = MathLib::createZeroedMatrix<NodalMatrixType>(
123 local_K_data, local_matrix_size, local_matrix_size);
124 auto local_b = MathLib::createZeroedVector<NodalVectorType>(
125 local_b_data, local_matrix_size);
126
127 unsigned const n_integration_points =
128 _integration_method.getNumberOfPoints();
129
131 pos.setElementID(_element.getID());
132
133 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
134 auto const& liquid_phase = medium.phase("AqueousLiquid");
135
137 vars.temperature =
139 .template value<double>(vars, pos, t, dt);
140
141 GlobalDimVectorType const projected_body_force_vector =
142 _process_data.element_rotation_matrices[_element.getID()] *
143 _process_data.element_rotation_matrices[_element.getID()].transpose() *
144 _process_data.specific_body_force;
145
146 for (unsigned ip = 0; ip < n_integration_points; ip++)
147 {
148 auto const& ip_data = _ip_data[ip];
149
150 double p = 0.;
151 NumLib::shapeFunctionInterpolate(local_x, ip_data.N, p);
152 vars.phase_pressure = p;
153
154 // Compute density:
155 auto const fluid_density =
157 .template value<double>(vars, pos, t, dt);
158 assert(fluid_density > 0.);
159 vars.density = fluid_density;
160
161 auto const ddensity_dpressure =
163 .template dValue<double>(
165 dt);
166
167 auto const porosity =
169 .template value<double>(vars, pos, t, dt);
170 auto const storage = medium[MaterialPropertyLib::PropertyType::storage]
171 .template value<double>(vars, pos, t, dt);
172
173 // Assemble mass matrix, M
174 local_M.noalias() +=
175 (porosity * ddensity_dpressure / fluid_density + storage) *
176 ip_data.N.transpose() * ip_data.N * ip_data.integration_weight;
177
178 // Compute viscosity:
179 auto const viscosity =
181 .template value<double>(vars, pos, t, dt);
182
183 pos.setIntegrationPoint(ip);
184 GlobalDimMatrixType const permeability =
185 MaterialPropertyLib::formEigenTensor<GlobalDim>(
187 vars, pos, t, dt));
188
189 // Assemble Laplacian, K, and RHS by the gravitational term
190 LaplacianGravityVelocityCalculator::calculateLaplacianAndGravityTerm(
191 local_K, local_b, ip_data, permeability, viscosity, fluid_density,
192 projected_body_force_vector, _process_data.has_gravity);
193 }
194}
195
196template <typename ShapeFunction, int GlobalDim>
197template <typename VelocityCacheType>
199 bool const is_scalar_permeability, const double t, const double dt,
200 std::vector<double> const& local_x,
202 VelocityCacheType& darcy_velocity_at_ips) const
203{
204 if (is_scalar_permeability)
205 { // isotropic or 1D problem.
206 computeProjectedDarcyVelocity<IsotropicCalculator>(
207 t, dt, local_x, pos, darcy_velocity_at_ips);
208 }
209 else
210 {
211 computeProjectedDarcyVelocity<AnisotropicCalculator>(
212 t, dt, local_x, pos, darcy_velocity_at_ips);
213 }
214}
215
216template <typename ShapeFunction, int GlobalDim>
217std::vector<double> const&
219 const double t,
220 std::vector<GlobalVector*> const& x,
221 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
222 std::vector<double>& velocity_cache) const
223{
224 // TODO (tf) Temporary value not used by current material models. Need
225 // extension of secondary variable interface.
226 double const dt = std::numeric_limits<double>::quiet_NaN();
227
228 constexpr int process_id = 0;
229 auto const indices =
230 NumLib::getIndices(_element.getID(), *dof_tables[process_id]);
231 auto const local_x = x[process_id]->get(indices);
232 auto const n_integration_points = _integration_method.getNumberOfPoints();
233 velocity_cache.clear();
234
236 pos.setElementID(_element.getID());
237
238 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
240 vars.temperature =
242 .template value<double>(vars, pos, t, dt);
243 vars.phase_pressure = std::numeric_limits<double>::quiet_NaN();
244
245 GlobalDimMatrixType const permeability =
246 MaterialPropertyLib::formEigenTensor<GlobalDim>(
248 vars, pos, t, dt));
249
250 assert(permeability.rows() == GlobalDim || permeability.rows() == 1);
251
252 bool const is_scalar_permeability = (permeability.size() == 1);
253
254 auto velocity_cache_vectors = MathLib::createZeroedMatrix<
255 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
256 velocity_cache, GlobalDim, n_integration_points);
257
258 computeDarcyVelocity(is_scalar_permeability, t, dt, local_x, pos,
259 velocity_cache_vectors);
260
261 return velocity_cache;
262}
263
264template <typename ShapeFunction, int GlobalDim>
265template <typename LaplacianGravityVelocityCalculator,
266 typename VelocityCacheType>
269 const double t, const double dt, std::vector<double> const& local_x,
271 VelocityCacheType& darcy_velocity_at_ips) const
272{
273 auto const local_matrix_size = local_x.size();
274 assert(local_matrix_size == ShapeFunction::NPOINTS);
275
276 const auto local_p_vec =
277 MathLib::toVector<NodalVectorType>(local_x, local_matrix_size);
278
279 unsigned const n_integration_points =
280 _integration_method.getNumberOfPoints();
281
282 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
283 auto const& liquid_phase = medium.phase("AqueousLiquid");
284
286 vars.temperature =
288 .template value<double>(vars, pos, t, dt);
289
290 GlobalDimVectorType const projected_body_force_vector =
291 _process_data.element_rotation_matrices[_element.getID()] *
292 _process_data.element_rotation_matrices[_element.getID()].transpose() *
293 _process_data.specific_body_force;
294
295 for (unsigned ip = 0; ip < n_integration_points; ip++)
296 {
297 auto const& ip_data = _ip_data[ip];
298 double p = 0.;
299 NumLib::shapeFunctionInterpolate(local_x, ip_data.N, p);
300 vars.phase_pressure = p;
301
302 // Compute density:
303 auto const fluid_density =
305 .template value<double>(vars, pos, t, dt);
306 vars.density = fluid_density;
307
308 // Compute viscosity:
309 auto const viscosity =
311 .template value<double>(vars, pos, t, dt);
312
313 GlobalDimMatrixType const permeability =
314 MaterialPropertyLib::formEigenTensor<GlobalDim>(
316 vars, pos, t, dt));
317
318 darcy_velocity_at_ips.col(ip) =
319 LaplacianGravityVelocityCalculator::calculateVelocity(
320 local_p_vec, ip_data, permeability, viscosity, fluid_density,
321 projected_body_force_vector, _process_data.has_gravity);
322 }
323}
324
325template <typename ShapeFunction, int GlobalDim>
328 Eigen::Map<NodalMatrixType>& local_K,
329 Eigen::Map<NodalVectorType>& local_b,
331 GlobalDimNodalMatrixType> const& ip_data,
332 GlobalDimMatrixType const& permeability, double const mu,
333 double const rho_L, GlobalDimVectorType const& specific_body_force,
334 bool const has_gravity)
335{
336 const double K = permeability(0, 0) / mu;
337 const double fac = K * ip_data.integration_weight;
338 local_K.noalias() += fac * ip_data.dNdx.transpose() * ip_data.dNdx;
339
340 if (has_gravity)
341 {
342 local_b.noalias() +=
343 (fac * rho_L) * ip_data.dNdx.transpose() * specific_body_force;
344 }
345}
346
347template <typename ShapeFunction, int GlobalDim>
348Eigen::Matrix<double, GlobalDim, 1>
351 Eigen::Map<const NodalVectorType> const& local_p,
353 GlobalDimNodalMatrixType> const& ip_data,
354 GlobalDimMatrixType const& permeability, double const mu,
355 double const rho_L, GlobalDimVectorType const& specific_body_force,
356 bool const has_gravity)
357{
358 const double K = permeability(0, 0) / mu;
359 // Compute the velocity
360 GlobalDimVectorType velocity = -K * ip_data.dNdx * local_p;
361 // gravity term
362 if (has_gravity)
363 {
364 velocity += (K * rho_L) * specific_body_force;
365 }
366 return velocity;
367}
368
369template <typename ShapeFunction, int GlobalDim>
372 Eigen::Map<NodalMatrixType>& local_K,
373 Eigen::Map<NodalVectorType>& local_b,
375 GlobalDimNodalMatrixType> const& ip_data,
376 GlobalDimMatrixType const& permeability, double const mu,
377 double const rho_L, GlobalDimVectorType const& specific_body_force,
378 bool const has_gravity)
379{
380 const double fac = ip_data.integration_weight / mu;
381 local_K.noalias() +=
382 fac * ip_data.dNdx.transpose() * permeability * ip_data.dNdx;
383
384 if (has_gravity)
385 {
386 local_b.noalias() += (fac * rho_L) * ip_data.dNdx.transpose() *
387 permeability * specific_body_force;
388 }
389}
390
391template <typename ShapeFunction, int GlobalDim>
392Eigen::Matrix<double, GlobalDim, 1>
395 Eigen::Map<const NodalVectorType> const& local_p,
397 GlobalDimNodalMatrixType> const& ip_data,
398 GlobalDimMatrixType const& permeability, double const mu,
399 double const rho_L, GlobalDimVectorType const& specific_body_force,
400 bool const has_gravity)
401{
402 // Compute the velocity
403 GlobalDimVectorType velocity = -permeability * ip_data.dNdx * local_p / mu;
404
405 // gravity term
406 if (has_gravity)
407 {
408 velocity += (rho_L / mu) * permeability * specific_body_force;
409 }
410 return velocity;
411}
412
413} // namespace LiquidFlow
414} // 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::GlobalDimNodalMatrixType GlobalDimNodalMatrixType
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
typename ShapeMatricesType::NodalRowVectorType NodalRowVectorType
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::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
Definition: EigenMapTools.h:32
void shapeFunctionInterpolate(const NodalValues &, const ShapeMatrix &)
Definition: Interpolation.h:27
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)
static void calculateLaplacianAndGravityTerm(Eigen::Map< NodalMatrixType > &local_K, Eigen::Map< NodalVectorType > &local_b, IntegrationPointData< NodalRowVectorType, GlobalDimNodalMatrixType > const &ip_data, GlobalDimMatrixType const &permeability, 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< NodalRowVectorType, 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< NodalRowVectorType, GlobalDimNodalMatrixType > const &ip_data, GlobalDimMatrixType const &permeability, 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< NodalRowVectorType, GlobalDimNodalMatrixType > const &ip_data, GlobalDimMatrixType const &permeability, double const mu, double const rho_L, GlobalDimVectorType const &specific_body_force, bool const has_gravity)