use crate::error::{IntegrateError, IntegrateResult as Result};
use scirs2_core::ndarray::Array2;
use super::super::core::FluidBoundaryCondition;
pub fn apply_boundary_conditions_2d(
u: &mut Array2<f64>,
v: &mut Array2<f64>,
bc_x: (FluidBoundaryCondition, FluidBoundaryCondition),
bc_y: (FluidBoundaryCondition, FluidBoundaryCondition),
) -> Result<()> {
let (ny, nx) = u.dim();
apply_x_boundary_left(u, v, bc_x.0, ny)?;
apply_x_boundary_right(u, v, bc_x.1, ny, nx)?;
apply_y_boundary_bottom(u, v, bc_y.0, nx)?;
apply_y_boundary_top(u, v, bc_y.1, nx, ny)?;
Ok(())
}
fn apply_x_boundary_left(
u: &mut Array2<f64>,
v: &mut Array2<f64>,
bc: FluidBoundaryCondition,
ny: usize,
) -> Result<()> {
match bc {
FluidBoundaryCondition::NoSlip => {
for j in 0..ny {
u[[j, 0]] = 0.0;
v[[j, 0]] = 0.0;
}
}
FluidBoundaryCondition::FreeSlip => {
for j in 0..ny {
u[[j, 0]] = u[[j, 1]]; v[[j, 0]] = 0.0; }
}
FluidBoundaryCondition::Periodic => {
for j in 0..ny {
u[[j, 0]] = u[[j, u.dim().1 - 2]];
v[[j, 0]] = v[[j, v.dim().1 - 2]];
}
}
FluidBoundaryCondition::Inflow(u_in, v_in) => {
for j in 0..ny {
u[[j, 0]] = u_in;
v[[j, 0]] = v_in;
}
}
FluidBoundaryCondition::Outflow => {
for j in 0..ny {
u[[j, 0]] = u[[j, 1]]; v[[j, 0]] = v[[j, 1]];
}
}
}
Ok(())
}
fn apply_x_boundary_right(
u: &mut Array2<f64>,
v: &mut Array2<f64>,
bc: FluidBoundaryCondition,
ny: usize,
nx: usize,
) -> Result<()> {
match bc {
FluidBoundaryCondition::NoSlip => {
for j in 0..ny {
u[[j, nx - 1]] = 0.0;
v[[j, nx - 1]] = 0.0;
}
}
FluidBoundaryCondition::FreeSlip => {
for j in 0..ny {
u[[j, nx - 1]] = u[[j, nx - 2]]; v[[j, nx - 1]] = 0.0; }
}
FluidBoundaryCondition::Periodic => {
for j in 0..ny {
u[[j, nx - 1]] = u[[j, 1]];
v[[j, nx - 1]] = v[[j, 1]];
}
}
FluidBoundaryCondition::Inflow(u_in, v_in) => {
for j in 0..ny {
u[[j, nx - 1]] = u_in;
v[[j, nx - 1]] = v_in;
}
}
FluidBoundaryCondition::Outflow => {
for j in 0..ny {
u[[j, nx - 1]] = u[[j, nx - 2]]; v[[j, nx - 1]] = v[[j, nx - 2]];
}
}
}
Ok(())
}
fn apply_y_boundary_bottom(
u: &mut Array2<f64>,
v: &mut Array2<f64>,
bc: FluidBoundaryCondition,
nx: usize,
) -> Result<()> {
match bc {
FluidBoundaryCondition::NoSlip => {
for i in 1..nx - 1 {
u[[0, i]] = 0.0;
v[[0, i]] = 0.0;
}
}
FluidBoundaryCondition::FreeSlip => {
for i in 1..nx - 1 {
u[[0, i]] = 0.0; v[[0, i]] = v[[1, i]]; }
}
FluidBoundaryCondition::Periodic => {
for i in 1..nx - 1 {
u[[0, i]] = u[[u.dim().0 - 2, i]];
v[[0, i]] = v[[v.dim().0 - 2, i]];
}
}
FluidBoundaryCondition::Inflow(u_in, v_in) => {
for i in 1..nx - 1 {
u[[0, i]] = u_in;
v[[0, i]] = v_in;
}
}
FluidBoundaryCondition::Outflow => {
for i in 1..nx - 1 {
u[[0, i]] = u[[1, i]]; v[[0, i]] = v[[1, i]];
}
}
}
Ok(())
}
fn apply_y_boundary_top(
u: &mut Array2<f64>,
v: &mut Array2<f64>,
bc: FluidBoundaryCondition,
nx: usize,
ny: usize,
) -> Result<()> {
match bc {
FluidBoundaryCondition::NoSlip => {
for i in 1..nx - 1 {
u[[ny - 1, i]] = 0.0;
v[[ny - 1, i]] = 0.0;
}
}
FluidBoundaryCondition::FreeSlip => {
for i in 1..nx - 1 {
u[[ny - 1, i]] = 0.0; v[[ny - 1, i]] = v[[ny - 2, i]]; }
}
FluidBoundaryCondition::Periodic => {
for i in 1..nx - 1 {
u[[ny - 1, i]] = u[[1, i]];
v[[ny - 1, i]] = v[[1, i]];
}
}
FluidBoundaryCondition::Inflow(u_in, v_in) => {
for i in 1..nx - 1 {
u[[ny - 1, i]] = u_in;
v[[ny - 1, i]] = v_in;
}
}
FluidBoundaryCondition::Outflow => {
for i in 1..nx - 1 {
u[[ny - 1, i]] = u[[ny - 2, i]]; v[[ny - 1, i]] = v[[ny - 2, i]];
}
}
}
Ok(())
}
pub fn apply_pressure_boundary_conditions(pressure: &mut Array2<f64>) -> Result<()> {
let (ny, nx) = pressure.dim();
for j in 0..ny {
pressure[[j, 0]] = pressure[[j, 1]];
pressure[[j, nx - 1]] = pressure[[j, nx - 2]];
}
for i in 0..nx {
pressure[[0, i]] = pressure[[1, i]];
pressure[[ny - 1, i]] = pressure[[ny - 2, i]];
}
Ok(())
}
pub fn apply_wall_velocity_conditions(
u: &mut Array2<f64>,
v: &mut Array2<f64>,
wall_velocities: (
Option<(f64, f64)>,
Option<(f64, f64)>,
Option<(f64, f64)>,
Option<(f64, f64)>,
),
) -> Result<()> {
let (ny, nx) = u.dim();
if let Some((u_wall, v_wall)) = wall_velocities.0 {
for j in 0..ny {
u[[j, 0]] = u_wall;
v[[j, 0]] = v_wall;
}
}
if let Some((u_wall, v_wall)) = wall_velocities.1 {
for j in 0..ny {
u[[j, nx - 1]] = u_wall;
v[[j, nx - 1]] = v_wall;
}
}
if let Some((u_wall, v_wall)) = wall_velocities.2 {
for i in 0..nx {
u[[0, i]] = u_wall;
v[[0, i]] = v_wall;
}
}
if let Some((u_wall, v_wall)) = wall_velocities.3 {
for i in 0..nx {
u[[ny - 1, i]] = u_wall;
v[[ny - 1, i]] = v_wall;
}
}
Ok(())
}
pub fn apply_periodic_conditions(
u: &mut Array2<f64>,
v: &mut Array2<f64>,
periodic_x: bool,
periodic_y: bool,
) -> Result<()> {
let (ny, nx) = u.dim();
if periodic_x {
for j in 0..ny {
u[[j, 0]] = u[[j, nx - 2]];
u[[j, nx - 1]] = u[[j, 1]];
v[[j, 0]] = v[[j, nx - 2]];
v[[j, nx - 1]] = v[[j, 1]];
}
}
if periodic_y {
for i in 0..nx {
u[[0, i]] = u[[ny - 2, i]];
u[[ny - 1, i]] = u[[1, i]];
v[[0, i]] = v[[ny - 2, i]];
v[[ny - 1, i]] = v[[1, i]];
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use scirs2_core::ndarray::Array2;
#[test]
fn test_no_slip_boundary_conditions() {
let mut u = Array2::ones((5, 5));
let mut v = Array2::ones((5, 5));
let bc_x = (
FluidBoundaryCondition::NoSlip,
FluidBoundaryCondition::NoSlip,
);
let bc_y = (
FluidBoundaryCondition::NoSlip,
FluidBoundaryCondition::NoSlip,
);
apply_boundary_conditions_2d(&mut u, &mut v, bc_x, bc_y).expect("Operation failed");
for i in 0..5 {
assert_eq!(u[[0, i]], 0.0); assert_eq!(u[[4, i]], 0.0); assert_eq!(v[[0, i]], 0.0); assert_eq!(v[[4, i]], 0.0); }
for j in 0..5 {
assert_eq!(u[[j, 0]], 0.0); assert_eq!(u[[j, 4]], 0.0); assert_eq!(v[[j, 0]], 0.0); assert_eq!(v[[j, 4]], 0.0); }
}
#[test]
fn test_pressure_boundary_conditions() {
let mut pressure = Array2::from_shape_fn((5, 5), |(i, j)| (i + j) as f64);
let original_interior = pressure[[2, 2]];
apply_pressure_boundary_conditions(&mut pressure).expect("Operation failed");
assert_eq!(pressure[[2, 2]], original_interior);
assert_eq!(pressure[[0, 2]], pressure[[1, 2]]); assert_eq!(pressure[[4, 2]], pressure[[3, 2]]); assert_eq!(pressure[[2, 0]], pressure[[2, 1]]); assert_eq!(pressure[[2, 4]], pressure[[2, 3]]); }
#[test]
fn test_inflow_boundary_conditions() {
let mut u = Array2::zeros((5, 5));
let mut v = Array2::zeros((5, 5));
let bc_x = (
FluidBoundaryCondition::Inflow(1.0, 0.5),
FluidBoundaryCondition::Outflow,
);
let bc_y = (
FluidBoundaryCondition::NoSlip,
FluidBoundaryCondition::NoSlip,
);
apply_boundary_conditions_2d(&mut u, &mut v, bc_x, bc_y).expect("Operation failed");
for j in 0..5 {
assert_eq!(u[[j, 0]], 1.0);
assert_eq!(v[[j, 0]], 0.5);
}
}
}