PolyFEM
Loading...
Searching...
No Matches
BarrierForms.cpp
Go to the documentation of this file.
2
4#include <polyfem/Common.hpp>
10
11#include <Eigen/Core>
12
13#include <cassert>
14#include <cstddef>
15#include <memory>
16#include <string>
17#include <utility>
18#include <vector>
19
20namespace polyfem::solver
21{
22 namespace
23 {
24 class QuadraticBarrier : public ipc::Barrier
25 {
26 public:
27 QuadraticBarrier(const double weight = 1) : weight_(weight) {}
28
29 double operator()(const double d, const double dhat) const override
30 {
31 if (d > dhat)
32 return 0;
33 else
34 return weight_ * (d - dhat) * (d - dhat);
35 }
36 double first_derivative(const double d, const double dhat) const override
37 {
38 if (d > dhat)
39 return 0;
40 else
41 return 2 * weight_ * (d - dhat);
42 }
43 double second_derivative(const double d, const double dhat) const override
44 {
45 if (d > dhat)
46 return 0;
47 else
48 return 2 * weight_;
49 }
50 double units(const double dhat) const override
51 {
52 return dhat * dhat;
53 }
54
55 private:
56 const double weight_;
57 };
58
59 } // namespace
60
61 CollisionBarrierForm::CollisionBarrierForm(const VariableToSimulationGroup &variable_to_simulation, std::shared_ptr<const varform::DifferentiableVarForm> varform, const io::ResourceIO &resources, const double dhat, const double dmin)
62 : AdjointForm(variable_to_simulation), varform_(std::move(varform)), dhat_(dhat), dmin_(dmin), barrier_potential_(dhat, 1.0)
63 {
65 varform_->get_mesh(), varform_->primary_space().geometry->n_bases, varform_->primary_space().geometry_basis_list(), varform_->primary_space().geometry_basis_list(),
66 varform_->boundary_state().total_local_boundary, varform_->get_obstacle(), varform_->get_args(), resources,
67 varform_->primary_space().space_in_node_to_node, collision_mesh_);
68
69 Eigen::MatrixXd V;
70 varform_->get_vertices(V);
72
73 broad_phase_method_ = ipc::BroadPhaseMethod::HASH_GRID;
74 }
75
76 double CollisionBarrierForm::value_unweighted(const Eigen::VectorXd &x) const
77 {
78 const Eigen::MatrixXd displaced_surface = collision_mesh_.vertices(utils::unflatten(get_updated_mesh_nodes(x), varform_->get_mesh().dimension()));
79 return barrier_potential_(collision_set, collision_mesh_, displaced_surface);
80 }
81
82 void CollisionBarrierForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
83 {
85 const Eigen::MatrixXd displaced_surface = collision_mesh_.vertices(utils::unflatten(get_updated_mesh_nodes(x), varform_->get_mesh().dimension()));
86 const Eigen::VectorXd grad = collision_mesh_.to_full_dof(barrier_potential_.gradient(collision_set, collision_mesh_, displaced_surface));
88 });
89 }
90
91 void CollisionBarrierForm::solution_changed(const Eigen::VectorXd &x)
92 {
94
95 const Eigen::MatrixXd displaced_surface = collision_mesh_.vertices(utils::unflatten(get_updated_mesh_nodes(x), varform_->get_mesh().dimension()));
96 build_collision_set(displaced_surface);
97 }
98
99 bool CollisionBarrierForm::is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
100 {
101 const Eigen::MatrixXd V0 = utils::unflatten(get_updated_mesh_nodes(x0), varform_->get_mesh().dimension());
102 const Eigen::MatrixXd V1 = utils::unflatten(get_updated_mesh_nodes(x1), varform_->get_mesh().dimension());
103
104 // Skip CCD if the displacement is zero.
105 if ((V1 - V0).lpNorm<Eigen::Infinity>() == 0.0)
106 return true;
107
108 const ipc::TightInclusionCCD tight_inclusion_ccd(1e-6, 1e6);
109 bool is_valid = ipc::is_step_collision_free(
111 collision_mesh_.vertices(V0),
112 collision_mesh_.vertices(V1),
113 dmin_,
114 ipc::create_broad_phase(broad_phase_method_).get(),
115 tight_inclusion_ccd);
116
117 return is_valid;
118 }
119
120 double CollisionBarrierForm::max_step_size(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
121 {
122 const Eigen::MatrixXd V0 = utils::unflatten(get_updated_mesh_nodes(x0), varform_->get_mesh().dimension());
123 const Eigen::MatrixXd V1 = utils::unflatten(get_updated_mesh_nodes(x1), varform_->get_mesh().dimension());
124
125 const ipc::TightInclusionCCD tight_inclusion_ccd(1e-6, 1e6);
126 double max_step = ipc::compute_collision_free_stepsize(
128 collision_mesh_.vertices(V0),
129 collision_mesh_.vertices(V1),
130 dmin_,
131 ipc::create_broad_phase(broad_phase_method_).get(),
132 tight_inclusion_ccd);
133
134 adjoint_logger().info("Objective {}: max step size is {}.", name(), max_step);
135
136 return max_step;
137 }
138
139 void CollisionBarrierForm::build_collision_set(const Eigen::MatrixXd &displaced_surface)
140 {
141 static Eigen::MatrixXd cached_displaced_surface;
142 if (cached_displaced_surface.size() == displaced_surface.size() && cached_displaced_surface == displaced_surface)
143 return;
144
145 collision_set.build(collision_mesh_, displaced_surface, dhat_, dmin_, ipc::create_broad_phase(broad_phase_method_).get());
146
147 cached_displaced_surface = displaced_surface;
148 }
149
150 Eigen::VectorXd CollisionBarrierForm::get_updated_mesh_nodes(const Eigen::VectorXd &x) const
151 {
152 Eigen::VectorXd X = X_init;
155 }
156
158 std::shared_ptr<const varform::DifferentiableVarForm> varform,
159 const io::ResourceIO &resources,
160 const std::vector<int> &boundary_ids,
161 const double dhat,
162 const bool use_log_barrier,
163 const double dmin)
164 : CollisionBarrierForm(variable_to_simulations, std::move(varform), resources, dhat, dmin),
165 boundary_ids_(boundary_ids)
166 {
167 for (const auto &id : boundary_ids_)
168 boundary_ids_to_dof_[id] = std::set<int>();
169
171
172 if (!use_log_barrier)
173 barrier_potential_.set_barrier(std::make_shared<QuadraticBarrier>());
174 }
175
177 {
178 Eigen::MatrixXd node_positions;
179 Eigen::MatrixXi boundary_edges, boundary_triangles;
180 std::vector<Eigen::Triplet<double>> displacement_map_entries;
181 io::OutGeometryData::extract_boundary_mesh(varform_->get_mesh(), varform_->primary_space().geometry->n_bases, varform_->primary_space().geometry_basis_list(), varform_->boundary_state().total_local_boundary,
182 node_positions, boundary_edges, boundary_triangles, displacement_map_entries);
183
184 std::vector<bool> is_on_surface;
185 is_on_surface.resize(node_positions.rows(), false);
186
188 Eigen::MatrixXd points, uv, normals;
189 Eigen::VectorXd weights;
190 Eigen::VectorXi global_primitive_ids;
191 for (const auto &lb : varform_->boundary_state().total_local_boundary)
192 {
193 const int e = lb.element_id();
194 bool has_samples = utils::BoundarySampler::boundary_quadrature(lb, varform_->n_boundary_samples(), varform_->get_mesh(), false, uv, points, normals, weights, global_primitive_ids);
195
196 if (!has_samples)
197 continue;
198
199 const basis::ElementBases &gbs = varform_->primary_space().geometry_basis_list()[e];
200
201 vals.compute(e, varform_->get_mesh().is_volume(), points, gbs, gbs);
202
203 for (int i = 0; i < lb.size(); ++i)
204 {
205 const int primitive_global_id = lb.global_primitive_id(i);
206 const auto nodes = gbs.local_nodes_for_primitive(primitive_global_id, varform_->get_mesh());
207 const int boundary_id = varform_->get_mesh().get_boundary_id(primitive_global_id);
208
209 if (!std::count(boundary_ids_.begin(), boundary_ids_.end(), boundary_id))
210 continue;
211
212 for (long n = 0; n < nodes.size(); ++n)
213 {
214 const assembler::AssemblyValues &v = vals.basis_values[nodes(n)];
215 is_on_surface[v.global[0].index] = true;
216 assert(v.global[0].index < node_positions.rows());
217 boundary_ids_to_dof_[boundary_id].insert(v.global[0].index);
218 }
219 }
220 }
221
222 Eigen::SparseMatrix<double> displacement_map;
223 if (!displacement_map_entries.empty())
224 {
225 displacement_map.resize(node_positions.rows(), varform_->primary_space().geometry->n_bases);
226 displacement_map.setFromTriplets(displacement_map_entries.begin(), displacement_map_entries.end());
227 }
228
229 // Fix boundary edges and boundary triangles to exclude vertices not on triangles
230 Eigen::MatrixXi boundary_edges_alt(0, 2), boundary_triangles_alt(0, 3);
231 {
232 for (int i = 0; i < boundary_edges.rows(); ++i)
233 {
234 bool on_surface = true;
235 for (int j = 0; j < boundary_edges.cols(); ++j)
236 on_surface &= is_on_surface[boundary_edges(i, j)];
237 if (on_surface)
238 {
239 boundary_edges_alt.conservativeResize(boundary_edges_alt.rows() + 1, 2);
240 boundary_edges_alt.row(boundary_edges_alt.rows() - 1) = boundary_edges.row(i);
241 }
242 }
243
244 if (varform_->get_mesh().is_volume())
245 {
246 for (int i = 0; i < boundary_triangles.rows(); ++i)
247 {
248 bool on_surface = true;
249 for (int j = 0; j < boundary_triangles.cols(); ++j)
250 on_surface &= is_on_surface[boundary_triangles(i, j)];
251 if (on_surface)
252 {
253 boundary_triangles_alt.conservativeResize(boundary_triangles_alt.rows() + 1, 3);
254 boundary_triangles_alt.row(boundary_triangles_alt.rows() - 1) = boundary_triangles.row(i);
255 }
256 }
257 }
258 else
259 boundary_triangles_alt.resize(0, 0);
260 }
261
262 collision_mesh_ = ipc::CollisionMesh(is_on_surface,
263 std::vector<bool>(is_on_surface.size(), false),
264 node_positions,
265 boundary_edges_alt,
266 boundary_triangles_alt,
267 displacement_map);
268
269 can_collide_cache_.resize(collision_mesh_.num_vertices(), collision_mesh_.num_vertices());
270 for (int i = 0; i < can_collide_cache_.rows(); ++i)
271 {
272 int dof_idx_i = collision_mesh_.to_full_vertex_id(i);
273 if (!is_on_surface[dof_idx_i])
274 continue;
275 for (int j = 0; j < can_collide_cache_.cols(); ++j)
276 {
277 int dof_idx_j = collision_mesh_.to_full_vertex_id(j);
278 if (!is_on_surface[dof_idx_j])
279 continue;
280
281 bool collision_allowed = true;
282 for (const auto &id : boundary_ids_)
283 if (boundary_ids_to_dof_[id].count(dof_idx_i) && boundary_ids_to_dof_[id].count(dof_idx_j))
284 collision_allowed = false;
285 can_collide_cache_(i, j) = collision_allowed;
286 }
287 }
288
289 collision_mesh_.can_collide = [&](size_t vi, size_t vj) {
290 return (bool)can_collide_cache_(vi, vj);
291 };
292
293 collision_mesh_.init_area_jacobians();
294 }
295
296 DeformedCollisionBarrierForm::DeformedCollisionBarrierForm(const VariableToSimulationGroup &variable_to_simulation, std::shared_ptr<const varform::DifferentiableVarForm> varform, std::shared_ptr<const DiffCache> diff_cache, const io::ResourceIO &resources, const double dhat)
297 : AdjointForm(variable_to_simulation), varform_(std::move(varform)), diff_cache_(std::move(diff_cache)), dhat_(dhat), barrier_potential_(dhat, 1.0)
298 {
299 if (varform_->primary_space().n_bases != varform_->primary_space().geometry->n_bases)
300 log_and_throw_adjoint_error("[{}] Should use linear FE basis!", name());
301
303 varform_->get_mesh(), varform_->primary_space().geometry->n_bases, varform_->primary_space().geometry_basis_list(), varform_->primary_space().geometry_basis_list(),
304 varform_->boundary_state().total_local_boundary, varform_->get_obstacle(), varform_->get_args(), resources,
305 varform_->primary_space().space_in_node_to_node, collision_mesh_);
306
307 Eigen::MatrixXd V;
308 varform_->get_vertices(V);
310
311 broad_phase_method_ = ipc::BroadPhaseMethod::HASH_GRID;
312 }
313
314 double DeformedCollisionBarrierForm::value_unweighted(const Eigen::VectorXd &x) const
315 {
316 const Eigen::MatrixXd displaced_surface = collision_mesh_.vertices(utils::unflatten(get_updated_mesh_nodes(x), varform_->get_mesh().dimension()));
317
318 return barrier_potential_(collision_set, collision_mesh_, displaced_surface);
319 }
320
321 void DeformedCollisionBarrierForm::compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
322 {
324 const Eigen::MatrixXd displaced_surface = collision_mesh_.vertices(utils::unflatten(get_updated_mesh_nodes(x), varform_->get_mesh().dimension()));
325 const Eigen::VectorXd grad = collision_mesh_.to_full_dof(barrier_potential_.gradient(collision_set, collision_mesh_, displaced_surface));
327 });
328 }
329
331 {
333
334 const Eigen::MatrixXd displaced_surface = collision_mesh_.vertices(utils::unflatten(get_updated_mesh_nodes(x), varform_->get_mesh().dimension()));
335 build_collision_set(displaced_surface);
336 }
337
338 bool DeformedCollisionBarrierForm::is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
339 {
340 // const Eigen::MatrixXd V0 = utils::unflatten(get_updated_mesh_nodes(x0), varform_->get_mesh().dimension());
341 // const Eigen::MatrixXd V1 = utils::unflatten(get_updated_mesh_nodes(x1), varform_->get_mesh().dimension());
342
343 // // Skip CCD if the displacement is zero.
344 // if ((V1 - V0).lpNorm<Eigen::Infinity>() == 0.0)
345 // return true;
346
347 // bool is_valid = ipc::is_step_collision_free(
348 // collision_mesh_,
349 // collision_mesh_.vertices(V0),
350 // collision_mesh_.vertices(V1),
351 // broad_phase_method_,
352 // 1e-6, 1e6);
353
354 return true; // is_valid;
355 }
356
357 double DeformedCollisionBarrierForm::max_step_size(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const
358 {
359 // const Eigen::MatrixXd V0 = utils::unflatten(get_updated_mesh_nodes(x0), varform_->get_mesh().dimension());
360 // const Eigen::MatrixXd V1 = utils::unflatten(get_updated_mesh_nodes(x1), varform_->get_mesh().dimension());
361
362 // double max_step = ipc::compute_collision_free_stepsize(
363 // collision_mesh_,
364 // collision_mesh_.vertices(V0),
365 // collision_mesh_.vertices(V1),
366 // broad_phase_method_, 1e-6, 1e6);
367
368 return 1; // max_step;
369 }
370
371 void DeformedCollisionBarrierForm::build_collision_set(const Eigen::MatrixXd &displaced_surface)
372 {
373 static Eigen::MatrixXd cached_displaced_surface;
374 if (cached_displaced_surface.size() == displaced_surface.size() && cached_displaced_surface == displaced_surface)
375 return;
376
377 collision_set.build(collision_mesh_, displaced_surface, dhat_, 0, ipc::create_broad_phase(broad_phase_method_).get());
378
379 cached_displaced_surface = displaced_surface;
380 }
381
382 Eigen::VectorXd DeformedCollisionBarrierForm::get_updated_mesh_nodes(const Eigen::VectorXd &x) const
383 {
384 Eigen::VectorXd X = X_init;
387 }
388
390 const VariableToSimulationGroup &variable_to_simulations,
391 std::shared_ptr<const varform::DifferentiableVarForm> varform,
392 std::shared_ptr<const DiffCache> diff_cache,
393 const json &args)
394 : StaticForm(variable_to_simulations),
395 varform_(std::move(varform)),
396 diff_cache_(std::move(diff_cache)),
397 params_(varform_->get_args()["contact"]["dhat"], varform_->get_args()["contact"]["alpha_t"], 0, varform_->get_args()["contact"]["alpha_n"], 0, varform_->get_mesh().is_volume() ? 2 : 1),
398 potential_(params_)
399 {
400 auto tmp_ids = args["surface_selection"].get<std::vector<int>>();
401 boundary_ids_ = std::set(tmp_ids.begin(), tmp_ids.end());
402
404 }
405
407 {
408 // Deep copy and change the can_collide() function
409 collision_mesh_ = varform_->collision_mesh();
410
411 // const int num_fe_nodes = varform_->primary_space().n_bases - varform_->obstacle.n_vertices();
412
413 // collision_mesh_.can_collide = [this, num_fe_nodes](size_t vi, size_t vj) {
414 // return this->collision_mesh()_.to_full_vertex_id(vi) >= num_fe_nodes || this->collision_mesh()_.to_full_vertex_id(vj) >= num_fe_nodes;
415 // };
416
417 std::vector<int> is_obstacle(varform_->primary_space().n_bases);
418 for (int e = 0; e < varform_->primary_space().basis_list().size(); e++)
419 {
420 const auto &b = varform_->primary_space().basis_list()[e];
421 if (varform_->get_mesh().get_body_id(e) == 1)
422 for (const auto &bs : b.bases)
423 {
424 for (const auto &g : bs.global())
425 {
426 is_obstacle[g.index] = true;
427 }
428 }
429 }
430
431 collision_mesh_.can_collide = [this, is_obstacle](size_t vi, size_t vj) {
432 return is_obstacle[this->collision_mesh_.to_full_vertex_id(vi)] || is_obstacle[this->collision_mesh_.to_full_vertex_id(vj)];
433 };
434 }
435
436 ipc::SmoothCollisions SmoothContactForceForm::get_smooth_collision_set(const Eigen::MatrixXd &displaced_surface)
437 {
438 ipc::SmoothCollisions collisions;
439 const auto smooth_contact = dynamic_cast<const SmoothContactForm *>(varform_->solve_data()->contact_form.get());
440 collisions.build(collision_mesh_, displaced_surface, smooth_contact->get_params(), smooth_contact->using_adaptive_dhat(), smooth_contact->get_broad_phase().get());
441 return collisions;
442 }
443
444 double SmoothContactForceForm::value_unweighted_step(const int time_step, const Eigen::VectorXd &x) const
445 {
446 assert(varform_->solve_data()->contact_form != nullptr);
447
448 const Eigen::MatrixXd displaced_surface = collision_mesh_.displace_vertices(utils::unflatten(diff_cache_->u(time_step), collision_mesh_.dim()));
449
450 Eigen::VectorXd forces = collision_mesh_.to_full_dof(potential_.gradient(collisions_, collision_mesh_, displaced_surface));
451
452 // return forces.squaredNorm();
453
454 Eigen::VectorXd coeff(forces.size());
455 coeff.setZero();
456 coeff(Eigen::seq(1, coeff.size(), collision_mesh_.dim())).array() = 1;
457 return (coeff.array() * forces.array()).matrix().squaredNorm() / 2;
458 }
459
460 Eigen::VectorXd SmoothContactForceForm::compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const
461 {
462 assert(varform_->solve_data()->contact_form != nullptr);
463
464 const Eigen::MatrixXd displaced_surface = collision_mesh_.displace_vertices(utils::unflatten(diff_cache_->u(time_step), collision_mesh_.dim()));
465
466 Eigen::VectorXd forces = potential_.gradient(collisions_, collision_mesh_, displaced_surface);
467 forces = collision_mesh_.to_full_dof(forces);
468
469 StiffnessMatrix hessian = potential_.hessian(collisions_, collision_mesh_, displaced_surface, ipc::PSDProjectionMethod::NONE);
470 hessian = collision_mesh_.to_full_dof(hessian);
471
472 Eigen::VectorXd coeff(forces.size());
473 coeff.setZero();
474 coeff(Eigen::seq(1, coeff.size(), collision_mesh_.dim())).array() = 1;
475 return weight() * (hessian * (coeff.array() * forces.array()).matrix());
476 }
477
478 void SmoothContactForceForm::compute_partial_gradient_step(const int time_step, const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const
479 {
480 assert(varform_->solve_data()->contact_form != nullptr);
481
482 const Eigen::MatrixXd displaced_surface = collision_mesh_.displace_vertices(utils::unflatten(diff_cache_->u(time_step), collision_mesh_.dim()));
483
484 Eigen::VectorXd forces = potential_.gradient(collisions_, collision_mesh_, displaced_surface);
485 forces = collision_mesh_.to_full_dof(forces);
486
487 StiffnessMatrix hessian = potential_.hessian(collisions_, collision_mesh_, displaced_surface, ipc::PSDProjectionMethod::NONE);
488 hessian = collision_mesh_.to_full_dof(hessian);
489
491 // Eigen::VectorXd grads = 2 * hessian.transpose() * forces;
492
493 Eigen::VectorXd coeff(forces.size());
494 coeff.setZero();
495 coeff(Eigen::seq(1, coeff.size(), collision_mesh_.dim())).array() = 1;
496 Eigen::VectorXd grads = (hessian * (coeff.array() * forces.array()).matrix());
497
498 grads = diff_cache_->basis_nodes_to_gbasis_nodes() * grads;
500 });
501 }
502
503 void SmoothContactForceForm::solution_changed_step(const int time_step, const Eigen::VectorXd &x)
504 {
506 const Eigen::MatrixXd displaced_surface = collision_mesh_.displace_vertices(utils::unflatten(diff_cache_->u(time_step), collision_mesh_.dim()));
507 collisions_ = get_smooth_collision_set(displaced_surface);
508 }
509} // namespace polyfem::solver
int V
ElementAssemblyValues vals
Definition Assembler.cpp:26
const double weight_
std::vector< std::pair< int, double > > weights
int x
Storage for additional data required by differntial code.
Definition DiffCache.hpp:22
stores per local bases evaluations
std::vector< basis::Local2Global > global
stores per element basis values at given quadrature points and geometric mapping
Stores the basis functions for a given element in a mesh (facet in 2d, cell in 3d).
Eigen::VectorXi local_nodes_for_primitive(const int local_index, const mesh::Mesh &mesh) const
static void extract_boundary_mesh(const mesh::Mesh &mesh, const int n_bases, const std::vector< basis::ElementBases > &bases, const std::vector< mesh::LocalBoundary > &total_local_boundary, Eigen::MatrixXd &node_positions, Eigen::MatrixXi &boundary_edges, Eigen::MatrixXi &boundary_triangles, std::vector< Eigen::Triplet< double > > &displacement_map_entries)
extracts the boundary mesh
Definition OutData.cpp:737
Read-only interface to a hierarchical collection of simulation resources.
virtual void solution_changed(const Eigen::VectorXd &new_x) override
Update cached fields upon a change in the solution.
const VariableToSimulationGroup variable_to_simulations_
ipc::BarrierPotential barrier_potential_
std::string name() const override
void build_collision_set(const Eigen::MatrixXd &displaced_surface)
ipc::BroadPhaseMethod broad_phase_method_
CollisionBarrierForm(const VariableToSimulationGroup &variable_to_simulation, std::shared_ptr< const varform::DifferentiableVarForm > varform, const io::ResourceIO &resources, const double dhat, const double dmin=0)
bool is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Checks if the step is collision free.
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 compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
void solution_changed(const Eigen::VectorXd &x) override
Update cached fields upon a change in the solution.
std::shared_ptr< const varform::DifferentiableVarForm > varform_
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
Eigen::VectorXd get_updated_mesh_nodes(const Eigen::VectorXd &x) const
bool is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Checks if the step is collision free.
std::shared_ptr< const DiffCache > diff_cache_
void compute_partial_gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
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.
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
const ipc::BarrierPotential barrier_potential_
void build_collision_set(const Eigen::MatrixXd &displaced_surface)
Eigen::VectorXd get_updated_mesh_nodes(const Eigen::VectorXd &x) const
DeformedCollisionBarrierForm(const VariableToSimulationGroup &variable_to_simulation, std::shared_ptr< const varform::DifferentiableVarForm > varform, std::shared_ptr< const DiffCache > diff_cache, const io::ResourceIO &resources, const double dhat)
void solution_changed(const Eigen::VectorXd &x) override
Update cached fields upon a change in the solution.
std::shared_ptr< const varform::DifferentiableVarForm > varform_
virtual double weight() const
Get the form's multiplicative constant weight.
Definition Form.hpp:128
LayerThicknessForm(const VariableToSimulationGroup &variable_to_simulations, std::shared_ptr< const varform::DifferentiableVarForm > varform, const io::ResourceIO &resources, const std::vector< int > &boundary_ids, const double dhat, const bool use_log_barrier=false, const double dmin=0)
std::map< int, std::set< int > > boundary_ids_to_dof_
ipc::SmoothCollisions get_smooth_collision_set(const Eigen::MatrixXd &displaced_surface)
std::shared_ptr< const varform::DifferentiableVarForm > varform_
void solution_changed_step(const int time_step, const Eigen::VectorXd &x) override
Eigen::VectorXd compute_adjoint_rhs_step(const int time_step, const Eigen::VectorXd &x, const varform::DifferentiableVarForm &varform, const DiffCache &diff_cache) const override
SmoothContactForceForm(const VariableToSimulationGroup &variable_to_simulations, std::shared_ptr< const varform::DifferentiableVarForm > varform, std::shared_ptr< const DiffCache > diff_cache, const json &args)
double value_unweighted_step(const int time_step, const Eigen::VectorXd &x) const override
void compute_partial_gradient_step(const int time_step, const Eigen::VectorXd &x, Eigen::VectorXd &gradv) const override
std::shared_ptr< const DiffCache > diff_cache_
ipc::SmoothContactPotential potential_
Eigen::VectorXd apply_parametrization_jacobian(ParameterType type, const varform::DifferentiableVarForm &target, const Eigen::VectorXd &x, const std::function< Eigen::VectorXd()> &grad) const
Compute parametrization jacobian for all var2sim matching parameter type and output to target varform...
void compute_state_variable(ParameterType type, const varform::DifferentiableVarForm &target, const Eigen::VectorXd &x, Eigen::VectorXd &state_variable) const
static bool boundary_quadrature(const mesh::LocalBoundary &local_boundary, const QuadratureOrders &order, const mesh::Mesh &mesh, const bool skip_computation, Eigen::MatrixXd &uv, Eigen::MatrixXd &points, Eigen::MatrixXd &normals, Eigen::VectorXd &weights, Eigen::VectorXi &global_primitive_ids)
Optimization-facing interface implemented by differentiated VarForm adapters.
static void build_collision_mesh(const mesh::Mesh &mesh, const int n_bases, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &geom_bases, const std::vector< mesh::LocalBoundary > &total_local_boundary, const mesh::Obstacle &obstacle, const json &args, const io::ResourceIO &resources, const Eigen::VectorXi &in_node_to_node, ipc::CollisionMesh &collision_mesh)
Eigen::VectorXd map_node_to_primitive_order(const varform::DifferentiableVarForm &varform, const Eigen::VectorXd &nodes)
Eigen::VectorXd map_primitive_to_node_order(const varform::DifferentiableVarForm &varform, const Eigen::VectorXd &primitives)
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, const unsigned max_iter)
Definition Jacobian.cpp:201
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
Eigen::VectorXd flatten(const Eigen::MatrixXd &X)
Flatten rowwises.
spdlog::logger & adjoint_logger()
Retrieves the current logger for adjoint.
Definition Logger.cpp:30
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24