Add Evaluator for defining IC/BC in json config

This commit is contained in:
2021-06-29 17:55:19 +02:00
parent 300f6a34e5
commit b5360af6de
12 changed files with 793 additions and 96 deletions

97
euler/src/eval.rs Normal file
View File

@@ -0,0 +1,97 @@
//! Traits for evaluating initial conditions, exact solutions, or boundary conditions
use super::Float;
use super::GAMMA;
use ndarray::{azip, ArrayView, ArrayViewMut, Dimension};
pub trait Evaluator<D: Dimension>: Send + Sync {
fn evaluate(
&self,
t: Float,
x: ArrayView<Float, D>,
y: ArrayView<Float, D>,
rho: ArrayViewMut<Float, D>,
rhou: ArrayViewMut<Float, D>,
rhov: ArrayViewMut<Float, D>,
e: ArrayViewMut<Float, D>,
);
}
/// Necessary to avoid specialisation of `Evaluator` trait for items
/// that could implement both this and `Evaluator`
#[derive(Clone, Debug)]
pub struct EvaluatorPressureWrapper<'a, D: Dimension, E: EvaluatorPressure<D>>(
&'a E,
std::marker::PhantomData<D>,
);
impl<'a, D: Dimension, E: EvaluatorPressure<D>> EvaluatorPressureWrapper<'a, D, E> {
pub fn new(e: &'a E) -> Self {
Self(e, std::marker::PhantomData)
}
}
pub trait EvaluatorPressure<D: Dimension>: Send + Sync {
fn rho(
&self,
t: Float,
x: ArrayView<Float, D>,
y: ArrayView<Float, D>,
out: ArrayViewMut<Float, D>,
);
fn u(
&self,
t: Float,
x: ArrayView<Float, D>,
y: ArrayView<Float, D>,
rho: ArrayView<Float, D>,
out: ArrayViewMut<Float, D>,
);
fn v(
&self,
t: Float,
x: ArrayView<Float, D>,
y: ArrayView<Float, D>,
rho: ArrayView<Float, D>,
out: ArrayViewMut<Float, D>,
);
fn p(
&self,
t: Float,
x: ArrayView<Float, D>,
y: ArrayView<Float, D>,
rho: ArrayView<Float, D>,
u: ArrayView<Float, D>,
v: ArrayView<Float, D>,
out: ArrayViewMut<Float, D>,
);
}
impl<'a, D: Dimension, BP: EvaluatorPressure<D>> Evaluator<D>
for EvaluatorPressureWrapper<'a, D, BP>
{
fn evaluate(
&self,
t: Float,
x: ArrayView<Float, D>,
y: ArrayView<Float, D>,
mut rho: ArrayViewMut<Float, D>,
mut rhou: ArrayViewMut<Float, D>,
mut rhov: ArrayViewMut<Float, D>,
mut e: ArrayViewMut<Float, D>,
) {
let eva = &self.0;
eva.rho(t, x.view(), y.view(), rho.view_mut());
eva.u(t, x.view(), y.view(), rho.view(), rhou.view_mut());
eva.v(t, x.view(), y.view(), rho.view(), rhov.view_mut());
eva.p(t, x, y, rho.view(), rhou.view(), rhov.view(), e.view_mut());
azip!((rho in &rho, u in &rhou, v in &rhov, e in &mut e) {
let p = *e;
*e = p / (GAMMA - 1.0) + rho * (u*u + v*v) / 2.0;
});
azip!((rho in &rho, rhou in &mut rhou) *rhou /= rho);
azip!((rho in &rho, rhov in &mut rhov) *rhov /= rho);
}
}

View File

@@ -6,6 +6,8 @@ use sbp::operators::{InterpolationOperator, SbpOperator2d, UpwindOperator2d};
use sbp::utils::Direction;
use sbp::Float;
pub mod eval;
mod vortex;
pub use vortex::{vortex, VortexParameters, Vortice};
@@ -691,11 +693,25 @@ pub enum BoundaryCharacteristic {
This,
Grid(usize),
Vortex(VortexParameters),
Eval(std::sync::Arc<dyn eval::Evaluator<ndarray::Ix1>>),
// Vortices(Vec<VortexParameters>),
Interpolate(usize, Box<dyn InterpolationOperator>),
MultiGrid(Vec<(usize, usize, usize)>),
}
impl std::fmt::Debug for BoundaryCharacteristic {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::This => write!(f, "This"),
Self::Grid(g) => write!(f, "Grid({})", g),
Self::Vortex(vp) => write!(f, "{:?}", vp),
Self::Eval(_) => write!(f, "Eval"),
Self::Interpolate(_, _) => write!(f, "Interpolate"),
Self::MultiGrid(m) => write!(f, "Multigrid: {:?}", m),
}
}
}
pub type BoundaryTerms<'a> = Direction<ArrayView2<'a, Float>>;
pub type BoundaryCharacteristics = Direction<BoundaryCharacteristic>;
@@ -708,6 +724,7 @@ fn boundary_extractor<'a>(
north: match &bc.north {
BoundaryCharacteristic::This => field.south(),
BoundaryCharacteristic::Vortex(_params) => todo!(),
BoundaryCharacteristic::Eval(_) => todo!(),
BoundaryCharacteristic::Grid(_)
| BoundaryCharacteristic::Interpolate(_, _)
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
@@ -715,6 +732,7 @@ fn boundary_extractor<'a>(
south: match &bc.south {
BoundaryCharacteristic::This => field.north(),
BoundaryCharacteristic::Vortex(_params) => todo!(),
BoundaryCharacteristic::Eval(_) => todo!(),
BoundaryCharacteristic::Grid(_)
| BoundaryCharacteristic::Interpolate(_, _)
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
@@ -722,6 +740,7 @@ fn boundary_extractor<'a>(
west: match &bc.west {
BoundaryCharacteristic::This => field.east(),
BoundaryCharacteristic::Vortex(_params) => todo!(),
BoundaryCharacteristic::Eval(_) => todo!(),
BoundaryCharacteristic::Grid(_)
| BoundaryCharacteristic::Interpolate(_, _)
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
@@ -729,6 +748,7 @@ fn boundary_extractor<'a>(
east: match &bc.east {
BoundaryCharacteristic::This => field.west(),
BoundaryCharacteristic::Vortex(_params) => todo!(),
BoundaryCharacteristic::Eval(_) => todo!(),
BoundaryCharacteristic::Grid(_)
| BoundaryCharacteristic::Interpolate(_, _)
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
@@ -748,11 +768,6 @@ fn boundary_extract<'a>(
match bc {
BoundaryCharacteristic::This => seldir(field),
BoundaryCharacteristic::Grid(g) => seldir(&fields[*g]),
BoundaryCharacteristic::Vortex(v) => {
let field = eb.unwrap();
vortexify(field.view_mut(), grid, v, time);
field.view()
}
BoundaryCharacteristic::Interpolate(g, operator) => {
let to = eb.unwrap();
let fine2coarse = field.nx() < fields[*g].nx();
@@ -785,6 +800,24 @@ fn boundary_extract<'a>(
}
to.view()
}
BoundaryCharacteristic::Vortex(v) => {
let field = eb.unwrap();
vortexify(field.view_mut(), grid, v, time);
field.view()
}
BoundaryCharacteristic::Eval(expr) => {
let field = eb.unwrap();
let (x, y) = grid;
let mut fiter = field.outer_iter_mut();
let (rho, rhou, rhov, e) = (
fiter.next().unwrap(),
fiter.next().unwrap(),
fiter.next().unwrap(),
fiter.next().unwrap(),
);
expr.evaluate(time, x, y, rho, rhou, rhov, e);
field.view()
}
}
}
@@ -864,6 +897,7 @@ impl BoundaryStorage {
Self {
north: match bt.north() {
BoundaryCharacteristic::Vortex(_)
| BoundaryCharacteristic::Eval(_)
| BoundaryCharacteristic::Interpolate(_, _)
| BoundaryCharacteristic::MultiGrid(_) => {
Some(ndarray::Array2::zeros((4, grid.nx())))
@@ -872,6 +906,7 @@ impl BoundaryStorage {
},
south: match bt.south() {
BoundaryCharacteristic::Vortex(_)
| BoundaryCharacteristic::Eval(_)
| BoundaryCharacteristic::Interpolate(_, _)
| BoundaryCharacteristic::MultiGrid(_) => {
Some(ndarray::Array2::zeros((4, grid.nx())))
@@ -880,6 +915,7 @@ impl BoundaryStorage {
},
east: match bt.east() {
BoundaryCharacteristic::Vortex(_)
| BoundaryCharacteristic::Eval(_)
| BoundaryCharacteristic::Interpolate(_, _)
| BoundaryCharacteristic::MultiGrid(_) => {
Some(ndarray::Array2::zeros((4, grid.ny())))
@@ -888,6 +924,7 @@ impl BoundaryStorage {
},
west: match bt.west() {
BoundaryCharacteristic::Vortex(_)
| BoundaryCharacteristic::Eval(_)
| BoundaryCharacteristic::Interpolate(_, _)
| BoundaryCharacteristic::MultiGrid(_) => {
Some(ndarray::Array2::zeros((4, grid.ny())))