13 template <
class T,
int p = 3>
16 constexpr static double C = 1e2;
19 static_assert(p % 2 == 1);
20 static T value(T J,
double JBarrierThreshold)
22 if (J >= JBarrierThreshold)
24 const T tmp1 = J / JBarrierThreshold - 1;
25 const T tmp2 = pow(tmp1, p);
26 return C * (1 / (tmp2 + 1) - 1);
29 static T first_derivatives(T J,
double JBarrierThreshold)
31 if (J >= JBarrierThreshold)
33 const T tmp1 = J / JBarrierThreshold - 1;
34 const T tmp2 = pow(tmp1, p);
35 return C * (-1 / JBarrierThreshold) * p * tmp2 / tmp1 / pow(1 + tmp2, 2);
38 static T second_derivatives(T J,
double JBarrierThreshold)
40 if (J >= JBarrierThreshold)
42 const T tmp1 = J / JBarrierThreshold - 1;
43 const T tmp2 = pow(tmp1, p);
44 return C * (1 / (JBarrierThreshold * JBarrierThreshold)) * p * tmp2 / pow(tmp1, 2) * ((1 - p) + (1 + p) * tmp2) / pow(1 + tmp2, 3);
49 void jacobian_cofactor_derivatives(
const Eigen::MatrixXd &def_grad,
const int dim,
50 Eigen::MatrixXd &delJ_delF, Eigen::MatrixXd &del2J_delF2)
52 delJ_delF.setZero(dim, dim);
53 del2J_delF2.setZero(dim * dim, dim * dim);
62 del2J_delF2(0, 3) = 1;
63 del2J_delF2(1, 2) = -1;
64 del2J_delF2(2, 1) = -1;
65 del2J_delF2(3, 0) = 1;
70 delJ_delF.col(0) = v.cross(w);
71 delJ_delF.col(1) = w.cross(u);
72 delJ_delF.col(2) = u.cross(v);
74 auto hat = [](
const Eigen::Vector3d &
x) {
76 prod << 0, -
x(2),
x(1),
82 del2J_delF2.block<3, 3>(0, 6) =
hat(v);
83 del2J_delF2.block<3, 3>(6, 0) = -
hat(v);
84 del2J_delF2.block<3, 3>(0, 3) = -
hat(w);
85 del2J_delF2.block<3, 3>(3, 0) =
hat(w);
86 del2J_delF2.block<3, 3>(3, 6) = -
hat(u);
87 del2J_delF2.block<3, 3>(6, 3) =
hat(u);
93 : JBarrierThreshold_(
"JBarrierThreshold")
104 if (params.count(
"JBarrierThreshold"))
110 json params_with_default = params;
111 params_with_default[
"JBarrierThreshold"] = 0.5;
116 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 3, 1>
119 assert(pt.size() ==
size());
120 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 3, 1> res;
130 Eigen::MatrixXd &all,
131 const std::function<Eigen::MatrixXd(
const Eigen::MatrixXd &)> &fun)
const
133 const auto &displacement = data.
fun;
135 const auto &bs = data.
bs;
136 const auto &gbs = data.
gbs;
137 const auto el_id = data.
el_id;
138 const auto t = data.
t;
140 Eigen::MatrixXd displacement_grad(
size(),
size());
142 assert(displacement.cols() == 1);
144 all.resize(local_pts.rows(), all_size);
148 const auto I = Eigen::MatrixXd::Identity(
size(),
size());
150 for (
long p = 0; p < local_pts.rows(); ++p)
154 const Eigen::MatrixXd def_grad = I + displacement_grad;
157 all.row(p) = fun(def_grad);
164 Eigen::MatrixXd delJ_delF, del2J_delF2;
165 jacobian_cofactor_derivatives(def_grad,
size(), delJ_delF, del2J_delF2);
171 Eigen::MatrixXd stress_tensor = mu * barrier<double>::first_derivatives(J, JBarrierThreshold) * delJ_delF;
173 stress_tensor = (stress_tensor * def_grad.transpose()) / J;
175 stress_tensor = def_grad.inverse() * stress_tensor;
178 all.row(p) = fun(stress_tensor);
184 const int dim =
size();
187 Eigen::VectorXd jacs;
191 Eigen::MatrixXd local_disp(n_basis, dim);
192 local_disp.setZero();
193 for (
int i = 0; i < n_basis; ++i)
195 for (
int d = 0; d < dim; ++d)
196 local_disp(i, d) += g.val * data.
x(g.index * dim + d);
199 const int n_pts = data.
da.size();
200 for (
long p = 0; p < n_pts; ++p)
202 Eigen::MatrixXd grad(n_basis, dim);
203 for (
int i = 0; i < n_basis; ++i)
206 const Eigen::MatrixXd jac_it = data.
vals.
jac_it[p];
207 const Eigen::MatrixXd def_grad = (local_disp.transpose() * grad) * jac_it + Eigen::MatrixXd::Identity(dim, dim);
209 const double J =
use_robust_jacobian ? jacs(p) * jac_it.determinant() : def_grad.determinant();
215 energy += mu * barrier<double>::value(J, JBarrierThreshold) * data.
da(p);
222 const int dim =
size();
225 Eigen::VectorXd jacs;
229 Eigen::MatrixXd local_disp(n_basis, dim);
230 local_disp.setZero();
231 for (
int i = 0; i < n_basis; ++i)
233 for (
int d = 0; d < dim; ++d)
234 local_disp(i, d) += g.val * data.
x(g.index * dim + d);
236 Eigen::MatrixXd G = Eigen::MatrixXd::Zero(n_basis, dim);
238 const int n_pts = data.
da.size();
239 for (
long p = 0; p < n_pts; ++p)
241 Eigen::MatrixXd grad(n_basis, dim);
242 for (
int i = 0; i < n_basis; ++i)
245 const Eigen::MatrixXd jac_it = data.
vals.
jac_it[p];
246 const Eigen::MatrixXd delF_delU = grad * jac_it;
248 const Eigen::MatrixXd def_grad = local_disp.transpose() * delF_delU + Eigen::MatrixXd::Identity(dim, dim);
250 const double J =
use_robust_jacobian ? jacs(p) * jac_it.determinant() : def_grad.determinant();
253 Eigen::MatrixXd delJ_delF, del2J_delF2;
254 jacobian_cofactor_derivatives(def_grad, dim, delJ_delF, del2J_delF2);
259 const Eigen::MatrixXd gradient_temp = mu * barrier<double>::first_derivatives(J, JBarrierThreshold) * delJ_delF;
260 const Eigen::MatrixXd gradient = delF_delU * gradient_temp.transpose();
262 G.noalias() += gradient * data.
da(p);
265 const Eigen::MatrixXd G_T = G.transpose();
266 return Eigen::Map<const Eigen::VectorXd>(G_T.data(), G_T.size());
271 const int dim =
size();
273 const int N = n_basis * dim;
275 Eigen::MatrixXd H = Eigen::MatrixXd::Zero(N, N);
277 Eigen::VectorXd jacs;
281 Eigen::MatrixXd local_disp(n_basis, dim);
282 local_disp.setZero();
283 for (
int i = 0; i < n_basis; ++i)
285 for (
int d = 0; d < dim; ++d)
286 local_disp(i, d) += g.val * data.
x(g.index * dim + d);
288 const int n_pts = data.
da.size();
289 for (
long p = 0; p < n_pts; ++p)
291 Eigen::MatrixXd grad(n_basis, dim);
292 for (
int i = 0; i < n_basis; ++i)
295 const Eigen::MatrixXd jac_it = data.
vals.
jac_it[p];
296 const Eigen::MatrixXd delF_delU = grad * jac_it;
298 const Eigen::MatrixXd def_grad = local_disp.transpose() * delF_delU + Eigen::MatrixXd::Identity(dim, dim);
300 const double J =
use_robust_jacobian ? jacs(p) * jac_it.determinant() : def_grad.determinant();
303 Eigen::MatrixXd delJ_delF, del2J_delF2;
304 jacobian_cofactor_derivatives(def_grad, dim, delJ_delF, del2J_delF2);
309 const Eigen::Map<const Eigen::VectorXd> g_j(delJ_delF.data(), delJ_delF.size());
311 const Eigen::MatrixXd hessian_temp = mu * barrier<double>::first_derivatives(J, JBarrierThreshold) * del2J_delF2
312 + mu * barrier<double>::second_derivatives(J, JBarrierThreshold) * (g_j * g_j.transpose());
314 Eigen::MatrixXd delF_delU_tensor = Eigen::MatrixXd::Zero(dim * dim, N);
315 for (
int i = 0; i < n_basis; ++i)
317 for (
int j = 0; j < dim; ++j)
319 Eigen::MatrixXd temp = Eigen::MatrixXd::Zero(dim, dim);
320 temp.row(j) = delF_delU.row(i);
321 delF_delU_tensor.col(i * dim + j) = Eigen::Map<const Eigen::VectorXd>(temp.data(), temp.size());
325 H += (delF_delU_tensor.transpose() * hessian_temp * delF_delU_tensor) * data.
da(p);
332 std::map<std::string, ParamFunc> res;
338 params.lambda_mu(uv, p, t, e, lambda, mu);
342 res[
"JBarrierThreshold"] = [&JBarrierThreshold](
const RowVectorNd &uv,
const RowVectorNd &p,
double t,
int e) {
343 return JBarrierThreshold(p, t, e);
ElementAssemblyValues vals
std::string stress() const
stores per element basis values at given quadrature points and geometric mapping
std::vector< AssemblyValues > basis_values
void compute(const int el_index, const bool is_volume, const Eigen::MatrixXd &pts, const basis::ElementBases &basis, const basis::ElementBases &gbasis)
computes the per element values at the local (ref el) points (pts) sets basis_values,...
std::vector< Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > > jac_it
Eigen::VectorXd eval_deformed_jacobian_determinant(const Eigen::VectorXd &disp) const
quadrature::Quadrature quadrature
void add_multimaterial(const int index, const json ¶ms, const std::string &unit_type, const std::string &root_path)
GenericMatParam JBarrierThreshold_
VectorNd compute_rhs(const AutodiffHessianPt &pt) const override
void add_multimaterial(const int index, const json ¶ms, const Units &units, const std::string &root_path) override
void assign_stress_tensor(const OutputData &data, const int all_size, const ElasticityTensorType &type, Eigen::MatrixXd &all, const std::function< Eigen::MatrixXd(const Eigen::MatrixXd &)> &fun) const override
Eigen::MatrixXd assemble_hessian(const NonLinearAssemblerData &data) const override
std::map< std::string, ParamFunc > parameters() const override
double compute_energy(const NonLinearAssemblerData &data) const override
Eigen::VectorXd assemble_gradient(const NonLinearAssemblerData &data) const override
void lambda_mu(double px, double py, double pz, double x, double y, double z, double t, int el_id, double &lambda, double &mu) const
void add_multimaterial(const int index, const json ¶ms, const bool is_volume, const std::string &stress_unit, const std::string &root_path)
const ElementAssemblyValues & vals
const Eigen::MatrixXd & x
const QuadratureVector & da
const basis::ElementBases & bs
const Eigen::MatrixXd & fun
const Eigen::MatrixXd & local_pts
const basis::ElementBases & gbs
Eigen::Matrix< double, dim, dim > hat(const Eigen::Matrix< double, dim, 1 > &x)
T determinant(const Eigen::Matrix< T, rows, cols, option, maxRow, maxCol > &mat)
Eigen::Matrix< AutodiffScalarHessian, Eigen::Dynamic, 1, 0, 3, 1 > AutodiffHessianPt
void compute_diplacement_grad(const int size, const ElementAssemblyValues &vals, const Eigen::MatrixXd &local_pts, const int p, const Eigen::MatrixXd &displacement, Eigen::MatrixXd &displacement_grad)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd