Wildmeshing Toolkit
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Types | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
wmtk::TetOptimizerMesh Class Referenceabstract

What tetwild and simwild's 3D mesh share. More...

#include <TetOptimizerMesh.h>

Inheritance diagram for wmtk::TetOptimizerMesh:
wmtk::TetMesh wmtk::RationalPositions wmtk::components::simwild::SimWildMesh wmtk::components::tetwild::TetWildMesh wmtk::components::topological_offset::TopoOffsetTetMesh wmtk::components::manifold_extraction::ManExtractTetMesh

Classes

struct  CoarsenScratch
 Per-thread buffers for the coarsening composite, so it allocates nothing. More...
 
struct  CoarsenStats
 What coarsen_mesh() achieved, for the run report. Zeroed when the pass is off. More...
 
struct  CollapseInfoCache
 
struct  FeatureEdgeAttributes
 Per-edge feature tag: does this tet edge tile an input feature curve. More...
 
struct  FeaturePointAttributes
 
struct  OpHookReasons
 A kind's hook refusals by reason: the nonzero leaves as "name=n" and their sums. More...
 
struct  SplitInfoCache
 
struct  SurfaceFolds
 
struct  SwapInfoCache
 
struct  VertexAttributes
 

Public Types

using FaceAttributes = wmtk::SurfaceTagAttributes
 
using VertAttCol = AttributeCollection< VertexAttributes >
 
using FaceAttCol = AttributeCollection< FaceAttributes >
 
using EdgeAttCol = AttributeCollection< FeatureEdgeAttributes >
 
using PositionKey = std::array< std::array< double, 3 >, 3 >
 A tracked face by its corners' positions, sorted.
 
using SurfaceTopoSignature = wmtk::utils::SurfaceTopoSignature
 
- Public Types inherited from wmtk::TetMesh
enum class  OpKind : int {
  split , collapse , swap_32 , swap_44 ,
  swap_56 , swap_face , COUNT
}
 
enum class  OpEvent : int {
  attempt , before_hook , link_condition , no_return_tet ,
  duplicate_tet , topology , valence , boundary ,
  exists , no_case_allowed , no_better_case , out_of_slots ,
  after_hook , invariants , committed , screened ,
  COUNT
}
 
template<typename T >
using vector = std::vector< T >
 
using VertexMutex = wmtk::threading::VertexMutex
 

Public Member Functions

std::vector< std::array< size_t, 3 > > oriented_tracked_faces () const
 The tracked surface as an oriented soup: each tracked face emitted |m_orientation| times, in the orientation the input gave it. Faces whose sheets cancel are left out. Vertex ids index m_vertex_attribute.
 
std::vector< std::pair< std::array< size_t, 2 >, int > > tracked_surface_boundary () const
 Mesh edges where the oriented tracked surface has a boundary.
 
void throw_if_in_operation_pass (const char *call) const
 
void add_edge_attributes (AbstractAttributeContainer *c)
 Register an edge collection with m_edge_attr_group and point p_edge_attrs at the group.
 
void enable_feature_edge_tracking ()
 Turn on feature-edge tracking. The collection joins m_edge_attr_group beside whatever the application registered there.
 
bool vertex_has_feature_edge (size_t vid) const
 
size_t substructure_order_of_edge (const std::array< size_t, 2 > &vids) const override
 The orders substructure_link_condition consults, overridable so an application can widen the 1D substructure beyond what the surface complex derives.
 
size_t substructure_order_of_vertex (size_t vid) const override
 
void substructure_feature_neighbors (size_t vid, std::vector< size_t > &out) const override
 One-ring vertices x of vid where (vid, x) is 1D substructure NOT derivable from the surface complex (feature edges through the interior, for instance). The link condition's order-2 edge collection walks surface faces and would never see them.
 
bool feature_edges_at_vertex_inside (size_t vid) const
 
virtual bool smoothing_position_is_allowed (const size_t vid, const Vector3d &p) const
 
bool is_force_split_edge (const size_t v1, const size_t v2) const
 
bool storage_grows_on_demand () const override
 
bool split_edge_is_due (const Tuple &e) const
 
 TetOptimizerMesh (OptimizerParameters &params, std::shared_ptr< Envelope > env)
 
virtual double cell_quality (const size_t tid) const =0
 The quality of cell tid, and how to write it.
 
virtual void set_cell_quality (const size_t tid, const double q)=0
 
virtual double quality_rel (const size_t tid) const
 A cell's quality relative to the quality it is required to reach; <= 1 means it meets it.
 
void compute_vertex_partition ()
 
void compute_vertex_partition_morton ()
 
size_t get_partition_id (const Tuple &loc) const
 
double get_length2 (const Tuple &l) const
 
bool is_inverted (const std::array< size_t, 4 > &vs) const
 
bool is_inverted (const Tuple &loc) const
 
bool is_inverted_f (const Tuple &loc) const
 Inversion check using only the double positions.
 
double get_quality (const std::array< size_t, 4 > &vs) const
 
double get_quality (const Tuple &loc) const
 
std::tuple< double, double > get_max_avg_energy ()
 
virtual void update_attributes ()
 Update the attributes of the mesh after an iteration of operations.
 
void update_attributes_and_history ()
 update_attributes(), then the change it made to the tracked surface, if recording one.
 
void record_surface_history (const std::string &metadata)
 
std::optional< history::SurfaceHistory > finish_surface_history (const history::SurfaceHistory *input=nullptr)
 Bring the recorded surface up to date with the tracked faces, stop recording, log what the history holds and return it, for the application to save (ComponentIO:: save_history). None if not recording.
 
void record_volume_history ()
 
std::optional< std::vector< uint8_t > > finish_volume_history (const std::map< int64_t, std::string > &tag_names={})
 
bool is_tracked_face (size_t tid, int j) const override
 The faces with m_is_surface_fs, for a surface history (TetMesh::start_surface_history).
 
std::array< size_t, 3 > orient_tracked_face (const std::array< size_t, 3 > &f, const std::vector< size_t > &tets) const override
 
std::vector< std::array< size_t, 2 > > tracked_feature_edges () const override
 The tagged feature edges (m_feature_edge_attribute) that are edges of tracked faces.
 
bool checks_tracked_surface () const override
 m_params.check_surface_folds; see there.
 
void tracked_surface_before (const std::vector< size_t > &vs, bool all) override
 
bool tracked_surface_after (const std::vector< size_t > &vs, bool all) override
 
Eigen::Vector3d tracked_area_normal (const std::vector< std::array< size_t, 3 > > &faces) const
 
size_t tracked_not_facing (const std::vector< std::array< size_t, 3 > > &faces, const Eigen::Vector3d &n) const
 
size_t tracked_star_folds (const std::vector< std::array< size_t, 3 > > &faces) const
 
void mesh_improvement (int max_its=80)
 
std::tuple< double, double > local_operations (const std::array< int, 4 > &ops, bool collapse_limit_length=true)
 
bool round (const Tuple &v)
 Round a vertex position to floating point, if that inverts no incident tet.
 
bool is_edge_on_surface (const Tuple &loc)
 
bool is_edge_on_bbox (const Tuple &loc)
 
virtual bool is_open_boundary_edge (const Tuple &e)
 Whether edge e lies on the boundary of the tracked surface.
 
int edge_incident_surface_face_count (const Tuple &e)
 How many of the faces incident to edge e are on the tracked surface.
 
virtual std::shared_ptr< Envelope > surface_envelope_for_face (const std::array< size_t, 3 > &vids, const FaceAttributes &attr) const
 Envelope the tracked-surface triangle vids must stay inside, given the attributes attr it carries – or, for a triangle an operation is creating, the ones the operation is about to write there.
 
bool surface_triangle_is_outside (const size_t a, const size_t b, const size_t c, const FaceAttributes &attr) const
 
bool vertex_is_on_surface (const size_t vid) const override
 Is a vertex part of the substructure.
 
bool face_is_on_surface (const size_t fid) const override
 Is a face part of the substructure.
 
size_t get_order_of_vertex (const size_t vid) const override
 Get the order of a vertex.
 
std::vector< std::array< size_t, 3 > > get_faces_by_condition (std::function< bool(const FaceAttributes &)> cond) const
 
void output_faces (std::string file, std::function< bool(const FaceAttributes &)> cond)
 
void gradation_smooth_sizing (double grade, const std::vector< size_t > &seeds)
 Grade the refined sizing region into its surroundings (monotone, only lowers).
 
double active_quality_threshold () const
 Cell-quality threshold above which a tet is "active" (worth operating on) for the skip-good-regions filter.
 
virtual std::vector< size_t > active_vertices () const
 
void split_all_edges ()
 
bool split_edge_before (const Tuple &t) override
 User specified preparations and desideratas for an edge split before changing the connectivity.
 
bool split_edge_after (const Tuple &loc) override
 This function computes the attributes for the added simplices. User specified modifications and desideratas for after an edge split.
 
void collapse_all_edges (bool is_limit_length=true)
 
bool collapse_edge_before (const Tuple &t) override
 User specified preparations and desideratas for an edge collapse before changing the connectivity.
 
bool collapse_edge_after (const Tuple &t) override
 User specified modifications and desideratas for after an edge collapse.
 
size_t coarsen_mesh ()
 Coarsen the mesh without letting the max energy rise.
 
bool coarsen_collapse_edge (const Tuple &e, std::vector< Tuple > &new_tets)
 One collapse under the coarsening rules, outside a coarsening pass.
 
size_t swap_all_edges_32 ()
 
bool swap_edge_before (const Tuple &t) override
 User specified preparations and desideratas for an 3-2 edge swap before changing the conenctivity.
 
bool swap_edge_after (const Tuple &t) override
 User specified modifications and desideratas for after a 3-2 edge swap.
 
size_t swap_all_edges_44 ()
 
bool swap_edge_44_before (const Tuple &t) override
 User specified preparations and desideratas for an 4-4 edge swap before changing the connectivity.
 
bool swap_edge_44_accept_case (const std::array< size_t, 2 > &new_edge) override
 Filter which of the 4-4 orientations may be chosen.
 
bool swap_edge_44_after (const Tuple &t) override
 User specified modifications and desideratas for after a 4-4 edge swap.
 
size_t swap_all_edges_56 ()
 
bool swap_edge_56_before (const Tuple &t) override
 User specified preparations and desideratas for a 5-6 edge swap before changing the connectivity.
 
bool swap_edge_56_accept_case (const std::array< size_t, 3 > &new_face) override
 Filter which of the 5-6 orientations may be chosen.
 
bool swap_edge_56_after (const Tuple &t) override
 User specified modifications and desideratas for after a 5-6 edge swap.
 
size_t swap_all_faces ()
 
bool swap_face_before (const Tuple &t) override
 User specified preparations and desideratas for an 2-3 face swap befroe changing the geometry.
 
bool swap_face_after (const Tuple &t) override
 User specified modifications and desideratas for after a 2-3 face swap.
 
size_t swap_all_edges_all ()
 
bool prepare_surface_flip (const Tuple &t, const std::vector< size_t > &incident_tets)
 
SurfaceTopoSignature surface_topology_signature () const
 
void warn_if_surface_topology_changed (const SurfaceTopoSignature &before, const char *where) const
 
double swap_edge_44_energy (const std::vector< std::array< size_t, 4 > > &tets, const int op_case) override
 User specified energy to decide which of the 4 possible orientations should be chosen.
 
double swap_edge_56_energy (const std::vector< std::array< size_t, 4 > > &tets, const int op_case) override
 User specified energy to decide which of the 5 possible orientations should be chosen.
 
virtual std::shared_ptr< Envelope > smoothing_containment_envelope (const size_t, const std::array< size_t, 3 > &face, const FaceAttributes &attr) const
 Envelope the smoother checks tracked face face (attributes attr) at the moved vertex vid against; null skips the face.
 
virtual std::shared_ptr< Envelope > smoothing_energy_envelope (const size_t vid) const =0
 Envelope a surface vertex is pulled toward while smoothing. A real envelope, never a composite (see smoothing_containment_envelope()). A derived mesh may select an order-2 or feature envelope here.
 
virtual bool boundary_edges_at_vertex_inside (size_t) const
 
virtual std::shared_ptr< polysolve::nonlinear::Problem > smoothing_extra_energy (const size_t) const
 An extra term the application adds to this vertex's smoothing objective, or null.
 
virtual double smoothing_cell_energy (const size_t, const double quality) const
 The number the shared smoother compares for one cell, given the cell's quality (AMIPS^3) at the position being tested. Its quality veto compares the max of this over the ring before and after the move, and the default smoothing_ring_energy() is the same max.
 
virtual double smoothing_ring_energy (const std::vector< Tuple > &ring, const bool stored) const
 The number the shared smoother's projected step compares for a whole one-ring: a vertex held on a surface takes the first projected candidate whose value is strictly below the value before the move.
 
bool smooth_before (const Tuple &t) override
 The smoothing hooks. A derived class overriding them – or invariants(), which a smooth also runs – must read every attribute outside the smoothed vertex's star (other vertices, and the edges, faces and tets not incident to the vertex) through const access, e.g. std::as_const(m_vertex_attribute)[u].
 
bool smooth_after (const Tuple &t) override
 User specified modifications and desideratas for after smoothing a vertex.
 
void smooth_all_vertices (const size_t n_iters=1)
 
bool use_colored_smoothing () const
 Whether this pass smooths by color class (see OptimizerParameters::colored_smoothing).
 
void smooth_vertices_colored (const std::vector< std::pair< std::string, Tuple > > &ops)
 One smoothing sweep over ops (all "vertex_smooth"), one color class at a time.
 
virtual void log_smoothing_pass_accounting ()
 
virtual void smoothing_pass_done ()
 
bool invariants (const std::vector< Tuple > &t) override
 
virtual std::array< size_t, 3 > orient_tracked_face (const std::array< size_t, 3 > &f, const std::vector< size_t > &tets) const
 
std::array< size_t, 3 > orient_tracked_face (const std::array< size_t, 3 > &f) const
 
- Public Member Functions inherited from wmtk::TetMesh
size_t vert_capacity () const
 get the current largest global vid
 
size_t tet_capacity () const
 get the current largest global tid
 
size_t vertex_size () const
 get the number of unremoved verticies
 
size_t tet_size () const
 get the number of unremoved tets
 
void init (size_t n_vertices, const std::vector< std::array< size_t, 4 > > &tets)
 
void init_with_isolated_vertices (size_t n_vertices, const std::vector< std::array< size_t, 4 > > &tets)
 
void init (const MatrixXi &T)
 Generate the connectivity of the mesh from an IGL-style T matrix.
 
bool split_edge (const Tuple &t, std::vector< Tuple > &new_tets)
 
virtual bool collapse_edge (const Tuple &t, std::vector< Tuple > &new_tets)
 
bool link_condition (const Tuple &t)
 
bool collapse_edge_conn (const Tuple &loc0, size_t &v1_id, Tuple &new_loc, std::map< size_t, wmtk::TetMesh::VertexConnectivity > &rollback_vert_conn, std::vector< size_t > &n1_t_ids_copy, std::vector< size_t > &new_tet_id, std::vector< TetrahedronConnectivity > &old_tets)
 
bool collapse_edge_check_topology (const std::vector< size_t > &new_tet_id)
 Check topology after collapse connectivity change. This is a sanity check and should not be necessary.
 
void collapse_edge_rollback (size_t &v1_id, std::map< size_t, wmtk::TetMesh::VertexConnectivity > &rollback_vert_conn, std::vector< size_t > &n1_t_ids, std::vector< size_t > &new_tet_id, std::vector< TetrahedronConnectivity > &old_tets)
 
bool swap_edge_56 (const Tuple &t, std::vector< Tuple > &new_tets)
 
bool swap_edge_44 (const Tuple &t, std::vector< Tuple > &new_tets)
 
bool swap_edge (const Tuple &t, std::vector< Tuple > &new_tets)
 3-2 edge swap
 
bool swap_face (const Tuple &t, std::vector< Tuple > &new_tets)
 2-3 face swap
 
bool smooth_vertex (const Tuple &t)
 
bool split_tet (const Tuple &t, std::vector< Tuple > &new_tets)
 Split a tet in 4 tets.
 
bool split_face (const Tuple &t, std::vector< Tuple > &new_tets)
 Split a face in 3 faces.
 
void triangle_insertion (const std::vector< Tuple > &intersected_tets, const std::vector< Tuple > &intersected_edges, std::vector< size_t > &new_edge_vids, std::vector< size_t > &new_center_vids, std::vector< std::array< size_t, 4 > > &center_split_tets)
 Insert a triangle into a tetmesh, with known intersection information.
 
bool insert_point (const Tuple &t, std::vector< Tuple > &new_tets)
 Insert a point into a tetmesh inside a tet. In general position, this split a tet into 4. In face position, split two tets. In edge position, In point position, do nothing. It has no surface history hooks, and throws while a surface history is recording.
 
virtual bool insert_point_before (const Tuple &t)
 
virtual bool insert_point_after (std::vector< Tuple > &new_tets)
 
void consolidate_mesh ()
 cleans up the deleted vertices or tetrahedra, fixes the corresponding indices, and reset the version number. WARNING: it invalidates all tuples!
 
std::shared_ptr< history::TrackedSurfaceRecorder > start_surface_history (std::function< Eigen::Vector3d(size_t)> position)
 Record every change to the tracked surface from now on (see wmtk/history/TrackedRecorder.hpp).
 
void stop_surface_history ()
 Stop recording. The recorder keeps what it has.
 
size_t resync_surface_history ()
 
std::shared_ptr< history::VolumeRecorder > start_volume_history (std::function< Eigen::Vector3d(size_t)> position)
 Record, alongside the surface history, the tets around every operation that changes the tracked surface (wmtk/history/VolumeHistory.hpp): what a map of the volume needs. The surface history must be recording; a volume history is its own choice, since it takes far more room. position(v) is called as start_surface_history()'s is; a tet's region is its tet_tags().
 
void stop_volume_history ()
 Stop recording the volume. The recorder keeps what it has.
 
virtual std::vector< int64_t > tet_tags (size_t tid) const
 
std::vector< std::array< size_t, 3 > > tracked_faces () const
 Every tracked face, oriented by orient_tracked_face().
 
std::array< size_t, 3 > orient_tracked_face (const std::array< size_t, 3 > &f) const
 orient_tracked_face, finding the face's tets.
 
std::array< size_t, 3 > face_out_of (size_t tid, const std::array< size_t, 3 > &face) const
 The corners of face, a face of tet tid, ordered so that its normal points out of the tet – for a tet the right way round as TetOptimizerMesh has them, with its fourth vertex on the side of the first three's normal (orient3d negative).
 
std::vector< size_t > tets_of_face (const std::array< size_t, 3 > &f) const
 The tets with the face f, sorted: one on the boundary, two inside.
 
std::vector< Tuple > get_edges () const
 
std::vector< Tuple > get_faces () const
 
std::vector< Tuple > get_vertices () const
 
std::vector< Tuple > get_tets () const
 
virtual void for_each_face (const std::function< void(const TetMesh::Tuple &)> &)
 looping through all the unique edges and perform the given function
 
void set_preallocation_factor (double factor)
 Preallocation factor: init/consolidate reserve capacity = max(floor, ceil(factor * live_count)) so operations can grab fresh slots without resizing the storage. When a pass exhausts the reserved capacity the affected operations fail (and are retried later after a consolidate). Tune per application (e.g. from JSON); values < 1 are clamped to 1.
 
double preallocation_factor () const
 
bool slots_exhausted () const
 
void clear_slots_exhausted ()
 
size_t request_tet_slots (size_t n)
 
size_t request_vert_slots (size_t n)
 
void ensure_free_tet_capacity (size_t extra)
 
void ensure_free_vert_capacity (size_t extra)
 
bool op_refused (const OpKind k, const OpEvent e) const
 op_event() for a refusal, returning false so a site reads return op_refused(...).
 
bool op_screened (const OpKind k) const
 The end of a dry run that would have gone on to change the mesh: true, and counted.
 
Tuple tuple_from_edge (size_t tid, int local_eid) const
 get a Tuple from global tetra index and local edge index (from 0-5).
 
Tuple tuple_from_edge (const std::array< size_t, 2 > &vids) const
 get a Tuple from global vids of the 2 end of an edge
 
Tuple tuple_from_face (size_t tid, int local_fid) const
 get a Tuple from global tetra index and local face index (from 0-3).
 
std::tuple< Tuple, size_t > tuple_from_face (const std::array< size_t, 3 > &vids) const
 get a Tuple and the global face index from global vertex index of the face.
 
std::optional< std::tuple< Tuple, size_t > > try_tuple_from_face (const std::array< size_t, 3 > &vids) const
 tuple_from_face for callers where a missing face is an answer, not a bug.
 
size_t lowest_common_tet (size_t v0_id, size_t v1_id, size_t v2_id) const
 Lowest tet id incident to all three vertices, or size_t(-1) if there is none.
 
size_t vertex_valence (const size_t vid) const
 Number of tets incident to a vertex, in O(1).
 
std::tuple< Tuple, size_t > tuple_from_face (const simplex::Face &f) const
 
Tuple tuple_from_vertex (size_t vid) const
 get a Tuple from global vertex index
 
Tuple tuple_from_tet (size_t tid) const
 get a Tuple from global tetra index
 
Tuple tuple_from_vids (size_t vid0, size_t vid1, size_t vid2, size_t vid3) const
 Get a Tuple from global vertex IDs.
 
simplex::Tet simplex_from_tet (const Tuple &t) const
 
simplex::Tet simplex_from_tet (const size_t tid) const
 
simplex::Face simplex_from_face (const Tuple &t) const
 
simplex::Edge simplex_from_edge (const Tuple &t) const
 
Tuple switch_vertex (const Tuple &t) const
 wrapper function from Tuple::switch_vertex
 
Tuple switch_edge (const Tuple &t) const
 wrapper function from Tuple::switch_edge
 
Tuple switch_face (const Tuple &t) const
 wrapper function from Tuple::switch_face
 
std::optional< Tuple > switch_tetrahedron (const Tuple &t) const
 wrapper function from Tuple::switch_tetrahedron
 
std::vector< Tuple > get_one_ring_tets_for_vertex (const Tuple &t) const
 Get the one ring tets for a vertex.
 
const std::vector< size_t > & get_one_ring_tids_for_vertex (const Tuple &t) const
 Get the one ring tids for vertex.
 
const std::vector< size_t > & get_one_ring_tids_for_vertex (const size_t vid) const
 
std::vector< Tuple > get_one_ring_vertices_for_vertex (const Tuple &t) const
 Get the one ring vertices for a vertex.
 
std::vector< size_t > get_one_ring_vids_for_vertex (size_t vid, std::vector< size_t > &cache)
 Get the one ring vids for vertex.
 
std::vector< size_t > get_one_ring_vids_for_vertex (size_t vid) const
 Get the one ring vids for vertex.
 
std::vector< size_t > get_one_ring_vids_for_vertex_adj (size_t vid) const
 Duplicate of the function TetMesh::get_one_ring_vids_for_vertex.
 
std::vector< size_t > get_one_ring_vids_for_vertex_adj (size_t vid, std::vector< size_t > &cache)
 Duplicate of the function TetMesh::get_one_ring_vids_for_vertex.
 
std::vector< Tuple > get_incident_tets_for_edge (const Tuple &t) const
 Get the incident tets for edge.
 
std::vector< Tuple > get_incident_tets_for_edge (const size_t vid0, const size_t vid1) const
 
std::vector< size_t > get_incident_tids_for_edge (const Tuple &t) const
 
std::vector< size_t > get_incident_tids_for_edge (const size_t vid0, const size_t vid1) const
 
std::vector< Tuple > get_one_ring_tets_for_edge (const Tuple &t) const
 Get the one ring tets for edge.
 
std::vector< std::array< size_t, 3 > > vertex_adjacent_boundary_faces (const Tuple &t) const
 
std::array< Tuple, 4 > oriented_tet_vertices (const Tuple &t) const
 
std::array< size_t, 4 > oriented_tet_vids (const Tuple &t) const
 
std::array< size_t, 4 > oriented_tet_vids (const size_t tid) const
 
std::array< Tuple, 3 > get_face_vertices (const Tuple &t) const
 Get the 3 vertices of a face represented by Tuple.
 
std::array< size_t, 3 > get_face_vids (const Tuple &t) const
 
std::array< Tuple, 6 > tet_edges (const Tuple &t) const
 get the 6 edges of a tet represented by Tuples
 
void check_tuple_validity (const Tuple &t) const
 
bool check_mesh_connectivity_validity () const
 checks the validity of the connectivity of the mesh. Including the validity of each Tuple
 
void remove_tets_by_ids (const std::vector< size_t > &tids)
 remove the tetrahedrons in the mesh that have given tet ids
 
void start_protect_attributes ()
 
void release_protect_attributes ()
 
void rollback_protected_attributes ()
 
int release_vertex_mutex_in_stack ()
 
int release_vertex_mutex_to (size_t mark)
 Release the mutexes taken since the release stack held mark entries.
 
bool try_set_vertex_mutex_n_ring (const Tuple &v, int threadid, int n)
 Lock every vertex within graph distance n of v, the seed included.
 
bool try_set_vertex_mutex_n_ring (size_t vid, int threadid, int n)
 
bool try_set_edge_mutex_n_ring (const Tuple &e, int threadid, int n)
 try_set_vertex_mutex_n_ring seeded from both ends of an edge.
 
bool try_set_face_mutex_n_ring (size_t v1, size_t v2, size_t v3, int threadid, int n)
 try_set_vertex_mutex_n_ring seeded from the three vertices of a face.
 
void for_each_edge (const std::function< void(const TetMesh::Tuple &)> &)
 perform the given function for each edge
 
void for_each_vertex (const std::function< void(const TetMesh::Tuple &)> &)
 perform the given function for each vertex
 
void for_each_tetra (const std::function< void(const TetMesh::Tuple &)> &)
 perform the given function for each tet
 
simplex::SimplexCollection get_surface_faces_for_vertex (const size_t vid) const
 Get all faces on the surface that are incident to vid.
 
simplex::SimplexCollection get_surface_faces_for_edge (const std::array< size_t, 2 > &vids) const
 Get all faces on the surface that are incident to the edge.
 
size_t get_num_surface_faces_for_edge (const std::array< size_t, 2 > &vids) const
 Get the number of surface faces incident to the edge.
 
size_t compute_vertex_order (const size_t vid) const
 Compute the vertex order for a single vertex.
 
size_t get_order_of_edge (const std::array< size_t, 2 > &vids) const
 Compute the order of an edge.
 
bool substructure_link_condition (const Tuple &e_tuple) const
 Link condition that also considers substructures.
 
size_t tet_storage_capacity () const
 
size_t vert_storage_capacity () const
 
bool try_set_vertex_mutex_two_ring (const Tuple &v, int threadid)
 Lock v's one-ring and, partially, its two-ring. See the note above.
 
bool try_set_vertex_mutex_two_ring_vid (const Tuple &v, int threadid)
 try_set_vertex_mutex_two_ring reached through vids rather than Tuples.
 
bool try_set_vertex_mutex_two_ring_vid (size_t v, int threadid)
 try_set_vertex_mutex_two_ring reached through vids rather than Tuples.
 
bool try_set_edge_mutex_two_ring (const Tuple &e, int threadid=0)
 Lock the edge's one-ring and, partially, its two-ring. See the note above.
 
bool try_set_face_mutex_two_ring (const Tuple &f, int threadid=0)
 Lock the face's one-ring and, partially, its two-ring. See the note above.
 
bool try_set_face_mutex_two_ring (const Tuple &v1, const Tuple &v2, const Tuple &v3, int threadid=0)
 Lock the face's one-ring and, partially, its two-ring. See the note above.
 
bool try_set_face_mutex_two_ring (size_t v1, size_t v2, size_t v3, int threadid=0)
 Lock the face's one-ring and, partially, its two-ring. See the note above.
 
bool try_set_vertex_mutex_one_ring (const Tuple &v, int threadid=0)
 Lock v and its one-ring. Complete, unlike the two-ring family.
 
size_t cell_capacity () const
 
size_t cell_storage_capacity () const
 
Tuple tuple_from_cell (size_t cid) const
 
size_t cell_slot_bound (const Tuple &t) const
 
void reserve_free_slots (size_t cells, size_t verts)
 
- Public Member Functions inherited from wmtk::RationalPositions
size_t round_all_vertices ()
 Try to round every un-rounded vertex; returns the number reclaimed.
 
bool round_and_check_all_rounded ()
 Run the sweep, then report whether the mesh is now fully rounded.
 

Static Public Member Functions

static PositionKey position_key (const Vector3d &a, const Vector3d &b, const Vector3d &c)
 
- Static Public Member Functions inherited from wmtk::TetMesh
static bool dry_run ()
 Whether operations on this thread are dry runs (see wmtk/OperationDryRun.hpp).
 
static SlotUsage slot_usage_of_this_thread ()
 

Public Attributes

VertAttCol m_vertex_attribute
 
FaceAttCol m_face_attribute
 
bool m_tracks_orientation = false
 The application set FaceAttributes::m_orientation at insertion, so the tracked surface carries the input's orientation and the operations keep it.
 
std::atomic< size_t > m_inconsistent_orientation_flips = 0
 Surface flips that joined two faces not oriented alike (a fold of the tracked surface, or unequal multiplicities).
 
AttributeContainerGroup m_vertex_attr_group
 What p_vertex_attrs points at, so a derived class can register more.
 
AttributeContainerGroup m_face_attr_group
 What p_face_attrs points at, so a derived class can register more.
 
AttributeContainerGroup m_edge_attr_group
 What p_edge_attrs points at, once a collection is registered with it.
 
bool m_in_operation_pass = false
 True while a pass of the shared operations runs.
 
EdgeAttCol m_feature_edge_attribute
 Sized, protected and rolled back only once enable_feature_edge_tracking() ran.
 
bool m_track_feature_edges = false
 Whether the shared operations maintain m_feature_edge_attribute.
 
std::shared_ptr< Envelope > m_feature_envelope
 Envelope around the input feature curves: the tube a tagged edge must stay in.
 
OptimizerParameters & m_params
 
std::shared_ptr< Envelope > m_envelope
 Surface envelope: what a surface vertex is pulled toward and checked against.
 
double m_s_amips = 1.
 
double m_s_envelope = -1.
 
double time_env = 0.0
 
igl::Timer isout_timer
 
wmtk::threading::enumerable_thread_specific< std::unique_ptr< polysolve::nonlinear::Solver > > m_solver
 Per-thread Newton solver for smoothing; created on first use.
 
optimization::SmoothRejectCounters m_smooth_rejects
 Why smoothing attempts were refused, reported once per pass.
 
optimization::NewtonCounters m_newton
 
bool m_collapse_limit_length = true
 
std::set< simplex::Edge > m_force_split_edges
 
size_t m_force_split_count = 0
 Force-splits taken in the current split pass. Diagnostic only.
 
std::unique_ptr< std::atomic< int >[]> m_high_valence_claim
 Per-pass claims for the shared high-valence split gate.
 
size_t m_high_valence_claim_size = 0
 
std::atomic< size_t > m_high_valence_rejects = 0
 
size_t m_split_order_waits = 0
 The current split pass's ExecutePass::waits() and wait_defects().
 
size_t m_split_order_wait_defects = 0
 
std::vector< std::pair< PositionKey, std::vector< uint32_t > > > m_insertion_sources
 
std::shared_ptr< history::VolumeRecorder > m_recorded_volume
 
uint64_t m_surface_edit_offset = 0
 
std::optional< history::SurfaceKey > m_finished_surface
 
std::atomic< size_t > m_surface_fold_refusals = 0
 The operations check_surface_folds refused.
 
int m_iterations_used = 0
 Shared TetWild/SimWild outer optimization schedule.
 
std::shared_ptr< history::TrackedSurfaceRecorder > m_recorded_surface
 
wmtk::threading::enumerable_thread_specific< SurfaceFolds > m_surface_folds_before
 
std::vector< std::vector< uint64_t > > m_recorded_sources
 The input triangles each face of the recorded surface's first state lies on.
 
int m_debug_print_counter = 0
 
std::string m_debug_pass_name
 
CoarsenStats m_coarsen_stats
 
std::atomic< int > cnt_swap = 0
 
std::atomic< int > cnt_surface_swap = 0
 
std::atomic< int > cnt_surface_swap_32 = 0
 
std::atomic< int > cnt_surface_swap_44 = 0
 
std::atomic< int > cnt_surface_swap_56 = 0
 
- Public Attributes inherited from wmtk::TetMesh
bool m_check_smoothing_stays_in_star = false
 While true, smooth_vertex() checks that the smooth recorded nothing outside the vertex's star – the vertex itself and the edges, faces and cells incident to it – and throws if it did.
 
AbstractAttributeContainer * p_vertex_attrs = nullptr
 
AbstractAttributeContainer * p_edge_attrs = nullptr
 
AbstractAttributeContainer * p_face_attrs = nullptr
 
AbstractAttributeContainer * p_tet_attrs = nullptr
 
bool m_collapse_check_link_condition = true
 
bool m_collapse_check_topology = false
 
bool m_collapse_check_manifold = true
 
wmtk::threading::enumerable_thread_specific< std::vector< size_t > > mutex_release_stack
 
wmtk::threading::enumerable_thread_specific< std::vector< size_t > > get_one_ring_cache
 
int NUM_THREADS = 0
 

Static Public Attributes

static constexpr double MAX_ENERGY = 1e50
 The sentinel get_quality returns for an element AMIPS cannot score.
 
- Static Public Attributes inherited from wmtk::TetMesh
static constexpr int EDGES_PER_CELL = 6
 
static constexpr int FACES_PER_CELL = 4
 

Protected Types

enum class  SwapReject : int {
  base_before , base_after , valence , bbox ,
  surface_not_allowed , feature_edge , prepare_flip , interior_hook ,
  flip_open_boundary , flip_not_two_surf , flip_nonmanifold_edge , flip_cd_nonmanifold ,
  flip_new_face_surface , flip_app_refused , flip_wrong_case , app_capture_label ,
  app_capture_tag , app_fid_missing , app_class_mismatch , app_mask_mismatch ,
  app_sag_raised , after_inverted , after_quality , after_cells ,
  app_after_side_conflict , app_after_no_side , after_envelope , face_tracked_surface ,
  face_tracked_bbox , face_inverted , face_not_better , COUNT
}
 
enum class  SwapStage : int {
  attempt , surface_attempt , before_pass , after_enter ,
  accepted , screened , COUNT
}
 
enum class  CollapseReject : int {
  coarsen_length , bbox , surface_leaves_envelope , inverted ,
  quality , substructure_link , feature_leaves_tube , feature_point ,
  app_both_surfaces , app_front_unlimited , app_leaves_input , app_leaves_offset ,
  app_leaves_region , app_order2 , app_substructure_link , app_ops_guard ,
  after_base , after_connectivity , after_envelope , after_face_attribute ,
  after_order2_chord , after_feature_edge , after_coarsen_region , COUNT
}
 
enum class  SwapRejectRole { before_leaf , after_leaf , wrapper , per_case }
 

Protected Member Functions

void on_slot_storage_grown () override
 
std::vector< size_t > all_vertex_ids () const override
 Every live vertex, in the mesh's own iteration order.
 
bool vertex_is_rounded (const size_t vid) const override
 Whether this vertex's double position is currently trusted.
 
bool round_vertex (const size_t vid) override
 
virtual std::tuple< double, double > optimization_quality_stats ()
 
virtual double optimization_stop_metric () const
 
virtual size_t refine_sizing_around_worst (double max_metric)=0
 
virtual bool optimization_bare_coarsen_passes () const
 Whether the loop opens with an UNLIMITED-LENGTH collapse pass.
 
virtual void optimization_iteration_done (int)
 
virtual void write_optimization_debug_output (const std::string &path)=0
 
virtual void optimization_sanity_checks_extra ()
 
virtual bool optimization_stop_at_float () const
 
virtual bool optimization_stalled (double prev, double cur)
 Whether an iteration that moved the metric from prev to cur is stalled, and the sizing refinement should therefore fire.
 
virtual bool collapse_before_vertex (size_t, size_t, double)
 
virtual bool collapse_quality_allowed (size_t v1, double quality, double ring_max) const
 
virtual bool collapse_is_order_2_edge (const std::array< size_t, 2 > &)
 
virtual bool collapse_after_connectivity (size_t, size_t, const std::vector< std::array< size_t, 2 > > &)
 
virtual void collapse_after_vertex (size_t, size_t)
 
virtual void collapse_after_features (size_t, size_t)
 
virtual bool split_before_cells (const Tuple &, const std::vector< Tuple > &)
 Cache application cell data before a split. TetWild needs none; SimWild caches tags.
 
virtual bool split_after_cells (size_t, size_t, size_t, const std::vector< Tuple > &)
 Restore application cell data on the children made by a split.
 
virtual bool split_adjust_position (size_t, const std::vector< Tuple > &)
 
virtual void split_after_vertex (size_t, bool)
 Application metadata not represented by the shared vertex attributes.
 
virtual bool allow_surface_swap () const =0
 
virtual bool check_surface_topology () const =0
 
virtual bool swap_before_interior (const std::vector< size_t > &)
 Application data attached to the old cells. TetWild has none; SimWild caches tags.
 
virtual bool swap_before_surface (const std::vector< size_t > &, size_t, size_t, size_t, size_t)
 
virtual bool swap_after_cells (const std::vector< size_t > &, bool)
 Propagate application data to the cells made by a successful topological swap.
 
bool swap_reject (SwapReject r) const
 
bool swap_reject_kind_only (SwapReject r) const
 
void swap_stage (SwapStage s) const
 
void swap_counters_reset ()
 
std::string swap_reject_report () const
 One line per nonzero counter, for a per-turn log. Does not reset.
 
bool collapse_reject (CollapseReject r) const
 
void op_event (OpKind k, OpEvent e) const override
 
std::string op_accounting_report (OpKind k) const
 
bool op_accounting_unexplained (OpKind k) const
 True when the report for k has a nonzero remainder: a refusal no counter named.
 
void op_accounting_reset ()
 
OpHookReasons op_hook_reasons (OpKind k) const
 
long op_event_count (const OpKind k, const OpEvent e) const
 
long op_unaccounted (OpKind k) const
 Attempts minus every outcome: 0 unless an exit of the TetMesh operation reports nothing.
 
virtual bool swap_quality_allowed (double after, double before, bool) const
 
void feature_edges_cache (const std::vector< size_t > &tids, std::map< std::array< size_t, 2 >, bool > &cache)
 Cache the feature tag of every edge of every tet in tids.
 
void feature_edges_restore_region (const std::vector< Tuple > &tets, const std::map< std::array< size_t, 2 >, bool > &cache)
 Write back tags over every edge of every tet in tets (created regions).
 
void feature_edges_restore_region (const std::vector< size_t > &tids, const std::map< std::array< size_t, 2 >, bool > &cache)
 
bool feature_edges_restore_remap (const std::map< std::array< size_t, 2 >, bool > &cache, size_t v_old, size_t v_new)
 Write back tags for every cached edge, with v_old renamed to v_new (collapse).
 
virtual void split_after_vertex_feature (size_t, bool)
 
- Protected Member Functions inherited from wmtk::TetMesh
std::vector< std::array< size_t, 3 > > tracked_faces_around (const std::vector< size_t > &vs, bool all) const
 
std::vector< VertexFace > faces_at_vertex (size_t v) const
 The faces with v as a corner, found from v's tets alone.
 
size_t face_id_in (const std::array< size_t, 3 > &f, size_t tid) const
 The face id (Tuple::fid) of f, a face of tet tid, its lowest; from tid alone.
 
virtual bool triangle_insertion_before (const std::vector< Tuple > &faces)
 
virtual bool triangle_insertion_after (const std::vector< std::vector< Tuple > > &)
 
virtual bool split_face_before (const Tuple &t)
 User specified preparations and desideratas for a face split before changing the connectivity.
 
virtual bool split_face_after (const Tuple &t)
 Compute the attributes for the added simplices.
 
virtual bool split_tet_before (const Tuple &t)
 User specified preparations and desideratas for a tet split before changing the connectivity.
 
virtual bool split_tet_after (const Tuple &t)
 Compute the attributes for the added simplices.
 
void resize_vertex_mutex (size_t v)
 

Static Protected Member Functions

static const char * swap_reject_name (SwapReject r)
 
static const char * swap_stage_name (SwapStage s)
 
static const char * collapse_reject_name (CollapseReject r)
 
static OpKind & current_op_kind ()
 
static const char * op_kind_name (OpKind k)
 
static const char * op_event_name (OpEvent e)
 
static SwapRejectRole swap_reject_role (SwapReject r)
 

Protected Attributes

uint32_t m_op_epoch = 0
 
std::array< std::atomic< long >, size_t(SwapReject::COUNT)> m_swap_reject {}
 
std::array< std::atomic< long >, size_t(SwapStage::COUNT)> m_swap_stage {}
 
std::array< std::atomic< long >, size_t(CollapseReject::COUNT)> m_collapse_reject {}
 
std::array< std::array< std::atomic< long >, size_t(OpEvent::COUNT)>, size_t(OpKind::COUNT)> m_op_events {}
 
std::array< std::array< std::atomic< long >, size_t(SwapReject::COUNT)>, size_t(OpKind::COUNT)+1 > m_swap_reject_by_kind {}
 
wmtk::threading::enumerable_thread_specific< SwapInfoCache > swap_cache
 
wmtk::threading::enumerable_thread_specific< SplitInfoCache > split_cache
 
wmtk::threading::enumerable_thread_specific< CollapseInfoCache > collapse_cache
 
bool m_coarsen_mode = false
 Set for the duration of coarsen_mesh(); read-only while a pass is running.
 
- Protected Attributes inherited from wmtk::RationalPositions
std::atomic< bool > m_all_rounded = false
 True when every vertex is known to be rounded.
 

Private Member Functions

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.
 
double region_max_quality_rel (const std::vector< size_t > &vids) const
 
bool smooth_vertex_reversible (size_t vid, CoarsenScratch &scr)
 One smoothing attempt on vid, restoring everything it wrote if it is rejected.
 
size_t collapse_all_edges_impl (bool is_limit_length, int lock_ring, size_t max_passes=0, bool exact_ball_lock=false)
 

Private Attributes

wmtk::threading::enumerable_thread_specific< CoarsenScratch > coarsen_scratch
 

Feature-point anchors

The 3D twin of TriOptimizerMesh's block of the same name, which states the reasoning: preserving a 0-dimensional feature – an input point, or a feature curve's endpoint (a junction too, when the application anchors those) – is a COVERAGE property, so each anchor vertex names WHICH feature it stands for. Lifted from tetwild, itself a port of triwild, with the same semantics and the same distance test.

Opt-in, in two levels. enable_feature_point_tracking() registers the per-vertex ids and has the shared operations maintain them: a split vertex stands for no feature, and a collapse survivor that stands for none takes over the collapsed vertex's. Its preserve argument additionally turns on the policy: a collapse that would leave a feature further than m_feature_eps from every vertex is refused (CollapseReject::feature_point), and smoothing may move an anchor vertex only inside its ball (the default smoothing_position_is_allowed()). The ids are maintained with the policy off too, so an application can still export and audit its anchors.

The application supplies the data, because which vertices stand for which features depends on its input: it fills m_feature_points and the ids after init(), and sets m_feature_eps.

using FeaturePointAttCol = AttributeCollection< FeaturePointAttributes >
 
FeaturePointAttCol m_feature_point_attribute
 Registered with m_vertex_attr_group only once enable_feature_point_tracking() ran.
 
std::vector< Vector3d > m_feature_points
 
double m_feature_eps = -1
 
bool m_track_feature_points = false
 Whether the shared operations maintain the ids (enable_feature_point_tracking()).
 
bool m_preserve_feature_points = false
 Whether the collapse and smoothing policy is on (its preserve argument).
 
static constexpr size_t NO_FEATURE_POINT = std::numeric_limits<size_t>::max()
 A vertex that stands for no feature point. See FeaturePointAttributes.
 
void enable_feature_point_tracking (const bool preserve)
 Turn on feature-point tracking, and the policy when preserve.
 
bool collapse_breaks_feature_point (const size_t v1_id, const size_t v2_id) const
 
bool feature_point_ball_contains (const size_t vid, const Vector3d &p) const
 
std::pair< size_t, size_t > feature_retention (double *worst_ratio=nullptr) const
 

Additional Inherited Members

- Static Protected Attributes inherited from wmtk::TetMesh
static constexpr std::array< std::array< int, 2 >, 6 > m_local_edges
 local edges within a tet
 

Detailed Description

What tetwild and simwild's 3D mesh share.

Seeded by MOVING tetwild's implementation here, not by designing an abstraction: tetwild is the more heavily measured of the two, so the move leaves it byte-identical and confines any output change to the commit where simwild adopts the base.

The 2D counterpart is wmtk::TriOptimizerMesh. The two are deliberately NOT unified with each other – see that class for why.

Cell attributes stay per-application. tetwild's tets carry winding numbers and a flood-fill id, simwild's carry a CellTag set, and an AttributeCollection member cannot change type in a derived class. The base therefore reaches the one field it needs – the quality – through cell_quality()/set_cell_quality(). This keeps the shared pass, swap and smoothing implementations independent of the derived cell-attribute layout; the virtual dispatch is negligible beside their geometric predicates and energy evaluations.

Member Enumeration Documentation

◆ SwapRejectRole

enum class wmtk::TetOptimizerMesh::SwapRejectRole
strongprotected

Where a SwapReject is decided, for the partition. A LEAF is the one place a refusal was decided and is counted once. A WRAPPER re-counts on its way out a refusal a leaf further in already counted: prepare_flip around the flip_* leaves and flip_app_refused, flip_app_refused around the app_* leaves, interior_hook around app_capture_*, after_cells around app_after_*. flip_wrong_case is counted once per candidate CASE inside TetMesh's case loop, not once per operation, so it is in neither sum.

◆ SwapStage

enum class wmtk::TetOptimizerMesh::SwapStage : int
strongprotected

Counted alongside the reasons: how far proposals get. surface_attempt counts edges that entered the surface branch at all, so "the surface never even presents a candidate" is distinguishable from "candidates are presented and refused".

In a screened pass (ExecutePass::screen_before_commit) the stages up to before_pass are counted by the dry run as well as by the real attempt. screened counts the dry runs that passed every check, i.e. the before_pass counts a real attempt repeats.

Member Function Documentation

◆ active_quality_threshold()

double wmtk::TetOptimizerMesh::active_quality_threshold ( ) const
inline

Cell-quality threshold above which a tet is "active" (worth operating on) for the skip-good-regions filter.

The quality stores AMIPS^3 and the energy is its cube root, so a tet is active when its energy is at least skip_good_regions_margin * stop_energy, i.e. the quality is at least (margin * stop_energy)^3.

◆ active_vertices()

std::vector< size_t > wmtk::TetOptimizerMesh::active_vertices ( ) const
virtual

vids of the vertices incident to at least one "active" cell, for the skip-good-regions filter.

Reimplemented in wmtk::components::simwild::SimWildMesh.

◆ add_edge_attributes()

void wmtk::TetOptimizerMesh::add_edge_attributes ( AbstractAttributeContainer *  c)
inline

Register an edge collection with m_edge_attr_group and point p_edge_attrs at the group.

Valid before or after init(), but not while an operation pass runs (it throws then; see throw_if_in_operation_pass()). Before init() the storage is empty and the resize here is a no-op; init() sizes the collection with the rest. After init() the resize brings it to what init() and every capacity growth size edge collections to – one entry per tet edge slot, 6 x tet_storage_capacity() – so the registered collections keep the invariant the operations index by (size >= every slot id they can hand out), and the new entries start at their default values. From then on growth, the owner migration in remove_tets_by_ids, consolidation and rollback move it with the others.

◆ all_vertex_ids()

std::vector< size_t > wmtk::TetOptimizerMesh::all_vertex_ids ( ) const
overrideprotectedvirtual

Every live vertex, in the mesh's own iteration order.

Implements wmtk::RationalPositions.

◆ allow_surface_swap()

virtual bool wmtk::TetOptimizerMesh::allow_surface_swap ( ) const
protectedpure virtual

◆ boundary_edges_at_vertex_inside()

virtual bool wmtk::TetOptimizerMesh::boundary_edges_at_vertex_inside ( size_t  ) const
inlinevirtual

Are all OPEN-BOUNDARY edges at vid inside the order-2 tube, at the current positions? Default true; tetwild overrides with its open-boundary flags and envelope. Membership is decided by flags + the topological face count, NOT by the tube itself – a tube-based membership test self-disables the moment geometry leaves the tube.

Reimplemented in wmtk::components::tetwild::TetWildMesh.

◆ cell_quality()

virtual double wmtk::TetOptimizerMesh::cell_quality ( const size_t  tid) const
pure virtual

The quality of cell tid, and how to write it.

The cell attribute types differ between the applications, so the base reaches the one field it shares through these. Both are AMIPS^3; see MAX_ENERGY. Topological operations and smoothing use the accessors so the shared algorithms remain independent of each application's cell-attribute type.

Implemented in wmtk::components::simwild::SimWildMesh, wmtk::components::tetwild::TetWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ checks_tracked_surface()

bool wmtk::TetOptimizerMesh::checks_tracked_surface ( ) const
inlineoverridevirtual

m_params.check_surface_folds; see there.

Reimplemented from wmtk::TetMesh.

◆ coarsen_collapse_edge()

bool wmtk::TetOptimizerMesh::coarsen_collapse_edge ( const Tuple &  e,
std::vector< Tuple > &  new_tets 
)

One collapse under the coarsening rules, outside a coarsening pass.

The pass sets the mode once and leaves it set for its whole duration, because every worker reads it; this is the single-operation form, for callers that want one and are not sharing the mesh with other threads.

◆ coarsen_mesh()

size_t wmtk::TetOptimizerMesh::coarsen_mesh ( )

Coarsen the mesh without letting the max energy rise.

The 3D twin of TriOptimizerMesh::coarsen_mesh; see OptimizerParameters::coarsen_pass for what makes the collapse in this pass different, and collapse_edge_after for how it is undone when it does not pay off. A no-op when m_params.coarsen_pass is false.

Returns
the number of collapses accepted across all rounds.

◆ collapse_after_connectivity()

virtual bool wmtk::TetOptimizerMesh::collapse_after_connectivity ( size_t  ,
size_t  ,
const std::vector< std::array< size_t, 2 > > &   
)
inlineprotectedvirtual

◆ collapse_after_features()

virtual void wmtk::TetOptimizerMesh::collapse_after_features ( size_t  ,
size_t   
)
inlineprotectedvirtual

Called once the feature-edge tags are restored after a collapse of v1 into v2, only when feature edges are tracked: the survivor's feature state is decided here.

Reimplemented in wmtk::components::tetwild::TetWildMesh.

◆ collapse_all_edges_impl()

size_t wmtk::TetOptimizerMesh::collapse_all_edges_impl ( bool  is_limit_length,
int  lock_ring,
size_t  max_passes = 0,
bool  exact_ball_lock = false 
)
private
Parameters
exact_ball_lockclaim the full lock_ring ball via try_set_edge_mutex_n_ring, bypassing make_locker's default-radius substitution of the partial two-ring helper (which under-claims in 3D – see "Ring lockers -- NOT balls" in TetMesh.h). Required whenever the operation writes beyond the seed's one-ring, as the coarsening composite's ring smoothing does.

◆ collapse_before_vertex()

virtual bool wmtk::TetOptimizerMesh::collapse_before_vertex ( size_t  ,
size_t  ,
double   
)
inlineprotectedvirtual

Non-const: an override may cache what it measured before the collapse so its after counterpart can tell a regression from a defect that was already there.

Reimplemented in wmtk::components::simwild::SimWildMesh, wmtk::components::tetwild::TetWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ collapse_breaks_feature_point()

bool wmtk::TetOptimizerMesh::collapse_breaks_feature_point ( const size_t  v1_id,
const size_t  v2_id 
) const

True iff collapsing v1 into v2 would drop or displace a feature-point anchor. False when the policy is off. Distance test included, as in 2D: two anchors within m_feature_eps of each other are allowed to merge – the survivor covers both – and forbidding that deadlocks the mesh (measured in 2D, see TriOptimizerMesh).

◆ collapse_edge_after()

bool wmtk::TetOptimizerMesh::collapse_edge_after ( const Tuple &  t)
overridevirtual

User specified modifications and desideratas for after an edge collapse.

Parameters
tedge Tuple that's collapsed
Returns
true if the modification succeed

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ collapse_edge_before()

bool wmtk::TetOptimizerMesh::collapse_edge_before ( const Tuple &  t)
overridevirtual

User specified preparations and desideratas for an edge collapse before changing the connectivity.

Parameters
tedge Tuple to be collapsed
Returns
true is the preparation succeed

check if on bbox/surface/boundary

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ collapse_quality_allowed()

virtual bool wmtk::TetOptimizerMesh::collapse_quality_allowed ( size_t  v1,
double  quality,
double  ring_max 
) const
inlineprotectedvirtual

◆ current_op_kind()

static OpKind & wmtk::TetOptimizerMesh::current_op_kind ( )
inlinestaticprotected

The operation running on this thread, set at its attempt, so a hook's swap_reject() can be charged to the right kind without passing the kind through every hook. COUNT (its own row, never reported) until the thread's first operation.

◆ edge_incident_surface_face_count()

int wmtk::TetOptimizerMesh::edge_incident_surface_face_count ( const Tuple &  e)

How many of the faces incident to edge e are on the tracked surface.

Unlike is_edge_on_surface(), this does NOT short-circuit on the (possibly stale) per-vertex flag – it counts the incident tets' face attributes directly.

◆ enable_feature_edge_tracking()

void wmtk::TetOptimizerMesh::enable_feature_edge_tracking ( )
inline

Turn on feature-edge tracking. The collection joins m_edge_attr_group beside whatever the application registered there.

Valid before or after init(), not during an operation pass (it throws then; see add_edge_attributes(), which sizes it). After init() it starts with no edge tagged, and the application tags the edges it needs. Late enabling is supported because an application may learn only from the built mesh whether its input has feature curves – topological_offset reads that off the labels init() produces – and enabling it for every input would make every operation cache and restore feature data it does not have (+50% wall time on the offset's triangle inputs). Idempotent: registering twice would move every tag twice.

◆ enable_feature_point_tracking()

void wmtk::TetOptimizerMesh::enable_feature_point_tracking ( const bool  preserve)
inline

Turn on feature-point tracking, and the policy when preserve.

Valid before or after init(), not during an operation pass (it throws then; see throw_if_in_operation_pass()). Before init() the storage is empty and the resize is a no-op; init() sizes the ids with the rest of m_vertex_attr_group. After init() the resize brings them to what init() and every capacity growth size vertex collections to, vert_storage_capacity(), with every vertex NO_FEATURE_POINT; the application then anchors what it needs. Late enabling is supported because an application may learn only from the built mesh whether its input has feature points, and enabling it for every input would make every operation cache and restore anchors it does not have. A second call changes only the policy.

◆ face_is_on_surface()

bool wmtk::TetOptimizerMesh::face_is_on_surface ( const size_t  fid) const
overridevirtual

Is a face part of the substructure.

Parameters
fidFace ID

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ feature_edges_at_vertex_inside()

bool wmtk::TetOptimizerMesh::feature_edges_at_vertex_inside ( size_t  vid) const

Are all tagged edges at vid inside the feature tube, at the CURRENT positions? True when tracking or the tube is off. Smoothing calls this with the candidate position already written into the vertex attribute.

◆ feature_point_ball_contains()

bool wmtk::TetOptimizerMesh::feature_point_ball_contains ( const size_t  vid,
const Vector3d &  p 
) const

May vertex vid sit at p as far as its anchor goes? True unless the policy is on, the vertex stands for a feature, and p is outside that feature's ball.

◆ feature_retention()

std::pair< size_t, size_t > wmtk::TetOptimizerMesh::feature_retention ( double *  worst_ratio = nullptr) const

{anchors still represented within m_feature_eps, total}. Geometric, as in 2D: "some vertex is within eps of this anchor", whether or not it carries the id.

◆ finish_surface_history()

std::optional< history::SurfaceHistory > wmtk::TetOptimizerMesh::finish_surface_history ( const history::SurfaceHistory *  input = nullptr)

Bring the recorded surface up to date with the tracked faces, stop recording, log what the history holds and return it, for the application to save (ComponentIO:: save_history). None if not recording.

With input, the history of the input the mesh was made from (read, welded, simplified): the history returned is that, then the insertion – each tracked face on the input faces it lies on, from m_insertion_sources – then the recorded one, so it maps the input files to the output.

◆ finish_volume_history()

std::optional< std::vector< uint8_t > > wmtk::TetOptimizerMesh::finish_volume_history ( const std::map< int64_t, std::string > &  tag_names = {})

Stop recording the volume, and return it as the bytes of its file (history::VolumeRecorder::to_bytes; io::ComponentIO::save_volume_history saves them), its edits indexed as in the surface history finish_surface_history() returned, with the names of the tags (tet_tags()) the mesh files give them. Nothing if not recording.

◆ get_order_of_vertex()

size_t wmtk::TetOptimizerMesh::get_order_of_vertex ( const size_t  vid) const
overridevirtual

Get the order of a vertex.

The order of a vertex in a TetMesh is as follows: 0: vertex is not on the surface 1: vertex is on the surface 2: vertex is on the surface boundary or a non-manifold edge 3: vertex is at the boundary of a non-manifold edge or a non-manifold vertex

Computing the vertex order is expensive. It is recommended to store the vertex order as a vertex attribute and override this method.

Parameters
vidVertex ID

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ invariants()

bool wmtk::TetOptimizerMesh::invariants ( const std::vector< Tuple > &  t)
overridevirtual

Reimplemented from wmtk::TetMesh.

◆ is_open_boundary_edge()

virtual bool wmtk::TetOptimizerMesh::is_open_boundary_edge ( const Tuple &  e)
inlinevirtual

Whether edge e lies on the boundary of the tracked surface.

Flipping such an edge would change the surface's boundary loops, so prepare_surface_flip refuses it. Defaults to false, which is exact for simwild: its surface is the interface between differently tagged tets, and around an interior edge the tags change an even number of times going around the tet ring, so an interface can never terminate there. It can only end where it meets the bbox – and is_edge_on_bbox() has already rejected those edges by the time this is asked. tetwild overrides it because its surface is the input mesh, which may be non-watertight anywhere.

Reimplemented in wmtk::components::tetwild::TetWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ is_tracked_face()

bool wmtk::TetOptimizerMesh::is_tracked_face ( size_t  tid,
int  j 
) const
overridevirtual

The faces with m_is_surface_fs, for a surface history (TetMesh::start_surface_history).

Reimplemented from wmtk::TetMesh.

◆ log_smoothing_pass_accounting()

virtual void wmtk::TetOptimizerMesh::log_smoothing_pass_accounting ( )
inlinevirtual

Called by smooth_all_vertices() after each pass's own accounting lines: an application that solves some vertices on a path of its own logs, and then resets, its counters here.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ on_slot_storage_grown()

void wmtk::TetOptimizerMesh::on_slot_storage_grown ( )
inlineoverrideprotectedvirtual

The high-valence claims are indexed by vertex id and sized to the storage at the start of a split pass; a split pass that grows the storage has to grow them with it, or the vertices it creates would fall outside the gate. Existing claims are kept.

Reimplemented from wmtk::TetMesh.

◆ op_accounting_report()

std::string wmtk::TetOptimizerMesh::op_accounting_report ( OpKind  k) const
protected

One line for kind k: attempts, the outcome partition, each hook's refusals split by reason, and the two remainders that must be 0. Does not reset.

◆ op_event()

void wmtk::TetOptimizerMesh::op_event ( OpKind  k,
OpEvent  e 
) const
inlineoverrideprotectedvirtual

Reimplemented from wmtk::TetMesh.

◆ optimization_bare_coarsen_passes()

virtual bool wmtk::TetOptimizerMesh::optimization_bare_coarsen_passes ( ) const
inlineprotectedvirtual

Whether the loop opens with an UNLIMITED-LENGTH collapse pass.

mesh_improvement() begins with local_operations({{0,1,1,0}}, false) – a collapse pass with collapse_limit_length FALSE, so no edge is too short to be collapsed and no edge is too long to be collapsed either. For TetWild and SimWild that is exactly right: it strips the redundancy left by insertion before the real work starts, and their tracked surface is held in place by an envelope throughout.

It is wrong for an application whose tracked surface is what the optimization exists to PLACE, and which therefore has no envelope holding it. topological_offset's offset surface is such a surface: measured on topological_offset_3d_convex, the opening pass alone took it from 1172 faces to 326 – a 72% decimation – before the loop had run at all, and nothing downstream can undo that. The sizing field can ask for refinement afterwards; it cannot refuse a collapse.

This governs the two BARE coarsening passes – the opening one and the closing one – and not coarsen_mesh(), which mesh_improvement() runs without this gate, nor the collapse inside the loop, which is interleaved with splits and smoothing and answers to the criterion. Measured on the same model with only the closing pass left enabled: 1172 faces to 350, so gating the opening one alone is not enough.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ optimization_iteration_done()

virtual void wmtk::TetOptimizerMesh::optimization_iteration_done ( int  )
inlineprotectedvirtual

Called at the end of each iteration of mesh_improvement(), after its operation groups and before the stop test (it from 0). No-op by default.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ optimization_quality_stats()

std::tuple< double, double > wmtk::TetOptimizerMesh::optimization_quality_stats ( )
protectedvirtual

Quality metric used by the driver. TetWild uses absolute AMIPS; SimWild overrides this with quality normalized by each cell's tag-dependent target.

Reimplemented in wmtk::components::simwild::SimWildMesh.

◆ optimization_stalled()

virtual bool wmtk::TetOptimizerMesh::optimization_stalled ( double  prev,
double  cur 
)
inlineprotectedvirtual

Whether an iteration that moved the metric from prev to cur is stalled, and the sizing refinement should therefore fire.

Exactly the expression mesh_improvement() used inline: the improvement is small next to the distance the metric still has to cover, i.e. the mesh is not on course to reach the target within about 1/stall_eps more iterations.

It is a virtual because the scalar the driver has is a MAX over criteria, and for an application with more than one criterion that max only ever reports on whichever is currently worst – so a run whose worst criterion is stuck refines every iteration even while the others are improving. An application that knows its criteria apart overrides this to ask the question of each of them.

◆ orient_tracked_face() [1/3]

std::array< size_t, 3 > wmtk::TetMesh::orient_tracked_face ( const std::array< size_t, 3 > &  f) const
inline

The input's orientation on the face (m_orientation), where insertion recorded one; ascending vertex order where it did not.

◆ orient_tracked_face() [2/3]

virtual std::array< size_t, 3 > wmtk::TetMesh::orient_tracked_face ( const std::array< size_t, 3 > &  f,
const std::vector< size_t > &  tets 
) const
inlinevirtual

The input's orientation on the face (m_orientation), where insertion recorded one; ascending vertex order where it did not.

Reimplemented from wmtk::TetMesh.

◆ orient_tracked_face() [3/3]

std::array< size_t, 3 > wmtk::TetOptimizerMesh::orient_tracked_face ( const std::array< size_t, 3 > &  f,
const std::vector< size_t > &  tets 
) const
overridevirtual

A tracked face's corners in the order that orients it, for a surface history, given the face's tets (tets_of_face). As given, unless an application says otherwise. The tets are passed in so that a caller holding one corner can find them from its tets alone (faces_at_vertex).

Reimplemented from wmtk::TetMesh.

◆ quality_rel()

virtual double wmtk::TetOptimizerMesh::quality_rel ( const size_t  tid) const
inlinevirtual

A cell's quality relative to the quality it is required to reach; <= 1 means it meets it.

The only quality that is comparable ACROSS cells. Raw cell_quality is not, once an application gives different regions different targets: the loose region's raw ceiling then hides degradation in the strict one, because a strict cell may get much worse and still sit below a number set somewhere it has nothing to do with. Shared code that compares one cell's quality against another's must go through here.

The cube root is because cell_quality stores AMIPS^3, so that this means the same thing as its 2D twin: AMIPS relative to target, not AMIPS^3 relative to target. TetWild's target is uniform, so this is a monotone function of the raw quality divided by a constant – neither of which can change the outcome of a before/after comparison, so its behaviour is unchanged.

Reimplemented in wmtk::components::simwild::SimWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ record_surface_history()

void wmtk::TetOptimizerMesh::record_surface_history ( const std::string &  metadata)

Start recording the tracked surface (TetMesh::start_surface_history), at m_posf, with metadata (the application's parameters, say) saved along. Takes m_insertion_sources.

◆ record_volume_history()

void wmtk::TetOptimizerMesh::record_volume_history ( )

Start recording the volume around the tracked surface too (TetMesh::start_volume_history), at m_posf. The surface history must be recording.

◆ refine_sizing_around_worst()

virtual size_t wmtk::TetOptimizerMesh::refine_sizing_around_worst ( double  max_metric)
protectedpure virtual

◆ region_max_quality_rel()

double wmtk::TetOptimizerMesh::region_max_quality_rel ( const std::vector< size_t > &  vids) const
private

Worst relative quality (quality_rel) over the cells incident to any vertex of vids.

◆ round()

bool wmtk::TetOptimizerMesh::round ( const Tuple &  v)

Round a vertex position to floating point, if that inverts no incident tet.

Returns
True if successful or already rounded, false otherwise.

◆ round_vertex()

bool wmtk::TetOptimizerMesh::round_vertex ( const size_t  vid)
inlineoverrideprotectedvirtual

Try to replace this vertex's exact position with its rounded one; false if that would invert an incident cell, in which case nothing is changed.

Implements wmtk::RationalPositions.

◆ smooth_after()

bool wmtk::TetOptimizerMesh::smooth_after ( const Tuple &  t)
overridevirtual

User specified modifications and desideratas for after smoothing a vertex.

Parameters
tTuple refering to a vertex
Returns
true if the preparation succeed

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ smooth_before()

bool wmtk::TetOptimizerMesh::smooth_before ( const Tuple &  t)
overridevirtual

The smoothing hooks. A derived class overriding them – or invariants(), which a smooth also runs – must read every attribute outside the smoothed vertex's star (other vertices, and the edges, faces and tets not incident to the vertex) through const access, e.g. std::as_const(m_vertex_attribute)[u].

Parallel smoothing runs non-adjacent vertices concurrently without locks (see OptimizerParameters::colored_smoothing). Two of them can share a neighbour, and a non-const access inside the smooth records the entry, which a rejected smooth writes back: two threads would write the same neighbour at once. Every smooth of that pass checks this (TetMesh/TriMeshm_check_smoothing_stays_in_star) and throws on the first offence.

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ smoothing_cell_energy()

virtual double wmtk::TetOptimizerMesh::smoothing_cell_energy ( const size_t  ,
const double  quality 
) const
inlinevirtual

The number the shared smoother compares for one cell, given the cell's quality (AMIPS^3) at the position being tested. Its quality veto compares the max of this over the ring before and after the move, and the default smoothing_ring_energy() is the same max.

The quality itself by default, so TetWild and SimWild compare exactly what they compared before. An application whose smoother minimises another per-cell energy (through smoothing_extra_energy()) overrides it, so that the smoother's tests judge a move by that same energy. The 2D twin is TriOptimizerMesh::smoothing_cell_energy.

◆ smoothing_containment_envelope()

virtual std::shared_ptr< Envelope > wmtk::TetOptimizerMesh::smoothing_containment_envelope ( const size_t  ,
const std::array< size_t, 3 > &  face,
const FaceAttributes &  attr 
) const
inlinevirtual

Envelope the smoother checks tracked face face (attributes attr) at the moved vertex vid against; null skips the face.

By default the face's own containment, surface_envelope_for_face() – the one every operation's check takes, so a move and an operation hold a face to the same set. It used to be ONE envelope per vertex for all its faces, which cannot be right once faces at one vertex belong to different inputs: a vertex where the solid's boundary meets a sheet crossing it would hold the solid's faces to the sheet's envelope too, or the reverse. topological_offset keeps its per-vertex answer by overriding this.

The pull (smoothing_energy_envelope()) stays one real envelope per vertex: the pull calls the non-virtual Envelope queries, which a composite cannot answer.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ smoothing_energy_envelope()

virtual std::shared_ptr< Envelope > wmtk::TetOptimizerMesh::smoothing_energy_envelope ( const size_t  vid) const
pure virtual

Envelope a surface vertex is pulled toward while smoothing. A real envelope, never a composite (see smoothing_containment_envelope()). A derived mesh may select an order-2 or feature envelope here.

Implemented in wmtk::components::simwild::SimWildMesh, wmtk::components::tetwild::TetWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ smoothing_extra_energy()

virtual std::shared_ptr< polysolve::nonlinear::Problem > wmtk::TetOptimizerMesh::smoothing_extra_energy ( const size_t  ) const
inlinevirtual

An extra term the application adds to this vertex's smoothing objective, or null.

The extension point that lets an application place a vertex by MINIMISING something rather than by computing a position and then defending it. topological_offset uses it for the offset surface: the term is w (Phi - c)^2, whose minimum is the offset itself, so an offset-surface vertex goes through this same smoother – the same line search, the same exact inversion test, the same quality veto – as every other vertex, instead of through the hand-rolled quadrics/Laplacian blend that bypassed all three.

Null by default, so TetWild and SimWild compose exactly the energy they composed before. The 2D twin is TriOptimizerMesh::smoothing_extra_energy.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ smoothing_pass_done()

virtual void wmtk::TetOptimizerMesh::smoothing_pass_done ( )
inlinevirtual

Called by smooth_all_vertices() at the end of EVERY smoothing pass, after its accounting (log_smoothing_pass_accounting()) and before its debug frame: an application that keeps state derived from the positions the pass just moved refreshes it here. Not called before the first pass.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ smoothing_position_is_allowed()

virtual bool wmtk::TetOptimizerMesh::smoothing_position_is_allowed ( const size_t  vid,
const Vector3d &  p 
) const
inlinevirtual

Per-vertex positional constraint, on top of the envelopes – the 3D counterpart of TriOptimizerMesh's hook of the same name. The default is the feature-point ball, which answers true when the anchors are off; an application overriding this while anchoring feature points must AND its own answer with feature_point_ball_contains().

◆ smoothing_ring_energy()

virtual double wmtk::TetOptimizerMesh::smoothing_ring_energy ( const std::vector< Tuple > &  ring,
const bool  stored 
) const
inlinevirtual

The number the shared smoother's projected step compares for a whole one-ring: a vertex held on a surface takes the first projected candidate whose value is strictly below the value before the move.

stored true: the ring before the move, read from the stored cell qualities; it is asked before the solve moves the vertex, so the mesh as it is is that ring too. stored false: the ring at the candidate position, every cell of it already tested for inversion.

By default the max over the ring of smoothing_cell_energy() – what the projected step compared before this hook existed – so TetWild and SimWild are unchanged. An application whose rules compare a sum of a per-cell energy over the cells a move changes overrides it with that sum, so that the projected step picks its candidate by the same rule. 3D only.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ split_adjust_position()

virtual bool wmtk::TetOptimizerMesh::split_adjust_position ( size_t  ,
const std::vector< Tuple > &   
)
inlineprotectedvirtual

Optional annotation-only adjustment of the midpoint. Ordinary optimization returns true without changing the shared TetWild position.

Reimplemented in wmtk::components::simwild::SimWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ split_after_cells()

virtual bool wmtk::TetOptimizerMesh::split_after_cells ( size_t  ,
size_t  ,
size_t  ,
const std::vector< Tuple > &   
)
inlineprotectedvirtual

Restore application cell data on the children made by a split.

Reimplemented in wmtk::components::simwild::SimWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ split_after_vertex()

virtual void wmtk::TetOptimizerMesh::split_after_vertex ( size_t  ,
bool   
)
inlineprotectedvirtual

Application metadata not represented by the shared vertex attributes.

Reimplemented in wmtk::components::tetwild::TetWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ split_after_vertex_feature()

virtual void wmtk::TetOptimizerMesh::split_after_vertex_feature ( size_t  ,
bool   
)
inlineprotectedvirtual

Hook: the split vertex was created on a feature edge (or not). Runs only when m_track_feature_edges is set; the counterpart of split_after_vertex for the feature flag, separate so existing overrides keep their signature.

Reimplemented in wmtk::components::tetwild::TetWildMesh.

◆ split_before_cells()

virtual bool wmtk::TetOptimizerMesh::split_before_cells ( const Tuple &  ,
const std::vector< Tuple > &   
)
inlineprotectedvirtual

Cache application cell data before a split. TetWild needs none; SimWild caches tags.

Reimplemented in wmtk::components::simwild::SimWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ split_edge_after()

bool wmtk::TetOptimizerMesh::split_edge_after ( const Tuple &  t)
overridevirtual

This function computes the attributes for the added simplices. User specified modifications and desideratas for after an edge split.

Parameters
theedge Tuple to be split
Returns
true if the modification succeed

check inversion & rounding

update quality

containment: the new surface triangles must stay inside the envelope

update vertex attribute

update face attribute

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ split_edge_before()

bool wmtk::TetOptimizerMesh::split_edge_before ( const Tuple &  t)
overridevirtual

User specified preparations and desideratas for an edge split before changing the connectivity.

Parameters
theedge Tuple to be split
Returns
true if the preparation succeed

save face track info

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ split_edge_is_due()

bool wmtk::TetOptimizerMesh::split_edge_is_due ( const Tuple &  e) const

split_all_edges's gate: length^2 >= splitting_l2 * s^2, s the mean of the endpoints' sizing scalars, or a force-split edge.

◆ storage_grows_on_demand()

bool wmtk::TetOptimizerMesh::storage_grows_on_demand ( ) const
inlineoverridevirtual

Every pass grows the storage at its serial points – between operations when serial, between rounds when parallel (see ExecutePass) – so the optimizer only keeps a small slack instead of the preallocation factor.

Reimplemented from wmtk::TetMesh.

◆ substructure_feature_neighbors()

void wmtk::TetOptimizerMesh::substructure_feature_neighbors ( size_t  ,
std::vector< size_t > &   
) const
overridevirtual

One-ring vertices x of vid where (vid, x) is 1D substructure NOT derivable from the surface complex (feature edges through the interior, for instance). The link condition's order-2 edge collection walks surface faces and would never see them.

Reimplemented from wmtk::TetMesh.

◆ substructure_order_of_edge()

size_t wmtk::TetOptimizerMesh::substructure_order_of_edge ( const std::array< size_t, 2 > &  vids) const
overridevirtual

The orders substructure_link_condition consults, overridable so an application can widen the 1D substructure beyond what the surface complex derives.

The paper's condition is written in terms of simplex orders; TetOptimizerMesh overrides these so an input FEATURE edge counts as order 2 (and its endpoints accordingly) without touching the meaning of get_order_of_* anywhere else – the feature tags are deliberately not part of the order classification.

Reimplemented from wmtk::TetMesh.

◆ substructure_order_of_vertex()

size_t wmtk::TetOptimizerMesh::substructure_order_of_vertex ( size_t  vid) const
overridevirtual

Reimplemented from wmtk::TetMesh.

◆ surface_envelope_for_face()

virtual std::shared_ptr< Envelope > wmtk::TetOptimizerMesh::surface_envelope_for_face ( const std::array< size_t, 3 > &  vids,
const FaceAttributes &  attr 
) const
inlinevirtual

Envelope the tracked-surface triangle vids must stay inside, given the attributes attr it carries – or, for a triangle an operation is creating, the ones the operation is about to write there.

Null means this triangle carries no containment requirement, and every containment check on it is skipped. The default answers with the one surface envelope; tetwild answers with the envelopes of the face's input set (SurfaceTagAttributes::input_set()), and an application tracking more than one surface (see SurfaceTagAttributes::m_surface_class) answers per class – the offset boundary, for instance, is free to move and is checked against nothing.

Keyed on the vertex ids rather than the fid because every caller is a topological operation asking about the triangles it is ABOUT to create or has just created, where only the vids are known for certain. The attributes come from the caller for the same reason: a new triangle's own slot is written only after the check – a collapse checks its faces before it writes their attributes back, a split before it writes its halves – and until then may hold a recycled face's. Every operation knows the face it is deriving the new one from, and passes what it will write.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, wmtk::components::simwild::SimWildMesh, and wmtk::components::tetwild::TetWildMesh.

◆ surface_triangle_is_outside()

bool wmtk::TetOptimizerMesh::surface_triangle_is_outside ( const size_t  a,
const size_t  b,
const size_t  c,
const FaceAttributes &  attr 
) const
inline

Whether the tracked-surface triangle (a,b,c) with attributes attr (see surface_envelope_for_face()) is outside its containment envelope. False when it has none. Every surface containment check in the operations goes through here.

◆ swap_after_cells()

virtual bool wmtk::TetOptimizerMesh::swap_after_cells ( const std::vector< size_t > &  ,
bool   
)
inlineprotectedvirtual

Propagate application data to the cells made by a successful topological swap.

Reimplemented in wmtk::components::simwild::SimWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ swap_before_interior()

virtual bool wmtk::TetOptimizerMesh::swap_before_interior ( const std::vector< size_t > &  )
inlineprotectedvirtual

Application data attached to the old cells. TetWild has none; SimWild caches tags.

Reimplemented in wmtk::components::simwild::SimWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ swap_edge_44_accept_case()

bool wmtk::TetOptimizerMesh::swap_edge_44_accept_case ( const std::array< size_t, 2 > &  new_edge)
overridevirtual

Filter which of the 4-4 orientations may be chosen.

Called for every candidate 4-4 case (identified by its new edge) BEFORE the energy-based selection; a candidate whose new edge is rejected here is not considered. The default accepts everything, so interior edges keep the pure min-energy behavior. A derived mesh can override this to force a specific retetrahedralization (e.g. tetwild forces the case that realizes a surface diagonal flip).

Parameters
new_edgeThe two vertices of the candidate's new edge. The ordering is implementation-defined (currently new_edge[0] is the case-selector vertex).

Reimplemented from wmtk::TetMesh.

◆ swap_edge_44_after()

bool wmtk::TetOptimizerMesh::swap_edge_44_after ( const Tuple &  t)
overridevirtual

User specified modifications and desideratas for after a 4-4 edge swap.

Parameters
tedge Tuple that's swaped
Returns
true if the modification succeed

Reimplemented from wmtk::TetMesh.

◆ swap_edge_44_before()

bool wmtk::TetOptimizerMesh::swap_edge_44_before ( const Tuple &  t)
overridevirtual

User specified preparations and desideratas for an 4-4 edge swap before changing the connectivity.

Parameters
tedge Tuple to be swaped
Returns
true if the preparation succeed

Reimplemented from wmtk::TetMesh.

◆ swap_edge_44_energy()

double wmtk::TetOptimizerMesh::swap_edge_44_energy ( const std::vector< std::array< size_t, 4 > > &  tets,
const int  op_case 
)
overridevirtual

User specified energy to decide which of the 4 possible orientations should be chosen.

Accepts the last shown orientation if not overridden.

Parameters
tetsNew tets after performing a 4-4 swap.
op_caseThe operation case, where 0 are the tets before swap.
Returns
energy The swap giving the tets with the lowest energy are chosen.

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ swap_edge_56_accept_case()

bool wmtk::TetOptimizerMesh::swap_edge_56_accept_case ( const std::array< size_t, 3 > &  new_face)
overridevirtual

Filter which of the 5-6 orientations may be chosen.

Called for every candidate 5-6 case (identified by its new fan face) BEFORE the energy-based selection; a candidate whose new face is rejected here is not considered. The default accepts everything, so interior edges keep the pure min-energy behavior. new_face[0] is the fan apex. A derived mesh can override this to force a specific retetrahedralization (e.g. tetwild forces the fan that realizes a surface diagonal flip).

Parameters
new_faceThe candidate's new fan face; new_face[0] is the fan apex.
Returns
true if this candidate case is allowed.

Reimplemented from wmtk::TetMesh.

◆ swap_edge_56_after()

bool wmtk::TetOptimizerMesh::swap_edge_56_after ( const Tuple &  t)
overridevirtual

User specified modifications and desideratas for after a 5-6 edge swap.

Parameters
tedge Tuple that's swaped
Returns
true if the modification succeed

There is no need to check for inversion or energy here. The operation would have been rejected already due to swap_edge_56_energy().

Reimplemented from wmtk::TetMesh.

◆ swap_edge_56_before()

bool wmtk::TetOptimizerMesh::swap_edge_56_before ( const Tuple &  t)
overridevirtual

User specified preparations and desideratas for a 5-6 edge swap before changing the connectivity.

Parameters
tedge Tuple to be swaped
Returns
true if the preparation succeed

Reimplemented from wmtk::TetMesh.

◆ swap_edge_56_energy()

double wmtk::TetOptimizerMesh::swap_edge_56_energy ( const std::vector< std::array< size_t, 4 > > &  tets,
const int  op_case 
)
overridevirtual

User specified energy to decide which of the 5 possible orientations should be chosen.

Accepts the last shown orientation if not overridden.

Parameters
tetsNew tets after performing a 5-6 swap.
op_caseThe operation case, where 0 are the tets before swap.
Returns
energy The swap giving the tets with the lowest energy are chosen.

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ swap_edge_after()

bool wmtk::TetOptimizerMesh::swap_edge_after ( const Tuple &  t)
overridevirtual

User specified modifications and desideratas for after a 3-2 edge swap.

Parameters
tedge Tuple that's swaped
Returns
true if the modification succeed

Setting the m_is_surface_fs flag to true is not necessary. This is already true in cache.sf_face_attr.

Reimplemented from wmtk::TetMesh.

◆ swap_edge_before()

bool wmtk::TetOptimizerMesh::swap_edge_before ( const Tuple &  t)
overridevirtual

User specified preparations and desideratas for an 3-2 edge swap before changing the conenctivity.

Parameters
tedge Tuple to be swaped
Returns
true if the preparation succeed

Reimplemented from wmtk::TetMesh.

◆ swap_face_after()

bool wmtk::TetOptimizerMesh::swap_face_after ( const Tuple &  t)
overridevirtual

User specified modifications and desideratas for after a 2-3 face swap.

Parameters
tedge Tuple that's swaped
Returns
true if the modification succeed

Reimplemented from wmtk::TetMesh.

◆ swap_face_before()

bool wmtk::TetOptimizerMesh::swap_face_before ( const Tuple &  t)
overridevirtual

User specified preparations and desideratas for an 2-3 face swap befroe changing the geometry.

Parameters
tedge Tuple to be swaped
Returns
true if the preparation succeed

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ swap_quality_allowed()

virtual bool wmtk::TetOptimizerMesh::swap_quality_allowed ( double  after,
double  before,
bool   
) const
inlineprotectedvirtual

Whether a swap's quality outcome is acceptable, given the max cell energy over the cells it creates and over the cells it destroyed. The default is STRICT improvement, which is what every swap here required before this hook existed, so a subclass that does not override it sees no change.

is_surface_flip distinguishes a surface diagonal flip (see prepare_surface_flip) from an interior swap, so an application can relax the rule for the surface it tracks without touching interior swaps. The twin on the collapse side is collapse_quality_allowed().

NOT consulted by swap_edge_56_after(), which has never had a quality gate: it computes a max energy and discards it. That is pre-existing and is left alone rather than silently changed, since it would move 5-6 behaviour for every consumer of this class.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ swap_reject_kind_only()

bool wmtk::TetOptimizerMesh::swap_reject_kind_only ( SwapReject  r) const
inlineprotected

The per-kind table alone (see op_accounting_report()), charged to the operation running on this thread. Face swaps use it directly; swap_reject() calls it for edge swaps.

◆ throw_if_in_operation_pass()

void wmtk::TetOptimizerMesh::throw_if_in_operation_pass ( const char *  call) const
inline

Registering a collection resizes it, which reallocates the storage under the pass's readers, and an operation already in flight has not protected it – nothing fails at the call, the corruption shows up later. Thrown, not asserted: release builds compile asserts out.

◆ tracked_area_normal()

Eigen::Vector3d wmtk::TetOptimizerMesh::tracked_area_normal ( const std::vector< std::array< size_t, 3 > > &  faces) const

The tracked faces, oriented, their area vectors summed; and, over their vertices, the faces of each one's tracked star not facing along that star's sum.

◆ tracked_feature_edges()

std::vector< std::array< size_t, 2 > > wmtk::TetOptimizerMesh::tracked_feature_edges ( ) const
overridevirtual

The tagged feature edges (m_feature_edge_attribute) that are edges of tracked faces.

Reimplemented from wmtk::TetMesh.

◆ tracked_surface_after()

bool wmtk::TetOptimizerMesh::tracked_surface_after ( const std::vector< size_t > &  vs,
bool  all 
)
overridevirtual

Reimplemented from wmtk::TetMesh.

◆ tracked_surface_before()

void wmtk::TetOptimizerMesh::tracked_surface_before ( const std::vector< size_t > &  vs,
bool  all 
)
overridevirtual

Reimplemented from wmtk::TetMesh.

◆ tracked_surface_boundary()

std::vector< std::pair< std::array< size_t, 2 >, int > > wmtk::TetOptimizerMesh::tracked_surface_boundary ( ) const

Mesh edges where the oriented tracked surface has a boundary.

The tracked surface is an integer 2-chain, and every operation preserves its boundary – except a surface flip of two faces not oriented alike, which is counted in m_inconsistent_orientation_flips: a closed input stays a cycle (signed sum of incident oriented tracked faces is 0 on every edge), and an open one keeps its boundary on the input's open boundary. Returns the edges with a nonzero sum, each with that sum, for the caller to compare with what the input allows. One pass over every face, then a map over the tracked faces' edges.

◆ update_attributes()

virtual void wmtk::TetOptimizerMesh::update_attributes ( )
inlinevirtual

Update the attributes of the mesh after an iteration of operations.

This is necessary in SimWild to update the surface flags of faces and vertices as operations might have collapsed away regions that are now no longer on the surface. In TetWild, this is a no-op.

Reimplemented in wmtk::components::simwild::SimWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ vertex_has_feature_edge()

bool wmtk::TetOptimizerMesh::vertex_has_feature_edge ( size_t  vid) const

Does any edge incident to vid carry the feature tag? Derived from the edge tags rather than from a vertex flag, so it cannot go stale.

◆ vertex_is_on_surface()

bool wmtk::TetOptimizerMesh::vertex_is_on_surface ( const size_t  vid) const
overridevirtual

Is a vertex part of the substructure.

Parameters
vidVertex ID

Reimplemented from wmtk::TetMesh.

Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.

◆ vertex_is_rounded()

bool wmtk::TetOptimizerMesh::vertex_is_rounded ( const size_t  vid) const
inlineoverrideprotectedvirtual

Whether this vertex's double position is currently trusted.

Implements wmtk::RationalPositions.

◆ write_optimization_debug_output()

virtual void wmtk::TetOptimizerMesh::write_optimization_debug_output ( const std::string &  path)
protectedpure virtual

Member Data Documentation

◆ m_collapse_limit_length

bool wmtk::TetOptimizerMesh::m_collapse_limit_length = true

Whether the current collapse pass applies the target-length limit; read by collapse_edge_before, which is where that limit is enforced.

◆ m_debug_pass_name

std::string wmtk::TetOptimizerMesh::m_debug_pass_name

WHICH PASS THE NEXT DEBUG FRAME BELONGS TO, e.g. "split", "smooth", "collapse-skipped" (a group whose op count was 0 still writes its checkpoint frame). Set by every writer before it writes, so an application that renames frames (the 3D offset) can carry the pass name into the file name; the base's own "debug_<N>" names are unchanged. The TriOptimizerMesh twin.

◆ m_edge_attr_group

AttributeContainerGroup wmtk::TetOptimizerMesh::m_edge_attr_group

What p_edge_attrs points at, once a collection is registered with it.

The 3D counterpart of wmtk::TriOptimizerMesh::m_edge_attr_group. Two owners keep a per-edge collection: the feature-edge tags (enable_feature_edge_tracking()) and topological_offset, which labels each edge by which part of the construction produced it. With one p_edge_attrs slot only one of them could register, so feature tracking had to refuse to run in the offset; registered here, each is resized, moved, protected and rolled back with the others.

Unlike the 2D group, which always holds the shared m_edge_attribute, this one starts EMPTY – the 3D base keeps no edge attribute of its own – so p_edge_attrs stays null until add_edge_attributes() registers the first collection. TetMesh skips every per-edge step on a null p_edge_attrs (the owner migration in remove_tets_by_ids, the moves in consolidate_mesh, the protect/rollback forwarding); pointing it at an empty group would pay for all of them in the tetwild and simwild runs that track no edges.

Same caveat as the 2D group: this moves the storage and nothing more. The shared operations maintain the VALUES of m_feature_edge_attribute only (the split and collapse restores); anything else registered here is its registering application's to maintain.

◆ m_face_attr_group

AttributeContainerGroup wmtk::TetOptimizerMesh::m_face_attr_group

What p_face_attrs points at, so a derived class can register more.

The counterpart of m_vertex_attr_group for faces. An application whose faces carry data the shared operations know nothing about – topological_offset labels each face by which part of the construction produced it – registers a second collection here, and it is resized, protected and rolled back with the shared one.

Note what this does NOT do: the shared operations propagate face data by copying SurfaceTagAttributes values around (the split and collapse caches, the swap tracker), and they only ever see their own collection. Anything registered here survives the mesh changing shape, but its values are the registering application's to maintain.

◆ m_feature_envelope

std::shared_ptr<Envelope> wmtk::TetOptimizerMesh::m_feature_envelope

Envelope around the input feature curves: the tube a tagged edge must stay in.

The collapse guard's veto (see collapse_edge_before). Kept SEPARATE from the surface envelope and the order-2 envelope: merging would let feature curves vouch for open boundaries (and vice versa) in guard decisions. Null => tagged edges are propagated but not geometrically constrained.

◆ m_feature_eps

double wmtk::TetOptimizerMesh::m_feature_eps = -1

Radius of the anchor ball. A separate name from the tube eps for the same reason triwild keeps it separate from its envelope eps; tetwild gives both the same value.

◆ m_feature_points

std::vector<Vector3d> wmtk::TetOptimizerMesh::m_feature_points

Anchor positions, indexed by FeaturePointAttributes::m_feature_point_id. A vertex carrying feature f may never end up further than m_feature_eps from m_feature_points[f]; the anchor never moves, so the id is a direct lookup.

◆ m_force_split_edges

std::set<simplex::Edge> wmtk::TetOptimizerMesh::m_force_split_edges

The longest edge of each current worst tet. split_all_edges force-splits exactly these edges (bypassing the length gate). Populated serially by refine_sizing_around_worst; read-only during the parallel split pass, then cleared once consumed.

◆ m_in_operation_pass

bool wmtk::TetOptimizerMesh::m_in_operation_pass = false

True while a pass of the shared operations runs.

Set, and restored on exit or throw, by the two drivers every such pass goes through: run_pass() (utils/RunPass.cpp) and the colored smoothing sweep (utils::smooth_classes_checked). No existing state says this: the attribute collections' protect flag is per thread and per operation, so it is false between two operations of a pass and on every thread not running one. Only the calls that register a collection read it; see throw_if_in_operation_pass().

◆ m_inconsistent_orientation_flips

std::atomic<size_t> wmtk::TetOptimizerMesh::m_inconsistent_orientation_flips = 0

Surface flips that joined two faces not oriented alike (a fold of the tracked surface, or unequal multiplicities).

The flip runs anyway – orientation must not change the operations – so the oriented surface no longer has the input's boundary there, and the tracked winding number is not an integer near the flipped faces. Nonzero only on a tracked surface that was folded or inconsistently oriented to begin with.

◆ m_insertion_sources

std::vector<std::pair<PositionKey, std::vector<uint32_t> > > wmtk::TetOptimizerMesh::m_insertion_sources

Where the tracked faces lie on the input the mesh was made from: by position key, sorted, the input triangles. Filled at insertion when a surface history is to start from the input; record_surface_history takes it.

◆ m_newton

optimization::NewtonCounters wmtk::TetOptimizerMesh::m_newton

How the solves smooth_after() makes ended – iterations and stop status – reported and reset once per pass, beside m_smooth_rejects. An application that solves on a path of its own keeps its own counters and reports them from log_smoothing_pass_accounting().

◆ m_op_epoch

uint32_t wmtk::TetOptimizerMesh::m_op_epoch = 0
protected

CHURN INSTRUMENTATION. Bumped at the start of every split pass in local_operations(), so the pass a vertex was born in can be compared against the pass a collapse removes it in. Zero until the first split pass runs, which is what lets a construction-era vertex be told apart from an optimization-split one. Never reset – only differences mean anything.

◆ m_params

OptimizerParameters& wmtk::TetOptimizerMesh::m_params

Only the fields shared by all three applications; each derived class keeps a typed reference to its own Parameters for the rest.

◆ m_recorded_volume

std::shared_ptr<history::VolumeRecorder> wmtk::TetOptimizerMesh::m_recorded_volume

The volume being recorded, kept past stop_surface_history() until finished; the offset of the recorded surface edits in the surface history finish_surface_history() returned, and that history's key, which the volume history keeps.

◆ m_s_amips

double wmtk::TetOptimizerMesh::m_s_amips = 1.

Scale factors putting AMIPS (dimensionless) and the envelope energy (a squared distance) on a comparable footing.

◆ m_track_feature_edges

bool wmtk::TetOptimizerMesh::m_track_feature_edges = false

Whether the shared operations maintain m_feature_edge_attribute.

The operations are guarded by THIS flag, never by p_edge_attrs != nullptr: topological_offset also registers an edge collection with m_edge_attr_group, with its own attribute type, so a non-null p_edge_attrs says nothing about feature tags.

◆ m_tracks_orientation

bool wmtk::TetOptimizerMesh::m_tracks_orientation = false

The application set FaceAttributes::m_orientation at insertion, so the tracked surface carries the input's orientation and the operations keep it.

The operations maintain the orientation whether or not this is set (it is 0 everywhere on a mesh that never set it, and stays 0); the flag says whether a consumer may trust it. See tracked_surface_boundary() for the invariant it obeys. The orientation never changes which operations run: it only feeds the tracked winding number.

◆ m_vertex_attr_group

AttributeContainerGroup wmtk::TetOptimizerMesh::m_vertex_attr_group

What p_vertex_attrs points at, so a derived class can register more.

VertexAttributes holds only what both 3D applications need. tetwild adds a per-vertex open-boundary flag through here; simwild never sets one, so it does not carry the field.

◆ MAX_ENERGY

constexpr double wmtk::TetOptimizerMesh::MAX_ENERGY = 1e50
staticconstexpr

The sentinel get_quality returns for an element AMIPS cannot score.

Not an energy: a positively oriented tet whose volume is too small for AMIPS, or one that produces inf/nan, gets this instead. The cell quality holds AMIPS^3, so it surfaces in the logs as its cube root, cbrt(1e50) = 4.6e16. 1e50 rather than double::max because every downstream ratio must stay finite – avg_energy sums qualities and would go inf.


The documentation for this class was generated from the following files: