peclet.voro 1.0.4
Device-native moving-particle Voronoi dynamics
Loading...
Searching...
No Matches
simulation.hpp
Go to the documentation of this file.
1
15#ifndef PECLET_VORO_PHYSICS_SIMULATION_HPP
16#define PECLET_VORO_PHYSICS_SIMULATION_HPP
17
18#include <array>
19#include <Kokkos_Core.hpp>
20
21#include "peclet/core/common/view.hpp"
24#include "peclet/voro/reeval_tessellation.hpp" // reevalPublish (E1 repair -> force geometry)
25#include "peclet/voro/repair.hpp" // MovingTessellation (incremental update)
28
29namespace peclet::voro {
30namespace physics {
31
35template <class Real, class Sdf = peclet::voro::NoSdf>
37 public:
38 using DView = Kokkos::View<Real*, peclet::core::MemSpace>;
39
40 void setSdf(const Sdf& s) { sdf_ = s; }
41
44 void init(const DView& posFlat, const DView& vel, const DView& invMass,
45 const std::array<Real, 3>& L, Real pressEq) {
46 N_ = static_cast<int>(invMass.extent(0));
47 pos_ = posFlat;
48 vel_ = vel;
49 invMass_ = invMass;
50 L_ = L;
51 pressEq_ = pressEq;
52 w_ = DView("w", N_);
53 force_ = DView("force", 3 * N_);
54 buildAndForce();
55 }
56
58 void setViscous(const DView& visc, const DView& bulkVisc) {
59 visc_ = visc;
60 bulkVisc_ = bulkVisc;
61 viscous_ = true;
62 // Persistent viscous scratch (9*N each), allocated once here rather than every buildAndForce
63 // (E4).
64 viscGrad_ = DView(Kokkos::view_alloc("visc.grad", Kokkos::WithoutInitializing),
65 static_cast<std::size_t>(9) * N_);
66 viscStress_ = DView(Kokkos::view_alloc("visc.stress", Kokkos::WithoutInitializing),
67 static_cast<std::size_t>(9) * N_);
68 buildAndForce();
69 }
70
71 void step(int nSteps, Real dt) {
72 using Exec = peclet::core::ExecSpace;
73 const Real halfDt = Real(0.5) * dt;
74 const Real Lx = L_[0], Ly = L_[1], Lz = L_[2];
75 auto pos = pos_;
76 auto vel = vel_;
77 auto im = invMass_;
78 auto force = force_;
79 for (int s = 0; s < nSteps; ++s) {
80 Kokkos::parallel_for(
81 "ee.kick1", Kokkos::RangePolicy<Exec>(0, N_), KOKKOS_LAMBDA(const int i) {
82 for (int k = 0; k < 3; ++k)
83 vel(3 * i + k) += force(3 * i + k) * im(i) * halfDt;
84 });
85 Kokkos::parallel_for(
86 "ee.drift", Kokkos::RangePolicy<Exec>(0, N_), KOKKOS_LAMBDA(const int i) {
87 Real x = pos(3 * i + 0) + vel(3 * i + 0) * dt;
88 Real y = pos(3 * i + 1) + vel(3 * i + 1) * dt;
89 Real z = pos(3 * i + 2) + vel(3 * i + 2) * dt;
90 pos(3 * i + 0) = x - Lx * Kokkos::floor(x / Lx);
91 pos(3 * i + 1) = y - Ly * Kokkos::floor(y / Ly);
92 pos(3 * i + 2) = z - Lz * Kokkos::floor(z / Lz);
93 });
94 buildAndForce();
95 force = force_;
96 Kokkos::parallel_for(
97 "ee.kick2", Kokkos::RangePolicy<Exec>(0, N_), KOKKOS_LAMBDA(const int i) {
98 for (int k = 0; k < 3; ++k)
99 vel(3 * i + k) += force(3 * i + k) * im(i) * halfDt;
100 });
101 time_ += dt;
102 }
103 Kokkos::fence();
104 }
105
106 Real kineticEnergy(const DView& mass) const {
107 using Exec = peclet::core::ExecSpace;
108 auto vel = vel_;
109 Real e = 0;
110 Kokkos::parallel_reduce(
111 "ee.ke", Kokkos::RangePolicy<Exec>(0, N_),
112 KOKKOS_LAMBDA(const int i, Real& acc) {
113 acc += mass(i) * (vel(3 * i + 0) * vel(3 * i + 0) + vel(3 * i + 1) * vel(3 * i + 1) +
114 vel(3 * i + 2) * vel(3 * i + 2));
115 },
116 e);
117 return Real(0.5) * e;
118 }
119
120 Real internalEnergy() const {
121 using Exec = peclet::core::ExecSpace;
122 auto vol = view_.cellVolume;
123 const Real pe = pressEq_, va = volAvg_;
124 Real e = 0;
125 Kokkos::parallel_reduce(
126 "ee.ie", Kokkos::RangePolicy<Exec>(0, N_),
127 KOKKOS_LAMBDA(const int i, Real& acc) { acc -= pe * va * Kokkos::log(vol(i) / va); }, e);
128 return e;
129 }
130
131 const DView& positions() const { return pos_; }
132 const DView& velocities() const { return vel_; }
133 const DView& force() const { return force_; }
134 const TessellationView<Real>& view() const { return view_; }
135 int numParticles() const { return N_; }
136 Real time() const { return time_; }
137
138 public:
143 void setRepair(bool on) { useRepair_ = on; }
144 bool repair() const { return useRepair_; }
146 void setProfile(bool on) { profile_ = on; }
147
148 private:
149 void buildAndForce() {
150 const Real Larr[3] = {L_[0], L_[1], L_[2]};
151 if (useRepair_) {
152 // Incremental path: cold-build the resident tessellation once (establishes the topology store
153 // + volumes), then repair it in place each subsequent step. Either way the force geometry is
154 // re-evaluated from the store and published into the same facet-CSR view the full build
155 // emits.
156 if (!mtInit_) {
157 const double boxVol = static_cast<double>(L_[0]) * L_[1] * L_[2];
158 const Real spacing = static_cast<Real>(std::cbrt(boxVol / (N_ > 0 ? N_ : 1)));
159 mt_.sdf = sdf_;
160 mt_.profile = profile_;
161 mt_.alloc(N_, Larr, Real(kCertificateTolerance) * spacing, Real(kSkin) * spacing,
162 kSearchWindow, /*density=*/N_);
163 mt_.rebuild(pos_);
164 mtInit_ = true;
165 } else {
166 mt_.step(pos_);
167 }
168 view_ = peclet::voro::reevalPublish<Real, kMaxPlanes, kMaxTriangles>(
169 mt_.store, pos_, mt_.vol, N_, Larr, mt_.wall, mt_.xRef);
170 } else {
171 // Pass the persistent worklist cache (last arg) so the step-invariant worklist table is built
172 // once and reused across steps (E3). All intermediate args are the buildTessellation
173 // defaults; the Sdf template arg is named explicitly because a defaulted `{}` Sdf cannot be
174 // deduced.
175 auto res = peclet::voro::buildTessellation<Real, false, Sdf>(
176 pos_, w_, N_, Larr, kSearchWindow, /*densityCount=*/-1, /*gid=*/{}, sdf_,
177 /*withForceGeom=*/true, /*nBuild=*/-1, /*outNp=*/{}, /*outNt=*/{}, /*outPnbr=*/{},
178 /*outTri=*/{}, /*outCand=*/{}, /*outCandCnt=*/{}, /*candCap=*/0, &wlCache_,
179 /*outWall=*/{}, /*withAreaGrad=*/false, /*outNear=*/{}, /*outNearCnt=*/{},
180 /*nearCap=*/0, /*nearMargin=*/Real(0), /*withWallFD=*/false, /*withMoments=*/false,
181 profile_);
182 view_ = res.view;
183 }
184 aux_ = peclet::voro::buildAuxMaps(view_);
185 volAvg_ = (L_[0] * L_[1] * L_[2]) / static_cast<Real>(N_);
186 Kokkos::deep_copy(force_, Real(0));
187 eulerPressureForce(view_, aux_.recip, aux_.cellOfFacet, pressEq_, volAvg_, force_);
188 if (viscous_)
189 viscousForce(view_, aux_.recip, aux_.cellOfFacet, vel_, visc_, bulkVisc_, force_, viscGrad_,
190 viscStress_);
191 }
192
193 int N_ = 0;
194 std::array<Real, 3> L_{};
195 Real pressEq_ = 0, volAvg_ = 0, time_ = 0;
196 bool viscous_ = false;
197 DView pos_, vel_, invMass_, w_, force_, visc_, bulkVisc_;
198 DView viscGrad_, viscStress_; // persistent 9*N viscous scratch (E4)
200 wlCache_; // step-invariant worklist table, reused across steps (E3)
201 TessellationView<Real> view_;
203 // E1 opt-in incremental path (default off): resident moving-point tessellation + its cold/repair
204 // state. Kept as members (Views free before Kokkos::finalize).
205 bool useRepair_ = false, mtInit_ = false, profile_ = false;
207 Sdf sdf_{};
208};
209
210} // namespace physics
211} // namespace peclet::voro
212
213#endif // PECLET_VORO_PHYSICS_SIMULATION_HPP
Definition simulation.hpp:36
void setSdf(const Sdf &s)
Definition simulation.hpp:40
const TessellationView< Real > & view() const
Definition simulation.hpp:134
Real kineticEnergy(const DView &mass) const
Definition simulation.hpp:106
int numParticles() const
Definition simulation.hpp:135
const DView & velocities() const
Definition simulation.hpp:132
const DView & force() const
Definition simulation.hpp:133
Kokkos::View< Real *, peclet::core::MemSpace > DView
Definition simulation.hpp:38
Real internalEnergy() const
Definition simulation.hpp:120
void setViscous(const DView &visc, const DView &bulkVisc)
Enable the viscous term (NavierStokes); per-particle viscosities (size N).
Definition simulation.hpp:58
Real time() const
Definition simulation.hpp:136
void init(const DView &posFlat, const DView &vel, const DView &invMass, const std::array< Real, 3 > &L, Real pressEq)
Definition simulation.hpp:44
bool repair() const
Definition simulation.hpp:144
void setProfile(bool on)
The cold build's timing / over-buffer report on stderr (buildTessellation's profile).
Definition simulation.hpp:146
void step(int nSteps, Real dt)
Definition simulation.hpp:71
const DView & positions() const
Definition simulation.hpp:131
void setRepair(bool on)
Definition simulation.hpp:143
Reference physics consumer: compressible-Euler pressure force (Phase 4).
void viscousForce(const TessellationView< Real > &view, const Kokkos::View< int *, peclet::core::MemSpace > &recip, const Kokkos::View< int *, peclet::core::MemSpace > &cellOfFacet, const Kokkos::View< Real *, peclet::core::MemSpace > &vel, const Kokkos::View< Real *, peclet::core::MemSpace > &visc, const Kokkos::View< Real *, peclet::core::MemSpace > &bulkVisc, const Kokkos::View< Real *, peclet::core::MemSpace > &force, const Kokkos::View< Real *, peclet::core::MemSpace > &grad, const Kokkos::View< Real *, peclet::core::MemSpace > &stress)
Definition viscous.hpp:119
void eulerPressureForce(const TessellationView< Real > &view, const Kokkos::View< int *, peclet::core::MemSpace > &recip, const Kokkos::View< int *, peclet::core::MemSpace > &cellOfFacet, Real pressEq, Real volAvg, const Kokkos::View< Real *, peclet::core::MemSpace > &force)
Definition euler_pressure.hpp:40
Device-native Voronoi tessellation, geometry and finite-volume physics.
Definition convex_cell.hpp:41
AuxMaps< Real > buildAuxMaps(const TessellationView< Real > &view)
Build {recip, cellOfFacet} on device from a published view (dense single-domain).
Definition transpose.hpp:33
constexpr double kSkin
Definition params.hpp:33
constexpr double kCertificateTolerance
Definition params.hpp:32
constexpr int kSearchWindow
Definition params.hpp:28
Definition transpose.hpp:26
Definition repair.hpp:90
Definition tessellation_view.hpp:111
Definition tess_grid.hpp:83
Viscous Navier-Stokes force over the published view (de-legacy Phase 2).
Kokkos::View< real_t *, peclet::core::MemSpace > DView
Definition voro_bindings_common.hpp:39