lib.rs 9.74 KiB
#![feature(concat_idents)]
mod rust_cfd;
mod setup;
use clap::Parser;
pub use crate::setup::*;
use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo, HerculesMutBox, HerculesMutBoxTo};
juno_build::juno!("euler");
juno_build::juno!("pre_euler");
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
pub struct CFDInputs {
pub data_file: String,
pub iterations: usize,
pub block_size: usize,
#[clap(short = None, long = Some("pre-euler"))]
pub pre_euler: bool,
}
fn run_euler(
nelr: usize,
iterations: usize,
mut variables: Variables,
areas: &[f32],
elements_surrounding_elements: &[i32],
normals: &Normals,
ff_variable: &Variable,
ff_fc_density_energy: &Float3,
ff_fc_momentum_x: &Float3,
ff_fc_momentum_y: &Float3,
ff_fc_momentum_z: &Float3,
) -> Variables {
let mut v_density = HerculesMutBox::from(variables.density.as_mut_slice());
let mut v_momentum_x = HerculesMutBox::from(variables.momentum.x.as_mut_slice());
let mut v_momentum_y = HerculesMutBox::from(variables.momentum.y.as_mut_slice());
let mut v_momentum_z = HerculesMutBox::from(variables.momentum.z.as_mut_slice());
let mut v_energy = HerculesMutBox::from(variables.energy.as_mut_slice());
let areas = HerculesImmBox::from(areas);
let elements_surrounding_elements = HerculesImmBox::from(elements_surrounding_elements);
let normals_x = HerculesImmBox::from(normals.x.as_slice());
let normals_y = HerculesImmBox::from(normals.y.as_slice());
let normals_z = HerculesImmBox::from(normals.z.as_slice());
let mut runner = runner!(euler);
let (density, momentum_x, momentum_y, momentum_z, energy) = async_std::task::block_on(async {
runner
.run(
nelr as u64,
iterations as u64,
v_density.to(),
v_momentum_x.to(),
v_momentum_y.to(),
v_momentum_z.to(),
v_energy.to(),
areas.to(),
elements_surrounding_elements.to(),
normals_x.to(),
normals_y.to(),
normals_z.to(),
ff_variable.density,
ff_variable.momentum.x,
ff_variable.momentum.y,
ff_variable.momentum.z,
ff_variable.energy,
ff_fc_density_energy.x,
ff_fc_density_energy.y,
ff_fc_density_energy.z,
ff_fc_momentum_x.x,
ff_fc_momentum_x.y,
ff_fc_momentum_x.z,
ff_fc_momentum_y.x,
ff_fc_momentum_y.y,
ff_fc_momentum_y.z,
ff_fc_momentum_z.x,
ff_fc_momentum_z.y,
ff_fc_momentum_z.z,
)
.await
});
Variables {
density: AlignedSlice::from_slice(HerculesMutBox::from(density).as_slice()),
momentum: Momentum {
x: AlignedSlice::from_slice(HerculesMutBox::from(momentum_x).as_slice()),
y: AlignedSlice::from_slice(HerculesMutBox::from(momentum_y).as_slice()),
z: AlignedSlice::from_slice(HerculesMutBox::from(momentum_z).as_slice()),
},
energy: AlignedSlice::from_slice(HerculesMutBox::from(energy).as_slice()),
}
}
fn run_pre_euler(
nelr: usize,
iterations: usize,
mut variables: Variables,
areas: &[f32],
elements_surrounding_elements: &[i32],
normals: &Normals,
ff_variable: &Variable,
ff_fc_density_energy: &Float3,
ff_fc_momentum_x: &Float3,
ff_fc_momentum_y: &Float3,
ff_fc_momentum_z: &Float3,
) -> Variables {
let mut v_density = HerculesMutBox::from(variables.density.as_mut_slice());
let mut v_momentum_x = HerculesMutBox::from(variables.momentum.x.as_mut_slice());
let mut v_momentum_y = HerculesMutBox::from(variables.momentum.y.as_mut_slice());
let mut v_momentum_z = HerculesMutBox::from(variables.momentum.z.as_mut_slice());
let mut v_energy = HerculesMutBox::from(variables.energy.as_mut_slice());
let areas = HerculesImmBox::from(areas);
let elements_surrounding_elements = HerculesImmBox::from(elements_surrounding_elements);
let normals_x = HerculesImmBox::from(normals.x.as_slice());
let normals_y = HerculesImmBox::from(normals.y.as_slice());
let normals_z = HerculesImmBox::from(normals.z.as_slice());
let mut runner = runner!(pre_euler);
let (density, momentum_x, momentum_y, momentum_z, energy) = async_std::task::block_on(async {
runner
.run(
nelr as u64,
iterations as u64,
v_density.to(),
v_momentum_x.to(),
v_momentum_y.to(),
v_momentum_z.to(),
v_energy.to(),
areas.to(),
elements_surrounding_elements.to(),
normals_x.to(),
normals_y.to(),
normals_z.to(),
ff_variable.density,
ff_variable.momentum.x,
ff_variable.momentum.y,
ff_variable.momentum.z,
ff_variable.energy,
ff_fc_density_energy.x,
ff_fc_density_energy.y,
ff_fc_density_energy.z,
ff_fc_momentum_x.x,
ff_fc_momentum_x.y,
ff_fc_momentum_x.z,
ff_fc_momentum_y.x,
ff_fc_momentum_y.y,
ff_fc_momentum_y.z,
ff_fc_momentum_z.x,
ff_fc_momentum_z.y,
ff_fc_momentum_z.z,
)
.await
});
Variables {
density: AlignedSlice::from_slice(HerculesMutBox::from(density).as_slice()),
momentum: Momentum {
x: AlignedSlice::from_slice(HerculesMutBox::from(momentum_x).as_slice()),
y: AlignedSlice::from_slice(HerculesMutBox::from(momentum_y).as_slice()),
z: AlignedSlice::from_slice(HerculesMutBox::from(momentum_z).as_slice()),
},
energy: AlignedSlice::from_slice(HerculesMutBox::from(energy).as_slice()),
}
}
fn compare_float(x: f32, y: f32) -> bool {
(x - y).abs() < 1e-5
}
fn compare_floats(xs: &Variables, ys: &Variables) -> bool {
let xs_density = xs.density.as_slice();
let xs_momentum_x = xs.momentum.x.as_slice();
let xs_momentum_y = xs.momentum.y.as_slice();
let xs_momentum_z = xs.momentum.z.as_slice();
let xs_energy = xs.energy.as_slice();
let ys_density = ys.density.as_slice();
let ys_momentum_x = ys.momentum.x.as_slice();
let ys_momentum_y = ys.momentum.y.as_slice();
let ys_momentum_z = ys.momentum.z.as_slice();
let ys_energy = ys.energy.as_slice();
xs_density.len() == ys_density.len()
&& xs_density
.iter()
.zip(ys_density.iter())
.all(|(x, y)| compare_float(*x, *y))
&& xs_momentum_x.len() == ys_momentum_x.len()
&& xs_momentum_x
.iter()
.zip(ys_momentum_x.iter())
.all(|(x, y)| compare_float(*x, *y))
&& xs_momentum_y.len() == ys_momentum_y.len()
&& xs_momentum_y
.iter()
.zip(ys_momentum_y.iter())
.all(|(x, y)| compare_float(*x, *y))
&& xs_momentum_z.len() == ys_momentum_z.len()
&& xs_momentum_z
.iter()
.zip(ys_momentum_z.iter())
.all(|(x, y)| compare_float(*x, *y))
&& xs_energy.len() == ys_energy.len()
&& xs_energy
.iter()
.zip(ys_energy.iter())
.all(|(x, y)| compare_float(*x, *y))
}
pub fn cfd_harness(args: CFDInputs) {
let CFDInputs {
data_file,
iterations,
block_size,
pre_euler,
} = args;
let FarFieldConditions {
ff_variable,
ff_fc_momentum_x,
ff_fc_momentum_y,
ff_fc_momentum_z,
ff_fc_density_energy,
} = set_far_field_conditions();
let GeometryData {
nelr,
areas,
elements_surrounding_elements,
normals,
} = read_domain_geometry(data_file, block_size);
let variables = initialize_variables(nelr, &ff_variable);
println!("Running CFD with nelr = {}.", nelr);
let res_juno = if pre_euler {
run_pre_euler(
nelr,
iterations,
variables.clone(),
areas.as_slice(),
elements_surrounding_elements.as_slice(),
&normals,
&ff_variable,
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
} else {
run_euler(
nelr,
iterations,
variables.clone(),
areas.as_slice(),
elements_surrounding_elements.as_slice(),
&normals,
&ff_variable,
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
};
let res_rust = if pre_euler {
rust_cfd::pre_euler(
nelr,
iterations,
variables,
areas.as_slice(),
elements_surrounding_elements.as_slice(),
&normals,
&ff_variable,
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
} else {
rust_cfd::euler(
nelr,
iterations,
variables,
areas.as_slice(),
elements_surrounding_elements.as_slice(),
&normals,
&ff_variable,
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
};
if !compare_floats(&res_juno, &res_rust) {
panic!("Mismatch in results");
}
}