numerics
Loading...
Searching...
No Matches
sph_kernel.hpp
Go to the documentation of this file.
1/// @file spatial/sph_kernel.hpp
2/// @brief Dimension-generic SPH smoothing kernels.
3///
4/// SPHKernel<2> -- 2D kernels (cubic sigma = 10/(7π h²), spiky = -15/(16π h⁵) (2h-r)²)
5/// SPHKernel<3> -- 3D kernels (cubic sigma = 1/(π h³), spiky = -45/(π (2h)⁶) (2h-r)²)
6///
7/// Support radius 2h throughout; q = r/h.
8///
9/// Cubic spline (density + Morris viscosity Laplacian):
10/// W = sigma * { 1 - 1.5q² + 0.75q³ q ≤ 1
11/// { 0.25(2-q)³ 1 < q ≤ 2
12/// dW/dr = sigma/h * { -3q + 2.25q² q ≤ 1
13/// { -0.75(2-q)² 1 < q ≤ 2
14///
15/// Spiky kernel (pressure gradient -- dW/dr ≠ 0 as r→0 prevents clustering):
16/// dW/dr < 0, Spiky_gradW returns (dW/dr / r) * r_vec
17///
18/// Spiky_gradW takes std::array<float, Dim> and returns std::array<float, Dim>.
19#pragma once
20
21#include <cmath>
22#include <array>
23
24namespace num {
25
26namespace detail {
27
28template<int Dim> struct CubicSigma;
29template<> struct CubicSigma<2> {
30 static float compute(float h) {
31 return 10.0f / (7.0f * 3.14159265f * h * h);
32 }
33};
34template<> struct CubicSigma<3> {
35 static float compute(float h) {
36 return 1.0f / (3.14159265f * h * h * h);
37 }
38};
39
40template<int Dim> struct SpikyDW;
41template<> struct SpikyDW<2> {
42 // dW/dr = -15/(16π h⁵) * (2h-r)²
43 static float compute(float r, float h) {
44 const float H = 2.0f * h;
45 if (r >= H) return 0.0f;
46 const float h5 = h * h * h * h * h;
47 const float d = H - r;
48 return (-15.0f / (16.0f * 3.14159265f * h5)) * d * d;
49 }
50};
51template<> struct SpikyDW<3> {
52 // dW/dr = -45/(π H⁶) * (H-r)², H = 2h
53 static float compute(float r, float h) {
54 const float H = 2.0f * h;
55 if (r >= H || r < 1e-10f) return 0.0f;
56 const float H6 = H * H * H * H * H * H;
57 const float d = H - r;
58 return -45.0f / (3.14159265f * H6) * d * d;
59 }
60};
61
62} // namespace detail
63
64/// Dimension-generic SPH smoothing kernels. Dim = 2 or 3.
65template<int Dim>
66struct SPHKernel {
67 static_assert(Dim == 2 || Dim == 3, "SPHKernel: Dim must be 2 or 3");
68
69 /// 2D/3D cubic spline density kernel. Support = 2h.
70 static float W(float r, float h) {
72 const float q = r / h;
73 if (q <= 1.0f)
74 return sigma * (1.0f - 1.5f * q * q + 0.75f * q * q * q);
75 if (q <= 2.0f) {
76 const float t = 2.0f - q;
77 return sigma * 0.25f * t * t * t;
78 }
79 return 0.0f;
80 }
81
82 /// Radial derivative dW/dr of cubic spline (<= 0 for r > 0).
83 /// Used for the Morris SPH Laplacian in viscosity and heat.
84 static float dW_dr(float r, float h) {
86 const float q = r / h;
87 if (q <= 1.0f) return (sigma / h) * (-3.0f * q + 2.25f * q * q);
88 if (q <= 2.0f) {
89 const float t = 2.0f - q;
90 return (sigma / h) * (-0.75f * t * t);
91 }
92 return 0.0f;
93 }
94
95 /// Radial derivative dW/dr of spiky kernel (<= 0, non-zero at r=0).
96 static float Spiky_dW_dr(float r, float h) {
98 }
99
100 /// Gradient of spiky kernel: g = (dW/dr / r) * r_vec.
101 /// Returns zero array if r < eps or r >= 2h.
102 static std::array<float, Dim> Spiky_gradW(std::array<float, Dim> r_vec,
103 float r, float h) {
104 std::array<float, Dim> g{};
105 if (r < 1e-10f || r >= 2.0f * h) return g;
106 const float c = detail::SpikyDW<Dim>::compute(r, h) / r;
107 for (int d = 0; d < Dim; ++d) g[d] = c * r_vec[d];
108 return g;
109 }
110};
111
112} // namespace num
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
Dimension-generic SPH smoothing kernels. Dim = 2 or 3.
static std::array< float, Dim > Spiky_gradW(std::array< float, Dim > r_vec, float r, float h)
static float dW_dr(float r, float h)
static float Spiky_dW_dr(float r, float h)
Radial derivative dW/dr of spiky kernel (<= 0, non-zero at r=0).
static float W(float r, float h)
2D/3D cubic spline density kernel. Support = 2h.
static float compute(float h)
static float compute(float h)
static float compute(float r, float h)
static float compute(float r, float h)