PolyFEM
Loading...
Searching...
No Matches
Parametrizations.cpp
Go to the documentation of this file.
2
6#include <polyfem/Common.hpp>
8
9#include <string_view>
10
11namespace polyfem::solver
12{
13 namespace
14 {
15 constexpr std::string_view ERR_STRING =
16 "Please check your variable to simulation and composition chain.";
17
18 void check_from_to(int from, int to, std::string_view name)
19 {
20 // If from != -1, [from, to] implies a range.
21 // range size must > 0.
22 if (from >= 0 && from >= to)
23 {
25 "Invalid composition {}. Reason: [from, to] = [{}, {}] is not a valid range. {}", name, from, to, ERR_STRING);
26 }
27 }
28
29 void check_non_empty(int size, std::string_view name)
30 {
31 if (size <= 0)
33 "Invalid composition {}. Reason: Empty or negative optimization parameter DOF {}. {}", name, size, ERR_STRING);
34 }
35
36 } // namespace
37
38 ExponentialMap::ExponentialMap(const int from, const int to)
39 : from_(from), to_(to)
40 {
41 check_from_to(from, to, "exp");
42 }
43
44 int ExponentialMap::inverse_size(int y_size) const
45 {
46 check_non_empty(y_size, "ExponentialMap::inverse_size");
47 return y_size;
48 }
49
50 int ExponentialMap::size(const int x_size) const
51 {
52 return x_size;
53 }
54
55 Eigen::VectorXd ExponentialMap::inverse_eval(const Eigen::VectorXd &y) const
56 {
57 if (from_ >= 0)
58 {
59 Eigen::VectorXd res = y;
60 res.segment(from_, to_ - from_) = y.segment(from_, to_ - from_).array().log();
61 return res;
62 }
63 else
64 return y.array().log();
65 }
66
67 Eigen::VectorXd ExponentialMap::eval(const Eigen::VectorXd &x) const
68 {
69 if (from_ >= 0)
70 {
71 Eigen::VectorXd y = x;
72 y.segment(from_, to_ - from_) = x.segment(from_, to_ - from_).array().exp();
73 return y;
74 }
75 else
76 return x.array().exp();
77 }
78
79 Eigen::VectorXd ExponentialMap::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
80 {
81 if (from_ >= 0)
82 {
83 Eigen::VectorXd res = grad.array();
84 res.segment(from_, to_ - from_) = x.segment(from_, to_ - from_).array().exp() * grad.segment(from_, to_ - from_).array();
85 return res;
86 }
87 else
88 return x.array().exp() * grad.array();
89 }
90
91 Scaling::Scaling(const double scale, const int from, const int to)
92 : from_(from), to_(to), scale_(scale)
93 {
94 check_from_to(from, to, "scale");
95 }
96
97 int Scaling::inverse_size(int y_size) const
98 {
99 check_non_empty(y_size, "Scaling::inverse_size");
100 return y_size;
101 }
102
103 int Scaling::size(const int x_size) const
104 {
105 return x_size;
106 }
107
108 Eigen::VectorXd Scaling::inverse_eval(const Eigen::VectorXd &y) const
109 {
110 if (from_ >= 0)
111 {
112 Eigen::VectorXd res = y;
113 res.segment(from_, to_ - from_) = y.segment(from_, to_ - from_).array() / scale_;
114 return res;
115 }
116 else
117 return y.array() / scale_;
118 }
119
120 Eigen::VectorXd Scaling::eval(const Eigen::VectorXd &x) const
121 {
122 if (from_ >= 0)
123 {
124 Eigen::VectorXd y = x;
125 y.segment(from_, to_ - from_) = x.segment(from_, to_ - from_).array() * scale_;
126 return y;
127 }
128 else
129 return x.array() * scale_;
130 }
131
132 Eigen::VectorXd Scaling::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
133 {
134 if (from_ >= 0)
135 {
136 Eigen::VectorXd res = grad.array();
137 res.segment(from_, to_ - from_) = scale_ * grad.segment(from_, to_ - from_).array();
138 return res;
139 }
140 else
141 return scale_ * grad.array();
142 }
143
144 PowerMap::PowerMap(const double power, const int from, const int to)
145 : power_(power), from_(from), to_(to)
146 {
147 check_from_to(from, to, "power");
148 }
149
150 int PowerMap::inverse_size(int y_size) const
151 {
152 check_non_empty(y_size, "PowerMap::inverse_size");
153 return y_size;
154 }
155
156 int PowerMap::size(const int x_size) const
157 {
158 return x_size;
159 }
160
161 Eigen::VectorXd PowerMap::inverse_eval(const Eigen::VectorXd &y) const
162 {
163 if (from_ >= 0)
164 {
165 Eigen::VectorXd res = y;
166 res.segment(from_, to_ - from_) = y.segment(from_, to_ - from_).array().pow(1. / power_);
167 return res;
168 }
169 else
170 return y.array().pow(1. / power_);
171 }
172
173 Eigen::VectorXd PowerMap::eval(const Eigen::VectorXd &x) const
174 {
175 if (from_ >= 0)
176 {
177 Eigen::VectorXd y = x;
178 y.segment(from_, to_ - from_) = x.segment(from_, to_ - from_).array().pow(power_);
179 return y;
180 }
181 else
182 return x.array().pow(power_);
183 }
184
185 Eigen::VectorXd PowerMap::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
186 {
187 if (from_ >= 0)
188 {
189 Eigen::VectorXd res = grad;
190 res.segment(from_, to_ - from_) = grad.segment(from_, to_ - from_).array() * x.segment(from_, to_ - from_).array().pow(power_ - 1) * power_;
191 return res;
192 }
193 else
194 return grad.array() * x.array().pow(power_ - 1) * power_;
195 }
196
197 ENu2LambdaMu::ENu2LambdaMu(const bool is_volume)
198 : is_volume_(is_volume)
199 {
200 }
201
202 int ENu2LambdaMu::inverse_size(int y_size) const
203 {
204 check_non_empty(y_size, "E-nu-to-lambda-mu");
205 if (y_size % 2 != 0)
206 {
207 log_and_throw_adjoint_error("Invalid composition E-nu-to-lambda-mu. Reason: Expect output dof be multiple of 2 but instead get {}. {}", y_size, ERR_STRING);
208 }
209 return y_size;
210 }
211
212 int ENu2LambdaMu::size(const int x_size) const
213 {
214 return x_size;
215 }
216
217 Eigen::VectorXd ENu2LambdaMu::inverse_eval(const Eigen::VectorXd &y) const
218 {
219 const int size = y.size() / 2;
220 assert(size * 2 == y.size());
221
222 Eigen::VectorXd x(y.size());
223 for (int i = 0; i < size; i++)
224 {
225 x(i) = convert_to_E(is_volume_, y(i), y(i + size));
226 x(i + size) = convert_to_nu(is_volume_, y(i), y(i + size));
227 }
228
229 return x;
230 }
231
232 Eigen::VectorXd ENu2LambdaMu::eval(const Eigen::VectorXd &x) const
233 {
234 const int size = x.size() / 2;
235 assert(size * 2 == x.size());
236
237 Eigen::VectorXd y;
238 y.setZero(x.size());
239 for (int i = 0; i < size; i++)
240 {
241 y(i) = convert_to_lambda(is_volume_, x(i), x(i + size));
242 y(i + size) = convert_to_mu(x(i), x(i + size));
243 }
244
245 return y;
246 }
247
248 Eigen::VectorXd ENu2LambdaMu::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
249 {
250 const int size = grad.size() / 2;
251 assert(size * 2 == grad.size());
252 assert(size * 2 == x.size());
253
254 Eigen::VectorXd grad_E_nu;
255 grad_E_nu.setZero(grad.size());
256 for (int i = 0; i < size; i++)
257 {
258 const Eigen::Matrix2d jacobian = d_lambda_mu_d_E_nu(is_volume_, x(i), x(i + size));
259 grad_E_nu(i) = grad(i) * jacobian(0, 0) + grad(i + size) * jacobian(1, 0);
260 grad_E_nu(i + size) = grad(i) * jacobian(0, 1) + grad(i + size) * jacobian(1, 1);
261 }
262
263 return grad_E_nu;
264 }
265
266 PerBody2PerNode::PerBody2PerNode(const mesh::Mesh &mesh, const std::vector<basis::ElementBases> &bases, const int n_bases) : mesh_(mesh), bases_(bases), full_size_(n_bases)
267 {
268 reduced_size_ = 0;
269 std::map<int, int> body_id_to_compacted_id;
270 for (int e = 0; e < mesh.n_elements(); e++)
271 {
272 const int body_id = mesh.get_body_id(e);
273 if (!body_id_to_compacted_id.count(body_id))
274 {
275 body_id_to_compacted_id[body_id] = reduced_size_;
277 }
278 }
279 logger().info("{} objects found!", reduced_size_);
280
281 compacted_body_node_num_ = Eigen::VectorXi::Zero(reduced_size_);
282 node_id_to_compacted_body_ = Eigen::VectorXi::Constant(full_size_, -1);
283 for (int e = 0; e < bases.size(); e++)
284 {
285 const int body_id = mesh_.get_body_id(e);
286 const int id = body_id_to_compacted_id.at(body_id);
287 for (const auto &bs : bases[e].bases)
288 {
289 for (const auto &g : bs.global())
290 {
291 if (node_id_to_compacted_body_(g.index) < 0)
292 {
294 node_id_to_compacted_body_(g.index) = id;
295 }
296 else if (node_id_to_compacted_body_(g.index) != id)
297 {
298 log_and_throw_adjoint_error("Same node on different bodies!");
299 }
300 }
301 }
302 }
303 }
304
305 int PerBody2PerNode::inverse_size(int y_size) const
306 {
307 check_non_empty(y_size, "PerBody2PerNode::inverse_size");
308 if (y_size % full_size_ != 0)
309 {
310 log_and_throw_adjoint_error("Invalid composition per-body-to-per-node. Reason: Expect output dof be multiple of mesh node num but instead get mesh node num = {} and output size = {}. {}", full_size_, y_size, ERR_STRING);
311 }
312 int dim = y_size / full_size_;
313 return reduced_size_ * dim;
314 }
315
316 Eigen::VectorXd PerBody2PerNode::inverse_eval(const Eigen::VectorXd &y) const
317 {
318 // Inverse does not exists. Choose average as a good enough alternative.
319
320 Eigen::VectorXd x = Eigen::VectorXd::Zero(inverse_size(y.size()));
321 assert(y.size() % full_size_ == 0);
322 int dim = y.size() / full_size_;
323 for (int i = 0; i < full_size_; i++)
324 {
325 for (int d = 0; d < dim; d++)
326 {
327 x(node_id_to_compacted_body_(i) * dim + d) += y(i * dim + d);
328 }
329 }
330 for (int i = 0; i < reduced_size_; i++)
331 {
332 for (int d = 0; d < dim; d++)
333 {
334 assert(compacted_body_node_num_(i) != 0);
335 x(i * dim + d) /= static_cast<double>(compacted_body_node_num_(i));
336 }
337 }
338
339 return x;
340 }
341
342 Eigen::VectorXd PerBody2PerNode::eval(const Eigen::VectorXd &x) const
343 {
344 Eigen::VectorXd y;
345 y.setZero(size(x.size()));
346 const int dim = x.size() / reduced_size_;
347
348 for (int i = 0; i < full_size_; i++)
349 {
350 for (int d = 0; d < dim; d++)
351 {
352 y(i * dim + d) = x(node_id_to_compacted_body_(i) * dim + d);
353 }
354 }
355
356 return y;
357 }
358
359 int PerBody2PerNode::size(const int x_size) const
360 {
361 assert(x_size % reduced_size_ == 0);
362 return (x_size / reduced_size_) * full_size_;
363 }
364
365 Eigen::VectorXd PerBody2PerNode::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
366 {
367 assert(grad.size() == size(x.size()));
368 Eigen::VectorXd grad_body;
369 grad_body.setZero(x.size());
370 const int dim = x.size() / reduced_size_;
371
372 for (int i = 0; i < full_size_; i++)
373 {
374 for (int d = 0; d < dim; d++)
375 {
376 grad_body(node_id_to_compacted_body_(i) * dim + d) += grad(i * dim + d);
377 }
378 }
379
380 return grad_body;
381 }
382
383 PerBody2PerElem::PerBody2PerElem(const mesh::Mesh &mesh) : mesh_(mesh), full_size_(mesh_.n_elements())
384 {
385 reduced_size_ = 0;
386 std::map<int, int> compacted_body_id_map;
387 for (int e = 0; e < mesh.n_elements(); e++)
388 {
389 const int body_id = mesh.get_body_id(e);
390 if (!compacted_body_id_map.count(body_id))
391 {
392 compacted_body_id_map[body_id] = reduced_size_;
394 }
395 }
396 logger().info("{} objects found!", reduced_size_);
397
398 compacted_body_elem_num_ = Eigen::VectorXi::Zero(reduced_size_);
399 elem_id_to_compacted_body_id_ = Eigen::VectorXi::Constant(full_size_, -1);
400 for (int e = 0; e < mesh.n_elements(); e++)
401 {
402 const int body_id = mesh_.get_body_id(e);
403 const int id = compacted_body_id_map.at(body_id);
406 }
407 }
408
409 int PerBody2PerElem::inverse_size(int y_size) const
410 {
411 check_non_empty(y_size, "PerBody2PerElem::inverse_size");
412 if (y_size % full_size_ != 0)
413 {
414 log_and_throw_adjoint_error("Invalid composition per-body-to-per-elem. Reason: Expect output dof be multiple of mesh element num but instead get mesh element num = {} and output size = {}. {}", full_size_, y_size, ERR_STRING);
415 }
416 int dim = y_size / full_size_;
417 return reduced_size_ * dim;
418 }
419
420 Eigen::VectorXd PerBody2PerElem::inverse_eval(const Eigen::VectorXd &y) const
421 {
422 // Inverse does not exists. Choose average as a good enough alternative.
423
424 Eigen::VectorXd x = Eigen::VectorXd::Zero(inverse_size(y.size()));
425 assert(y.size() % full_size_ == 0);
426 int dim = y.size() / full_size_;
427 for (int e = 0; e < mesh_.n_elements(); e++)
428 {
430 x(Eigen::seq(id, x.size() - 1, reduced_size_)) += y(Eigen::seq(e, y.size() - 1, full_size_));
431 }
432 for (int i = 0; i < reduced_size_; i++)
433 {
434 assert(compacted_body_elem_num_(i) != 0);
435 x(Eigen::seq(i, x.size() - 1, reduced_size_)) /= compacted_body_elem_num_(i);
436 }
437
438 return x;
439 }
440
441 Eigen::VectorXd PerBody2PerElem::eval(const Eigen::VectorXd &x) const
442 {
443 Eigen::VectorXd y;
444 y.setZero(size(x.size()));
445
446 for (int e = 0; e < mesh_.n_elements(); e++)
447 {
448 const auto &id = elem_id_to_compacted_body_id_(e);
449 y(Eigen::seq(e, y.size() - 1, full_size_)) = x(Eigen::seq(id, x.size() - 1, reduced_size_));
450 }
451
452 return y;
453 }
454
455 int PerBody2PerElem::size(const int x_size) const
456 {
457 assert(x_size % reduced_size_ == 0);
458 return (x_size / reduced_size_) * full_size_;
459 }
460
461 Eigen::VectorXd PerBody2PerElem::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
462 {
463 assert(grad.size() == size(x.size()));
464 Eigen::VectorXd grad_body;
465 grad_body.setZero(x.size());
466
467 for (int e = 0; e < mesh_.n_elements(); e++)
468 {
470 grad_body(Eigen::seq(id, x.size() - 1, reduced_size_)) += grad(Eigen::seq(e, grad.size() - 1, full_size_));
471 }
472
473 return grad_body;
474 }
475
476 SliceMap::SliceMap(const int from, const int to, const int total) : from_(from), to_(to), total_(total)
477 {
478 if (to_ - from_ < 0)
479 log_and_throw_adjoint_error("Invalid Slice Map input!");
480 }
481
482 int SliceMap::inverse_size(int y_size) const
483 {
484 if (total_ == -1)
485 {
486 log_and_throw_adjoint_error("SliceMap with unknown total is impossible to inverse!");
487 }
488 if (y_size != to_ - from_)
489 {
490 log_and_throw_adjoint_error("Invalid composition slice. Reason: Output DOF {} and [from, to] = [{}, {}] size mismatch. {}", y_size, from_, to_, ERR_STRING);
491 }
492 return total_;
493 }
494
495 Eigen::VectorXd SliceMap::inverse_eval(const Eigen::VectorXd &y) const
496 {
497 if (total_ == -1)
498 {
499 log_and_throw_adjoint_error("SliceMap with unknown total is impossible to inverse!");
500 }
501 if (y.size() != size(0))
502 {
503 log_and_throw_adjoint_error("Inverse eval on SliceMap is inconsistent in size!");
504 }
505
506 Eigen::VectorXd y_;
507 y_.setZero(total_);
508 y_.segment(from_, to_ - from_) = y;
509 return y_;
510 }
511
512 Eigen::VectorXd SliceMap::eval(const Eigen::VectorXd &x) const
513 {
514 return x.segment(from_, to_ - from_);
515 }
516
517 Eigen::VectorXd SliceMap::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
518 {
519 Eigen::VectorXd grad_full;
520 grad_full.setZero(x.size());
521 grad_full.segment(from_, to_ - from_) = grad;
522 return grad_full;
523 }
524
525 InsertConstantMap::InsertConstantMap(const int size, const double val, const int start_index) : start_index_(start_index)
526 {
527 if (size <= 0)
528 log_and_throw_adjoint_error("Invalid InsertConstantMap input!");
529 values_.setConstant(size, val);
530 }
531
532 InsertConstantMap::InsertConstantMap(const Eigen::VectorXd &values, const int start_index) : start_index_(start_index), values_(values)
533 {
534 }
535
536 int InsertConstantMap::size(const int x_size) const
537 {
538 return x_size + values_.size();
539 }
540
542 {
543 if (y_size < values_.size())
544 {
545 log_and_throw_adjoint_error("Invalid composition append-const. Reason: Output DOF {} is smaller than append size {}. {}", y_size, values_.size(), ERR_STRING);
546 }
547 return y_size - values_.size();
548 }
549
550 Eigen::VectorXd InsertConstantMap::inverse_eval(const Eigen::VectorXd &y) const
551 {
552 if (start_index_ >= 0)
553 {
554 Eigen::VectorXd x(y.size() - values_.size());
555 if (start_index_ > 0)
556 x.head(start_index_) = y.head(start_index_);
557 x.tail(x.size() - start_index_) = y.tail(y.size() - start_index_ - values_.size());
558 return x;
559 }
560 else
561 return y.head(y.size() - values_.size());
562 }
563
564 Eigen::VectorXd InsertConstantMap::eval(const Eigen::VectorXd &x) const
565 {
566 Eigen::VectorXd y;
567 y.setZero(size(x.size()));
568 if (start_index_ >= 0)
569 {
570 if (start_index_ > 0)
571 y.head(start_index_) = x.head(start_index_);
572 y.segment(start_index_, values_.size()) = values_;
573 y.tail(y.size() - start_index_ - values_.size()) = x.tail(x.size() - start_index_);
574 }
575 else
576 y << x, values_;
577
578 return y;
579 }
580
581 Eigen::VectorXd InsertConstantMap::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
582 {
583 assert(x.size() == grad.size() - values_.size());
584 Eigen::VectorXd reduced_grad(grad.size() - values_.size());
585 if (start_index_ >= 0)
586 {
587 if (start_index_ > 0)
588 reduced_grad.head(start_index_) = grad.head(start_index_);
589 reduced_grad.tail(reduced_grad.size() - start_index_) = grad.tail(grad.size() - start_index_ - values_.size());
590 }
591 else
592 reduced_grad = grad.head(grad.size() - values_.size());
593
594 return reduced_grad;
595 }
596
597 LinearFilter::LinearFilter(const mesh::Mesh &mesh, const double radius)
598 {
599 std::vector<Eigen::Triplet<double>> tt_adjacency_list;
600
601 Eigen::MatrixXd barycenters;
602 if (mesh.is_volume())
603 mesh.cell_barycenters(barycenters);
604 else
605 mesh.face_barycenters(barycenters);
606
607 RowVectorNd min, max;
608 mesh.bounding_box(min, max);
609 // TODO: more efficient way
610 for (int i = 0; i < barycenters.rows(); i++)
611 {
612 auto center_i = barycenters.row(i);
613 for (int j = 0; j <= i; j++)
614 {
615 auto center_j = barycenters.row(j);
616 double dist = 0;
617 dist = (center_i - center_j).norm();
618 if (dist < radius)
619 {
620 tt_adjacency_list.emplace_back(i, j, radius - dist);
621 if (i != j)
622 tt_adjacency_list.emplace_back(j, i, radius - dist);
623 }
624 }
625 }
626 tt_radius_adjacency.resize(barycenters.rows(), barycenters.rows());
627 tt_radius_adjacency.setFromTriplets(tt_adjacency_list.begin(), tt_adjacency_list.end());
628
630 for (int i = 0; i < tt_radius_adjacency.rows(); i++)
632 }
633
634 int LinearFilter::inverse_size(int y_size) const
635 {
636 check_non_empty(y_size, "LinearFilter::inverse_size");
637 if (y_size != tt_radius_adjacency.rows())
638 {
639 log_and_throw_adjoint_error("Invalid composition linear-filter. Reason: Output DOF {} and mesh element count {} mismatch. {}", y_size, tt_radius_adjacency.rows(), ERR_STRING);
640 }
641 return y_size;
642 }
643
644 int LinearFilter::size(const int x_size) const
645 {
646 return x_size;
647 }
648
649 Eigen::VectorXd LinearFilter::eval(const Eigen::VectorXd &x) const
650 {
651 assert(x.size() == tt_radius_adjacency.rows());
652 return (tt_radius_adjacency * x).array() / tt_radius_adjacency_row_sum.array();
653 }
654
655 Eigen::VectorXd LinearFilter::inverse_eval(const Eigen::VectorXd &y) const
656 {
657 // No inverse exists. Choose identity as reasonable alternative.
658 return y;
659 }
660
661 Eigen::VectorXd LinearFilter::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
662 {
663 assert(x.size() == tt_radius_adjacency.rows());
664 return (tt_radius_adjacency * grad).array() / tt_radius_adjacency_row_sum.array();
665 }
666
667 ScalarVelocityParametrization::ScalarVelocityParametrization(const double start_val, const double dt) : start_val_(start_val), dt_(dt) {}
668
670 {
671 check_non_empty(y_size, "ScalarVelocityParametrization::inverse_size");
672 return y_size;
673 }
674
675 int ScalarVelocityParametrization::size(const int x_size) const
676 {
677 return x_size;
678 }
679
680 Eigen::VectorXd ScalarVelocityParametrization::inverse_eval(const Eigen::VectorXd &y) const
681 {
682 Eigen::VectorXd x;
683 x.setZero(size(y.size()));
684 x(0) = (y(0) - start_val_) / dt_;
685 for (int i = 1; i < x.size(); ++i)
686 x(i) = (y(i) - y(i - 1)) / dt_;
687 return x;
688 }
689
690 Eigen::VectorXd ScalarVelocityParametrization::eval(const Eigen::VectorXd &x) const
691 {
692 Eigen::VectorXd y;
693 y.setZero(size(x.size()));
694 y(0) = start_val_ + dt_ * x(0);
695 for (int i = 1; i < x.size(); ++i)
696 y(i) = y(i - 1) + dt_ * x(i);
697 return y;
698 }
699
700 Eigen::VectorXd ScalarVelocityParametrization::apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const
701 {
702 assert(x.size() == grad.size());
703
704 Eigen::MatrixXd hess;
705 hess.setZero(x.size(), size(x.size()));
706 for (int i = 0; i < hess.rows(); ++i)
707 for (int j = 0; j <= i; ++j)
708 hess(i, j) = dt_;
709
710 return hess.transpose() * grad;
711 }
712
713} // namespace polyfem::solver
double val
Definition Assembler.cpp:86
int y
int x
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:41
int n_elements() const
utitlity to return the number of elements, cells or faces in 3d and 2d
Definition Mesh.hpp:163
virtual int get_body_id(const int primitive) const
Get the volume selection of an element (cell in 3d, face in 2d)
Definition Mesh.hpp:514
void cell_barycenters(Eigen::MatrixXd &barycenters) const
all cells barycenters
Definition Mesh.cpp:320
virtual void bounding_box(RowVectorNd &min, RowVectorNd &max) const =0
computes the bbox of the mesh
void face_barycenters(Eigen::MatrixXd &barycenters) const
all face barycenters
Definition Mesh.cpp:311
virtual bool is_volume() const =0
checks if mesh is volume
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
int size(const int x_size) const override
Compute DOF of y given DOF of x.
ENu2LambdaMu(const bool is_volume)
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
ExponentialMap(const int from=-1, const int to=-1)
int size(const int x_size) const override
Compute DOF of y given DOF of x.
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
int size(const int x_size) const override
Compute DOF of y given DOF of x.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
InsertConstantMap(const int size=-1, const double val=0, const int start_index=-1)
Eigen::SparseMatrix< double > tt_radius_adjacency
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
LinearFilter(const mesh::Mesh &mesh, const double radius)
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
int size(const int x_size) const override
Compute DOF of y given DOF of x.
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
PerBody2PerElem(const mesh::Mesh &mesh)
Eigen::VectorXi compacted_body_elem_num_
Body num.
int size(const int x_size) const override
Compute DOF of y given DOF of x.
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXi elem_id_to_compacted_body_id_
Number if elements of a body.
int size(const int x_size) const override
Compute DOF of y given DOF of x.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
Eigen::VectorXi compacted_body_node_num_
Body num.
PerBody2PerNode(const mesh::Mesh &mesh, const std::vector< basis::ElementBases > &bases, const int n_bases)
Eigen::VectorXi node_id_to_compacted_body_
Number of nodes of a body.
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
int size(const int x_size) const override
Compute DOF of y given DOF of x.
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
PowerMap(const double power=1, const int from=-1, const int to=-1)
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
ScalarVelocityParametrization(const double start_val, const double dt)
int size(const int x_size) const override
Compute DOF of y given DOF of x.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
Scaling(const double scale, const int from=-1, const int to=-1)
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
int size(const int x_size) const override
Compute DOF of y given DOF of x.
Eigen::VectorXd apply_jacobian(const Eigen::VectorXd &grad, const Eigen::VectorXd &x) const override
Apply jacobian for chain rule.
SliceMap(const int from=-1, const int to=-1, const int total=-1)
Eigen::VectorXd inverse_eval(const Eigen::VectorXd &y) const override
Eval x = f^-1 (y).
int size(const int x_size) const override
Compute DOF of y given DOF of x.
Eigen::VectorXd eval(const Eigen::VectorXd &x) const override
Eval y = f(x).
int inverse_size(int y_size) const override
Compute DOF of x given DOF of y.
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:44
double convert_to_E(const bool is_volume, const double lambda, const double mu)
double convert_to_mu(const double E, const double nu)
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79
double convert_to_nu(const bool is_volume, const double lambda, const double mu)
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Definition Types.hpp:13
double convert_to_lambda(const bool is_volume, const double E, const double nu)
Eigen::Matrix2d d_lambda_mu_d_E_nu(const bool is_volume, const double E, const double nu)