Wildmeshing Toolkit
Loading...
Searching...
No Matches
TriOptimizerMesh.h
1#pragma once
2
3#include <wmtk/OptimizerParameters.h>
4#include <wmtk/RationalPositions.h>
5#include <wmtk/SurfaceTagAttributes.h>
6#include <wmtk/TriMesh.h>
7#include <wmtk/Types.hpp>
8#include <wmtk/envelope/Envelope.hpp>
9#include <wmtk/optimization/SmoothVertex.hpp>
10#include <wmtk/optimization/solver.hpp>
11#include <wmtk/threading/enumerable_thread_specific.hpp>
12
13#include <polysolve/nonlinear/Problem.hpp>
14
15#include <atomic>
16#include <limits>
17#include <map>
18#include <memory>
19#include <set>
20#include <vector>
21
22namespace wmtk {
23
38{
39public:
41 {
42 Vector2d m_posf; // position as double
43 Vector2r m_pos; // exact position in rational
49 bool m_is_rounded = false;
50
51 bool m_is_on_surface = false;
52 std::vector<int> on_bbox_faces;
53
54 double m_sizing_scalar = 1;
55
56 size_t partition_id = 0;
57
59 VertexAttributes(const Vector2d& p)
60 : m_posf(p)
61 , m_pos(to_rational(p))
62 , m_is_rounded(true)
63 {}
64 VertexAttributes(const Vector2r& p)
65 : m_posf(to_double(p))
66 , m_pos(p)
67 {}
68 };
69
70 using EdgeAttributes = wmtk::SurfaceTagAttributes;
71
73 {
74 double m_quality;
75 double m_winding_number = 0;
76 std::set<int64_t> tags;
77 int part_id = -1;
78 };
79
80 using VertAttCol = AttributeCollection<VertexAttributes>;
81 using EdgeAttCol = AttributeCollection<EdgeAttributes>;
82 using FaceAttCol = AttributeCollection<FaceAttributes>;
83
84 VertAttCol m_vertex_attribute;
85 EdgeAttCol m_edge_attribute;
86 FaceAttCol m_face_attribute;
87
96
111
122
131 static constexpr double MAX_ENERGY = 1e50;
132
136
137 std::shared_ptr<SampleEnvelope> m_envelope;
138 double m_envelope_eps = -1;
139
142 double m_s_amips = -1;
143 double m_s_envelope = -1;
144
146 m_solver;
147
150
151 bool m_collapse_limit_length = true;
152 int m_debug_print_counter = 0;
153
154 size_t m_tags_count = 0;
155 std::map<int64_t, std::string> m_tag_id_to_name;
156 std::map<std::string, int64_t> m_tag_name_to_id;
157
159 : m_params(params)
160 {
161 m_vertex_attr_group.add(&m_vertex_attribute);
162 p_vertex_attrs = &m_vertex_attr_group;
163 m_edge_attr_group.add(&m_edge_attribute);
164 p_edge_attrs = &m_edge_attr_group;
165 m_face_attr_group.add(&m_face_attribute);
166 p_face_attrs = &m_face_attr_group;
167
168 m_s_amips = 1.;
173 m_s_envelope = 1. / (m_params.eps * m_params.eps);
174 }
175 ~TriOptimizerMesh() override = default;
176
177 size_t get_partition_id(const Tuple& loc) const
178 {
179 return m_vertex_attribute[loc.vid(*this)].partition_id;
180 }
181 void partition_mesh();
182 void partition_mesh_morton();
183
184 double get_length2(const Tuple& l) const;
185
194 bool is_inverted(const std::array<size_t, 3>& vs) const;
195 bool is_inverted(const Tuple& loc) const;
196 bool is_inverted(const size_t fid) const;
198 bool is_inverted_f(const Tuple& loc) const;
199 bool is_inverted_f(const size_t fid) const;
200
201 double get_quality(const std::array<size_t, 3>& vs) const;
202 double get_quality(const Tuple& loc) const;
203 double get_quality(const size_t fid) const;
204
205 std::tuple<double, double> get_max_avg_energy();
206
209 void mesh_improvement(int max_its = 80);
210 std::tuple<double, double> local_operations(
211 const std::array<int, 4>& ops,
212 bool collapse_limit_length = true);
213
214 std::set<simplex::Edge> m_force_split_edges;
215 size_t m_force_split_count = 0;
216 std::unique_ptr<std::atomic<int>[]> m_high_valence_claim;
217 size_t m_high_valence_claim_size = 0;
218 std::atomic<size_t> m_high_valence_rejects = 0;
219
220 bool is_force_split_edge(const size_t v1, const size_t v2) const
221 {
222 return m_force_split_edges.find(simplex::Edge(v1, v2)) != m_force_split_edges.end();
223 }
224
225 void split_all_edges();
226 bool split_edge_before(const Tuple& t) override;
227 bool split_edge_after(const Tuple& loc) override;
228
229 void collapse_all_edges(bool is_limit_length = true);
230 bool collapse_edge_before(const Tuple& t) override;
231 bool collapse_edge_after(const Tuple& t) override;
232
244 size_t coarsen_mesh();
245
253 bool coarsen_collapse_edge(const Tuple& e, std::vector<Tuple>& new_tris);
254
257 {
258 size_t accepted = 0;
259 size_t cells_before = 0;
260 size_t cells_after = 0;
261 double max_energy_before = 0.;
262 double max_energy_after = 0.;
263 };
264 CoarsenStats m_coarsen_stats;
265
273 size_t swap_all_edges();
274 double swap_weight(const Tuple& t) const;
275 bool swap_edge_before(const Tuple& t) override;
276 bool swap_edge_after(const Tuple& t) override;
277
285 void smooth_all_vertices(size_t n_iters = 1);
286 bool smooth_before(const Tuple& t) override;
287 bool smooth_after(const Tuple& t) override;
288
289 Vector2d smoothing_position(size_t vid) const;
290 void set_smoothing_position(size_t vid, const Vector2d& p);
291 virtual bool smoothing_position_is_allowed(size_t vid, const Vector2d& p) const = 0;
292
293 double active_quality_threshold() const
294 {
295 return m_params.skip_good_regions_margin * m_params.stop_energy;
296 }
297 virtual std::vector<size_t> active_vertices() const;
298
312 virtual double quality_rel(const size_t fid) const
313 {
314 return m_face_attribute.at(fid).m_quality / m_params.stop_energy;
315 }
316
321 bool round(const Tuple& v);
322
323protected:
326 virtual std::tuple<double, double> optimization_quality_stats();
327 virtual double optimization_stop_metric() const { return m_params.stop_energy; }
328 virtual size_t refine_sizing_around_worst(double max_metric) = 0;
329 virtual bool optimization_stop_at_float() const { return false; }
330
331 virtual void collapse_pass_begin() {}
332 virtual void collapse_pass_end(size_t) {}
333 virtual bool collapse_before_vertex(size_t, size_t) { return true; }
334 virtual bool collapse_quality_allowed(size_t v1, size_t, double q, double ring_max) const
335 {
336 return !m_vertex_attribute.at(v1).m_is_rounded || q <= m_params.stop_energy ||
337 q <= ring_max;
338 }
339 virtual void collapse_after_vertex(size_t, size_t) {}
340
341 virtual bool split_adjust_position(size_t, const std::vector<Tuple>&) { return true; }
342 virtual void split_after_vertex(size_t) {}
343
344 virtual void write_smoothing_debug_output(const std::string& path) const = 0;
345
346 // RationalPositions supplies round_all_vertices() and round_and_check_all_rounded() on
347 // top of these three.
348 std::vector<size_t> all_vertex_ids() const override;
349 bool vertex_is_rounded(const size_t vid) const override
350 {
351 return m_vertex_attribute.at(vid).m_is_rounded;
352 }
353 // Equivalent to round() on the tuple get_vertices() would have yielded: round() reads only
354 // the vid and the one-ring, and the one-ring query is answered from
355 // m_vertex_connectivity[vid] regardless of which cell the tuple names.
356 bool round_vertex(const size_t vid) override { return round(tuple_from_vertex(vid)); }
357
358public:
359 bool is_edge_on_surface(const Tuple& loc) const;
360 bool is_edge_on_surface(const std::array<size_t, 2>& vids) const;
361 bool is_edge_on_bbox(const Tuple& loc) const;
362 bool is_edge_on_bbox(const std::array<size_t, 2>& vids) const;
363
364 bool vertex_is_on_surface(const size_t vid) const override
365 {
366 return m_vertex_attribute.at(vid).m_is_on_surface ||
367 !m_vertex_attribute.at(vid).on_bbox_faces.empty();
368 }
369 bool edge_is_on_surface(const std::array<size_t, 2>& vids) const override
370 {
371 if (!vertex_is_on_surface(vids[0]) || !vertex_is_on_surface(vids[1])) {
372 return false;
373 }
374
375 const auto [_, eid] = tuple_from_edge(vids);
376 bool on_surface = m_edge_attribute.at(eid).m_is_surface_fs;
377 bool on_bbox = m_edge_attribute.at(eid).m_is_bbox_fs >= 0;
378 return on_surface || on_bbox;
379 }
380
393 virtual std::shared_ptr<SampleEnvelope> surface_envelope_for_edge(
394 const std::array<size_t, 2>& vids) const
395 {
396 return m_envelope;
397 }
398
401 bool surface_segment_is_outside(const size_t a, const size_t b) const
402 {
403 const std::shared_ptr<SampleEnvelope> env = surface_envelope_for_edge({{a, b}});
404 if (!env) return false;
405 const auto& VA = m_vertex_attribute;
406 return env->is_outside(std::array<Vector2d, 2>{{VA[a].m_posf, VA[b].m_posf}});
407 }
408
409 std::vector<std::array<size_t, 2>> get_edges_by_condition(
410 std::function<bool(const EdgeAttributes&)> cond) const;
411
420 void gradation_smooth_sizing(double grade, const std::vector<size_t>& seeds);
421
422protected:
424 {
425 size_t v1_id = 0;
426 size_t v2_id = 0;
427 double max_quality_before = 0.;
428 EdgeAttributes old_e_attrs;
429 std::map<simplex::Edge, EdgeAttributes> changed_edges;
430 std::map<size_t, FaceAttributes> faces;
431 };
433
435 {
436 size_t v1_id = 0;
437 size_t v2_id = 0;
438 double max_energy = 0.;
439 double edge_length = 0.;
440 std::vector<std::pair<EdgeAttributes, std::array<size_t, 2>>> changed_edges;
441 std::vector<std::array<size_t, 2>> surface_edges;
442 std::vector<size_t> changed_fids;
443 std::vector<double> changed_energies;
447 };
449
451 bool m_coarsen_mode = false;
452
453private:
455 {
456 double max_energy;
457 std::map<simplex::Edge, EdgeAttributes> changed_edges;
458 std::set<int64_t> face_tags;
459 };
461
471 {
472 std::vector<size_t> ring; // vertices to re-smooth, BFS order
473 std::vector<size_t> frontier;
474 std::vector<size_t> next;
475 std::vector<size_t> one_ring;
476 std::vector<uint32_t> stamp;
477 uint32_t epoch = 0;
478 VertexAttributes saved_vertex;
479 std::vector<std::pair<size_t, double>> saved_qualities;
480 };
482
484 const std::vector<size_t>&
485 collect_vertex_ball(const size_t* seeds, size_t n_seeds, int n, CoarsenScratch& scr) const;
486
489 double region_max_quality_rel(const std::vector<size_t>& vids) const;
490
492 bool smooth_vertex_reversible(size_t vid, CoarsenScratch& scr);
493
494 size_t collapse_all_edges_impl(bool is_limit_length, int lock_ring, size_t max_passes = 0);
495};
496
497} // namespace wmtk
Several attribute collections for the same simplex type, behind one container.
Definition AttributeCollection.hpp:132
The rounded/exact bookkeeping shared by every mesh that keeps both coordinates.
Definition RationalPositions.h:21
Whether a codimension-1 simplex is tracked surface, and which bbox side it lies on.
Definition SurfaceTagAttributes.h:15
int m_is_bbox_fs
Which bbox side this simplex is on; -1 for none.
Definition SurfaceTagAttributes.h:20
bool m_is_surface_fs
Is this simplex part of the tracked surface.
Definition SurfaceTagAttributes.h:18
Definition TriMesh.h:31
Definition TriMesh.h:27
Tuple tuple_from_edge(size_t vid1, size_t vid2, size_t fid) const
Definition TriMesh.cpp:2204
Tuple tuple_from_vertex(size_t vid) const
Definition TriMesh.h:906
What triwild and simwild's 2D mesh share.
Definition TriOptimizerMesh.h:38
void smooth_all_vertices(size_t n_iters=1)
Run TriWild's vertex-smoothing pass.
Definition TriOptimizerMeshSmooth.cpp:62
bool smooth_after(const Tuple &t) override
User specified modifications and desideras after an edge smooth.
Definition TriOptimizerMeshSmooth.cpp:25
bool is_inverted_f(const Tuple &loc) const
Inversion check using only the double positions.
Definition TriOptimizerMesh.cpp:399
bool vertex_is_rounded(const size_t vid) const override
Whether this vertex's double position is currently trusted.
Definition TriOptimizerMesh.h:349
bool vertex_is_on_surface(const size_t vid) const override
Is a vertex part of the substructure.
Definition TriOptimizerMesh.h:364
std::vector< size_t > all_vertex_ids() const override
Every live vertex, in the mesh's own iteration order.
Definition TriOptimizerMesh.cpp:459
bool smooth_vertex_reversible(size_t vid, CoarsenScratch &scr)
One smoothing attempt on vid, restoring everything it wrote if it is rejected.
Definition TriOptimizerMeshCollapse.cpp:467
AttributeContainerGroup m_edge_attr_group
What p_edge_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:110
AttributeContainerGroup m_vertex_attr_group
What p_vertex_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:95
virtual std::shared_ptr< SampleEnvelope > surface_envelope_for_edge(const std::array< size_t, 2 > &vids) const
Envelope the tracked-surface segment vids must stay inside.
Definition TriOptimizerMesh.h:393
size_t coarsen_mesh()
Coarsen the mesh without letting the max energy rise.
Definition TriOptimizerMeshCollapse.cpp:508
bool swap_edge_before(const Tuple &t) override
User specified preparations and desideratas for an edge swap including 1.can't swap on boundary edge....
Definition TriOptimizerMesh.cpp:269
virtual double quality_rel(const size_t fid) const
A face's quality relative to the quality it is required to reach; <= 1 means it meets it.
Definition TriOptimizerMesh.h:312
bool coarsen_collapse_edge(const Tuple &e, std::vector< Tuple > &new_tris)
One collapse under the coarsening rules, outside a coarsening pass.
Definition TriOptimizerMeshCollapse.cpp:496
static constexpr double MAX_ENERGY
The sentinel get_quality returns for a face AMIPS2D cannot score.
Definition TriOptimizerMesh.h:131
void gradation_smooth_sizing(double grade, const std::vector< size_t > &seeds)
Monotone (only-decreasing) gradation smoothing of the sizing field.
Definition TriOptimizerMesh.cpp:325
bool m_coarsen_mode
Set for the duration of coarsen_mesh(); read-only while a pass is running.
Definition TriOptimizerMesh.h:451
size_t swap_all_edges()
Run TriWild's quality-improving interior edge-flip pass.
Definition TriOptimizerMesh.cpp:222
const std::vector< size_t > & collect_vertex_ball(const size_t *seeds, size_t n_seeds, int n, CoarsenScratch &scr) const
Vertices within n edges of seeds, in BFS order. Uses coarsen_scratch.
Definition TriOptimizerMeshCollapse.cpp:400
bool edge_is_on_surface(const std::array< size_t, 2 > &vids) const override
Is an edge part of the substructure.
Definition TriOptimizerMesh.h:369
TriOptimizerMesh(OptimizerParameters &params)
Definition TriOptimizerMesh.h:158
bool surface_segment_is_outside(const size_t a, const size_t b) const
Definition TriOptimizerMesh.h:401
AttributeContainerGroup m_face_attr_group
What p_face_attrs points at, so a derived class can register more.
Definition TriOptimizerMesh.h:121
optimization::SmoothRejectCounters m_smooth_rejects
Why smoothing attempts were refused, reported once per pass.
Definition TriOptimizerMesh.h:149
OptimizerParameters & m_params
Definition TriOptimizerMesh.h:135
double m_s_amips
Definition TriOptimizerMesh.h:142
bool swap_edge_after(const Tuple &t) override
User specified modifications and desideras after an edge swap.
Definition TriOptimizerMesh.cpp:298
bool collapse_edge_after(const Tuple &t) override
User specified modifications and desideratas after an edge collapse.
Definition TriOptimizerMeshCollapse.cpp:325
bool round_vertex(const size_t vid) override
Definition TriOptimizerMesh.h:356
bool round(const Tuple &v)
Round a vertex position to floating point, if that inverts no incident face.
Definition TriOptimizerMesh.cpp:470
int m_iterations_used
Shared TriWild/SimWild outer optimization schedule.
Definition TriOptimizerMesh.h:208
bool split_edge_after(const Tuple &loc) override
User specified modifications and desideratas after an edge split.
Definition TriOptimizerMeshSplit.cpp:177
double region_max_quality_rel(const std::vector< size_t > &vids) const
Definition TriOptimizerMeshCollapse.cpp:456
virtual std::tuple< double, double > optimization_quality_stats()
Definition TriOptimizerMesh.cpp:27
bool split_edge_before(const Tuple &t) override
User specified preparations and desideratas for an edge split.
Definition TriOptimizerMeshSplit.cpp:101
bool collapse_edge_before(const Tuple &t) override
User specified preparations and desideratas for an edge collapse including the link check as collapse...
Definition TriOptimizerMeshCollapse.cpp:90
bool smooth_before(const Tuple &t) override
User specified preparations and desideratas for an edge smooth.
Definition TriOptimizerMeshSmooth.cpp:12
Definition Simplex.hpp:46
Definition enumerable_thread_specific.hpp:26
The parameters tetwild, triwild and simwild all share.
Definition OptimizerParameters.h:28
Per-thread buffers for the coarsening composite, so it allocates nothing.
Definition TriOptimizerMesh.h:471
What coarsen_mesh() achieved, for the run report. Zeroed when the pass is off.
Definition TriOptimizerMesh.h:257
Definition TriOptimizerMesh.h:435
double region_max_rel_before
Definition TriOptimizerMesh.h:446
Definition TriOptimizerMesh.h:73
Definition TriOptimizerMesh.h:424
Definition TriOptimizerMesh.h:455
Definition TriOptimizerMesh.h:41
bool m_is_rounded
Definition TriOptimizerMesh.h:49
Why a smoothing attempt was refused, counted per pass.
Definition SmoothVertex.hpp:31