OGS
HydroMechanicsLocalAssemblerMatrix-impl.h
Go to the documentation of this file.
1 
11 #pragma once
12 
16 #include "MathLib/KelvinVector.h"
17 #include "MeshLib/ElementStatus.h"
21 
22 namespace ProcessLib
23 {
24 namespace LIE
25 {
26 namespace HydroMechanics
27 {
28 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
29  typename IntegrationMethod, int GlobalDim>
30 HydroMechanicsLocalAssemblerMatrix<ShapeFunctionDisplacement,
31  ShapeFunctionPressure, IntegrationMethod,
32  GlobalDim>::
33  HydroMechanicsLocalAssemblerMatrix(
34  MeshLib::Element const& e,
35  std::size_t const n_variables,
36  std::size_t const /*local_matrix_size*/,
37  std::vector<unsigned> const& dofIndex_to_localIndex,
38  bool const is_axially_symmetric,
39  unsigned const integration_order,
42  e, is_axially_symmetric,
43  (n_variables - 1) * ShapeFunctionDisplacement::NPOINTS * GlobalDim +
44  ShapeFunctionPressure::NPOINTS,
45  dofIndex_to_localIndex),
46  _process_data(process_data)
47 {
48  IntegrationMethod integration_method(integration_order);
49  unsigned const n_integration_points =
50  integration_method.getNumberOfPoints();
51 
52  _ip_data.reserve(n_integration_points);
53 
54  auto const shape_matrices_u =
55  NumLib::initShapeMatrices<ShapeFunctionDisplacement,
57  e, is_axially_symmetric, integration_method);
58 
59  auto const shape_matrices_p =
60  NumLib::initShapeMatrices<ShapeFunctionPressure,
61  ShapeMatricesTypePressure, GlobalDim>(
62  e, is_axially_symmetric, integration_method);
63 
65  _process_data.solid_materials, _process_data.material_ids, e.getID());
66 
68  x_position.setElementID(e.getID());
69  for (unsigned ip = 0; ip < n_integration_points; ip++)
70  {
71  x_position.setIntegrationPoint(ip);
72 
73  _ip_data.emplace_back(solid_material);
74  auto& ip_data = _ip_data[ip];
75  auto const& sm_u = shape_matrices_u[ip];
76  auto const& sm_p = shape_matrices_p[ip];
77  ip_data.integration_weight =
78  sm_u.detJ * sm_u.integralMeasure *
79  integration_method.getWeightedPoint(ip).getWeight();
80  ip_data.darcy_velocity.setZero();
81 
82  ip_data.N_u = sm_u.N;
83  ip_data.dNdx_u = sm_u.dNdx;
84  ip_data.H_u.setZero(GlobalDim, displacement_size);
85  for (int i = 0; i < GlobalDim; ++i)
86  {
87  ip_data.H_u
88  .template block<1, displacement_size / GlobalDim>(
89  i, i * displacement_size / GlobalDim)
90  .noalias() = ip_data.N_u;
91  }
92 
93  ip_data.N_p = sm_p.N;
94  ip_data.dNdx_p = sm_p.dNdx;
95 
96  ip_data.sigma_eff.setZero(kelvin_vector_size);
97  ip_data.eps.setZero(kelvin_vector_size);
98 
99  ip_data.sigma_eff_prev.resize(kelvin_vector_size);
100  ip_data.eps_prev.resize(kelvin_vector_size);
101  ip_data.C.resize(kelvin_vector_size, kelvin_vector_size);
102 
103  auto const initial_effective_stress =
104  _process_data.initial_effective_stress(0, x_position);
105  for (unsigned i = 0; i < kelvin_vector_size; i++)
106  {
107  ip_data.sigma_eff[i] = initial_effective_stress[i];
108  ip_data.sigma_eff_prev[i] = initial_effective_stress[i];
109  }
110  }
111 }
112 
113 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
114  typename IntegrationMethod, int GlobalDim>
116  ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
117  GlobalDim>::assembleWithJacobianConcrete(double const t, double const dt,
118  Eigen::VectorXd const& local_x,
119  Eigen::VectorXd const& local_x_dot,
120  Eigen::VectorXd& local_rhs,
121  Eigen::MatrixXd& local_Jac)
122 {
123  auto p = const_cast<Eigen::VectorXd&>(local_x).segment(pressure_index,
124  pressure_size);
125  auto p_dot = const_cast<Eigen::VectorXd&>(local_x_dot)
126  .segment(pressure_index, pressure_size);
127 
128  if (_process_data.deactivate_matrix_in_flow)
129  {
130  setPressureOfInactiveNodes(t, p);
131  setPressureDotOfInactiveNodes(p_dot);
132  }
133 
134  auto u = local_x.segment(displacement_index, displacement_size);
135  auto u_dot = local_x_dot.segment(displacement_index, displacement_size);
136 
137  auto rhs_p = local_rhs.template segment<pressure_size>(pressure_index);
138  auto rhs_u =
139  local_rhs.template segment<displacement_size>(displacement_index);
140 
141  auto J_pp = local_Jac.template block<pressure_size, pressure_size>(
142  pressure_index, pressure_index);
143  auto J_pu = local_Jac.template block<pressure_size, displacement_size>(
144  pressure_index, displacement_index);
145  auto J_uu = local_Jac.template block<displacement_size, displacement_size>(
146  displacement_index, displacement_index);
147  auto J_up = local_Jac.template block<displacement_size, pressure_size>(
148  displacement_index, pressure_index);
149 
150  assembleBlockMatricesWithJacobian(t, dt, p, p_dot, u, u_dot, rhs_p, rhs_u,
151  J_pp, J_pu, J_uu, J_up);
152 }
153 
154 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
155  typename IntegrationMethod, int GlobalDim>
156 void HydroMechanicsLocalAssemblerMatrix<ShapeFunctionDisplacement,
157  ShapeFunctionPressure,
158  IntegrationMethod, GlobalDim>::
159  assembleBlockMatricesWithJacobian(
160  double const t, double const dt,
161  Eigen::Ref<const Eigen::VectorXd> const& p,
162  Eigen::Ref<const Eigen::VectorXd> const& p_dot,
163  Eigen::Ref<const Eigen::VectorXd> const& u,
164  Eigen::Ref<const Eigen::VectorXd> const& u_dot,
165  Eigen::Ref<Eigen::VectorXd> rhs_p, Eigen::Ref<Eigen::VectorXd> rhs_u,
166  Eigen::Ref<Eigen::MatrixXd> J_pp, Eigen::Ref<Eigen::MatrixXd> J_pu,
167  Eigen::Ref<Eigen::MatrixXd> J_uu, Eigen::Ref<Eigen::MatrixXd> J_up)
168 {
169  assert(this->_element.getDimension() == GlobalDim);
170 
171  typename ShapeMatricesTypePressure::NodalMatrixType laplace_p =
172  ShapeMatricesTypePressure::NodalMatrixType::Zero(pressure_size,
173  pressure_size);
174 
175  typename ShapeMatricesTypePressure::NodalMatrixType storage_p =
176  ShapeMatricesTypePressure::NodalMatrixType::Zero(pressure_size,
177  pressure_size);
178 
179  typename ShapeMatricesTypeDisplacement::template MatrixType<
180  displacement_size, pressure_size>
181  Kup = ShapeMatricesTypeDisplacement::template MatrixType<
182  displacement_size, pressure_size>::Zero(displacement_size,
183  pressure_size);
184 
185  auto const& gravity_vec = _process_data.specific_body_force;
186 
187  MPL::VariableArray variables;
188  MPL::VariableArray variables_prev;
190  x_position.setElementID(_element.getID());
191 
192  unsigned const n_integration_points = _ip_data.size();
193  for (unsigned ip = 0; ip < n_integration_points; ip++)
194  {
195  x_position.setIntegrationPoint(ip);
196 
197  auto& ip_data = _ip_data[ip];
198  auto const& ip_w = ip_data.integration_weight;
199  auto const& N_u = ip_data.N_u;
200  auto const& dNdx_u = ip_data.dNdx_u;
201  auto const& N_p = ip_data.N_p;
202  auto const& dNdx_p = ip_data.dNdx_p;
203  auto const& H_u = ip_data.H_u;
204 
205  auto const x_coord =
206  NumLib::interpolateXCoordinate<ShapeFunctionDisplacement,
208  _element, N_u);
209  auto const B =
211  ShapeFunctionDisplacement::NPOINTS,
212  typename BMatricesType::BMatrixType>(
213  dNdx_u, N_u, x_coord, _is_axially_symmetric);
214 
215  auto const& eps_prev = ip_data.eps_prev;
216  auto const& sigma_eff_prev = ip_data.sigma_eff_prev;
217  auto& sigma_eff = ip_data.sigma_eff;
218 
219  auto& eps = ip_data.eps;
220  auto& state = ip_data.material_state_variables;
221 
222  auto const alpha = _process_data.biot_coefficient(t, x_position)[0];
223  auto const rho_sr = _process_data.solid_density(t, x_position)[0];
224  auto const rho_fr = _process_data.fluid_density(t, x_position)[0];
225  auto const porosity = _process_data.porosity(t, x_position)[0];
226 
227  double const rho = rho_sr * (1 - porosity) + porosity * rho_fr;
228  auto const& identity2 =
230 
231  eps.noalias() = B * u;
232 
233  variables[static_cast<int>(
236 
237  variables_prev[static_cast<int>(MaterialPropertyLib::Variable::stress)]
239  sigma_eff_prev);
240  variables_prev[static_cast<int>(
243  eps_prev);
244  variables_prev[static_cast<int>(
246  .emplace<double>(_process_data.reference_temperature);
247 
248  auto&& solution = _ip_data[ip].solid_material.integrateStress(
249  variables_prev, variables, t, x_position, dt, *state);
250 
251  if (!solution)
252  {
253  OGS_FATAL("Computation of local constitutive relation failed.");
254  }
255 
257  std::tie(sigma_eff, state, C) = std::move(*solution);
258 
259  J_uu.noalias() += B.transpose() * C * B * ip_w;
260 
261  rhs_u.noalias() -= B.transpose() * sigma_eff * ip_w;
262  rhs_u.noalias() -= -H_u.transpose() * rho * gravity_vec * ip_w;
263 
264  //
265  // pressure equation, pressure part and displacement equation, pressure
266  // part
267  //
268  if (!_process_data.deactivate_matrix_in_flow) // Only for hydraulically
269  // active matrix
270  {
271  Kup.noalias() += B.transpose() * alpha * identity2 * N_p * ip_w;
272 
273  double const k_over_mu =
274  _process_data.intrinsic_permeability(t, x_position)[0] /
275  _process_data.fluid_viscosity(t, x_position)[0];
276  double const S = _process_data.specific_storage(t, x_position)[0];
277 
278  auto q = ip_data.darcy_velocity.head(GlobalDim);
279  q.noalias() = -k_over_mu * (dNdx_p * p + rho_fr * gravity_vec);
280 
281  laplace_p.noalias() +=
282  dNdx_p.transpose() * k_over_mu * dNdx_p * ip_w;
283  storage_p.noalias() += N_p.transpose() * S * N_p * ip_w;
284 
285  rhs_p.noalias() +=
286  dNdx_p.transpose() * rho_fr * k_over_mu * gravity_vec * ip_w;
287  }
288  }
289 
290  // displacement equation, pressure part
291  J_up.noalias() -= Kup;
292 
293  // pressure equation, pressure part.
294  J_pp.noalias() += laplace_p + storage_p / dt;
295 
296  // pressure equation, displacement part.
297  J_pu.noalias() += Kup.transpose() / dt;
298 
299  // pressure equation
300  rhs_p.noalias() -=
301  laplace_p * p + storage_p * p_dot + Kup.transpose() * u_dot;
302 
303  // displacement equation
304  rhs_u.noalias() -= -Kup * p;
305 }
306 
307 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
308  typename IntegrationMethod, int GlobalDim>
310  ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
311  GlobalDim>::postTimestepConcreteWithVector(double const t, double const dt,
312  Eigen::VectorXd const& local_x)
313 {
314  auto p = const_cast<Eigen::VectorXd&>(local_x).segment(pressure_index,
315  pressure_size);
316  if (_process_data.deactivate_matrix_in_flow)
317  {
318  setPressureOfInactiveNodes(t, p);
319  }
320  auto u = local_x.segment(displacement_index, displacement_size);
321 
322  postTimestepConcreteWithBlockVectors(t, dt, p, u);
323 }
324 
325 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
326  typename IntegrationMethod, int GlobalDim>
327 void HydroMechanicsLocalAssemblerMatrix<ShapeFunctionDisplacement,
328  ShapeFunctionPressure,
329  IntegrationMethod, GlobalDim>::
330  postTimestepConcreteWithBlockVectors(
331  double const t, double const dt,
332  Eigen::Ref<const Eigen::VectorXd> const& p,
333  Eigen::Ref<const Eigen::VectorXd> const& u)
334 {
335  MPL::VariableArray variables;
336  MPL::VariableArray variables_prev;
338  x_position.setElementID(_element.getID());
339 
340  unsigned const n_integration_points = _ip_data.size();
341  for (unsigned ip = 0; ip < n_integration_points; ip++)
342  {
343  x_position.setIntegrationPoint(ip);
344 
345  auto& ip_data = _ip_data[ip];
346 
347  auto const& eps_prev = ip_data.eps_prev;
348  auto const& sigma_eff_prev = ip_data.sigma_eff_prev;
349 
350  auto& eps = ip_data.eps;
351  auto& sigma_eff = ip_data.sigma_eff;
352  auto& state = ip_data.material_state_variables;
353 
354  auto const& N_u = ip_data.N_u;
355  auto const& dNdx_u = ip_data.dNdx_u;
356 
357  auto const x_coord =
358  NumLib::interpolateXCoordinate<ShapeFunctionDisplacement,
360  _element, N_u);
361  auto const B =
363  ShapeFunctionDisplacement::NPOINTS,
364  typename BMatricesType::BMatrixType>(
365  dNdx_u, N_u, x_coord, _is_axially_symmetric);
366 
367  eps.noalias() = B * u;
368 
369  variables[static_cast<int>(
372 
373  variables_prev[static_cast<int>(MaterialPropertyLib::Variable::stress)]
375  sigma_eff_prev);
376  variables_prev[static_cast<int>(
379  eps_prev);
380  variables_prev[static_cast<int>(
382  .emplace<double>(_process_data.reference_temperature);
383 
384  auto&& solution = _ip_data[ip].solid_material.integrateStress(
385  variables_prev, variables, t, x_position, dt, *state);
386 
387  if (!solution)
388  {
389  OGS_FATAL("Computation of local constitutive relation failed.");
390  }
391 
393  std::tie(sigma_eff, state, C) = std::move(*solution);
394 
395  if (!_process_data.deactivate_matrix_in_flow) // Only for hydraulically
396  // active matrix
397  {
398  double const k_over_mu =
399  _process_data.intrinsic_permeability(t, x_position)[0] /
400  _process_data.fluid_viscosity(t, x_position)[0];
401  auto const rho_fr = _process_data.fluid_density(t, x_position)[0];
402  auto const& gravity_vec = _process_data.specific_body_force;
403  auto const& dNdx_p = ip_data.dNdx_p;
404 
405  ip_data.darcy_velocity.head(GlobalDim).noalias() =
406  -k_over_mu * (dNdx_p * p + rho_fr * gravity_vec);
407  }
408  }
409 
410  int n = GlobalDim == 2 ? 4 : 6;
411  Eigen::VectorXd ele_stress = Eigen::VectorXd::Zero(n);
412  Eigen::VectorXd ele_strain = Eigen::VectorXd::Zero(n);
413  GlobalDimVector ele_velocity = GlobalDimVector::Zero();
414 
415  for (auto const& ip_data : _ip_data)
416  {
417  ele_stress += ip_data.sigma_eff;
418  ele_strain += ip_data.eps;
419  ele_velocity += ip_data.darcy_velocity;
420  }
421 
422  ele_stress /= static_cast<double>(n_integration_points);
423  ele_strain /= static_cast<double>(n_integration_points);
424  ele_velocity /= static_cast<double>(n_integration_points);
425 
426  auto const element_id = _element.getID();
427  (*_process_data.mesh_prop_stress_xx)[_element.getID()] = ele_stress[0];
428  (*_process_data.mesh_prop_stress_yy)[_element.getID()] = ele_stress[1];
429  (*_process_data.mesh_prop_stress_zz)[_element.getID()] = ele_stress[2];
430  (*_process_data.mesh_prop_stress_xy)[_element.getID()] = ele_stress[3];
431  if (GlobalDim == 3)
432  {
433  (*_process_data.mesh_prop_stress_yz)[_element.getID()] = ele_stress[4];
434  (*_process_data.mesh_prop_stress_xz)[_element.getID()] = ele_stress[5];
435  }
436 
437  (*_process_data.mesh_prop_strain_xx)[_element.getID()] = ele_strain[0];
438  (*_process_data.mesh_prop_strain_yy)[_element.getID()] = ele_strain[1];
439  (*_process_data.mesh_prop_strain_zz)[_element.getID()] = ele_strain[2];
440  (*_process_data.mesh_prop_strain_xy)[_element.getID()] = ele_strain[3];
441  if (GlobalDim == 3)
442  {
443  (*_process_data.mesh_prop_strain_yz)[_element.getID()] = ele_strain[4];
444  (*_process_data.mesh_prop_strain_xz)[_element.getID()] = ele_strain[5];
445  }
446 
447  for (unsigned i = 0; i < GlobalDim; i++)
448  {
449  (*_process_data.mesh_prop_velocity)[element_id * GlobalDim + i] =
450  ele_velocity[i];
451  }
452 
454  ShapeFunctionPressure, typename ShapeFunctionDisplacement::MeshElement,
455  GlobalDim>(_element, _is_axially_symmetric, p,
456  *_process_data.mesh_prop_nodal_p);
457 }
458 
459 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
460  typename IntegrationMethod, int GlobalDim>
462  ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
463  GlobalDim>::setPressureOfInactiveNodes(double const t,
464  Eigen::Ref<Eigen::VectorXd>
465  p)
466 {
468  x_position.setElementID(_element.getID());
469  for (unsigned i = 0; i < pressure_size; i++)
470  {
471  // only inactive nodes
472  if (_process_data.p_element_status->isActiveNode(_element.getNode(i)))
473  {
474  continue;
475  }
476  x_position.setNodeID(getNodeIndex(_element, i));
477  auto const p0 = (*_process_data.p0)(t, x_position)[0];
478  p[i] = p0;
479  }
480 }
481 
482 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
483  typename IntegrationMethod, int GlobalDim>
485  ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
486  GlobalDim>::setPressureDotOfInactiveNodes(Eigen::Ref<Eigen::VectorXd> p_dot)
487 {
488  for (unsigned i = 0; i < pressure_size; i++)
489  {
490  // only inactive nodes
491  if (_process_data.p_element_status->isActiveNode(_element.getNode(i)))
492  {
493  continue;
494  }
495  p_dot[i] = 0;
496  }
497 }
498 
499 } // namespace HydroMechanics
500 } // namespace LIE
501 } // namespace ProcessLib
Definition of the ElementStatus class.
#define OGS_FATAL(...)
Definition: Error.h:26
virtual std::size_t getID() const final
Returns the ID of the element.
Definition: Element.h:82
void setNodeID(std::size_t node_id)
void setElementID(std::size_t element_id)
void setIntegrationPoint(unsigned integration_point)
MatrixType< _kelvin_vector_size, _number_of_dof > BMatrixType
Definition: BMatrixPolicy.h:55
std::vector< IntegrationPointDataType, Eigen::aligned_allocator< IntegrationPointDataType > > _ip_data
ShapeMatrixPolicyType< ShapeFunctionPressure, GlobalDim > ShapeMatricesTypePressure
ShapeMatrixPolicyType< ShapeFunctionDisplacement, GlobalDim > ShapeMatricesTypeDisplacement
MechanicsBase< DisplacementDim > & selectSolidConstitutiveRelation(std::map< int, std::unique_ptr< MechanicsBase< DisplacementDim >>> const &constitutive_relations, MeshLib::PropertyVector< int > const *const material_ids, std::size_t const element_id)
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
Definition: VariableType.h:108
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Definition: KelvinVector.h:48
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), kelvin_vector_dimensions(DisplacementDim), Eigen::RowMajor > KelvinMatrixType
Definition: KelvinVector.h:56
static const double q
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition: Element.cpp:225
double interpolateXCoordinate(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
void interpolateToHigherOrderNodes(MeshLib::Element const &element, bool const is_axially_symmetric, Eigen::MatrixBase< EigenMatrixType > const &node_values, MeshLib::PropertyVector< double > &interpolated_values_global_vector)
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > initShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, IntegrationMethod const &integration_method)
BMatrixType computeBMatrix(DNDX_Type const &dNdx, N_Type const &N, const double radius, const bool is_axially_symmetric)
Fills a B-matrix based on given shape function dN/dx values.
Definition: LinearBMatrix.h:42
MatrixType< ShapeFunction::NPOINTS, ShapeFunction::NPOINTS > NodalMatrixType