use crate::lattice::{CS2, D2Q9_C, D2Q9_W, D3Q27_C, D3Q27_W, h2, h3};
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Moments2d {
pub rho: f64,
pub u: [f64; 2],
pub s: [f64; 3],
}
impl Moments2d {
pub fn equilibrium(rho: f64, u: [f64; 2]) -> Self {
Self {
rho,
u,
s: [u[0] * u[0], u[1] * u[1], u[0] * u[1]],
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Moments3d {
pub rho: f64,
pub u: [f64; 3],
pub s: [f64; 6],
}
impl Moments3d {
pub fn equilibrium(rho: f64, u: [f64; 3]) -> Self {
Self {
rho,
u,
s: [
u[0] * u[0],
u[1] * u[1],
u[2] * u[2],
u[0] * u[1],
u[0] * u[2],
u[1] * u[2],
],
}
}
}
pub fn reconstruct_d2q9(m: &Moments2d) -> [f64; 9] {
let (ux, uy) = (m.u[0], m.u[1]);
let (sxx, syy, sxy) = (m.s[0], m.s[1], m.s[2]);
let a_xxy = sxx * uy + 2.0 * sxy * ux - 2.0 * ux * ux * uy;
let a_xyy = syy * ux + 2.0 * sxy * uy - 2.0 * ux * uy * uy;
let inv_cs2 = 1.0 / CS2;
let inv_2cs4 = 1.0 / (2.0 * CS2 * CS2);
let inv_2cs6 = 3.0 / (2.0 * CS2 * CS2 * CS2);
let mut f = [0.0; 9];
for i in 0..9 {
let c = &D2Q9_C[i];
let cu = (c[0] as f64) * ux + (c[1] as f64) * uy;
let hs = h2(c, 0, 0) * sxx + h2(c, 1, 1) * syy + 2.0 * h2(c, 0, 1) * sxy;
let h3s = h3(c, 0, 0, 1) * a_xxy + h3(c, 0, 1, 1) * a_xyy;
f[i] = m.rho * D2Q9_W[i] * (1.0 + cu * inv_cs2 + hs * inv_2cs4 + h3s * inv_2cs6);
}
f
}
pub fn reconstruct_d3q27(m: &Moments3d) -> [f64; 27] {
let (ux, uy, uz) = (m.u[0], m.u[1], m.u[2]);
let (sxx, syy, szz) = (m.s[0], m.s[1], m.s[2]);
let (sxy, sxz, syz) = (m.s[3], m.s[4], m.s[5]);
let a_xxy = sxx * uy + 2.0 * sxy * ux - 2.0 * ux * ux * uy;
let a_xyy = syy * ux + 2.0 * sxy * uy - 2.0 * ux * uy * uy;
let a_xxz = sxx * uz + 2.0 * sxz * ux - 2.0 * ux * ux * uz;
let a_xzz = szz * ux + 2.0 * sxz * uz - 2.0 * ux * uz * uz;
let a_yyz = syy * uz + 2.0 * syz * uy - 2.0 * uy * uy * uz;
let a_yzz = szz * uy + 2.0 * syz * uz - 2.0 * uy * uz * uz;
let a_xyz = sxy * uz + syz * ux + sxz * uy - 2.0 * ux * uy * uz;
let inv_cs2 = 1.0 / CS2;
let inv_2cs4 = 1.0 / (2.0 * CS2 * CS2);
let cs6 = CS2 * CS2 * CS2;
let k3 = 3.0 / (2.0 * cs6);
let k6 = 6.0 / (2.0 * cs6);
let mut f = [0.0; 27];
for i in 0..27 {
let c = &D3Q27_C[i];
let cu = (c[0] as f64) * ux + (c[1] as f64) * uy + (c[2] as f64) * uz;
let hs = h2(c, 0, 0) * sxx
+ h2(c, 1, 1) * syy
+ h2(c, 2, 2) * szz
+ 2.0 * (h2(c, 0, 1) * sxy + h2(c, 0, 2) * sxz + h2(c, 1, 2) * syz);
let h3s = k3
* (h3(c, 0, 0, 1) * a_xxy
+ h3(c, 0, 1, 1) * a_xyy
+ h3(c, 0, 0, 2) * a_xxz
+ h3(c, 0, 2, 2) * a_xzz
+ h3(c, 1, 1, 2) * a_yyz
+ h3(c, 1, 2, 2) * a_yzz)
+ k6 * h3(c, 0, 1, 2) * a_xyz;
f[i] = m.rho * D3Q27_W[i] * (1.0 + cu * inv_cs2 + hs * inv_2cs4 + h3s);
}
f
}
pub fn moments_d2q9(f: &[f64; 9]) -> Moments2d {
let rho: f64 = f.iter().sum();
let mut mom = [0.0; 2];
let mut pi = [0.0; 3]; for i in 0..9 {
let c = &D2Q9_C[i];
mom[0] += f[i] * c[0] as f64;
mom[1] += f[i] * c[1] as f64;
pi[0] += f[i] * (c[0] * c[0]) as f64;
pi[1] += f[i] * (c[1] * c[1]) as f64;
pi[2] += f[i] * (c[0] * c[1]) as f64;
}
let inv = 1.0 / rho;
Moments2d {
rho,
u: [mom[0] * inv, mom[1] * inv],
s: [pi[0] * inv - CS2, pi[1] * inv - CS2, pi[2] * inv],
}
}
pub fn moments_d3q27(f: &[f64; 27]) -> Moments3d {
let rho: f64 = f.iter().sum();
let mut mom = [0.0; 3];
let mut pi = [0.0; 6]; for i in 0..27 {
let c = &D3Q27_C[i];
for a in 0..3 {
mom[a] += f[i] * c[a] as f64;
}
pi[0] += f[i] * (c[0] * c[0]) as f64;
pi[1] += f[i] * (c[1] * c[1]) as f64;
pi[2] += f[i] * (c[2] * c[2]) as f64;
pi[3] += f[i] * (c[0] * c[1]) as f64;
pi[4] += f[i] * (c[0] * c[2]) as f64;
pi[5] += f[i] * (c[1] * c[2]) as f64;
}
let inv = 1.0 / rho;
Moments3d {
rho,
u: [mom[0] * inv, mom[1] * inv, mom[2] * inv],
s: [
pi[0] * inv - CS2,
pi[1] * inv - CS2,
pi[2] * inv - CS2,
pi[3] * inv,
pi[4] * inv,
pi[5] * inv,
],
}
}
pub fn omega(viscosity: f64) -> f64 {
1.0 / (3.0 * viscosity + 0.5)
}
pub fn collide_d2q9(m: &Moments2d, viscosity: f64, force: [f64; 2]) -> Moments2d {
let om = omega(viscosity);
let rho = m.rho;
let (fx, fy) = (force[0], force[1]);
let ux = m.u[0];
let uy = m.u[1];
let (sxx, syy, sxy) = (m.s[0], m.s[1], m.s[2]);
let pixx = rho * (sxx + CS2);
let piyy = rho * (syy + CS2);
let pixy = rho * sxy;
let ru2 = rho * ux * ux;
let rv2 = rho * uy * uy;
let dev = (pixx - piyy) / 2.0;
let pixy_n = (1.0 - om) * pixy + om * rho * ux * uy + (1.0 - 0.5 * om) * (fy * ux + fx * uy);
let pixx_n = rho * CS2
+ dev * (1.0 - om)
+ (1.0 + om) / 2.0 * ru2
+ (1.0 - om) / 2.0 * rv2
+ fx * ux
+ (1.0 - om) / 2.0 * (fx * ux - fy * uy);
let piyy_n = rho * CS2 - dev * (1.0 - om)
+ (1.0 + om) / 2.0 * rv2
+ (1.0 - om) / 2.0 * ru2
+ fy * uy
+ (1.0 - om) / 2.0 * (fy * uy - fx * ux);
let inv = 1.0 / rho;
Moments2d {
rho,
u: [ux + 0.5 * fx * inv, uy + 0.5 * fy * inv],
s: [pixx_n * inv - CS2, piyy_n * inv - CS2, pixy_n * inv],
}
}