Wildmeshing Toolkit
Loading...
Searching...
No Matches
Classes | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
wmtk::components::topological_offset::BandVolumeEnergy3D Class Reference

A vertex's part of the energy's band term (TopoOffsetTetMesh::band_cell_term()), the vertex moving: More...

#include <OffsetPotential.hpp>

Inheritance diagram for wmtk::components::topological_offset::BandVolumeEnergy3D:

Classes

struct  Cell
 One band cell of the ring: its three other corners, at their current positions. More...
 
struct  Face
 
struct  SweptDerivCounts
 

Public Member Functions

 BandVolumeEnergy3D (std::shared_ptr< const Envelope > env, double pad, std::vector< Cell > cells, const Eigen::Vector3d &x0, double delta)
 
double value (const TVector &x) override
 
void gradient (const TVector &x, TVector &gradv) override
 
void hessian (const TVector &x, THessian &hessian) override
 
void hessian (const TVector &x, MatrixXd &hessian) override
 
void solution_changed (const TVector &new_x) override
 
void set_exact_integral (std::shared_ptr< const ExactBandIntegral > eb, double delta)
 EXPERIMENTAL_band_volume_rule "exact": a cell's Vol_t m_t becomes J_t / delta, J_t = int_t (d - delta) dV in closed form (ExactBandIntegral), the moving vertex x one of t's corners – the term band_cell_term() reads. Values from ExactBandIntegral::value(), the function band_cell_term() calls (the corners in another order); gradient and Hessian from ExactBandIntegral::value_grad_hess() in x (its J equals value() to rounding): exact, except on rule-(a) pieces (the bound's derivative) and at a kink of d on a face of t through x (the one-sided limit for x moving into t). The last point's value, and its gradient and Hessian, are kept: polysolve asks for each separately at one x. The corner bound's minima and certified ball are not used.
 
void set_front_flux (std::shared_ptr< const ExactBandIntegral > eb, double delta, std::vector< Face > faces)
 EXPERIMENTAL_band_volume_rule "front_flux": the front form of the same band term (ExactBandIntegral.hpp): the value is (sum over the band's boundary faces f through x of int_f G.n dA.
 
void set_swept (std::shared_ptr< const ExactBandIntegral > eb, double delta, std::vector< std::array< Eigen::Vector3d, 2 > > faces, SweptDerivCounts *counts)
 EXPERIMENTAL_band_volume_rule "exact_swept": the smoother's search model is the function the move is judged on (TopoOffsetTetMesh::swept_accept()). Its value at x is swept_change(x0, x) over faces, x0 the position at construction: (E(B(x)) - E(B(x0))) / delta, E(B) = int_B chi (d - delta) dV, exactly where value() integrates every piece exactly. Its gradient and Hessian are E(B)'s at x by Reynolds' transport theorem: the sum over f of ExactBandIntegral::front_face_derivs((x, a_f, b_f), delta, 0) / delta, the "front_flux" rule's derivative, no D_t term (d is Lipschitz). Each face's normal stays out of B at every x the solver evaluates, where no ring cell is inverted (polysolve tests is_step_valid() before each trial value). Defined at x = x0 too, where every swept tet is flat and its own value_grad_hess() would be 0.
 
std::pair< Eigen::Vector3d, double > certified_ball () const
 The current certified ball, its centre and radius (radius < 0: none yet). For the tests.
 

Static Public Member Functions

static std::string & front_flux_error ()
 
static double swept_change (const ExactBandIntegral &eb, double delta, const Eigen::Vector3d &x0, const Eigen::Vector3d &x1, const std::vector< std::array< Eigen::Vector3d, 2 > > &faces, ExactBandIntegral::Stats *st=nullptr)
 

Private Member Functions

double eval (const Eigen::Vector3d &x, int need, Eigen::Vector3d &g, Eigen::Matrix3d &H) const
 need: 0 value, 1 + gradient, 2 + Hessian.
 
void exact_minima (const Eigen::Vector3d &x) const
 m_min_md and m_min_tri at x (see the class comment).
 
bool certify_ball (const Eigen::Vector3d &x) const
 
double ff_eval (const Eigen::Vector3d &x, int need, Eigen::Vector3d &g, Eigen::Matrix3d &H) const
 The front form's value / derivatives at x (eval()).
 
double sw_eval (const Eigen::Vector3d &x, int need, Eigen::Vector3d &g, Eigen::Matrix3d &H) const
 The "exact_swept" model's value / derivatives at x (eval()).
 

Private Attributes

std::shared_ptr< const Envelope > m_env
 the input's primitives
 
double m_pad = 0.
 input_pad() of the input
 
double m_delta = 1.
 
std::vector< int64_t > m_hint
 
bool m_min_set = false
 
Eigen::Vector3d m_min_x = Eigen::Vector3d::Zero()
 
std::vector< double > m_min_md
 
std::vector< int64_t > m_min_tri
 
Eigen::Vector3d m_ball_c = Eigen::Vector3d::Zero()
 certify_ball(): the ball's centre and radius (< 0: none), and per cell its candidates.
 
double m_ball_r = -1.
 
std::vector< std::vector< BallCandidate > > m_ball_cand
 
std::shared_ptr< const ExactBandIntegral > m_eb
 set_exact_integral(): the integral, and the last point's value / gradient and Hessian.
 
std::vector< ExactBandIntegral::Partition > m_eb_parts
 
bool m_eb_val_set = false
 
bool m_eb_der_set = false
 
Eigen::Vector3d m_eb_val_x = Eigen::Vector3d::Zero()
 
Eigen::Vector3d m_eb_der_x = Eigen::Vector3d::Zero()
 
double m_eb_E = 0.
 
Eigen::Vector3d m_eb_g = Eigen::Vector3d::Zero()
 
Eigen::Matrix3d m_eb_H = Eigen::Matrix3d::Zero()
 
bool m_ff = false
 
std::vector< Face > m_ff_faces
 
std::vector< ExactBandIntegral::FaceParts > m_ff_fparts
 
std::vector< double > m_ff_U
 
std::vector< Eigen::Vector3d > m_ff_Ux
 
std::vector< char > m_ff_Ux_set
 
bool m_sw = false
 
std::vector< std::array< Eigen::Vector3d, 2 > > m_sw_faces
 
std::vector< ExactBandIntegral::FaceParts > m_sw_fparts
 
SweptDerivCounts * m_sw_counts = nullptr
 
Eigen::Vector3d m_x0 = Eigen::Vector3d::Zero()
 The moving vertex's position at construction.
 
std::vector< Cell > m_cells
 

Detailed Description

A vertex's part of the energy's band term (TopoOffsetTetMesh::band_cell_term()), the vertex moving:

E(x) = sum over the vertex's band cells t of  Vol_t(x) * m_t(x),
m_t(x) = min over ALL input triangles P of (1/4) sum over t's 4 corners q of
         (d_P(q) - delta) / delta,

the four corners being x and the cell's three fixed ones, Vol_t the cell's signed volume, positive on a valid cell. Each cell's term is band_cell_term() at x, so the solve descends exactly the cell terms E sums.

Vol_t(x) = (q1 - x) . ((q2 - q1) x (q3 - q1)) / 6 is affine in x: its gradient is -(q2 - q1) x (q3 - q1) / 6 and its Hessian zero. The gradient and Hessian of m_t are the minimising triangle P's: grad m_t = grad d_P(x) / (4 delta), hess m_t = hess d_P(x) / (4 delta). So grad E_t = m_t grad Vol + Vol grad m_t and hess E_t = grad Vol grad m_t^T + grad m_t grad Vol^T + Vol hess m_t. The outer-product pair is indefinite in general; polysolve's Newton regularises, and the AMIPS term beside it carries the shape.

Every value, gradient and Hessian equals, bit for bit, that of a min_mean_distance() call per cell and evaluation; the work behind them is cut twice (exact_minima()):

Constructor & Destructor Documentation

◆ BandVolumeEnergy3D()

wmtk::components::topological_offset::BandVolumeEnergy3D::BandVolumeEnergy3D ( std::shared_ptr< const Envelope >  env,
double  pad,
std::vector< Cell >  cells,
const Eigen::Vector3d &  x0,
double  delta 
)

env and pad: the input's primitives and input_pad() of its vertices (the band term's searches). x0: the moving vertex's current position. Each cell's corners are ordered here so that its volume at x0 is positive (the ring the smoother starts from is valid). delta = target_distance.

Member Function Documentation

◆ certify_ball()

bool wmtk::components::topological_offset::BandVolumeEnergy3D::certify_ball ( const Eigen::Vector3d &  x) const
private

Centre the certified ball at x, when its radius there is positive and finite; false (the old ball kept) otherwise.

◆ front_flux_error()

std::string & wmtk::components::topological_offset::BandVolumeEnergy3D::front_flux_error ( )
static

The message of the last exception the front-flux band term threw on this thread, until the caller clears it (smooth_front_vertex() rethrows it after the solve).

◆ set_front_flux()

void wmtk::components::topological_offset::BandVolumeEnergy3D::set_front_flux ( std::shared_ptr< const ExactBandIntegral >  eb,
double  delta,
std::vector< Face >  faces 
)

EXPERIMENTAL_band_volume_rule "front_flux": the front form of the same band term (ExactBandIntegral.hpp): the value is (sum over the band's boundary faces f through x of int_f G.n dA.

  • sum over the cells t of D_t, for the flagged cells) / delta, which differs from the "exact" rule's sum over the cells of J_t / delta by the flux through the faces that do not hold x, a constant in x: a face holding x lies in two cells of x's ring, so its fluxes cancel unless one side is not a band cell. Gradient and Hessian are those of E(B) / delta in x (ExactBandIntegral::front_face(), summed over faces); they have no D_t term. D_t is evaluated for a cell flagged by ExactBandIntegral::front_flux_flag(), or whose bound on d exceeds front_flux_reach() (the flag's polytopes hold the bisector points with d <= reach only): U_t = ExactBandIntegral::distance_bound(), kept per cell with the x it was computed at and read as U_t + |x - x_U| at a later x, a bound too (each d_P is 1-Lipschitz and only x moves), the search repeated where that exceeds the reach. Why U_t and not d(x) + max |q - x| (d 1-Lipschitz): MEASURED (stored cube_out band, 52957 cells, reach 2 delta), the latter put 10618 band cells beyond the reach, 5.0 D_t evaluations per front vertex, where the cube outward has no region overlaps on its offset side at all. The certified ball and the exact rule's integrals are not used. Any exception from the band term is kept (front_flux_error()) before it propagates: the shared smoother takes an exception out of a solve for a failed line search.

◆ set_swept()

void wmtk::components::topological_offset::BandVolumeEnergy3D::set_swept ( std::shared_ptr< const ExactBandIntegral >  eb,
double  delta,
std::vector< std::array< Eigen::Vector3d, 2 > >  faces,
SweptDerivCounts *  counts 
)

EXPERIMENTAL_band_volume_rule "exact_swept": the smoother's search model is the function the move is judged on (TopoOffsetTetMesh::swept_accept()). Its value at x is swept_change(x0, x) over faces, x0 the position at construction: (E(B(x)) - E(B(x0))) / delta, E(B) = int_B chi (d - delta) dV, exactly where value() integrates every piece exactly. Its gradient and Hessian are E(B)'s at x by Reynolds' transport theorem: the sum over f of ExactBandIntegral::front_face_derivs((x, a_f, b_f), delta, 0) / delta, the "front_flux" rule's derivative, no D_t term (d is Lipschitz). Each face's normal stays out of B at every x the solver evaluates, where no ring cell is inverted (polysolve tests is_step_valid() before each trial value). Defined at x = x0 too, where every swept tet is flat and its own value_grad_hess() would be 0.

Where front_face_derivs() throws at x – a curved bisector crossing a piece of a face (not logged, ExactBandIntegral::QuietCurvedBisector), or a face's pieces not tiling it – the derivatives at that x are the "exact" rule's: the sum over the ring's band cells of ExactBandIntegral::grad_hess(t, 0) / delta, the derivative of the same E(B) up to the cells that do not move (the bound's on rule-(a) pieces). Every derivative evaluation is counted into counts, and those that took the ring cells'. The last point's value, and its gradient and Hessian, are kept.

Why: the former model, the 7-point rule of G = psi(d) grad d over the front faces with each rule point's feature kind frozen at x0, differed from the judged function by the jumps of G.n across the bisectors, which it left out. MEASURED with it (uk-sonic, screw piece 15, 8 threads, 5 turns, 2026-10-23): 4,752 of turn 2's 44,974 front solves refused after 4 halvings (10.6%); the ring max held at one vertex, (2.169, -16.6, 3.056), through turns 1-3 at 7.03 / 5.96 / 5.71x, against the "exact" rule's ring max 8.73 / 3.20 / 2.66x.

◆ swept_change()

double wmtk::components::topological_offset::BandVolumeEnergy3D::swept_change ( const ExactBandIntegral &  eb,
double  delta,
const Eigen::Vector3d &  x0,
const Eigen::Vector3d &  x1,
const std::vector< std::array< Eigen::Vector3d, 2 > > &  faces,
ExactBandIntegral::Stats *  st = nullptr 
)
static

"exact_swept": the band term's change for the vertex moving from x0 to x1, dE* / delta = ( sum over f of sign_f value(conv(x0, x1, a_f, b_f), delta) ) / delta, f = (x, a_f, b_f) the boundary faces of the band B through the vertex, ordered with their normal (a_f - x0) x (b_f - x0) out of B (TopoOffsetTetMesh::band_swept_faces()), sign_f the sign of (x1 - x0) along it by exact orient3d, a flat swept tet skipped (TopoOffsetTetMesh, EXACT SWEPT CHANGE). value() with a Stats (st, or a local one), which keeps the value table out of the swept tets: no other call asks for them again. The one function both the decisions (TopoOffsetTetMesh::band_swept_sum()) and the smoother's search model (set_swept()) evaluate.

Member Data Documentation

◆ m_eb_parts

std::vector<ExactBandIntegral::Partition> wmtk::components::topological_offset::BandVolumeEnergy3D::m_eb_parts
mutableprivate

Per cell its partition at the last x it was evaluated at, shared by value() and value_grad_hess() (ExactBandIntegral::Partition).

◆ m_ff

bool wmtk::components::topological_offset::BandVolumeEnergy3D::m_ff = false
private

set_front_flux(): on, and the band's boundary faces through x; per cell its bound U_t on d and the x it was computed at (m_ff_Ux_set: computed).

◆ m_ff_fparts

std::vector<ExactBandIntegral::FaceParts> wmtk::components::topological_offset::BandVolumeEnergy3D::m_ff_fparts
mutableprivate

per face its labelled parts at the last x (ExactBandIntegral::FaceParts), shared by the value and the derivatives

◆ m_hint

std::vector<int64_t> wmtk::components::topological_offset::BandVolumeEnergy3D::m_hint
mutableprivate

per cell: the last minimiser (search start only)

◆ m_min_set

bool wmtk::components::topological_offset::BandVolumeEnergy3D::m_min_set = false
mutableprivate

exact_minima(): per cell min_mean_distance() and its minimiser at m_min_x (bitwise), the last point evaluated; valid once m_min_set.

◆ m_sw

bool wmtk::components::topological_offset::BandVolumeEnergy3D::m_sw = false
private

set_swept(): on, the boundary faces of B through x as (a_f, b_f), per face its labelled parts at the last x (ExactBandIntegral::FaceParts), and the counts.


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