Loading [MathJax]/extensions/tex2jax.js
PolyFEM
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FrictionForm.cpp
Go to the documentation of this file.
1#include "FrictionForm.hpp"
2#include "ContactForm.hpp"
3
6
7namespace polyfem::solver
8{
10 const ipc::CollisionMesh &collision_mesh,
11 const std::shared_ptr<time_integrator::ImplicitTimeIntegrator> time_integrator,
12 const double epsv,
13 const double mu,
14 const ipc::BroadPhaseMethod broad_phase_method,
15 const ContactForm &contact_form,
16 const int n_lagging_iters)
17 : collision_mesh_(collision_mesh),
18 time_integrator_(time_integrator),
19 epsv_(epsv),
20 mu_(mu),
21 broad_phase_method_(broad_phase_method),
22 n_lagging_iters_(n_lagging_iters < 0 ? std::numeric_limits<int>::max() : n_lagging_iters),
23 contact_form_(contact_form),
24 friction_potential_(epsv)
25 {
26 assert(epsv_ > 0);
27 }
28
30 const Eigen::MatrixXd &prev_solution,
31 const Eigen::MatrixXd &solution,
32 const Eigen::MatrixXd &adjoint,
33 const ipc::TangentialCollisions &friction_constraints_set,
34 Eigen::VectorXd &term)
35 {
36 Eigen::MatrixXd U = collision_mesh_.vertices(utils::unflatten(solution, collision_mesh_.dim()));
37 Eigen::MatrixXd U_prev = collision_mesh_.vertices(utils::unflatten(prev_solution, collision_mesh_.dim()));
38
39 // TODO: use the time integration to compute the velocity
40 const Eigen::MatrixXd velocities = (U - U_prev) / time_integrator_->dt();
41
42 StiffnessMatrix hess = -friction_potential_.force_jacobian(
43 friction_constraints_set,
44 collision_mesh_, collision_mesh_.rest_positions(),
45 /*lagged_displacements=*/U_prev, velocities,
48 ipc::FrictionPotential::DiffWRT::REST_POSITIONS);
49
50 // {
51 // Eigen::MatrixXd X = collision_mesh_.rest_positions();
52 // Eigen::VectorXd x = utils::flatten(X);
53 // const double barrier_stiffness = contact_form_.barrier_stiffness();
54 // const double dhat = dhat_;
55 // const double mu = mu_;
56 // const double epsv = epsv_;
57 // const double dt = time_integrator_->dt();
58
59 // Eigen::MatrixXd fgrad;
60 // fd::finite_jacobian(
61 // x, [&](const Eigen::VectorXd &y) -> Eigen::VectorXd
62 // {
63 // Eigen::MatrixXd fd_X = utils::unflatten(y, X.cols());
64
65 // ipc::CollisionMesh fd_mesh(fd_X, collision_mesh_.edges(), collision_mesh_.faces());
66 // fd_mesh.init_area_jacobians();
67
68 // ipc::TangentialCollisions fd_friction_constraints;
69 // ipc::NormalCollisions fd_constraints;
70 // fd_constraints.set_use_convergent_formulation(contact_form_.use_convergent_formulation());
71 // fd_constraints.set_are_shape_derivatives_enabled(true);
72 // fd_constraints.build(fd_mesh, fd_X + U_prev, dhat);
73
74 // fd_friction_constraints.build(
75 // fd_mesh, fd_X + U_prev, fd_constraints, dhat, barrier_stiffness,
76 // mu);
77
78 // return fd_friction_constraints.compute_potential_gradient(fd_mesh, (U - U_prev) / dt, epsv);
79
80 // }, fgrad, fd::AccuracyOrder::SECOND, 1e-8);
81
82 // logger().trace("force shape derivative error {} {}", (fgrad - hess).norm(), hess.norm());
83 // }
84
85 term = collision_mesh_.to_full_dof(hess).transpose() * adjoint;
86 }
87
88 Eigen::MatrixXd FrictionForm::compute_displaced_surface(const Eigen::VectorXd &x) const
89 {
91 }
92
93 Eigen::MatrixXd FrictionForm::compute_surface_velocities(const Eigen::VectorXd &x) const
94 {
95 // In the case of a static problem, the velocity is the displacement
96 const Eigen::VectorXd v = time_integrator_ != nullptr ? time_integrator_->compute_velocity(x) : x;
97 return collision_mesh_.map_displacements(utils::unflatten(v, collision_mesh_.dim()));
98 }
99
100 double FrictionForm::dv_dx() const
101 {
102 return time_integrator_ != nullptr ? time_integrator_->dv_dx() : 1;
103 }
104
109
110 void FrictionForm::first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
111 {
112 const Eigen::VectorXd grad_friction = friction_potential_.gradient(
114 gradv = collision_mesh_.to_full_dof(grad_friction);
115 }
116
117 void FrictionForm::second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const
118 {
119 POLYFEM_SCOPED_TIMER("friction hessian");
120
121 ipc::PSDProjectionMethod psd_projection_method;
122
123 if (project_to_psd_)
124 {
125 psd_projection_method = ipc::PSDProjectionMethod::CLAMP;
126 }
127 else
128 {
129 psd_projection_method = ipc::PSDProjectionMethod::NONE;
130 }
131
132 hessian = dv_dx() * friction_potential_.hessian( //
134
135 hessian = collision_mesh_.to_full_dof(hessian);
136 }
137
138 void FrictionForm::update_lagging(const Eigen::VectorXd &x, const int iter_num)
139 {
140 const Eigen::MatrixXd displaced_surface = compute_displaced_surface(x);
141
142 ipc::NormalCollisions collision_set;
143 // collision_set.set_use_convergent_formulation(contact_form_.use_convergent_formulation());
144 collision_set.set_use_improved_max_approximator(contact_form_.use_improved_max_operator());
145 collision_set.set_use_area_weighting(contact_form_.use_area_weighting());
146
147 collision_set.set_enable_shape_derivatives(contact_form_.enable_shape_derivatives());
148 collision_set.build(
149 collision_mesh_, displaced_surface, contact_form_.dhat(), /*dmin=*/0, broad_phase_method_);
150
152 collision_mesh_, displaced_surface, collision_set,
154 }
155} // namespace polyfem::solver
int x
#define POLYFEM_SCOPED_TIMER(...)
Definition Timer.hpp:10
Form representing the contact potential and forces.
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 barrier_stiffness() const
Get the current barrier stiffness.
bool use_area_weighting() const
Get use_area_weighting.
bool use_improved_max_operator() const
Get use_improved_max_operator.
bool project_to_psd_
If true, the form's second derivative is projected to be positive semidefinite.
Definition Form.hpp:147
const ipc::BroadPhaseMethod broad_phase_method_
Broad-phase method used for distance computation and collision detection.
FrictionForm(const ipc::CollisionMesh &collision_mesh, const std::shared_ptr< time_integrator::ImplicitTimeIntegrator > time_integrator, const double epsv, const double mu, const ipc::BroadPhaseMethod broad_phase_method, const ContactForm &contact_form, const int n_lagging_iters)
Construct a new Friction Form object.
void update_lagging(const Eigen::VectorXd &x, const int iter_num) override
Update lagged fields.
void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &hessian) const override
Compute the second derivative of the value wrt x.
const ipc::CollisionMesh & collision_mesh_
Reference to the collision mesh.
void force_shape_derivative(const Eigen::MatrixXd &prev_solution, const Eigen::MatrixXd &solution, const Eigen::MatrixXd &adjoint, const ipc::TangentialCollisions &friction_constraints_set, Eigen::VectorXd &term)
const std::shared_ptr< time_integrator::ImplicitTimeIntegrator > time_integrator_
Pointer to the time integrator.
Eigen::MatrixXd compute_surface_velocities(const Eigen::VectorXd &x) const
Compute the surface velocities.
const ipc::FrictionPotential friction_potential_
Eigen::MatrixXd compute_displaced_surface(const Eigen::VectorXd &x) const
Compute the displaced positions of the surface nodes.
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
double dv_dx() const
Compute the derivative of the velocities wrt x.
void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
Compute the first derivative of the value wrt x.
const ContactForm & contact_form_
necessary to have the barrier stiffnes, maybe clean me
ipc::TangentialCollisions friction_collision_set_
Lagged friction constraint set.
const double epsv_
Smoothing factor between static and dynamic friction.
const double mu_
Global coefficient of friction.
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:22