16 const float h = params.
h;
17 const float m = params.
mass;
18 const float rho0 = params.
rho0;
19 const float B = rho0 * params.
c0 * params.
c0 /
static_cast<float>(params.
gamma);
20 const float supp_sq = 4.0f * h * h;
23 for (
Particle3D& p : particles) p.density = m * W0;
26 const float rx = particles[i].x - particles[j].x;
27 const float ry = particles[i].y - particles[j].y;
28 const float rz = particles[i].z - particles[j].z;
29 const float r2 = rx*rx + ry*ry + rz*rz;
30 if (r2 >= supp_sq)
return;
32 particles[i].density += w;
33 particles[j].density += w;
37 p.density = std::max(p.density, rho0 * 0.1f);
38 p.pressure = std::max(0.0f, B * (
num::ipow<7>(p.density / rho0) - 1.0f));
45 const float h = params.
h;
46 const float m = params.
mass;
47 const float mu = params.
mu;
48 const float supp_sq = 4.0f * h * h;
49 const float eps2 = 0.01f * h * h;
51 for (
Particle3D& p : particles) { p.ax = params.
gx; p.ay = params.
gy; p.az = params.
gz; }
56 const float rx = pi.x - pj.
x, ry = pi.y - pj.
y, rz = pi.z - pj.
z;
57 const float r2 = rx*rx + ry*ry + rz*rz;
58 if (r2 >= supp_sq || r2 < 1e-10f)
return;
59 const float r = std::sqrt(r2);
63 const float pterm = pi.pressure / (pi.density * pi.density)
65 const float fpx = -m * pterm * gx, fpy = -m * pterm * gy, fpz = -m * pterm * gz;
66 pi.ax += fpx; pi.ay += fpy; pi.az += fpz;
67 pj.
ax -= fpx; pj.
ay -= fpy; pj.
az -= fpz;
70 const float visc = m * mu / (pi.density * pj.
density) * lap;
71 const float fvx = visc * (pi.evx - pj.
evx);
72 const float fvy = visc * (pi.evy - pj.
evy);
73 const float fvz = visc * (pi.evz - pj.
evz);
74 pi.ax += fvx; pi.ay += fvy; pi.az += fvz;
75 pj.
ax -= fvx; pj.
ay -= fvy; pj.
az -= fvz;
80 const std::vector<RigidBody3D>& bodies,
84 const float dx = p.x - body.x, dy = p.y - body.y, dz = p.z - body.z;
85 const float d = std::sqrt(dx*dx + dy*dy + dz*dz);
86 if (d < body.radius && d > 1e-8f) {
87 const float nx = dx/d, ny = dy/d, nz = dz/d;
88 p.x = body.x + body.radius * nx;
89 p.y = body.y + body.radius * ny;
90 p.z = body.z + body.radius * nz;
91 const float vn = p.vx*nx + p.vy*ny + p.vz*nz;
94 p.vx -= c * nx; p.vy -= c * ny; p.vz -= c * nz;
102 const float dt = params.
dt;
104 p.vx += p.ax * dt; p.vy += p.ay * dt; p.vz += p.az * dt;
105 p.x += p.vx * dt; p.y += p.vy * dt; p.z += p.vz * dt;
106 p.evx = 0.5f * (p.evx + p.vx);
107 p.evy = 0.5f * (p.evy + p.vy);
108 p.evz = 0.5f * (p.evz + p.vz);
109 p.temperature = std::clamp(p.temperature + p.dT_dt * dt, -100.0f, 300.0f);
116 if (p.x < params.
xmin) { p.x = params.
xmin; p.vx = std::abs(p.vx) * e; }
117 if (p.x > params.
xmax) { p.x = params.
xmax; p.vx = -std::abs(p.vx) * e; }
118 if (p.y < params.
ymin) { p.y = params.
ymin; p.vy = std::abs(p.vy) * e; }
119 if (p.y > params.
ymax) { p.y = params.
ymax; p.vy = -std::abs(p.vy) * e; }
120 if (p.z < params.
zmin) { p.z = params.
zmin; p.vz = std::abs(p.vz) * e; }
121 if (p.z > params.
zmax) { p.z = params.
zmax; p.vz = -std::abs(p.vz) * e; }
126 const std::vector<RigidBody3D>& bodies,
127 float& T_min,
float& T_max) {
128 if (particles.empty())
return;
129 T_min = T_max = particles[0].temperature;
131 T_min = std::min(T_min, p.temperature);
132 T_max = std::max(T_max, p.temperature);
135 T_min = std::min(T_min, b.temperature);
136 T_max = std::max(T_max, b.temperature);
143 if (b.fixed)
continue;
144 b.vx += params.
gx * dt; b.vy += params.
gy * dt; b.vz += params.
gz * dt;
145 b.x += b.vx * dt; b.y += b.vy * dt; b.z += b.vz * dt;
146 const float r = b.radius;
147 if (b.x - r < params.
xmin) { b.x = params.
xmin + r; b.vx = std::abs(b.vx) * e; }
148 if (b.x + r > params.
xmax) { b.x = params.
xmax - r; b.vx = -std::abs(b.vx) * e; }
149 if (b.y - r < params.
ymin) { b.y = params.
ymin + r; b.vy = std::abs(b.vy) * e; }
150 if (b.y + r > params.
ymax) { b.y = params.
ymax - r; b.vy = -std::abs(b.vy) * e; }
151 if (b.z - r < params.
zmin) { b.z = params.
zmin + r; b.vz = std::abs(b.vz) * e; }
152 if (b.z + r > params.
zmax) { b.z = params.
zmax - r; b.vz = -std::abs(b.vz) * e; }
void iterate_pairs(F &&f) const
Newton's 3rd law pair traversal – 13 forward offsets, O(n*k/2).
Compile-time integer exponentiation via repeated squaring.
SPH smoothing kernels for 3D WCSPH — delegates to num::SPHKernel<3>.
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
void enforce_boundaries(std::vector< Particle > &particles, const FluidParams ¶ms)
void body_collisions(std::vector< Particle > &particles, const std::vector< RigidBody > &bodies, const FluidParams ¶ms)
void integrate(std::vector< Particle > &particles, const FluidParams ¶ms)
void compute_density_pressure(std::vector< Particle > &particles, const FluidParams ¶ms, const SpatialHash &grid)
Newton's 3rd law pair traversal – O(n*k/2).
void update_temp_range(const std::vector< Particle > &particles, const std::vector< RigidBody > &bodies, float &T_min, float &T_max)
void integrate_bodies(std::vector< RigidBody > &bodies, const FluidParams ¶ms)
void compute_forces(std::vector< Particle > &particles, const FluidParams ¶ms, const SpatialHash &grid)
Newton's 3rd law pair traversal – O(n*k/2).
std::experimental::simd butterfly for FFT.
float mu
Dynamic viscosity [Pa*s].
float c0
Speed of sound [m/s].
float h
Smoothing length [m].
int gamma
Tait EOS exponent.
float mass
Particle mass [kg] (~= rho_0*(0.8h)^3)
float rho0
Rest density [kg/m^3].
static void Spiky_gradW(float rx, float ry, float rz, float r, float h, float &gx, float &gy, float &gz)
static float Spiky_dW_dr(float r, float h)
static float W(float r, float h)
3D SPH particle – AoS layout
float evz
smoothed velocity (ev = (ev+v)/2 each step)
3D rigid spherical body that interacts with SPH particles