Use serde for json configuration file
This commit is contained in:
parent
f90618be42
commit
d0e6727ac3
|
@ -8,11 +8,13 @@ edition = "2018"
|
||||||
# Internal feature flag to gate the expensive tests
|
# Internal feature flag to gate the expensive tests
|
||||||
# which should be run only in release builds
|
# which should be run only in release builds
|
||||||
expensive_tests = []
|
expensive_tests = []
|
||||||
|
serde1 = ["serde", "arrayvec/serde"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ndarray = "0.13.1"
|
ndarray = "0.13.1"
|
||||||
sbp = { path = "../sbp" }
|
sbp = { path = "../sbp" }
|
||||||
arrayvec = "0.5.1"
|
arrayvec = "0.5.1"
|
||||||
|
serde = { version = "1.0.115", default-features = false, optional = true, features = ["derive"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.3.2"
|
criterion = "0.3.2"
|
||||||
|
|
|
@ -402,6 +402,7 @@ fn h2_diff() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
|
||||||
pub struct Vortice {
|
pub struct Vortice {
|
||||||
pub x0: Float,
|
pub x0: Float,
|
||||||
pub y0: Float,
|
pub y0: Float,
|
||||||
|
@ -409,7 +410,11 @@ pub struct Vortice {
|
||||||
pub eps: Float,
|
pub eps: Float,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde1")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
|
||||||
pub struct VortexParameters {
|
pub struct VortexParameters {
|
||||||
pub vortices: ArrayVec<[Vortice; 5]>,
|
pub vortices: ArrayVec<[Vortice; 5]>,
|
||||||
pub mach: Float,
|
pub mach: Float,
|
||||||
|
|
|
@ -6,12 +6,15 @@ edition = "2018"
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sbp = { path = "../sbp", features = ["rayon"] }
|
sbp = { path = "../sbp", features = ["rayon", "serde"] }
|
||||||
euler = { path = "../euler" }
|
euler = { path = "../euler", features = ["serde1"] }
|
||||||
hdf5 = "0.7.0"
|
hdf5 = "0.7.0"
|
||||||
rayon = "1.3.0"
|
rayon = "1.3.0"
|
||||||
indicatif = "0.14.0"
|
indicatif = "0.14.0"
|
||||||
structopt = "0.3.14"
|
structopt = "0.3.14"
|
||||||
ndarray = "0.13.1"
|
ndarray = { version = "0.13.1", features = ["serde"] }
|
||||||
json = "0.12.4"
|
json = "0.12.4"
|
||||||
either = "1.5.3"
|
either = "1.5.3"
|
||||||
|
serde = { version = "1.0.115", features = ["derive"] }
|
||||||
|
json5 = "0.2.8"
|
||||||
|
indexmap = { version = "1.5.2", features = ["serde-1"] }
|
||||||
|
|
|
@ -1,10 +1,127 @@
|
||||||
use super::DiffOp;
|
use super::DiffOp;
|
||||||
use either::*;
|
use either::*;
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use sbp::grid::Grid;
|
|
||||||
use sbp::utils::h2linspace;
|
use sbp::utils::h2linspace;
|
||||||
use sbp::Float;
|
use sbp::Float;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum Operator {
|
||||||
|
Upwind4,
|
||||||
|
Upwind9,
|
||||||
|
Upwind4h2,
|
||||||
|
Upwind9h2,
|
||||||
|
Sbp4,
|
||||||
|
Sbp8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Operators {
|
||||||
|
pub xi: Operator,
|
||||||
|
pub eta: Operator,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Linspace {
|
||||||
|
pub start: Float,
|
||||||
|
pub end: Float,
|
||||||
|
pub steps: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub h2: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum GridLike {
|
||||||
|
Linspace(Linspace),
|
||||||
|
Array(ArrayForm),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Linspace> for GridLike {
|
||||||
|
fn from(t: Linspace) -> Self {
|
||||||
|
Self::Linspace(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ArrayForm> for GridLike {
|
||||||
|
fn from(t: ArrayForm) -> Self {
|
||||||
|
Self::Array(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ndarray::Array1<Float>> for GridLike {
|
||||||
|
fn from(t: ndarray::Array1<Float>) -> Self {
|
||||||
|
Self::Array(t.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ndarray::Array2<Float>> for GridLike {
|
||||||
|
fn from(t: ndarray::Array2<Float>) -> Self {
|
||||||
|
Self::Array(t.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum InterpolationOperator {
|
||||||
|
#[serde(rename = "4")]
|
||||||
|
Four,
|
||||||
|
#[serde(rename = "8")]
|
||||||
|
Eight,
|
||||||
|
#[serde(rename = "9")]
|
||||||
|
Nine,
|
||||||
|
#[serde(rename = "9h2")]
|
||||||
|
NineH2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Interpolate {
|
||||||
|
operator: Option<InterpolationOperator>,
|
||||||
|
neighbour: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum BoundaryType {
|
||||||
|
This,
|
||||||
|
Interpolate(Interpolate),
|
||||||
|
Neighbour(String),
|
||||||
|
Vortex,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type BoundaryDescriptors = sbp::utils::Direction<Option<BoundaryType>>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct GridConfig {
|
||||||
|
pub operators: Option<Operators>,
|
||||||
|
pub x: Option<GridLike>,
|
||||||
|
pub y: Option<GridLike>,
|
||||||
|
pub boundary_conditions: Option<BoundaryDescriptors>,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Grids = indexmap::IndexMap<String, GridConfig>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Configuration {
|
||||||
|
pub grids: Grids,
|
||||||
|
pub integration_time: Float,
|
||||||
|
pub vortex: euler::VortexParameters,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RuntimeConfiguration {
|
||||||
|
names: Vec<String>,
|
||||||
|
grids: Vec<sbp::grid::Grid>,
|
||||||
|
bc: Vec<euler::BoundaryCharacteristics>,
|
||||||
|
op: Vec<DiffOp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Configuration {
|
||||||
|
fn to_runtime(self) -> RuntimeConfiguration {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn json_to_grids(
|
pub fn json_to_grids(
|
||||||
mut jsongrids: JsonValue,
|
mut jsongrids: JsonValue,
|
||||||
vortexparams: euler::VortexParameters,
|
vortexparams: euler::VortexParameters,
|
||||||
|
@ -191,8 +308,9 @@ pub fn json_to_grids(
|
||||||
|
|
||||||
(names, grids, bcs, operators)
|
(names, grids, bcs, operators)
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
enum ArrayForm {
|
#[serde(untagged)]
|
||||||
|
pub enum ArrayForm {
|
||||||
/// Only know the one dimension, will broadcast to
|
/// Only know the one dimension, will broadcast to
|
||||||
/// two dimensions once we know about both dims
|
/// two dimensions once we know about both dims
|
||||||
Array1(ndarray::Array1<Float>),
|
Array1(ndarray::Array1<Float>),
|
||||||
|
@ -200,6 +318,18 @@ enum ArrayForm {
|
||||||
Array2(ndarray::Array2<Float>),
|
Array2(ndarray::Array2<Float>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ndarray::Array1<Float>> for ArrayForm {
|
||||||
|
fn from(t: ndarray::Array1<Float>) -> Self {
|
||||||
|
Self::Array1(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ndarray::Array2<Float>> for ArrayForm {
|
||||||
|
fn from(t: ndarray::Array2<Float>) -> Self {
|
||||||
|
Self::Array2(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parsing json strings to some gridlike form
|
/// Parsing json strings to some gridlike form
|
||||||
///
|
///
|
||||||
/// Each grid should be an object with the descriptors on the form
|
/// Each grid should be an object with the descriptors on the form
|
||||||
|
@ -217,7 +347,7 @@ enum ArrayForm {
|
||||||
/// Optional parameters:
|
/// Optional parameters:
|
||||||
/// * name (for relating boundaries)
|
/// * name (for relating boundaries)
|
||||||
/// * dir{e,w,n,s} (for boundary terms)
|
/// * dir{e,w,n,s} (for boundary terms)
|
||||||
fn json2grid(x: JsonValue, y: JsonValue) -> Result<Grid, String> {
|
fn json2grid(x: JsonValue, y: JsonValue) -> Result<sbp::grid::Grid, String> {
|
||||||
let to_array_form = |mut x: JsonValue| {
|
let to_array_form = |mut x: JsonValue| {
|
||||||
if let Some(s) = x.take_string() {
|
if let Some(s) = x.take_string() {
|
||||||
if let Some(s) = s.strip_prefix("linspace:") {
|
if let Some(s) = s.strip_prefix("linspace:") {
|
||||||
|
@ -346,7 +476,7 @@ fn json2grid(x: JsonValue, y: JsonValue) -> Result<Grid, String> {
|
||||||
};
|
};
|
||||||
assert_eq!(x.shape(), y.shape());
|
assert_eq!(x.shape(), y.shape());
|
||||||
|
|
||||||
Ok(Grid::new(x, y).unwrap())
|
Ok(sbp::grid::Grid::new(x, y).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn json_to_vortex(mut json: JsonValue) -> euler::VortexParameters {
|
pub fn json_to_vortex(mut json: JsonValue) -> euler::VortexParameters {
|
||||||
|
@ -391,3 +521,154 @@ pub fn json_to_vortex(mut json: JsonValue) -> euler::VortexParameters {
|
||||||
|
|
||||||
euler::VortexParameters { vortices, mach }
|
euler::VortexParameters { vortices, mach }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn output_configuration() {
|
||||||
|
let mut grids = Grids::new();
|
||||||
|
grids.insert(
|
||||||
|
"default".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: None,
|
||||||
|
x: None,
|
||||||
|
y: None,
|
||||||
|
operators: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
grids.insert(
|
||||||
|
"operators1".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: None,
|
||||||
|
x: None,
|
||||||
|
y: None,
|
||||||
|
operators: Some(Operators {
|
||||||
|
xi: Operator::Upwind4,
|
||||||
|
eta: Operator::Upwind9,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
grids.insert(
|
||||||
|
"operators2".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: None,
|
||||||
|
x: None,
|
||||||
|
y: None,
|
||||||
|
operators: Some(Operators {
|
||||||
|
xi: Operator::Upwind4h2,
|
||||||
|
eta: Operator::Upwind9h2,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
grids.insert(
|
||||||
|
"operators3".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: None,
|
||||||
|
x: None,
|
||||||
|
y: None,
|
||||||
|
operators: Some(Operators {
|
||||||
|
xi: Operator::Sbp4,
|
||||||
|
eta: Operator::Sbp8,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
grids.insert(
|
||||||
|
"linspaced".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: None,
|
||||||
|
x: Some(
|
||||||
|
Linspace {
|
||||||
|
start: 0.0,
|
||||||
|
end: 1.0,
|
||||||
|
steps: 32,
|
||||||
|
h2: false,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
y: Some(
|
||||||
|
Linspace {
|
||||||
|
start: -1.0,
|
||||||
|
end: 1.0,
|
||||||
|
steps: 35,
|
||||||
|
h2: true,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
operators: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
grids.insert(
|
||||||
|
"array1".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: None,
|
||||||
|
x: Some(ndarray::arr1(&[1.0, 2.0, 3.0, 4.0]).into()),
|
||||||
|
y: Some(ndarray::arr1(&[-4.0, -3.0, -2.0, -1.0, 0.0]).into()),
|
||||||
|
operators: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
grids.insert(
|
||||||
|
"array2".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: None,
|
||||||
|
x: Some(ndarray::arr2(&[[1.0, 2.0, 3.0, 4.0], [2.0, 3.0, 4.0, 5.0]]).into()),
|
||||||
|
y: Some(ndarray::arr2(&[[0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]]).into()),
|
||||||
|
operators: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
grids.insert(
|
||||||
|
"boundary_conditions".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: Some(BoundaryDescriptors {
|
||||||
|
north: None,
|
||||||
|
south: Some(BoundaryType::This),
|
||||||
|
east: Some(BoundaryType::Neighbour("name_of_grid".to_string())),
|
||||||
|
west: Some(BoundaryType::Vortex),
|
||||||
|
}),
|
||||||
|
x: None,
|
||||||
|
y: None,
|
||||||
|
operators: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
grids.insert(
|
||||||
|
"boundary_conditions_interpolation".to_string(),
|
||||||
|
GridConfig {
|
||||||
|
boundary_conditions: Some(BoundaryDescriptors {
|
||||||
|
north: Some(BoundaryType::Interpolate(Interpolate {
|
||||||
|
neighbour: "name_of_grid".to_string(),
|
||||||
|
operator: Some(InterpolationOperator::Four),
|
||||||
|
})),
|
||||||
|
south: Some(BoundaryType::Interpolate(Interpolate {
|
||||||
|
neighbour: "name_of_grid".to_string(),
|
||||||
|
operator: Some(InterpolationOperator::Nine),
|
||||||
|
})),
|
||||||
|
west: Some(BoundaryType::Interpolate(Interpolate {
|
||||||
|
neighbour: "name_of_grid".to_string(),
|
||||||
|
operator: Some(InterpolationOperator::Eight),
|
||||||
|
})),
|
||||||
|
east: Some(BoundaryType::Interpolate(Interpolate {
|
||||||
|
neighbour: "name_of_grid".to_string(),
|
||||||
|
operator: Some(InterpolationOperator::NineH2),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
x: None,
|
||||||
|
y: None,
|
||||||
|
operators: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let configuration = Configuration {
|
||||||
|
grids,
|
||||||
|
integration_time: 2.0,
|
||||||
|
vortex: euler::VortexParameters {
|
||||||
|
mach: 0.5,
|
||||||
|
vortices: {
|
||||||
|
let mut arr = euler::ArrayVec::new();
|
||||||
|
arr.push(euler::Vortice {
|
||||||
|
eps: 1.0,
|
||||||
|
x0: -1.0,
|
||||||
|
y0: 0.0,
|
||||||
|
rstar: 0.5,
|
||||||
|
});
|
||||||
|
arr
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
println!("{}", json5::to_string(&configuration).unwrap());
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ packed_simd = "0.3.3"
|
||||||
rayon = { version = "1.3.0", optional = true }
|
rayon = { version = "1.3.0", optional = true }
|
||||||
sprs = { version = "0.7.1", optional = true }
|
sprs = { version = "0.7.1", optional = true }
|
||||||
num-traits = "0.2.11"
|
num-traits = "0.2.11"
|
||||||
|
serde = { version = "1.0.115", optional = true, default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Use f32 as precision, default is f64
|
# Use f32 as precision, default is f64
|
||||||
|
|
|
@ -8,7 +8,11 @@ pub use jacobi::*;
|
||||||
mod kronecker_product;
|
mod kronecker_product;
|
||||||
#[cfg(feature = "sparse")]
|
#[cfg(feature = "sparse")]
|
||||||
pub use kronecker_product::kronecker_product;
|
pub use kronecker_product::kronecker_product;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct Direction<T> {
|
pub struct Direction<T> {
|
||||||
pub north: T,
|
pub north: T,
|
||||||
pub south: T,
|
pub south: T,
|
||||||
|
|
Loading…
Reference in New Issue