Wildmeshing Toolkit
Loading...
Searching...
No Matches
TetWildMesh.h
1#pragma once
2
3#include <igl/Timer.h>
4#include <wmtk/SurfaceTagAttributes.h>
5#include <wmtk/TetMesh.h>
6#include <wmtk/TetOptimizerMesh.h>
7#include <wmtk/utils/PartitionMesh.h>
8#include <algorithm>
9#include <wmtk/envelope/Envelope.hpp>
10#include <wmtk/optimization/SmoothVertex.hpp>
11#include <wmtk/threading/concurrent_map.hpp>
12#include <wmtk/threading/enumerable_thread_specific.hpp>
13#include <wmtk/threading/parallel_for.hpp>
14
15#include "Parameters.h"
16
17// clang-format off
18#include <wmtk/utils/DisableWarnings.hpp>
19#include <fastenvelope/FastEnvelope.h>
20#include <VolumeRemesher/embed.h>
21#include <wmtk/utils/EnableWarnings.hpp>
22// clang-format on
23
24#include <igl/remove_unreferenced.h>
25#include <memory>
26#include <set>
27#include <unordered_set>
28#include <utility>
29#include <wmtk/utils/SurfaceTopology.hpp>
30#include <wmtk/utils/partition_utils.hpp>
31
32namespace wmtk::components::tetwild {
33
35using VertexAttributes = wmtk::TetOptimizerMesh::VertexAttributes;
36using FaceAttributes = wmtk::TetOptimizerMesh::FaceAttributes;
37
38// TODO: missing comments on what these attributes are
40{
41public:
42 double m_quality;
43 double m_winding_number_input = 0; // winding number w.r.t. the input
44 double m_winding_number_tracked = 0; // winding number w.r.t. the tracked surface
45 std::vector<double> m_winding_number_per_input;
46 int part_id = -1; // flood fill ID
47};
48
50{
51public:
60 {
65 };
67
71
75 std::shared_ptr<SampleEnvelope> m_order2_envelope;
76
79 std::vector<std::string> m_input_names;
80
82 TetAttCol m_tet_attribute;
83
84 double cell_quality(const size_t tid) const override { return m_tet_attribute[tid].m_quality; }
85 void set_cell_quality(const size_t tid, const double q) override
86 {
87 m_tet_attribute[tid].m_quality = q;
88 }
89 bool allow_surface_swap() const override { return m_tet_params.allow_surface_swap; }
90 bool check_surface_topology() const override { return m_tet_params.check_surface_topology; }
91 void split_after_vertex(const size_t vid, const bool is_open_boundary) override
92 {
93 m_vertex_extra[vid].m_is_on_open_boundary = is_open_boundary;
94 }
95 bool collapse_before_vertex(size_t v1, size_t v2, double edge_length) override
96 {
97 if (edge_length <= 0 || !m_vertex_extra[v1].m_is_on_open_boundary) return true;
98 return m_vertex_extra[v2].m_is_on_open_boundary ||
99 !m_order2_envelope->is_outside(m_vertex_attribute[v2].m_posf);
100 }
101 bool collapse_is_order_2_edge(const std::array<size_t, 2>& e) override
102 {
103 return is_open_boundary_edge(e);
104 }
105 bool collapse_after_connectivity(
106 size_t v1,
107 size_t v2,
108 const std::vector<std::array<size_t, 2>>&) override
109 {
110 m_vertex_extra[v2].m_is_on_open_boundary =
111 m_vertex_extra[v1].m_is_on_open_boundary || m_vertex_extra[v2].m_is_on_open_boundary;
112 return true;
113 }
114 void collapse_after_vertex(size_t, size_t v2) override
115 {
116 if (m_vertex_extra[v2].m_is_on_open_boundary && !is_vertex_on_boundary(v2)) {
117 m_vertex_extra[v2].m_is_on_open_boundary = false;
118 }
119 }
120
122 std::shared_ptr<SampleEnvelope> smoothing_energy_envelope(const size_t vid) const override;
123 TetWildMesh(
124 Parameters& _m_params,
125 std::shared_ptr<SampleEnvelope> _m_envelope,
126 int _num_threads = 1)
127 : wmtk::TetOptimizerMesh(_m_params, std::move(_m_envelope))
128 , m_tet_params(_m_params)
129 {
130 m_vertex_attr_group.add(&m_vertex_extra);
131 NUM_THREADS = _num_threads;
132 p_tet_attrs = &m_tet_attribute;
133 m_collapse_check_link_condition = false;
134 m_collapse_check_manifold = false;
135
136 optimization::deactivate_opt_logger();
137 m_s_envelope = 1. / (m_params.eps * m_params.eps);
138 m_params.w_envelope = 1. - m_params.w_amips;
139 }
140
141 ~TetWildMesh() {}
142
143 // only used with unit tests
144 void create_mesh_attributes(
145 const std::vector<VertexAttributes>& _vertex_attribute,
146 const std::vector<TetAttributes>& _tet_attribute)
147 {
148 const size_t n_tet = _tet_attribute.size();
149 m_vertex_attribute.resize(_vertex_attribute.size());
150 // The extras carry no data a caller supplies -- every field defaults -- so they only
151 // have to be sized alongside the shared collection.
152 m_vertex_extra.resize(_vertex_attribute.size());
153 m_face_attribute.resize(4 * n_tet);
154 m_tet_attribute.resize(n_tet);
155
156 // new for edge
157 // m_edge_attribute.resize(6 * n_tet);
158
159 for (size_t i = 0; i < _vertex_attribute.size(); i++)
160 m_vertex_attribute[i] = _vertex_attribute[i];
161
162 // Keep whatever init() reserved. AttributeCollection::resize only ever grows, so the
163 // calls above cannot shrink a collection -- but assigning m_attributes directly does,
164 // and it used to drop the tet attributes to exactly n_tet. The attributes have to stay
165 // at least as large as the connectivity: an operation that creates a new element
166 // indexes them by its id, and a 5->6 swap creates one. That left m_tet_attribute one
167 // short of the tet the swap adds, and AttributeCollection::operator[] read past the end
168 // of it -- ASan reports a heap-buffer-overflow reached from swap_edge_56_after, and
169 // libstdc++ then aborts on the corrupted heap a few allocations later, while libc++
170 // carries on and the tests pass.
171 const size_t tcap = std::max(n_tet, m_tet_attribute.size());
172 m_tet_attribute.m_attributes = std::vector<TetAttributes>(tcap);
173 for (size_t i = 0; i < n_tet; i++) m_tet_attribute[i] = _tet_attribute[i];
174 for (size_t i = 0; i < n_tet; i++)
175 m_tet_attribute[i].m_quality = get_quality(tuple_from_tet(i));
176 }
177
179
180 void output_mesh(std::string file);
181 void init_from_delaunay_box_mesh(const std::vector<Eigen::Vector3d>& vertices);
182
183public:
184 //
189 bool is_vertex_on_boundary(const size_t vid);
190 //
194 void mesh_improvement_legacy(int max_its = 80);
195
206 Eigen::MatrixXd tet_barycenters(const std::vector<Tuple>& tets) const;
207
208 void compute_winding_number(
209 const std::vector<Tuple>& tets,
210 const Eigen::MatrixXd& barycenters,
211 const std::vector<Vector3d>& vertices = {},
212 const std::vector<std::array<size_t, 3>>& faces = {});
213
214 // `in_vertices`/`in_faces` let the single-input case reuse the already-loaded
215 // surface instead of re-reading it from disk.
216 void compute_winding_numbers(
217 const std::vector<std::string>& input_paths,
218 const std::vector<Tuple>& tets,
219 const Eigen::MatrixXd& barycenters,
220 const std::vector<Vector3d>& in_vertices = {},
221 const std::vector<std::array<size_t, 3>>& in_faces = {});
222
223 void filter_with_input_surface_winding_number();
224 void filter_with_tracked_surface_winding_number();
225 void filter_with_flood_fill();
226
227
228 // debug use
229 std::atomic<int> cnt_split = 0, cnt_collapse = 0;
230
231private:
232 // tags: correspondence map from new tet-face node indices to in-triangle ids.
233 // built up while triangles are inserted.
234 wmtk::threading::concurrent_map<std::array<size_t, 3>, std::vector<int>> tet_face_tags;
235
237 {
238 // local info: for each face insertion
239 int face_id;
240 std::vector<std::array<size_t, 3>> old_face_vids;
241 };
243 triangle_insertion_local_cache;
244
245 // for incremental tetwild
246public:
254 const std::vector<Vector3d>& vertices,
255 const std::vector<std::array<size_t, 3>>& faces,
256 std::vector<Vector3r>& v_rational,
257 std::vector<std::array<size_t, 3>>& facets_after,
258 std::vector<bool>& is_v_on_input,
259 std::vector<std::array<size_t, 4>>& tets_after,
260 std::vector<bool>& tet_face_on_input_surface);
261
262 void init_from_Volumeremesher(
263 const std::vector<Vector3r>& v_rational,
264 const std::vector<std::array<size_t, 3>>& facets,
265 const std::vector<bool>& is_v_on_input,
266 const std::vector<std::array<size_t, 4>>& tets,
267 const std::vector<bool>& tet_face_on_input_surface);
268
269 void init_from_file(std::string input_dir);
270
271
284 size_t refine_sizing_around_worst(double max_energy) override;
285
286 // for open boundary
287 void find_open_boundary();
290 bool is_open_boundary_edge(const Tuple& e) override;
291 bool is_open_boundary_edge(const std::array<size_t, 2>& e);
292
293public:
294 // substructure functions
295
299 void init_vertex_order();
300
301public:
302 // for boolean operations
303 int flood_fill();
304
305 void save_paraview(const std::string& path, const bool use_hdf5);
306 void write_optimization_debug_output(const std::string& path) override
307 {
308 save_paraview(path, false);
309 }
310 void optimization_sanity_checks_extra() override;
311
312 // initialize sizing field (for topology preservation)
313 void init_sizing_field();
314
315public:
317 {
318 // tet mesh
319 MatrixXd V;
320 MatrixXi T;
321 // tracked surface
322 MatrixXi F;
323 // attributes
324 VectorXd t_amips;
325 VectorXd t_winding_number_input;
326 VectorXd t_winding_number_tracked;
327 MatrixXd t_winding_number_per_input;
328 VectorXi t_part;
329 };
330 // export functionality
331 ExportStruct export_mesh_data() const;
332};
333
334
335} // namespace wmtk::components::tetwild
Whether a codimension-1 simplex is tracked surface, and which bbox side it lies on.
Definition SurfaceTagAttributes.h:15
a Tuple refers to a global vid and a global tet id, and a local edge id and local face id
Definition TetMesh.h:49
Tuple tuple_from_tet(size_t tid) const
get a Tuple from global tetra index
Definition TetMesh.cpp:640
What tetwild and simwild's 3D mesh share.
Definition TetOptimizerMesh.h:45
AttributeContainerGroup m_vertex_attr_group
What p_vertex_attrs points at, so a derived class can register more.
Definition TetOptimizerMesh.h:92
OptimizerParameters & m_params
Definition TetOptimizerMesh.h:121
Definition TetWildMesh.h:40
Definition TetWildMesh.h:50
std::shared_ptr< SampleEnvelope > m_order2_envelope
Definition TetWildMesh.h:75
void init_from_delaunay_box_mesh(const std::vector< Eigen::Vector3d > &vertices)
Definition DelaunayBoxMesh.cpp:22
Parameters & m_tet_params
Definition TetWildMesh.h:70
Eigen::MatrixXd tet_barycenters(const std::vector< Tuple > &tets) const
Compute the winding number.
Definition TetWildMesh.cpp:460
void insertion_by_volumeremesher(const std::vector< Vector3d > &vertices, const std::vector< std::array< size_t, 3 > > &faces, std::vector< Vector3r > &v_rational, std::vector< std::array< size_t, 3 > > &facets_after, std::vector< bool > &is_v_on_input, std::vector< std::array< size_t, 4 > > &tets_after, std::vector< bool > &tet_face_on_input_surface)
Conformally insert the input surface into a background tet mesh, via the exact arrangement (vol_rem::...
Definition VolumemesherInsertion.cpp:41
bool is_open_boundary_edge(const Tuple &e) override
Definition VolumemesherInsertion.cpp:473
void split_after_vertex(const size_t vid, const bool is_open_boundary) override
Application metadata not represented by the shared vertex attributes.
Definition TetWildMesh.h:91
void init_vertex_order()
Compute the vertex order for every vertex.
Definition TetWildMesh.cpp:804
std::vector< std::string > m_input_names
Definition TetWildMesh.h:79
std::shared_ptr< SampleEnvelope > smoothing_energy_envelope(const size_t vid) const override
Envelope a vertex is pulled toward while smoothing.
Definition TetWildMesh.cpp:68
size_t refine_sizing_around_worst(double max_energy) override
Escape a stuck max energy by refining the sizing field around the worst elements.
Definition TetWildMesh.cpp:315
bool is_vertex_on_boundary(const size_t vid)
Definition TetWildMesh.cpp:748
bool collapse_before_vertex(size_t v1, size_t v2, double edge_length) override
Definition TetWildMesh.h:95
double cell_quality(const size_t tid) const override
The quality of cell tid, and how to write it.
Definition TetWildMesh.h:84
void mesh_improvement_legacy(int max_its=80)
Call the original TetWild code.
Definition TetWildMesh.cpp:79
Definition concurrent_map.hpp:66
Definition enumerable_thread_specific.hpp:26
Definition AttributeCollection.hpp:36
double w_amips
Definition OptimizerParameters.h:154
Definition TetOptimizerMesh.h:48
The fields shared with triwild and simwild live in wmtk::OptimizerParameters.
Definition Parameters.h:8
tetwild's per-vertex additions to the shared VertexAttributes.
Definition TetWildMesh.h:60
bool m_is_on_open_boundary
Definition TetWildMesh.h:64