15 constexpr std::string_view ERR_STRING =
16 "Please check your variable to simulation and composition chain.";
18 void check_from_to(
int from,
int to, std::string_view name)
22 if (from >= 0 && from >= to)
25 "Invalid composition {}. Reason: [from, to] = [{}, {}] is not a valid range. {}", name, from, to, ERR_STRING);
29 void check_non_empty(
int size, std::string_view name)
33 "Invalid composition {}. Reason: Empty or negative optimization parameter DOF {}. {}", name, size, ERR_STRING);
39 : from_(from), to_(to)
41 check_from_to(from, to,
"exp");
46 check_non_empty(y_size,
"ExponentialMap::inverse_size");
59 Eigen::VectorXd res =
y;
64 return y.array().log();
71 Eigen::VectorXd
y =
x;
76 return x.array().exp();
83 Eigen::VectorXd res = grad.array();
88 return x.array().exp() * grad.array();
92 : from_(from), to_(to), scale_(scale)
94 check_from_to(from, to,
"scale");
99 check_non_empty(y_size,
"Scaling::inverse_size");
112 Eigen::VectorXd res =
y;
124 Eigen::VectorXd
y =
x;
136 Eigen::VectorXd res = grad.array();
141 return scale_ * grad.array();
145 : power_(power), from_(from), to_(to)
147 check_from_to(from, to,
"power");
152 check_non_empty(y_size,
"PowerMap::inverse_size");
165 Eigen::VectorXd res =
y;
170 return y.array().pow(1. /
power_);
177 Eigen::VectorXd
y =
x;
189 Eigen::VectorXd res = grad;
198 : is_volume_(is_volume)
204 check_non_empty(y_size,
"E-nu-to-lambda-mu");
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);
219 const int size =
y.size() / 2;
220 assert(
size * 2 ==
y.size());
222 Eigen::VectorXd
x(
y.size());
223 for (
int i = 0; i <
size; i++)
234 const int size =
x.size() / 2;
235 assert(
size * 2 ==
x.size());
239 for (
int i = 0; i <
size; i++)
250 const int size = grad.size() / 2;
251 assert(
size * 2 == grad.size());
252 assert(
size * 2 ==
x.size());
254 Eigen::VectorXd grad_E_nu;
255 grad_E_nu.setZero(grad.size());
256 for (
int i = 0; i <
size; i++)
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);
269 std::map<int, int> body_id_to_compacted_id;
273 if (!body_id_to_compacted_id.count(body_id))
283 for (
int e = 0; e < bases.size(); e++)
286 const int id = body_id_to_compacted_id.at(body_id);
287 for (
const auto &bs : bases[e].bases)
289 for (
const auto &g : bs.global())
307 check_non_empty(y_size,
"PerBody2PerNode::inverse_size");
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);
320 Eigen::VectorXd
x = Eigen::VectorXd::Zero(
inverse_size(
y.size()));
325 for (
int d = 0; d < dim; d++)
332 for (
int d = 0; d < dim; d++)
345 y.setZero(
size(
x.size()));
350 for (
int d = 0; d < dim; d++)
367 assert(grad.size() ==
size(
x.size()));
368 Eigen::VectorXd grad_body;
369 grad_body.setZero(
x.size());
374 for (
int d = 0; d < dim; d++)
386 std::map<int, int> compacted_body_id_map;
390 if (!compacted_body_id_map.count(body_id))
403 const int id = compacted_body_id_map.at(body_id);
411 check_non_empty(y_size,
"PerBody2PerElem::inverse_size");
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);
424 Eigen::VectorXd
x = Eigen::VectorXd::Zero(
inverse_size(
y.size()));
444 y.setZero(
size(
x.size()));
463 assert(grad.size() ==
size(
x.size()));
464 Eigen::VectorXd grad_body;
465 grad_body.setZero(
x.size());
476 SliceMap::SliceMap(
const int from,
const int to,
const int total) : from_(from), to_(to), total_(total)
501 if (
y.size() !=
size(0))
519 Eigen::VectorXd grad_full;
520 grad_full.setZero(
x.size());
538 return x_size +
values_.size();
547 return y_size -
values_.size();
554 Eigen::VectorXd
x(
y.size() -
values_.size());
561 return y.head(
y.size() -
values_.size());
567 y.setZero(
size(
x.size()));
583 assert(
x.size() == grad.size() -
values_.size());
584 Eigen::VectorXd reduced_grad(grad.size() -
values_.size());
592 reduced_grad = grad.head(grad.size() -
values_.size());
599 std::vector<Eigen::Triplet<double>> tt_adjacency_list;
601 Eigen::MatrixXd barycenters;
610 for (
int i = 0; i < barycenters.rows(); i++)
612 auto center_i = barycenters.row(i);
613 for (
int j = 0; j <= i; j++)
615 auto center_j = barycenters.row(j);
617 dist = (center_i - center_j).norm();
620 tt_adjacency_list.emplace_back(i, j, radius - dist);
622 tt_adjacency_list.emplace_back(j, i, radius - dist);
636 check_non_empty(y_size,
"LinearFilter::inverse_size");
671 check_non_empty(y_size,
"ScalarVelocityParametrization::inverse_size");
683 x.setZero(
size(
y.size()));
685 for (
int i = 1; i <
x.size(); ++i)
686 x(i) = (
y(i) -
y(i - 1)) /
dt_;
693 y.setZero(
size(
x.size()));
695 for (
int i = 1; i <
x.size(); ++i)
696 y(i) =
y(i - 1) +
dt_ *
x(i);
702 assert(
x.size() == grad.size());
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)
710 return hess.transpose() * grad;
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
int n_elements() const
utitlity to return the number of elements, cells or faces in 3d and 2d
virtual int get_body_id(const int primitive) const
Get the volume selection of an element (cell in 3d, face in 2d)
void cell_barycenters(Eigen::MatrixXd &barycenters) const
all cells barycenters
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
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.
Eigen::VectorXd tt_radius_adjacency_row_sum
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).
int reduced_size_
Element num.
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.
int reduced_size_
FE node 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.
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)
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
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)