20#include "backends/seq/impl.hpp"
27#ifdef NUMERICS_HAS_OMP
36#ifdef NUMERICS_HAS_OMP
37 const float h = params.
h;
38 const float m = params.
mass;
39 const float rho0 = params.
rho0;
40 const float B = rho0 * params.
c0 * params.
c0 /
static_cast<float>(params.
gamma);
41 const float supp_sq = 4.0f * h * h;
42 const int n =
static_cast<int>(particles.size());
44# pragma omp parallel for schedule(static)
45 for (
int i = 0; i < n; ++i) {
48 grid.
query(pi.x, pi.y, [&](
int j) {
49 const float rx = pi.x - particles[j].x;
50 const float ry = pi.y - particles[j].y;
51 const float r2 = rx * rx + ry * ry;
52 if (r2 < supp_sq) rho += m *
Kernel::W(std::sqrt(r2), h);
54 pi.density = std::max(rho, rho0 * 0.1f);
55 pi.pressure = std::max(0.0f, B * (
num::ipow<7>(pi.density / rho0) - 1.0f));
65#ifdef NUMERICS_HAS_OMP
66 const float h = params.
h;
67 const float m = params.
mass;
68 const float mu = params.
mu;
69 const float supp_sq = 4.0f * h * h;
70 const float eps2 = 0.01f * h * h;
71 const int n =
static_cast<int>(particles.size());
73# pragma omp parallel for schedule(static)
74 for (
int i = 0; i < n; ++i) {
76 float ax = params.
gx, ay = params.
gy;
77 grid.
query(pi.x, pi.y, [&](
int j) {
80 const float rx = pi.x - pj.
x, ry = pi.y - pj.
y;
81 const float r2 = rx * rx + ry * ry;
82 if (r2 >= supp_sq || r2 < 1e-10f)
return;
83 const float r = std::sqrt(r2);
87 const float pterm = pi.pressure / (pi.density * pi.density)
93 const float visc = m * mu / (pi.density * pj.
density) * lap;
94 ax += visc * (pi.evx - pj.
evx);
95 ay += visc * (pi.evy - pj.
evy);
106 const std::vector<RigidBody>& bodies,
108#ifdef NUMERICS_HAS_OMP
109 const int n =
static_cast<int>(particles.size());
110# pragma omp parallel for schedule(static)
111 for (
int i = 0; i < n; ++i) {
114 const float dx = p.
x - body.x, dy = p.
y - body.y;
115 const float d = std::sqrt(dx * dx + dy * dy);
116 if (d < body.radius && d > 1e-8f) {
117 const float nx = dx / d, ny = dy / d;
118 p.
x = body.x + body.radius * nx;
119 p.
y = body.y + body.radius * ny;
120 const float vn = p.
vx * nx + p.
vy * ny;
134#ifdef NUMERICS_HAS_OMP
135 const float dt = params.
dt;
136 const int n =
static_cast<int>(particles.size());
137# pragma omp parallel for schedule(static)
138 for (
int i = 0; i < n; ++i) {
140 p.
vx += p.
ax * dt; p.
vy += p.
ay * dt;
141 p.
x += p.
vx * dt; p.
y += p.
vy * dt;
152#ifdef NUMERICS_HAS_OMP
154 const int n =
static_cast<int>(particles.size());
155# pragma omp parallel for schedule(static)
156 for (
int i = 0; i < n; ++i) {
158 if (p.
x < params.
xmin) { p.
x = params.
xmin; p.
vx = std::abs(p.
vx) * e; }
159 if (p.
x > params.
xmax) { p.
x = params.
xmax; p.
vx = -std::abs(p.
vx) * e; }
160 if (p.
y < params.
ymin) { p.
y = params.
ymin; p.
vy = std::abs(p.
vy) * e; }
161 if (p.
y > params.
ymax) { p.
y = params.
ymax; p.
vy = -std::abs(p.
vy) * e; }
169 const std::vector<RigidBody>& bodies,
170 float& T_min,
float& T_max) {
171#ifdef NUMERICS_HAS_OMP
172 if (particles.empty())
return;
173 const int n =
static_cast<int>(particles.size());
174 float lo = FLT_MAX, hi = -FLT_MAX;
175# pragma omp parallel for reduction(min:lo) reduction(max:hi) schedule(static)
176 for (
int i = 0; i < n; ++i) {
177 lo = std::min(lo, particles[i].temperature);
178 hi = std::max(hi, particles[i].temperature);
180 T_min = lo; T_max = hi;
182 T_min = std::min(T_min, b.temperature);
183 T_max = std::max(T_max, b.temperature);
void query(float px, float py, 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 body_collisions(std::vector< Particle > &particles, const std::vector< RigidBody > &bodies, const FluidParams ¶ms)
void compute_forces(std::vector< Particle > &particles, const FluidParams ¶ms, const SpatialHash &grid)
Per-particle query – each thread writes only to particles[i]. O(n*k).
void compute_density_pressure(std::vector< Particle > &particles, const FluidParams ¶ms, const SpatialHash &grid)
Per-particle query – each thread writes only to particles[i]. O(n*k).
void update_temp_range(const std::vector< Particle > &particles, const std::vector< RigidBody > &bodies, float &T_min, float &T_max)
reduction(min:T_min) reduction(max:T_max)
void integrate(std::vector< Particle > &particles, const FluidParams ¶ms)
void enforce_boundaries(std::vector< Particle > &particles, const FluidParams ¶ms)
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 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 dT_dt
Temperature rate [ degC/s] (updated each step)
float temperature
Temperature T_i [ degC].
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.