PolyFEM
Loading...
Searching...
No Matches
PeriodicContactForceDerivative.cpp
Go to the documentation of this file.
2
3#include <Eigen/Core>
5#include <polyfem/State.hpp>
10#include <ipc/collisions/normal/normal_collisions.hpp>
11
12namespace polyfem::solver
13{
15 const PeriodicContactForm &form,
16 const State &state,
17 const DiffCache &diff_cache,
18 const PeriodicMeshToMesh &periodic_mesh_map,
19 const Eigen::VectorXd &periodic_mesh_representation,
20 const ipc::NormalCollisions &contact_set,
21 const Eigen::VectorXd &solution,
22 const Eigen::VectorXd &adjoint_sol,
23 Eigen::VectorXd &term)
24 {
25 const int dim = form.collision_mesh_.dim();
26 const Eigen::MatrixXd displaced_surface = form.compute_displaced_surface(form.single_to_tiled(solution));
27
28 Eigen::VectorXd tiled_term;
29
30 {
31 StiffnessMatrix dq_h = form.collision_mesh_.to_full_dof(form.barrier_potential().shape_derivative(contact_set, form.collision_mesh_, displaced_surface));
32 tiled_term = dq_h.transpose() * form.single_to_tiled(adjoint_sol);
33 }
34
35 {
36 Eigen::VectorXd force;
37 force = form.barrier_potential().gradient(contact_set, form.collision_mesh_, displaced_surface);
38 force = form.collision_mesh_.to_full_dof(force);
39 Eigen::MatrixXd adjoint_affine = utils::unflatten(adjoint_sol.tail(dim * dim), dim);
40 for (int k = 0; k < form.collision_mesh_.num_vertices(); k++)
41 {
42 const int k_full = form.collision_mesh_.to_full_vertex_id(k);
43 tiled_term.segment(k_full * dim, dim) += adjoint_affine.transpose() * force.segment(k_full * dim, dim);
44 }
45 }
46
47 {
48 StiffnessMatrix hessian_full;
49 form.BarrierContactForm::second_derivative_unweighted(form.single_to_tiled(solution), hessian_full);
50 Eigen::VectorXd tmp = form.single_to_tiled(adjoint_sol).transpose() * hessian_full;
51 Eigen::MatrixXd sol_affine = utils::unflatten(solution.tail(dim * dim), dim);
52 for (int k = 0; k < form.collision_mesh_.num_vertices(); k++)
53 {
54 const int k_full = form.collision_mesh_.to_full_vertex_id(k);
55 tiled_term.segment(k_full * dim, dim) += sol_affine.transpose() * tmp.segment(k_full * dim, dim);
56 }
57 }
58
59 // chain rule from tiled to periodic
60 Eigen::VectorXd unit_term;
61 Eigen::MatrixXd affine_term;
62 affine_term.setZero(dim, dim);
63 unit_term.setZero(tiled_term.size());
64 Eigen::MatrixXd affine = utils::unflatten(periodic_mesh_representation.tail(dim * dim), dim).transpose();
65 for (int k = 0; k < form.collision_mesh_.num_vertices(); k++)
66 {
67 const int k_full = form.collision_mesh_.to_full_vertex_id(k);
68 affine_term += tiled_term.segment(k_full * dim, dim) * form.collision_mesh_.rest_positions().row(k);
69 unit_term.segment(k_full * dim, dim) += affine.transpose() * tiled_term.segment(k_full * dim, dim);
70 }
71
72 Eigen::VectorXd single_term =
73 diff_cache.basis_nodes_to_gbasis_nodes() * form.proj.topRows(dim * form.n_single_dof_) * unit_term;
74 single_term = utils::flatten(utils::unflatten(single_term, dim)(state.primitive_to_node(), Eigen::all));
75
76 term.setZero(periodic_mesh_representation.size());
77 for (int i = 0; i < state.n_geom_bases; i++)
78 term.segment(periodic_mesh_map.full_to_periodic(i) * dim, dim).array() += single_term.segment(i * dim, dim).array();
79 term.tail(dim * dim) = Eigen::Map<Eigen::VectorXd>(affine_term.data(), dim * dim, 1);
80
81 term *= form.weight();
82 }
83} // namespace polyfem::solver
Storage for additional data required by differntial code.
Definition DiffCache.hpp:21
const StiffnessMatrix & basis_nodes_to_gbasis_nodes() const
main class that contains the polyfem solver and all its state
Definition State.hpp:113
std::vector< int > primitive_to_node() const
Definition State.cpp:232
int n_geom_bases
number of geometric bases
Definition State.hpp:216
const ipc::BarrierPotential & barrier_potential() const
Eigen::MatrixXd compute_displaced_surface(const Eigen::VectorXd &x) const
Compute the displaced positions of the surface nodes.
double weight() const override
Get the form's multiplicative constant weight.
const ipc::CollisionMesh & collision_mesh_
Collision mesh.
static void force_shape_derivative(const PeriodicContactForm &form, const State &state, const DiffCache &diff_cache, const PeriodicMeshToMesh &periodic_mesh_map, const Eigen::VectorXd &periodic_mesh_representation, const ipc::NormalCollisions &contact_set, const Eigen::VectorXd &solution, const Eigen::VectorXd &adjoint_sol, Eigen::VectorXd &term)
Form representing the contact potential and forces on a periodic mesh This form has a different input...
Eigen::VectorXd single_to_tiled(const Eigen::VectorXd &x) const
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
Eigen::VectorXd flatten(const Eigen::MatrixXd &X)
Flatten rowwises.
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24