10 template <
class Matrix>
11 Matrix strain_from_disp_grad(
const Matrix &disp_grad)
15 for (
int i = 0; i < mat.size(); ++i)
22 Eigen::Matrix<double, dim, dim> strain(
const Eigen::MatrixXd &grad,
const Eigen::MatrixXd &jac_it,
int k,
int coo)
24 Eigen::Matrix<double, dim, dim> jac;
26 jac.row(coo) =
grad.row(k);
29 return strain_from_disp_grad(jac);
32 template <
typename T,
unsigned long N>
33 T stress(
const ElasticityTensor &elasticity_tensor,
const std::array<T, N> &strain,
const int j)
35 T res = elasticity_tensor(j, 0) * strain[0];
37 for (
unsigned long k = 1; k <
N; ++k)
38 res += elasticity_tensor(j, k) * strain[k];
52 if (!params.contains(
"elasticity_tensor") || params[
"elasticity_tensor"].empty())
54 if (params.count(
"young"))
56 if (params[
"young"].is_number() && params[
"nu"].is_number())
59 else if (params.count(
"E"))
61 if (params[
"E"].is_number() && params[
"nu"].is_number())
64 else if (params.count(
"lambda"))
66 if (params[
"lambda"].is_number() && params[
"mu"].is_number())
72 std::vector<double>
entries = params[
"elasticity_tensor"];
83 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1>
90 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1> res(
size() *
size());
92 assert(gradi.cols() ==
size());
93 assert(gradj.cols() ==
size());
94 assert(
size_t(gradi.rows()) == data.
vals.
jac_it.size());
96 for (
long k = 0; k < gradi.rows(); ++k)
98 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 9, 1> res_k(
size() *
size());
102 const Eigen::Matrix2d eps_x_i = strain<2>(gradi, data.
vals.
jac_it[k], k, 0);
103 const Eigen::Matrix2d eps_y_i = strain<2>(gradi, data.
vals.
jac_it[k], k, 1);
105 const Eigen::Matrix2d eps_x_j = strain<2>(gradj, data.
vals.
jac_it[k], k, 0);
106 const Eigen::Matrix2d eps_y_j = strain<2>(gradj, data.
vals.
jac_it[k], k, 1);
108 std::array<double, 3> e_x, e_y;
109 e_x[0] = eps_x_i(0, 0);
110 e_x[1] = eps_x_i(1, 1);
111 e_x[2] = 2 * eps_x_i(0, 1);
113 e_y[0] = eps_y_i(0, 0);
114 e_y[1] = eps_y_i(1, 1);
115 e_y[2] = 2 * eps_y_i(0, 1);
117 Eigen::Matrix2d sigma_x;
121 Eigen::Matrix2d sigma_y;
125 res_k(0) = (sigma_x * eps_x_j).trace();
126 res_k(2) = (sigma_x * eps_y_j).trace();
128 res_k(1) = (sigma_y * eps_x_j).trace();
129 res_k(3) = (sigma_y * eps_y_j).trace();
133 const Eigen::Matrix3d eps_x_i = strain<3>(gradi, data.
vals.
jac_it[k], k, 0);
134 const Eigen::Matrix3d eps_y_i = strain<3>(gradi, data.
vals.
jac_it[k], k, 1);
135 const Eigen::Matrix3d eps_z_i = strain<3>(gradi, data.
vals.
jac_it[k], k, 2);
137 const Eigen::Matrix3d eps_x_j = strain<3>(gradj, data.
vals.
jac_it[k], k, 0);
138 const Eigen::Matrix3d eps_y_j = strain<3>(gradj, data.
vals.
jac_it[k], k, 1);
139 const Eigen::Matrix3d eps_z_j = strain<3>(gradj, data.
vals.
jac_it[k], k, 2);
141 std::array<double, 6> e_x, e_y, e_z;
142 e_x[0] = eps_x_i(0, 0);
143 e_x[1] = eps_x_i(1, 1);
144 e_x[2] = eps_x_i(2, 2);
145 e_x[3] = 2 * eps_x_i(1, 2);
146 e_x[4] = 2 * eps_x_i(0, 2);
147 e_x[5] = 2 * eps_x_i(0, 1);
149 e_y[0] = eps_y_i(0, 0);
150 e_y[1] = eps_y_i(1, 1);
151 e_y[2] = eps_y_i(2, 2);
152 e_y[3] = 2 * eps_y_i(1, 2);
153 e_y[4] = 2 * eps_y_i(0, 2);
154 e_y[5] = 2 * eps_y_i(0, 1);
156 e_z[0] = eps_z_i(0, 0);
157 e_z[1] = eps_z_i(1, 1);
158 e_z[2] = eps_z_i(2, 2);
159 e_z[3] = 2 * eps_z_i(1, 2);
160 e_z[4] = 2 * eps_z_i(0, 2);
161 e_z[5] = 2 * eps_z_i(0, 1);
163 Eigen::Matrix3d sigma_x;
168 Eigen::Matrix3d sigma_y;
173 Eigen::Matrix3d sigma_z;
178 res_k(0) = (sigma_x * eps_x_j).trace();
179 res_k(3) = (sigma_x * eps_y_j).trace();
180 res_k(6) = (sigma_x * eps_z_j).trace();
182 res_k(1) = (sigma_y * eps_x_j).trace();
183 res_k(4) = (sigma_y * eps_y_j).trace();
184 res_k(7) = (sigma_y * eps_z_j).trace();
186 res_k(2) = (sigma_z * eps_x_j).trace();
187 res_k(5) = (sigma_z * eps_y_j).trace();
188 res_k(8) = (sigma_z * eps_z_j).trace();
191 res += res_k * data.
da(k);
203 Eigen::MatrixXd &all,
204 const std::function<Eigen::MatrixXd(
const Eigen::MatrixXd &)> &fun)
const
206 const auto &displacement = data.
fun;
208 const auto &bs = data.
bs;
209 const auto &gbs = data.
gbs;
210 const auto el_id = data.
el_id;
212 Eigen::MatrixXd displacement_grad(
size(),
size());
214 assert(displacement.cols() == 1);
216 all.resize(local_pts.rows(), all_size);
221 for (
long p = 0; p < local_pts.rows(); ++p)
227 all.row(p) = fun(displacement_grad + Eigen::MatrixXd::Identity(
size(),
size()));
231 Eigen::MatrixXd strain = (displacement_grad + displacement_grad.transpose()) / 2;
232 Eigen::MatrixXd sigma(
size(),
size());
236 std::array<double, 3> eps;
237 eps[0] = strain(0, 0);
238 eps[1] = strain(1, 1);
239 eps[2] = 2 * strain(0, 1);
246 std::array<double, 6> eps;
247 eps[0] = strain(0, 0);
248 eps[1] = strain(1, 1);
249 eps[2] = strain(2, 2);
250 eps[3] = 2 * strain(1, 2);
251 eps[4] = 2 * strain(0, 2);
252 eps[5] = 2 * strain(0, 1);
264 all.row(p) = fun(sigma);
268 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 3, 1>
271 assert(pt.size() ==
size());
272 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 3, 1> res;
276 else if (
size() == 3)
286 std::map<std::string, ParamFunc> res;
288 const int size = this->
size() == 2 ? 3 : 6;
290 for (
int i = 0; i <
size; ++i)
292 for (
int j = i; j <
size; ++j)
294 res[fmt::format(
"C_{}{}", i, j)] = [&elast_tensor, i, j](
const RowVectorNd &,
const RowVectorNd &, double, int) {
295 return elast_tensor(i, j);
304 return compute_energy_aux<double>(data);
311 size(), n_bases, data,
312 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 6, 1>>>(data); },
313 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 8, 1>>>(data); },
314 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 12, 1>>>(data); },
315 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 18, 1>>>(data); },
316 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 24, 1>>>(data); },
317 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 30, 1>>>(data); },
318 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 60, 1>>>(data); },
319 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 81, 1>>>(data); },
320 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, SMALL_N, 1>>>(data); },
321 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, BIG_N, 1>>>(data); },
322 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar1<double, Eigen::VectorXd>>(data); });
329 size(), n_bases, data,
330 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 6, 1>, Eigen::Matrix<double, 6, 6>>>(data); },
331 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 8, 1>, Eigen::Matrix<double, 8, 8>>>(data); },
332 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 12, 1>, Eigen::Matrix<double, 12, 12>>>(data); },
333 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 18, 1>, Eigen::Matrix<double, 18, 18>>>(data); },
334 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 24, 1>, Eigen::Matrix<double, 24, 24>>>(data); },
335 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 30, 1>, Eigen::Matrix<double, 30, 30>>>(data); },
336 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 60, 1>, Eigen::Matrix<double, 60, 60>>>(data); },
337 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 81, 1>, Eigen::Matrix<double, 81, 81>>>(data); },
338 [&](
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); },
339 [&](
const NonLinearAssemblerData &data) {
return compute_energy_aux<DScalar2<double, Eigen::VectorXd, Eigen::MatrixXd>>(data); });
342 template <
typename T>
345 typedef Eigen::Matrix<T, Eigen::Dynamic, 1>
AutoDiffVect;
346 typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3>
AutoDiffGradMat;
355 const int n_pts = data.
da.size();
356 for (
long p = 0; p < n_pts; ++p)
365 std::array<T, 3> eps;
366 eps[0] = strain(0, 0);
367 eps[1] = strain(1, 1);
368 eps[2] = 2 * strain(0, 1);
375 std::array<T, 6> eps;
376 eps[0] = strain(0, 0);
377 eps[1] = strain(1, 1);
378 eps[2] = strain(2, 2);
379 eps[3] = 2 * strain(1, 2);
380 eps[4] = 2 * strain(0, 2);
381 eps[5] = 2 * strain(0, 1);
388 energy += (stress_tensor * strain).trace() * data.
da(p);
ElementAssemblyValues vals
std::vector< Eigen::Triplet< double > > entries
std::string stress() const
virtual void set_size(const int size)
void resize(const int size)
void set_from_entries(const std::vector< double > &entries, const std::string &stress_unit)
void set_from_young_poisson(const double young, const double poisson, const std::string &stress_unit)
double compute_stress(const std::array< double, DIM > &strain, const int j) const
void set_from_lambda_mu(const double lambda, const double mu, const std::string &stress_unit)
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::Matrix< double, Eigen::Dynamic, 1, 0, 9, 1 > assemble(const LinearAssemblerData &data) const override
local assembly function that defines the bilinear form (LHS) computes and returns a single local stif...
double compute_energy(const NonLinearAssemblerData &data) const override
std::map< std::string, ParamFunc > parameters() const override
const ElasticityTensor & elasticity_tensor() const
void add_multimaterial(const int index, const json ¶ms, const Units &units) override
VectorNd compute_rhs(const AutodiffHessianPt &pt) const override
Eigen::MatrixXd assemble_hessian(const NonLinearAssemblerData &data) const override
T compute_energy_aux(const NonLinearAssemblerData &data) const
Eigen::VectorXd assemble_gradient(const NonLinearAssemblerData &data) 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
void set_size(const int size) override
ElasticityTensor elasticity_tensor_
const ElementAssemblyValues & vals
stores the evaluation for that element
const QuadratureVector & da
contains both the quadrature weight and the change of metric in the integral
const int i
first local order
const int j
second local order
const ElementAssemblyValues & vals
const QuadratureVector & da
const basis::ElementBases & bs
const Eigen::MatrixXd & fun
const Eigen::MatrixXd & local_pts
const basis::ElementBases & gbs
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > AutoDiffGradMat
Eigen::Matrix< T, Eigen::Dynamic, 1 > AutoDiffVect
void hooke_3d_function(const AutodiffHessianPt &pt, const assembler::ElasticityTensor &C, Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > &res)
void hooke_2d_function(const AutodiffHessianPt &pt, const assembler::ElasticityTensor &C, Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > &res)
Eigen::MatrixXd pk2_from_cauchy(const Eigen::MatrixXd &stress, const Eigen::MatrixXd &F)
void compute_disp_grad_at_quad(const assembler::NonLinearAssemblerData &data, const AutoDiffVect &local_disp, const int p, const int size, AutoDiffGradMat &def_grad)
Eigen::Matrix< AutodiffScalarHessian, Eigen::Dynamic, 1, 0, 3, 1 > AutodiffHessianPt
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)
void get_local_disp(const assembler::NonLinearAssemblerData &data, const int size, AutoDiffVect &local_disp)
Eigen::MatrixXd pk1_from_cauchy(const Eigen::MatrixXd &stress, const Eigen::MatrixXd &F)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
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)