Wildmeshing Toolkit
Loading...
Searching...
No Matches
ExactBandIntegral.hpp
1#pragma once
2
3#include <Eigen/Core>
4#include <Eigen/Geometry>
5
6#include <wmtk/envelope/Envelope.hpp>
7
8#include <array>
9#include <cstdint>
10#include <memory>
11#include <mutex>
12#include <utility>
13#include <vector>
14
15namespace wmtk::components::topological_offset {
16
104{
105public:
109 ExactBandIntegral(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F)
110 : ExactBandIntegral(V, F, {}, 0)
111 {}
122 ExactBandIntegral(
123 const Eigen::MatrixXd& V,
124 const Eigen::MatrixXi& F,
125 const std::vector<int8_t>& face_side,
126 int sigma,
127 size_t value_slots = 0,
128 std::shared_ptr<const wmtk::Envelope> envelope = nullptr);
129
132 struct Stats
133 {
134 int64_t cells = 0;
135 int64_t candidates = 0;
136 int64_t pieces = 0;
137 int64_t rule_a_pieces = 0;
138 double vol = 0.;
139 double exact_vol = 0.;
140 double rule_a_vol = 0.;
141 double empty_vol = 0.;
142 int64_t clips = 0;
143 int64_t clips_closed_up = 0;
144 int64_t caps_split = 0;
147 bool check_closed = false;
148 int64_t closed_checked = 0, open_results = 0;
149 int64_t point_faces = 0;
150 int64_t line_faces_radial = 0;
152 int64_t line_faces_series = 0;
153 int64_t closed_edges = 0;
154 int64_t series_short = 0;
155 int64_t series_long = 0;
159 int64_t side_clipped = 0, side_rule_a_split = 0, side_D = 0, side_D_pos = 0;
164 bool timing = false;
165 double t_total = 0., t_candidates = 0., t_clip = 0., t_closed = 0., t_series = 0.;
166 };
167
190 double value(const std::array<Eigen::Vector3d, 4>& t, double delta, Stats* stats = nullptr)
191 const;
192
193 struct Work;
208 {
209 public:
210 Partition();
211 ~Partition();
212 Partition(Partition&&) noexcept;
213 Partition& operator=(Partition&&) noexcept;
214
215 private:
216 friend class ExactBandIntegral;
217 std::unique_ptr<Work> m_w;
218 uint64_t m_owner = 0;
219 double m_key[12] = {};
220 bool m_ok = false;
221 };
223 double value(const std::array<Eigen::Vector3d, 4>& t, double delta, Partition& keep) const;
229 void reserve_values(size_t slots) const;
230
253 double value_grad_hess(
254 const std::array<Eigen::Vector3d, 4>& t,
255 int kv,
256 double delta,
257 Eigen::Vector3d& grad,
258 Eigen::Matrix3d& hess,
259 Stats* stats = nullptr) const;
261 double value_grad_hess(
262 const std::array<Eigen::Vector3d, 4>& t,
263 int kv,
264 double delta,
265 Eigen::Vector3d& grad,
266 Eigen::Matrix3d& hess,
267 Partition& keep) const;
277 void grad_hess(
278 const std::array<Eigen::Vector3d, 4>& t,
279 int kv,
280 double delta,
281 Eigen::Vector3d& grad,
282 Eigen::Matrix3d& hess,
283 Partition& keep) const;
284
286 struct MaxInfo
287 {
288 Eigen::Vector3d at;
289 bool rule_a = false;
290 double U = 0.;
291 int candidates = 0, pieces = 0, rule_a_pieces = 0;
292 };
293
319 double max_distance(const std::array<Eigen::Vector3d, 3>& f, MaxInfo* info = nullptr) const;
320
321 // --------------------------------------------------------------------------------------------
322 // The front form (EXPERIMENTAL_band_volume_rule "front_flux"; Python prototype front_form.py,
323 // d_vertex.py, e_hessian.py, scratchpad front_form/ of 2026-10-13). Per feature k, in its
324 // local region, a field G_k with div G_k = d - delta, tangent to the region's planes and 0 on
325 // the input (d = 0):
326 // face G = (d^2/2 - delta d) W d = W.x - c, W = +-n on each side of its plane
327 // edge G = (d/3 - delta/2) (x - x_e) x_e the projection of x on the edge's line
328 // vertex G = (d/4 - delta/3) (x - v).
329 // On a band B made of cells, the divergence theorem cell by cell gives
330 // E(B) = int_B (d - delta) dV = sum over the boundary faces f of B of int_f G.n dA
331 // + sum over the cells t of D_t,
332 // D_t = int_t (d - delta) dV - oint_dt G.n dA: the jumps of G.n across the BISECTORS inside t
333 // (the sets where two features are nearest), 0 for a cell no bisector crosses. Every piece of
334 // the partition (as value()'s) is labelled with its nearest feature exactly: a member whose
335 // squared distance is not below another's anywhere on the piece is dropped (the exact range
336 // of the difference, a quadratic, over the piece); members that still cross must have a
337 // planar bisector (face-face, vertex-vertex, parallel or intersecting edge-edge), and the
338 // piece is split by it. A crossing pair with a curved bisector (face-edge, face-vertex,
339 // edge-vertex, skew edges) THROWS std::runtime_error naming the pair and the position:
340 // there is no approximation in this form (rule (a)'s bound is value()'s only).
341 //
342 // The offset side (class doc), as value(): a labelled part counts only on the offset side of
343 // its label's plane. On a labelled part the label is the nearest feature, whose plane meets it
344 // only where d = 0 (the pseudonormal theorem), so the side drops whole parts: a face's far
345 // side, and the edge and vertex parts beyond the input (MEASURED, the side cases' cells of
346 // the tests: 47 edge parts clipped by their side plane, every one dropped whole, none cut).
347 // Where G = 0 (on the input) the
348 // dropped parts carry no flux, so the identity holds with the side as without it. The
349 // Python prototype used the unsigned d (both sides of every face counted); the two agree on
350 // every part on the offset side, and constructed without a side this class is the prototype.
351
352 struct FaceWork;
362 {
363 public:
364 FaceParts();
365 ~FaceParts();
366 FaceParts(FaceParts&&) noexcept;
367 FaceParts& operator=(FaceParts&&) noexcept;
368
369 private:
370 friend class ExactBandIntegral;
371 std::unique_ptr<FaceWork> m_w;
372 uint64_t m_owner = 0;
373 double m_key[9] = {};
374 };
395 double front_face(
396 const std::array<Eigen::Vector3d, 3>& f,
397 double delta,
398 FaceParts* keep = nullptr) const;
399 void front_face_derivs(
400 const std::array<Eigen::Vector3d, 3>& f,
401 double delta,
402 int kv,
403 Eigen::Vector3d& grad,
404 Eigen::Matrix3d& hess,
405 FaceParts* keep = nullptr) const;
415 {
416 public:
420 QuietCurvedBisector& operator=(const QuietCurvedBisector&) = delete;
421
422 private:
423 bool m_prev = false;
424 };
437 double bisector_jump(
438 const std::array<Eigen::Vector3d, 4>& t,
439 double delta,
440 Partition* keep = nullptr) const;
449 void prepare_front_flux(double delta);
451 double front_flux_reach() const { return m_ff_reach; }
452 size_t front_flux_polytopes() const { return m_ff_boxes.size(); }
461 bool front_flux_flag(const std::array<Eigen::Vector3d, 4>& t) const
462 {
463 return front_flux_flag(t.data(), 4);
464 }
468 bool front_flux_flag(const Eigen::Vector3d* t, int n) const;
470 double distance(const Eigen::Vector3d& x) const { return upper_bound(&x, 1); }
473 double distance_bound(const std::array<Eigen::Vector3d, 4>& t) const
474 {
475 return upper_bound(t.data(), 4);
476 }
478 double distance_bound(const Eigen::Vector3d* t, const int n) const { return upper_bound(t, n); }
479
480 size_t num_faces() const { return m_A.size(); }
481
482private:
486 struct Feature
487 {
488 int kind = 0;
489 Eigen::Vector3d p, dir;
490 int h_begin = 0, h_end = 0;
491 Eigen::Vector3d lo, hi;
492 };
493 std::vector<Feature> m_feat;
502 std::vector<std::pair<Eigen::Vector3d, Eigen::Vector3d>> m_hs;
503 int m_nF = 0, m_nE = 0;
504 std::vector<Eigen::Vector3d> m_A, m_B, m_C;
505 std::vector<std::array<int, 6>> m_face_feats;
509 int m_sigma = 0;
510 std::vector<char> m_side_has;
511 std::vector<Eigen::Vector3d> m_side_n, m_side_q;
512
516 std::shared_ptr<const wmtk::Envelope> m_env;
519 double m_pad = 0.;
522 struct Node
523 {
524 Eigen::Vector3d lo, hi;
525 int left = -1, right = -1, begin = 0, end = 0;
526 };
527
530 struct Local;
531 struct TriWork;
534 void localize(const Eigen::Vector3d* t, int n, Local& w, Stats* stats) const;
537 bool partition(const std::array<Eigen::Vector3d, 4>& t, Work& w, Stats* stats) const;
541 const Work* cell_partition(
542 const std::array<Eigen::Vector3d, 4>& t,
543 Stats* stats,
544 Work* own,
545 Partition* keep) const;
548 uint64_t m_id = 0;
550 double evaluate(
551 const std::array<Eigen::Vector3d, 4>& t,
552 double delta,
553 Stats* stats,
554 Partition* keep) const;
556 double value_tabled(const std::array<Eigen::Vector3d, 4>& t, double delta, Partition* keep)
557 const;
561 const std::array<Eigen::Vector3d, 4>& t,
562 int kv,
563 double delta,
564 Eigen::Vector3d& grad,
565 Eigen::Matrix3d& hess,
566 Stats* stats,
567 Partition* keep,
568 bool want_value) const;
572 {
573 double in[13];
574 double out = 0.;
575 bool full = false;
576 };
577 static constexpr size_t kValueStripes = 1024;
578 mutable std::vector<ValueSlot> m_values;
579 mutable std::unique_ptr<std::mutex[]> m_value_locks;
581 void tri_partition(const std::array<Eigen::Vector3d, 3>& f, TriWork& w) const;
583 double upper_bound(const Eigen::Vector3d* t, int n) const;
588 const std::array<Eigen::Vector3d, 4>& t,
589 double delta,
590 const Work& w,
591 double vol_sum,
592 double empty_vol) const;
593 void check_face_pieces(
594 const std::array<Eigen::Vector3d, 3>& f,
595 const TriWork& w,
596 const char* who) const;
599 void label_face(const std::array<Eigen::Vector3d, 3>& f, FaceWork& fw) const;
601 const FaceWork& face_parts(const std::array<Eigen::Vector3d, 3>& f, FaceParts* keep) const;
604 struct FFBox
605 {
606 Eigen::Vector3d lo, hi;
607 std::vector<std::pair<Eigen::Vector3d, double>> planes;
608 };
609 std::vector<FFBox> m_ff_boxes;
610 std::vector<Node> m_ff_nodes;
611 std::vector<int> m_ff_order;
612 double m_ff_reach = 0.;
613 int build_ff_node(int begin, int end);
615 void candidates(
616 const Eigen::Vector3d& lo,
617 const Eigen::Vector3d& hi,
618 double r,
619 std::vector<int>& out) const;
620};
621
622} // namespace wmtk::components::topological_offset
One face's labelled parts, kept by the caller between front_face() calls on that face,...
Definition ExactBandIntegral.hpp:362
uint64_t m_owner
the integral's m_id; 0: none
Definition ExactBandIntegral.hpp:372
One cell's partition, kept by the caller between value() and value_grad_hess() of that cell: each par...
Definition ExactBandIntegral.hpp:208
uint64_t m_owner
the integral's m_id; 0: none
Definition ExactBandIntegral.hpp:218
bool m_ok
false: t is flat
Definition ExactBandIntegral.hpp:220
While one is alive on a thread, a curved bisector crossing a piece of a face (front_face(),...
Definition ExactBandIntegral.hpp:415
The band-volume integral of one cell, in closed form:
Definition ExactBandIntegral.hpp:104
bool front_flux_flag(const std::array< Eigen::Vector3d, 4 > &t) const
Whether the cell t can meet a bisector at points with d <= front_flux_reach(): t's box meets a kept p...
Definition ExactBandIntegral.hpp:461
double distance_bound(const std::array< Eigen::Vector3d, 4 > &t) const
Definition ExactBandIntegral.hpp:473
double value_tabled(const std::array< Eigen::Vector3d, 4 > &t, double delta, Partition *keep) const
value(t, delta, stats, keep) through the value table (value()).
Definition ExactBandIntegral.cpp:3732
std::shared_ptr< const wmtk::Envelope > m_env
Definition ExactBandIntegral.hpp:516
void localize(const Eigen::Vector3d *t, int n, Local &w, Stats *stats) const
Definition ExactBandIntegral.cpp:3408
void check_cell_pieces(const std::array< Eigen::Vector3d, 4 > &t, double delta, const Work &w, double vol_sum, double empty_vol) const
Definition ExactBandIntegral.cpp:4631
double distance(const Eigen::Vector3d &x) const
d(x), the distance to the input: min over the triangles of the point-triangle distance.
Definition ExactBandIntegral.hpp:470
void reserve_values(size_t slots) const
Definition ExactBandIntegral.cpp:3724
double front_face(const std::array< Eigen::Vector3d, 3 > &f, double delta, FaceParts *keep=nullptr) const
front_face(): int over the triangle f of G.n dA, n = (f1 - f0) x (f2 - f0) / |.| (f ordered with the ...
Definition ExactBandIntegral.cpp:4872
double bisector_jump(const std::array< Eigen::Vector3d, 4 > &t, double delta, Partition *keep=nullptr) const
D_t = int_t (d - delta) dV - oint_dt G.n dA of the cell t (either orientation): 0 exactly when one fe...
Definition ExactBandIntegral.cpp:4989
std::vector< Eigen::Vector3d > m_C
triangle corners, for d_P
Definition ExactBandIntegral.hpp:504
double front_flux_reach() const
prepare_front_flux()'s R (0 before it), and the number of polytopes it kept.
Definition ExactBandIntegral.hpp:451
double value_grad_hess_impl(const std::array< Eigen::Vector3d, 4 > &t, int kv, double delta, Eigen::Vector3d &grad, Eigen::Matrix3d &hess, Stats *stats, Partition *keep, bool want_value) const
Definition ExactBandIntegral.cpp:4179
double evaluate(const std::array< Eigen::Vector3d, 4 > &t, double delta, Stats *stats, Partition *keep) const
value() without the value table.
Definition ExactBandIntegral.cpp:3765
double m_pad
Definition ExactBandIntegral.hpp:519
void prepare_front_flux(double delta)
Builds, from the input alone, where bisectors can be: for every pair of features g,...
Definition ExactBandIntegral.cpp:5110
void candidates(const Eigen::Vector3d &lo, const Eigen::Vector3d &hi, double r, std::vector< int > &out) const
Feature indices whose box is within r of [lo, hi], ascending.
Definition ExactBandIntegral.cpp:3346
std::vector< std::pair< Eigen::Vector3d, Eigen::Vector3d > > m_hs
Definition ExactBandIntegral.hpp:502
bool partition(const std::array< Eigen::Vector3d, 4 > &t, Work &w, Stats *stats) const
Definition ExactBandIntegral.cpp:3459
double distance_bound(const Eigen::Vector3d *t, const int n) const
The same bound for the n points t; a subset's bound is never larger.
Definition ExactBandIntegral.hpp:478
void tri_partition(const std::array< Eigen::Vector3d, 3 > &f, TriWork &w) const
_tri_partition: the same for the face f, its pieces planar rings.
Definition ExactBandIntegral.cpp:3554
double max_distance(const std::array< Eigen::Vector3d, 3 > &f, MaxInfo *info=nullptr) const
max over the triangle f of d (exact_mesh.max_on_triangle), the settle loop's max test....
Definition ExactBandIntegral.cpp:3621
void label_face(const std::array< Eigen::Vector3d, 3 > &f, FaceWork &fw) const
Definition ExactBandIntegral.cpp:4784
double upper_bound(const Eigen::Vector3d *t, int n) const
U: min over all triangles of max over the n points t of d_P.
Definition ExactBandIntegral.cpp:3319
void grad_hess(const std::array< Eigen::Vector3d, 4 > &t, int kv, double delta, Eigen::Vector3d &grad, Eigen::Matrix3d &hess, Partition &keep) const
value_grad_hess()'s gradient and Hessian alone, t's partition read from or written to keep: J's own i...
Definition ExactBandIntegral.cpp:4168
double value(const std::array< Eigen::Vector3d, 4 > &t, double delta, Stats *stats=nullptr) const
J(t) = int_t (d - delta) dV for the cell with corners t (either orientation), restricted to the offse...
Definition ExactBandIntegral.cpp:3706
std::vector< std::array< int, 6 > > m_face_feats
Definition ExactBandIntegral.hpp:505
std::vector< Feature > m_feat
Definition ExactBandIntegral.hpp:493
double value_grad_hess(const std::array< Eigen::Vector3d, 4 > &t, int kv, double delta, Eigen::Vector3d &grad, Eigen::Matrix3d &hess, Stats *stats=nullptr) const
J and its exact gradient and Hessian with respect to corner kv of t, the other three fixed (exact_mes...
Definition ExactBandIntegral.cpp:4146
int m_sigma
Definition ExactBandIntegral.hpp:509
const FaceWork & face_parts(const std::array< Eigen::Vector3d, 3 > &f, FaceParts *keep) const
f's labelled parts, from keep when it holds f's, else made (into keep, or a scratch).
Definition ExactBandIntegral.cpp:4845
const Work * cell_partition(const std::array< Eigen::Vector3d, 4 > &t, Stats *stats, Work *own, Partition *keep) const
Definition ExactBandIntegral.cpp:3526
ExactBandIntegral(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F)
Definition ExactBandIntegral.hpp:109
uint64_t m_id
Definition ExactBandIntegral.hpp:548
Eigen::Vector3d hi
bounding box
Definition ExactBandIntegral.hpp:491
What max_distance() found besides the max.
Definition ExactBandIntegral.hpp:287
Eigen::Vector3d at
a point of f where the returned max is attained
Definition ExactBandIntegral.hpp:288
double U
min over P of max over f's corners of d_P (the former settle bound)
Definition ExactBandIntegral.hpp:290
bool rule_a
the max came from a rule-(a) piece: an upper bound there
Definition ExactBandIntegral.hpp:289
int64_t caps_split
Definition ExactBandIntegral.hpp:144
int64_t point_faces
faces integrated against a point distance
Definition ExactBandIntegral.hpp:149
double empty_vol
volume of pieces with no member (must be rounding)
Definition ExactBandIntegral.hpp:141
double vol
cell volume
Definition ExactBandIntegral.hpp:138
bool check_closed
Definition ExactBandIntegral.hpp:147
int64_t candidates
candidate features
Definition ExactBandIntegral.hpp:135
int64_t side_clipped
Definition ExactBandIntegral.hpp:159
double rule_a_vol
volume of rule-(a) pieces (upper bound)
Definition ExactBandIntegral.hpp:140
int64_t line_faces_series
... near-parallel series
Definition ExactBandIntegral.hpp:152
int64_t pieces
convex pieces of the partition
Definition ExactBandIntegral.hpp:136
int64_t clips_closed_up
cutting clips whose kept faces closed up without a cap
Definition ExactBandIntegral.hpp:143
int64_t series_long
Definition ExactBandIntegral.hpp:155
int64_t series_short
near-parallel edges, Taylor series along the edge
Definition ExactBandIntegral.hpp:154
bool timing
Definition ExactBandIntegral.hpp:164
int64_t clips
half-space clips of a polytope
Definition ExactBandIntegral.hpp:142
int64_t line_faces_radial
... against a line distance, radial closed form
Definition ExactBandIntegral.hpp:150
int64_t cells
value() calls with a non-flat cell
Definition ExactBandIntegral.hpp:134
double exact_vol
volume of pieces integrated exactly
Definition ExactBandIntegral.hpp:139
int64_t closed_edges
polygon edges integrated by a closed form
Definition ExactBandIntegral.hpp:153
int64_t line_faces_parallel
... line exactly parallel to the face
Definition ExactBandIntegral.hpp:151