Wildmeshing Toolkit
Loading...
Searching...
No Matches
OffsetPotential.hpp
1#pragma once
2
3#include <functional>
4
5#include <wmtk/Types.hpp>
6#include <wmtk/envelope/Envelope.hpp>
7
8#include <wmtk/threading/enumerable_thread_specific.hpp>
9#include "ExactBandIntegral.hpp"
10#include "SimplicialComplexBVH.hpp"
11
12#include <polysolve/nonlinear/Problem.hpp>
13
14#include <array>
15#include <atomic>
16#include <cmath>
17#include <memory>
18#include <string>
19#include <vector>
20
21namespace wmtk::components::topological_offset {
22
40template <int DIM>
42{
43 static_assert(DIM == 2 || DIM == 3, "the offset potential exists in 2D and 3D only");
44
45public:
46 using VecD = Eigen::Matrix<double, DIM, 1>;
47 using MatD = Eigen::Matrix<double, DIM, DIM>;
48
53
55 double target_level() const { return m_c; }
56
58 double delta() const { return m_delta; }
59
62 double dhat() const { return m_dhat; }
63
76 double level_set_slope() const { return m_grad_ref; }
77
78 virtual double value(const VecD& p) const = 0;
80 virtual bool is_euclidean() const { return false; }
81 virtual VecD gradient(const VecD& p) const = 0;
82 virtual MatD hessian(const VecD& p) const = 0;
83
86 virtual void value_gradient(const VecD& p, double& v, VecD& g) const
87 {
88 v = value(p);
89 g = gradient(p);
90 }
91
98 virtual double residual_length(const VecD& p) const = 0;
99
111 virtual double relative_residual(const VecD& p) const = 0;
112
114 virtual bool within_support(const VecD& p) const = 0;
115
122 virtual bool is_inside_offset(const VecD& p) const = 0;
123
125 virtual std::string describe_active(const VecD& p) const = 0;
126
127protected:
130 OffsetPotential(const double delta, const double dhat)
131 : m_delta(delta)
132 , m_dhat(dhat)
133 {}
134
135 double m_delta = 0.;
136 double m_dhat = 0.;
137 double m_c = 0.;
140 double m_grad_ref = 1.;
141};
142
145
146
192template <int DIM>
194{
195 static_assert(DIM == 2 || DIM == 3, "the offset potential exists in 2D and 3D only");
196
197public:
198 using VecD = typename OffsetPotential<DIM>::VecD;
199 using MatD = typename OffsetPotential<DIM>::MatD;
200
220 const MatrixXd& V,
221 const MatrixXi& E,
222 const MatrixXi& F,
223 const std::vector<int>& P,
224 double delta,
225 double dhat_factor);
226
227 ~SmoothOffsetPotential() override;
228
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;
234
247 double residual_length(const VecD& p) const override;
248
265 double relative_residual(const VecD& p) const override;
266
268 bool within_support(const VecD& p) const override { return value(p) > 0.; }
269
271 bool is_inside_offset(const VecD& p) const override { return value(p) >= m_c; }
272
274 std::string describe_active(const VecD& p) const override;
275
276private:
277 // Dependent base members: name them unqualified in the definitions below.
278 using OffsetPotential<DIM>::m_delta;
279 using OffsetPotential<DIM>::m_dhat;
280 using OffsetPotential<DIM>::m_c;
282
285 SmoothOffsetPotential(double delta, double dhat_factor, int /*calibration tag*/);
286
287 void build(const MatrixXd& V, const MatrixXi& E, const MatrixXi& F, const std::vector<int>& P);
288
292 bool level_set_distance(const VecD& p, double& t) const;
293
296 struct Impl;
297 std::unique_ptr<Impl> m_impl;
298};
299
300using SmoothOffsetPotential2D = SmoothOffsetPotential<2>;
301using SmoothOffsetPotential3D = SmoothOffsetPotential<3>;
302
303
332template <int DIM>
334{
335 static_assert(DIM == 2 || DIM == 3, "the offset potential exists in 2D and 3D only");
336
337public:
338 bool is_euclidean() const override { return true; }
339 using VecD = typename OffsetPotential<DIM>::VecD;
340 using MatD = typename OffsetPotential<DIM>::MatD;
341
350 EuclideanOffsetPotential(const std::shared_ptr<Envelope>& envelope, double delta);
351
361 EuclideanOffsetPotential(const std::shared_ptr<SimplicialComplexBVH>& bvh, double delta);
362
363 double value(const VecD& p) const override;
364 VecD gradient(const VecD& p) const override;
365 MatD hessian(const VecD& p) const override;
366
369 double residual_length(const VecD& p) const override
370 {
371 return std::abs(value(p) - m_c) / m_grad_ref;
372 }
373
377 double relative_residual(const VecD& p) const override { return (value(p) - m_c) / m_c; }
378
380 bool within_support(const VecD& p) const override { return true; }
381
384 bool is_inside_offset(const VecD& p) const override { return value(p) <= m_c; }
385
386 std::string describe_active(const VecD& p) const override;
387
388private:
391 void nearest_feature(const VecD& p, VecD& foot, int& dim, VecD& dir) const;
392
393 using OffsetPotential<DIM>::m_delta;
395 using OffsetPotential<DIM>::m_dhat;
396 using OffsetPotential<DIM>::m_c;
397
400 std::shared_ptr<Envelope> m_envelope;
401 std::shared_ptr<SimplicialComplexBVH> m_bvh;
402};
403
406
407
430template <int DIM>
431class OffsetEnergy : public polysolve::nonlinear::Problem
432{
433public:
434 using typename polysolve::nonlinear::Problem::Scalar;
435 using typename polysolve::nonlinear::Problem::THessian;
436 using typename polysolve::nonlinear::Problem::TVector;
437
438 using VecD = Eigen::Matrix<double, DIM, 1>;
439 using MatD = Eigen::Matrix<double, DIM, DIM>;
440
453 const std::shared_ptr<const OffsetPotential<DIM>>& potential,
454 double weight = 1.,
455 bool gauss_newton = true,
456 bool distance_residual = false,
457 bool one_sided = false);
458
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
462 {
463 log_and_throw_error("Sparse functions do not exist, use dense solver");
464 }
465 void hessian(const TVector& x, MatrixXd& hessian) override;
466
467 void solution_changed(const TVector& new_x) override {}
468
469private:
470 std::shared_ptr<const OffsetPotential<DIM>> m_potential;
471 double m_weight;
472 bool m_gauss_newton;
473 bool m_distance_residual;
474 bool m_one_sided;
476 void residual(const VecD& p, double& r, VecD& dr) const;
477};
478
481
522class StencilEnergy2D : public polysolve::nonlinear::Problem
523{
524public:
525 using typename polysolve::nonlinear::Problem::Scalar;
526 using typename polysolve::nonlinear::Problem::THessian;
527 using typename polysolve::nonlinear::Problem::TVector;
528
530 struct Sample
531 {
532 double a, b;
533 };
535 struct Edge
536 {
537 Eigen::Vector2d q1;
538 std::vector<Sample> samples;
539 };
540
542 const std::shared_ptr<const OffsetPotential2D>& potential,
543 std::vector<Edge> edges,
544 double weight,
545 bool gauss_newton = false);
546
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
550 {
551 log_and_throw_error("Sparse functions do not exist, use dense solver");
552 }
553 void hessian(const TVector& x, MatrixXd& hessian) override;
554 void solution_changed(const TVector& new_x) override {}
555
556private:
560 struct Reading
561 {
562 double r = 0.;
563 Eigen::Vector2d dr = Eigen::Vector2d::Zero();
564 bool r_ok = false;
565 bool dr_ok = false;
566 };
567
573 const std::vector<Reading>& readings_at(const Eigen::Vector2d& x, bool need_dr) const;
574
575 std::shared_ptr<const OffsetPotential2D> m_potential;
576 std::vector<Edge> m_edges;
577 double m_weight;
578 bool m_gauss_newton;
579 double m_c = 1.;
580
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;
585};
586
605class RestAMIPSEnergy2D : public polysolve::nonlinear::Problem
606{
607public:
608 using typename polysolve::nonlinear::Problem::Scalar;
609 using typename polysolve::nonlinear::Problem::THessian;
610 using typename polysolve::nonlinear::Problem::TVector;
611 struct Cell
612 {
613 Eigen::Vector2d q1, q2;
614 Eigen::Matrix2d rest_inv;
615 };
616 RestAMIPSEnergy2D(std::vector<Cell> cells, double weight);
617
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
621 {
622 log_and_throw_error("Sparse functions do not exist, use dense solver");
623 }
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;
627
628private:
630 bool cell_F(const Eigen::Vector2d& x, const Cell& c, Eigen::Matrix2d& F, double& d) const;
631 std::vector<Cell> m_cells;
632 double m_weight;
633};
634
646class CubedAMIPSEnergy3D : public polysolve::nonlinear::Problem
647{
648public:
649 using typename polysolve::nonlinear::Problem::Scalar;
650 using typename polysolve::nonlinear::Problem::THessian;
651 using typename polysolve::nonlinear::Problem::TVector;
652 CubedAMIPSEnergy3D(std::vector<std::array<double, 12>> cells, double weight);
653
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
657 {
658 log_and_throw_error("Sparse functions do not exist, use dense solver");
659 }
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;
663
664private:
667 void at_point(const TVector& x);
668
669 std::vector<std::array<double, 12>> m_cells;
670 double m_weight;
671 bool m_x_set = false;
672 Eigen::Vector3d m_x = Eigen::Vector3d::Zero();
673 std::vector<double> m_a;
674 bool m_value_set = false;
675 double m_value = 0.;
676 bool m_grad_set = false;
677 TVector m_grad;
678};
679
707class VolAMIPSEnergy3D : public polysolve::nonlinear::Problem
708{
709public:
710 using typename polysolve::nonlinear::Problem::Scalar;
711 using typename polysolve::nonlinear::Problem::THessian;
712 using typename polysolve::nonlinear::Problem::TVector;
715 struct Cell
716 {
717 std::array<Eigen::Vector3d, 3> q;
718 Eigen::Matrix3d rest_inv;
719 Eigen::Vector3d s;
720 double c;
721 };
724 static bool cell(const std::array<Eigen::Vector3d, 3>& q, const Eigen::Matrix3d& R, Cell& out);
726 static Eigen::Matrix3d regular_rest();
729 static double value_of(const std::array<Eigen::Vector3d, 4>& p, const Eigen::Matrix3d& R);
730
731 VolAMIPSEnergy3D(std::vector<Cell> cells, double weight);
732
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
736 {
737 log_and_throw_error("Sparse functions do not exist, use dense solver");
738 }
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;
742
743private:
744 double eval(const Eigen::Vector3d& x, int need, Eigen::Vector3d& g, Eigen::Matrix3d& H) const;
745 std::vector<Cell> m_cells;
746 double m_weight;
747};
748
778double input_pad(const Eigen::MatrixXd& V);
779
783int64_t nearest_primitive(const Envelope& env, double pad, const Eigen::Vector3d& p);
784
790double min_mean_distance(
791 const Envelope& env,
792 double pad,
793 const Eigen::Vector3d* p,
794 int n,
795 int64_t& best,
796 int64_t hint = -1);
797
800{
801 int64_t tri = -1;
802 double d1 = 0., d2 = 0., d3 = 0.;
803};
809void ball_candidates(
810 const Envelope& env,
811 double pad,
812 const Eigen::Vector3d& c,
813 double r,
814 const std::array<Eigen::Vector3d, 3>& q,
815 std::vector<BallCandidate>& out);
816
821double min_triangle_distance(
822 const Envelope& env,
823 double pad,
824 const Eigen::Vector3d& a,
825 const Eigen::Vector3d& b,
826 const Eigen::Vector3d& c);
827
833double min_max_corner_distance(const Envelope& env, double pad, const Eigen::Vector3d* p, int n);
834
840double face_mean_sq_cos(
841 const Envelope& env,
842 double pad,
843 const Eigen::Vector3d& a,
844 const Eigen::Vector3d& b,
845 const Eigen::Vector3d& c,
846 const Eigen::Vector3d& n,
847 double delta);
848
887class BandVolumeEnergy3D : public polysolve::nonlinear::Problem
888{
889public:
890 using typename polysolve::nonlinear::Problem::Scalar;
891 using typename polysolve::nonlinear::Problem::THessian;
892 using typename polysolve::nonlinear::Problem::TVector;
894 struct Cell
895 {
896 Eigen::Vector3d q1, q2, q3;
897 };
903 std::shared_ptr<const Envelope> env,
904 double pad,
905 std::vector<Cell> cells,
906 const Eigen::Vector3d& x0,
907 double delta);
908
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
912 {
913 log_and_throw_error("Sparse functions do not exist, use dense solver");
914 }
915 void hessian(const TVector& x, MatrixXd& hessian) override;
916 void solution_changed(const TVector& new_x) override {}
928 void set_exact_integral(std::shared_ptr<const ExactBandIntegral> eb, double delta);
931 struct Face
932 {
933 Eigen::Vector3d a, b;
934 };
956 void set_front_flux(
957 std::shared_ptr<const ExactBandIntegral> eb,
958 double delta,
959 std::vector<Face> faces);
962 static std::string& front_flux_error();
972 static double swept_change(
973 const ExactBandIntegral& eb,
974 double delta,
975 const Eigen::Vector3d& x0,
976 const Eigen::Vector3d& x1,
977 const std::vector<std::array<Eigen::Vector3d, 2>>& faces,
978 ExactBandIntegral::Stats* st = nullptr);
982 {
983 std::atomic<size_t> evals{0}, ring_cells{0};
984 };
1012 void set_swept(
1013 std::shared_ptr<const ExactBandIntegral> eb,
1014 double delta,
1015 std::vector<std::array<Eigen::Vector3d, 2>> faces,
1016 SweptDerivCounts* counts);
1018 std::pair<Eigen::Vector3d, double> certified_ball() const { return {m_ball_c, m_ball_r}; }
1019
1020private:
1022 double eval(const Eigen::Vector3d& x, int need, Eigen::Vector3d& g, Eigen::Matrix3d& H) const;
1024 void exact_minima(const Eigen::Vector3d& x) const;
1027 bool certify_ball(const Eigen::Vector3d& x) const;
1028 std::shared_ptr<const Envelope> m_env;
1029 double m_pad = 0.;
1030 double m_delta = 1.;
1031 mutable std::vector<int64_t> m_hint;
1034 mutable bool m_min_set = false;
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;
1046 mutable std::vector<ExactBandIntegral::Partition> m_eb_parts;
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();
1055 bool m_ff = false;
1056 std::vector<Face> m_ff_faces;
1059 mutable std::vector<ExactBandIntegral::FaceParts> m_ff_fparts;
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)
1065 const;
1068 bool m_sw = false;
1069 std::vector<std::array<Eigen::Vector3d, 2>> m_sw_faces;
1070 mutable std::vector<ExactBandIntegral::FaceParts> m_sw_fparts;
1071 SweptDerivCounts* m_sw_counts = nullptr;
1073 double sw_eval(const Eigen::Vector3d& x, int need, Eigen::Vector3d& g, Eigen::Matrix3d& H)
1074 const;
1076 Eigen::Vector3d m_x0 = Eigen::Vector3d::Zero();
1077
1078 std::vector<Cell> m_cells;
1079};
1080
1089const std::vector<std::array<double, 3>>& subdivision_face_stencil(int order);
1090
1098const std::vector<std::array<double, 3>>& interior_face_stencil(int order);
1099
1108const std::vector<std::array<double, 3>>& fem_face_stencil(int order);
1109
1122const std::vector<double>& fem_face_stencil_weights(int order);
1123
1144class SurfaceOffsetError3D : public polysolve::nonlinear::Problem
1145{
1146public:
1147 using typename polysolve::nonlinear::Problem::Scalar;
1148 using typename polysolve::nonlinear::Problem::THessian;
1149 using typename polysolve::nonlinear::Problem::TVector;
1151 struct Face
1152 {
1153 Eigen::Vector3d q1, q2;
1154 };
1156 std::shared_ptr<const OffsetPotential3D> pot,
1157 std::vector<Face> faces,
1158 int stencil_order,
1159 double weight);
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,
1170 double weight);
1171
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
1175 {
1176 log_and_throw_error("Sparse functions do not exist, use dense solver");
1177 }
1178 void hessian(const TVector& x, MatrixXd& hessian) override;
1179 void solution_changed(const TVector& new_x) override {}
1180
1184 static double face_value(
1185 const OffsetPotential3D& pot,
1186 const std::vector<std::array<double, 3>>& stencil,
1187 const std::vector<double>* point_weights,
1188 double weight,
1189 const Eigen::Vector3d& a,
1190 const Eigen::Vector3d& b,
1191 const Eigen::Vector3d& c);
1192
1193private:
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;
1200 const std::vector<double>* m_point_weights = nullptr;
1201 double m_weight;
1202};
1203
1204} // namespace wmtk::components::topological_offset
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
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
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
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
double c
det(R)^2 / 6
Definition OffsetPotential.hpp:720
Eigen::Vector3d s
rest_inv^T 1
Definition OffsetPotential.hpp:719