19 using DefGradMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3>;
21 template <
typename Derived>
41 const std::function<Eigen::MatrixXd(
const Eigen::MatrixXd &)> &fun)
const override;
44 const Eigen::MatrixXd &mat,
45 Eigen::MatrixXd &stress,
46 Eigen::MatrixXd &result)
const override;
49 Eigen::MatrixXd &stress,
50 Eigen::MatrixXd &result)
const override;
53 const Eigen::MatrixXd &vect,
54 Eigen::MatrixXd &stress,
55 Eigen::MatrixXd &result)
const override;
58 Derived &
derived() {
return static_cast<Derived &
>(*this); }
60 const Derived &
derived()
const {
return static_cast<const Derived &
>(*this); }
72 virtual Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3>
gradient(
76 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> &
F)
const
81 virtual Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9>
hessian(
85 const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> &
F)
const
98 const int n_pts = data.
da.size();
99 bool any_absolute =
false;
100 for (
int p = 0; p < n_pts; ++p)
106 const int n_simplex_bases =
size() + 1;
109 "Absolute mode (use_rest_pose false) needs straight simplices with linear displacement; element {} has {} bases and {} geometric bases",
112 const Eigen::VectorXd reference = data.
da.array() / data.
vals.
det.array();
113 const double reference_volume = reference.sum();
114 Eigen::VectorXd w = data.
da;
115 for (
int p = 0; p < n_pts; ++p)
117 w(p) = reference(p) / reference_volume;
128 template <
typename T>
131 typedef Eigen::Matrix<T, Eigen::Dynamic, 1>
AutoDiffVect;
132 typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3>
AutoDiffGradMat;
133 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
142 const int n_pts = data.
da.size();
144 for (
long p = 0; p < n_pts; ++p)
149 for (
int d = 0; d <
size(); ++d)
150 def_grad(d, d) += T(1);
154 DoubleGradMat tmp_jac_it = data.
vals.
jac_it[p];
155 tmp_jac_it = tmp_jac_it.inverse();
158 for (
long k = 0; k < jac_it.size(); ++k)
159 jac_it(k) = T(tmp_jac_it(k));
166 energy +=
val * w(p);
180 template <
int n_basis,
int dim>
184 typedef Eigen::Matrix<Diff, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3>
AutoDiffGradMat;
185 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
187 const int n_pts = data.
da.size();
191 local_disp.setZero();
195 for (
size_t ii = 0; ii < bs.global.size(); ++ii)
197 for (
int d = 0; d < dim; ++d)
199 local_disp(i, d) += bs.global[ii].val * data.
x(bs.global[ii].index *
size() + d);
204 Eigen::Matrix<double, dim, dim> def_grad(
size(),
size());
211 for (
long p = 0; p < n_pts; ++p)
218 Eigen::Matrix<double, dim, dim> jac_it = data.
vals.
jac_it[p];
219 Eigen::Matrix<double, n_basis, dim> G = grad * jac_it;
220 def_grad = local_disp.transpose() * G + Eigen::Matrix<double, dim, dim>::Identity(
size(),
size());
222 for (
int d1 = 0; d1 <
size(); ++d1)
223 for (
int d2 = 0; d2 <
size(); ++d2)
224 def_grad_ad(d1, d2) = Diff(d1 *
size() + d2, def_grad(d1, d2));
228 DoubleGradMat tmp_jac_it = data.
vals.
jac_it[p];
229 tmp_jac_it = tmp_jac_it.inverse();
232 for (
long k = 0; k < jac_it.size(); ++k)
233 jac_it(k) = Diff(tmp_jac_it(k));
235 def_grad_ad *= jac_it;
240 Eigen::Matrix<double, dim, dim> P;
241 for (
int i = 0; i <
size(); ++i)
242 for (
int j = 0; j <
size(); ++j)
243 P(i, j) =
val.getGradient()(i *
size() + j);
245 const Eigen::Matrix<double, n_basis, dim> Rloc = G * P.transpose() * w(p);
248 for (
int d = 0; d <
size(); ++d)
249 res(a *
size() + d) += Rloc(a, d);
253 template <
int n_basis,
int dim>
256 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
258 const int n_pts = data.
da.size();
262 local_disp.setZero();
266 for (
size_t ii = 0; ii < bs.global.size(); ++ii)
268 for (
int d = 0; d < dim; ++d)
270 local_disp(i, d) += bs.global[ii].val * data.
x(bs.global[ii].index *
size() + d);
275 Eigen::Matrix<double, dim, dim> def_grad(
size(),
size());
279 for (
long p = 0; p < n_pts; ++p)
286 Eigen::Matrix<double, dim, dim> jac_it = data.
vals.
jac_it[p];
287 Eigen::Matrix<double, n_basis, dim> G = grad * jac_it;
288 def_grad = local_disp.transpose() * G + Eigen::Matrix<double, dim, dim>::Identity(
size(),
size());
293 jac_it = jac_it.inverse();
299 const Eigen::Matrix<double, n_basis, dim> Bgrad =
rest_pose_at(data, p) ? G : grad;
300 const Eigen::Matrix<double, n_basis, dim> Rloc = Bgrad * P.transpose() * w(p);
303 for (
int d = 0; d <
size(); ++d)
304 res(a *
size() + d) += Rloc(a, d);
308 template <
int n_basis,
int dim>
311 typedef DScalar2<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1>, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9>> Diff2;
312 typedef Eigen::Matrix<Diff2, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3>
AutoDiffGradMat;
313 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
315 const int d =
size();
317 const int n_pts = data.
da.size();
320 Eigen::Matrix<double, n_basis, dim> local_disp(nb, d);
321 local_disp.setZero();
325 for (
size_t ii = 0; ii < bs.global.size(); ++ii)
327 for (
int dd = 0; dd < d; ++dd)
328 local_disp(i, dd) += bs.global[ii].val * data.
x(bs.global[ii].index * d + dd);
334 Eigen::Matrix<double, dim, dim> def_grad(d, d);
336 H.resize(nb * d, nb * d);
339 for (
long p = 0; p < n_pts; ++p)
341 Eigen::Matrix<double, n_basis, dim> grad_ref(nb, d);
345 const Eigen::Matrix<double, dim, dim> jac_it = data.
vals.
jac_it[p];
346 const Eigen::Matrix<double, n_basis, dim> G = grad_ref * jac_it;
348 def_grad = local_disp.transpose() * G + Eigen::Matrix<double, dim, dim>::Identity();
350 for (
int i = 0; i < d; ++i)
351 for (
int j = 0; j < d; ++j)
352 def_grad_ad(i, j) = Diff2(i * d + j, def_grad(i, j));
356 DoubleGradMat tmp_jac_it = data.
vals.
jac_it[p];
357 tmp_jac_it = tmp_jac_it.inverse();
360 for (
long k = 0; k < jac_it.size(); ++k)
361 jac_it(k) = Diff2(tmp_jac_it(k));
363 def_grad_ad *= jac_it;
368 Eigen::Matrix<double, dim * dim, dim * dim> A(d * d, d * d);
373 for (
int r = 0; r < d * d; ++r)
374 for (
int c = 0; c < d * d; ++c)
375 A(r, c) =
val.getHessian()(r, c);
377 for (
int a = 0; a < nb; ++a)
379 const Eigen::Matrix<double, dim * dim, dim> Ba = compute_B_block<dim>(G.row(a));
381 for (
int b = 0; b < nb; ++b)
383 const Eigen::Matrix<double, dim * dim, dim> Bb = compute_B_block<dim>(G.row(b));
385 const Eigen::Matrix<double, dim, dim> Kab =
386 Ba.transpose() * A * Bb * w(p);
388 H.template block<dim, dim>(a * d, b * d) += Kab;
394 template <
int n_basis,
int dim>
397 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> DoubleGradMat;
399 const int d =
size();
401 const int n_pts = data.
da.size();
404 Eigen::Matrix<double, n_basis, dim> local_disp(nb, d);
405 local_disp.setZero();
409 for (
size_t ii = 0; ii < bs.global.size(); ++ii)
411 for (
int dd = 0; dd < d; ++dd)
412 local_disp(i, dd) += bs.global[ii].val * data.
x(bs.global[ii].index * d + dd);
416 Eigen::Matrix<double, dim, dim> def_grad(d, d);
418 H.resize(nb * d, nb * d);
421 for (
long p = 0; p < n_pts; ++p)
423 Eigen::Matrix<double, n_basis, dim> grad_ref(nb, d);
427 const Eigen::Matrix<double, dim, dim> jac_it = data.
vals.
jac_it[p];
428 const Eigen::Matrix<double, n_basis, dim> G = grad_ref * jac_it;
430 def_grad = local_disp.transpose() * G + Eigen::Matrix<double, dim, dim>::Identity();
435 jac_it = jac_it.inverse();
444 const Eigen::Matrix<double, n_basis, dim> Bgrad =
rest_pose_at(data, p) ? G : grad_ref;
446 for (
int a = 0; a < nb; ++a)
448 const Eigen::Matrix<double, dim * dim, dim> Ba = compute_B_block<dim>(Bgrad.row(a));
450 for (
int b = 0; b < nb; ++b)
452 const Eigen::Matrix<double, dim * dim, dim> Bb = compute_B_block<dim>(Bgrad.row(b));
454 const Eigen::Matrix<double, dim, dim> Kab =
455 Ba.transpose() * A * Bb * w(p);
457 H.template block<dim, dim>(a * d, b * d) += Kab;
464 Eigen::Matrix<double, dim * dim, dim>
compute_B_block(
const Eigen::Matrix<double, 1, dim> &g)
const;
virtual void assemble_gradient(const bool is_volume, const int n_basis, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev, Eigen::MatrixXd &rhs) const
virtual void assemble_hessian(const bool is_volume, const int n_basis, const bool project_to_psd, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev, utils::MatrixCache &mat_cache, StiffnessMatrix &grad) const
virtual double assemble_energy(const bool is_volume, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const AssemblyValsCache &cache, const double t, const double dt, const Eigen::MatrixXd &displacement, const Eigen::MatrixXd &displacement_prev) const
std::vector< AssemblyValues > basis_values
std::vector< Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > > jac_it
void compute_stress_grad_multiply_stress(const OptAssemblerData &data, Eigen::MatrixXd &stress, Eigen::MatrixXd &result) const override
void compute_hessian_from_stress_noad(const NonLinearAssemblerData &data, Eigen::MatrixXd &H) const
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
bool rest_pose_at(const NonLinearAssemblerData &data, const long p) const
Eigen::VectorXd assemble_gradient_full_ad(const NonLinearAssemblerData &data) const
virtual Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 9, 9 > hessian(const RowVectorNd &p, const double t, const int el_id, const Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > &F) const
Derived & derived()
Returns this as a reference to derived class.
Eigen::MatrixXd assemble_hessian_full_ad(const NonLinearAssemblerData &data) const
const Derived & derived() const
Returns this as a const reference to derived class.
Eigen::MatrixXd assemble_hessian_stress_noad(const NonLinearAssemblerData &data) const
virtual void add_multimaterial(const int index, const json ¶ms, const Units &units, const io::ResourceIO &resources) override=0
virtual ~GenericElastic()=default
virtual bool real_def_grad(const RowVectorNd &p, const double t, const int el_id) 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
bool allow_inversion() const override
Eigen::VectorXd assemble_gradient_stress_ad(const NonLinearAssemblerData &data) const
void compute_hessian_from_stress(const NonLinearAssemblerData &data, Eigen::MatrixXd &H) const
void compute_gradient_from_stress_noad(const NonLinearAssemblerData &data, Eigen::VectorXd &res) const
virtual Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > gradient(const RowVectorNd &p, const double t, const int el_id, const Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > &F) const
Eigen::VectorXd point_weights(const NonLinearAssemblerData &data) const
AutodiffType autodiff_type_
void compute_gradient_from_stress(const NonLinearAssemblerData &data, Eigen::VectorXd &res) const
double compute_energy(const NonLinearAssemblerData &data) const override
T compute_energy_aux(const NonLinearAssemblerData &data) const
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 & x
const QuadratureVector & da
Read-only interface to a hierarchical collection of simulation resources.
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > DefGradMatrix
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > AutoDiffGradMat
Eigen::Matrix< T, Eigen::Dynamic, 1 > AutoDiffVect
void compute_disp_grad_at_quad(const assembler::NonLinearAssemblerData &data, const AutoDiffVect &local_disp, const int p, const int size, AutoDiffGradMat &def_grad)
void get_local_disp(const assembler::NonLinearAssemblerData &data, const int size, AutoDiffVect &local_disp)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
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.