OGS
LiquidFlowLocalAssembler-impl.h
Go to the documentation of this file.
1 
13 #pragma once
14 
20 
21 namespace ProcessLib
22 {
23 namespace LiquidFlow
24 {
25 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
27  assemble(double const t, double const dt,
28  std::vector<double> const& local_x,
29  std::vector<double> const& /*local_xdot*/,
30  std::vector<double>& local_M_data,
31  std::vector<double>& local_K_data,
32  std::vector<double>& local_b_data)
33 {
35  pos.setElementID(_element.getID());
36 
37  auto const& medium = *_process_data.media_map->getMedium(_element.getID());
39  vars[static_cast<int>(MaterialPropertyLib::Variable::temperature)] =
41  .template value<double>(vars, pos, t, dt);
42  vars[static_cast<int>(MaterialPropertyLib::Variable::phase_pressure)] =
43  std::numeric_limits<double>::quiet_NaN();
45  MaterialPropertyLib::formEigenTensor<ShapeFunction::DIM>(
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() == ShapeFunction::DIM ||
52  permeability.rows() == 1);
53 
54  if (permeability.size() == 1)
55  { // isotropic or 1D problem.
56  assembleMatrixAndVector<IsotropicCalculator>(
57  t, dt, local_x, local_M_data, local_K_data, local_b_data);
58  }
59  else
60  {
61  assembleMatrixAndVector<AnisotropicCalculator>(
62  t, dt, local_x, local_M_data, local_K_data, local_b_data);
63  }
64 }
65 
66 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
67 Eigen::Vector3d
69  MathLib::Point3d const& p_local_coords, double const t,
70  std::vector<double> const& local_x) const
71 {
72  // TODO (tf) Temporary value not used by current material models. Need
73  // extension of getFlux interface
74  double const dt = std::numeric_limits<double>::quiet_NaN();
75 
76  // Note: Axial symmetry is set to false here, because we only need dNdx
77  // here, which is not affected by axial symmetry.
78  auto const shape_matrices =
80  ShapeFunction::DIM>(
81  _element,
82  false /*is_axially_symmetric*/,
83  std::array{p_local_coords})[0];
84 
85  // create pos object to access the correct media property
87  pos.setElementID(_element.getID());
88 
89  auto const& medium = *_process_data.media_map->getMedium(_element.getID());
90  auto const& liquid_phase = medium.phase("AqueousLiquid");
91 
93 
94  double pressure = 0.0;
95  NumLib::shapeFunctionInterpolate(local_x, shape_matrices.N, pressure);
96  vars[static_cast<int>(MaterialPropertyLib::Variable::phase_pressure)] =
97  pressure;
98 
99  DimMatrixType const intrinsic_permeability =
100  MaterialPropertyLib::formEigenTensor<ShapeFunction::DIM>(
102  vars, pos, t, dt));
103  auto const viscosity =
105  .template value<double>(vars, pos, t, dt);
106 
107  Eigen::Vector3d flux(0.0, 0.0, 0.0);
108  auto const flux_local =
109  (-intrinsic_permeability / viscosity * shape_matrices.dNdx *
110  Eigen::Map<const NodalVectorType>(local_x.data(), local_x.size()))
111  .eval();
112 
113  flux.head<GlobalDim>() =
114  _process_data.element_rotation_matrices[_element.getID()] * flux_local;
115 
116  return flux;
117 }
118 
119 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
120 template <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 
131  auto local_M = MathLib::createZeroedMatrix<NodalMatrixType>(
132  local_M_data, local_matrix_size, local_matrix_size);
133  auto local_K = MathLib::createZeroedMatrix<NodalMatrixType>(
134  local_K_data, local_matrix_size, local_matrix_size);
135  auto local_b = MathLib::createZeroedVector<NodalVectorType>(
136  local_b_data, local_matrix_size);
137 
138  unsigned const n_integration_points =
139  _integration_method.getNumberOfPoints();
140 
142  pos.setElementID(_element.getID());
143 
144  auto const& medium = *_process_data.media_map->getMedium(_element.getID());
145  auto const& liquid_phase = medium.phase("AqueousLiquid");
146 
148  vars[static_cast<int>(MaterialPropertyLib::Variable::temperature)] =
150  .template value<double>(vars, pos, t, dt);
151 
152  DimVectorType const projected_body_force_vector =
153  _process_data.element_rotation_matrices[_element.getID()].transpose() *
154  _process_data.specific_body_force;
155 
156  for (unsigned ip = 0; ip < n_integration_points; ip++)
157  {
158  auto const& ip_data = _ip_data[ip];
159 
160  double p = 0.;
161  NumLib::shapeFunctionInterpolate(local_x, ip_data.N, p);
162  vars[static_cast<int>(MaterialPropertyLib::Variable::phase_pressure)] =
163  p;
164 
165  // Compute density:
166  auto const fluid_density =
168  .template value<double>(vars, pos, t, dt);
169  assert(fluid_density > 0.);
170  auto const ddensity_dpressure =
172  .template dValue<double>(
174  dt);
175 
176  auto const porosity =
178  .template value<double>(vars, pos, t, dt);
180  .template value<double>(vars, pos, t, dt);
181 
182  // Assemble mass matrix, M
183  local_M.noalias() +=
184  (porosity * ddensity_dpressure / fluid_density + storage) *
185  ip_data.N.transpose() * ip_data.N * ip_data.integration_weight;
186 
187  // Compute viscosity:
188  auto const viscosity =
190  .template value<double>(vars, pos, t, dt);
191 
192  pos.setIntegrationPoint(ip);
194  MaterialPropertyLib::formEigenTensor<ShapeFunction::DIM>(
196  vars, pos, t, dt));
197 
198  // Assemble Laplacian, K, and RHS by the gravitational term
199  LaplacianGravityVelocityCalculator::calculateLaplacianAndGravityTerm(
200  local_K, local_b, ip_data, permeability, viscosity, fluid_density,
201  projected_body_force_vector, _process_data.has_gravity);
202  }
203 }
204 
205 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
206 template <typename VelocityCacheType>
208  computeDarcyVelocity(bool const is_scalar_permeability, const double t,
209  const double dt, std::vector<double> const& local_x,
211  VelocityCacheType& darcy_velocity_at_ips) const
212 {
213  if (is_scalar_permeability)
214  { // isotropic or 1D problem.
215  computeProjectedDarcyVelocity<IsotropicCalculator>(
216  t, dt, local_x, pos, darcy_velocity_at_ips);
217  }
218  else
219  {
220  computeProjectedDarcyVelocity<AnisotropicCalculator>(
221  t, dt, local_x, pos, darcy_velocity_at_ips);
222  }
223 }
224 
225 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
226 std::vector<double> const&
229  const double t,
230  std::vector<GlobalVector*> const& x,
231  std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
232  std::vector<double>& velocity_cache) const
233 {
234  // TODO (tf) Temporary value not used by current material models. Need
235  // extension of secondary variable interface.
236  double const dt = std::numeric_limits<double>::quiet_NaN();
237 
238  constexpr int process_id = 0;
239  auto const indices =
240  NumLib::getIndices(_element.getID(), *dof_table[process_id]);
241  auto const local_x = x[process_id]->get(indices);
242  auto const n_integration_points = _integration_method.getNumberOfPoints();
243  velocity_cache.clear();
244 
246  pos.setElementID(_element.getID());
247 
248  auto const& medium = *_process_data.media_map->getMedium(_element.getID());
250  vars[static_cast<int>(MaterialPropertyLib::Variable::temperature)] =
252  .template value<double>(vars, pos, t, dt);
253  vars[static_cast<int>(MaterialPropertyLib::Variable::phase_pressure)] =
254  std::numeric_limits<double>::quiet_NaN();
255 
257  MaterialPropertyLib::formEigenTensor<ShapeFunction::DIM>(
259  vars, pos, t, dt));
260 
261  assert(permeability.rows() == _element.getDimension() ||
262  permeability.rows() == 1);
263 
264  bool const is_scalar_permeability = (permeability.size() == 1);
265 
266  auto velocity_cache_vectors = MathLib::createZeroedMatrix<
267  Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
268  velocity_cache, GlobalDim, n_integration_points);
269 
270  computeDarcyVelocity(is_scalar_permeability, t, dt, local_x, pos,
271  velocity_cache_vectors);
272 
273  return velocity_cache;
274 }
275 
276 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
277 template <typename LaplacianGravityVelocityCalculator,
278  typename VelocityCacheType>
281  const double t, const double dt, std::vector<double> const& local_x,
283  VelocityCacheType& darcy_velocity_at_ips) const
284 {
285  auto const local_matrix_size = local_x.size();
286  assert(local_matrix_size == ShapeFunction::NPOINTS);
287 
288  const auto local_p_vec =
289  MathLib::toVector<NodalVectorType>(local_x, local_matrix_size);
290 
291  unsigned const n_integration_points =
292  _integration_method.getNumberOfPoints();
293 
294  auto const& medium = *_process_data.media_map->getMedium(_element.getID());
295  auto const& liquid_phase = medium.phase("AqueousLiquid");
296 
298  vars[static_cast<int>(MaterialPropertyLib::Variable::temperature)] =
300  .template value<double>(vars, pos, t, dt);
301 
302  DimVectorType const projected_body_force_vector =
303  _process_data.element_rotation_matrices[_element.getID()].transpose() *
304  _process_data.specific_body_force;
305 
306  for (unsigned ip = 0; ip < n_integration_points; ip++)
307  {
308  auto const& ip_data = _ip_data[ip];
309  double p = 0.;
310  NumLib::shapeFunctionInterpolate(local_x, ip_data.N, p);
311  vars[static_cast<int>(MaterialPropertyLib::Variable::phase_pressure)] =
312  p;
313 
314  // Compute density:
315  auto const fluid_density =
317  .template value<double>(vars, pos, t, dt);
318  // Compute viscosity:
319  auto const viscosity =
321  .template value<double>(vars, pos, t, dt);
322 
324  MaterialPropertyLib::formEigenTensor<ShapeFunction::DIM>(
326  vars, pos, t, dt));
327 
328  Eigen::VectorXd const velocity_at_ip =
329  LaplacianGravityVelocityCalculator::calculateVelocity(
330  local_p_vec, ip_data, permeability, viscosity, fluid_density,
331  projected_body_force_vector, _process_data.has_gravity);
332 
333  Eigen::MatrixXd const& rotation_matrix =
334  _process_data.element_rotation_matrices[_element.getID()];
335  darcy_velocity_at_ips.col(ip) = rotation_matrix * velocity_at_ip;
336  }
337 }
338 
339 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
342  Eigen::Map<NodalMatrixType>& local_K,
343  Eigen::Map<NodalVectorType>& local_b,
345  GlobalDimNodalMatrixType> const& ip_data,
346  DimMatrixType const& permeability, double const mu, double const rho_L,
347  DimVectorType const& specific_body_force, bool const has_gravity)
348 {
349  const double K = permeability(0, 0) / mu;
350  const double fac = K * ip_data.integration_weight;
351  local_K.noalias() += fac * ip_data.dNdx.transpose() * ip_data.dNdx;
352 
353  if (has_gravity)
354  {
355  local_b.noalias() +=
356  (fac * rho_L) * ip_data.dNdx.transpose() * specific_body_force;
357  }
358 }
359 
360 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
361 Eigen::Matrix<double, ShapeFunction::DIM, 1>
364  Eigen::Map<const NodalVectorType> const& local_p,
366  GlobalDimNodalMatrixType> const& ip_data,
367  DimMatrixType const& permeability, double const mu, double const rho_L,
368  DimVectorType const& specific_body_force, bool const has_gravity)
369 {
370  const double K = permeability(0, 0) / mu;
371  // Compute the velocity
372  DimVectorType velocity = -K * ip_data.dNdx * local_p;
373  // gravity term
374  if (has_gravity)
375  {
376  velocity += (K * rho_L) * specific_body_force;
377  }
378  return velocity;
379 }
380 
381 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
384  Eigen::Map<NodalMatrixType>& local_K,
385  Eigen::Map<NodalVectorType>& local_b,
387  GlobalDimNodalMatrixType> const& ip_data,
388  DimMatrixType const& permeability, double const mu, double const rho_L,
389  DimVectorType const& specific_body_force, bool const has_gravity)
390 {
391  const double fac = ip_data.integration_weight / mu;
392  local_K.noalias() +=
393  fac * ip_data.dNdx.transpose() * permeability * ip_data.dNdx;
394 
395  if (has_gravity)
396  {
397  local_b.noalias() += (fac * rho_L) * ip_data.dNdx.transpose() *
398  permeability * specific_body_force;
399  }
400 }
401 
402 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
403 Eigen::Matrix<double, ShapeFunction::DIM, 1>
406  Eigen::Map<const NodalVectorType> const& local_p,
408  GlobalDimNodalMatrixType> const& ip_data,
409  DimMatrixType const& permeability, double const mu, double const rho_L,
410  DimVectorType const& specific_body_force, bool const has_gravity)
411 {
412  // Compute the velocity
413  DimVectorType velocity = -permeability * ip_data.dNdx * local_p / mu;
414 
415  // gravity term
416  if (has_gravity)
417  {
418  velocity += (rho_L / mu) * permeability * specific_body_force;
419  }
420  return velocity;
421 }
422 
423 } // namespace LiquidFlow
424 } // namespace ProcessLib
void setElementID(std::size_t element_id)
void setIntegrationPoint(unsigned integration_point)
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 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
typename ShapeMatricesType::DimVectorType DimVectorType
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
typename ShapeMatricesType::NodalRowVectorType NodalRowVectorType
typename ShapeMatricesType::GlobalDimNodalMatrixType GlobalDimNodalMatrixType
Eigen::Vector3d getFlux(MathLib::Point3d const &p_local_coords, double const t, std::vector< double > const &local_x) const override
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::DimMatrixType DimMatrixType
void computeProjectedDarcyVelocity(const double t, const double dt, std::vector< double > const &local_x, ParameterLib::SpatialPosition const &pos, VelocityCacheType &darcy_velocity_at_ips) const
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
Definition: VariableType.h:108
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
Definition: EigenMapTools.h:32
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > computeShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, PointContainer const &points)
void shapeFunctionInterpolate(const NodalValues &nodal_values, const ShapeMatrix &shape_matrix_N, double &interpolated_value, ScalarTypes &... interpolated_values)
Definition: Interpolation.h:79
std::vector< GlobalIndexType > getIndices(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
double fluid_density(const double p, const double T, const double x)
static void calculateLaplacianAndGravityTerm(Eigen::Map< NodalMatrixType > &local_K, Eigen::Map< NodalVectorType > &local_b, IntegrationPointData< NodalRowVectorType, GlobalDimNodalMatrixType > const &ip_data, DimMatrixType const &permeability, double const mu, double const rho_L, DimVectorType const &specific_body_force, bool const has_gravity)
static Eigen::Matrix< double, ShapeFunction::DIM, 1 > calculateVelocity(Eigen::Map< const NodalVectorType > const &local_p, IntegrationPointData< NodalRowVectorType, GlobalDimNodalMatrixType > const &ip_data, DimMatrixType const &permeability, double const mu, double const rho_L, DimVectorType 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, DimMatrixType const &permeability, double const mu, double const rho_L, DimVectorType const &specific_body_force, bool const has_gravity)
static Eigen::Matrix< double, ShapeFunction::DIM, 1 > calculateVelocity(Eigen::Map< const NodalVectorType > const &local_p, IntegrationPointData< NodalRowVectorType, GlobalDimNodalMatrixType > const &ip_data, DimMatrixType const &permeability, double const mu, double const rho_L, DimVectorType const &specific_body_force, bool const has_gravity)