Wildmeshing Toolkit
Loading...
Searching...
No Matches
SimWildMesh.h
1#pragma once
2
3#include <wmtk/MeshData.hpp>
4
5#include <igl/Timer.h>
6#include <wmtk/SurfaceTagAttributes.h>
7#include <wmtk/TetMesh.h>
8#include <wmtk/TetOptimizerMesh.h>
9#include <wmtk/utils/PartitionMesh.h>
10#include <polysolve/nonlinear/Problem.hpp>
11#include <wmtk/envelope/CompositeEnvelopes.hpp>
12#include <wmtk/envelope/Envelope.hpp>
13#include <wmtk/optimization/SmoothVertex.hpp>
14#include <wmtk/optimization/solver.hpp>
15#include <wmtk/simplex/Simplex.hpp>
16#include <wmtk/threading/enumerable_thread_specific.hpp>
17#include <wmtk/threading/parallel_for.hpp>
18
19#include "ConnectedComponent.hpp"
20#include "Parameters.h"
21
22// clang-format off
23#include <wmtk/utils/DisableWarnings.hpp>
24#include <fastenvelope/FastEnvelope.h>
25#include <wmtk/utils/EnableWarnings.hpp>
26// clang-format on
27
28#include <igl/remove_unreferenced.h>
29#include <atomic>
30#include <memory>
31
32#include <wmtk/utils/SurfaceTopology.hpp>
33#include <wmtk/utils/partition_utils.hpp>
34#include "expression_parser/Expression.hpp"
35
36namespace wmtk::components::simwild {
37
41using VertexAttributes = wmtk::TetOptimizerMesh::VertexAttributes;
42using FaceAttributes = wmtk::TetOptimizerMesh::FaceAttributes;
43
45{
46public:
50 double m_quality;
55 CellTag tags;
56};
57
59{
60public:
61 using ExprPtr = expression_parser::ExpressionPtr;
62
63 size_t m_tags_count = 0;
64 std::map<int64_t, std::string> m_tag_id_to_name;
65 std::map<std::string, int64_t> m_tag_name_to_id;
67 std::vector<std::string> m_face_tag_names;
68
92
94 InputSet face_tag_mask() const
95 {
96 const size_t n = m_face_tag_names.size();
97 return n >= size_t(SurfaceTagAttributes::max_inputs) ? ~InputSet(0)
98 : (InputSet(1) << n) - 1;
99 }
100
103 std::vector<InputSet> m_F_envelope_labels;
104
108 void init_label_envelopes(double eps, bool exact);
109
111 std::shared_ptr<Envelope> surface_envelope_for_face(
112 const std::array<size_t, 3>& vids,
113 const FaceAttributes& attr) const override
114 {
115 if (m_input_envelopes.empty() || attr.input_set() == 0) return m_envelope;
116 return m_input_envelopes.containment(attr.input_set());
117 }
118
122 std::vector<Vector3d> m_V_envelope;
123 std::vector<Vector3i> m_F_envelope;
124 double m_envelope_eps = -1;
125
126 std::vector<std::tuple<ExprPtr, double>> m_sizing_field;
127 std::vector<std::tuple<ExprPtr, double>> m_quality_field;
128
129 bool m_collapse_check_quality = true;
130
131 // for open boundary
133 std::shared_ptr<Envelope> m_order_2_edge_envelope;
134
136 std::shared_ptr<Envelope> smoothing_energy_envelope(const size_t vid) const override;
137
138 // When set, split_edge_after binary-searches vmid onto the zero-crossing of this function.
139 // Negative = stays on v1 side, positive = stays on v2 side.
140 std::function<double(const Vector3d&)> m_voronoi_split_fn = nullptr;
141
142 SimWildMesh(Parameters& _m_params, double envelope_eps, int _num_threads = 0)
143 : wmtk::TetOptimizerMesh(_m_params, nullptr)
144 , m_sim_params(_m_params)
145 {
146 m_envelope_eps = envelope_eps;
147 NUM_THREADS = _num_threads;
148 p_tet_attrs = &m_tet_attribute;
149 m_collapse_check_link_condition = false;
150 m_collapse_check_manifold = false;
151
152 // solver is lazily created on first use
153
154 optimization::deactivate_opt_logger();
155
156 m_s_envelope = 1. / (m_params.eps * m_params.eps);
157
158 double& wa = m_params.w_amips;
159 double& we = m_params.w_envelope;
160 we = 1 - wa;
161 logger().info("w_envelope = {}", we);
162 }
163
164 ~SimWildMesh() {}
166 TetAttCol m_tet_attribute;
167
168 double cell_quality(const size_t tid) const override { return m_tet_attribute[tid].m_quality; }
169 void set_cell_quality(const size_t tid, const double q) override
170 {
171 m_tet_attribute[tid].m_quality = q;
172 }
173 bool allow_surface_swap() const override { return m_sim_params.allow_surface_swap; }
174 bool check_surface_topology() const override { return m_sim_params.check_surface_topology; }
175
176 // only used with unit tests
177 void create_mesh_attributes(
178 const std::vector<VertexAttributes>& _vertex_attribute,
179 const std::vector<TetAttributes>& _tet_attribute)
180 {
181 const size_t n_tet = _tet_attribute.size();
182 m_vertex_attribute.resize(_vertex_attribute.size());
183 m_face_attribute.resize(4 * n_tet);
184 m_tet_attribute.resize(n_tet);
185
186 for (size_t i = 0; i < _vertex_attribute.size(); i++)
187 m_vertex_attribute[i] = _vertex_attribute[i];
188
189 // Keep whatever init() reserved. AttributeCollection::resize only ever grows, so the
190 // calls above cannot shrink a collection -- but assigning m_attributes directly does,
191 // and it used to drop the tet attributes to exactly n_tet. The attributes have to stay
192 // at least as large as the connectivity: an operation that creates a new element
193 // indexes them by its id, and a 5->6 swap creates one. tetwild hit the same thing (see
194 // the note on its copy); there the overrun wrote a double past the end and libc++ let
195 // it pass, here it assigns a std::set and segfaults outright.
196 const size_t tcap = std::max(n_tet, m_tet_attribute.size());
197 m_tet_attribute.m_attributes = std::vector<TetAttributes>(tcap);
198 for (size_t i = 0; i < n_tet; i++) m_tet_attribute[i] = _tet_attribute[i];
199 for (size_t i = 0; i < n_tet; i++)
200 m_tet_attribute[i].m_quality = get_quality(tuple_from_tet(i));
201 }
202
203 // TODO This should not be here but inside wmtk
204 // TODO This should not be here but inside wmtk
205 void init_envelope(const MatrixXd& V, const MatrixXi& F);
206
207 CellTag string_set_to_cell_tag(const std::set<std::string>& str_set);
208
209 void set_sizing_field(const nlohmann::json& sizing_field_json);
210
211 void set_quality_field(const nlohmann::json& quality_field_json);
212
213 double target_quality(const size_t tid) const;
214 double target_quality(const Tuple& t) const;
217 double quality_rel(const size_t tid) const override;
218 double quality_rel(const Tuple& t) const;
219 bool check_mesh_quality(double& max_rel_quality, const bool verbose = false) const;
229 bool check_interface_faces_tagged(const bool verbose = false) const;
230
243 void update_attributes() override;
247 std::array<size_t, 3> orient_tracked_face(
248 const std::array<size_t, 3>& f,
249 const std::vector<size_t>& tets) const override;
251 std::vector<int64_t> tet_tags(size_t tid) const override;
252
253 std::vector<size_t> active_vertices() const override;
254
255
257
258
259public:
260 void simplify();
261
266 bool all_rounded() const;
267
268 //
269 //
270 // debug use
271 std::atomic<int> cnt_split = 0, cnt_collapse = 0;
272
273protected:
274 std::tuple<double, double> optimization_quality_stats() override;
275 double optimization_stop_metric() const override { return 1.; }
276 bool optimization_stop_at_float() const override { return m_sim_params.stop_at_float; }
277 void write_optimization_debug_output(const std::string& path) override { write_vtu(path); }
278
279 bool collapse_before_vertex(size_t v1, size_t v2, double edge_length) override;
280 bool collapse_quality_allowed(size_t v1, double quality, double ring_max) const override;
281 bool collapse_is_order_2_edge(const std::array<size_t, 2>& e) override;
282 bool collapse_after_connectivity(
283 size_t v1,
284 size_t v2,
285 const std::vector<std::array<size_t, 2>>& boundary_edges) override;
286
287 bool split_before_cells(const Tuple& edge, const std::vector<Tuple>& parents) override;
288 bool split_after_cells(size_t v1, size_t v2, size_t v_new, const std::vector<Tuple>& children)
289 override;
290 bool split_adjust_position(size_t v_new, const std::vector<Tuple>& children) override;
291
292 bool swap_before_interior(const std::vector<size_t>& tids) override;
293 bool swap_before_surface(
294 const std::vector<size_t>& tids,
295 size_t a,
296 size_t b,
297 size_t c,
298 size_t d) override;
299 bool swap_after_cells(const std::vector<size_t>& tids, bool is_surface_flip) override;
300
301private:
303
305 {
306 size_t v_new = 0;
308 std::map<simplex::Edge, TetAttributes> tets;
309 };
311
313 {
314 CellTag tet_tags;
315 std::map<size_t, CellTag> ring_tags;
316 };
318
319public:
327 void init_from_image(
328 const MatrixXr& V,
329 const MatrixXi& T,
330 const MatrixSi& T_tags,
331 const std::vector<std::string>& tag_names,
332 const MatrixXi& F_tagged = MatrixXi(),
333 const MatrixSi& F_tags = MatrixSi(),
334 const std::vector<std::string>& face_tag_names = {});
335 void init_from_image(
336 const MatrixXd& V,
337 const MatrixXi& T,
338 const MatrixSi& T_tags,
339 const std::vector<std::string>& tag_names,
340 const MatrixXi& F_tagged = MatrixXi(),
341 const MatrixSi& F_tags = MatrixSi(),
342 const std::vector<std::string>& face_tag_names = {});
343
344 void init_surfaces_and_boundaries();
347 void init_face_tags(
348 const MatrixXi& F_tagged,
349 const MatrixSi& F_tags,
350 const std::vector<std::string>& face_tag_names);
351
352
365 size_t refine_sizing_around_worst(double max_metric = 0.) override;
366
367
377 void find_order_2_edges();
387 bool is_order_2_edge(const Tuple& e) const;
388 bool is_order_2_edge(const std::array<size_t, 2>& e) const;
389
390 void write_vtu(const std::string& path, MeshMap* output = nullptr);
391
392 void write_surface(const std::string& path) const;
393
394public:
395 // substructure functions
396
400 void init_vertex_order();
401
402public:
403 // Annotations
404
405 double tet_volume(const size_t tid) const;
406
410 std::vector<ConnectedComponent> compute_connected_components(const CellTag& tag_in) const;
411 std::vector<ConnectedComponent> compute_connected_components(const ExprPtr& expr) const;
412
430 std::vector<ConnectedComponent> find_holes(const std::vector<CellTag>& tag_in) const;
431
440 void compute_tag_boundary(const CellTag& tag, MatrixXd& V, MatrixXi& F) const;
441
450 const std::vector<CellTag>& lcc_tags,
451 const size_t n_lcc = 1);
452
453 void fill_holes_topo(
454 const std::vector<CellTag>& fill_holes_tags,
455 double threshold = std::numeric_limits<double>::infinity());
456
457 void seal_connected_components(
458 const std::vector<CellTag>& tag_sets,
459 const std::vector<ConnectedComponent>& components);
460
461 void tight_seal_topo(
462 const std::vector<std::vector<CellTag>>& tight_seal_tag_sets,
463 double threshold = std::numeric_limits<double>::infinity());
464
465 void resolve_overlaps(const std::vector<std::array<ExprPtr, 2>>& intersecting_tags);
466
467 void replace_tags(const std::vector<CellTag>& tags_in, const std::vector<CellTag>& tags_out);
468
479 void tag_priority(const std::vector<int64_t>& tags);
480};
481
482} // namespace wmtk::components::simwild
One envelope per input, and the containment and the pull of an INPUT SET (bit i = input i; see Surfac...
Definition CompositeEnvelopes.hpp:152
Definition SurfaceTagAttributes.h:24
static constexpr int max_inputs
One input per bit of InputSet: the width is set there, and only there.
Definition SurfaceTagAttributes.h:130
Tuple tuple_from_tet(size_t tid) const
get a Tuple from global tetra index
Definition TetMesh.cpp:715
What tetwild and simwild's 3D mesh share.
Definition TetOptimizerMesh.h:51
std::array< size_t, 3 > orient_tracked_face(const std::array< size_t, 3 > &f, const std::vector< size_t > &tets) const override
Definition TetOptimizerMesh.cpp:1000
OptimizerParameters & m_params
Definition TetOptimizerMesh.h:425
std::shared_ptr< Envelope > m_envelope
Surface envelope: what a surface vertex is pulled toward and checked against.
Definition TetOptimizerMesh.h:428
Definition SimWildMesh.h:59
std::vector< std::string > m_face_tag_names
Names of the face tags: bit i of a face's input set is m_face_tag_names[i].
Definition SimWildMesh.h:67
bool swap_after_cells(const std::vector< size_t > &tids, bool is_surface_flip) override
Propagate application data to the cells made by a successful topological swap.
Definition EdgeSwapping.cpp:48
std::vector< ConnectedComponent > compute_connected_components(const CellTag &tag_in) const
Find all connected components that contain the tag_in tags.
Definition AnnotationsTet.cpp:7
void init_label_envelopes(double eps, bool exact)
Definition SimWildMesh.cpp:481
void init_face_tags(const MatrixXi &F_tagged, const MatrixSi &F_tags, const std::vector< std::string > &face_tag_names)
Definition VolumemesherInsertion.cpp:280
bool split_before_cells(const Tuple &edge, const std::vector< Tuple > &parents) override
Cache application cell data before a split. TetWild needs none; SimWild caches tags.
Definition EdgeSplitting.cpp:7
bool collapse_before_vertex(size_t v1, size_t v2, double edge_length) override
Definition EdgeCollapsing.cpp:8
void init_vertex_order()
Compute the vertex order for every vertex.
Definition SimWildMesh.cpp:805
std::shared_ptr< Envelope > smoothing_energy_envelope(const size_t vid) const override
Envelope a vertex is pulled toward while smoothing.
Definition Smooth.cpp:5
bool all_rounded() const
Check if all vertices of the mesh are rounded.
Definition SimWildMesh.cpp:583
size_t refine_sizing_around_worst(double max_metric=0.) override
Escape a stuck max energy by refining the sizing field around the worst elements.
Definition SimWildMesh.cpp:401
InputSet face_tag_mask() const
The face-tag bits of an input set: those below the number of face tags.
Definition SimWildMesh.h:94
bool split_after_cells(size_t v1, size_t v2, size_t v_new, const std::vector< Tuple > &children) override
Restore application cell data on the children made by a split.
Definition EdgeSplitting.cpp:20
bool check_interface_faces_tagged(const bool verbose=false) const
Verify that every interface between unlike tags carries a surface face.
Definition SimWildMesh.cpp:304
Parameters & m_sim_params
Definition SimWildMesh.h:121
void find_order_2_edges()
Find open boundary edges of the embedded surface and initialize a BVH for the open boundary.
Definition VolumemesherInsertion.cpp:463
std::shared_ptr< Envelope > m_order_2_edge_envelope
Follows m_envelope's use_exact; see where it is built in VolumemesherInsertion.cpp.
Definition SimWildMesh.h:133
std::shared_ptr< Envelope > surface_envelope_for_face(const std::array< size_t, 3 > &vids, const FaceAttributes &attr) const override
A tracked face's containment: its labels' envelopes if it has any, else m_envelope.
Definition SimWildMesh.h:111
double cell_quality(const size_t tid) const override
The quality of cell tid, and how to write it.
Definition SimWildMesh.h:168
void compute_tag_boundary(const CellTag &tag, MatrixXd &V, MatrixXi &F) const
Compute the boundary of a tag.
Definition AnnotationsTet.cpp:202
std::vector< InputSet > m_F_envelope_labels
Definition SimWildMesh.h:103
void keep_largest_connected_component(const std::vector< CellTag > &lcc_tags, const size_t n_lcc=1)
Keep only the largest connected component for each of the distinct tag_0 values, and engulf all other...
Definition AnnotationsTet.cpp:446
wmtk::InputEnvelopes m_input_envelopes
One envelope per label, and each surface face held by those of the labels it lies on: bit i < F of a ...
Definition SimWildMesh.h:91
std::vector< int64_t > tet_tags(size_t tid) const override
A tet's tags: the regions of a volume history are the tag sets.
Definition SimWildMesh.cpp:201
std::tuple< double, double > optimization_quality_stats() override
Definition SimWildMesh.cpp:172
std::array< size_t, 3 > orient_tracked_face(const std::array< size_t, 3 > &f, const std::vector< size_t > &tets) const override
Definition SimWildMesh.cpp:190
void init_from_image(const MatrixXr &V, const MatrixXi &T, const MatrixSi &T_tags, const std::vector< std::string > &tag_names, const MatrixXi &F_tagged=MatrixXi(), const MatrixSi &F_tags=MatrixSi(), const std::vector< std::string > &face_tag_names={})
Init from meshes image.
Definition VolumemesherInsertion.cpp:10
void tag_priority(const std::vector< int64_t > &tags)
Gives tags priority over others.
Definition AnnotationsTet.cpp:688
void update_attributes() override
Update the attributes of the mesh after an iteration of operations.
Definition SimWildMesh.cpp:207
bool is_order_2_edge(const Tuple &e) const
Checks if an edge COULD be an open boundary edge.
Definition VolumemesherInsertion.cpp:504
bool split_adjust_position(size_t v_new, const std::vector< Tuple > &children) override
Definition EdgeSplitting.cpp:50
std::vector< size_t > active_vertices() const override
Definition SimWildMesh.cpp:259
void simplify()
Definition EdgeCollapsing.cpp:44
std::vector< ConnectedComponent > find_holes(const std::vector< CellTag > &tag_in) const
Find all regions that do not contain the tags from tag_in.
Definition AnnotationsTet.cpp:127
bool swap_before_interior(const std::vector< size_t > &tids) override
Application data attached to the old cells. TetWild has none; SimWild caches tags.
Definition EdgeSwapping.cpp:7
double quality_rel(const size_t tid) const override
Definition SimWildMesh.cpp:162
Definition SimWildMesh.h:45
double m_quality
Definition SimWildMesh.h:50
CellTag tags
Definition SimWildMesh.h:55
Definition enumerable_thread_specific.hpp:37
Definition AttributeCollection.hpp:46
double w_amips
Definition OptimizerParameters.h:172
Definition TetOptimizerMesh.h:54
The fields shared with tetwild and triwild live in wmtk::OptimizerParameters.
Definition Parameters.h:10
std::map< simplex::Edge, TetAttributes > tets
Parent cell data, keyed by the edge opposite the split edge.
Definition SimWildMesh.h:308