5#include <wmtk/Types.hpp>
6#include <wmtk/envelope/Envelope.hpp>
8#include <wmtk/threading/enumerable_thread_specific.hpp>
9#include "ExactBandIntegral.hpp"
10#include "SimplicialComplexBVH.hpp"
12#include <polysolve/nonlinear/Problem.hpp>
21namespace wmtk::components::topological_offset {
43 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
46 using VecD = Eigen::Matrix<double, DIM, 1>;
47 using MatD = Eigen::Matrix<double, DIM, DIM>;
58 double delta()
const {
return m_delta; }
62 double dhat()
const {
return m_dhat; }
78 virtual double value(
const VecD& p)
const = 0;
81 virtual VecD gradient(
const VecD& p)
const = 0;
82 virtual MatD hessian(
const VecD& p)
const = 0;
195 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
198 using VecD =
typename OffsetPotential<DIM>::VecD;
199 using MatD =
typename OffsetPotential<DIM>::MatD;
223 const std::vector<int>& P,
229 double value(
const VecD& p)
const override;
230 VecD gradient(
const VecD& p)
const override;
231 MatD hessian(
const VecD& p)
const override;
233 void value_gradient(
const VecD& p,
double& v, VecD& g)
const override;
287 void build(
const MatrixXd& V,
const MatrixXi& E,
const MatrixXi& F,
const std::vector<int>& P);
297 std::unique_ptr<Impl> m_impl;
300using SmoothOffsetPotential2D = SmoothOffsetPotential<2>;
301using SmoothOffsetPotential3D = SmoothOffsetPotential<3>;
335 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
339 using VecD =
typename OffsetPotential<DIM>::VecD;
340 using MatD =
typename OffsetPotential<DIM>::MatD;
363 double value(
const VecD& p)
const override;
364 VecD gradient(
const VecD& p)
const override;
365 MatD hessian(
const VecD& p)
const override;
391 void nearest_feature(
const VecD& p, VecD& foot,
int& dim, VecD& dir)
const;
401 std::shared_ptr<SimplicialComplexBVH> m_bvh;
434 using typename polysolve::nonlinear::Problem::Scalar;
435 using typename polysolve::nonlinear::Problem::THessian;
436 using typename polysolve::nonlinear::Problem::TVector;
438 using VecD = Eigen::Matrix<double, DIM, 1>;
439 using MatD = Eigen::Matrix<double, DIM, DIM>;
455 bool gauss_newton =
true,
456 bool distance_residual =
false,
457 bool one_sided =
false);
459 double value(
const TVector& x)
override;
460 void gradient(
const TVector& x, TVector& gradv)
override;
461 void hessian(
const TVector& x, THessian& hessian)
override
463 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
465 void hessian(
const TVector& x, MatrixXd& hessian)
override;
467 void solution_changed(
const TVector& new_x)
override {}
470 std::shared_ptr<const OffsetPotential<DIM>> m_potential;
473 bool m_distance_residual;
476 void residual(
const VecD& p,
double& r, VecD& dr)
const;
525 using typename polysolve::nonlinear::Problem::Scalar;
526 using typename polysolve::nonlinear::Problem::THessian;
527 using typename polysolve::nonlinear::Problem::TVector;
538 std::vector<Sample> samples;
542 const std::shared_ptr<const OffsetPotential2D>& potential,
543 std::vector<Edge> edges,
545 bool gauss_newton =
false);
547 double value(
const TVector& x)
override;
548 void gradient(
const TVector& x, TVector& gradv)
override;
549 void hessian(
const TVector& x, THessian& hessian)
override
551 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
553 void hessian(
const TVector& x, MatrixXd& hessian)
override;
554 void solution_changed(
const TVector& new_x)
override {}
563 Eigen::Vector2d dr = Eigen::Vector2d::Zero();
573 const std::vector<Reading>&
readings_at(
const Eigen::Vector2d& x,
bool need_dr)
const;
575 std::shared_ptr<const OffsetPotential2D> m_potential;
576 std::vector<Edge> m_edges;
581 mutable std::vector<Reading> m_readings;
582 mutable Eigen::Vector2d m_readings_x;
583 mutable bool m_readings_valid =
false;
584 mutable bool m_readings_have_dr =
false;
608 using typename polysolve::nonlinear::Problem::Scalar;
609 using typename polysolve::nonlinear::Problem::THessian;
610 using typename polysolve::nonlinear::Problem::TVector;
613 Eigen::Vector2d q1,
q2;
618 double value(
const TVector& x)
override;
619 void gradient(
const TVector& x, TVector& gradv)
override;
620 void hessian(
const TVector& x, THessian& hessian)
override
622 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
624 void hessian(
const TVector& x, MatrixXd& hessian)
override;
625 void solution_changed(
const TVector& new_x)
override {}
626 bool is_step_valid(
const TVector& x0,
const TVector& x1)
override;
630 bool cell_F(
const Eigen::Vector2d& x,
const Cell& c, Eigen::Matrix2d& F,
double& d)
const;
631 std::vector<Cell> m_cells;
649 using typename polysolve::nonlinear::Problem::Scalar;
650 using typename polysolve::nonlinear::Problem::THessian;
651 using typename polysolve::nonlinear::Problem::TVector;
654 double value(
const TVector& x)
override;
655 void gradient(
const TVector& x, TVector& gradv)
override;
656 void hessian(
const TVector& x, THessian& hessian)
override
658 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
660 void hessian(
const TVector& x, MatrixXd& hessian)
override;
661 void solution_changed(
const TVector& new_x)
override {}
662 bool is_step_valid(
const TVector& x0,
const TVector& x1)
override;
669 std::vector<std::array<double, 12>> m_cells;
671 bool m_x_set =
false;
672 Eigen::Vector3d m_x = Eigen::Vector3d::Zero();
674 bool m_value_set =
false;
676 bool m_grad_set =
false;
710 using typename polysolve::nonlinear::Problem::Scalar;
711 using typename polysolve::nonlinear::Problem::THessian;
712 using typename polysolve::nonlinear::Problem::TVector;
717 std::array<Eigen::Vector3d, 3> q;
718 Eigen::Matrix3d rest_inv;
724 static bool cell(
const std::array<Eigen::Vector3d, 3>& q,
const Eigen::Matrix3d& R,
Cell& out);
729 static double value_of(
const std::array<Eigen::Vector3d, 4>& p,
const Eigen::Matrix3d& R);
733 double value(
const TVector& x)
override;
734 void gradient(
const TVector& x, TVector& gradv)
override;
735 void hessian(
const TVector& x, THessian& hessian)
override
737 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
739 void hessian(
const TVector& x, MatrixXd& hessian)
override;
740 void solution_changed(
const TVector& new_x)
override {}
741 bool is_step_valid(
const TVector& x0,
const TVector& x1)
override;
744 double eval(
const Eigen::Vector3d& x,
int need, Eigen::Vector3d& g, Eigen::Matrix3d& H)
const;
745 std::vector<Cell> m_cells;
778double input_pad(
const Eigen::MatrixXd& V);
783int64_t nearest_primitive(
const Envelope& env,
double pad,
const Eigen::Vector3d& p);
790double min_mean_distance(
793 const Eigen::Vector3d* p,
802 double d1 = 0., d2 = 0., d3 = 0.;
812 const Eigen::Vector3d& c,
814 const std::array<Eigen::Vector3d, 3>& q,
815 std::vector<BallCandidate>& out);
821double min_triangle_distance(
824 const Eigen::Vector3d& a,
825 const Eigen::Vector3d& b,
826 const Eigen::Vector3d& c);
833double min_max_corner_distance(
const Envelope& env,
double pad,
const Eigen::Vector3d* p,
int n);
840double face_mean_sq_cos(
843 const Eigen::Vector3d& a,
844 const Eigen::Vector3d& b,
845 const Eigen::Vector3d& c,
846 const Eigen::Vector3d& n,
890 using typename polysolve::nonlinear::Problem::Scalar;
891 using typename polysolve::nonlinear::Problem::THessian;
892 using typename polysolve::nonlinear::Problem::TVector;
896 Eigen::Vector3d q1, q2, q3;
903 std::shared_ptr<const Envelope> env,
905 std::vector<Cell> cells,
906 const Eigen::Vector3d& x0,
909 double value(
const TVector& x)
override;
910 void gradient(
const TVector& x, TVector& gradv)
override;
911 void hessian(
const TVector& x, THessian& hessian)
override
913 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
915 void hessian(
const TVector& x, MatrixXd& hessian)
override;
916 void solution_changed(
const TVector& new_x)
override {}
933 Eigen::Vector3d a, b;
957 std::shared_ptr<const ExactBandIntegral> eb,
959 std::vector<Face> faces);
975 const Eigen::Vector3d& x0,
976 const Eigen::Vector3d& x1,
977 const std::vector<std::array<Eigen::Vector3d, 2>>& faces,
983 std::atomic<size_t> evals{0}, ring_cells{0};
1013 std::shared_ptr<const ExactBandIntegral> eb,
1015 std::vector<std::array<Eigen::Vector3d, 2>> faces,
1022 double eval(
const Eigen::Vector3d& x,
int need, Eigen::Vector3d& g, Eigen::Matrix3d& H)
const;
1030 double m_delta = 1.;
1035 mutable Eigen::Vector3d m_min_x = Eigen::Vector3d::Zero();
1036 mutable std::vector<double> m_min_md;
1037 mutable std::vector<int64_t> m_min_tri;
1039 mutable Eigen::Vector3d
m_ball_c = Eigen::Vector3d::Zero();
1040 mutable double m_ball_r = -1.;
1041 mutable std::vector<std::vector<BallCandidate>> m_ball_cand;
1043 std::shared_ptr<const ExactBandIntegral>
m_eb;
1047 mutable bool m_eb_val_set =
false, m_eb_der_set =
false;
1048 mutable Eigen::Vector3d m_eb_val_x = Eigen::Vector3d::Zero();
1049 mutable Eigen::Vector3d m_eb_der_x = Eigen::Vector3d::Zero();
1050 mutable double m_eb_E = 0.;
1051 mutable Eigen::Vector3d m_eb_g = Eigen::Vector3d::Zero();
1052 mutable Eigen::Matrix3d m_eb_H = Eigen::Matrix3d::Zero();
1056 std::vector<Face> m_ff_faces;
1060 mutable std::vector<double> m_ff_U;
1061 mutable std::vector<Eigen::Vector3d> m_ff_Ux;
1062 mutable std::vector<char> m_ff_Ux_set;
1064 double ff_eval(
const Eigen::Vector3d& x,
int need, Eigen::Vector3d& g, Eigen::Matrix3d& H)
1069 std::vector<std::array<Eigen::Vector3d, 2>> m_sw_faces;
1070 mutable std::vector<ExactBandIntegral::FaceParts> m_sw_fparts;
1073 double sw_eval(
const Eigen::Vector3d& x,
int need, Eigen::Vector3d& g, Eigen::Matrix3d& H)
1076 Eigen::Vector3d
m_x0 = Eigen::Vector3d::Zero();
1078 std::vector<Cell> m_cells;
1089const std::vector<std::array<double, 3>>& subdivision_face_stencil(
int order);
1098const std::vector<std::array<double, 3>>& interior_face_stencil(
int order);
1108const std::vector<std::array<double, 3>>& fem_face_stencil(
int order);
1122const std::vector<double>& fem_face_stencil_weights(
int order);
1147 using typename polysolve::nonlinear::Problem::Scalar;
1148 using typename polysolve::nonlinear::Problem::THessian;
1149 using typename polysolve::nonlinear::Problem::TVector;
1153 Eigen::Vector3d q1, q2;
1156 std::shared_ptr<const OffsetPotential3D> pot,
1157 std::vector<Face> faces,
1166 std::shared_ptr<const OffsetPotential3D> pot,
1167 std::vector<Face> faces,
1168 const std::vector<std::array<double, 3>>& stencil,
1169 const std::vector<double>* point_weights,
1172 double value(
const TVector& x)
override;
1173 void gradient(
const TVector& x, TVector& gradv)
override;
1174 void hessian(
const TVector& x, THessian& hessian)
override
1176 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
1178 void hessian(
const TVector& x, MatrixXd& hessian)
override;
1179 void solution_changed(
const TVector& new_x)
override {}
1185 const OffsetPotential3D& pot,
1186 const std::vector<std::array<double, 3>>& stencil,
1187 const std::vector<double>* point_weights,
1189 const Eigen::Vector3d& a,
1190 const Eigen::Vector3d& b,
1191 const Eigen::Vector3d& c);
1195 double eval(
const Eigen::Vector3d& x,
int need, Eigen::Vector3d& g, Eigen::Matrix3d& H)
const;
1196 std::shared_ptr<const OffsetPotential3D> m_pot;
1197 std::vector<Face> m_faces;
1198 const std::vector<std::array<double, 3>>& m_stencil;
Definition Envelope.hpp:19
A vertex's part of the energy's band term (TopoOffsetTetMesh::band_cell_term()), the vertex moving:
Definition OffsetPotential.hpp:888
bool m_sw
Definition OffsetPotential.hpp:1068
double m_pad
input_pad() of the input
Definition OffsetPotential.hpp:1029
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()).
Definition OffsetPotential.cpp:1429
std::shared_ptr< const ExactBandIntegral > m_eb
set_exact_integral(): the integral, and the last point's value / gradient and Hessian.
Definition OffsetPotential.hpp:1043
double eval(const Eigen::Vector3d &x, int need, Eigen::Vector3d &g, Eigen::Matrix3d &H) const
need: 0 value, 1 + gradient, 2 + Hessian.
Definition OffsetPotential.cpp:1615
Eigen::Vector3d m_ball_c
certify_ball(): the ball's centre and radius (< 0: none), and per cell its candidates.
Definition OffsetPotential.hpp:1039
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...
Definition OffsetPotential.cpp:1356
void exact_minima(const Eigen::Vector3d &x) const
m_min_md and m_min_tri at x (see the class comment).
Definition OffsetPotential.cpp:1584
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....
Definition OffsetPotential.cpp:1367
std::vector< ExactBandIntegral::Partition > m_eb_parts
Definition OffsetPotential.hpp:1046
bool certify_ball(const Eigen::Vector3d &x) const
Definition OffsetPotential.cpp:1563
std::vector< ExactBandIntegral::FaceParts > m_ff_fparts
Definition OffsetPotential.hpp:1059
std::shared_ptr< const Envelope > m_env
the input's primitives
Definition OffsetPotential.hpp:1028
static std::string & front_flux_error()
Definition OffsetPotential.cpp:1492
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()).
Definition OffsetPotential.cpp:1498
std::vector< int64_t > m_hint
Definition OffsetPotential.hpp:1031
bool m_ff
Definition OffsetPotential.hpp:1055
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)
Definition OffsetPotential.cpp:1386
bool m_min_set
Definition OffsetPotential.hpp:1034
Eigen::Vector3d m_x0
The moving vertex's position at construction.
Definition OffsetPotential.hpp:1076
std::pair< Eigen::Vector3d, double > certified_ball() const
The current certified ball, its centre and radius (radius < 0: none yet). For the tests.
Definition OffsetPotential.hpp:1018
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 ...
Definition OffsetPotential.cpp:1411
The per-tet energy's AMIPS term as the smoother minimises it: w * sum over cells of vol AMIPS^3 (Topo...
Definition OffsetPotential.hpp:647
std::vector< double > m_a
per cell: AMIPS at m_x
Definition OffsetPotential.hpp:673
void at_point(const TVector &x)
Definition OffsetPotential.cpp:900
The Euclidean offset: Phi = d(p, input complex), level set d = delta.
Definition OffsetPotential.hpp:334
std::string describe_active(const VecD &p) const override
Diagnostic: what the field is made of at p, one contribution per line.
Definition OffsetPotential.cpp:705
double relative_residual(const VecD &p) const override
Definition OffsetPotential.hpp:377
std::shared_ptr< Envelope > m_envelope
Definition OffsetPotential.hpp:400
bool is_euclidean() const override
The Euclidean field: value() is the distance, so a distance residual is the plain one.
Definition OffsetPotential.hpp:338
bool is_inside_offset(const VecD &p) const override
Definition OffsetPotential.hpp:384
void nearest_feature(const VecD &p, VecD &foot, int &dim, VecD &dir) const
Definition OffsetPotential.cpp:600
bool within_support(const VecD &p) const override
Everywhere. d has no compact support.
Definition OffsetPotential.hpp:380
double residual_length(const VecD &p) const override
Definition OffsetPotential.hpp:369
The band-volume integral of one cell, in closed form:
Definition ExactBandIntegral.hpp:104
The offset term of the smoothing objective: w * (Phi(x) - c)^2.
Definition OffsetPotential.hpp:432
void residual(const VecD &p, double &r, VecD &dr) const
r and its gradient under either residual (see the constructor).
Definition OffsetPotential.cpp:478
The offset potential: the scalar field on space whose level set the front is placed on.
Definition OffsetPotential.hpp:42
double delta() const
The offset distance the field is calibrated to.
Definition OffsetPotential.hpp:58
virtual bool is_inside_offset(const VecD &p) const =0
Whether p lies inside the offset region – on the complex's side of the level set.
virtual std::string describe_active(const VecD &p) const =0
Diagnostic: what the field is made of at p, one contribution per line.
double m_grad_ref
Definition OffsetPotential.hpp:140
double level_set_slope() const
|d(field)/d(distance)| at the level set on a flat stretch of input.
Definition OffsetPotential.hpp:76
OffsetPotential(const double delta, const double dhat)
Definition OffsetPotential.hpp:130
virtual double residual_length(const VecD &p) const =0
Distance from p to the level set, in length units.
double dhat() const
Definition OffsetPotential.hpp:62
virtual bool is_euclidean() const
The Euclidean field: value() is the distance, so a distance residual is the plain one.
Definition OffsetPotential.hpp:80
virtual ~OffsetPotential()
double target_level() const
The level value the offset boundary is placed on.
Definition OffsetPotential.hpp:55
virtual double relative_residual(const VecD &p) const =0
The signed distance from p to the level set, as a fraction of delta: > 0 outside the offset region,...
virtual void value_gradient(const VecD &p, double &v, VecD &g) const
Definition OffsetPotential.hpp:86
virtual bool within_support(const VecD &p) const =0
Whether p is somewhere the field can give a direction to the level set at all.
AMIPS against a rest shape, for deform_others: the smoothing term of a deformable region's faces.
Definition OffsetPotential.hpp:606
bool cell_F(const Eigen::Vector2d &x, const Cell &c, Eigen::Matrix2d &F, double &d) const
e = tr(F^T F), d = det F at x for one cell; false when d <= 0.
Definition OffsetPotential.cpp:739
The smooth offset potential Phi, and the offset defined as its level set Phi = c.
Definition OffsetPotential.hpp:194
std::string describe_active(const VecD &p) const override
Diagnostic: Phi, |grad Phi| and the trace of the Hessian at p.
Definition OffsetPotential.cpp:263
bool level_set_distance(const VecD &p, double &t) const
Definition OffsetPotential.cpp:286
bool within_support(const VecD &p) const override
Whether p is inside the support at all, i.e. Phi(p) > 0.
Definition OffsetPotential.hpp:268
void value_gradient(const VecD &p, double &v, VecD &g) const override
value() and gradient() at p from one collision build; see the definition.
Definition OffsetPotential.cpp:274
double relative_residual(const VecD &p) const override
The same root, signed and over delta: t / delta, > 0 outside the offset region. NaN where residual_le...
Definition OffsetPotential.cpp:452
double residual_length(const VecD &p) const override
The distance from p to the level set Phi = c ALONG THE FIELD, in length units.
Definition OffsetPotential.cpp:445
bool is_inside_offset(const VecD &p) const override
Phi decreases with distance, so the offset region is where it is still above the level.
Definition OffsetPotential.hpp:271
THE offset term of a 2D front vertex's smoothing objective: the mean squared relative error of the fi...
Definition OffsetPotential.hpp:523
double m_c
the potential's target level, cached
Definition OffsetPotential.hpp:579
const std::vector< Reading > & readings_at(const Eigen::Vector2d &x, bool need_dr) const
Definition OffsetPotential.cpp:1732
EXPERIMENTAL_band_volume_rule "surface": a vertex's part of the offset term, the vertex x moving,...
Definition OffsetPotential.hpp:1145
const std::vector< double > * m_point_weights
The points' area weights (fem_face_stencil_weights()); null for the plain mean.
Definition OffsetPotential.hpp:1200
static double face_value(const OffsetPotential3D &pot, const std::vector< std::array< double, 3 > > &stencil, const std::vector< double > *point_weights, double weight, const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c)
Definition OffsetPotential.cpp:2005
double eval(const Eigen::Vector3d &x, int need, Eigen::Vector3d &g, Eigen::Matrix3d &H) const
need: 0 value, 1 + gradient, 2 + Hessian.
Definition OffsetPotential.cpp:2056
The per-tet energy's AMIPS term for cells measured against a REFERENCE shape R, at one moving vertex ...
Definition OffsetPotential.hpp:708
static bool cell(const std::array< Eigen::Vector3d, 3 > &q, const Eigen::Matrix3d &R, Cell &out)
Definition OffsetPotential.cpp:1017
static Eigen::Matrix3d regular_rest()
The regular tet's edge matrix (unit edges): the elastic reference.
Definition OffsetPotential.cpp:1008
static double value_of(const std::array< Eigen::Vector3d, 4 > &p, const Eigen::Matrix3d &R)
Definition OffsetPotential.cpp:1031
A primitive and its distances to three fixed points (ball_candidates()).
Definition OffsetPotential.hpp:800
One band cell of the ring: its three other corners, at their current positions.
Definition OffsetPotential.hpp:895
Definition OffsetPotential.hpp:932
Definition OffsetPotential.hpp:982
Definition ExactBandIntegral.hpp:133
Definition OffsetPotential.hpp:612
Eigen::Matrix2d rest_inv
inverse rest Jacobian [r1-r0, r2-r0]^-1, same corner order
Definition OffsetPotential.hpp:614
Eigen::Vector2d q2
the fixed endpoints, current positions
Definition OffsetPotential.hpp:613
One incident front chord, the moving vertex implicit.
Definition OffsetPotential.hpp:536
Definition OffsetPotential.hpp:561
One stencil point's barycentric weights. a is the moving vertex's, so dq_i/dx = a_i I.
Definition OffsetPotential.hpp:531
One offset face at the moving vertex: its two fixed corners.
Definition OffsetPotential.hpp:1152
Definition OffsetPotential.hpp:716
double c
det(R)^2 / 6
Definition OffsetPotential.hpp:720
Eigen::Vector3d s
rest_inv^T 1
Definition OffsetPotential.hpp:719