8#include <ipc/barrier/adaptive_stiffness.hpp>
9#include <ipc/utils/world_bbox_diagonal_length.hpp>
19 const double avg_mass,
20 const bool use_area_weighting,
21 const bool use_improved_max_operator,
22 const bool use_physical_barrier,
23 const bool use_adaptive_barrier_stiffness,
24 const bool is_time_dependent,
25 const bool enable_shape_derivatives,
26 const ipc::BroadPhaseMethod broad_phase_method,
27 const double ccd_tolerance,
28 const int ccd_max_iterations,
29 const double dhat_epsilon_scale,
30 const ipc::NormalCollisions::CollisionSetType collision_set_type,
31 const bool skip_obstacles,
32 std::shared_ptr<ipc::Barrier> barrier) :
ContactForm(collision_mesh, dhat, avg_mass, use_adaptive_barrier_stiffness, is_time_dependent, enable_shape_derivatives, broad_phase_method, ccd_tolerance, ccd_max_iterations, dhat_epsilon_scale),
33 barrier_potential_(barrier
34 ?
ipc::BarrierPotential(barrier, dhat, 1.0, false, false)
35 :
ipc::BarrierPotential(dhat, 1.0, use_physical_barrier))
46 if (collision_set_type != ipc::NormalCollisions::CollisionSetType::IPC)
60 log_and_throw_error(
"Adaptive barrier stiffness is not supported for the selected barrier.");
67 ipc::NormalCollisions nonconvergent_constraints;
69 nonconvergent_constraints.set_use_area_weighting(
false);
70 nonconvergent_constraints.set_use_improved_max_approximator(
false);
71 nonconvergent_constraints.build(
83 double scaling_factor = 0;
84 if (!nonconvergent_constraints.empty())
93 scaling_factor = nonconvergent_potential / convergent_potential;
110 "Setting adaptive barrier stiffness to {} (max barrier stiffness: {})",
149 auto storage = utils::create_thread_storage<Eigen::VectorXd>(Eigen::VectorXd::Zero(num_vertices));
152 Eigen::VectorXd &local_storage = utils::get_local_thread_storage(storage, thread_id);
154 for (size_t i = start; i < end; i++)
157 const double potential = barrier_potential_(collision_set_[i], collision_set_[i].dof(V, E, F));
159 const int n_v = collision_set_[i].num_vertices();
160 const auto vis = collision_set_[i].vertex_ids(E, F);
161 for (int j = 0; j < n_v; j++)
163 assert(0 <= vis[j] && vis[j] < num_vertices);
164 local_storage[vis[j]] += potential / n_v;
169 Eigen::VectorXd out = Eigen::VectorXd::Zero(num_vertices);
170 for (
const auto &local_potential : storage)
172 out += local_potential;
175 Eigen::VectorXd out_full = Eigen::VectorXd::Zero(collision_mesh_.full_num_vertices());
176 for (
int i = 0; i < out.size(); i++)
177 out_full[collision_mesh_.to_full_vertex_id(i)] = out[i];
179 assert(std::abs(value_unweighted(
x) - out_full.sum()) < std::max(1e-10 * out_full.sum(), 1e-10));
184 void BarrierContactForm::first_derivative_unweighted(
const Eigen::VectorXd &
x, Eigen::VectorXd &gradv)
const
186 gradv = barrier_potential_.gradient(collision_set_, collision_mesh_, compute_displaced_surface(
x));
187 gradv = collision_mesh_.to_full_dof(gradv);
190 void BarrierContactForm::second_derivative_unweighted(
const Eigen::VectorXd &
x,
StiffnessMatrix &hessian)
const
194 ipc::PSDProjectionMethod psd_projection_method;
198 psd_projection_method = ipc::PSDProjectionMethod::CLAMP;
202 psd_projection_method = ipc::PSDProjectionMethod::NONE;
205 hessian = barrier_potential_.hessian(collision_set_, collision_mesh_, compute_displaced_surface(
x), psd_projection_method);
206 hessian = collision_mesh_.to_full_dof(hessian);
209 void BarrierContactForm::post_step(
const polysolve::nonlinear::PostStepData &data)
211 const Eigen::MatrixXd displaced_surface = compute_displaced_surface(data.x);
213 const double curr_distance = collision_set_.compute_minimum_distance(collision_mesh_, displaced_surface);
214 if (!std::isinf(curr_distance))
216 const double ratio = sqrt(curr_distance) / dhat();
217 const auto log_level = (ratio < 1e-6) ? spdlog::level::err : ((ratio < 1e-4) ? spdlog::level::warn : spdlog::level::debug);
218 polyfem::logger().log(log_level,
"Minimum distance during solve: {}, dhat: {}", sqrt(curr_distance), dhat());
221 if (data.iter_num == 0)
224 if (use_adaptive_barrier_stiffness_)
226 if (is_time_dependent_)
228 const double prev_barrier_stiffness = barrier_stiffness();
230 barrier_stiffness_ = ipc::update_barrier_stiffness(
231 prev_distance_, curr_distance, max_barrier_stiffness_,
232 barrier_stiffness(), ipc::world_bbox_diagonal_length(displaced_surface),
233 dhat_epsilon_scale_);
235 if (barrier_stiffness() != prev_barrier_stiffness)
238 "updated barrier stiffness from {:g} to {:g} (max barrier stiffness: )",
239 prev_barrier_stiffness, barrier_stiffness(), max_barrier_stiffness_);
249 prev_distance_ = curr_distance;
#define POLYFEM_SCOPED_TIMER(...)
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