PolyFEM
Loading...
Searching...
No Matches
SaintVenantElasticity.cpp
Go to the documentation of this file.
2
4
5namespace polyfem::assembler
6{
7 namespace
8 {
9 template <class Matrix>
10 Matrix strain_from_disp_grad(const Matrix &disp_grad)
11 {
12 // Matrix mat = (disp_grad + disp_grad.transpose());
13 Matrix mat = (disp_grad.transpose() * disp_grad + disp_grad + disp_grad.transpose());
14
15 for (int i = 0; i < mat.size(); ++i)
16 mat(i) *= 0.5;
17
18 return mat;
19 }
20 } // namespace
21
25
26 void SaintVenantElasticity::add_multimaterial(const int index, const json &params, const Units &units)
27 {
28 assert(size() == 2 || size() == 3);
29
30 if (!params.contains("elasticity_tensor"))
31 {
32 if (params.count("young"))
33 {
34 if (params["young"].is_number() && params["nu"].is_number())
35 elasticity_tensor_.set_from_young_poisson(params["young"], params["nu"], units.stress());
36 }
37 else if (params.count("E"))
38 {
39 if (params["E"].is_number() && params["nu"].is_number())
40 elasticity_tensor_.set_from_young_poisson(params["E"], params["nu"], units.stress());
41 }
42 else if (params.count("lambda"))
43 {
44 if (params["lambda"].is_number() && params["mu"].is_number())
45 elasticity_tensor_.set_from_lambda_mu(params["lambda"], params["mu"], units.stress());
46 }
47 }
48 else
49 {
50 std::vector<double> entries = params["elasticity_tensor"];
52 }
53 }
54
60
61 template <typename T, unsigned long N>
62 T SaintVenantElasticity::stress(const std::array<T, N> &strain, const int j) const
63 {
64 T res = elasticity_tensor_(j, 0) * strain[0];
65
66 for (unsigned long k = 1; k < N; ++k)
67 res += elasticity_tensor_(j, k) * strain[k];
68
69 return res;
70 }
71
72 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 3, 1>
74 {
75 assert(pt.size() == size());
76 Eigen::Matrix<double, Eigen::Dynamic, 1, 0, 3, 1> res;
77
78 if (size() == 2)
80 else if (size() == 3)
82 else
83 assert(false);
84
85 return res;
86 }
87
88 Eigen::VectorXd
90 {
91 // igl::Timer time; time.start();
92
93 const int n_bases = data.vals.basis_values.size();
94
96 size(), n_bases, data,
97 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 6, 1>>>(data); },
98 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 8, 1>>>(data); },
99 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 12, 1>>>(data); },
100 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 18, 1>>>(data); },
101 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 24, 1>>>(data); },
102 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 30, 1>>>(data); },
103 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 60, 1>>>(data); },
104 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, 81, 1>>>(data); },
105 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, SMALL_N, 1>>>(data); },
106 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::Matrix<double, Eigen::Dynamic, 1, 0, BIG_N, 1>>>(data); },
107 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar1<double, Eigen::VectorXd>>(data); });
108 }
109
110 Eigen::MatrixXd
112 {
113 // igl::Timer time; time.start();
114
115 const int n_bases = data.vals.basis_values.size();
117 size(), n_bases, data,
118 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 6, 1>, Eigen::Matrix<double, 6, 6>>>(data); },
119 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 8, 1>, Eigen::Matrix<double, 8, 8>>>(data); },
120 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 12, 1>, Eigen::Matrix<double, 12, 12>>>(data); },
121 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 18, 1>, Eigen::Matrix<double, 18, 18>>>(data); },
122 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 24, 1>, Eigen::Matrix<double, 24, 24>>>(data); },
123 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 30, 1>, Eigen::Matrix<double, 30, 30>>>(data); },
124 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 60, 1>, Eigen::Matrix<double, 60, 60>>>(data); },
125 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::Matrix<double, 81, 1>, Eigen::Matrix<double, 81, 81>>>(data); },
126 [&](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); },
127 [&](const NonLinearAssemblerData &data) { return compute_energy_aux<DScalar2<double, Eigen::VectorXd, Eigen::MatrixXd>>(data); });
128 }
129
131 const OutputData &data,
132 const int all_size,
133 const ElasticityTensorType &type,
134 Eigen::MatrixXd &all,
135 const std::function<Eigen::MatrixXd(const Eigen::MatrixXd &)> &fun) const
136 {
137 const auto &displacement = data.fun;
138 const auto &local_pts = data.local_pts;
139 const auto &bs = data.bs;
140 const auto &gbs = data.gbs;
141 const auto el_id = data.el_id;
142 const auto t = data.t;
143
144 Eigen::MatrixXd displacement_grad(size(), size());
145
146 assert(displacement.cols() == 1);
147
148 all.resize(local_pts.rows(), all_size);
149
151 vals.compute(el_id, size() == 3, local_pts, bs, gbs);
152
153 for (long p = 0; p < local_pts.rows(); ++p)
154 {
155 compute_diplacement_grad(size(), bs, vals, local_pts, p, displacement, displacement_grad);
156
157 if (type == ElasticityTensorType::F)
158 {
159 all.row(p) = fun(displacement_grad + Eigen::MatrixXd::Identity(size(), size()));
160 continue;
161 }
162
163 Eigen::MatrixXd strain = strain_from_disp_grad(displacement_grad);
164 Eigen::MatrixXd stress_tensor(size(), size());
165
166 if (size() == 2)
167 {
168 std::array<double, 3> eps;
169 eps[0] = strain(0, 0);
170 eps[1] = strain(1, 1);
171 eps[2] = 2 * strain(0, 1);
172
173 stress_tensor << stress(eps, 0), stress(eps, 2),
174 stress(eps, 2), stress(eps, 1);
175 }
176 else
177 {
178 std::array<double, 6> eps;
179 eps[0] = strain(0, 0);
180 eps[1] = strain(1, 1);
181 eps[2] = strain(2, 2);
182 eps[3] = 2 * strain(1, 2);
183 eps[4] = 2 * strain(0, 2);
184 eps[5] = 2 * strain(0, 1);
185
186 stress_tensor << stress(eps, 0), stress(eps, 5), stress(eps, 4),
187 stress(eps, 5), stress(eps, 1), stress(eps, 3),
188 stress(eps, 4), stress(eps, 3), stress(eps, 2);
189 }
190
191 stress_tensor = (Eigen::MatrixXd::Identity(size(), size()) + displacement_grad) * stress_tensor;
192
193 if (type == ElasticityTensorType::PK1)
194 stress_tensor = pk1_from_cauchy(stress_tensor, displacement_grad + Eigen::MatrixXd::Identity(size(), size()));
195 else if (type == ElasticityTensorType::PK2)
196 stress_tensor = pk2_from_cauchy(stress_tensor, displacement_grad + Eigen::MatrixXd::Identity(size(), size()));
197
198 all.row(p) = fun(stress_tensor);
199 }
200 }
201
203 {
204 return compute_energy_aux<double>(data);
205 }
206
207 // Compute \int \sigma : E
208 template <typename T>
210 {
211 typedef Eigen::Matrix<T, Eigen::Dynamic, 1> AutoDiffVect;
212 typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3> AutoDiffGradMat;
213
214 AutoDiffVect local_disp;
215 get_local_disp(data, size(), local_disp);
216
217 AutoDiffGradMat disp_grad(size(), size());
218
219 T energy = T(0.0);
220
221 const int n_pts = data.da.size();
222 for (long p = 0; p < n_pts; ++p)
223 {
224 compute_disp_grad_at_quad(data, local_disp, p, size(), disp_grad);
225
226 AutoDiffGradMat strain = strain_from_disp_grad(disp_grad);
227 AutoDiffGradMat stress_tensor(size(), size());
228
229 if (size() == 2)
230 {
231 std::array<T, 3> eps;
232 eps[0] = strain(0, 0);
233 eps[1] = strain(1, 1);
234 eps[2] = 2 * strain(0, 1);
235
236 stress_tensor << stress(eps, 0), stress(eps, 2),
237 stress(eps, 2), stress(eps, 1);
238 }
239 else
240 {
241 std::array<T, 6> eps;
242 eps[0] = strain(0, 0);
243 eps[1] = strain(1, 1);
244 eps[2] = strain(2, 2);
245 eps[3] = 2 * strain(1, 2);
246 eps[4] = 2 * strain(0, 2);
247 eps[5] = 2 * strain(0, 1);
248
249 stress_tensor << stress(eps, 0), stress(eps, 5), stress(eps, 4),
250 stress(eps, 5), stress(eps, 1), stress(eps, 3),
251 stress(eps, 4), stress(eps, 3), stress(eps, 2);
252 }
253
254 energy += (stress_tensor * strain).trace() * data.da(p);
255 }
256
257 return energy * 0.5;
258 }
259
260 std::map<std::string, Assembler::ParamFunc> SaintVenantElasticity::parameters() const
261 {
262 std::map<std::string, ParamFunc> res;
263
264 const auto &elast_tensor = this->elasticity_tensor_;
265 const int size = this->size() == 2 ? 3 : 6;
266
267 for (int i = 0; i < size; ++i)
268 {
269 for (int j = i; j < size; ++j)
270 {
271 res[fmt::format("C_{}{}", i, j)] = [&elast_tensor, i, j](const RowVectorNd &, const RowVectorNd &, double, int) {
272 return elast_tensor(i, j);
273 };
274 }
275 }
276 return res;
277 }
278} // namespace polyfem::assembler
ElementAssemblyValues vals
Definition Assembler.cpp:22
std::vector< Eigen::Triplet< double > > entries
Eigen::MatrixXd mat
std::string stress() const
Definition Units.hpp:25
virtual void set_size(const int size)
Definition Assembler.hpp:64
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)
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
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,...
const basis::ElementBases & bs
const Eigen::MatrixXd & fun
const Eigen::MatrixXd & local_pts
const basis::ElementBases & gbs
void add_multimaterial(const int index, const json &params, const Units &units) override
T stress(const std::array< T, N > &strain, const int j) const
double compute_energy(const NonLinearAssemblerData &data) const override
T compute_energy_aux(const NonLinearAssemblerData &data) const
Eigen::MatrixXd assemble_hessian(const NonLinearAssemblerData &data) const override
std::map< std::string, ParamFunc > parameters() const override
VectorNd compute_rhs(const AutodiffHessianPt &pt) 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::VectorXd assemble_gradient(const NonLinearAssemblerData &data) const override
Used for test only.
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > AutoDiffGradMat
Eigen::Matrix< T, Eigen::Dynamic, 1 > AutoDiffVect
void saint_venant_3d_function(const AutodiffHessianPt &pt, const assembler::ElasticityTensor &C, Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > &res)
void saint_venant_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)
nlohmann::json json
Definition Common.hpp:9
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
Definition Types.hpp:11
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)