use burn::{
Tensor,
prelude::{
Backend,
Bool,
},
};
use crate::kits::sims::lbm::d2q9::{
LbmTables,
OmegaSource,
RelaxationParam,
moments,
relaxed_sum,
thermal_equilibrium,
with_spherical_reflection,
};
pub fn bgk_collision<B: Backend, S: Into<OmegaSource<B>>>(
dist: Tensor<B, 4>,
relaxation: S,
correction: Option<f64>,
lbm_tables: &LbmTables<B>,
) -> Tensor<B, 4> {
let (source_rho, u) = moments(dist.clone(), lbm_tables);
let eq_dist = thermal_equilibrium(source_rho.clone(), u, lbm_tables);
relaxed_sum(dist, eq_dist, relaxation, correction)
}
pub fn bgk_collision_with_spherical_reflection<B: Backend>(
dist: Tensor<B, 4>,
solid_mask: Tensor<B, 2, Bool>,
relaxation: RelaxationParam,
correction: Option<f64>,
lbm_tables: &LbmTables<B>,
) -> Tensor<B, 4> {
with_spherical_reflection(
dist.clone(),
bgk_collision(dist, relaxation, correction, lbm_tables),
solid_mask,
)
}
#[cfg(test)]
mod tests {
use burn::{
Tensor,
tensor::{
DType::F32,
Distribution,
Tolerance,
},
};
use super::*;
use crate::{
kits::sims::lbm::d2q9::{
LbmTables,
RelaxationParam,
density,
},
support::testing::PerfTestBackend,
};
#[test]
fn test_collision_invariants() {
type B = PerfTestBackend;
let device = Default::default();
let dtype = F32;
let dist = Tensor::<B, 4>::random([20, 20, 3, 3], Distribution::Uniform(0.1, 1.0), &device)
.cast(dtype);
let rho = density(dist.clone());
let lbm_tables = LbmTables::for_dist(&dist);
let col_dist = bgk_collision(dist.clone(), RelaxationParam::Omega(0.5), None, &lbm_tables);
density(col_dist.clone())
.to_data()
.assert_approx_eq::<f32>(&rho.clone().to_data(), Tolerance::default());
{
let col_dist = bgk_collision(
dist.clone(),
RelaxationParam::Omega(0.5),
Some(1.2),
&lbm_tables,
);
density(col_dist.clone())
.to_data()
.assert_approx_eq::<f32>(&(rho * 1.2).to_data(), Tolerance::default());
}
}
}