PolyFEM
Loading...
Searching...
No Matches
PeriodicContactForm.cpp
Go to the documentation of this file.
2
4#include <polysolve/nonlinear/PostStepData.hpp>
5
6#include <Eigen/Core>
7#include <Eigen/SparseCore>
8
9#include <cassert>
10#include <vector>
11
12namespace polyfem::solver
13{
14 PeriodicContactForm::PeriodicContactForm(const ipc::CollisionMesh &periodic_collision_mesh,
15 const Eigen::VectorXi &tiled_to_single,
16 const double dhat,
17 const double avg_mass,
18 const bool use_area_weighting,
19 const bool use_improved_max_operator,
20 const bool use_physical_barrier,
21 const bool use_adaptive_barrier_stiffness,
22 const bool is_time_dependent,
23 const bool enable_shape_derivatives,
24 const ipc::BroadPhaseMethod broad_phase_method,
25 const double ccd_tolerance,
26 const int ccd_max_iterations,
27 const double dhat_epsilon_scale) : BarrierContactForm(periodic_collision_mesh, dhat, avg_mass, use_area_weighting, use_improved_max_operator, use_physical_barrier, use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase_method, ccd_tolerance, ccd_max_iterations, dhat_epsilon_scale), tiled_to_single_(tiled_to_single), n_single_dof_(tiled_to_single_.maxCoeff() + 1)
28 {
29 assert(tiled_to_single_.size() == collision_mesh_.full_num_vertices());
30
32
33 // const Eigen::MatrixXd displaced = collision_mesh_.displace_vertices(
34 // Eigen::MatrixXd::Zero(collision_mesh_.full_num_vertices(), collision_mesh_.dim()));
35
36 // io::OBJWriter::write(
37 // "tiled-rest.obj", displaced,
38 // collision_mesh_.edges(), collision_mesh_.faces());
39 }
40
42 {
43 const int dim = collision_mesh_.dim();
44 const auto &boundary_vertices = collision_mesh_.rest_positions();
45
46 std::vector<Eigen::Triplet<double>> entries;
47 for (int i = 0; i < collision_mesh_.num_vertices(); i++)
48 {
49 const int i_full = collision_mesh_.to_full_vertex_id(i);
50 for (int d = 0; d < dim; d++)
51 entries.emplace_back(tiled_to_single_(i_full) * dim + d, i_full * dim + d, 1);
52
53 for (int p = 0; p < dim; p++)
54 for (int q = 0; q < dim; q++)
55 entries.emplace_back(n_single_dof_ * dim + p * dim + q, i_full * dim + p, boundary_vertices(i, q));
56 }
57
58 proj.resize(n_single_dof_ * dim + dim * dim, tiled_to_single_.size() * dim);
59 proj.setZero();
60 proj.setFromTriplets(entries.begin(), entries.end());
61 }
62
63 Eigen::VectorXd PeriodicContactForm::single_to_tiled(const Eigen::VectorXd &x) const
64 {
65 const int dim = collision_mesh_.dim();
66 const auto &boundary_vertices = collision_mesh_.rest_positions();
67 assert(x.size() == n_single_dof_ * dim + dim * dim);
68
69 Eigen::VectorXd tiled_x;
70 tiled_x.setZero(tiled_to_single_.size() * dim);
71 for (int i = 0; i < collision_mesh_.num_vertices(); i++)
72 {
73 const int i_full = collision_mesh_.to_full_vertex_id(i);
74 for (int d = 0; d < dim; d++)
75 tiled_x(i_full * dim + d) += x(tiled_to_single_(i_full) * dim + d);
76
77 for (int p = 0; p < dim; p++)
78 for (int q = 0; q < dim; q++)
79 tiled_x(i_full * dim + p) += x(n_single_dof_ * dim + p * dim + q) * boundary_vertices(i, q);
80 }
81
82 return tiled_x;
83 }
84 Eigen::VectorXd PeriodicContactForm::tiled_to_single_grad(const Eigen::VectorXd &grad) const
85 {
86 const int dim = collision_mesh_.dim();
87 const auto &boundary_vertices = collision_mesh_.rest_positions();
88 assert(grad.size() == tiled_to_single_.size() * dim);
89
90 Eigen::VectorXd reduced_grad;
91 reduced_grad.setZero(n_single_dof_ * dim + dim * dim);
92 for (int i = 0; i < collision_mesh_.num_vertices(); i++)
93 {
94 const int i_full = collision_mesh_.to_full_vertex_id(i);
95 for (int d = 0; d < dim; d++)
96 reduced_grad(tiled_to_single_(i_full) * dim + d) += grad(i_full * dim + d);
97
98 for (int p = 0; p < dim; p++)
99 for (int q = 0; q < dim; q++)
100 reduced_grad(n_single_dof_ * dim + p * dim + q) += boundary_vertices(i, q) * grad(i_full * dim + p);
101 }
102
103 return reduced_grad;
104 }
105
106 void PeriodicContactForm::init(const Eigen::VectorXd &x)
107 {
109 }
110
111 double PeriodicContactForm::value_unweighted(const Eigen::VectorXd &x) const
112 {
114 }
115
116 void PeriodicContactForm::first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
117 {
119 gradv = tiled_to_single_grad(gradv);
120 }
121
122 void PeriodicContactForm::second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const
123 {
124 StiffnessMatrix hessian_full;
126
128 hessian = proj * hessian_full * proj.transpose();
129
130 // const Eigen::MatrixXd displaced = collision_mesh_.displace_vertices(utils::unflatten(single_to_tiled(x), collision_mesh_.dim()));
131
132 // io::OBJWriter::write(
133 // "tiled.obj", displaced,
134 // collision_mesh_.edges(), collision_mesh_.faces());
135 }
136
137 void PeriodicContactForm::update_quantities(const double t, const Eigen::VectorXd &x)
138 {
140 }
141
142 double PeriodicContactForm::max_step_size(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
143 {
145 }
146
147 void PeriodicContactForm::line_search_begin(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1)
148 {
150 }
151
152 void PeriodicContactForm::solution_changed(const Eigen::VectorXd &new_x)
153 {
155 }
156
157 void PeriodicContactForm::post_step(const polysolve::nonlinear::PostStepData &data)
158 {
160 polysolve::nonlinear::PostStepData(
161 data.iter_num, data.solver_info, single_to_tiled(data.x), single_to_tiled(data.grad)));
162 }
163
164 bool PeriodicContactForm::is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
165 {
167 }
168
169 void PeriodicContactForm::update_barrier_stiffness(const Eigen::VectorXd &x, const Eigen::MatrixXd &grad_energy)
170 {
172 }
173} // namespace polyfem::solver
std::vector< Eigen::Triplet< double > > entries
int x
virtual void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
Compute the first derivative of the value wrt x.
virtual void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const override
Compute the second derivative of the value wrt x.
virtual double value_unweighted(const Eigen::VectorXd &x) const override
Compute the contact barrier potential value.
virtual void update_barrier_stiffness(const Eigen::VectorXd &x, const Eigen::MatrixXd &grad_energy) override
Update the barrier stiffness based on the current elasticity energy.
void post_step(const polysolve::nonlinear::PostStepData &data) override
Update fields after a step in the optimization.
virtual void init(const Eigen::VectorXd &x) override
Initialize the form.
virtual double max_step_size(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Determine the maximum step size allowable between the current and next solution.
virtual void solution_changed(const Eigen::VectorXd &new_x) override
Update cached fields upon a change in the solution.
const ipc::CollisionMesh & collision_mesh_
Collision mesh.
virtual void line_search_begin(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) override
Initialize variables used during the line search.
virtual void update_quantities(const double t, const Eigen::VectorXd &x) override
Update time-dependent fields.
virtual bool is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Checks if the step is collision free.
PeriodicContactForm(const ipc::CollisionMesh &periodic_collision_mesh, const Eigen::VectorXi &tiled_to_single, const double dhat, const double avg_mass, const bool use_area_weighting, const bool use_improved_max_operator, const bool use_physical_barrier, const bool use_adaptive_barrier_stiffness, const bool is_time_dependent, const bool enable_shape_derivatives, const ipc::BroadPhaseMethod broad_phase_method, const double ccd_tolerance, const int ccd_max_iterations, const double dhat_epsilon_scale)
Construct a new Contact Form object.
void post_step(const polysolve::nonlinear::PostStepData &data) override
Update fields after a step in the optimization.
Eigen::VectorXd single_to_tiled(const Eigen::VectorXd &x) const
void solution_changed(const Eigen::VectorXd &new_x) override
Update cached fields upon a change in the solution.
bool is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Checks if the step is collision free.
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the contact barrier potential value.
void line_search_begin(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) override
Initialize variables used during the line search.
void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const override
Compute the second derivative of the value wrt x.
double max_step_size(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Determine the maximum step size allowable between the current and next solution.
void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
Compute the first derivative of the value wrt x.
void init(const Eigen::VectorXd &x) override
Initialize the form.
Eigen::VectorXd tiled_to_single_grad(const Eigen::VectorXd &grad) const
void update_quantities(const double t, const Eigen::VectorXd &x) override
Update time-dependent fields.
void update_barrier_stiffness(const Eigen::VectorXd &x, const Eigen::MatrixXd &grad_energy) override
Update the barrier stiffness based on the current elasticity energy.
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24