///|
/// Collision operators supported by the reusable solver.
pub(all) enum CollisionModel {
Bgk(Double)
Regularized(Double)
Mrt(Double)
} derive(Debug)
///|
/// Construct a BGK collision model.
pub fn CollisionModel::bgk(omega~ : Double) -> CollisionModel {
Bgk(omega)
}
///|
/// Construct a regularized collision model.
pub fn CollisionModel::regularized(omega~ : Double) -> CollisionModel {
Regularized(omega)
}
///|
/// Construct a two-relaxation-time MRT model.
pub fn CollisionModel::mrt(omega~ : Double) -> CollisionModel {
Mrt(omega)
}
///|
/// Read the shear relaxation parameter from a collision model.
pub fn CollisionModel::omega(self : CollisionModel) -> Double {
match self {
Bgk(omega) => omega
Regularized(omega) => omega
Mrt(omega) => omega
}
}
///|
/// Outer-boundary behavior for the advanced solver.
pub(all) enum BoundaryMode {
BounceBack
Periodic
Open
} derive(Debug, Eq)
///|
/// Configuration shared by collision, streaming, and stability checks.
pub(all) struct SimulationOptions {
model : CollisionModel
boundary : BoundaryMode
force_x : Double
force_y : Double
density_floor : Double
max_mach : Double
} derive(Debug)
///|
/// Build conservative solver options.
pub fn SimulationOptions::new(
model~ : CollisionModel,
boundary? : BoundaryMode = BounceBack,
force_x? : Double = 0.0,
force_y? : Double = 0.0,
density_floor? : Double = 0.0000000001,
max_mach? : Double = 0.35,
) -> SimulationOptions {
{ model, boundary, force_x, force_y, density_floor, max_mach }
}
///|
/// Configuration errors are explicit so callers can reject unsafe runs.
pub(all) enum ValidationError {
InvalidRelaxation(Double)
InvalidDomain(Size)
InvalidDensityFloor(Double)
InvalidMachLimit(Double)
} derive(Debug)
///|
/// Validate solver options before allocating a simulation.
pub fn validate_options(
options : SimulationOptions,
) -> Result[Unit, ValidationError] {
if options.model.omega() <= 0.0 || options.model.omega() >= 2.0 {
Err(InvalidRelaxation(options.model.omega()))
} else if options.density_floor <= 0.0 {
Err(InvalidDensityFloor(options.density_floor))
} else if options.max_mach <= 0.0 {
Err(InvalidMachLimit(options.max_mach))
} else {
Ok(())
}
}
///|
/// Validate a rectangular domain size.
pub fn validate_size(size : Size) -> Result[Unit, ValidationError] {
if size.width <= 0 || size.height <= 0 {
Err(InvalidDomain(size))
} else {
Ok(())
}
}