16 const std::unordered_map<size_t, double> edge_sizings = this->compute_edge_sizings();
17 double min = std::numeric_limits<double>::max();
18 double max = std::numeric_limits<double>::min();
19 for (
const Tuple &e : WMTKMesh::get_edges())
21 min = std::min(min, edge_sizings.at(e.eid(*
this)));
22 max = std::max(max, edge_sizings.at(e.eid(*
this)));
23 if (edge_sizings.at(e.eid(*
this)) >= 1)
24 splits.emplace_back(
"edge_split", e);
26 logger().debug(
"min sij: {}, max sij: {}", min, max);
32 return edge_sizings.at(t.eid(m));
35 executor(*
this, splits);
75 if (!Super::collapse_edge_after(t))
78 if constexpr (Super::DIM == 2)
80 const std::unordered_map<size_t, double> edge_sizings = this->compute_edge_sizings();
81 for (
const Tuple &e : WMTKMesh::get_one_ring_edges_for_vertex(t))
82 if (edge_sizings.at(e.eid(*
this)) > 0.8)
87 const std::unordered_map<size_t, double> edge_sizings = this->compute_edge_sizings();
88 for (
const Tuple &tet : WMTKMesh::get_one_ring_tets_for_vertex(t))
90 for (
int i = 0; i < 6; ++i)
92 const Tuple e = WMTKMesh::tuple_from_edge(tet.tid(*
this), i);
93 if (edge_sizings.at(e.eid(*
this)) > 0.8)
106 const Candidates &candidates,
107 const ipc::CollisionMesh &collision_mesh,
108 const Eigen::MatrixXd &
V,
109 const double dhat)
const
111 const Eigen::MatrixXd &V_rest = collision_mesh.rest_positions();
112 const Eigen::MatrixXi &E = collision_mesh.edges();
113 const Eigen::MatrixXi &
F = collision_mesh.faces();
115 Eigen::VectorXd min_distance_per_vertex = Eigen::VectorXd::Constant(
V.rows(), dhat * dhat);
118 for (
const auto &candidate : candidates)
120 const double distance_sqr = candidate.compute_distance(candidate.dof(
V, E,
F));
121 const double rest_distance_sqr = candidate.compute_distance(candidate.dof(V_rest, E,
F));
122 const ipc::VectorMax12d distance_grad = candidate.compute_distance_gradient(candidate.dof(
V, E,
F));
123 const auto vertices = candidate.vertex_ids(E,
F);
124 for (
int i = 0; i < 4; i++)
126 const long vi = vertices[i];
127 if (vi < 0 || vi >
V.rows() - this->obstacle().n_vertices())
129 if (distance_sqr / rest_distance_sqr >= 0.1 || distance_sqr > min_distance_per_vertex[vi])
132 VectorNd g = distance_grad.segment<Super::DIM>(Super::DIM * i) / (2 * sqrt(distance_sqr));
134 sizing_field[collision_mesh.to_full_vertex_id(vi)] = g * (g.transpose() / distance_sqr);
135 min_distance_per_vertex[vi] = distance_sqr;
146 Eigen::MatrixXd V_rest = this->rest_positions();
149 ipc::CollisionMesh collision_mesh = ipc::CollisionMesh::build_from_full_mesh(
150 V_rest, this->boundary_edges(), this->boundary_faces());
152 Eigen::MatrixXd
V = this->positions();
153 if (this->obstacle().n_vertices())
156 V_rest = collision_mesh.rest_positions();
157 V = collision_mesh.vertices(
V);
158 const Eigen::MatrixXi &E = collision_mesh.edges();
159 const Eigen::MatrixXi &
F = collision_mesh.faces();
161 const double dhat = state.args[
"contact"][
"dhat"].template get<double>();
163 ipc::HashGrid hash_grid;
164 hash_grid.build(
V, E,
F, dhat / 2);
165 if constexpr (Super::DIM == 2)
167 ipc::Candidates candidates;
168 hash_grid.detect_edge_vertex_candidates(candidates.ev_candidates);
169 return this->compute_contact_sizing_field_from_candidates(
170 candidates.ev_candidates, collision_mesh,
V, dhat);
174 ipc::Candidates candidates;
175 hash_grid.detect_face_vertex_candidates(candidates.fv_candidates);
178 return this->compute_contact_sizing_field_from_candidates(
179 candidates.fv_candidates, collision_mesh,
V, dhat);
189 for (
const Tuple &f : this->boundary_facets())
191 const auto vids = this->facet_vids(f);
193 for (
const size_t vid : vids)
194 if (sizing_field.find(vid) != sizing_field.end())
195 M += sizing_field.at(vid);
198 std::vector<Tuple> edges;
199 if constexpr (Super::DIM == 2)
202 edges = {{f, f.switch_edge(*
this), f.switch_vertex(*this).switch_edge(*
this)}};
204 for (
const Tuple &e : edges)
206 if (sizing_field.find(e.eid(*
this)) == sizing_field.end())
207 smoothed_sizing_field[e.eid(*
this)] = MatrixNd::Zero();
208 smoothed_sizing_field[e.eid(*
this)] += M / edges.size();
212 return smoothed_sizing_field;
220 combine_sizing_fields(
221 compute_elasticity_sizing_field(),
222 smooth_contact_sizing_field(compute_contact_sizing_field()));
224 std::unordered_map<size_t, double> edge_sizings;
225 for (
const Tuple &e : WMTKMesh::get_edges())
227 const std::array<size_t, 2> vids =
228 {{e.vid(*
this), e.switch_vertex(*this).vid(*
this)}};
230 const VectorNd xi_bar = vertex_attrs[vids[0]].rest_position;
231 const VectorNd xj_bar = vertex_attrs[vids[1]].rest_position;
233 const VectorNd xij_bar = xj_bar - xi_bar;
235 const MatrixNd M = sizing_field.at(e.eid(*
this));
237 edge_sizings[e.eid(*
this)] = sqrt(xij_bar.transpose() * M * xij_bar);
246 std::unordered_map<size_t, MatrixNd> Fs, Fs_inv;
247 for (
const Tuple &t : this->get_elements())
249 const auto vids = this->element_vids(t);
251 if constexpr (std::is_same_v<WMTKMesh, wmtk::TriMesh>)
253 Dm.col(0) = vertex_attrs[vids[1]].rest_position - vertex_attrs[vids[0]].rest_position;
254 Dm.col(1) = vertex_attrs[vids[2]].rest_position - vertex_attrs[vids[0]].rest_position;
255 Ds.col(0) = vertex_attrs[vids[1]].position - vertex_attrs[vids[0]].position;
256 Ds.col(1) = vertex_attrs[vids[2]].position - vertex_attrs[vids[0]].position;
260 Dm.col(0) = vertex_attrs[vids[1]].rest_position - vertex_attrs[vids[0]].rest_position;
261 Dm.col(1) = vertex_attrs[vids[2]].rest_position - vertex_attrs[vids[0]].rest_position;
262 Dm.col(2) = vertex_attrs[vids[3]].rest_position - vertex_attrs[vids[0]].rest_position;
263 Ds.col(0) = vertex_attrs[vids[1]].position - vertex_attrs[vids[0]].position;
264 Ds.col(1) = vertex_attrs[vids[2]].position - vertex_attrs[vids[0]].position;
265 Ds.col(2) = vertex_attrs[vids[3]].position - vertex_attrs[vids[0]].position;
267 Fs[this->element_id(t)] = Ds * Dm.inverse();
268 Fs_inv[this->element_id(t)] = Dm * Ds.inverse();
271 const double k = 1.0;
273 std::unordered_map<size_t, VectorNd> element_centers;
274 for (
const Tuple &t : this->get_elements())
277 const auto &vids = this->element_vids(t);
278 for (
const size_t &vid : vids)
279 center += vertex_attrs[vid].rest_position;
280 element_centers[this->element_id(t)] = center / vids.size();
284 for (
const Tuple &t : this->get_elements())
286 const size_t tid = this->element_id(t);
307 element_sizing_field[tid] = Fs[tid].transpose() * Fs[tid];
309 assert(!element_sizing_field.empty());
312 for (
const Tuple &e : this->get_edges())
314 const size_t eid = e.eid(*
this);
315 const auto &incident_elements = this->get_incident_elements_for_edge(e);
316 for (
const Tuple &t : incident_elements)
318 if (sizing_field.find(eid) == sizing_field.end())
319 sizing_field[eid] = MatrixNd::Zero();
320 sizing_field[eid] += element_sizing_field[this->element_id(t)];
322 sizing_field[eid] /= incident_elements.size() * std::pow(state.starting_max_edge_length, 2);