10#ifndef PECLET_VORO_BINDINGS_TESS_HPP
11#define PECLET_VORO_BINDINGS_TESS_HPP
31template <
bool W,
class S>
40 d[
"pass1"] = st.
pass1;
41 d[
"pass2"] = st.
pass2;
45 d[
"extra"] = st.
extra;
52class Tess :
public peclet::core::python::Releasable {
57 std::array<bool, 3> periodic) {
61 std::array<real_t, 3>
extent()
const {
return L_; }
64 throw std::invalid_argument(
"voro: set_tolerance(frac) needs frac > 0.");
68 nb::ndarray<real_t, nb::c_contig> node_reals,
int root,
real_t grad_h) {
75 throw std::invalid_argument(
"voro: set_wall_mode(skin_frac=...) needs skin_frac >= 0.");
76 wallSkinFrac_ = skin_frac;
80 throw std::runtime_error(
"set_weights(): expected an (N,) array");
97 std::visit([&](
auto& mt) { mt.profile = on; }, mt_);
100 auto r = std::visit([](
auto& mt) {
return mt.report(); }, mt_);
102 d[
"buried"] = r.buried;
103 d[
"reach_exceeded"] = r.reachExceeded;
104 d[
"empty"] = r.empty;
105 d[
"overflow"] = r.overflow;
106 d[
"incomplete"] = r.incomplete;
107 d[
"over_buffer_rebuilds"] = r.overBufferRebuilds;
112 void build(nb::ndarray<real_t, nb::c_contig> a,
bool strict) {
113 std::vector<real_t> p =
flatten3(a);
114 N_ =
static_cast<int>(p.size() / 3);
116 throw std::runtime_error(
"voro: build() needs at least one point");
117 const double boxVol =
static_cast<double>(L_[0]) * L_[1] * L_[2];
118 const real_t spacing =
static_cast<real_t>(std::cbrt(boxVol / N_));
119 if (weighted_ &&
static_cast<int>(wHost_.size()) != N_)
120 throw std::runtime_error(
"build(): weights (N,) must match the particle count");
121 pos_ = peclet::core::toDevice<real_t>(p,
"pos");
123 weight_ = peclet::core::toDevice<real_t>(wHost_,
"w");
126 if (!weighted_ && !scene_.
set)
127 mt_.template emplace<MT<false, NoSdfT>>();
128 else if (weighted_ && !scene_.
set)
129 mt_.template emplace<MT<true, NoSdfT>>();
131 mt_.template emplace<MT<false, SceneT>>();
133 mt_.template emplace<MT<true, SceneT>>();
136 using T = std::decay_t<
decltype(mt)>;
137 mt.localCert = localCert_;
138 mt.useGate = useGate_;
139 mt.profile = profile_;
140 if constexpr (T::kHasSdf) {
141 mt.sdf = scene_.
scene;
142 mt.wallExact = wallExact_;
143 mt.wallSkin = wallSkinFrac_ * spacing;
145 if constexpr (std::is_same_v<typename T::PlanePolicy, peclet::voro::Power>)
146 mt.setWeights(weight_);
147 mt.alloc(N_, L_.data(), tolFrac_ * spacing,
real_t(defaults::kSkin) * spacing,
148 defaults::kSearchWindow, N_);
152 auto r = std::visit([](
auto& mt) {
return mt.report(); }, mt_);
153 if (r.buried > 0 || r.reachExceeded > 0 || r.overflow > 0) {
154 const std::string msg =
155 "peclet.voro: the tessellation is not a guaranteed-exact partition: " +
156 std::to_string(r.buried) +
157 " buried power cell(s) (seed outside its own cell, emptied), " +
158 std::to_string(r.reachExceeded) +
" cell(s) with a search reach beyond half the box " +
159 "(min-image invalid), " + std::to_string(r.overflow) +
160 " overflowed cell(s). See diagnostics.build_report().";
162 throw std::runtime_error(msg);
163 nb::module_::import_(
"warnings").attr(
"warn")(msg);
169 nb::dict
step(nb::ndarray<real_t, nb::c_contig> a) {
171 throw std::runtime_error(
172 "voro: Tessellation.step() before build() — call build(positions) first.");
173 std::vector<real_t> p =
flatten3(a);
174 if (
static_cast<int>(p.size() / 3) != N_)
175 throw std::runtime_error(
176 "voro: step(positions) got " + std::to_string(p.size() / 3) +
" points but build() had " +
178 " — the count is fixed by build(); call build() again to change it.");
179 pos_ = peclet::core::toDevice<real_t>(p,
"pos");
180 if (weighted_ && wDirty_) {
181 if (
static_cast<int>(wHost_.size()) != N_)
182 throw std::runtime_error(
"step(): weights (N,) must match the particle count");
184 weight_, Kokkos::View<const real_t*, Kokkos::HostSpace>(wHost_.data(), wHost_.size()));
187 auto st = std::visit([&](
auto& mt) {
return mt.step(pos_); }, mt_);
192 const std::size_t N =
static_cast<std::size_t
>(N_);
193 DView vol = std::visit([](
auto& mt) {
return mt.vol; }, mt_);
194 auto v = Kokkos::subview(vol, Kokkos::make_pair(std::size_t(0), N));
195 return peclet::core::python::vector_to_ndarray(peclet::core::toVector(v), {N}, {1});
203 Kokkos::View<int*, peclet::core::MemSpace> cnt(
"nbr", N);
204 auto st = std::visit([](
auto& mt) {
return mt.store; }, mt_);
206 const real_t Lx = L_[0], Ly = L_[1], Lz = L_[2];
207 Kokkos::parallel_for(
208 "peclet.voro.nbrcount", Kokkos::RangePolicy<peclet::core::ExecSpace>(0, N),
209 KOKKOS_LAMBDA(
int i) {
211 st.load(i, c, Lx, Ly, Lz);
212 C(i) = c.countFaces();
214 return peclet::core::python::vector_to_ndarray(peclet::core::toVector(cnt),
215 {
static_cast<std::size_t
>(N)}, {1});
223 nb::ndarray<real_t, nb::c_contig> tension,
224 std::optional<nb::ndarray<real_t, nb::c_contig>> sigma_wall,
225 std::optional<nb::ndarray<real_t, nb::c_contig>> dEdV,
real_t lloyd,
228 throw std::runtime_error(
229 "voro: Tessellation.energy_forces() before build() — call build(positions) first.");
231 if ((
int)types.shape(0) != N)
232 throw std::runtime_error(
"energy_forces(): types must be (N,)");
234 for (
int i = 0; i < N; ++i)
235 nT = std::max(nT, types.data()[i] + 1);
236 if ((
int)tension.size() != nT * nT)
237 throw std::runtime_error(
238 "energy_forces(): tension must be (nTypes, nTypes) with nTypes = max(types)+1");
239 Kokkos::View<int*, Mem> dtype(
"en.type", N);
240 Kokkos::deep_copy(dtype, Kokkos::View<const int*, Kokkos::HostSpace>(types.data(), N));
241 DView dten(
"en.tension", (
size_t)nT * nT);
243 dten, Kokkos::View<const real_t*, Kokkos::HostSpace>(tension.data(), (
size_t)nT * nT));
246 if ((
int)sigma_wall->size() != nT)
247 throw std::runtime_error(
"energy_forces(): sigma_wall must be (nTypes,)");
248 dsw =
DView(
"en.sw", nT);
249 Kokkos::deep_copy(dsw,
250 Kokkos::View<const real_t*, Kokkos::HostSpace>(sigma_wall->data(), nT));
253 if ((
int)dEdV->size() != N)
254 throw std::runtime_error(
"energy_forces(): dEdV must be (N,)");
255 dde =
DView(
"en.dEdV", N);
256 Kokkos::deep_copy(dde, Kokkos::View<const real_t*, Kokkos::HostSpace>(dEdV->data(), N));
258 DView force(
"en.force", 3 * (
size_t)N), forceW(
"en.forceW", weighted_ ? N : 0);
259 Kokkos::deep_copy(force,
real_t(0));
261 Kokkos::deep_copy(forceW,
real_t(0));
262 real_t eIf = 0, eWall = 0, eLloyd = 0, eTen = 0;
263 const real_t Larr[3] = {L_[0], L_[1], L_[2]};
266 using T = std::decay_t<
decltype(mt)>;
267 using Policy =
typename T::PlanePolicy;
269 peclet::voro::reevalPublish<real_t, defaults::kMaxPlanes, defaults::kMaxTriangles>(
270 mt.store, pos_, mt.vol, N, Larr, mt.wall, mt.xRef,
true,
273 eLloyd = peclet::voro::energy::lloydEnergyForce<real_t>(view, pos_, lloyd, force);
274 if (facet_tension != 0)
275 eTen = peclet::voro::energy::facetTensionEnergyForce<real_t, Policy>(
276 view, facet_tension, pos_, weight_, L_[0], force, forceW, mt.sdf);
277 eIf = peclet::voro::energy::interfaceEnergyForce<real_t, Policy>(
278 view, dtype, dten, nT, pos_, weight_, L_[0], force, forceW, mt.sdf);
279 if (dsw.extent(0) > 0)
280 eWall = peclet::voro::energy::wallEnergyForce<real_t, Policy>(
281 view, dtype, dsw, mt.sdf, pos_, weight_, L_[0], force, forceW);
282 if (dde.extent(0) > 0)
283 peclet::voro::energy::volumeGradientForce<real_t, Policy>(view, dde, pos_, weight_,
284 L_[0], force, forceW, mt.sdf);
288 d[
"interface_energy"] = eIf;
289 d[
"wall_energy"] = eWall;
290 d[
"lloyd_energy"] = eLloyd;
291 d[
"tension_energy"] = eTen;
292 d[
"force"] = peclet::core::python::vector_to_ndarray(
293 peclet::core::toVector(force), {
static_cast<std::size_t
>(N), std::size_t(3)}, {3, 1});
295 d[
"force_w"] = peclet::core::python::vector_to_ndarray(peclet::core::toVector(forceW),
296 {
static_cast<std::size_t
>(N)}, {1});
306 const std::size_t N =
static_cast<std::size_t
>(N_);
307 std::vector<int> v = std::visit(
309 using T = std::decay_t<
decltype(mt)>;
310 if constexpr (T::kHasSdf)
311 return peclet::core::toVector(mt.wall.cnt);
313 return std::vector<int>(N, 0);
316 return peclet::core::python::vector_to_ndarray(std::move(v), {N}, {1});
323 mt_.template emplace<MT<false, NoSdfT>>();
331 std::array<real_t, 3> L_{1, 1, 1};
332 real_t tolFrac_ = defaults::kCertificateTolerance;
333 bool localCert_ =
true, useGate_ =
true, profile_ =
false;
334 bool wallExact_ =
true;
336 bool weighted_ =
false, wDirty_ =
false;
337 std::vector<real_t> wHost_;
Definition voro_bindings_tess.hpp:52
std::array< real_t, 3 > extent() const
Definition voro_bindings_tess.hpp:61
nb::dict build_report()
Definition voro_bindings_tess.hpp:99
nb::ndarray< nb::numpy, real_t > get_volumes()
Definition voro_bindings_tess.hpp:191
void release() noexcept override
Definition voro_bindings_tess.hpp:322
void set_geometry(nb::ndarray< int, nb::c_contig > node_ints, nb::ndarray< real_t, nb::c_contig > node_reals, int root, real_t grad_h)
Definition voro_bindings_tess.hpp:67
nb::ndarray< nb::numpy, int > get_neighbor_counts()
Definition voro_bindings_tess.hpp:199
void set_tolerance(real_t frac)
Definition voro_bindings_tess.hpp:62
void set_gate(bool on)
Definition voro_bindings_tess.hpp:94
nb::dict energy_forces(nb::ndarray< int, nb::c_contig > types, nb::ndarray< real_t, nb::c_contig > tension, std::optional< nb::ndarray< real_t, nb::c_contig > > sigma_wall, std::optional< nb::ndarray< real_t, nb::c_contig > > dEdV, real_t lloyd, real_t facet_tension)
Definition voro_bindings_tess.hpp:222
nb::dict step(nb::ndarray< real_t, nb::c_contig > a)
Definition voro_bindings_tess.hpp:169
void set_local_certificate(bool on)
Definition voro_bindings_tess.hpp:93
void set_weights(nb::ndarray< real_t, nb::c_contig > w)
Definition voro_bindings_tess.hpp:78
void clear_weights()
Definition voro_bindings_tess.hpp:85
void clear_geometry()
Definition voro_bindings_tess.hpp:71
nb::ndarray< nb::numpy, int > get_wall_counts()
Definition voro_bindings_tess.hpp:305
void set_wall_mode(const std::string &mode, real_t skin_frac)
Definition voro_bindings_tess.hpp:72
void set_domain(std::array< real_t, 3 > extent, std::array< real_t, 3 > origin, std::array< bool, 3 > periodic)
Definition voro_bindings_tess.hpp:56
peclet::voro::fv::FaceMesh< real_t > face_mesh()
Definition voro_tessellation.cpp:8
void set_profile(bool on)
Definition voro_bindings_tess.hpp:95
void build(nb::ndarray< real_t, nb::c_contig > a, bool strict)
Definition voro_bindings_tess.hpp:112
int num_particles() const
Definition voro_bindings_tess.hpp:319
Rung A3: interfacial (surface-tension) energy between cells of different species on the published vie...
Track B, rung B1: the CENTROIDAL (Lloyd / CVT) energy on the published view.
Track C, rung C1 (Voronoi methods plan): the FACE mesh of a published tessellation — one record per g...
constexpr double kWallSkin
Definition voro_bindings_common.hpp:70
Definition voro_bindings_common.hpp:45
void checkDomain(const char *cls, std::array< real_t, 3 > extent, std::array< real_t, 3 > origin, std::array< bool, 3 > periodic)
Definition voro_bindings_common.hpp:195
nb::dict repairStatsDict(const peclet::voro::RepairStats &st)
Definition voro_bindings_tess.hpp:37
std::vector< real_t > flatten1(nb::ndarray< real_t, nb::c_contig > a)
Definition voro_bindings_common.hpp:114
std::vector< real_t > flatten3(nb::ndarray< real_t, nb::c_contig > a)
Definition voro_bindings_common.hpp:106
bool parseWallMode(const std::string &mode)
Definition voro_bindings_common.hpp:216
std::variant< MT< false, NoSdfT >, MT< true, NoSdfT >, MT< false, SceneT >, MT< true, SceneT > > MtVariant
Definition voro_bindings_tess.hpp:35
SceneHolder makeSceneHolder(nb::ndarray< int, nb::c_contig > node_ints, nb::ndarray< real_t, nb::c_contig > node_reals, int root, real_t grad_h)
Definition voro_bindings_common.hpp:152
Definition convex_cell.hpp:140
Per-step repair telemetry.
Definition repair.hpp:61
int wallFlagged
cells flagged by the SDF boundary watch (0 without an SDF)
Definition repair.hpp:70
int extra
cells gathered across the verify extra-passes
Definition repair.hpp:67
int pass1
cells gathered in Pass 1 (flagged ∪ partners ∪ skin-movers, after dilation)
Definition repair.hpp:64
int surgical
Pass-1 cells repaired surgically (Phase 4, no grid gather)
Definition repair.hpp:68
int pass2
cells gathered in Pass 2 (new face-neighbours of the movers)
Definition repair.hpp:66
bool fellBack
true if the cold-build fallback was triggered (repair did not close)
Definition repair.hpp:73
Route route
Definition repair.hpp:72
int pass1Raw
flagged count BEFORE dilation (the gate signal: pass1Raw/nProc = churn)
Definition repair.hpp:65
@ kRebuildGate
Definition repair.hpp:63
int verifyPasses
number of verify iterations run
Definition repair.hpp:69
SceneT scene
Definition voro_bindings_common.hpp:141
void clear()
Definition voro_bindings_common.hpp:143
bool set
Definition voro_bindings_common.hpp:142
Definition voro_bindings_tess.hpp:345
Tess * t
Definition voro_bindings_tess.hpp:346
Track B, rung B1: uniform facet tension E = σ Σ_faces A_f (every interior face once) — the "roundness...
Rung A3: per-cell volume energies e_i(V_i) on the published view — target volume, log-barrier and the...
Internal helpers shared by the translation units of the peclet.voro nanobind module.
Kokkos::View< real_t *, peclet::core::MemSpace > DView
Definition voro_bindings_common.hpp:39
double real_t
Definition voro_bindings_common.hpp:38
The ONE seed-foot SDF wall chain (Voronoi methods plan, rung A3) + the wall interfacial energy on the...