22 const float h = params.
h;
23 const float m = params.
mass;
24 const float rho0 = params.
rho0;
25 const float B = rho0 * params.
c0 * params.
c0 /
static_cast<float>(params.
gamma);
26 const float supp_sq = 4.0f * h * h;
33 const float rx = particles[i].x - particles[j].x;
34 const float ry = particles[i].y - particles[j].y;
35 const float r2 = rx * rx + ry * ry;
36 if (r2 >= supp_sq)
return;
37 const float w = m *
Kernel::W(std::sqrt(r2), h);
38 particles[i].density += w;
39 particles[j].density += w;
43 p.density = std::max(p.density, rho0 * 0.1f);
44 p.pressure = std::max(0.0f, B * (
num::ipow<7>(p.density / rho0) - 1.0f));
53 const float h = params.
h;
54 const float m = params.
mass;
55 const float mu = params.
mu;
56 const float supp_sq = 4.0f * h * h;
57 const float eps2 = 0.01f * h * h;
59 for (
Particle& p : particles) { p.ax = params.
gx; p.ay = params.
gy; }
64 const float rx = pi.x - pj.
x, ry = pi.y - pj.
y;
65 const float r2 = rx * rx + ry * ry;
66 if (r2 >= supp_sq || r2 < 1e-10f)
return;
67 const float r = std::sqrt(r2);
71 const float pterm = pi.pressure / (pi.density * pi.density)
73 const float fpx = -m * pterm * gx, fpy = -m * pterm * gy;
74 pi.ax += fpx; pi.ay += fpy;
75 pj.
ax -= fpx; pj.
ay -= fpy;
78 const float visc = m * mu / (pi.density * pj.
density) * lap;
79 const float fvx = visc * (pi.evx - pj.
evx), fvy = visc * (pi.evy - pj.
evy);
80 pi.ax += fvx; pi.ay += fvy;
81 pj.
ax -= fvx; pj.
ay -= fvy;
88 const std::vector<RigidBody>& bodies,
92 const float dx = p.x - body.x, dy = p.y - body.y;
93 const float d = std::sqrt(dx * dx + dy * dy);
94 if (d < body.radius && d > 1e-8f) {
95 const float nx = dx / d, ny = dy / d;
96 p.x = body.x + body.radius * nx;
97 p.y = body.y + body.radius * ny;
98 const float vn = p.vx * nx + p.vy * ny;
109 const float dt = params.
dt;
111 p.vx += p.ax * dt; p.vy += p.ay * dt;
112 p.x += p.vx * dt; p.y += p.vy * dt;
113 p.evx = 0.5f * (p.evx + p.vx);
114 p.evy = 0.5f * (p.evy + p.vy);
115 p.temperature = std::clamp(p.temperature + p.dT_dt * dt, -100.0f, 300.0f);
122 if (p.x < params.
xmin) { p.x = params.
xmin; p.vx = std::abs(p.vx) * e; }
123 if (p.x > params.
xmax) { p.x = params.
xmax; p.vx = -std::abs(p.vx) * e; }
124 if (p.y < params.
ymin) { p.y = params.
ymin; p.vy = std::abs(p.vy) * e; }
125 if (p.y > params.
ymax) { p.y = params.
ymax; p.vy = -std::abs(p.vy) * e; }
130 const std::vector<RigidBody>& bodies,
131 float& T_min,
float& T_max) {
132 if (particles.empty())
return;
133 T_min = T_max = particles[0].temperature;
134 for (
const Particle& p : particles) {
135 T_min = std::min(T_min, p.temperature);
136 T_max = std::max(T_max, p.temperature);
139 T_min = std::min(T_min, b.temperature);
140 T_max = std::max(T_max, b.temperature);
147 if (b.fixed)
continue;
148 b.vx += params.
gx * dt; b.vy += params.
gy * dt;
149 b.x += b.vx * dt; b.y += b.vy * dt;
150 const float r = b.radius;
151 if (b.x - r < params.
xmin) { b.x = params.
xmin + r; b.vx = std::abs(b.vx) * e; }
152 if (b.x + r > params.
xmax) { b.x = params.
xmax - r; b.vx = -std::abs(b.vx) * e; }
153 if (b.y - r < params.
ymin) { b.y = params.
ymin + r; b.vy = std::abs(b.vy) * e; }
154 if (b.y + r > params.
ymax) { b.y = params.
ymax - r; b.vy = -std::abs(b.vy) * e; }
void iterate_pairs(F &&f) const
Compile-time integer exponentiation via repeated squaring.
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 rho0
Rest density [kg/m^3].
float mu
Dynamic viscosity [Pa*s].
int gamma
Tait EOS exponent.
float h
Smoothing length [m].
float c0
Speed of sound [m/s] -> B = rho_0c_0^2/gamma.
float gy
Gravity y [m/s^2].
float restitution
Velocity restitution at walls.
float gx
Gravity x [m/s^2].
float dt
Timestep [s] (must satisfy CFL: dt < h/c0)
float mass
Particle mass [kg] (~= rho_0*dx^2, dx=0.8h)
static float Spiky_dW_dr(float r, float h)
static void Spiky_gradW(float rx, float ry, float r, float h, float &gx, float &gy)
static float W(float r, float h)
A single SPH fluid particle (float precision for performance)
float pressure
Pressure p_i [Pa].
float density
SPH density rho_i [kg/m^3].
float ay
Acceleration [m/s^2] (updated each step)
A rigid spherical body that interacts with fluid particles.