61 double const rho_LR_m,
64 double const alpha_B,
double const phi,
double const p_L,
65 double const p_L_m_prev,
67 double const S_L_m_prev,
double const phi_m_prev,
73 static constexpr int kelvin_vector_size =
76 static constexpr int nls_size = 1 + 1 + 1 + kelvin_vector_size;
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;
83 using ResidualVectorType = Eigen::Matrix<double, nls_size, 1>;
84 using JacobianMatrix =
85 Eigen::Matrix<double, nls_size, nls_size, Eigen::RowMajor>;
87 Eigen::FullPivLU<Eigen::Matrix<double, nls_size, nls_size, Eigen::RowMajor>>
90 JacobianMatrix jacobian;
93 ResidualVectorType solution = ResidualVectorType::Zero();
95 if (p_L >= 0 && p_L_m_prev >= 0)
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)};
101 double const alpha_bar =
104 auto const update_residual = [&](ResidualVectorType& residual)
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];
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;
122 saturation_micro.template value<double>(variables, pos, t, dt);
124 double const delta_S_L_m = S_L_m - S_L_m_prev;
126 auto const sigma_sw_dot =
128 swelling_stress_rate.template value<Eigen::Matrix3d>(
129 variables, variables_prev, pos, t, dt));
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;
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 -
144 auto const update_jacobian = [&](JacobianMatrix& jacobian)
146 jacobian = JacobianMatrix::Identity();
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];
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;
160 saturation_micro.template value<double>(variables, pos, t, dt);
163 double const delta_S_L_m = S_L_m - S_L_m_prev;
165 double const dS_L_m_dp_cap_m = saturation_micro.template dValue<double>(
167 auto const dsigma_sw_dS_L_m =
169 swelling_stress_rate.template dValue<Eigen::Matrix3d>(
173 jacobian(i_phi_m, i_e_sw) = -(alpha_B - phi);
175 jacobian.template block<1, kelvin_vector_size>(i_e_sw, i_sigma_sw) =
176 I_2_C_el_inverse.transpose();
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;
181 jacobian(i_p_L_m, i_phi_m) =
182 rho_LR_m * (delta_S_L_m + S_L_m * delta_e_sw);
184 jacobian(i_p_L_m, i_e_sw) = -rho_LR_m * S_L_m * (alpha_B - phi - phi_m);
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) *
192 auto const update_solution = [&](ResidualVectorType
const& increment)
193 { solution += increment; };
196 linear_solver, update_jacobian, update_residual, update_solution,
199 auto const success_iterations = newton_solver.solve(jacobian);
201 if (!success_iterations)
204 "Could not find solution for local double structure nonlinear "
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)};