|
16 | 16 | #include <cmath> |
17 | 17 | #include <vector> |
18 | 18 |
|
19 | | -real computeAdaptiveDt(const std::vector<Particle> &p, real base_dt) { |
20 | | - real maxSpeed = 0; |
21 | | - |
22 | | - for (const auto &a : p) { |
23 | | - real speed = std::sqrt(a.vx * a.vx + a.vy * a.vy + a.vz * a.vz); |
24 | | - if (speed > maxSpeed) |
25 | | - maxSpeed = speed; |
26 | | - } |
27 | | - |
28 | | - maxSpeed = std::min(maxSpeed, real(1e4)); |
29 | | - |
30 | | - // If everything is basically stationary, use base dt |
31 | | - if (maxSpeed < real(1e-8)) |
32 | | - return base_dt; |
33 | | - |
34 | | - // Smaller dt when speeds are high |
35 | | - real dt = base_dt / (1 + maxSpeed); |
36 | | - |
37 | | - // Clamp dt to a reasonable range |
38 | | - dt = std::max(dt, base_dt * real(0.01)); // never smaller than 1% of base |
39 | | - dt = std::min(dt, base_dt * real(1.0)); // never larger than base |
40 | | - |
41 | | - return dt; |
| 19 | +/** |
| 20 | + * @brief Computes a global adaptive time-step based on the maximum velocity in the system. |
| 21 | + * Updated for SoA (Structure of Arrays) for better cache performance. |
| 22 | + */ |
| 23 | +real computeAdaptiveDt(const Particle &p, real base_dt) { |
| 24 | + real maxSpeedSq = 0; |
| 25 | + const size_t N = p.size(); |
| 26 | + |
| 27 | + // High-speed linear scan through velocity arrays |
| 28 | + // The compiler can easily vectorize this with SIMD (AVX/SSE) |
| 29 | + for (size_t i = 0; i < N; ++i) { |
| 30 | + real speedSq = p.vx[i] * p.vx[i] + p.vy[i] * p.vy[i] + p.vz[i] * p.vz[i]; |
| 31 | + if (speedSq > maxSpeedSq) |
| 32 | + maxSpeedSq = speedSq; |
| 33 | + } |
| 34 | + |
| 35 | + real maxSpeed = std::sqrt(maxSpeedSq); |
| 36 | + |
| 37 | + // Safety clamp to prevent dt from exploding or becoming zero |
| 38 | + maxSpeed = std::min(maxSpeed, real(1e4)); |
| 39 | + |
| 40 | + // If everything is basically stationary, use base dt |
| 41 | + if (maxSpeed < real(1e-8)) |
| 42 | + return base_dt; |
| 43 | + |
| 44 | + // Standard Courant-like condition: smaller dt when speeds are high |
| 45 | + real dt = base_dt / (1 + maxSpeed); |
| 46 | + |
| 47 | + // Clamp dt to a reasonable range |
| 48 | + dt = std::max(dt, base_dt * real(0.01)); // never smaller than 1% of base |
| 49 | + dt = std::min(dt, base_dt * real(1.0)); // never larger than base |
| 50 | + |
| 51 | + return dt; |
42 | 52 | } |
0 commit comments