OGS
ThermoHydroMechanicsFEM-impl.h
Go to the documentation of this file.
1 
11 #pragma once
12 
13 #include "MaterialLib/MPL/Medium.h"
19 #include "MathLib/KelvinVector.h"
24 
25 namespace ProcessLib
26 {
27 namespace ThermoHydroMechanics
28 {
29 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
30  typename IntegrationMethod, int DisplacementDim>
31 ThermoHydroMechanicsLocalAssembler<ShapeFunctionDisplacement,
32  ShapeFunctionPressure, IntegrationMethod,
33  DisplacementDim>::
34  ThermoHydroMechanicsLocalAssembler(
35  MeshLib::Element const& e,
36  std::size_t const /*local_matrix_size*/,
37  bool const is_axially_symmetric,
38  unsigned const integration_order,
40  : _process_data(process_data),
41  _integration_method(integration_order),
42  _element(e),
43  _is_axially_symmetric(is_axially_symmetric)
44 {
45  unsigned const n_integration_points =
46  _integration_method.getNumberOfPoints();
47 
48  _ip_data.reserve(n_integration_points);
49  _secondary_data.N_u.resize(n_integration_points);
50 
51  auto const shape_matrices_u =
52  NumLib::initShapeMatrices<ShapeFunctionDisplacement,
54  DisplacementDim>(e, is_axially_symmetric,
56 
57  auto const shape_matrices_p =
58  NumLib::initShapeMatrices<ShapeFunctionPressure,
59  ShapeMatricesTypePressure, DisplacementDim>(
60  e, is_axially_symmetric, _integration_method);
61 
62  auto const& solid_material =
64  _process_data.solid_materials, _process_data.material_ids,
65  e.getID());
66 
67  for (unsigned ip = 0; ip < n_integration_points; ip++)
68  {
69  _ip_data.emplace_back(solid_material);
70  auto& ip_data = _ip_data[ip];
71  auto const& sm_u = shape_matrices_u[ip];
72  ip_data.integration_weight =
73  _integration_method.getWeightedPoint(ip).getWeight() *
74  sm_u.integralMeasure * sm_u.detJ;
75 
76  ip_data.N_u_op = ShapeMatricesTypeDisplacement::template MatrixType<
77  DisplacementDim, displacement_size>::Zero(DisplacementDim,
79  for (int i = 0; i < DisplacementDim; ++i)
80  ip_data.N_u_op
81  .template block<1, displacement_size / DisplacementDim>(
82  i, i * displacement_size / DisplacementDim)
83  .noalias() = sm_u.N;
84 
85  ip_data.N_u = sm_u.N;
86  ip_data.dNdx_u = sm_u.dNdx;
87 
88  ip_data.N_p = shape_matrices_p[ip].N;
89  ip_data.dNdx_p = shape_matrices_p[ip].dNdx;
90 
91  _secondary_data.N_u[ip] = shape_matrices_u[ip].N;
92  }
93 }
94 
95 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
96  typename IntegrationMethod, int DisplacementDim>
98  ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
99  DisplacementDim>::setIPDataInitialConditions(std::string const& name,
100  double const* values,
101  int const integration_order)
102 {
103  if (integration_order !=
104  static_cast<int>(_integration_method.getIntegrationOrder()))
105  {
106  OGS_FATAL(
107  "Setting integration point initial conditions; The integration "
108  "order of the local assembler for element {:d} is different from "
109  "the integration order in the initial condition.",
110  _element.getID());
111  }
112 
113  if (name == "sigma_ip")
114  {
115  if (_process_data.initial_stress != nullptr)
116  {
117  OGS_FATAL(
118  "Setting initial conditions for stress from integration "
119  "point data and from a parameter '{:s}' is not possible "
120  "simultaneously.",
121  _process_data.initial_stress->name);
122  }
123 
124  return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
125  values, _ip_data, &IpData::sigma_eff);
126  }
127  if (name == "epsilon_ip")
128  {
129  return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
130  values, _ip_data, &IpData::eps);
131  }
132 
133  return 0;
134 }
135 
136 // Assembles the local Jacobian matrix. So far, the linearisation of HT part is
137 // not considered as that in HT process.
138 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
139  typename IntegrationMethod, int DisplacementDim>
140 void ThermoHydroMechanicsLocalAssembler<ShapeFunctionDisplacement,
141  ShapeFunctionPressure,
142  IntegrationMethod, DisplacementDim>::
143  assembleWithJacobian(double const t, double const dt,
144  std::vector<double> const& local_x,
145  std::vector<double> const& local_xdot,
146  const double /*dxdot_dx*/, const double /*dx_dx*/,
147  std::vector<double>& /*local_M_data*/,
148  std::vector<double>& /*local_K_data*/,
149  std::vector<double>& local_rhs_data,
150  std::vector<double>& local_Jac_data)
151 {
152  assert(local_x.size() ==
153  pressure_size + displacement_size + temperature_size);
154 
155  auto T = Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
156  temperature_size> const>(local_x.data() + temperature_index,
157  temperature_size);
158 
159  auto p = Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
160  pressure_size> const>(local_x.data() + pressure_index, pressure_size);
161 
162  auto u =
163  Eigen::Map<typename ShapeMatricesTypeDisplacement::template VectorType<
164  displacement_size> const>(local_x.data() + displacement_index,
165  displacement_size);
166 
167  auto T_dot =
168  Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
169  temperature_size> const>(local_xdot.data() + temperature_index,
170  temperature_size);
171 
172  auto p_dot =
173  Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
174  pressure_size> const>(local_xdot.data() + pressure_index,
175  pressure_size);
176  auto u_dot =
177  Eigen::Map<typename ShapeMatricesTypeDisplacement::template VectorType<
178  displacement_size> const>(local_xdot.data() + displacement_index,
179  displacement_size);
180 
181  auto local_Jac = MathLib::createZeroedMatrix<
182  typename ShapeMatricesTypeDisplacement::template MatrixType<
183  temperature_size + displacement_size + pressure_size,
184  temperature_size + displacement_size + pressure_size>>(
185  local_Jac_data, displacement_size + pressure_size + temperature_size,
186  displacement_size + pressure_size + temperature_size);
187 
188  auto local_rhs = MathLib::createZeroedVector<
189  typename ShapeMatricesTypeDisplacement::template VectorType<
190  displacement_size + pressure_size + temperature_size>>(
191  local_rhs_data, displacement_size + pressure_size + temperature_size);
192 
194  MTT.setZero(temperature_size, temperature_size);
195 
196  typename ShapeMatricesTypeDisplacement::template MatrixType<
197  temperature_size, displacement_size>
198  MTu;
199  MTu.setZero(temperature_size, displacement_size);
200 
202  KTT.setZero(temperature_size, temperature_size);
203 
205  KTp.setZero(temperature_size, pressure_size);
206 
208  laplace_p.setZero(pressure_size, pressure_size);
209 
211  laplace_T.setZero(pressure_size, temperature_size);
212 
214  storage_p.setZero(pressure_size, pressure_size);
215 
217  storage_T.setZero(pressure_size, temperature_size);
218 
219  typename ShapeMatricesTypeDisplacement::template MatrixType<
220  displacement_size, pressure_size>
221  Kup;
222  Kup.setZero(displacement_size, pressure_size);
223  typename ShapeMatricesTypeDisplacement::template MatrixType<
224  displacement_size, temperature_size>
225  KuT;
226  KuT.setZero(displacement_size, temperature_size);
227 
229  *_process_data.solid_materials[0];
230 
232  x_position.setElementID(_element.getID());
233 
234  auto const& medium = _process_data.media_map->getMedium(_element.getID());
235  auto const& liquid_phase = medium->phase("AqueousLiquid");
236  auto const& solid_phase = medium->phase("Solid");
238 
239  auto const& identity2 = Invariants::identity2;
240 
241  unsigned const n_integration_points =
242  _integration_method.getNumberOfPoints();
243  for (unsigned ip = 0; ip < n_integration_points; ip++)
244  {
245  x_position.setIntegrationPoint(ip);
246  auto const& w = _ip_data[ip].integration_weight;
247 
248  auto const& N_u_op = _ip_data[ip].N_u_op;
249 
250  auto const& N_u = _ip_data[ip].N_u;
251  auto const& dNdx_u = _ip_data[ip].dNdx_u;
252 
253  auto const& N_p = _ip_data[ip].N_p;
254  auto const& dNdx_p = _ip_data[ip].dNdx_p;
255 
256  // same shape function for pressure and temperature since they have the
257  // same order
258  auto const& N_T = N_p;
259  auto const& dNdx_T = dNdx_p;
260  auto const T_int_pt = N_T.dot(T);
261  double const dT_int_pt = N_T.dot(T_dot) * dt;
262 
263  auto const x_coord =
264  NumLib::interpolateXCoordinate<ShapeFunctionDisplacement,
266  _element, N_u);
267  auto const B =
268  LinearBMatrix::computeBMatrix<DisplacementDim,
269  ShapeFunctionDisplacement::NPOINTS,
270  typename BMatricesType::BMatrixType>(
271  dNdx_u, N_u, x_coord, _is_axially_symmetric);
272 
273  auto& eps = _ip_data[ip].eps;
274  eps.noalias() = B * u;
275  auto const& sigma_eff = _ip_data[ip].sigma_eff;
276 
277  vars[static_cast<int>(MaterialPropertyLib::Variable::temperature)] =
278  T_int_pt;
279  double const p_int_pt = N_p.dot(p);
280  vars[static_cast<int>(MaterialPropertyLib::Variable::phase_pressure)] =
281  p_int_pt;
282 
283  vars[static_cast<int>(
285 
286  auto const solid_density =
287  solid_phase.property(MaterialPropertyLib::PropertyType::density)
288  .template value<double>(vars, x_position, t, dt);
289 
290  auto const porosity =
292  .template value<double>(vars, x_position, t, dt);
293  vars[static_cast<int>(MaterialPropertyLib::Variable::porosity)] =
294  porosity;
295 
296  auto const alpha =
297  medium
299  .template value<double>(vars, x_position, t, dt);
300 
301  auto const solid_skeleton_compressibility =
302  1 / solid_material.getBulkModulus(t, x_position);
303 
304  auto const beta_SR = (1 - alpha) * solid_skeleton_compressibility;
305 
306  // Set mechanical variables for the intrinsic permeability model
307  // For stress dependent permeability.
308  {
309  auto const sigma_total =
310  (_ip_data[ip].sigma_eff - alpha * p_int_pt * identity2).eval();
311  vars[static_cast<int>(MaterialPropertyLib::Variable::total_stress)]
312  .emplace<SymmetricTensor>(
314  sigma_total));
315  }
316  // For strain dependent permeability
317  vars[static_cast<int>(
319  Invariants::trace(_ip_data[ip].eps);
320  vars[static_cast<int>(
322  _ip_data[ip].material_state_variables->getEquivalentPlasticStrain();
323 
324  auto const intrinsic_permeability =
325  MaterialPropertyLib::formEigenTensor<DisplacementDim>(
326  medium
328  .value(vars, x_position, t, dt));
329 
330  auto const fluid_density =
331  liquid_phase.property(MaterialPropertyLib::PropertyType::density)
332  .template value<double>(vars, x_position, t, dt);
333 
334  auto const drho_dp =
335  liquid_phase.property(MaterialPropertyLib::PropertyType::density)
336  .template dValue<double>(
338  x_position, t, dt);
339 
340  auto const fluid_compressibility = 1 / fluid_density * drho_dp;
341 
342  double const fluid_volumetric_thermal_expansion_coefficient =
344  liquid_phase, vars, fluid_density, x_position, t, dt);
345 
346  // Use the viscosity model to compute the viscosity
347  auto const viscosity =
348  liquid_phase.property(MaterialPropertyLib::PropertyType::viscosity)
349  .template value<double>(vars, x_position, t, dt);
350  GlobalDimMatrixType K_over_mu = intrinsic_permeability / viscosity;
351 
352  auto const& b = _process_data.specific_body_force;
353 
354  // Consider also anisotropic thermal expansion.
356  DisplacementDim> const solid_linear_thermal_expansion_coefficient =
357  MPL::formKelvinVectorFromThermalExpansivity<DisplacementDim>(
358  solid_phase
359  .property(
361  .value(vars, x_position, t, dt));
362 
364  dthermal_strain =
365  solid_linear_thermal_expansion_coefficient * dT_int_pt;
366 
367  auto const K_pT_thermal_osmosis =
368  (solid_phase.hasProperty(
370  ? MaterialPropertyLib::formEigenTensor<DisplacementDim>(
371  solid_phase
374  .value(vars, x_position, t, dt))
375  : Eigen::MatrixXd::Zero(DisplacementDim, DisplacementDim));
376 
377  auto velocity =
378  (-K_over_mu * dNdx_p * p - K_pT_thermal_osmosis * dNdx_T * T)
379  .eval();
380  velocity += K_over_mu * fluid_density * b;
381 
382  //
383  // displacement equation, displacement part
384  //
385  auto& eps_prev = _ip_data[ip].eps_prev;
386  auto& eps_m = _ip_data[ip].eps_m;
387  auto& eps_m_prev = _ip_data[ip].eps_m_prev;
388  eps_m.noalias() = eps_m_prev + eps - eps_prev - dthermal_strain;
391  eps_m);
392 
393  auto C = _ip_data[ip].updateConstitutiveRelation(
394  vars, t, x_position, dt, T_int_pt - dT_int_pt);
395 
396  local_Jac
397  .template block<displacement_size, displacement_size>(
398  displacement_index, displacement_index)
399  .noalias() += B.transpose() * C * B * w;
400 
401  auto const rho =
402  solid_density * (1 - porosity) + porosity * fluid_density;
403  local_rhs.template segment<displacement_size>(displacement_index)
404  .noalias() -=
405  (B.transpose() * sigma_eff - N_u_op.transpose() * rho * b) * w;
406 
407  //
408  // displacement equation, pressure part (K_up)
409  //
410 
411  Kup.noalias() += B.transpose() * alpha * identity2 * N_p * w;
412 
413  //
414  // pressure equation, pressure part (K_pp and M_pp).
415  //
416  laplace_p.noalias() += dNdx_p.transpose() * K_over_mu * dNdx_p * w;
417 
418  storage_p.noalias() +=
419  N_p.transpose() *
420  (porosity * fluid_compressibility + (alpha - porosity) * beta_SR) *
421  N_p * w;
422 
423  laplace_T.noalias() +=
424  dNdx_p.transpose() * K_pT_thermal_osmosis * dNdx_T * w;
425  //
426  // RHS, pressure part
427  //
428  local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
429  dNdx_p.transpose() * fluid_density * K_over_mu * b * w;
430  //
431  // pressure equation, temperature part (M_pT)
432  //
433  auto const beta =
434  porosity * fluid_volumetric_thermal_expansion_coefficient +
435  (alpha - porosity) *
436  Invariants::trace(solid_linear_thermal_expansion_coefficient);
437  storage_T.noalias() += N_T.transpose() * beta * N_T * w;
438 
439  //
440  // pressure equation, displacement part.
441  //
442  // Reusing Kup.transpose().
443 
444  //
445  // temperature equation, temperature part.
446  //
447  const double c_f =
448  liquid_phase
449  .property(
451  .template value<double>(vars, x_position, t, dt);
452  auto const effective_thermal_conductivity =
453  MaterialPropertyLib::formEigenTensor<DisplacementDim>(
454  medium
455  ->property(
457  .value(vars, x_position, t, dt));
458 
459  KTT.noalias() +=
460  (dNdx_T.transpose() * effective_thermal_conductivity * dNdx_T +
461  N_T.transpose() * velocity.transpose() * dNdx_T * fluid_density *
462  c_f) *
463  w -
464  fluid_density * c_f * N_T.transpose() * (dNdx_T * T).transpose() *
465  K_pT_thermal_osmosis * dNdx_T * w;
466 
467  auto const effective_volumetric_heat_capacity =
468  porosity * fluid_density * c_f +
469  (1.0 - porosity) * solid_density *
470  solid_phase
473  .template value<double>(vars, x_position, t, dt);
474 
475  MTT.noalias() +=
476  N_T.transpose() * effective_volumetric_heat_capacity * N_T * w;
477 
478  //
479  // temperature equation, pressure part
480  //
481  KTp.noalias() +=
482  fluid_density * c_f * N_T.transpose() * (dNdx_T * T).transpose() *
483  K_over_mu * dNdx_p * w -
484  dNdx_T.transpose() * T_int_pt * K_pT_thermal_osmosis * dNdx_p * w;
485 
486  // Add heat sink on MTu, KTT, KTp and fw when fluid_compressibility != 0
487  if (fluid_compressibility != 0)
488  {
489  local_rhs.template segment<temperature_size>(temperature_index)
490  .noalias() +=
491  dNdx_T.transpose() *
492  (-T_int_pt * fluid_volumetric_thermal_expansion_coefficient /
493  fluid_compressibility) *
494  fluid_density * K_over_mu * b * w;
495 
496  MTu.noalias() +=
497  (-T_int_pt *
498  Invariants::trace(solid_linear_thermal_expansion_coefficient) /
499  solid_skeleton_compressibility) *
500  N_T.transpose() * identity2.transpose() * B * w;
501 
502  KTT.noalias() +=
503  dNdx_T.transpose() *
504  (-T_int_pt * fluid_volumetric_thermal_expansion_coefficient *
505  K_pT_thermal_osmosis / fluid_compressibility) *
506  dNdx_T * w;
507 
508  KTp.noalias() +=
509  dNdx_T.transpose() *
510  (T_int_pt * fluid_volumetric_thermal_expansion_coefficient *
511  K_over_mu / fluid_compressibility) *
512  dNdx_p * w;
513  }
514  }
515  // temperature equation, temperature part
516  local_Jac
517  .template block<temperature_size, temperature_size>(temperature_index,
518  temperature_index)
519  .noalias() += KTT + MTT / dt;
520 
521  // temperature equation, pressure part
522  local_Jac
523  .template block<temperature_size, pressure_size>(temperature_index,
524  pressure_index)
525  .noalias() -= KTp;
526 
527  // temperature equation,displacement part
528  local_Jac
529  .template block<temperature_size, displacement_size>(temperature_index,
530  displacement_index)
531  .noalias() += MTu / dt;
532 
533  // displacement equation, temperature part
534  local_Jac
535  .template block<displacement_size, temperature_size>(displacement_index,
536  temperature_index)
537  .noalias() -= KuT;
538 
539  // displacement equation, pressure part
540  local_Jac
541  .template block<displacement_size, pressure_size>(displacement_index,
542  pressure_index)
543  .noalias() -= Kup;
544 
545  // pressure equation, temperature part.
546  local_Jac
547  .template block<pressure_size, temperature_size>(pressure_index,
548  temperature_index)
549  .noalias() -= storage_T / dt - laplace_T;
550 
551  // pressure equation, pressure part.
552  local_Jac
553  .template block<pressure_size, pressure_size>(pressure_index,
554  pressure_index)
555  .noalias() += laplace_p + storage_p / dt;
556 
557  // pressure equation, displacement part.
558  local_Jac
559  .template block<pressure_size, displacement_size>(pressure_index,
560  displacement_index)
561  .noalias() += Kup.transpose() / dt;
562 
563  // pressure equation (f_p)
564  local_rhs.template segment<pressure_size>(pressure_index).noalias() -=
565  laplace_p * p + laplace_T * T + storage_p * p_dot - storage_T * T_dot +
566  Kup.transpose() * u_dot;
567 
568  // displacement equation (f_u)
569  local_rhs.template segment<displacement_size>(displacement_index)
570  .noalias() += Kup * p;
571 
572  // temperature equation (f_T)
573  local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
574  KTT * T + MTT * T_dot;
575 }
576 
577 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
578  typename IntegrationMethod, int DisplacementDim>
579 std::vector<double> const& ThermoHydroMechanicsLocalAssembler<
580  ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
581  DisplacementDim>::
582  getIntPtDarcyVelocity(
583  const double t,
584  std::vector<GlobalVector*> const& x,
585  std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
586  std::vector<double>& cache) const
587 {
588  unsigned const n_integration_points =
589  _integration_method.getNumberOfPoints();
590 
591  constexpr int process_id = 0; // monolithic scheme;
592  auto const indices =
593  NumLib::getIndices(_element.getID(), *dof_table[process_id]);
594  assert(!indices.empty());
595  auto const local_x = x[process_id]->get(indices);
596 
597  cache.clear();
598  auto cache_matrix = MathLib::createZeroedMatrix<Eigen::Matrix<
599  double, DisplacementDim, Eigen::Dynamic, Eigen::RowMajor>>(
600  cache, DisplacementDim, n_integration_points);
601 
602  auto p = Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
603  pressure_size> const>(local_x.data() + pressure_index, pressure_size);
604  auto T = Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
605  temperature_size> const>(local_x.data() + temperature_index,
606  temperature_size);
607 
609  x_position.setElementID(_element.getID());
610 
611  auto const& medium = _process_data.media_map->getMedium(_element.getID());
612  auto const& liquid_phase = medium->phase("AqueousLiquid");
613  auto const& solid_phase = medium->phase("Solid");
615 
616  auto const& identity2 = Invariants::identity2;
617 
618  for (unsigned ip = 0; ip < n_integration_points; ip++)
619  {
620  x_position.setIntegrationPoint(ip);
621 
622  auto const& N_p = _ip_data[ip].N_p;
623 
624  vars[static_cast<int>(MaterialPropertyLib::Variable::temperature)] =
625  N_p.dot(T); // N_p = N_T
626  double const p_int_pt = N_p.dot(p);
627  vars[static_cast<int>(MaterialPropertyLib::Variable::phase_pressure)] =
628  p_int_pt;
629 
630  // TODO (naumov) Temporary value not used by current material models.
631  // Need extension of secondary variables interface.
632  double const dt = std::numeric_limits<double>::quiet_NaN();
633  auto const viscosity =
634  liquid_phase.property(MaterialPropertyLib::PropertyType::viscosity)
635  .template value<double>(vars, x_position, t, dt);
636 
637  auto const alpha =
638  medium
640  .template value<double>(vars, x_position, t, dt);
641 
642  // Set mechanical variables for the intrinsic permeability model
643  // For stress dependent permeability.
644  {
645  auto const sigma_total =
646  (_ip_data[ip].sigma_eff - alpha * p_int_pt * identity2).eval();
647  vars[static_cast<int>(MaterialPropertyLib::Variable::total_stress)]
648  .emplace<SymmetricTensor>(
650  sigma_total));
651  }
652  // For strain dependent permeability
653  vars[static_cast<int>(
655  Invariants::trace(_ip_data[ip].eps);
656  vars[static_cast<int>(
658  _ip_data[ip].material_state_variables->getEquivalentPlasticStrain();
659 
660  GlobalDimMatrixType K_over_mu =
661  MaterialPropertyLib::formEigenTensor<DisplacementDim>(
662  medium
664  .value(vars, x_position, t, dt)) /
665  viscosity;
666 
667  auto const fluid_density =
668  liquid_phase.property(MaterialPropertyLib::PropertyType::density)
669  .template value<double>(vars, x_position, t, dt);
670  auto const& b = _process_data.specific_body_force;
671 
672  auto const K_pT_thermal_osmosis =
673  (solid_phase.hasProperty(
675  ? MaterialPropertyLib::formEigenTensor<DisplacementDim>(
676  solid_phase
679  .value(vars, x_position, t, dt))
680  : Eigen::MatrixXd::Zero(DisplacementDim, DisplacementDim));
681 
682  // Compute the velocity and add thermal osmosis effect on velocity
683  auto const& dNdx_p = _ip_data[ip].dNdx_p;
684  cache_matrix.col(ip).noalias() = -K_over_mu * dNdx_p * p -
685  K_pT_thermal_osmosis * dNdx_p * T +
686  K_over_mu * fluid_density * b;
687  }
688 
689  return cache;
690 }
691 
692 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
693  typename IntegrationMethod, int DisplacementDim>
694 void ThermoHydroMechanicsLocalAssembler<ShapeFunctionDisplacement,
695  ShapeFunctionPressure,
696  IntegrationMethod, DisplacementDim>::
697  postNonLinearSolverConcrete(std::vector<double> const& local_x,
698  std::vector<double> const& local_xdot,
699  double const t, double const dt,
700  bool const use_monolithic_scheme,
701  int const /*process_id*/)
702 {
703  const int displacement_offset =
704  use_monolithic_scheme ? displacement_index : 0;
705 
706  auto u =
707  Eigen::Map<typename ShapeMatricesTypeDisplacement::template VectorType<
708  displacement_size> const>(local_x.data() + displacement_offset,
709  displacement_size);
710 
711  auto T = Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
712  temperature_size> const>(local_x.data() + temperature_index,
713  temperature_size);
714  auto p = Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
715  pressure_size> const>(local_x.data() + pressure_index, pressure_size);
716 
717  auto const T_dot =
718  Eigen::Map<typename ShapeMatricesTypePressure::template VectorType<
719  temperature_size> const>(local_xdot.data() + temperature_index,
720  temperature_size);
721 
723  x_position.setElementID(_element.getID());
724  auto const& medium = _process_data.media_map->getMedium(_element.getID());
725  auto const& solid_phase = medium->phase("Solid");
727 
728  int const n_integration_points = _integration_method.getNumberOfPoints();
729  for (int ip = 0; ip < n_integration_points; ip++)
730  {
731  x_position.setIntegrationPoint(ip);
732  auto const& N_u = _ip_data[ip].N_u;
733  auto const& N_T = _ip_data[ip].N_p;
734  auto const& dNdx_u = _ip_data[ip].dNdx_u;
735 
736  auto const x_coord =
737  NumLib::interpolateXCoordinate<ShapeFunctionDisplacement,
739  _element, N_u);
740  auto const B =
741  LinearBMatrix::computeBMatrix<DisplacementDim,
742  ShapeFunctionDisplacement::NPOINTS,
743  typename BMatricesType::BMatrixType>(
744  dNdx_u, N_u, x_coord, _is_axially_symmetric);
745 
746  double const T_int_pt = N_T.dot(T);
747  vars[static_cast<int>(MaterialPropertyLib::Variable::temperature)] =
748  T_int_pt;
749  vars[static_cast<int>(MaterialPropertyLib::Variable::phase_pressure)] =
750  N_T.dot(p); // N_T = N_p
751 
752  // Consider also anisotropic thermal expansion.
754  DisplacementDim> const solid_linear_thermal_expansion_coefficient =
755  MPL::formKelvinVectorFromThermalExpansivity<DisplacementDim>(
756  solid_phase
757  .property(
759  .value(vars, x_position, t, dt));
760 
761  double const dT_int_pt = N_T.dot(T_dot) * dt;
763  dthermal_strain =
764  solid_linear_thermal_expansion_coefficient * dT_int_pt;
765 
766  auto& eps = _ip_data[ip].eps;
767  eps.noalias() = B * u;
768 
769  auto& eps_prev = _ip_data[ip].eps_prev;
770  auto& eps_m = _ip_data[ip].eps_m;
771  auto& eps_m_prev = _ip_data[ip].eps_m_prev;
772  eps_m.noalias() = eps_m_prev + eps - eps_prev - dthermal_strain;
775  eps_m);
776 
777  _ip_data[ip].updateConstitutiveRelation(vars, t, x_position, dt,
778  T_int_pt - dT_int_pt);
779  }
780 }
781 
782 template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
783  typename IntegrationMethod, int DisplacementDim>
784 void ThermoHydroMechanicsLocalAssembler<ShapeFunctionDisplacement,
785  ShapeFunctionPressure,
786  IntegrationMethod, DisplacementDim>::
787  computeSecondaryVariableConcrete(double const /*t*/, double const /*dt*/,
788  Eigen::VectorXd const& local_x,
789  Eigen::VectorXd const& /*local_x_dot*/)
790 {
791  auto const p = local_x.template segment<pressure_size>(pressure_index);
792 
794  ShapeFunctionPressure, typename ShapeFunctionDisplacement::MeshElement,
795  DisplacementDim>(_element, _is_axially_symmetric, p,
796  *_process_data.pressure_interpolated);
797 
798  auto T = local_x.template segment<temperature_size>(temperature_index);
799 
801  ShapeFunctionPressure, typename ShapeFunctionDisplacement::MeshElement,
802  DisplacementDim>(_element, _is_axially_symmetric, T,
803  *_process_data.temperature_interpolated);
804 }
805 } // namespace ThermoHydroMechanics
806 } // namespace ProcessLib
#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 setElementID(std::size_t element_id)
void setIntegrationPoint(unsigned integration_point)
MatrixType< _kelvin_vector_size, _number_of_dof > BMatrixType
Definition: BMatrixPolicy.h:55
typename ShapeMatricesTypePressure::GlobalDimMatrixType GlobalDimMatrixType
ShapeMatrixPolicyType< ShapeFunctionDisplacement, DisplacementDim > ShapeMatricesTypeDisplacement
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
ThermoHydroMechanicsProcessData< DisplacementDim > & _process_data
ShapeMatrixPolicyType< ShapeFunctionPressure, DisplacementDim > ShapeMatricesTypePressure
SecondaryData< typename ShapeMatricesTypeDisplacement::ShapeMatrices::ShapeType > _secondary_data
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)
double getLiquidThermalExpansivity(Phase const &phase, VariableArray const &vars, const double density, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
Definition: VariableType.h:108
Eigen::Matrix< double, 4, 1 > kelvinVectorToSymmetricTensor(Eigen::Matrix< double, 4, 1, Eigen::ColMajor, 4, 1 > const &v)
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Definition: KelvinVector.h:48
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
Definition: EigenMapTools.h:32
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
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< 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 > > 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
double fluid_density(const double p, const double T, const double x)
MatrixType< ShapeFunction::NPOINTS, ShapeFunction::NPOINTS > NodalMatrixType
virtual double getBulkModulus(double const, ParameterLib::SpatialPosition const &, KelvinMatrix const *const =nullptr) const
std::vector< ShapeMatrixType, Eigen::aligned_allocator< ShapeMatrixType > > N_u