23 std::shared_ptr<const varform::DifferentiableVarForm> varform,
24 const bool scale_invariant,
26 const std::vector<int> &surface_selections,
27 const std::vector<int> &active_dims) :
AdjointForm(variable_to_simulations), varform_(std::move(varform)), scale_invariant_(scale_invariant), power_(power), active_dims_(active_dims)
29 const auto &mesh =
varform_->get_mesh();
30 const int dim = mesh.dimension();
31 const int n_verts = mesh.n_vertices();
32 assert(mesh.is_simplicial());
40 surface_ids_ = std::set(surface_selections.begin(), surface_selections.end());
43 std::vector<bool> active_mask;
44 active_mask.assign(n_verts,
false);
45 std::vector<Eigen::Triplet<bool>> T_adj;
47 for (
int b = 0; b < mesh.n_boundary_elements(); b++)
49 const int boundary_id = mesh.get_boundary_id(b);
53 for (
int lv = 0; lv < dim; lv++)
55 active_mask[mesh.boundary_element_vertex(b, lv)] =
true;
58 for (
int lv1 = 0; lv1 < dim; lv1++)
59 for (
int lv2 = 0; lv2 < lv1; lv2++)
61 const int v1 = mesh.boundary_element_vertex(b, lv1);
62 const int v2 = mesh.boundary_element_vertex(b, lv2);
63 T_adj.emplace_back(v2, v1,
true);
64 T_adj.emplace_back(v1, v2,
true);
69 adj.resize(n_verts, n_verts);
70 adj.setFromTriplets(T_adj.begin(), T_adj.end());
72 std::vector<int> degrees(n_verts, 0);
73 for (
int k = 0; k <
adj.outerSize(); ++k)
74 for (Eigen::SparseMatrix<bool, Eigen::RowMajor>::InnerIterator it(
adj, k); it; ++it)
78 L.resize(n_verts, n_verts);
81 std::vector<Eigen::Triplet<double>> T_L;
82 for (
int k = 0; k <
adj.outerSize(); ++k)
86 T_L.emplace_back(k, k, 1);
87 for (Eigen::SparseMatrix<bool, Eigen::RowMajor>::InnerIterator it(
adj, k); it; ++it)
89 assert(it.row() == k);
90 T_L.emplace_back(it.row(), it.col(), -1. / degrees[k]);
93 L.setFromTriplets(T_L.begin(), T_L.end());
94 L.prune([](
int i,
int j,
double val) {
return abs(
val) > 1e-12; });
141 const auto &mesh =
varform_->get_mesh();
142 const int dim = mesh.dimension();
143 const int n_verts = mesh.n_vertices();
145 Eigen::VectorXd grad;
148 grad.setZero(n_verts * dim);
149 for (
int b = 0; b <
adj.rows(); b++)
156 for (Eigen::SparseMatrix<bool, Eigen::RowMajor>::InnerIterator it(
adj, b); it; ++it)
158 assert(it.col() != b);
161 sum_norm +=
x.norm();
162 sum_normalized +=
x.normalized();
168 const double coeff =
power_ * pow(s.norm(),
power_ - 2.) / sum_norm;
170 grad.segment(b * dim, dim) += (s * valence - s.squaredNorm() * sum_normalized) * coeff;
171 for (Eigen::SparseMatrix<bool, Eigen::RowMajor>::InnerIterator it(
adj, b); it; ++it)
172 grad.segment(it.col() * dim, dim) -= (s + s.squaredNorm() * (mesh.point(it.col()) - mesh.point(b)).normalized()) * coeff;
181 Eigen::MatrixXd grad_mat = 2 * (
L.transpose() * (
L *
V));
182 for (
int d = 0; d < dim; d++)
184 grad_mat.col(d).setZero();
195 std::shared_ptr<const varform::DifferentiableVarForm> varform,
196 const std::vector<int> &volume_selections)
197 :
AdjointForm(variable_to_simulations), varform_(std::move(varform))
200 if (!mesh.is_conforming())
203 int elastic_mappings = 0;
212 if (elastic_mappings != 1)
218 std::set<int> volume_ids(volume_selections.begin(), volume_selections.end());
219 auto is_selected = [&mesh, &volume_ids](
const int element) {
221 return volume_ids.empty() || volume_ids.count(mesh.get_body_id(element)) > 0;
225 if (mesh.is_volume())
227 const auto *mesh3d =
dynamic_cast<const mesh::Mesh3D *
>(&mesh);
228 assert(mesh3d !=
nullptr);
230 for (
int element = 0; element < mesh3d->n_cells(); ++element)
232 if (!is_selected(element))
236 for (
int face = 0; face < mesh3d->n_cell_faces(element); ++face)
243 auto index = mesh3d->get_index_from_element(element, face, 0);
244 int neighbor = mesh3d->switch_element(index).element;
246 if (neighbor >= 0 && is_selected(neighbor))
253 const auto *mesh2d =
dynamic_cast<const mesh::Mesh2D *
>(&mesh);
254 assert(mesh2d !=
nullptr);
256 for (
int element = 0; element < mesh2d->n_faces(); ++element)
258 if (!is_selected(element))
261 for (
int edge = 0; edge < mesh2d->n_face_vertices(element); ++edge)
263 auto index = mesh2d->get_index_from_face(element, edge);
264 int neighbor = mesh2d->switch_face(index).face;
266 if (neighbor >= 0 && is_selected(neighbor))
287 int n_elements =
varform_->get_mesh().n_elements();
289 auto lmd = parameters.head(n_elements);
290 auto mu = parameters.tail(n_elements);
296 double lmd_penalty = 1 - lmd(a) / lmd(b);
297 double mu_penalty = 1 - mu(a) / mu(b);
298 value += lmd_penalty * lmd_penalty + mu_penalty * mu_penalty;
308 gradv = Eigen::VectorXd::Zero(
x.size());
312 int n_elements =
varform_->get_mesh().n_elements();
314 auto lmd = parameters.head(n_elements);
315 auto mu = parameters.tail(n_elements);
316 Eigen::VectorXd grad = Eigen::VectorXd::Zero(parameters.size());
321 double lmd_ratio = lmd(a) / lmd(b);
322 grad(a) += 2 * (lmd_ratio - 1) / lmd(b);
323 grad(b) += 2 * (1 - lmd_ratio) * lmd(a) / (lmd(b) * lmd(b));
325 double mu_ratio = mu(a) / mu(b);
326 grad(n_elements + a) += 2 * (mu_ratio - 1) / mu(b);
327 grad(n_elements + b) += 2 * (1 - mu_ratio) * mu(a) / (mu(b) * mu(b));
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...