3#include <wmtk/Types.hpp>
4#include <wmtk/envelope/Envelope.hpp>
6#include <wmtk/threading/enumerable_thread_specific.hpp>
7#include "SimplicialComplexBVH.hpp"
9#include <polysolve/nonlinear/Problem.hpp>
16namespace wmtk::components::topological_offset {
38 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
41 using VecD = Eigen::Matrix<double, DIM, 1>;
42 using MatD = Eigen::Matrix<double, DIM, DIM>;
53 double delta()
const {
return m_delta; }
57 double dhat()
const {
return m_dhat; }
73 virtual double value(
const VecD& p)
const = 0;
76 virtual VecD gradient(
const VecD& p)
const = 0;
77 virtual MatD hessian(
const VecD& p)
const = 0;
174 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
177 using VecD =
typename OffsetPotential<DIM>::VecD;
178 using MatD =
typename OffsetPotential<DIM>::MatD;
202 const std::vector<int>& P,
208 double value(
const VecD& p)
const override;
209 VecD gradient(
const VecD& p)
const override;
210 MatD hessian(
const VecD& p)
const override;
265 void build(
const MatrixXd& V,
const MatrixXi& E,
const MatrixXi& F,
const std::vector<int>& P);
278 std::unique_ptr<Impl> m_impl;
281using SmoothOffsetPotential2D = SmoothOffsetPotential<2>;
282using SmoothOffsetPotential3D = SmoothOffsetPotential<3>;
316 static_assert(DIM == 2 || DIM == 3,
"the offset potential exists in 2D and 3D only");
320 using VecD =
typename OffsetPotential<DIM>::VecD;
321 using MatD =
typename OffsetPotential<DIM>::MatD;
343 double value(
const VecD& p)
const override;
344 VecD gradient(
const VecD& p)
const override;
345 MatD hessian(
const VecD& p)
const override;
371 void nearest_feature(
const VecD& p, VecD& foot,
int& dim, VecD& dir)
const;
381 std::shared_ptr<SimplicialComplexBVH> m_bvh;
414 using typename polysolve::nonlinear::Problem::Scalar;
415 using typename polysolve::nonlinear::Problem::THessian;
416 using typename polysolve::nonlinear::Problem::TVector;
418 using VecD = Eigen::Matrix<double, DIM, 1>;
419 using MatD = Eigen::Matrix<double, DIM, DIM>;
429 bool gauss_newton =
true,
430 bool distance_residual =
false);
432 double value(
const TVector& x)
override;
433 void gradient(
const TVector& x, TVector& gradv)
override;
434 void hessian(
const TVector& x, THessian& hessian)
override
436 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
438 void hessian(
const TVector& x, MatrixXd& hessian)
override;
440 void solution_changed(
const TVector& new_x)
override {}
443 std::shared_ptr<const OffsetPotential<DIM>> m_potential;
446 bool m_distance_residual;
453 void residual(
const VecD& p,
double& r, VecD& dr)
const;
455 mutable bool m_cache_valid =
false;
456 mutable VecD m_cache_p;
457 mutable double m_cache_r = 0.;
458 mutable VecD m_cache_dr;
484 using typename polysolve::nonlinear::Problem::Scalar;
485 using typename polysolve::nonlinear::Problem::THessian;
486 using typename polysolve::nonlinear::Problem::TVector;
500 const std::shared_ptr<const OffsetPotential2D>& potential,
501 std::vector<Edge> edges,
505 void residual(
const Eigen::Vector2d& x,
const Edge& e,
double& r, Eigen::Vector2d& J)
const;
506 double value(
const TVector& x)
override;
507 void gradient(
const TVector& x, TVector& gradv)
override;
508 void hessian(
const TVector& x, THessian& hessian)
override
510 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
512 void hessian(
const TVector& x, MatrixXd& hessian)
override;
513 void solution_changed(
const TVector& new_x)
override {}
516 std::shared_ptr<const OffsetPotential2D> m_potential;
517 std::vector<Edge> m_edges;
518 double m_sign, m_weight;
520using OffsetEnergy3D = OffsetEnergy<3>;
538 using typename polysolve::nonlinear::Problem::Scalar;
539 using typename polysolve::nonlinear::Problem::THessian;
540 using typename polysolve::nonlinear::Problem::TVector;
543 Eigen::Vector3d q1,
q2;
552 const std::shared_ptr<const OffsetPotential3D>& potential,
553 std::vector<Face> faces,
557 void residual(
const Eigen::Vector3d& x,
const Face& f,
double& r, Eigen::Vector3d& J)
const;
558 double value(
const TVector& x)
override;
559 void gradient(
const TVector& x, TVector& gradv)
override;
560 void hessian(
const TVector& x, THessian& hessian)
override
562 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
564 void hessian(
const TVector& x, MatrixXd& hessian)
override;
565 void solution_changed(
const TVector& new_x)
override {}
568 std::shared_ptr<const OffsetPotential3D> m_potential;
569 std::vector<Face> m_faces;
570 double m_sign, m_weight;
620 using typename polysolve::nonlinear::Problem::Scalar;
621 using typename polysolve::nonlinear::Problem::THessian;
622 using typename polysolve::nonlinear::Problem::TVector;
633 Eigen::Vector3d q1, q2;
634 std::vector<Sample> samples;
639 const std::shared_ptr<const OffsetPotential3D>& potential,
640 std::vector<Face> faces,
643 double value(
const TVector& x)
override;
644 void gradient(
const TVector& x, TVector& gradv)
override;
645 void hessian(
const TVector& x, THessian& hessian)
override
647 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
649 void hessian(
const TVector& x, MatrixXd& hessian)
override;
650 void solution_changed(
const TVector& new_x)
override {}
655 bool residual_at(
const Eigen::Vector3d& p,
double& r, Eigen::Vector3d* dr)
const;
657 std::shared_ptr<const OffsetPotential3D> m_potential;
658 std::vector<Face> m_faces;
684 using typename polysolve::nonlinear::Problem::Scalar;
685 using typename polysolve::nonlinear::Problem::THessian;
686 using typename polysolve::nonlinear::Problem::TVector;
689 Eigen::Vector2d q1,
q2;
694 double value(
const TVector& x)
override;
695 void gradient(
const TVector& x, TVector& gradv)
override;
696 void hessian(
const TVector& x, THessian& hessian)
override
698 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
700 void hessian(
const TVector& x, MatrixXd& hessian)
override;
701 void solution_changed(
const TVector& new_x)
override {}
702 bool is_step_valid(
const TVector& x0,
const TVector& x1)
override;
706 bool cell_F(
const Eigen::Vector2d& x,
const Cell& c, Eigen::Matrix2d& F,
double& d)
const;
707 std::vector<Cell> m_cells;
726 using typename polysolve::nonlinear::Problem::Scalar;
727 using typename polysolve::nonlinear::Problem::THessian;
728 using typename polysolve::nonlinear::Problem::TVector;
731 Eigen::Vector3d q1, q2,
q3;
736 double value(
const TVector& x)
override;
737 void gradient(
const TVector& x, TVector& gradv)
override;
738 void hessian(
const TVector& x, THessian& hessian)
override
740 log_and_throw_error(
"Sparse functions do not exist, use dense solver");
742 void hessian(
const TVector& x, MatrixXd& hessian)
override;
743 void solution_changed(
const TVector& new_x)
override {}
744 bool is_step_valid(
const TVector& x0,
const TVector& x1)
override;
748 bool cell_F(
const Eigen::Vector3d& x,
const Cell& c, Eigen::Matrix3d& F,
double& d)
const;
749 std::vector<Cell> m_cells;
First-order offset term: each front edge at the vertex against the field.
Definition OffsetPotential.hpp:482
void residual(const Eigen::Vector2d &x, const Edge &e, double &r, Eigen::Vector2d &J) const
r_e and its derivative for one edge; r = 0 with J = 0 where grad Phi vanishes.
Definition OffsetPotential.cpp:950
The 3D twin of AlignEnergy2D: each incident front FACE at the vertex against the field.
Definition OffsetPotential.hpp:536
void residual(const Eigen::Vector3d &x, const Face &f, double &r, Eigen::Vector3d &J) const
r_f and its derivative for one face; r = 0 with J = 0 where grad Phi or the face vanishes.
Definition OffsetPotential.cpp:1478
The Euclidean offset: Phi = d(p, input complex), level set d = delta.
Definition OffsetPotential.hpp:315
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:1323
double relative_residual(const VecD &p) const override
Definition OffsetPotential.hpp:357
bool is_euclidean() const override
The Euclidean field: value() is the distance, so a distance residual is the plain one.
Definition OffsetPotential.hpp:319
std::shared_ptr< SampleEnvelope > m_envelope
Definition OffsetPotential.hpp:380
bool is_inside_offset(const VecD &p) const override
Definition OffsetPotential.hpp:364
void nearest_feature(const VecD &p, VecD &foot, int &dim, VecD &dir) const
Definition OffsetPotential.cpp:1218
bool within_support(const VecD &p) const override
Everywhere. d has no compact support.
Definition OffsetPotential.hpp:360
double residual_length(const VecD &p) const override
Definition OffsetPotential.hpp:349
The offset term of the smoothing objective: w * (Phi(x) - c)^2.
Definition OffsetPotential.hpp:412
void residual(const VecD &p, double &r, VecD &dr) const
Definition OffsetPotential.cpp:1102
bool root_distance(const VecD &p, double &s, VecD &n) const
Definition OffsetPotential.cpp:1017
double m_last_root
warm start for root_distance(), see there
Definition OffsetPotential.hpp:454
The offset potential: the scalar field on space whose level set the front is placed on.
Definition OffsetPotential.hpp:37
double delta() const
The offset distance the field is calibrated to.
Definition OffsetPotential.hpp:53
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:127
double level_set_slope() const
|d(field)/d(distance)| at the level set on a flat stretch of input.
Definition OffsetPotential.hpp:71
OffsetPotential(const double delta, const double dhat)
Definition OffsetPotential.hpp:117
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:57
virtual bool is_euclidean() const
The Euclidean field: value() is the distance, so a distance residual is the plain one.
Definition OffsetPotential.hpp:75
virtual ~OffsetPotential()
double target_level() const
The level value the offset boundary is placed on.
Definition OffsetPotential.hpp:50
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 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:682
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:1357
The 3D twin of RestAMIPSEnergy2D: AMIPS of a tet against its rest shape.
Definition OffsetPotential.hpp:724
bool cell_F(const Eigen::Vector3d &x, const Cell &c, Eigen::Matrix3d &F, double &d) const
F and d = det F at x for one cell; false when d <= 0.
Definition OffsetPotential.cpp:1552
The smooth offset potential Phi, and the offset defined as its level set Phi = c.
Definition OffsetPotential.hpp:173
std::string describe_active(const VecD &p) const override
Definition OffsetPotential.cpp:669
bool level_set_distance(const VecD &p, double &t) const
Definition OffsetPotential.cpp:750
bool within_support(const VecD &p) const override
Whether p is inside the support at all, i.e. Phi(p) > 0.
Definition OffsetPotential.hpp:245
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:916
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:909
void value_gradient(const VecD &p, double &v, VecD &g) const
value() and gradient() at p from one collision build per part; see the definition.
Definition OffsetPotential.cpp:704
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:248
THE offset term of a front vertex's smoothing objective: the mean squared relative error of the field...
Definition OffsetPotential.hpp:618
double m_c
the potential's target level, cached
Definition OffsetPotential.hpp:660
bool residual_at(const Eigen::Vector3d &p, double &r, Eigen::Vector3d *dr) const
Definition OffsetPotential.cpp:1695
Definition OffsetPotential.hpp:488
Eigen::Vector2d q
the other endpoint
Definition OffsetPotential.hpp:489
double agree
Definition OffsetPotential.hpp:497
double sigma
Definition OffsetPotential.hpp:490
Definition OffsetPotential.hpp:542
double sigma
Definition OffsetPotential.hpp:544
double agree
Definition OffsetPotential.hpp:549
Eigen::Vector3d q2
the two other corners, in the band tet's orientation
Definition OffsetPotential.hpp:543
Definition OffsetPotential.hpp:688
Eigen::Matrix2d rest_inv
inverse rest Jacobian [r1-r0, r2-r0]^-1, same corner order
Definition OffsetPotential.hpp:690
Eigen::Vector2d q2
the fixed endpoints, current positions
Definition OffsetPotential.hpp:689
Definition OffsetPotential.hpp:730
Eigen::Vector3d q3
the fixed corners, current positions
Definition OffsetPotential.hpp:731
Eigen::Matrix3d rest_inv
inverse rest Jacobian [r1-r0, r2-r0, r3-r0]^-1
Definition OffsetPotential.hpp:732
Definition OffsetPotential.hpp:632
One stencil point's barycentric weights. a is the moving vertex's, so dq_i/dx = a_i I.
Definition OffsetPotential.hpp:626