20 std::shared_ptr<const varform::DifferentiableVarForm> varform,
21 const bool scale_invariant,
23 const std::vector<int> &surface_selections,
24 const std::vector<int> &active_dims) :
AdjointForm(variable_to_simulations), varform_(std::move(varform)), scale_invariant_(scale_invariant), power_(power), active_dims_(active_dims)
26 const auto &mesh =
varform_->get_mesh();
27 const int dim = mesh.dimension();
28 const int n_verts = mesh.n_vertices();
29 assert(mesh.is_simplicial());
37 surface_ids_ = std::set(surface_selections.begin(), surface_selections.end());
40 std::vector<bool> active_mask;
41 active_mask.assign(n_verts,
false);
42 std::vector<Eigen::Triplet<bool>> T_adj;
44 for (
int b = 0; b < mesh.n_boundary_elements(); b++)
46 const int boundary_id = mesh.get_boundary_id(b);
50 for (
int lv = 0; lv < dim; lv++)
52 active_mask[mesh.boundary_element_vertex(b, lv)] =
true;
55 for (
int lv1 = 0; lv1 < dim; lv1++)
56 for (
int lv2 = 0; lv2 < lv1; lv2++)
58 const int v1 = mesh.boundary_element_vertex(b, lv1);
59 const int v2 = mesh.boundary_element_vertex(b, lv2);
60 T_adj.emplace_back(v2, v1,
true);
61 T_adj.emplace_back(v1, v2,
true);
66 adj.resize(n_verts, n_verts);
67 adj.setFromTriplets(T_adj.begin(), T_adj.end());
69 std::vector<int> degrees(n_verts, 0);
70 for (
int k = 0; k <
adj.outerSize(); ++k)
71 for (Eigen::SparseMatrix<bool, Eigen::RowMajor>::InnerIterator it(
adj, k); it; ++it)
75 L.resize(n_verts, n_verts);
78 std::vector<Eigen::Triplet<double>> T_L;
79 for (
int k = 0; k <
adj.outerSize(); ++k)
83 T_L.emplace_back(k, k, 1);
84 for (Eigen::SparseMatrix<bool, Eigen::RowMajor>::InnerIterator it(
adj, k); it; ++it)
86 assert(it.row() == k);
87 T_L.emplace_back(it.row(), it.col(), -1. / degrees[k]);
90 L.setFromTriplets(T_L.begin(), T_L.end());
91 L.prune([](
int i,
int j,
double val) {
return abs(
val) > 1e-12; });
138 const auto &mesh =
varform_->get_mesh();
139 const int dim = mesh.dimension();
140 const int n_verts = mesh.n_vertices();
142 Eigen::VectorXd grad;
145 grad.setZero(n_verts * dim);
146 for (
int b = 0; b <
adj.rows(); b++)
153 for (Eigen::SparseMatrix<bool, Eigen::RowMajor>::InnerIterator it(
adj, b); it; ++it)
155 assert(it.col() != b);
158 sum_norm +=
x.norm();
159 sum_normalized +=
x.normalized();
165 const double coeff =
power_ * pow(s.norm(),
power_ - 2.) / sum_norm;
167 grad.segment(b * dim, dim) += (s * valence - s.squaredNorm() * sum_normalized) * coeff;
168 for (Eigen::SparseMatrix<bool, Eigen::RowMajor>::InnerIterator it(
adj, b); it; ++it)
169 grad.segment(it.col() * dim, dim) -= (s + s.squaredNorm() * (mesh.point(it.col()) - mesh.point(b)).normalized()) * coeff;
178 Eigen::MatrixXd grad_mat = 2 * (
L.transpose() * (
L *
V));
179 for (
int d = 0; d < dim; d++)
181 grad_mat.col(d).setZero();
Eigen::VectorXd apply_parametrization_jacobian(ParameterType type, const varform::DifferentiableVarForm &target, const Eigen::VectorXd &x, const std::function< Eigen::VectorXd()> &grad) const
Compute parametrization jacobian for all var2sim matching parameter type and output to target varform...