18#include "backends/seq/impl.hpp"
25#ifdef NUMERICS_HAS_OMP
34#ifdef NUMERICS_HAS_OMP
35 const float h = params.
h;
36 const float m = params.
mass;
37 const float rho0 = params.
rho0;
38 const float B = rho0 * params.
c0 * params.
c0 /
static_cast<float>(params.
gamma);
39 const float supp_sq = 4.0f * h * h;
40 const int n =
static_cast<int>(particles.size());
42# pragma omp parallel for schedule(static)
43 for (
int i = 0; i < n; ++i) {
46 grid.
query(pi.x, pi.y, pi.z, [&](
int j) {
47 const float rx = pi.x - particles[j].x;
48 const float ry = pi.y - particles[j].y;
49 const float rz = pi.z - particles[j].z;
50 const float r2 = rx*rx + ry*ry + rz*rz;
51 if (r2 < supp_sq) rho += m *
Kernel3D::W(std::sqrt(r2), h);
53 pi.density = std::max(rho, rho0 * 0.1f);
54 pi.pressure = std::max(0.0f, B * (
num::ipow<7>(pi.density / rho0) - 1.0f));
64#ifdef NUMERICS_HAS_OMP
65 const float h = params.
h;
66 const float m = params.
mass;
67 const float mu = params.
mu;
68 const float supp_sq = 4.0f * h * h;
69 const float eps2 = 0.01f * h * h;
70 const int n =
static_cast<int>(particles.size());
72# pragma omp parallel for schedule(static)
73 for (
int i = 0; i < n; ++i) {
75 float ax = params.
gx, ay = params.
gy, az = params.
gz;
76 grid.
query(pi.x, pi.y, pi.z, [&](
int j) {
79 const float rx = pi.x - pj.
x, ry = pi.y - pj.
y, rz = pi.z - pj.
z;
80 const float r2 = rx*rx + ry*ry + rz*rz;
81 if (r2 >= supp_sq || r2 < 1e-10f)
return;
82 const float r = std::sqrt(r2);
86 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);
96 az += visc * (pi.evz - pj.
evz);
100 particles[i].az = az;
108 const std::vector<RigidBody3D>& bodies,
110#ifdef NUMERICS_HAS_OMP
111 const int n =
static_cast<int>(particles.size());
112# pragma omp parallel for schedule(static)
113 for (
int i = 0; i < n; ++i) {
116 const float dx = p.
x - body.x, dy = p.
y - body.y, dz = p.
z - body.z;
117 const float d = std::sqrt(dx*dx + dy*dy + dz*dz);
118 if (d < body.radius && d > 1e-8f) {
119 const float nx = dx/d, ny = dy/d, nz = dz/d;
120 p.
x = body.x + body.radius * nx;
121 p.
y = body.y + body.radius * ny;
122 p.
z = body.z + body.radius * nz;
123 const float vn = p.
vx*nx + p.
vy*ny + p.
vz*nz;
126 p.
vx -= c * nx; p.
vy -= c * ny; p.
vz -= c * nz;
137#ifdef NUMERICS_HAS_OMP
138 const float dt = params.
dt;
139 const int n =
static_cast<int>(particles.size());
140# pragma omp parallel for schedule(static)
141 for (
int i = 0; i < n; ++i) {
143 p.
vx += p.
ax * dt; p.
vy += p.
ay * dt; p.
vz += p.
az * dt;
144 p.
x += p.
vx * dt; p.
y += p.
vy * dt; p.
z += p.
vz * dt;
156#ifdef NUMERICS_HAS_OMP
158 const int n =
static_cast<int>(particles.size());
159# pragma omp parallel for schedule(static)
160 for (
int i = 0; i < n; ++i) {
162 if (p.
x < params.
xmin) { p.
x = params.
xmin; p.
vx = std::abs(p.
vx) * e; }
163 if (p.
x > params.
xmax) { p.
x = params.
xmax; p.
vx = -std::abs(p.
vx) * e; }
164 if (p.
y < params.
ymin) { p.
y = params.
ymin; p.
vy = std::abs(p.
vy) * e; }
165 if (p.
y > params.
ymax) { p.
y = params.
ymax; p.
vy = -std::abs(p.
vy) * e; }
166 if (p.
z < params.
zmin) { p.
z = params.
zmin; p.
vz = std::abs(p.
vz) * e; }
167 if (p.
z > params.
zmax) { p.
z = params.
zmax; p.
vz = -std::abs(p.
vz) * e; }
175 const std::vector<RigidBody3D>& bodies,
176 float& T_min,
float& T_max) {
177#ifdef NUMERICS_HAS_OMP
178 if (particles.empty())
return;
179 const int n =
static_cast<int>(particles.size());
180 float lo = FLT_MAX, hi = -FLT_MAX;
181# pragma omp parallel for reduction(min:lo) reduction(max:hi) schedule(static)
182 for (
int i = 0; i < n; ++i) {
183 lo = std::min(lo, particles[i].temperature);
184 hi = std::max(hi, particles[i].temperature);
186 T_min = lo; T_max = hi;
188 T_min = std::min(T_min, b.temperature);
189 T_max = std::max(T_max, b.temperature);
void query(float px, float py, float pz, F &&f) const
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 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 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