///|
/// Common local boundary schemes.
pub(all) enum BoundaryKind {
NoSlip
VelocityInlet
PressureOutlet
PeriodicX
PeriodicY
Symmetry
} derive(Debug, Eq)
///|
/// Parameters for one boundary patch.
pub(all) struct BoundarySpec {
kind : BoundaryKind
value_x : Double
value_y : Double
density : Double
} derive(Debug)
///|
/// Construct a no-slip patch.
pub fn BoundarySpec::no_slip() -> BoundarySpec {
{ kind: NoSlip, value_x: 0.0, value_y: 0.0, density: 1.0 }
}
///|
/// Construct a Zou/He velocity patch.
pub fn BoundarySpec::velocity(
value_x~ : Double,
value_y~ : Double,
density? : Double = 1.0,
) -> BoundarySpec {
{ kind: VelocityInlet, value_x, value_y, density }
}
///|
/// Construct a Zou/He pressure patch.
pub fn BoundarySpec::pressure(
density~ : Double,
value_x? : Double = 0.0,
value_y? : Double = 0.0,
) -> BoundarySpec {
{ kind: PressureOutlet, value_x, value_y, density }
}
///|
/// Reconstruct a velocity boundary from its requested equilibrium moments.
pub fn apply_velocity_boundary(
distribution : ArrayView[Double],
rho~ : Double,
ux~ : Double,
uy~ : Double,
) -> Array[Double] {
let requested = equilibrium_distribution(rho~, ux~, uy~)
let result = Array::make(q, 0.0)
for d in 0.. Array[Double] {
apply_velocity_boundary(distribution, rho=density, ux~, uy~)
}
///|
/// Apply a local boundary specification.
pub fn apply_boundary(
distribution : ArrayView[Double],
spec~ : BoundarySpec,
) -> Array[Double] {
match spec.kind {
NoSlip =>
collide_distribution(
distribution,
rho=spec.density,
ux=0.0,
uy=0.0,
model=Bgk(1.0),
)
VelocityInlet =>
apply_velocity_boundary(
distribution,
rho=spec.density,
ux=spec.value_x,
uy=spec.value_y,
)
PressureOutlet =>
apply_pressure_boundary(
distribution,
density=spec.density,
ux=spec.value_x,
uy=spec.value_y,
)
PeriodicX | PeriodicY | Symmetry => distribution.to_owned()
}
}
///|
/// Return the opposite direction used by a bounce-back link.
pub fn bounce_direction(direction : Int) -> Int {
if direction >= 0 && direction < q {
opposite[direction]
} else {
0
}
}
///|
/// Return a periodic coordinate for a lattice extent.
pub fn periodic_coordinate(value : Int, extent : Int) -> Int {
wrap_coordinate(value, extent)
}
///|
/// Compute the local momentum exchange of a reflected population.
pub fn momentum_exchange(direction~ : Int, population~ : Double) -> Point {
if direction < 0 || direction >= q {
Point::new(x=0.0, y=0.0)
} else {
Point::new(
x=2.0 * population * cx[direction].to_double(),
y=2.0 * population * cy[direction].to_double(),
)
}
}