10 template <
typename Derived>
14 Eigen::Matrix<double, dim * dim, dim> B(size() * size(), size());
17 for (
int i = 0; i < dim; ++i)
18 for (
int j = 0; j < dim; ++j)
19 B(i * dim + j, i) = g(j);
24 template <
typename Derived>
29 template <
typename Derived>
35 const std::function<Eigen::MatrixXd(
const Eigen::MatrixXd &)> &fun)
const
37 Eigen::MatrixXd deformation_grad(size(), size());
38 Eigen::MatrixXd stress_tensor(size(), size());
42 const auto &displacement = data.
fun;
44 const auto &bs = data.
bs;
45 const auto &gbs = data.
gbs;
46 const auto el_id = data.
el_id;
48 assert(displacement.cols() == 1);
50 all.resize(local_pts.rows(), all_size);
53 Eigen::Matrix<Diff, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> def_grad(size(), size());
56 vals.
compute(el_id, size() == 3, local_pts, bs, gbs);
58 for (
long p = 0; p < local_pts.rows(); ++p)
63 for (
int d = 0; d < size(); ++d)
64 deformation_grad(d, d) += 1;
68 all.row(p) = fun(deformation_grad);
73 if (!derived().real_def_grad(
vals.
val.row(p), data.
t, el_id))
75 all.row(p).setConstant(std::nan(
""));
79 for (
int d1 = 0; d1 < size(); ++d1)
81 for (
int d2 = 0; d2 < size(); ++d2)
82 def_grad(d1, d2) = Diff(d1 * size() + d2, deformation_grad(d1, d2));
85 const auto val = derived().elastic_energy(local_pts.row(p), data.
t,
vals.
element_id, def_grad);
87 for (
int d1 = 0; d1 < size(); ++d1)
89 for (
int d2 = 0; d2 < size(); ++d2)
90 stress_tensor(d1, d2) =
val.getGradient()(d1 * size() + d2);
93 stress_tensor = 1.0 / deformation_grad.determinant() * stress_tensor * deformation_grad.transpose();
100 all.row(p) = fun(stress_tensor);
104 template <
typename Derived>
107 return compute_energy_aux<double>(data);
110 template <
typename Derived>
114 return assemble_gradient_full_ad(data);
118 auto grad = assemble_gradient_stress_ad(data);
119 auto grad_full = assemble_gradient_full_ad(data);
120 assert((std::isnan(grad.norm()) && std::isnan(grad_full.norm())) || (grad - grad_full).norm() < 1e-6);
122 return assemble_gradient_stress_ad(data);
127 auto grad = assemble_gradient_stress_noad(data);
128 auto grad_full = assemble_gradient_stress_ad(data);
129 assert((std::isnan(grad.norm()) && std::isnan(grad_full.norm())) || (grad - grad_full).norm() < 1e-6);
131 return assemble_gradient_stress_noad(data);
135 template <
typename Derived>
140 size(), n_bases, data,
141 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 6, 1>>>(data); },
142 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 8, 1>>>(data); },
143 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 12, 1>>>(data); },
144 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 18, 1>>>(data); },
145 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 24, 1>>>(data); },
146 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 30, 1>>>(data); },
147 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 60, 1>>>(data); },
148 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 81, 1>>>(data); },
149 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, SMALL_N, 1>>>(data); },
150 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, BIG_N, 1>>>(data); },
151 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::VectorXd>>(data); });
154 template <
typename Derived>
157 Eigen::Matrix<double, Eigen::Dynamic, 1> gradient;
166 compute_gradient_from_stress<3, 2>(data, gradient);
172 compute_gradient_from_stress<6, 2>(data, gradient);
178 compute_gradient_from_stress<10, 2>(data, gradient);
184 compute_gradient_from_stress<Eigen::Dynamic, 2>(data, gradient);
197 compute_gradient_from_stress<4, 3>(data, gradient);
203 compute_gradient_from_stress<10, 3>(data, gradient);
209 compute_gradient_from_stress<20, 3>(data, gradient);
215 compute_gradient_from_stress<Eigen::Dynamic, 3>(data, gradient);
224 template <
typename Derived>
227 Eigen::Matrix<double, Eigen::Dynamic, 1> gradient;
236 compute_gradient_from_stress_noad<3, 2>(data, gradient);
242 compute_gradient_from_stress_noad<6, 2>(data, gradient);
248 compute_gradient_from_stress_noad<10, 2>(data, gradient);
254 compute_gradient_from_stress_noad<Eigen::Dynamic, 2>(data, gradient);
267 compute_gradient_from_stress_noad<4, 3>(data, gradient);
273 compute_gradient_from_stress_noad<10, 3>(data, gradient);
279 compute_gradient_from_stress_noad<20, 3>(data, gradient);
285 compute_gradient_from_stress_noad<Eigen::Dynamic, 3>(data, gradient);
294 template <
typename Derived>
298 return assemble_hessian_full_ad(data);
302 auto hessian = assemble_hessian_stress_ad(data);
303 auto hessian_full = assemble_hessian_full_ad(data);
304 assert((std::isnan(hessian.norm()) && std::isnan(hessian_full.norm())) || (hessian - hessian_full).norm() < 1e-5);
306 return assemble_hessian_stress_ad(data);
311 auto hessian = assemble_hessian_stress_noad(data);
312 auto hessian_full = assemble_hessian_stress_ad(data);
313 assert((std::isnan(hessian.norm()) && std::isnan(hessian_full.norm())) || (hessian - hessian_full).norm() < 1e-5);
315 return assemble_hessian_stress_noad(data);
319 template <
typename Derived>
324 size(), n_bases, data,
325 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 6, 1>, Eigen::Matrix<double, 6, 6>>>(data); },
326 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 8, 1>, Eigen::Matrix<double, 8, 8>>>(data); },
327 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 12, 1>, Eigen::Matrix<double, 12, 12>>>(data); },
328 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 18, 1>, Eigen::Matrix<double, 18, 18>>>(data); },
329 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 24, 1>, Eigen::Matrix<double, 24, 24>>>(data); },
330 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 30, 1>, Eigen::Matrix<double, 30, 30>>>(data); },
331 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 60, 1>, Eigen::Matrix<double, 60, 60>>>(data); },
332 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 81, 1>, Eigen::Matrix<double, 81, 81>>>(data); },
333 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, SMALL_N, 1>, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, SMALL_N, SMALL_N>>>(data); },
334 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::VectorXd, Eigen::MatrixXd>>(data); });
337 template <
typename Derived>
340 Eigen::MatrixXd hessian;
348 hessian.resize(6, 6);
350 compute_hessian_from_stress<3, 2>(data, hessian);
355 hessian.resize(12, 12);
357 compute_hessian_from_stress<6, 2>(data, hessian);
362 hessian.resize(20, 20);
364 compute_hessian_from_stress<10, 2>(data, hessian);
371 compute_hessian_from_stress<Eigen::Dynamic, 2>(data, hessian);
383 hessian.resize(12, 12);
385 compute_hessian_from_stress<4, 3>(data, hessian);
390 hessian.resize(30, 30);
392 compute_hessian_from_stress<10, 3>(data, hessian);
397 hessian.resize(60, 60);
399 compute_hessian_from_stress<20, 3>(data, hessian);
406 compute_hessian_from_stress<Eigen::Dynamic, 3>(data, hessian);
415 template <
typename Derived>
418 Eigen::MatrixXd hessian;
426 hessian.resize(6, 6);
428 compute_hessian_from_stress_noad<3, 2>(data, hessian);
433 hessian.resize(12, 12);
435 compute_hessian_from_stress_noad<6, 2>(data, hessian);
440 hessian.resize(20, 20);
442 compute_hessian_from_stress_noad<10, 2>(data, hessian);
449 compute_hessian_from_stress_noad<Eigen::Dynamic, 2>(data, hessian);
461 hessian.resize(12, 12);
463 compute_hessian_from_stress_noad<4, 3>(data, hessian);
468 hessian.resize(30, 30);
470 compute_hessian_from_stress_noad<10, 3>(data, hessian);
475 hessian.resize(60, 60);
477 compute_hessian_from_stress_noad<20, 3>(data, hessian);
484 compute_hessian_from_stress_noad<Eigen::Dynamic, 3>(data, hessian);
493 template <
typename Derived>
496 const Eigen::MatrixXd &mat,
497 Eigen::MatrixXd &stress,
498 Eigen::MatrixXd &result)
const
500 typedef DScalar2<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1>, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9>> Diff;
502 const double t = data.
t;
503 const int el_id = data.
el_id;
504 if (!derived().real_def_grad(data.
global_pts, t, el_id))
505 log_and_throw_error(
"Stress derivatives are not available in absolute mode (use_rest_pose false)");
506 const Eigen::MatrixXd &local_pts = data.
local_pts;
507 const Eigen::MatrixXd &global_pts = data.
global_pts;
508 const Eigen::MatrixXd &grad_u_i = data.
grad_u_i;
511 Eigen::Matrix<Diff, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> def_grad(size(), size());
513 Eigen::MatrixXd
F = grad_u_i;
514 for (
int d = 0; d < size(); ++d)
517 assert(local_pts.rows() == 1);
518 for (
int i = 0; i < size(); ++i)
519 for (
int j = 0; j < size(); ++j)
520 def_grad(i, j) = Diff(i + j * size(),
F(i, j));
522 auto energy = derived().elastic_energy(global_pts, t, el_id, def_grad);
525 Eigen::MatrixXd grad = energy.getGradient().reshaped(size(), size());
527 Eigen::MatrixXd hess = energy.getHessian();
532 result = (hess * mat.reshaped(size() * size(), 1)).reshaped(size(), size());
535 template <
typename Derived>
538 Eigen::MatrixXd &stress,
539 Eigen::MatrixXd &result)
const
541 typedef DScalar2<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1>, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9>> Diff;
543 const double t = data.
t;
544 const int el_id = data.
el_id;
545 if (!derived().real_def_grad(data.
global_pts, t, el_id))
546 log_and_throw_error(
"Stress derivatives are not available in absolute mode (use_rest_pose false)");
547 const Eigen::MatrixXd &local_pts = data.
local_pts;
548 const Eigen::MatrixXd &global_pts = data.
global_pts;
549 const Eigen::MatrixXd &grad_u_i = data.
grad_u_i;
552 Eigen::Matrix<Diff, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> def_grad(size(), size());
554 Eigen::MatrixXd
F = grad_u_i;
555 for (
int d = 0; d < size(); ++d)
558 assert(local_pts.rows() == 1);
559 for (
int i = 0; i < size(); ++i)
560 for (
int j = 0; j < size(); ++j)
561 def_grad(i, j) = Diff(i + j * size(),
F(i, j));
563 auto energy = derived().elastic_energy(global_pts, t, el_id, def_grad);
566 Eigen::MatrixXd grad = energy.getGradient().reshaped(size(), size());
568 Eigen::MatrixXd hess = energy.getHessian();
573 result = (hess * stress.reshaped(size() * size(), 1)).reshaped(size(), size());
576 template <
typename Derived>
579 const Eigen::MatrixXd &vect,
580 Eigen::MatrixXd &stress,
581 Eigen::MatrixXd &result)
const
583 typedef DScalar2<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1>, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9>> Diff;
585 const double t = data.
t;
586 const int el_id = data.
el_id;
587 if (!derived().real_def_grad(data.
global_pts, t, el_id))
588 log_and_throw_error(
"Stress derivatives are not available in absolute mode (use_rest_pose false)");
589 const Eigen::MatrixXd &local_pts = data.
local_pts;
590 const Eigen::MatrixXd &global_pts = data.
global_pts;
591 const Eigen::MatrixXd &grad_u_i = data.
grad_u_i;
594 Eigen::Matrix<Diff, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> def_grad(size(), size());
596 Eigen::MatrixXd
F = grad_u_i;
597 for (
int d = 0; d < size(); ++d)
600 assert(local_pts.rows() == 1);
601 for (
int i = 0; i < size(); ++i)
602 for (
int j = 0; j < size(); ++j)
603 def_grad(i, j) = Diff(i + j * size(),
F(i, j));
605 auto energy = derived().elastic_energy(global_pts, t, el_id, def_grad);
608 Eigen::MatrixXd grad = energy.getGradient().reshaped(size(), size());
610 Eigen::MatrixXd hess = energy.getHessian();
614 result.resize(hess.rows(), vect.size());
615 for (
int i = 0; i < hess.rows(); ++i)
616 if (vect.rows() == 1)
618 result.row(i) = vect * hess.row(i).reshaped(size(), size());
621 result.row(i) = (hess.row(i).reshaped(size(), size()) * vect).transpose();
ElementAssemblyValues vals
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,...
void compute_stress_grad_multiply_stress(const OptAssemblerData &data, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const 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::Matrix< double, dim *dim, dim > compute_B_block(const Eigen::Matrix< double, 1, dim > &g) const
Eigen::VectorXd assemble_gradient_full_ad(const NonLinearAssemblerData &data) const
Eigen::MatrixXd assemble_hessian_full_ad(const NonLinearAssemblerData &data) const
Eigen::MatrixXd assemble_hessian_stress_noad(const NonLinearAssemblerData &data) const
Eigen::VectorXd assemble_gradient_stress_noad(const NonLinearAssemblerData &data) const
Eigen::MatrixXd assemble_hessian_stress_ad(const NonLinearAssemblerData &data) const
Eigen::MatrixXd assemble_hessian(const NonLinearAssemblerData &data) const override
void compute_stress_grad_multiply_vect(const OptAssemblerData &data, const Eigen::MatrixXd &vect, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const override
Eigen::VectorXd assemble_gradient(const NonLinearAssemblerData &data) const override
Eigen::VectorXd assemble_gradient_stress_ad(const NonLinearAssemblerData &data) const
double compute_energy(const NonLinearAssemblerData &data) const override
void compute_stress_grad_multiply_mat(const OptAssemblerData &data, const Eigen::MatrixXd &mat, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const override
const ElementAssemblyValues & vals
const Eigen::MatrixXd & local_pts
const Eigen::MatrixXd & global_pts
const Eigen::MatrixXd & grad_u_i
const basis::ElementBases & bs
const Eigen::MatrixXd & fun
const Eigen::MatrixXd & local_pts
const basis::ElementBases & gbs
Eigen::MatrixXd pk2_from_cauchy(const Eigen::MatrixXd &stress, const Eigen::MatrixXd &F)
Eigen::MatrixXd hessian_from_energy(const int size, const int n_bases, const assembler::NonLinearAssemblerData &data, const std::function< DScalar2< double, Eigen::Matrix< double, 6, 1 >, Eigen::Matrix< double, 6, 6 > >(const assembler::NonLinearAssemblerData &)> &fun6, const std::function< DScalar2< double, Eigen::Matrix< double, 8, 1 >, Eigen::Matrix< double, 8, 8 > >(const assembler::NonLinearAssemblerData &)> &fun8, const std::function< DScalar2< double, Eigen::Matrix< double, 12, 1 >, Eigen::Matrix< double, 12, 12 > >(const assembler::NonLinearAssemblerData &)> &fun12, const std::function< DScalar2< double, Eigen::Matrix< double, 18, 1 >, Eigen::Matrix< double, 18, 18 > >(const assembler::NonLinearAssemblerData &)> &fun18, const std::function< DScalar2< double, Eigen::Matrix< double, 24, 1 >, Eigen::Matrix< double, 24, 24 > >(const assembler::NonLinearAssemblerData &)> &fun24, const std::function< DScalar2< double, Eigen::Matrix< double, 30, 1 >, Eigen::Matrix< double, 30, 30 > >(const assembler::NonLinearAssemblerData &)> &fun30, const std::function< DScalar2< double, Eigen::Matrix< double, 60, 1 >, Eigen::Matrix< double, 60, 60 > >(const assembler::NonLinearAssemblerData &)> &fun60, const std::function< DScalar2< double, Eigen::Matrix< double, 81, 1 >, Eigen::Matrix< double, 81, 81 > >(const assembler::NonLinearAssemblerData &)> &fun81, const std::function< DScalar2< double, Eigen::Matrix< double, Eigen::Dynamic, 1, 0, SMALL_N, 1 >, Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, SMALL_N, SMALL_N > >(const assembler::NonLinearAssemblerData &)> &funN, const std::function< DScalar2< double, Eigen::VectorXd, Eigen::MatrixXd >(const assembler::NonLinearAssemblerData &)> &funn)
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::MatrixXd pk1_from_cauchy(const Eigen::MatrixXd &stress, const Eigen::MatrixXd &F)
Eigen::VectorXd gradient_from_energy(const int size, const int n_bases, const assembler::NonLinearAssemblerData &data, const std::function< DScalar1< double, Eigen::Matrix< double, 6, 1 > >(const assembler::NonLinearAssemblerData &)> &fun6, const std::function< DScalar1< double, Eigen::Matrix< double, 8, 1 > >(const assembler::NonLinearAssemblerData &)> &fun8, const std::function< DScalar1< double, Eigen::Matrix< double, 12, 1 > >(const assembler::NonLinearAssemblerData &)> &fun12, const std::function< DScalar1< double, Eigen::Matrix< double, 18, 1 > >(const assembler::NonLinearAssemblerData &)> &fun18, const std::function< DScalar1< double, Eigen::Matrix< double, 24, 1 > >(const assembler::NonLinearAssemblerData &)> &fun24, const std::function< DScalar1< double, Eigen::Matrix< double, 30, 1 > >(const assembler::NonLinearAssemblerData &)> &fun30, const std::function< DScalar1< double, Eigen::Matrix< double, 60, 1 > >(const assembler::NonLinearAssemblerData &)> &fun60, const std::function< DScalar1< double, Eigen::Matrix< double, 81, 1 > >(const assembler::NonLinearAssemblerData &)> &fun81, const std::function< DScalar1< double, Eigen::Matrix< double, Eigen::Dynamic, 1, 0, SMALL_N, 1 > >(const assembler::NonLinearAssemblerData &)> &funN, const std::function< DScalar1< double, Eigen::Matrix< double, Eigen::Dynamic, 1, 0, BIG_N, 1 > >(const assembler::NonLinearAssemblerData &)> &funBigN, const std::function< DScalar1< double, Eigen::VectorXd >(const assembler::NonLinearAssemblerData &)> &funn)
void log_and_throw_error(const std::string &msg)
Automatic differentiation scalar with first-order derivatives.
Automatic differentiation scalar with first- and second-order derivatives.
static void setVariableCount(size_t value)
Set the independent variable count used by the automatic differentiation layer.