Add Evaluator for defining IC/BC in json config
This commit is contained in:
parent
300f6a34e5
commit
b5360af6de
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ use sbp::operators::{InterpolationOperator, SbpOperator2d, UpwindOperator2d};
|
||||||
use sbp::utils::Direction;
|
use sbp::utils::Direction;
|
||||||
use sbp::Float;
|
use sbp::Float;
|
||||||
|
|
||||||
|
pub mod eval;
|
||||||
|
|
||||||
mod vortex;
|
mod vortex;
|
||||||
pub use vortex::{vortex, VortexParameters, Vortice};
|
pub use vortex::{vortex, VortexParameters, Vortice};
|
||||||
|
|
||||||
|
@ -691,11 +693,25 @@ pub enum BoundaryCharacteristic {
|
||||||
This,
|
This,
|
||||||
Grid(usize),
|
Grid(usize),
|
||||||
Vortex(VortexParameters),
|
Vortex(VortexParameters),
|
||||||
|
Eval(std::sync::Arc<dyn eval::Evaluator<ndarray::Ix1>>),
|
||||||
// Vortices(Vec<VortexParameters>),
|
// Vortices(Vec<VortexParameters>),
|
||||||
Interpolate(usize, Box<dyn InterpolationOperator>),
|
Interpolate(usize, Box<dyn InterpolationOperator>),
|
||||||
MultiGrid(Vec<(usize, usize, usize)>),
|
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 BoundaryTerms<'a> = Direction<ArrayView2<'a, Float>>;
|
||||||
pub type BoundaryCharacteristics = Direction<BoundaryCharacteristic>;
|
pub type BoundaryCharacteristics = Direction<BoundaryCharacteristic>;
|
||||||
|
|
||||||
|
@ -708,6 +724,7 @@ fn boundary_extractor<'a>(
|
||||||
north: match &bc.north {
|
north: match &bc.north {
|
||||||
BoundaryCharacteristic::This => field.south(),
|
BoundaryCharacteristic::This => field.south(),
|
||||||
BoundaryCharacteristic::Vortex(_params) => todo!(),
|
BoundaryCharacteristic::Vortex(_params) => todo!(),
|
||||||
|
BoundaryCharacteristic::Eval(_) => todo!(),
|
||||||
BoundaryCharacteristic::Grid(_)
|
BoundaryCharacteristic::Grid(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
|
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
|
||||||
|
@ -715,6 +732,7 @@ fn boundary_extractor<'a>(
|
||||||
south: match &bc.south {
|
south: match &bc.south {
|
||||||
BoundaryCharacteristic::This => field.north(),
|
BoundaryCharacteristic::This => field.north(),
|
||||||
BoundaryCharacteristic::Vortex(_params) => todo!(),
|
BoundaryCharacteristic::Vortex(_params) => todo!(),
|
||||||
|
BoundaryCharacteristic::Eval(_) => todo!(),
|
||||||
BoundaryCharacteristic::Grid(_)
|
BoundaryCharacteristic::Grid(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
|
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
|
||||||
|
@ -722,6 +740,7 @@ fn boundary_extractor<'a>(
|
||||||
west: match &bc.west {
|
west: match &bc.west {
|
||||||
BoundaryCharacteristic::This => field.east(),
|
BoundaryCharacteristic::This => field.east(),
|
||||||
BoundaryCharacteristic::Vortex(_params) => todo!(),
|
BoundaryCharacteristic::Vortex(_params) => todo!(),
|
||||||
|
BoundaryCharacteristic::Eval(_) => todo!(),
|
||||||
BoundaryCharacteristic::Grid(_)
|
BoundaryCharacteristic::Grid(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
|
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
|
||||||
|
@ -729,6 +748,7 @@ fn boundary_extractor<'a>(
|
||||||
east: match &bc.east {
|
east: match &bc.east {
|
||||||
BoundaryCharacteristic::This => field.west(),
|
BoundaryCharacteristic::This => field.west(),
|
||||||
BoundaryCharacteristic::Vortex(_params) => todo!(),
|
BoundaryCharacteristic::Vortex(_params) => todo!(),
|
||||||
|
BoundaryCharacteristic::Eval(_) => todo!(),
|
||||||
BoundaryCharacteristic::Grid(_)
|
BoundaryCharacteristic::Grid(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
|
| BoundaryCharacteristic::MultiGrid(_) => panic!("Only working on self grid"),
|
||||||
|
@ -748,11 +768,6 @@ fn boundary_extract<'a>(
|
||||||
match bc {
|
match bc {
|
||||||
BoundaryCharacteristic::This => seldir(field),
|
BoundaryCharacteristic::This => seldir(field),
|
||||||
BoundaryCharacteristic::Grid(g) => seldir(&fields[*g]),
|
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) => {
|
BoundaryCharacteristic::Interpolate(g, operator) => {
|
||||||
let to = eb.unwrap();
|
let to = eb.unwrap();
|
||||||
let fine2coarse = field.nx() < fields[*g].nx();
|
let fine2coarse = field.nx() < fields[*g].nx();
|
||||||
|
@ -785,6 +800,24 @@ fn boundary_extract<'a>(
|
||||||
}
|
}
|
||||||
to.view()
|
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 {
|
Self {
|
||||||
north: match bt.north() {
|
north: match bt.north() {
|
||||||
BoundaryCharacteristic::Vortex(_)
|
BoundaryCharacteristic::Vortex(_)
|
||||||
|
| BoundaryCharacteristic::Eval(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => {
|
| BoundaryCharacteristic::MultiGrid(_) => {
|
||||||
Some(ndarray::Array2::zeros((4, grid.nx())))
|
Some(ndarray::Array2::zeros((4, grid.nx())))
|
||||||
|
@ -872,6 +906,7 @@ impl BoundaryStorage {
|
||||||
},
|
},
|
||||||
south: match bt.south() {
|
south: match bt.south() {
|
||||||
BoundaryCharacteristic::Vortex(_)
|
BoundaryCharacteristic::Vortex(_)
|
||||||
|
| BoundaryCharacteristic::Eval(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => {
|
| BoundaryCharacteristic::MultiGrid(_) => {
|
||||||
Some(ndarray::Array2::zeros((4, grid.nx())))
|
Some(ndarray::Array2::zeros((4, grid.nx())))
|
||||||
|
@ -880,6 +915,7 @@ impl BoundaryStorage {
|
||||||
},
|
},
|
||||||
east: match bt.east() {
|
east: match bt.east() {
|
||||||
BoundaryCharacteristic::Vortex(_)
|
BoundaryCharacteristic::Vortex(_)
|
||||||
|
| BoundaryCharacteristic::Eval(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => {
|
| BoundaryCharacteristic::MultiGrid(_) => {
|
||||||
Some(ndarray::Array2::zeros((4, grid.ny())))
|
Some(ndarray::Array2::zeros((4, grid.ny())))
|
||||||
|
@ -888,6 +924,7 @@ impl BoundaryStorage {
|
||||||
},
|
},
|
||||||
west: match bt.west() {
|
west: match bt.west() {
|
||||||
BoundaryCharacteristic::Vortex(_)
|
BoundaryCharacteristic::Vortex(_)
|
||||||
|
| BoundaryCharacteristic::Eval(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => {
|
| BoundaryCharacteristic::MultiGrid(_) => {
|
||||||
Some(ndarray::Array2::zeros((4, grid.ny())))
|
Some(ndarray::Array2::zeros((4, grid.ny())))
|
||||||
|
|
|
@ -17,3 +17,4 @@ serde = { version = "1.0.115", features = ["derive"] }
|
||||||
json5 = "0.3.0"
|
json5 = "0.3.0"
|
||||||
indexmap = { version = "1.5.2", features = ["serde-1"] }
|
indexmap = { version = "1.5.2", features = ["serde-1"] }
|
||||||
argh = "0.1.4"
|
argh = "0.1.4"
|
||||||
|
evalexpr = "6.2.0"
|
||||||
|
|
|
@ -5,10 +5,6 @@
|
||||||
"operators": {
|
"operators": {
|
||||||
"xi": "upwind9",
|
"xi": "upwind9",
|
||||||
"eta": "upwind9h2"
|
"eta": "upwind9h2"
|
||||||
},
|
|
||||||
"boundary_conditions": {
|
|
||||||
"east": "vortex",
|
|
||||||
"west": "vortex"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid0": {
|
"grid0": {
|
||||||
|
@ -26,7 +22,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"integration_time": 2.0,
|
|
||||||
|
"initial_conditions": {
|
||||||
"vortex": {
|
"vortex": {
|
||||||
"vortices": [{
|
"vortices": [{
|
||||||
"x0": -1.0,
|
"x0": -1.0,
|
||||||
|
@ -36,4 +33,7 @@
|
||||||
}],
|
}],
|
||||||
"mach": 0.5
|
"mach": 0.5
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"boundary_conditions": "initial_conditions",
|
||||||
|
"integration_time": 2.0
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,6 @@
|
||||||
"operators": {
|
"operators": {
|
||||||
"xi": "upwind9",
|
"xi": "upwind9",
|
||||||
"eta": "upwind9"
|
"eta": "upwind9"
|
||||||
},
|
|
||||||
"boundary_conditions": {
|
|
||||||
"south": "vortex",
|
|
||||||
"north": "vortex",
|
|
||||||
"east": "vortex",
|
|
||||||
"west": "vortex"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid0": {
|
"grid0": {
|
||||||
|
@ -28,6 +22,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"integration_time": 2.0,
|
"integration_time": 2.0,
|
||||||
|
"initial_conditions": {
|
||||||
"vortex": {
|
"vortex": {
|
||||||
"vortices": [{
|
"vortices": [{
|
||||||
"x0": -1.0,
|
"x0": -1.0,
|
||||||
|
@ -37,4 +32,6 @@
|
||||||
}],
|
}],
|
||||||
"mach": 0.5
|
"mach": 0.5
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"boundary_conditions": "initial_conditions"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,6 @@
|
||||||
"operators": {
|
"operators": {
|
||||||
"xi": "upwind9",
|
"xi": "upwind9",
|
||||||
"eta": "upwind9"
|
"eta": "upwind9"
|
||||||
},
|
|
||||||
"boundary_conditions": {
|
|
||||||
"south": "vortex",
|
|
||||||
"north": "vortex",
|
|
||||||
"east": "vortex",
|
|
||||||
"west": "vortex"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid0": {
|
"grid0": {
|
||||||
|
@ -56,6 +50,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"integration_time": 2.0,
|
"integration_time": 2.0,
|
||||||
|
"initial_conditions": {
|
||||||
"vortex": {
|
"vortex": {
|
||||||
"vortices": [{
|
"vortices": [{
|
||||||
"x0": -1.0,
|
"x0": -1.0,
|
||||||
|
@ -65,4 +60,6 @@
|
||||||
}],
|
}],
|
||||||
"mach": 0.5
|
"mach": 0.5
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"boundary_conditions": "initial_conditions"
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"integration_time": 2.0,
|
"integration_time": 2.0,
|
||||||
|
"initial_conditions": {
|
||||||
"vortex": {
|
"vortex": {
|
||||||
"vortices": [{
|
"vortices": [{
|
||||||
"x0": -1.0,
|
"x0": -1.0,
|
||||||
|
@ -57,4 +58,5 @@
|
||||||
}],
|
}],
|
||||||
"mach": 0.5
|
"mach": 0.5
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"integration_time": 2.0,
|
"integration_time": 2.0,
|
||||||
|
"initial_conditions": {
|
||||||
"vortex": {
|
"vortex": {
|
||||||
"vortices": [{
|
"vortices": [{
|
||||||
"x0": -1.0,
|
"x0": -1.0,
|
||||||
|
@ -177,4 +178,5 @@
|
||||||
}],
|
}],
|
||||||
"mach": 0.5
|
"mach": 0.5
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,6 @@
|
||||||
"operators": {
|
"operators": {
|
||||||
"xi": "upwind9",
|
"xi": "upwind9",
|
||||||
"eta": "upwind9"
|
"eta": "upwind9"
|
||||||
},
|
|
||||||
"boundary_conditions": {
|
|
||||||
"south": "vortex",
|
|
||||||
"north": "vortex",
|
|
||||||
"east": "vortex",
|
|
||||||
"west": "vortex"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid0": {
|
"grid0": {
|
||||||
|
@ -37,6 +31,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"integration_time": 2.0,
|
"integration_time": 2.0,
|
||||||
|
"initial_conditions": {
|
||||||
"vortex": {
|
"vortex": {
|
||||||
"vortices": [{
|
"vortices": [{
|
||||||
"x0": 0.0,
|
"x0": 0.0,
|
||||||
|
@ -46,4 +41,6 @@
|
||||||
}],
|
}],
|
||||||
"mach": 0.5
|
"mach": 0.5
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"boundary_conditions": "initial_conditions"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,330 @@
|
||||||
|
use euler::GAMMA;
|
||||||
|
use evalexpr::*;
|
||||||
|
use ndarray::{azip, ArrayView, ArrayViewMut, Dimension};
|
||||||
|
use sbp::Float;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Evaluator {
|
||||||
|
Pressure(EvaluatorPressure),
|
||||||
|
Conservation(EvaluatorConservation),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EvaluatorConservation {
|
||||||
|
pub(crate) ctx: HashMapContext,
|
||||||
|
pub(crate) rho: Node,
|
||||||
|
pub(crate) rhou: Node,
|
||||||
|
pub(crate) rhov: Node,
|
||||||
|
pub(crate) e: Node,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: ndarray::Dimension> euler::eval::Evaluator<D> for Evaluator {
|
||||||
|
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>,
|
||||||
|
) {
|
||||||
|
match self {
|
||||||
|
Self::Conservation(c) => c.evaluate(t, x, y, rho, rhou, rhov, e),
|
||||||
|
Self::Pressure(p) => {
|
||||||
|
euler::eval::EvaluatorPressureWrapper::new(p).evaluate(t, x, y, rho, rhou, rhov, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EvaluatorPressure {
|
||||||
|
pub(crate) ctx: HashMapContext,
|
||||||
|
pub(crate) rho: Node,
|
||||||
|
pub(crate) u: Node,
|
||||||
|
pub(crate) v: Node,
|
||||||
|
pub(crate) p: Node,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ContextWrapper<'a> {
|
||||||
|
ctx: &'a HashMapContext,
|
||||||
|
x: Option<Value>,
|
||||||
|
y: Option<Value>,
|
||||||
|
t: Value,
|
||||||
|
rho: Option<Value>,
|
||||||
|
u: Option<Value>,
|
||||||
|
v: Option<Value>,
|
||||||
|
rhou: Option<Value>,
|
||||||
|
rhov: Option<Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ContextWrapper<'a> {
|
||||||
|
fn wrap(ctx: &'a HashMapContext, t: Value) -> Self {
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
t,
|
||||||
|
x: None,
|
||||||
|
y: None,
|
||||||
|
rho: None,
|
||||||
|
rhou: None,
|
||||||
|
rhov: None,
|
||||||
|
u: None,
|
||||||
|
v: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context for ContextWrapper<'_> {
|
||||||
|
fn get_value(&self, identifier: &str) -> Option<&Value> {
|
||||||
|
match identifier {
|
||||||
|
"t" => Some(&self.t),
|
||||||
|
"x" => self.x.as_ref(),
|
||||||
|
"y" => self.y.as_ref(),
|
||||||
|
"rho" => self.rho.as_ref(),
|
||||||
|
"rhou" => self.rhou.as_ref(),
|
||||||
|
"rhov" => self.rhov.as_ref(),
|
||||||
|
"u" => self.u.as_ref(),
|
||||||
|
"v" => self.v.as_ref(),
|
||||||
|
id => self.ctx.get_value(id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_function(&self, identifier: &str, argument: &Value) -> EvalexprResult<Value> {
|
||||||
|
self.ctx.call_function(identifier, argument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> euler::eval::Evaluator<D> for EvaluatorConservation {
|
||||||
|
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 mut ctx = ContextWrapper::wrap(&self.ctx, t.into());
|
||||||
|
|
||||||
|
azip!((&x in &x.view(), &y in &y, rho in &mut rho) {
|
||||||
|
ctx.x = Some(x.into());
|
||||||
|
ctx.y = Some(y.into());
|
||||||
|
|
||||||
|
*rho = self.rho.eval_number_with_context(&ctx).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
azip!((&x in &x, &y in &y, &rho in &rho, rhou in &mut rhou) {
|
||||||
|
ctx.x = Some(x.into());
|
||||||
|
ctx.y = Some(y.into());
|
||||||
|
ctx.rho = Some(rho.into());
|
||||||
|
|
||||||
|
*rhou = self.rhou.eval_number_with_context(&ctx).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
azip!((&x in &x, &y in &y, &rho in &rho, rhov in &mut rhov) {
|
||||||
|
ctx.x = Some(x.into());
|
||||||
|
ctx.y = Some(y.into());
|
||||||
|
ctx.rho = Some(rho.into());
|
||||||
|
|
||||||
|
*rhov = self.rhov.eval_number_with_context(&ctx).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
azip!((&x in &x, &y in &y, &rho in &rho, &rhou in &rhou, &rhov in &rhov, e in &mut e) {
|
||||||
|
ctx.x = Some(x.into());
|
||||||
|
ctx.y = Some(y.into());
|
||||||
|
ctx.rho = Some(rho.into());
|
||||||
|
ctx.rhou = Some(rhou.into());
|
||||||
|
ctx.rhov = Some(rhov.into());
|
||||||
|
|
||||||
|
*e = self.e.eval_number_with_context(&ctx).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Dimension> euler::eval::EvaluatorPressure<D> for EvaluatorPressure {
|
||||||
|
fn rho(
|
||||||
|
&self,
|
||||||
|
t: Float,
|
||||||
|
x: ArrayView<Float, D>,
|
||||||
|
y: ArrayView<Float, D>,
|
||||||
|
mut rho: ArrayViewMut<Float, D>,
|
||||||
|
) {
|
||||||
|
let mut ctx = ContextWrapper::wrap(&self.ctx, t.into());
|
||||||
|
|
||||||
|
azip!((&x in &x, &y in &y, rho in &mut rho) {
|
||||||
|
ctx.x = Some(x.into());
|
||||||
|
ctx.y = Some(y.into());
|
||||||
|
|
||||||
|
*rho = self.rho.eval_number_with_context(&ctx).unwrap();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u(
|
||||||
|
&self,
|
||||||
|
t: Float,
|
||||||
|
x: ArrayView<Float, D>,
|
||||||
|
y: ArrayView<Float, D>,
|
||||||
|
rho: ArrayView<Float, D>,
|
||||||
|
mut u: ArrayViewMut<Float, D>,
|
||||||
|
) {
|
||||||
|
let mut ctx = ContextWrapper::wrap(&self.ctx, t.into());
|
||||||
|
|
||||||
|
azip!((&x in &x, &y in &y, &rho in &rho, u in &mut u) {
|
||||||
|
ctx.x = Some(x.into());
|
||||||
|
ctx.y = Some(y.into());
|
||||||
|
ctx.rho = Some(rho.into());
|
||||||
|
|
||||||
|
*u = self.u.eval_number_with_context(&ctx).unwrap();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn v(
|
||||||
|
&self,
|
||||||
|
t: Float,
|
||||||
|
x: ArrayView<Float, D>,
|
||||||
|
y: ArrayView<Float, D>,
|
||||||
|
rho: ArrayView<Float, D>,
|
||||||
|
mut v: ArrayViewMut<Float, D>,
|
||||||
|
) {
|
||||||
|
let mut ctx = ContextWrapper::wrap(&self.ctx, t.into());
|
||||||
|
|
||||||
|
azip!((&x in &x, &y in &y, &rho in &rho, v in &mut v) {
|
||||||
|
ctx.x = Some(x.into());
|
||||||
|
ctx.y = Some(y.into());
|
||||||
|
ctx.rho = Some(rho.into());
|
||||||
|
|
||||||
|
*v = self.v.eval_number_with_context(&ctx).unwrap();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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>,
|
||||||
|
mut p: ArrayViewMut<Float, D>,
|
||||||
|
) {
|
||||||
|
let mut ctx = ContextWrapper::wrap(&self.ctx, t.into());
|
||||||
|
|
||||||
|
azip!((&x in &x, &y in &y, &rho in &rho, &u in &u, &v in &v, p in &mut p) {
|
||||||
|
ctx.x = Some(x.into());
|
||||||
|
ctx.y = Some(y.into());
|
||||||
|
ctx.rho = Some(rho.into());
|
||||||
|
ctx.u = Some(u.into());
|
||||||
|
ctx.v = Some(v.into());
|
||||||
|
|
||||||
|
*p = self.p.eval_number_with_context(&ctx).unwrap();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn append_default_context() {
|
||||||
|
let basic_ctx = context_map! {
|
||||||
|
"a" => 2,
|
||||||
|
}
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut ctx = ContextWrapper::wrap(&basic_ctx, Value::from(4));
|
||||||
|
ctx.x = Some(3.into());
|
||||||
|
|
||||||
|
let expr = "a + x + t";
|
||||||
|
|
||||||
|
let node = build_operator_tree(expr).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(node.eval_with_context(&ctx).unwrap().as_int().unwrap(), 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_context() -> HashMapContext {
|
||||||
|
let mut context = math_consts_context! {}.unwrap();
|
||||||
|
|
||||||
|
context.set_value("GAMMA".into(), GAMMA.into()).unwrap();
|
||||||
|
|
||||||
|
context
|
||||||
|
.set_function(
|
||||||
|
"if".into(),
|
||||||
|
Function::new(|arg| {
|
||||||
|
let arg = arg.as_tuple()?;
|
||||||
|
if arg.len() != 3 {
|
||||||
|
return Err(error::EvalexprError::WrongFunctionArgumentAmount {
|
||||||
|
expected: 3,
|
||||||
|
actual: arg.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let b = arg[0].as_boolean()?;
|
||||||
|
if b.into() {
|
||||||
|
Ok(arg[1].clone())
|
||||||
|
} else {
|
||||||
|
Ok(arg[2].clone())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
context
|
||||||
|
.set_function(
|
||||||
|
"case".into(),
|
||||||
|
Function::new(|arg| {
|
||||||
|
let mut arg = arg.as_tuple()?;
|
||||||
|
if arg.len() % 2 == 0 {
|
||||||
|
return Err(error::EvalexprError::WrongFunctionArgumentAmount {
|
||||||
|
expected: arg.len() + 1,
|
||||||
|
actual: arg.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//let mut arg = arg.as_slice();
|
||||||
|
while arg.len() > 2 {
|
||||||
|
let boolean = arg.remove(0);
|
||||||
|
let value = arg.remove(0);
|
||||||
|
|
||||||
|
if boolean.as_boolean()? {
|
||||||
|
return Ok(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(arg.pop().unwrap())
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
context
|
||||||
|
.set_function(
|
||||||
|
"math::atan2".into(),
|
||||||
|
Function::new(|arg| {
|
||||||
|
let arg = arg.as_tuple()?;
|
||||||
|
if arg.len() != 2 {
|
||||||
|
return Err(error::EvalexprError::WrongFunctionArgumentAmount {
|
||||||
|
expected: 2,
|
||||||
|
actual: arg.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let s = arg[0].as_number()?;
|
||||||
|
let o = arg[1].as_number()?;
|
||||||
|
Ok(s.atan2(o).into())
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
context
|
||||||
|
.set_function(
|
||||||
|
"math::hypot".into(),
|
||||||
|
Function::new(|arg| {
|
||||||
|
let arg = arg.as_tuple()?;
|
||||||
|
if arg.len() != 2 {
|
||||||
|
return Err(error::EvalexprError::WrongFunctionArgumentAmount {
|
||||||
|
expected: 2,
|
||||||
|
actual: arg.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let s = arg[0].as_number()?;
|
||||||
|
let o = arg[1].as_number()?;
|
||||||
|
Ok(s.hypot(o).into())
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
context
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
use argh::FromArgs;
|
use argh::FromArgs;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
|
use euler::eval::Evaluator;
|
||||||
use sbp::operators::SbpOperator2d;
|
use sbp::operators::SbpOperator2d;
|
||||||
use sbp::*;
|
use sbp::*;
|
||||||
|
|
||||||
mod file;
|
mod file;
|
||||||
mod parsing;
|
mod parsing;
|
||||||
use file::*;
|
use file::*;
|
||||||
|
mod eval;
|
||||||
|
|
||||||
struct System {
|
struct System {
|
||||||
fnow: Vec<euler::Field>,
|
fnow: Vec<euler::Field>,
|
||||||
|
@ -283,14 +285,35 @@ fn main() {
|
||||||
let parsing::RuntimeConfiguration {
|
let parsing::RuntimeConfiguration {
|
||||||
names,
|
names,
|
||||||
grids,
|
grids,
|
||||||
bc: bt,
|
grid_connections,
|
||||||
op: operators,
|
op: operators,
|
||||||
integration_time,
|
integration_time,
|
||||||
vortex: vortexparams,
|
initial_conditions,
|
||||||
|
boundary_conditions: _,
|
||||||
} = config.into_runtime();
|
} = config.into_runtime();
|
||||||
|
|
||||||
let mut sys = System::new(grids, bt, operators);
|
let mut sys = System::new(grids, grid_connections, operators);
|
||||||
sys.vortex(0.0, &vortexparams);
|
match initial_conditions {
|
||||||
|
/*
|
||||||
|
parsing::InitialConditions::File(f) => {
|
||||||
|
for grid in &sys.grids {
|
||||||
|
// Copy initial conditions from file, requires name of field
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
parsing::InitialConditions::Vortex(vortexparams) => sys.vortex(0.0, &vortexparams),
|
||||||
|
parsing::InitialConditions::Expressions(expr) => {
|
||||||
|
let t = 0.0;
|
||||||
|
for (grid, field) in sys.grids.iter().zip(sys.fnow.iter_mut()) {
|
||||||
|
// Evaluate the expressions on all variables
|
||||||
|
let x = grid.x();
|
||||||
|
let y = grid.y();
|
||||||
|
let (rho, rhou, rhov, e) = field.components_mut();
|
||||||
|
(*expr).evaluate(t, x, y, rho, rhou, rhov, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let dt = sys.max_dt();
|
let dt = sys.max_dt();
|
||||||
|
|
||||||
|
@ -348,16 +371,23 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
output.add_timestep(ntime, &sys.fnow);
|
output.add_timestep(ntime, &sys.fnow);
|
||||||
|
/*
|
||||||
if opt.error {
|
if opt.error {
|
||||||
let time = ntime as Float * dt;
|
let time = ntime as Float * dt;
|
||||||
let mut e = 0.0;
|
let mut e = 0.0;
|
||||||
for ((fmod, grid), op) in sys.fnow.iter().zip(&sys.grids).zip(&sys.operators) {
|
for ((fmod, grid), op) in sys.fnow.iter().zip(&sys.grids).zip(&sys.operators) {
|
||||||
let mut fvort = fmod.clone();
|
let mut fvort = fmod.clone();
|
||||||
fvort.vortex(grid.x(), grid.y(), time, &vortexparams);
|
fvort.vortex(
|
||||||
|
grid.x(),
|
||||||
|
grid.y(),
|
||||||
|
time,
|
||||||
|
&vortexparams.as_ref().unwrap().clone(),
|
||||||
|
);
|
||||||
e += fmod.h2_err(&fvort, &**op);
|
e += fmod.h2_err(&fvort, &**op);
|
||||||
}
|
}
|
||||||
outinfo.error = Some(e);
|
outinfo.error = Some(e);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if opt.output_json {
|
if opt.output_json {
|
||||||
println!("{}", json5::to_string(&outinfo).unwrap());
|
println!("{}", json5::to_string(&outinfo).unwrap());
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
use sbp::operators::SbpOperator2d;
|
use sbp::operators::SbpOperator2d;
|
||||||
use sbp::utils::h2linspace;
|
use sbp::utils::h2linspace;
|
||||||
use sbp::Float;
|
use sbp::Float;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::eval;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum Operator {
|
pub enum Operator {
|
||||||
|
@ -35,6 +39,10 @@ pub struct Linspace {
|
||||||
pub enum GridLike {
|
pub enum GridLike {
|
||||||
Linspace(Linspace),
|
Linspace(Linspace),
|
||||||
Array(ArrayForm),
|
Array(ArrayForm),
|
||||||
|
/*
|
||||||
|
#[serde(rename = "initial_conditions")]
|
||||||
|
InitialConditions,
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<GridLike> for ArrayForm {
|
impl From<GridLike> for ArrayForm {
|
||||||
|
@ -46,6 +54,7 @@ impl From<GridLike> for ArrayForm {
|
||||||
ndarray::Array::linspace(lin.start, lin.end, lin.steps)
|
ndarray::Array::linspace(lin.start, lin.end, lin.steps)
|
||||||
}),
|
}),
|
||||||
GridLike::Array(arr) => arr,
|
GridLike::Array(arr) => arr,
|
||||||
|
// GridLike::InitialConditions => Self::Unknown,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,25 +146,185 @@ pub struct GridConfig {
|
||||||
type Grids = indexmap::IndexMap<String, GridConfig>;
|
type Grids = indexmap::IndexMap<String, GridConfig>;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
/// Will be evaluated by evalexpr
|
||||||
|
pub struct ExpressionsConservation {
|
||||||
|
pub globals: Option<String>,
|
||||||
|
pub rho: String,
|
||||||
|
pub rhou: String,
|
||||||
|
pub rhov: String,
|
||||||
|
pub e: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
/// Will be evaluated by evalexpr
|
||||||
|
pub struct ExpressionsPressure {
|
||||||
|
pub globals: Option<String>,
|
||||||
|
pub rho: String,
|
||||||
|
pub u: String,
|
||||||
|
pub v: String,
|
||||||
|
pub p: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Expressions {
|
||||||
|
Conservation(ExpressionsConservation),
|
||||||
|
Pressure(ExpressionsPressure),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum InputInitialConditions {
|
||||||
|
Vortex(euler::VortexParameters),
|
||||||
|
// File(String),
|
||||||
|
Expressions(Expressions),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum InitialConditions {
|
||||||
|
Vortex(euler::VortexParameters),
|
||||||
|
// File(hdf5::File),
|
||||||
|
Expressions(std::sync::Arc<eval::Evaluator>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Expressions> for eval::Evaluator {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(expr: Expressions) -> Result<Self, Self::Error> {
|
||||||
|
let mut context = eval::default_context();
|
||||||
|
match expr {
|
||||||
|
Expressions::Pressure(ExpressionsPressure {
|
||||||
|
globals,
|
||||||
|
rho,
|
||||||
|
u,
|
||||||
|
v,
|
||||||
|
p,
|
||||||
|
}) => {
|
||||||
|
if let Some(globals) = &globals {
|
||||||
|
evalexpr::eval_with_context_mut(globals, &mut context).unwrap();
|
||||||
|
}
|
||||||
|
let [rho, u, v, p] = [
|
||||||
|
evalexpr::build_operator_tree(&rho).unwrap(),
|
||||||
|
evalexpr::build_operator_tree(&u).unwrap(),
|
||||||
|
evalexpr::build_operator_tree(&v).unwrap(),
|
||||||
|
evalexpr::build_operator_tree(&p).unwrap(),
|
||||||
|
];
|
||||||
|
Ok(eval::Evaluator::Pressure(eval::EvaluatorPressure {
|
||||||
|
ctx: context,
|
||||||
|
rho,
|
||||||
|
u,
|
||||||
|
v,
|
||||||
|
p,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
Expressions::Conservation(ExpressionsConservation {
|
||||||
|
globals,
|
||||||
|
rho,
|
||||||
|
rhou,
|
||||||
|
rhov,
|
||||||
|
e,
|
||||||
|
}) => {
|
||||||
|
if let Some(globals) = &globals {
|
||||||
|
evalexpr::eval_with_context_mut(globals, &mut context).unwrap();
|
||||||
|
}
|
||||||
|
let [rho, rhou, rhov, e] = [
|
||||||
|
evalexpr::build_operator_tree(&rho).unwrap(),
|
||||||
|
evalexpr::build_operator_tree(&rhou).unwrap(),
|
||||||
|
evalexpr::build_operator_tree(&rhov).unwrap(),
|
||||||
|
evalexpr::build_operator_tree(&e).unwrap(),
|
||||||
|
];
|
||||||
|
Ok(eval::Evaluator::Conservation(eval::EvaluatorConservation {
|
||||||
|
ctx: context,
|
||||||
|
rho,
|
||||||
|
rhou,
|
||||||
|
rhov,
|
||||||
|
e,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<InputInitialConditions> for InitialConditions {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(v: InputInitialConditions) -> Result<Self, Self::Error> {
|
||||||
|
Ok(match v {
|
||||||
|
InputInitialConditions::Vortex(v) => Self::Vortex(v),
|
||||||
|
// InputInitialConditions::File(file) => Self::File(hdf5::File::open(file).unwrap()),
|
||||||
|
InputInitialConditions::Expressions(expr) => {
|
||||||
|
Self::Expressions(std::sync::Arc::new(expr.try_into()?))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum InputBoundaryConditions {
|
||||||
|
/// Initial conditions also contain the bc
|
||||||
|
#[serde(rename = "initial_conditions")]
|
||||||
|
InputInitialConditions,
|
||||||
|
Vortex(euler::VortexParameters),
|
||||||
|
Expressions(Expressions),
|
||||||
|
#[serde(rename = "not_needed")]
|
||||||
|
NotNeeded,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InputBoundaryConditions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::NotNeeded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum BoundaryConditions {
|
||||||
|
Vortex(euler::VortexParameters),
|
||||||
|
Expressions(std::sync::Arc<eval::Evaluator>),
|
||||||
|
NotNeeded,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
/// Input configuration (json)
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
pub grids: Grids,
|
pub grids: Grids,
|
||||||
pub integration_time: Float,
|
pub integration_time: Float,
|
||||||
pub vortex: euler::VortexParameters,
|
pub initial_conditions: InputInitialConditions,
|
||||||
|
#[serde(default)]
|
||||||
|
pub boundary_conditions: InputBoundaryConditions,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RuntimeConfiguration {
|
pub struct RuntimeConfiguration {
|
||||||
pub names: Vec<String>,
|
pub names: Vec<String>,
|
||||||
pub grids: Vec<sbp::grid::Grid>,
|
pub grids: Vec<sbp::grid::Grid>,
|
||||||
pub bc: Vec<euler::BoundaryCharacteristics>,
|
pub grid_connections: Vec<euler::BoundaryCharacteristics>,
|
||||||
pub op: Vec<Box<dyn SbpOperator2d>>,
|
pub op: Vec<Box<dyn SbpOperator2d>>,
|
||||||
pub integration_time: Float,
|
pub integration_time: Float,
|
||||||
pub vortex: euler::VortexParameters,
|
pub initial_conditions: InitialConditions,
|
||||||
|
pub boundary_conditions: BoundaryConditions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
pub fn into_runtime(mut self) -> RuntimeConfiguration {
|
pub fn into_runtime(mut self) -> RuntimeConfiguration {
|
||||||
let default = self.grids.shift_remove("default").unwrap_or_default();
|
let default = self.grids.shift_remove("default").unwrap_or_default();
|
||||||
let names = self.grids.keys().cloned().collect();
|
let names = self.grids.keys().cloned().collect();
|
||||||
|
|
||||||
|
let initial_conditions: InitialConditions =
|
||||||
|
self.initial_conditions.clone().try_into().unwrap();
|
||||||
|
|
||||||
|
let boundary_conditions = match &self.boundary_conditions {
|
||||||
|
InputBoundaryConditions::NotNeeded => BoundaryConditions::NotNeeded,
|
||||||
|
InputBoundaryConditions::Vortex(vp) => BoundaryConditions::Vortex(vp.clone()),
|
||||||
|
InputBoundaryConditions::Expressions(expr) => BoundaryConditions::Expressions(
|
||||||
|
std::sync::Arc::new(expr.clone().try_into().unwrap()),
|
||||||
|
),
|
||||||
|
InputBoundaryConditions::InputInitialConditions => match &initial_conditions {
|
||||||
|
InitialConditions::Vortex(vp) => BoundaryConditions::Vortex(vp.clone()),
|
||||||
|
InitialConditions::Expressions(expr) => {
|
||||||
|
BoundaryConditions::Expressions(expr.clone())
|
||||||
|
} // _ => panic!("Boundary conditions were set to initial conditions, although initial conditions are not available",),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let grids = self
|
let grids = self
|
||||||
.grids
|
.grids
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -198,7 +367,23 @@ impl Configuration {
|
||||||
(ArrayForm::Array2(x), ArrayForm::Array2(y)) => {
|
(ArrayForm::Array2(x), ArrayForm::Array2(y)) => {
|
||||||
assert_eq!(x.shape(), y.shape());
|
assert_eq!(x.shape(), y.shape());
|
||||||
(x, y)
|
(x, y)
|
||||||
|
} /*
|
||||||
|
(ArrayForm::Unknown, ArrayForm::Unknown) => {
|
||||||
|
if let InitialConditions::File(file) = &initial_conditions {
|
||||||
|
let g = file.group(name).unwrap();
|
||||||
|
let x = g.dataset("x").unwrap().read_2d::<Float>().unwrap();
|
||||||
|
let y = g.dataset("y").unwrap().read_2d::<Float>().unwrap();
|
||||||
|
assert_eq!(x.shape(), y.shape());
|
||||||
|
(x, y)
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"Grid {} requires a valid file for setting initial size",
|
||||||
|
name
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
sbp::grid::Grid::new(x, y).unwrap()
|
sbp::grid::Grid::new(x, y).unwrap()
|
||||||
})
|
})
|
||||||
|
@ -237,11 +422,11 @@ impl Configuration {
|
||||||
Box::new((matcher(eta), matcher(xi))) as Box<dyn SbpOperator2d>
|
Box::new((matcher(eta), matcher(xi))) as Box<dyn SbpOperator2d>
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let bc = self
|
let grid_connections = self
|
||||||
.grids
|
.grids
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (_name, g))| {
|
.map(|(i, (name, g))| {
|
||||||
let default_bc = default.boundary_conditions.clone().unwrap_or_default();
|
let default_bc = default.boundary_conditions.clone().unwrap_or_default();
|
||||||
g.boundary_conditions
|
g.boundary_conditions
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -249,10 +434,26 @@ impl Configuration {
|
||||||
.zip(default_bc)
|
.zip(default_bc)
|
||||||
.map(|(bc, fallback)| bc.or(fallback))
|
.map(|(bc, fallback)| bc.or(fallback))
|
||||||
.map(|bc| match bc {
|
.map(|bc| match bc {
|
||||||
None | Some(BoundaryType::Vortex) => {
|
None => match &boundary_conditions {
|
||||||
euler::BoundaryCharacteristic::Vortex(self.vortex.clone())
|
BoundaryConditions::Vortex(vortex) => {
|
||||||
|
euler::BoundaryCharacteristic::Vortex(vortex.clone())
|
||||||
}
|
}
|
||||||
|
BoundaryConditions::Expressions(expr) => {
|
||||||
|
euler::BoundaryCharacteristic::Eval(expr.clone() )
|
||||||
|
}
|
||||||
|
_ => panic!(
|
||||||
|
"Boundary conditions are not available, but needed for grid {}",
|
||||||
|
name
|
||||||
|
),
|
||||||
|
},
|
||||||
Some(BoundaryType::This) => euler::BoundaryCharacteristic::Grid(i),
|
Some(BoundaryType::This) => euler::BoundaryCharacteristic::Grid(i),
|
||||||
|
Some(BoundaryType::Vortex) => euler::BoundaryCharacteristic::Vortex(
|
||||||
|
if let BoundaryConditions::Vortex(vortex) = &boundary_conditions {
|
||||||
|
vortex.clone()
|
||||||
|
} else {
|
||||||
|
panic!("Wanted vortex boundary conditions not found, needed for grid {}", name)
|
||||||
|
},
|
||||||
|
),
|
||||||
Some(BoundaryType::Neighbour(name)) => {
|
Some(BoundaryType::Neighbour(name)) => {
|
||||||
let j = self.grids.get_index_of(&name).unwrap();
|
let j = self.grids.get_index_of(&name).unwrap();
|
||||||
euler::BoundaryCharacteristic::Grid(j)
|
euler::BoundaryCharacteristic::Grid(j)
|
||||||
|
@ -282,10 +483,11 @@ impl Configuration {
|
||||||
RuntimeConfiguration {
|
RuntimeConfiguration {
|
||||||
names,
|
names,
|
||||||
grids,
|
grids,
|
||||||
bc,
|
grid_connections,
|
||||||
op,
|
op,
|
||||||
integration_time: self.integration_time,
|
integration_time: self.integration_time,
|
||||||
vortex: self.vortex,
|
initial_conditions,
|
||||||
|
boundary_conditions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,6 +500,11 @@ pub enum ArrayForm {
|
||||||
Array1(ndarray::Array1<Float>),
|
Array1(ndarray::Array1<Float>),
|
||||||
/// The usize is the inner dimension (nx)
|
/// The usize is the inner dimension (nx)
|
||||||
Array2(ndarray::Array2<Float>),
|
Array2(ndarray::Array2<Float>),
|
||||||
|
/*
|
||||||
|
/// A still unknown array, will be filled out by later
|
||||||
|
/// pass when initial_conditions file is known
|
||||||
|
Unknown,
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ndarray::Array1<Float>> for ArrayForm {
|
impl From<ndarray::Array1<Float>> for ArrayForm {
|
||||||
|
|
Loading…
Reference in New Issue