13#include <ipc/barrier/adaptive_stiffness.hpp>
14#include <ipc/utils/world_bbox_diagonal_length.hpp>
16#include <igl/writePLY.h>
22 const double avg_mass,
23 const bool use_convergent_formulation,
24 const bool use_adaptive_barrier_stiffness,
25 const bool is_time_dependent,
26 const bool enable_shape_derivatives,
27 const ipc::BroadPhaseMethod broad_phase_method,
28 const double ccd_tolerance,
29 const int ccd_max_iterations)
30 : collision_mesh_(collision_mesh),
32 use_adaptive_barrier_stiffness_(use_adaptive_barrier_stiffness),
34 is_time_dependent_(is_time_dependent),
35 enable_shape_derivatives_(enable_shape_derivatives),
36 broad_phase_method_(broad_phase_method),
37 ccd_tolerance_(ccd_tolerance),
38 ccd_max_iterations_(ccd_max_iterations),
39 barrier_potential_(dhat)
42 assert(ccd_tolerance > 0);
84 ipc::Collisions nonconvergent_constraints;
85 nonconvergent_constraints.set_use_convergent_formulation(
false);
86 nonconvergent_constraints.build(
98 double scaling_factor = 0;
99 if (!nonconvergent_constraints.empty())
108 scaling_factor = nonconvergent_potential / convergent_potential;
125 "Setting adaptive barrier stiffness to {} (max barrier stiffness: {})",
132 static Eigen::MatrixXd cached_displaced_surface;
133 if (cached_displaced_surface.size() == displaced_surface.size() && cached_displaced_surface == displaced_surface)
142 cached_displaced_surface = displaced_surface;
165 auto storage = utils::create_thread_storage<Eigen::VectorXd>(Eigen::VectorXd::Zero(num_vertices));
168 Eigen::VectorXd &local_storage = utils::get_local_thread_storage(storage, thread_id);
170 for (size_t i = start; i < end; i++)
173 const double potential = barrier_potential_(collision_set_[i], collision_set_[i].dof(V, E, F));
175 const int n_v = collision_set_[i].num_vertices();
176 const std::array<long, 4> vis = collision_set_[i].vertex_ids(E, F);
177 for (int j = 0; j < n_v; j++)
179 assert(0 <= vis[j] && vis[j] < num_vertices);
180 local_storage[vis[j]] += potential / n_v;
185 Eigen::VectorXd out = Eigen::VectorXd::Zero(num_vertices);
186 for (
const auto &local_potential : storage)
188 out += local_potential;
191 Eigen::VectorXd out_full = Eigen::VectorXd::Zero(collision_mesh_.full_num_vertices());
192 for (
int i = 0; i < out.size(); i++)
193 out_full[collision_mesh_.to_full_vertex_id(i)] = out[i];
195 assert(std::abs(value_unweighted(
x) - out_full.sum()) < std::max(1e-10 * out_full.sum(), 1e-10));
234 max_step =
candidates_.compute_collision_free_stepsize(
237 max_step = ipc::compute_collision_free_stepsize(
247 Eigen::MatrixXd V_toi = (
V1 -
V0) * max_step +
V0;
251 logger().error(
"Taking max_step results in intersections (max_step={:g})", max_step);
254 const double Linf = (V_toi -
V0).lpNorm<Eigen::Infinity>();
255 if (max_step <= 0 || Linf == 0)
256 log_and_throw_error(
"Unable to find an intersection free step size (max_step={:g} L∞={:g})", max_step, Linf);
258 V_toi = (
V1 -
V0) * max_step +
V0;
285 if (data.iter_num == 0)
305 "updated barrier stiffness from {:g} to {:g} (max barrier stiffness: )",
325 if ((displaced1 - displaced0).lpNorm<Eigen::Infinity>() == 0.0)
337 is_valid = ipc::is_step_collision_free(
#define POLYFEM_SCOPED_TIMER(...)
std::tuple< bool, int, Tree > is_valid(const int dim, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXd &u, const double threshold)
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)
spdlog::logger & logger()
Retrieves the current logger.
void log_and_throw_error(const std::string &msg)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix