OGS
ComputeMicroPorosity.h
Go to the documentation of this file.
1 
10 #pragma once
11 
12 #include <cassert>
13 #include <ostream>
14 
15 #include "MaterialLib/MPL/Medium.h"
17 #include "MathLib/KelvinVector.h"
18 #include "NumLib/NewtonRaphson.h"
19 
21 {
22 template <int DisplacementDim>
24 {
25  double phi_m;
26  double e_sw;
27  double p_L_m;
29 
31  {
32  phi_m += state.phi_m;
33  e_sw += state.e_sw;
34  p_L_m += state.p_L_m;
35  sigma_sw += state.sigma_sw;
36  return *this;
37  }
38 
40 };
41 
42 template <int DisplacementDim>
43 std::ostream& operator<<(std::ostream& os,
45 {
46  return os << "phi_m: " << state.phi_m << ", "
47  << "e_sw: " << state.e_sw << ", "
48  << "p_L_m: " << state.p_L_m << ", "
49  << "sigma_sw: " << state.sigma_sw.transpose();
50 }
51 
53 {
55 
60 };
61 
62 template <int DisplacementDim>
65  I_2_C_el_inverse,
66  double const rho_LR_m, // for simplification equal to rho_LR_M
67  double const mu_LR,
68  MicroPorosityParameters const& micro_porosity_parameters,
69  double const alpha_B, double const phi, double const p_L,
70  double const p_L_m_prev,
71  MaterialPropertyLib::VariableArray const& /*variables_prev*/,
72  double const S_L_m_prev, double const phi_m_prev,
73  ParameterLib::SpatialPosition const pos, double const t, double const dt,
76 {
77  namespace MPL = MaterialPropertyLib;
78  static constexpr int kelvin_vector_size =
80  // phi_m, e_sw, p_L_m, sigma_sw
81  static constexpr int nls_size = 1 + 1 + 1 + kelvin_vector_size;
82 
83  static constexpr int i_phi_m = 0;
84  static constexpr int i_e_sw = 1;
85  static constexpr int i_p_L_m = 2;
86  static constexpr int i_sigma_sw = 3;
87 
88  using ResidualVectorType = Eigen::Matrix<double, nls_size, 1>;
89  using JacobianMatrix =
90  Eigen::Matrix<double, nls_size, nls_size, Eigen::RowMajor>;
91 
92  Eigen::FullPivLU<Eigen::Matrix<double, nls_size, nls_size, Eigen::RowMajor>>
93  linear_solver;
94 
95  JacobianMatrix jacobian;
96 
97  // Agglomerated solution vector construction.
98  ResidualVectorType solution = ResidualVectorType::Zero();
99 
100  if (p_L >= 0 && p_L_m_prev >= 0)
101  {
102  return {solution[i_phi_m], solution[i_e_sw], solution[i_p_L_m],
103  solution.template segment<kelvin_vector_size>(i_sigma_sw)};
104  }
105 
106  double const alpha_bar =
107  micro_porosity_parameters.mass_exchange_coefficient;
108 
109  auto const update_residual = [&](ResidualVectorType& residual)
110  {
111  double const delta_phi_m = solution[i_phi_m];
112  double const delta_e_sw = solution[i_e_sw];
113  auto const& delta_sigma_sw =
114  solution.template segment<kelvin_vector_size>(i_sigma_sw);
115  double const delta_p_L_m = solution[i_p_L_m];
116 
117  double const phi_m = phi_m_prev + delta_phi_m;
118  double const p_L_m = p_L_m_prev + delta_p_L_m;
119  MPL::VariableArray variables_prev;
120  variables_prev[static_cast<int>(MPL::Variable::capillary_pressure)] =
121  -p_L_m_prev;
122  variables_prev[static_cast<int>(MPL::Variable::liquid_saturation)] =
123  S_L_m_prev;
124 
125  MPL::VariableArray variables;
126  variables[static_cast<int>(MPL::Variable::capillary_pressure)] = -p_L_m;
127 
128  double const S_L_m =
129  saturation_micro.template value<double>(variables, pos, t, dt);
130  variables[static_cast<int>(MPL::Variable::liquid_saturation)] = S_L_m;
131  double const delta_S_L_m = S_L_m - S_L_m_prev;
132 
133  auto const sigma_sw_dot =
134  MathLib::KelvinVector::tensorToKelvin<DisplacementDim>(
135  swelling_stress_rate.template value<Eigen::Matrix3d>(
136  variables, variables_prev, pos, t, dt));
137 
138  residual[i_phi_m] = delta_phi_m - (alpha_B - phi) * delta_e_sw;
139  residual[i_e_sw] = delta_e_sw + I_2_C_el_inverse.dot(delta_sigma_sw);
140  residual.template segment<kelvin_vector_size>(i_sigma_sw).noalias() =
141  delta_sigma_sw - sigma_sw_dot * dt;
142 
143  residual[i_p_L_m] =
144  rho_LR_m *
145  (phi_m * delta_S_L_m - (alpha_B - phi) * S_L_m * delta_e_sw) +
146  phi_m * S_L_m * rho_LR_m * delta_e_sw -
147  micro_porosity_parameters.mass_exchange_coefficient / mu_LR *
148  (p_L - p_L_m) * dt;
149  };
150 
151  auto const update_jacobian = [&](JacobianMatrix& jacobian)
152  {
153  jacobian = JacobianMatrix::Identity();
154 
155  double const delta_phi_m = solution[i_phi_m];
156  double const delta_e_sw = solution[i_e_sw];
157  double const delta_p_L_m = solution[i_p_L_m];
158 
159  double const phi_m = phi_m_prev + delta_phi_m;
160  double const p_L_m = p_L_m_prev + delta_p_L_m;
161  MPL::VariableArray variables_prev;
162  variables_prev[static_cast<int>(MPL::Variable::capillary_pressure)] =
163  -p_L_m_prev;
164  MPL::VariableArray variables;
165  variables[static_cast<int>(MPL::Variable::capillary_pressure)] = -p_L_m;
166 
167  double const S_L_m =
168  saturation_micro.template value<double>(variables, pos, t, dt);
169  variables_prev[static_cast<int>(MPL::Variable::liquid_saturation)] =
170  S_L_m_prev;
171  variables[static_cast<int>(MPL::Variable::liquid_saturation)] = S_L_m;
172  double const delta_S_L_m = S_L_m - S_L_m_prev;
173 
174  double const dS_L_m_dp_cap_m = saturation_micro.template dValue<double>(
175  variables, MPL::Variable::capillary_pressure, pos, t, dt);
176  auto const dsigma_sw_dS_L_m =
177  MathLib::KelvinVector::tensorToKelvin<DisplacementDim>(
178  swelling_stress_rate.template dValue<Eigen::Matrix3d>(
179  variables, variables_prev, MPL::Variable::liquid_saturation,
180  pos, t, dt));
181 
182  jacobian(i_phi_m, i_e_sw) = -(alpha_B - phi);
183 
184  jacobian.template block<1, kelvin_vector_size>(i_e_sw, i_sigma_sw) =
185  I_2_C_el_inverse.transpose();
186 
187  jacobian.template block<kelvin_vector_size, 1>(i_sigma_sw, i_p_L_m) =
188  -dsigma_sw_dS_L_m * dS_L_m_dp_cap_m;
189 
190  jacobian(i_p_L_m, i_phi_m) =
191  rho_LR_m * (delta_S_L_m + S_L_m * delta_e_sw);
192 
193  jacobian(i_p_L_m, i_e_sw) = -rho_LR_m * S_L_m * (alpha_B - phi - phi_m);
194 
195  jacobian(i_p_L_m, i_p_L_m) =
196  alpha_bar / mu_LR * dt -
197  rho_LR_m * (phi_m - (alpha_B - phi - phi_m) * delta_e_sw) *
198  dS_L_m_dp_cap_m;
199  };
200 
201  auto const update_solution = [&](ResidualVectorType const& increment)
202  { solution += increment; };
203 
204  auto newton_solver =
205  NumLib::NewtonRaphson<decltype(linear_solver), JacobianMatrix,
206  decltype(update_jacobian), ResidualVectorType,
207  decltype(update_residual),
208  decltype(update_solution)>(
209  linear_solver, update_jacobian, update_residual, update_solution,
210  micro_porosity_parameters.nonlinear_solver_parameters);
211 
212  auto const success_iterations = newton_solver.solve(jacobian);
213 
214  if (!success_iterations)
215  {
216  OGS_FATAL(
217  "Could not find solution for local double structure nonlinear "
218  "problem.");
219  }
220 
221  return {solution[i_phi_m], solution[i_e_sw], solution[i_p_L_m],
222  solution.template segment<kelvin_vector_size>(i_sigma_sw)};
223 }
224 } // namespace ProcessLib::RichardsMechanics
#define OGS_FATAL(...)
Definition: Error.h:26
std::optional< int > solve(JacobianMatrix &jacobian) const
Definition: NewtonRaphson.h:56
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
Definition: VariableType.h:108
@ saturation_micro
capillary pressure saturation relationship for microstructure.
Definition: PropertyType.h:84
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Definition: KelvinVector.h:48
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
Definition: KelvinVector.h:23
MicroPorosityStateSpace< DisplacementDim > computeMicroPorosity(MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &I_2_C_el_inverse, double const rho_LR_m, double const mu_LR, MicroPorosityParameters const &micro_porosity_parameters, double const alpha_B, double const phi, double const p_L, double const p_L_m_prev, MaterialPropertyLib::VariableArray const &, double const S_L_m_prev, double const phi_m_prev, ParameterLib::SpatialPosition const pos, double const t, double const dt, MaterialPropertyLib::Property const &saturation_micro, MaterialPropertyLib::Property const &swelling_stress_rate)
std::ostream & operator<<(std::ostream &os, MicroPorosityStateSpace< DisplacementDim > const &state)
NumLib::NewtonRaphsonSolverParameters nonlinear_solver_parameters
MicroPorosityStateSpace & operator+=(MicroPorosityStateSpace const &state)
MathLib::KelvinVector::KelvinVectorType< DisplacementDim > sigma_sw