8#include <ipc/broad_phase/create_broad_phase.hpp>
9#include <ipc/potentials/potential.hpp>
21 const bool is_time_dependent,
22 const bool enable_shape_derivatives,
23 const ipc::BroadPhaseMethod broad_phase_method,
24 const double ccd_tolerance,
25 const int ccd_max_iterations)
26 : collision_mesh_(collision_mesh),
30 is_time_dependent_(is_time_dependent),
31 enable_shape_derivatives_(enable_shape_derivatives),
32 broad_phase_method_(broad_phase_method),
33 broad_phase_(
ipc::create_broad_phase(broad_phase_method)),
34 tight_inclusion_ccd_(ccd_tolerance, ccd_max_iterations),
35 normal_adhesion_potential_(dhat_p, dhat_a, Y, 1)
39 assert(ccd_tolerance > 0);
63 static Eigen::MatrixXd cached_displaced_surface;
64 if (cached_displaced_surface.size() == displaced_surface.size() && cached_displaced_surface == displaced_surface)
73 cached_displaced_surface = displaced_surface;
96 auto storage = utils::create_thread_storage<Eigen::VectorXd>(Eigen::VectorXd::Zero(num_vertices));
99 Eigen::VectorXd &local_storage = utils::get_local_thread_storage(storage, thread_id);
101 for (size_t i = start; i < end; i++)
104 const double potential = normal_adhesion_potential_(collision_set_[i], collision_set_[i].dof(V, E, F));
106 const int n_v = collision_set_[i].num_vertices();
107 const auto vis = collision_set_[i].vertex_ids(E, F);
108 for (int j = 0; j < n_v; j++)
110 assert(0 <= vis[j] && vis[j] < num_vertices);
111 local_storage[vis[j]] += potential / n_v;
116 Eigen::VectorXd out = Eigen::VectorXd::Zero(num_vertices);
117 for (
const auto &local_potential : storage)
119 out += local_potential;
122 Eigen::VectorXd out_full = Eigen::VectorXd::Zero(collision_mesh_.full_num_vertices());
123 for (
int i = 0; i < out.size(); i++)
124 out_full[collision_mesh_.to_full_vertex_id(i)] = out[i];
126 assert(std::abs(value_unweighted(
x) - out_full.sum()) < std::max(1e-10 * out_full.sum(), 1e-10));
131 void NormalAdhesionForm::first_derivative_unweighted(
const Eigen::VectorXd &
x, Eigen::VectorXd &gradv)
const
133 gradv = normal_adhesion_potential_.gradient(collision_set_, collision_mesh_, compute_displaced_surface(
x));
134 gradv = collision_mesh_.to_full_dof(gradv);
137 void NormalAdhesionForm::second_derivative_unweighted(
const Eigen::VectorXd &
x,
StiffnessMatrix &hessian)
const
141 ipc::PSDProjectionMethod psd_projection_method;
145 psd_projection_method = ipc::PSDProjectionMethod::CLAMP;
149 psd_projection_method = ipc::PSDProjectionMethod::NONE;
152 hessian = normal_adhesion_potential_.hessian(collision_set_, collision_mesh_, compute_displaced_surface(
x), psd_projection_method);
153 hessian = collision_mesh_.to_full_dof(hessian);
156 void NormalAdhesionForm::solution_changed(
const Eigen::VectorXd &new_x)
158 update_collision_set(compute_displaced_surface(new_x));
161 void NormalAdhesionForm::line_search_begin(
const Eigen::VectorXd &x0,
const Eigen::VectorXd &x1)
165 compute_displaced_surface(x0),
166 compute_displaced_surface(x1),
170 use_cached_candidates_ =
true;
173 void NormalAdhesionForm::line_search_end()
176 use_cached_candidates_ =
false;
179 void NormalAdhesionForm::post_step(
const polysolve::nonlinear::PostStepData &data)
181 if (data.iter_num == 0)
184 const Eigen::MatrixXd displaced_surface = compute_displaced_surface(data.x);
186 const double curr_distance = collision_set_.compute_minimum_distance(collision_mesh_, displaced_surface);
188 prev_distance_ = curr_distance;
#define POLYFEM_SCOPED_TIMER(...)
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
void maybe_parallel_for(int size, const std::function< void(int, int, int)> &partial_for)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix