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
189 linear_solver, update_jacobian, update_residual, update_solution,
191
192 auto const success_iterations = newton_solver.solve(jacobian);
193
194 if (!success_iterations)
195 {
197 "FractureModel/Coulomb local nonlinear solver didn't "
198 "converge.");
199 }
200
201
202
203 }
204
205 {
206 double const Fs = yield_function(sigma);
207 material_state_variables.setShearYieldFunctionValue(Fs);
208 }
209
210 Ke(index_ns, index_ns) *=
212 Eigen::RowVectorXd const A = yield_function_derivative(sigma).transpose() *
213 Ke /
214 (yield_function_derivative(sigma).transpose() *
215 Ke * plastic_potential_derivative(sigma));
216 Kep = Ke - Ke * plastic_potential_derivative(sigma) * A;
217}
double logPenaltyDerivative(double const aperture0, double const aperture, double const aperture_cutoff)