Computation of the constitutive relation for the Mohr-Coulomb model.
68{
69 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
70 &material_state_variables) != nullptr);
71
72 StateVariables<DisplacementDim>& state =
73 static_cast<StateVariables<DisplacementDim>&>(material_state_variables);
74
75 MaterialPropertyValues
const mat(
_mp, t, x);
76
77 const int index_ns = DisplacementDim - 1;
78 double const aperture = w[index_ns] + aperture0;
79
80 Eigen::MatrixXd Ke;
81 {
82 Ke = Eigen::MatrixXd::Zero(DisplacementDim, DisplacementDim);
83 for (int i = 0; i < index_ns; i++)
84 {
85 Ke(i, i) = mat.Ks;
86 }
87
88 Ke(index_ns, index_ns) = mat.Kn;
89 }
90
91
92
93
94
95 {
96 sigma.noalias() = Ke * (w - w_prev);
97
98 sigma.coeffRef(index_ns) *=
100 sigma.noalias() += sigma_prev;
101 }
102
103
105 {
106 Kep.setZero();
107 sigma.setZero();
108 state.w_p = w;
109 material_state_variables.setTensileStress(true);
110 return;
111 }
112
113 auto yield_function = [&mat](Eigen::VectorXd const& s)
114 {
115 double const sigma_n = s[DisplacementDim - 1];
116 Eigen::VectorXd const sigma_s = s.head(DisplacementDim - 1);
117 double const mag_tau = sigma_s.norm();
118 return mag_tau + sigma_n * std::tan(mat.phi) - mat.c;
119 };
120
121 {
122 double const Fs = yield_function(sigma);
123 material_state_variables.setShearYieldFunctionValue(Fs);
124 if (Fs < .0)
125 {
126 Kep = Ke;
129 return;
130 }
131 }
132
133 auto yield_function_derivative = [&mat](Eigen::VectorXd const& s)
134 {
135 Eigen::Matrix<double, DisplacementDim, 1> dFs_dS;
136 dFs_dS.template head<DisplacementDim - 1>().noalias() =
137 s.template head<DisplacementDim - 1>().normalized();
138 dFs_dS.coeffRef(DisplacementDim - 1) = std::tan(mat.phi);
139 return dFs_dS;
140 };
141
142
143 auto plastic_potential_derivative = [&mat](Eigen::VectorXd const& s)
144 {
145 Eigen::Matrix<double, DisplacementDim, 1> dQs_dS;
146 dQs_dS.template head<DisplacementDim - 1>().noalias() =
147 s.template head<DisplacementDim - 1>().normalized();
148 dQs_dS.coeffRef(DisplacementDim - 1) = std::tan(mat.psi);
149 return dQs_dS;
150 };
151
152 {
153
154 Eigen::FullPivLU<Eigen::Matrix<double, 1, 1, Eigen::RowMajor>>
155 linear_solver;
156 using ResidualVectorType = Eigen::Matrix<double, 1, 1, Eigen::RowMajor>;
157 using JacobianMatrix = Eigen::Matrix<double, 1, 1, Eigen::RowMajor>;
158
159 JacobianMatrix jacobian;
160 ResidualVectorType solution;
161 solution << 0;
162
163 auto const update_residual = [&](ResidualVectorType& residual)
164 { residual[0] = yield_function(sigma); };
165
166 auto const update_jacobian = [&](JacobianMatrix& jacobian)
167 {
168 jacobian(0, 0) = -yield_function_derivative(sigma).transpose() *
169 Ke * plastic_potential_derivative(sigma);
170 };
171
172 auto const update_solution = [&](ResidualVectorType const& increment)
173 {
174 solution += increment;
175
176
177
178 state.w_p = state.w_p_prev +
179 solution[0] * plastic_potential_derivative(sigma);
180
181 sigma.noalias() = Ke * (w - w_prev - state.w_p + state.w_p_prev);
182
185 sigma.noalias() += sigma_prev;
186 };
187
188 auto newton_solver =
190 decltype(update_jacobian), ResidualVectorType,
191 decltype(update_residual),
192 decltype(update_solution)>(
193 linear_solver, update_jacobian, update_residual,
195
196 auto const success_iterations = newton_solver.
solve(jacobian);
197
198 if (!success_iterations)
199 {
201 "FractureModel/Coulomb local nonlinear solver didn't "
202 "converge.");
203 }
204
205
206
207 }
208
209 {
210 double const Fs = yield_function(sigma);
211 material_state_variables.setShearYieldFunctionValue(Fs);
212 }
213
214 Ke(index_ns, index_ns) *=
216 Eigen::RowVectorXd const A = yield_function_derivative(sigma).transpose() *
217 Ke /
218 (yield_function_derivative(sigma).transpose() *
219 Ke * plastic_potential_derivative(sigma));
220 Kep = Ke - Ke * plastic_potential_derivative(sigma) * A;
221}
std::optional< int > solve(JacobianMatrix &jacobian) const
double logPenaltyDerivative(double const aperture0, double const aperture, double const aperture_cutoff)