OGS
ComputeMicroPorosity.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
6#include <Eigen/LU>
7#include <cassert>
8#include <iosfwd>
9
14
16{
17template <int DisplacementDim>
36
37template <int DisplacementDim>
38std::ostream& operator<<(std::ostream& os,
40{
41 return os << "phi_m: " << state.phi_m << ", "
42 << "e_sw: " << state.e_sw << ", "
43 << "p_L_m: " << state.p_L_m << ", "
44 << "sigma_sw: " << state.sigma_sw.transpose();
45}
46
56
57template <int DisplacementDim>
60 I_2_C_el_inverse,
61 double const rho_LR_m, // for simplification equal to rho_LR_M
62 double const mu_LR,
63 MicroPorosityParameters const& micro_porosity_parameters,
64 double const alpha_B, double const phi, double const p_L,
65 double const p_L_m_prev,
66 MaterialPropertyLib::VariableArray const& /*variables_prev*/,
67 double const S_L_m_prev, double const phi_m_prev,
68 ParameterLib::SpatialPosition const pos, double const t, double const dt,
69 MaterialPropertyLib::Property const& saturation_micro,
70 MaterialPropertyLib::Property const& swelling_stress_rate)
71{
72 namespace MPL = MaterialPropertyLib;
73 static constexpr int kelvin_vector_size =
75 // phi_m, e_sw, p_L_m, sigma_sw
76 static constexpr int nls_size = 1 + 1 + 1 + kelvin_vector_size;
77
78 static constexpr int i_phi_m = 0;
79 static constexpr int i_e_sw = 1;
80 static constexpr int i_p_L_m = 2;
81 static constexpr int i_sigma_sw = 3;
82
83 using ResidualVectorType = Eigen::Matrix<double, nls_size, 1>;
84 using JacobianMatrix =
85 Eigen::Matrix<double, nls_size, nls_size, Eigen::RowMajor>;
86
87 Eigen::FullPivLU<Eigen::Matrix<double, nls_size, nls_size, Eigen::RowMajor>>
88 linear_solver;
89
90 JacobianMatrix jacobian;
91
92 // Agglomerated solution vector construction.
93 ResidualVectorType solution = ResidualVectorType::Zero();
94
95 if (p_L >= 0 && p_L_m_prev >= 0)
96 {
97 return {solution[i_phi_m], solution[i_e_sw], solution[i_p_L_m],
98 solution.template segment<kelvin_vector_size>(i_sigma_sw)};
99 }
100
101 double const alpha_bar =
102 micro_porosity_parameters.mass_exchange_coefficient;
103
104 auto const update_residual = [&](ResidualVectorType& residual)
105 {
106 double const delta_phi_m = solution[i_phi_m];
107 double const delta_e_sw = solution[i_e_sw];
108 auto const& delta_sigma_sw =
109 solution.template segment<kelvin_vector_size>(i_sigma_sw);
110 double const delta_p_L_m = solution[i_p_L_m];
111
112 double const phi_m = phi_m_prev + delta_phi_m;
113 double const p_L_m = p_L_m_prev + delta_p_L_m;
114 MPL::VariableArray variables_prev;
115 variables_prev.capillary_pressure = -p_L_m_prev;
116 variables_prev.liquid_saturation = S_L_m_prev;
117
118 MPL::VariableArray variables;
119 variables.capillary_pressure = -p_L_m;
120
121 double const S_L_m =
122 saturation_micro.template value<double>(variables, pos, t, dt);
123 variables.liquid_saturation = S_L_m;
124 double const delta_S_L_m = S_L_m - S_L_m_prev;
125
126 auto const sigma_sw_dot =
128 swelling_stress_rate.template value<Eigen::Matrix3d>(
129 variables, variables_prev, pos, t, dt));
130
131 residual[i_phi_m] = delta_phi_m - (alpha_B - phi) * delta_e_sw;
132 residual[i_e_sw] = delta_e_sw + I_2_C_el_inverse.dot(delta_sigma_sw);
133 residual.template segment<kelvin_vector_size>(i_sigma_sw).noalias() =
134 delta_sigma_sw - sigma_sw_dot * dt;
135
136 residual[i_p_L_m] =
137 rho_LR_m *
138 (phi_m * delta_S_L_m - (alpha_B - phi) * S_L_m * delta_e_sw) +
139 phi_m * S_L_m * rho_LR_m * delta_e_sw -
140 micro_porosity_parameters.mass_exchange_coefficient / mu_LR *
141 (p_L - p_L_m) * dt;
142 };
143
144 auto const update_jacobian = [&](JacobianMatrix& jacobian)
145 {
146 jacobian = JacobianMatrix::Identity();
147
148 double const delta_phi_m = solution[i_phi_m];
149 double const delta_e_sw = solution[i_e_sw];
150 double const delta_p_L_m = solution[i_p_L_m];
151
152 double const phi_m = phi_m_prev + delta_phi_m;
153 double const p_L_m = p_L_m_prev + delta_p_L_m;
154 MPL::VariableArray variables_prev;
155 variables_prev.capillary_pressure = -p_L_m_prev;
156 MPL::VariableArray variables;
157 variables.capillary_pressure = -p_L_m;
158
159 double const S_L_m =
160 saturation_micro.template value<double>(variables, pos, t, dt);
161 variables_prev.liquid_saturation = S_L_m_prev;
162 variables.liquid_saturation = S_L_m;
163 double const delta_S_L_m = S_L_m - S_L_m_prev;
164
165 double const dS_L_m_dp_cap_m = saturation_micro.template dValue<double>(
166 variables, MPL::Variable::capillary_pressure, pos, t, dt);
167 auto const dsigma_sw_dS_L_m =
169 swelling_stress_rate.template dValue<Eigen::Matrix3d>(
170 variables, variables_prev, MPL::Variable::liquid_saturation,
171 pos, t, dt));
172
173 jacobian(i_phi_m, i_e_sw) = -(alpha_B - phi);
174
175 jacobian.template block<1, kelvin_vector_size>(i_e_sw, i_sigma_sw) =
176 I_2_C_el_inverse.transpose();
177
178 jacobian.template block<kelvin_vector_size, 1>(i_sigma_sw, i_p_L_m) =
179 -dsigma_sw_dS_L_m * dS_L_m_dp_cap_m;
180
181 jacobian(i_p_L_m, i_phi_m) =
182 rho_LR_m * (delta_S_L_m + S_L_m * delta_e_sw);
183
184 jacobian(i_p_L_m, i_e_sw) = -rho_LR_m * S_L_m * (alpha_B - phi - phi_m);
185
186 jacobian(i_p_L_m, i_p_L_m) =
187 alpha_bar / mu_LR * dt -
188 rho_LR_m * (phi_m - (alpha_B - phi - phi_m) * delta_e_sw) *
189 dS_L_m_dp_cap_m;
190 };
191
192 auto const update_solution = [&](ResidualVectorType const& increment)
193 { solution += increment; };
194
195 auto newton_solver = NumLib::NewtonRaphson(
196 linear_solver, update_jacobian, update_residual, update_solution,
197 micro_porosity_parameters.nonlinear_solver_parameters);
198
199 auto const success_iterations = newton_solver.solve(jacobian);
200
201 if (!success_iterations)
202 {
203 OGS_FATAL(
204 "Could not find solution for local double structure nonlinear "
205 "problem.");
206 }
207
208 return {solution[i_phi_m], solution[i_e_sw], solution[i_p_L_m],
209 solution.template segment<kelvin_vector_size>(i_sigma_sw)};
210}
211} // namespace ProcessLib::RichardsMechanics
#define OGS_FATAL(...)
Definition Error.h:19
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
KelvinVectorType< DisplacementDim > tensorToKelvin(Eigen::Matrix< double, 3, 3 > const &m)
std::ostream & operator<<(std::ostream &os, MicroPorosityStateSpace< DisplacementDim > const &state)
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)
NumLib::NewtonRaphsonSolverParameters nonlinear_solver_parameters
MicroPorosityStateSpace & operator+=(MicroPorosityStateSpace const &state)
MathLib::KelvinVector::KelvinVectorType< DisplacementDim > sigma_sw