7 template <
class WMTKMesh>
10 if constexpr (std::is_same_v<WMTKMesh, wmtk::TriMesh>)
16 template <
class WMTKMesh>
19 if (!WMTKMesh::swap_edge_before(e))
22 const int v0i = e.vid(*
this);
23 const int v1i = e.switch_vertex(*this).vid(*
this);
25 if (is_body_boundary_edge(e))
27 executor.m_cnt_fail--;
31 if constexpr (std::is_same_v<WMTKMesh, wmtk::TriMesh>)
33 const int v2i = opposite_vertex_on_face(e).vid(*
this);
34 const int v3i = opposite_vertex_on_face(*e.switch_face(*
this)).vid(*
this);
36 const double f0_area = std::abs(
utils::triangle_area_2D(vertex_attrs[v0i].rest_position, vertex_attrs[v1i].rest_position, vertex_attrs[v2i].rest_position));
37 const double f1_area = std::abs(
utils::triangle_area_2D(vertex_attrs[v0i].rest_position, vertex_attrs[v1i].rest_position, vertex_attrs[v3i].rest_position));
38 const double f2_area = std::abs(
utils::triangle_area_2D(vertex_attrs[v0i].rest_position, vertex_attrs[v2i].rest_position, vertex_attrs[v3i].rest_position));
39 const double f3_area = std::abs(
utils::triangle_area_2D(vertex_attrs[v1i].rest_position, vertex_attrs[v2i].rest_position, vertex_attrs[v3i].rest_position));
41 const double total_area = f0_area + f1_area;
42 if (f2_area < 1e-1 * total_area || f3_area < 1e-1 * total_area)
44 executor.m_cnt_fail--;
70 || this->edge_attr(e.eid(*
this)).op_depth >=
args[
"swap"][
"max_depth"].template get<int>())
86 const auto &old_edges = op_cache->edges();
87 for (
const Tuple &e : get_edges_for_elements({{e, e.switch_face(*this).value()}}))
89 size_t v0_id = e.vid(*
this);
90 size_t v1_id = e.switch_vertex(*this).vid(*
this);
92 const auto iter = old_edges.find({{v0_id, v1_id}});
93 if (iter != old_edges.end())
95 boundary_attrs[
e.eid(*
this)] = iter->second;
99 assert(
e.switch_face(*this).has_value());
101 boundary_attrs[
e.eid(*
this)] =
102 old_edges.find({{op_cache->v0().first, op_cache->v1().first}})->second;
108 void WildTriRemesher::map_edge_swap_element_attributes(
const Tuple &e)
110 assert(op_cache->faces()[0].body_id == op_cache->faces()[1].body_id);
111 element_attrs[
e.fid(*
this)] = op_cache->faces()[0];
112 element_attrs[
e.switch_face(*this)->fid(*
this)] = op_cache->faces()[1];
116 bool WildTriRemesher::swap_edge_after(
const Tuple &e)
118 if (!wmtk::TriMesh::swap_edge_after(e))
127 map_edge_swap_edge_attributes(e);
133 map_edge_swap_element_attributes(e);
139 assert(e.switch_face(*this).has_value());
140 if (is_inverted(e) || element_volume(e) < 1e-16
141 || is_inverted(e.switch_face(*this).value())
142 || element_volume(e.switch_face(*this).value()) < 1e-16)
156 bool WildTetRemesher::swap_edge_after(
const Tuple &e)
161 bool PhysicsTriRemesher::swap_edge_after(
const Tuple &e)
165 if (!Super::swap_edge_after(e))
173 (vertex_attrs[e.vid(*
this)].rest_position
174 + vertex_attrs[e.switch_vertex(*this).vid(*
this)].rest_position)
176 return local_relaxation(edge_midpoint, args[
"swap"][
"acceptance_tolerance"])
177 && invariants(std::vector<Tuple>());
186 std::array<std::pair<Tuple, int>, 4> valences;
187 valences[0].first = t;
188 valences[1].first = t.switch_vertex(m);
189 valences[2].first = t.switch_edge(m).switch_vertex(m);
190 assert(t.switch_face(m).has_value());
191 valences[3].first = t.switch_face(m)->switch_edge(m).switch_vertex(m);
192 for (
auto &[t, v] : valences)
193 v = m.get_valence_for_vertex(t);
195 double cost_before_swap = 0.0, cost_after_swap = 0.0;
196 for (
int i = 0; i < valences.size(); i++)
198 const auto &[vert, valence] = valences[i];
200 cost_before_swap += std::pow(
double(valence - ideal_val), 2);
202 std::pow(
double(i < 2 ? (valence - ideal_val - 1) : (valence - ideal_val + 1)), 2);
204 return cost_before_swap - cost_after_swap;
211 assert(t.switch_face(m).has_value());
213 return std::max(f0_area, f1_area) / std::min(f0_area, f1_area);
216 void PhysicsTriRemesher::swap_edges()
219 executor.should_renew = [](
auto val) {
return (
val > 0); };
220 executor.renew_neighbor_tuples = [&](
const WildRemesher &m, std::string op,
const std::vector<Tuple> &tris) ->
Operations {
221 assert(tris.size() == 1);
222 const Tuple &t = tris[0];
224 for (
const Tuple &t : this->get_edges_for_elements({{t, t.switch_face(*this).value()}}))
225 if (!is_body_boundary_edge(t))
226 new_ops.emplace_back(op, t);
232 std::vector<Tuple> included_edges;
234 const std::vector<Tuple> edges = this->get_edges();
235 std::copy_if(edges.begin(), edges.end(), std::back_inserter(included_edges), [
this](
const Tuple &e) {
237 return !is_body_boundary_edge(e);
241 if (included_edges.empty())
245 swaps.reserve(included_edges.size());
246 for (
const Tuple &e : included_edges)
247 swaps.emplace_back(
"edge_swap", e);
249 executor(*
this, swaps);
double local_mesh_energy(const VectorNd &local_mesh_center) const
Compute the energy of a local n-ring around a vertex.
wmtk::ExecutePass< WildRemesher, EXECUTION_POLICY > executor
typename Super::Operations Operations
typename Super::VectorNd VectorNd
wmtk::AttributeCollection< VertexAttributes > vertex_attrs
typename Super::Tuple Tuple
bool swap_edge_before(const Tuple &t) override
const json args
Copy of remesh args.
static std::shared_ptr< TetOperationCache > swap_32(WildTetRemesher &m, const Tuple &t)
static std::shared_ptr< TriOperationCache > swap_edge(WildTriRemesher &m, const Tuple &t)
std::conditional< std::is_same< WMTKMesh, wmtk::TriMesh >::value, std::shared_ptr< TriOperationCache >, std::shared_ptr< TetOperationCache > >::type op_cache
bool is_boundary_vertex(const Tuple &v) const
Is the given vertex tuple on the boundary of the mesh?
typename WMTKMesh::Tuple Tuple
EdgeAttributes & edge_attr(const size_t e_id)
Get a reference to an edge's attributes.
virtual bool swap_edge_before(const Tuple &t) override
void map_edge_swap_edge_attributes(const Tuple &t)
double element_volume(const Tuple &e) const
Compute the volume (area) of an tetrahedron (triangle) element.
void cache_swap_edge(const Tuple &e)
Cache the edge swap operation.
WildTetRemesher::Tuple Tuple
double compute_area_ratio_energy(const WildTriRemesher &m, std::string op, const WildTriRemesher::Tuple &t)
double compute_valence_energy(const WildTriRemesher &m, std::string op, const WildTriRemesher::Tuple &t)
double triangle_area_2D(const Eigen::Vector2d &a, const Eigen::Vector2d &b, const Eigen::Vector2d &c)
Compute the signed area of a 2D triangle defined by three points.
void log_and_throw_error(const std::string &msg)