numerics
Loading...
Searching...
No Matches
fluid.cpp
Go to the documentation of this file.
1/// @file backends/seq/fluid.cpp
2/// @brief Sequential 3D SPH backend -- Newton's 3rd law pair traversal
3
4#include "impl.hpp"
5#include "kernel3d.hpp"
7#include <cmath>
8#include <algorithm>
9#include <cfloat>
10
11namespace physics::backends::seq {
12
13void compute_density_pressure(std::vector<Particle3D>& particles,
14 const FluidParams3D& params,
15 const SpatialHash3D& grid) {
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;
21
22 const float W0 = Kernel3D::W(0.0f, h);
23 for (Particle3D& p : particles) p.density = m * W0;
24
25 grid.iterate_pairs([&](int i, int j) {
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;
31 const float w = m * Kernel3D::W(std::sqrt(r2), h);
32 particles[i].density += w;
33 particles[j].density += w;
34 });
35
36 for (Particle3D& p : particles) {
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));
39 }
40}
41
42void compute_forces(std::vector<Particle3D>& particles,
43 const FluidParams3D& params,
44 const SpatialHash3D& grid) {
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;
50
51 for (Particle3D& p : particles) { p.ax = params.gx; p.ay = params.gy; p.az = params.gz; }
52
53 grid.iterate_pairs([&](int i, int j) {
54 Particle3D& pi = particles[i];
55 Particle3D& pj = particles[j];
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);
60
61 float gx, gy, gz;
62 Kernel3D::Spiky_gradW(rx, ry, rz, r, h, gx, gy, gz);
63 const float pterm = pi.pressure / (pi.density * pi.density)
64 + pj.pressure / (pj.density * pj.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;
68
69 const float lap = 2.0f * Kernel3D::Spiky_dW_dr(r, h) * r / (r2 + eps2);
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;
76 });
77}
78
79void body_collisions(std::vector<Particle3D>& particles,
80 const std::vector<RigidBody3D>& bodies,
81 const FluidParams3D& params) {
82 for (Particle3D& p : particles) {
83 for (const RigidBody3D& body : 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;
92 if (vn < 0.0f) {
93 const float c = (1.0f + params.restitution) * vn;
94 p.vx -= c * nx; p.vy -= c * ny; p.vz -= c * nz;
95 }
96 }
97 }
98 }
99}
100
101void integrate(std::vector<Particle3D>& particles, const FluidParams3D& params) {
102 const float dt = params.dt;
103 for (Particle3D& p : particles) {
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);
110 }
111}
112
113void enforce_boundaries(std::vector<Particle3D>& particles, const FluidParams3D& params) {
114 const float e = params.restitution;
115 for (Particle3D& p : particles) {
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; }
122 }
123}
124
125void update_temp_range(const std::vector<Particle3D>& particles,
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;
130 for (const Particle3D& p : particles) {
131 T_min = std::min(T_min, p.temperature);
132 T_max = std::max(T_max, p.temperature);
133 }
134 for (const RigidBody3D& b : bodies) {
135 T_min = std::min(T_min, b.temperature);
136 T_max = std::max(T_max, b.temperature);
137 }
138}
139
140void integrate_bodies(std::vector<RigidBody3D>& bodies, const FluidParams3D& params) {
141 const float dt = params.dt, e = params.restitution;
142 for (RigidBody3D& b : bodies) {
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; }
153 }
154}
155
156} // namespace physics::backends::seq
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 &params)
Definition fluid.cpp:119
void body_collisions(std::vector< Particle > &particles, const std::vector< RigidBody > &bodies, const FluidParams &params)
Definition fluid.cpp:87
void integrate(std::vector< Particle > &particles, const FluidParams &params)
Definition fluid.cpp:108
void compute_density_pressure(std::vector< Particle > &particles, const FluidParams &params, const SpatialHash &grid)
Newton's 3rd law pair traversal – O(n*k/2).
Definition fluid.cpp:19
void update_temp_range(const std::vector< Particle > &particles, const std::vector< RigidBody > &bodies, float &T_min, float &T_max)
Definition fluid.cpp:129
void integrate_bodies(std::vector< RigidBody > &bodies, const FluidParams &params)
Definition fluid.cpp:144
void compute_forces(std::vector< Particle > &particles, const FluidParams &params, const SpatialHash &grid)
Newton's 3rd law pair traversal – O(n*k/2).
Definition fluid.cpp:50
std::experimental::simd butterfly for FFT.
float mu
Dynamic viscosity [Pa*s].
Definition fluid3d.hpp:26
float c0
Speed of sound [m/s].
Definition fluid3d.hpp:25
float h
Smoothing length [m].
Definition fluid3d.hpp:22
int gamma
Tait EOS exponent.
Definition fluid3d.hpp:24
float mass
Particle mass [kg] (~= rho_0*(0.8h)^3)
Definition fluid3d.hpp:27
float rho0
Rest density [kg/m^3].
Definition fluid3d.hpp:23
static void Spiky_gradW(float rx, float ry, float rz, float r, float h, float &gx, float &gy, float &gz)
Definition kernel3d.hpp:22
static float Spiky_dW_dr(float r, float h)
Definition kernel3d.hpp:19
static float W(float r, float h)
Definition kernel3d.hpp:13
3D SPH particle – AoS layout
Definition particle3d.hpp:8
float evz
smoothed velocity (ev = (ev+v)/2 each step)
3D rigid spherical body that interacts with SPH particles