|
Wildmeshing Toolkit
|
What tetwild and simwild's 3D mesh share. More...
#include <TetOptimizerMesh.h>
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 ¶ms, 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 > > ¢er_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 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 | |
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.
|
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.
|
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.
|
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.
|
virtual |
vids of the vertices incident to at least one "active" cell, for the skip-good-regions filter.
Reimplemented in wmtk::components::simwild::SimWildMesh.
|
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.
|
overrideprotectedvirtual |
Every live vertex, in the mesh's own iteration order.
Implements wmtk::RationalPositions.
|
protectedpure virtual |
Implemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
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.
|
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.
|
inlineoverridevirtual |
m_params.check_surface_folds; see there.
Reimplemented from wmtk::TetMesh.
| 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.
| 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.
|
inlineprotectedvirtual |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
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.
|
private |
| exact_ball_lock | claim 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. |
|
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.
| 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).
|
overridevirtual |
User specified modifications and desideratas for after an edge collapse.
| t | edge Tuple that's collapsed |
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
overridevirtual |
User specified preparations and desideratas for an edge collapse before changing the connectivity.
| t | edge Tuple to be collapsed |
check if on bbox/surface/boundary
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
inlineprotectedvirtual |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
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.
| 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.
|
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.
|
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.
|
overridevirtual |
Is a face part of the substructure.
| fid | Face ID |
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
| 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.
| 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.
| 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.
| 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.
| 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.
|
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.
| vid | Vertex ID |
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
overridevirtual |
Reimplemented from wmtk::TetMesh.
|
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.
|
overridevirtual |
The faces with m_is_surface_fs, for a surface history (TetMesh::start_surface_history).
Reimplemented from wmtk::TetMesh.
|
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.
|
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.
|
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.
|
inlineoverrideprotectedvirtual |
Reimplemented from wmtk::TetMesh.
|
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.
|
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.
|
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.
|
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.
|
inline |
The input's orientation on the face (m_orientation), where insertion recorded one; ascending vertex order where it did not.
|
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.
|
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.
|
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.
| 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.
| 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.
|
protectedpure virtual |
|
private |
Worst relative quality (quality_rel) over the cells incident to any vertex of vids.
| bool wmtk::TetOptimizerMesh::round | ( | const Tuple & | v | ) |
Round a vertex position to floating point, if that inverts no incident tet.
|
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.
|
overridevirtual |
User specified modifications and desideratas for after smoothing a vertex.
| t | Tuple refering to a vertex |
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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().
|
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.
|
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.
|
inlineprotectedvirtual |
Restore application cell data on the children made by a split.
Reimplemented in wmtk::components::simwild::SimWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.
|
inlineprotectedvirtual |
Application metadata not represented by the shared vertex attributes.
Reimplemented in wmtk::components::tetwild::TetWildMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.
|
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.
|
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.
|
overridevirtual |
This function computes the attributes for the added simplices. User specified modifications and desideratas for after an edge split.
| the | edge Tuple to be split |
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.
|
overridevirtual |
User specified preparations and desideratas for an edge split before changing the connectivity.
| the | edge Tuple to be split |
save face track info
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
| 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.
|
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.
|
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.
|
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.
|
overridevirtual |
Reimplemented from wmtk::TetMesh.
|
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.
|
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.
|
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.
|
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.
|
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).
| new_edge | The 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.
|
overridevirtual |
User specified modifications and desideratas for after a 4-4 edge swap.
| t | edge Tuple that's swaped |
Reimplemented from wmtk::TetMesh.
|
overridevirtual |
User specified preparations and desideratas for an 4-4 edge swap before changing the connectivity.
| t | edge Tuple to be swaped |
Reimplemented from wmtk::TetMesh.
|
overridevirtual |
User specified energy to decide which of the 4 possible orientations should be chosen.
Accepts the last shown orientation if not overridden.
| tets | New tets after performing a 4-4 swap. |
| op_case | The operation case, where 0 are the tets before swap. |
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
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).
| new_face | The candidate's new fan face; new_face[0] is the fan apex. |
Reimplemented from wmtk::TetMesh.
|
overridevirtual |
User specified modifications and desideratas for after a 5-6 edge swap.
| t | edge Tuple that's swaped |
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.
|
overridevirtual |
User specified preparations and desideratas for a 5-6 edge swap before changing the connectivity.
| t | edge Tuple to be swaped |
Reimplemented from wmtk::TetMesh.
|
overridevirtual |
User specified energy to decide which of the 5 possible orientations should be chosen.
Accepts the last shown orientation if not overridden.
| tets | New tets after performing a 5-6 swap. |
| op_case | The operation case, where 0 are the tets before swap. |
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
overridevirtual |
User specified modifications and desideratas for after a 3-2 edge swap.
| t | edge Tuple that's swaped |
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.
|
overridevirtual |
User specified preparations and desideratas for an 3-2 edge swap before changing the conenctivity.
| t | edge Tuple to be swaped |
Reimplemented from wmtk::TetMesh.
|
overridevirtual |
User specified modifications and desideratas for after a 2-3 face swap.
| t | edge Tuple that's swaped |
Reimplemented from wmtk::TetMesh.
|
overridevirtual |
User specified preparations and desideratas for an 2-3 face swap befroe changing the geometry.
| t | edge Tuple to be swaped |
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
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.
|
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.
|
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.
| 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.
|
overridevirtual |
The tagged feature edges (m_feature_edge_attribute) that are edges of tracked faces.
Reimplemented from wmtk::TetMesh.
|
overridevirtual |
Reimplemented from wmtk::TetMesh.
|
overridevirtual |
Reimplemented from wmtk::TetMesh.
| 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.
|
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.
| 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.
|
overridevirtual |
Is a vertex part of the substructure.
| vid | Vertex ID |
Reimplemented from wmtk::TetMesh.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
inlineoverrideprotectedvirtual |
Whether this vertex's double position is currently trusted.
Implements wmtk::RationalPositions.
|
protectedpure virtual |
Implemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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().
| 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.
| 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.
| 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().
|
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.
| 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.
| 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.
| double wmtk::TetOptimizerMesh::m_s_amips = 1. |
Scale factors putting AMIPS (dimensionless) and the envelope energy (a squared distance) on a comparable footing.
| 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.
| 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.
| 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.
|
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.