67 double const rho_LR_m,
70 double const alpha_B,
double const phi,
double const p_L,
71 double const p_L_m_prev,
73 double const S_L_m_prev,
double const phi_m_prev,
79 static constexpr int kelvin_vector_size =
82 static constexpr int nls_size = 1 + 1 + 1 + kelvin_vector_size;
84 static constexpr int i_phi_m = 0;
85 static constexpr int i_e_sw = 1;
86 static constexpr int i_p_L_m = 2;
87 static constexpr int i_sigma_sw = 3;
89 using ResidualVectorType = Eigen::Matrix<double, nls_size, 1>;
90 using JacobianMatrix =
91 Eigen::Matrix<double, nls_size, nls_size, Eigen::RowMajor>;
93 Eigen::FullPivLU<Eigen::Matrix<double, nls_size, nls_size, Eigen::RowMajor>>
96 JacobianMatrix jacobian;
99 ResidualVectorType solution = ResidualVectorType::Zero();
101 if (p_L >= 0 && p_L_m_prev >= 0)
103 return {solution[i_phi_m], solution[i_e_sw], solution[i_p_L_m],
104 solution.template segment<kelvin_vector_size>(i_sigma_sw)};
107 double const alpha_bar =
110 auto const update_residual = [&](ResidualVectorType& residual)
112 double const delta_phi_m = solution[i_phi_m];
113 double const delta_e_sw = solution[i_e_sw];
114 auto const& delta_sigma_sw =
115 solution.template segment<kelvin_vector_size>(i_sigma_sw);
116 double const delta_p_L_m = solution[i_p_L_m];
118 double const phi_m = phi_m_prev + delta_phi_m;
119 double const p_L_m = p_L_m_prev + delta_p_L_m;
128 saturation_micro.template value<double>(variables, pos, t, dt);
130 double const delta_S_L_m = S_L_m - S_L_m_prev;
132 auto const sigma_sw_dot =
134 swelling_stress_rate.template value<Eigen::Matrix3d>(
135 variables, variables_prev, pos, t, dt));
137 residual[i_phi_m] = delta_phi_m - (alpha_B - phi) * delta_e_sw;
138 residual[i_e_sw] = delta_e_sw + I_2_C_el_inverse.dot(delta_sigma_sw);
139 residual.template segment<kelvin_vector_size>(i_sigma_sw).noalias() =
140 delta_sigma_sw - sigma_sw_dot * dt;
144 (phi_m * delta_S_L_m - (alpha_B - phi) * S_L_m * delta_e_sw) +
145 phi_m * S_L_m * rho_LR_m * delta_e_sw -
150 auto const update_jacobian = [&](JacobianMatrix& jacobian)
152 jacobian = JacobianMatrix::Identity();
154 double const delta_phi_m = solution[i_phi_m];
155 double const delta_e_sw = solution[i_e_sw];
156 double const delta_p_L_m = solution[i_p_L_m];
158 double const phi_m = phi_m_prev + delta_phi_m;
159 double const p_L_m = p_L_m_prev + delta_p_L_m;
166 saturation_micro.template value<double>(variables, pos, t, dt);
169 double const delta_S_L_m = S_L_m - S_L_m_prev;
171 double const dS_L_m_dp_cap_m = saturation_micro.template dValue<double>(
172 variables, MPL::Variable::capillary_pressure, pos, t, dt);
173 auto const dsigma_sw_dS_L_m =
175 swelling_stress_rate.template dValue<Eigen::Matrix3d>(
176 variables, variables_prev, MPL::Variable::liquid_saturation,
179 jacobian(i_phi_m, i_e_sw) = -(alpha_B - phi);
181 jacobian.template block<1, kelvin_vector_size>(i_e_sw, i_sigma_sw) =
182 I_2_C_el_inverse.transpose();
184 jacobian.template block<kelvin_vector_size, 1>(i_sigma_sw, i_p_L_m) =
185 -dsigma_sw_dS_L_m * dS_L_m_dp_cap_m;
187 jacobian(i_p_L_m, i_phi_m) =
188 rho_LR_m * (delta_S_L_m + S_L_m * delta_e_sw);
190 jacobian(i_p_L_m, i_e_sw) = -rho_LR_m * S_L_m * (alpha_B - phi - phi_m);
192 jacobian(i_p_L_m, i_p_L_m) =
193 alpha_bar / mu_LR * dt -
194 rho_LR_m * (phi_m - (alpha_B - phi - phi_m) * delta_e_sw) *
198 auto const update_solution = [&](ResidualVectorType
const& increment)
199 { solution += increment; };
202 linear_solver, update_jacobian, update_residual, update_solution,
205 auto const success_iterations = newton_solver.solve(jacobian);
207 if (!success_iterations)
210 "Could not find solution for local double structure nonlinear "
214 return {solution[i_phi_m], solution[i_e_sw], solution[i_p_L_m],
215 solution.template segment<kelvin_vector_size>(i_sigma_sw)};