PolyFEM
Loading...
Searching...
No Matches
ElasticProblem.cpp
Go to the documentation of this file.
1#include "ElasticProblem.hpp"
2
3#include <iostream>
4
5using namespace Eigen;
6
7namespace polyfem
8{
9 namespace problem
10 {
11 ElasticProblem::ElasticProblem(const std::string &name)
12 : Problem(name)
13 {
14 boundary_ids_ = {1, 3, 5, 6};
15 }
16
17 void ElasticProblem::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
18 {
19 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
20 }
21
22 void ElasticProblem::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
23 {
24 val = Eigen::MatrixXd::Zero(pts.rows(), mesh.dimension());
25
26 for (long i = 0; i < pts.rows(); ++i)
27 {
28 if (mesh.get_boundary_id(global_ids(i)) == 1)
29 val(i, 0) = -0.25;
30 else if (mesh.get_boundary_id(global_ids(i)) == 3)
31 val(i, 0) = 0.25;
32 if (mesh.get_boundary_id(global_ids(i)) == 5)
33 val(i, 1) = -0.25;
34 else if (mesh.get_boundary_id(global_ids(i)) == 6)
35 val(i, 1) = 0.25;
36 }
37 }
38
40 : Problem(name)
41 {
42 boundary_ids_ = {5, 6};
43
44 trans_.resize(2);
45 trans_.setConstant(0.5);
46 }
47
48 void TorsionElasticProblem::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
49 {
50 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
51 }
52
53 void TorsionElasticProblem::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
54 {
55 val = Eigen::MatrixXd::Zero(pts.rows(), mesh.dimension());
56
57 double alpha = n_turns_ * t * 2 * M_PI;
58 Eigen::Matrix2d rot;
59 rot << cos(alpha), -sin(alpha),
60 sin(alpha), cos(alpha);
61
62 for (long i = 0; i < pts.rows(); ++i)
63 {
64 if (mesh.get_boundary_id(global_ids(i)) == boundary_ids_[1])
65 {
66 const Eigen::RowVector3d pt = pts.row(i);
67 Eigen::RowVector2d pt2;
68 pt2 << pt(coordiante_0_), pt(coordiante_1_);
69
70 pt2 -= trans_;
71 pt2 = pt2 * rot;
72 pt2 += trans_;
73
74 val(i, coordiante_0_) = pt2(0) - pt(coordiante_0_);
75 val(i, coordiante_1_) = pt2(1) - pt(coordiante_1_);
76 }
77 }
78 }
79
81 {
82 if (params.contains("axis_coordiante"))
83 {
84 const int coord = params["axis_coordiante"];
85 coordiante_0_ = (coord + 1) % 3;
86 coordiante_1_ = (coord + 2) % 3;
87 }
88
89 if (params.contains("n_turns"))
90 {
91 n_turns_ = params["n_turns"];
92 }
93
94 if (params.contains("fixed_boundary"))
95 {
96 boundary_ids_[0] = params["fixed_boundary"];
97 }
98
99 if (params.contains("turning_boundary"))
100 {
101 boundary_ids_[1] = params["turning_boundary"];
102 }
103
104 if (params.contains("bbox_center"))
105 {
106 auto bbox_center = params["bbox_center"];
107 if (bbox_center.is_array() && bbox_center.size() >= 3)
108 {
109 trans_(0) = bbox_center[coordiante_0_];
110 trans_(1) = bbox_center[coordiante_1_];
111 }
112 }
113 }
114
116 : Problem(name)
117 {
118 boundary_ids_ = {5, 6};
119
120 trans_0_.resize(2);
121 trans_0_.setConstant(0.5);
122
123 trans_1_.resize(2);
124 trans_1_.setConstant(0.5);
125 }
126
127 void DoubleTorsionElasticProblem::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
128 {
129 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
130 }
131
132 void DoubleTorsionElasticProblem::initial_solution(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
133 {
134 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
135 }
136 void DoubleTorsionElasticProblem::initial_velocity(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
137 {
138 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
139 }
140 void DoubleTorsionElasticProblem::initial_acceleration(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
141 {
142 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
143 }
144
145 void DoubleTorsionElasticProblem::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
146 {
147 val = Eigen::MatrixXd::Zero(pts.rows(), mesh.dimension());
148
149 double alpha0 = angular_v0_ * t;
150 double alpha1 = angular_v1_ * t;
151 Eigen::Matrix2d rot0;
152 rot0 << cos(alpha0), -sin(alpha0), sin(alpha0), cos(alpha0);
153
154 Eigen::Matrix2d rot1;
155 rot1 << cos(alpha1), -sin(alpha1), sin(alpha1), cos(alpha1);
156
157 for (long i = 0; i < pts.rows(); ++i)
158 {
159 const Eigen::RowVector3d pt = pts.row(i);
160
161 if (mesh.get_boundary_id(global_ids(i)) == boundary_ids_[0])
162 {
163 Eigen::RowVector2d pt2;
164 pt2 << pt(coordiante_0_[0]), pt(coordiante_0_[1]);
165
166 pt2 -= trans_0_;
167 pt2 = pt2 * rot0;
168 pt2 += trans_0_;
169
170 val(i, coordiante_0_[0]) = pt2(0) - pt(coordiante_0_[0]);
171 val(i, coordiante_0_[1]) = pt2(1) - pt(coordiante_0_[1]);
172 }
173 else if (mesh.get_boundary_id(global_ids(i)) == boundary_ids_[1])
174 {
175 Eigen::RowVector2d pt2;
176 pt2 << pt(coordiante_1_[0]), pt(coordiante_1_[1]);
177
178 pt2 -= trans_1_;
179 pt2 = pt2 * rot1;
180 pt2 += trans_1_;
181
182 val(i, coordiante_1_[0]) = pt2(0) - pt(coordiante_1_[0]);
183 val(i, coordiante_1_[1]) = pt2(1) - pt(coordiante_1_[1]);
184 }
185 }
186 }
187
189 {
190 if (params.contains("axis_coordiante0"))
191 {
192 const int coord = params["axis_coordiante0"];
193 coordiante_0_[0] = (coord + 1) % 3;
194 coordiante_0_[1] = (coord + 2) % 3;
195 }
196
197 if (params.contains("axis_coordiante1"))
198 {
199 const int coord = params["axis_coordiante1"];
200 coordiante_1_[0] = (coord + 1) % 3;
201 coordiante_1_[1] = (coord + 2) % 3;
202 }
203
204 if (params.contains("angular_v0"))
205 {
206 angular_v0_ = params["angular_v0"];
207 }
208
209 if (params.contains("angular_v1"))
210 {
211 angular_v1_ = params["angular_v1"];
212 }
213
214 if (params.contains("turning_boundary0"))
215 {
216 boundary_ids_[0] = params["turning_boundary0"];
217 }
218
219 if (params.contains("turning_boundary1"))
220 {
221 boundary_ids_[1] = params["turning_boundary1"];
222 }
223
224 if (params.contains("bbox_center"))
225 {
226 auto bbox_center = params["bbox_center"];
227 if (bbox_center.is_array() && bbox_center.size() >= 3)
228 {
229 trans_0_(0) = bbox_center[coordiante_0_[0]];
230 trans_0_(1) = bbox_center[coordiante_0_[1]];
231
232 trans_1_(0) = bbox_center[coordiante_1_[0]];
233 trans_1_(1) = bbox_center[coordiante_1_[1]];
234 }
235 }
236 }
237
239 : Problem(name)
240 {
241 boundary_ids_ = {1, 2, 3, 4, 5, 6};
242 }
243
244 void ElasticProblemZeroBC::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
245 {
246 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
247 val.col(1).setConstant(0.5);
248 }
249
250 void ElasticProblemZeroBC::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
251 {
252 val = Eigen::MatrixXd::Zero(pts.rows(), mesh.dimension());
253
254 for (long i = 0; i < pts.rows(); ++i)
255 {
256 if (mesh.get_boundary_id(global_ids(i)) > 0)
257 val.row(i).setZero();
258 }
259 }
260
261 namespace
262 {
263 template <typename T>
264 Eigen::Matrix<T, 2, 1> function(T x, T y, const double t)
265 {
266 Eigen::Matrix<T, 2, 1> res;
267
268 res(0) = t * (y * y * y + x * x + x * y) / 50.;
269 res(1) = t * (3 * x * x * x * x + x * y * y + x) / 50.;
270
271 return res;
272 }
273
274 template <typename T>
275 Eigen::Matrix<T, 3, 1> function(T x, T y, T z, const double t)
276 {
277 Eigen::Matrix<T, 3, 1> res;
278
279 res(0) = t * (x * y + x * x + y * y * y + 6 * z) / 80.;
280 res(1) = t * (z * x - z * z * z + x * y * y + 3 * x * x * x * x) / 80.;
281 res(2) = t * (x * y * z + z * z * y * y - 2 * x) / 80.;
282
283 return res;
284 }
285
286 template <typename T>
287 Eigen::Matrix<T, 2, 1> function_compression(T x, T y, const double t)
288 {
289 Eigen::Matrix<T, 2, 1> res;
290
291 res(0) = -t * (y * y * y + x * x + x * y) / 20.;
292 res(1) = -t * (3 * x * x * x * x + x * y * y + x) / 20.;
293
294 return res;
295 }
296
297 template <typename T>
298 Eigen::Matrix<T, 3, 1> function_compression(T x, T y, T z, const double t)
299 {
300 Eigen::Matrix<T, 3, 1> res;
301
302 res(0) = -t * (x * y + x * x + y * y * y + 6 * z) / 14.;
303 res(1) = -t * (z * x - z * z * z + x * y * y + 3 * x * x * x * x) / 14.;
304 res(2) = -t * (x * y * z + z * z * y * y - 2 * x) / 14.;
305
306 return res;
307 }
308
309 template <typename T>
310 Eigen::Matrix<T, 2, 1> function_quadratic(T x, T y, const double t)
311 {
312 Eigen::Matrix<T, 2, 1> res;
313
314 res(0) = -t * (y * y + x * x + x * y) / 50.;
315 res(1) = -t * (3 * x * x + y) / 50.;
316
317 return res;
318 }
319
320 template <typename T>
321 Eigen::Matrix<T, 3, 1> function_quadratic(T x, T y, T z, const double t)
322 {
323 Eigen::Matrix<T, 3, 1> res;
324
325 res(0) = -t * (y * y + x * x + x * y + z * y) / 50.;
326 res(1) = -t * (3 * x * x + y + z * z) / 50.;
327 res(2) = -t * (x * z + y * y - 2 * z) / 50.;
328
329 return res;
330 }
331
332 template <typename T>
333 Eigen::Matrix<T, 2, 1> function_linear(T x, T y, const double t)
334 {
335 Eigen::Matrix<T, 2, 1> res;
336
337 res(0) = -t * (y + x) / 50.;
338 res(1) = -t * (3 * x + y) / 50.;
339
340 return res;
341 }
342
343 template <typename T>
344 Eigen::Matrix<T, 3, 1> function_linear(T x, T y, T z, const double t)
345 {
346 Eigen::Matrix<T, 3, 1> res;
347
348 res(0) = -t * (y + x + z) / 50.;
349 res(1) = -t * (3 * x + y - z) / 50.;
350 res(2) = -t * (x + y - 2 * z) / 50.;
351
352 return res;
353 }
354
355 template <typename T>
356 void compute_singularity(const T &x, const T &y, Eigen::Matrix<T, -1, 1> &res, const double a, const double mu, const double nu, const double lambda, const double t)
357 {
358 double b1, b2, b3, b4;
359 T r = sqrt(x * x + y * y);
360 T phi = atan2(y, x);
361 T ur, ut;
362
363 b1 = sin(M_PI * a / 2) * ((a - 1) * mu + (1 - 2 * nu) * lambda) * (a - 4 * nu + 3) / cos(M_PI * a / 2) / ((a - 4 * nu + 2) * mu + (1 - 2 * nu) * lambda) / (a + 1);
364 b2 = (a + 4 * nu - 3) / (a + 1);
365 b3 = -sin(M_PI * a / 2) * ((a - 1) * mu + (1 - 2 * nu) * lambda) / cos(M_PI * a / 2) / ((a - 4 * nu + 2) * mu + (1 - 2 * nu) * lambda);
366 b4 = -1;
367
368 ur = -1 / mu * pow(r, a) * (b4 * (a + (4 * nu) - 3) * cos((a - 1) * phi) + b3 * (a + (4 * nu) - 3) * sin((a - 1) * phi) + (b2 * cos((a + 1) * phi) + b1 * sin((a + 1) * phi)) * (a + 1)) / 2;
369 ut = -1 / mu * pow(r, a) * (b3 * (a - (4 * nu) + 3) * cos((a - 1) * phi) - b4 * (a - (4 * nu) + 3) * sin((a - 1) * phi) + (b1 * cos((a + 1) * phi) - b2 * sin((a + 1) * phi)) * (a + 1)) / 2;
370
371 res(0) = 79.17 * t * ur * cos(ut);
372 res(1) = 79.17 * t * ur * sin(ut);
373 }
374
375 template <typename T>
376 Eigen::Matrix<T, -1, 1> function_cantilever(T x, T y, const double t, const double delta, const double E, const double nu, const int dim, const double L, const double D)
377 {
378 Eigen::Matrix<T, -1, 1> res, res1, res2;
379 res.setZero(dim, 1);
380 res1.setZero(dim, 1);
381 res2.setZero(dim, 1);
382 const double lambda = (E * nu) / (1 + nu) / (1 - (dim - 1) * nu);
383 const double mu = E / (2 * (1 + nu));
384
385 // Boundary condition related formulas in Rossel's paper
386 double a = 0.71117293;
387 double P = 100; // force
388 double I = D * D * D / 12; // second moment of area of the cross-section
389
390 // Add 2 singular solutions for an infinite wedge with Dirichlet/Neumann sides
391 compute_singularity(y + delta, x + delta, res1, a, mu, nu, lambda, t);
392 compute_singularity(D - y + delta, x + delta, res2, a, mu, nu, lambda, t);
393 res = res1 + res2;
394
395 // Formulas in Charles's paper
396 res(0) += t * P * (y - D / 2) / (6 * E * I) * ((6 * L - 3 * x) * x + (2 + nu) * ((y - D / 2) * (y - D / 2) - D * D / 4)) / 3;
397 res(1) += -t * P / (6 * E * I) * (3 * nu * (y - D / 2) * (y - D / 2) * (L - x) + (4 + 5 * nu) * D * D * x / 4 + (3 * L - x) * x * x) / 3;
398
399 return res;
400 }
401 } // namespace
402
404 : ProblemWithSolution(name)
405 {
406 }
407
408 VectorNd ElasticProblemExact::eval_fun(const VectorNd &pt, const double t) const
409 {
410 if (pt.size() == 2)
411 return function(pt(0), pt(1), t);
412 else if (pt.size() == 3)
413 return function(pt(0), pt(1), pt(2), t);
414
415 assert(false);
416 return VectorNd(pt.size());
417 }
418
420 {
421 if (pt.size() == 2)
422 return function(pt(0), pt(1), t);
423 else if (pt.size() == 3)
424 return function(pt(0), pt(1), pt(2), t);
425
426 assert(false);
427 return AutodiffGradPt(pt.size());
428 }
429
431 {
432 if (pt.size() == 2)
433 return function(pt(0), pt(1), t);
434 else if (pt.size() == 3)
435 return function(pt(0), pt(1), pt(2), t);
436
437 assert(false);
438 return AutodiffHessianPt(pt.size());
439 }
440
445
447 {
448 if (pt.size() == 2)
449 return function_compression(pt(0), pt(1), t);
450 else if (pt.size() == 3)
451 return function_compression(pt(0), pt(1), pt(2), t);
452
453 assert(false);
454 return VectorNd(pt.size());
455 }
456
458 {
459 if (pt.size() == 2)
460 return function_compression(pt(0), pt(1), t);
461 else if (pt.size() == 3)
462 return function_compression(pt(0), pt(1), pt(2), t);
463
464 assert(false);
465 return AutodiffGradPt(pt.size());
466 }
467
469 {
470 if (pt.size() == 2)
471 return function_compression(pt(0), pt(1), t);
472 else if (pt.size() == 3)
473 return function_compression(pt(0), pt(1), pt(2), t);
474
475 assert(false);
476 return AutodiffHessianPt(pt.size());
477 }
478
483
485 {
486 if (pt.size() == 2)
487 return function_quadratic(pt(0), pt(1), t);
488 else if (pt.size() == 3)
489 return function_quadratic(pt(0), pt(1), pt(2), t);
490
491 assert(false);
492 return VectorNd(pt.size());
493 }
494
496 {
497 if (pt.size() == 2)
498 return function_quadratic(pt(0), pt(1), t);
499 else if (pt.size() == 3)
500 return function_quadratic(pt(0), pt(1), pt(2), t);
501
502 assert(false);
503 return AutodiffGradPt(pt.size());
504 }
505
507 {
508 if (pt.size() == 2)
509 return function_quadratic(pt(0), pt(1), t);
510 else if (pt.size() == 3)
511 return function_quadratic(pt(0), pt(1), pt(2), t);
512
513 assert(false);
514 return AutodiffHessianPt(pt.size());
515 }
516
518 : ProblemWithSolution(name)
519 {
520 }
521
523 {
524 if (pt.size() == 2)
525 return function_linear(pt(0), pt(1), t);
526 else if (pt.size() == 3)
527 return function_linear(pt(0), pt(1), pt(2), t);
528
529 assert(false);
530 return VectorNd(pt.size());
531 }
532
534 {
535 if (pt.size() == 2)
536 return function_linear(pt(0), pt(1), t);
537 else if (pt.size() == 3)
538 return function_linear(pt(0), pt(1), pt(2), t);
539
540 assert(false);
541 return AutodiffGradPt(pt.size());
542 }
543
545 {
546 if (pt.size() == 2)
547 return function_linear(pt(0), pt(1), t);
548 else if (pt.size() == 3)
549 return function_linear(pt(0), pt(1), pt(2), t);
550
551 assert(false);
552 return AutodiffHessianPt(pt.size());
553 }
554
555 GravityProblem::GravityProblem(const std::string &name)
556 : Problem(name)
557 {
558 boundary_ids_ = {4};
559 }
560
562 {
563 if (params.contains("force"))
564 {
565 force_ = params["force"];
566 }
567 }
568
569 void GravityProblem::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
570 {
571 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
572 val.col(1).setConstant(force_);
573 }
574
575 void GravityProblem::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
576 {
577 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
578 }
579
580 void GravityProblem::initial_solution(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
581 {
582 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
583 }
584
585 void GravityProblem::initial_velocity(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
586 {
587 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
588 }
589
590 void GravityProblem::initial_acceleration(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
591 {
592 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
593 }
594
595 WalkProblem::WalkProblem(const std::string &name)
596 : Problem(name)
597 {
598 boundary_ids_ = {1, 2};
599 }
600
601 void WalkProblem::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
602 {
603 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
604 }
605
606 void WalkProblem::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
607 {
608 val = Eigen::MatrixXd::Zero(pts.rows(), mesh.dimension());
609
610 for (long i = 0; i < pts.rows(); ++i)
611 {
612 if (mesh.get_boundary_id(global_ids(i)) == 1)
613 val(i, 2) = 0.2 * sin(t);
614 else if (mesh.get_boundary_id(global_ids(i)) == 2)
615 val(i, 2) = -0.2 * sin(t);
616 }
617 }
618
619 void WalkProblem::initial_solution(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
620 {
621 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
622 }
623
624 void WalkProblem::initial_velocity(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
625 {
626 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
627 }
628
629 void WalkProblem::initial_acceleration(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const
630 {
631 val = Eigen::MatrixXd::Zero(pts.rows(), pts.cols());
632 }
633
635 : Problem(name)
636 {
638 neumann_boundary_ids_.clear();
639
640 boundary_ids_ = {1, 5, 6};
641 neumann_boundary_ids_ = {2, 3, 4};
642
644 E = 210000;
645 nu = 0.3;
646 formulation = "None";
647 length = 1;
648 width = 1 / 3.;
649 }
650
652 {
653 if (params.contains("displacement"))
654 {
655 singular_point_displacement = params["displacement"];
656 }
657 if (params.contains("E"))
658 {
659 E = params["E"];
660 }
661 if (params.contains("nu"))
662 {
663 nu = params["nu"];
664 }
665 if (params.contains("formulation"))
666 {
667 formulation = params["formulation"];
668 }
669 if (params.contains("mesh_size"))
670 {
671 auto size = params["mesh_size"];
672 if (size.is_array())
673 {
674 length = size[0];
675 width = size[1];
676 }
677 else
678 {
679 throw std::invalid_argument("Mesh_size needs to be an array!");
680 }
681 }
682 }
683
684 void ElasticCantileverExact::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
685 {
686 const int size = size_for(pts);
687 val.resize(pts.rows(), size);
688
689 const double lambda = (E * nu) / (1.0 + nu) / (1.0 - (size - 1.0) * nu);
690 const double mu = E / (2.0 * (1.0 + nu));
691
692 for (long i = 0; i < pts.rows(); ++i)
693 {
694 Matrix<double, Dynamic, 1, 0, 3, 1> point(pts.cols()), result;
695 point = pts.row(i);
696
698 AutodiffHessianPt pt(pts.cols());
699
700 for (long d = 0; d < pts.cols(); ++d)
701 pt(d) = AutodiffScalarHessian(d, pts(i, d));
702
703 const auto res = eval_fun(pt, t);
704 val.row(i) = assembler.compute_rhs(res).transpose();
705 }
706 }
707
708 void ElasticCantileverExact::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
709 {
710 exact(pts, t, val);
711 }
712
713 void ElasticCantileverExact::exact(const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
714 {
715 val.resize(pts.rows(), size_for(pts));
716
717 for (long i = 0; i < pts.rows(); ++i)
718 {
719 val.row(i) = eval_fun(VectorNd(pts.row(i)), t);
720 }
721 }
722
723 void ElasticCantileverExact::exact_grad(const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const
724 {
725 const int size = size_for(pts);
726 val.resize(pts.rows(), pts.cols() * size);
727
728 for (long i = 0; i < pts.rows(); ++i)
729 {
731 AutodiffGradPt pt(pts.cols());
732
733 for (long d = 0; d < pts.cols(); ++d)
734 pt(d) = AutodiffScalarGrad(d, pts(i, d));
735
736 const auto res = eval_fun(pt, t);
737
738 for (int m = 0; m < size; ++m)
739 {
740 const auto &tmp = res(m);
741 val.block(i, m * pts.cols(), 1, pts.cols()) = tmp.getGradient().transpose();
742 }
743 }
744 }
745
746 void ElasticCantileverExact::neumann_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &normals, const double t, Eigen::MatrixXd &val) const
747 {
748 val = Eigen::MatrixXd::Zero(pts.rows(), mesh.dimension());
749
750 const double lambda = (E * nu) / (1.0 + nu) / (1.0 - (mesh.dimension() - 1.0) * nu);
751 const double mu = E / 2.0 / (1.0 + nu);
752
753 for (long i = 0; i < pts.rows(); ++i)
754 {
755 const int id = mesh.get_boundary_id(global_ids(i));
756
758 AutodiffHessianPt pt(pts.cols());
759 Eigen::VectorXd neumann_bc_normal = normals.row(i);
760 Eigen::MatrixXd sigma;
761
762 for (long d = 0; d < pts.cols(); ++d)
763 pt(d) = AutodiffScalarHessian(d, pts(i, d));
764
765 AutodiffHessianPt res = eval_fun(pt, t);
766 Eigen::MatrixXd grad_u(mesh.dimension(), mesh.dimension());
767 for (int d1 = 0; d1 < mesh.dimension(); d1++)
768 {
769 for (int d2 = 0; d2 < mesh.dimension(); d2++)
770 {
771 grad_u(d1, d2) = res(d1).getGradient()(d2);
772 }
773 }
774
775 if (formulation == "LinearElasticity")
776 {
777 sigma = mu * (grad_u + grad_u.transpose()) + lambda * grad_u.trace() * Eigen::MatrixXd::Identity(mesh.dimension(), mesh.dimension());
778 }
779 else if (formulation == "NeoHookean")
780 {
781 Eigen::MatrixXd def_grad = Eigen::MatrixXd::Identity(grad_u.rows(), grad_u.cols()) + grad_u;
782 Eigen::MatrixXd FmT = def_grad.inverse().transpose();
783 sigma = mu * (def_grad - FmT) + lambda * std::log(def_grad.determinant()) * FmT;
784 }
785 else
786 {
787 throw std::invalid_argument("No specified formulation in params!");
788 assert(false);
789 }
790
791 val.row(i) = sigma * neumann_bc_normal;
792 }
793 }
794
795 VectorNd ElasticCantileverExact::eval_fun(const VectorNd &pt, const double t) const
796 {
797 return function_cantilever(pt(0), pt(1), t, singular_point_displacement, E, nu, pt.size(), length, width);
798 }
799
801 {
802 return function_cantilever(pt(0), pt(1), t, singular_point_displacement, E, nu, pt.size(), length, width);
803 }
804
806 {
807 return function_cantilever(pt(0), pt(1), t, singular_point_displacement, E, nu, pt.size(), length, width);
808 }
809 } // namespace problem
810} // namespace polyfem
double val
Definition Assembler.cpp:86
int y
int z
int x
virtual VectorNd compute_rhs(const AutodiffHessianPt &pt) const
std::vector< int > boundary_ids_
Definition Problem.hpp:78
std::vector< int > neumann_boundary_ids_
Definition Problem.hpp:79
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:39
virtual int get_boundary_id(const int primitive) const
Get the boundary selection of an element (face in 3d, edge in 2d)
Definition Mesh.hpp:475
int dimension() const
utily for dimension
Definition Mesh.hpp:151
VectorNd eval_fun(const VectorNd &pt, const double t) const override
void initial_solution(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
void initial_acceleration(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
void set_parameters(const json &params) override
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void initial_velocity(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
ElasticCantileverExact(const std::string &name)
void exact(const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void exact_grad(const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
int size_for(const Eigen::MatrixXd &pts) const
void set_parameters(const json &params) override
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void neumann_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &normals, const double t, Eigen::MatrixXd &val) const override
VectorNd eval_fun(const VectorNd &pt, const double t) const
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
VectorNd eval_fun(const VectorNd &pt, const double t) const override
ElasticProblemExact(const std::string &name)
ElasticProblem(const std::string &name)
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
ElasticProblemZeroBC(const std::string &name)
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void set_parameters(const json &params) override
void initial_solution(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void initial_velocity(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
GravityProblem(const std::string &name)
void initial_acceleration(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
VectorNd eval_fun(const VectorNd &pt, const double t) const override
VectorNd eval_fun(const VectorNd &pt, const double t) const override
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void set_parameters(const json &params) override
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
TorsionElasticProblem(const std::string &name)
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
void initial_acceleration(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
void initial_solution(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
void initial_velocity(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &pts, Eigen::MatrixXd &val) const override
WalkProblem(const std::string &name)
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val) const override
Eigen::ArrayXd P(const int m, const int p, const Eigen::ArrayXd &z)
Definition p_n_bases.cpp:42
Eigen::Matrix< AutodiffScalarHessian, Eigen::Dynamic, 1, 0, 3, 1 > AutodiffHessianPt
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > VectorNd
Definition Types.hpp:11
DScalar2< double, Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 >, Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > > AutodiffScalarHessian
nlohmann::json json
Definition Common.hpp:9
DScalar1< double, Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > > AutodiffScalarGrad
Eigen::Matrix< AutodiffScalarGrad, Eigen::Dynamic, 1, 0, 3, 1 > AutodiffGradPt
static void setVariableCount(size_t value)
Set the independent variable count used by the automatic differentiation layer.
Definition autodiff.h:54