split euler and maxwell to separate crates
This commit is contained in:
parent
52bd4f3f8f
commit
a1acf00c5a
|
@ -10,6 +10,8 @@ members = [
|
||||||
"sbp",
|
"sbp",
|
||||||
"webfront",
|
"webfront",
|
||||||
"multigrid",
|
"multigrid",
|
||||||
|
"euler",
|
||||||
|
"maxwell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.bench]
|
[profile.bench]
|
||||||
|
@ -17,4 +19,4 @@ debug = true
|
||||||
|
|
||||||
[patch]
|
[patch]
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
hdf5 = { git = "https://github.com/mulimoen/hdf5-rust.git", branch = "feature/resizable_idx" }
|
hdf5 = { git = "https://github.com/mulimoen/hdf5-rust.git", branch = "master" }
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
[package]
|
||||||
|
name = "euler"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Magnus Ulimoen <flymagnus@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# Internal feature flag to gate the expensive tests
|
||||||
|
# which should be run only in release builds
|
||||||
|
expensive_tests = []
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ndarray = "0.13.1"
|
||||||
|
sbp = { path = "../sbp" }
|
||||||
|
arrayvec = "0.5.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = "0.3.1"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "bench"
|
||||||
|
harness = false
|
|
@ -1,11 +1,11 @@
|
||||||
use super::grid::{Grid, Metrics};
|
|
||||||
use super::integrate;
|
|
||||||
use super::operators::{InterpolationOperator, SbpOperator2d, UpwindOperator2d};
|
|
||||||
use super::utils::Direction;
|
|
||||||
use super::Float;
|
|
||||||
pub use arrayvec::ArrayVec;
|
pub use arrayvec::ArrayVec;
|
||||||
use ndarray::azip;
|
use ndarray::azip;
|
||||||
use ndarray::prelude::*;
|
use ndarray::prelude::*;
|
||||||
|
use sbp::grid::{Grid, Metrics};
|
||||||
|
use sbp::integrate;
|
||||||
|
use sbp::operators::{InterpolationOperator, SbpOperator2d, UpwindOperator2d};
|
||||||
|
use sbp::utils::Direction;
|
||||||
|
use sbp::Float;
|
||||||
|
|
||||||
pub const GAMMA: Float = 1.4;
|
pub const GAMMA: Float = 1.4;
|
||||||
|
|
||||||
|
@ -101,10 +101,10 @@ impl<SBP: SbpOperator2d> System<SBP> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn x(&self) -> ArrayView2<Float> {
|
pub fn x(&self) -> ArrayView2<Float> {
|
||||||
self.grid.0.x.view()
|
self.grid.0.x()
|
||||||
}
|
}
|
||||||
pub fn y(&self) -> ArrayView2<Float> {
|
pub fn y(&self) -> ArrayView2<Float> {
|
||||||
self.grid.0.y.view()
|
self.grid.0.y()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nx(&self) -> usize {
|
pub fn nx(&self) -> usize {
|
||||||
|
@ -393,7 +393,7 @@ fn h2_diff() {
|
||||||
}
|
}
|
||||||
let field1 = Field::new(20, 21);
|
let field1 = Field::new(20, 21);
|
||||||
|
|
||||||
use super::operators::{Upwind4, Upwind9, SBP4, SBP8};
|
use sbp::operators::{Upwind4, Upwind9, SBP4, SBP8};
|
||||||
|
|
||||||
assert!((field0.h2_err(&field1, &Upwind4).powi(2) - 4.0).abs() < 1e-3);
|
assert!((field0.h2_err(&field1, &Upwind4).powi(2) - 4.0).abs() < 1e-3);
|
||||||
assert!((field0.h2_err(&field1, &Upwind9).powi(2) - 4.0).abs() < 1e-3);
|
assert!((field0.h2_err(&field1, &Upwind9).powi(2) - 4.0).abs() < 1e-3);
|
||||||
|
@ -460,7 +460,7 @@ pub fn vortex(
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
Some(vortice) => {
|
Some(vortice) => {
|
||||||
use crate::consts::PI;
|
use sbp::consts::PI;
|
||||||
|
|
||||||
let rstar = vortice.rstar;
|
let rstar = vortice.rstar;
|
||||||
let eps = vortice.eps;
|
let eps = vortice.eps;
|
||||||
|
@ -485,7 +485,7 @@ pub fn vortex(
|
||||||
}
|
}
|
||||||
|
|
||||||
for vortice in iterator {
|
for vortice in iterator {
|
||||||
use crate::consts::PI;
|
use sbp::consts::PI;
|
||||||
|
|
||||||
let rstar = vortice.rstar;
|
let rstar = vortice.rstar;
|
||||||
let eps = vortice.eps;
|
let eps = vortice.eps;
|
||||||
|
@ -543,7 +543,7 @@ pub fn RHS_trad(
|
||||||
azip!((out in &mut k.0,
|
azip!((out in &mut k.0,
|
||||||
eflux in &dE.0,
|
eflux in &dE.0,
|
||||||
fflux in &dF.0,
|
fflux in &dF.0,
|
||||||
detj in &metrics.detj.broadcast((4, y.ny(), y.nx())).unwrap()) {
|
detj in &metrics.detj().broadcast((4, y.ny(), y.nx())).unwrap()) {
|
||||||
*out = (-eflux - fflux)/detj
|
*out = (-eflux - fflux)/detj
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -584,7 +584,7 @@ pub fn RHS_upwind(
|
||||||
fflux in &dF.0,
|
fflux in &dF.0,
|
||||||
ad_xi in &ad_xi.0,
|
ad_xi in &ad_xi.0,
|
||||||
ad_eta in &ad_eta.0,
|
ad_eta in &ad_eta.0,
|
||||||
detj in &metrics.detj.broadcast((4, y.ny(), y.nx())).unwrap()) {
|
detj in &metrics.detj().broadcast((4, y.ny(), y.nx())).unwrap()) {
|
||||||
*out = (-eflux - fflux + ad_xi + ad_eta)/detj
|
*out = (-eflux - fflux + ad_xi + ad_eta)/detj
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -611,11 +611,11 @@ fn upwind_dissipation(
|
||||||
.axis_iter(ndarray::Axis(1))
|
.axis_iter(ndarray::Axis(1))
|
||||||
.zip(tmp0.axis_iter_mut(ndarray::Axis(1)))
|
.zip(tmp0.axis_iter_mut(ndarray::Axis(1)))
|
||||||
.zip(tmp1.axis_iter_mut(ndarray::Axis(1)))
|
.zip(tmp1.axis_iter_mut(ndarray::Axis(1)))
|
||||||
.zip(metrics.detj.iter())
|
.zip(metrics.detj().iter())
|
||||||
.zip(metrics.detj_dxi_dx.iter())
|
.zip(metrics.detj_dxi_dx().iter())
|
||||||
.zip(metrics.detj_dxi_dy.iter())
|
.zip(metrics.detj_dxi_dy().iter())
|
||||||
.zip(metrics.detj_deta_dx.iter())
|
.zip(metrics.detj_deta_dx().iter())
|
||||||
.zip(metrics.detj_deta_dy.iter())
|
.zip(metrics.detj_deta_dy().iter())
|
||||||
{
|
{
|
||||||
let rho = y[0];
|
let rho = y[0];
|
||||||
assert!(rho > 0.0);
|
assert!(rho > 0.0);
|
||||||
|
@ -661,10 +661,10 @@ fn upwind_dissipation(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluxes(k: (&mut Field, &mut Field), y: &Field, metrics: &Metrics) {
|
fn fluxes(k: (&mut Field, &mut Field), y: &Field, metrics: &Metrics) {
|
||||||
let j_dxi_dx = metrics.detj_dxi_dx.view();
|
let j_dxi_dx = metrics.detj_dxi_dx();
|
||||||
let j_dxi_dy = metrics.detj_dxi_dy.view();
|
let j_dxi_dy = metrics.detj_dxi_dy();
|
||||||
let j_deta_dx = metrics.detj_deta_dx.view();
|
let j_deta_dx = metrics.detj_deta_dx();
|
||||||
let j_deta_dy = metrics.detj_deta_dy.view();
|
let j_deta_dy = metrics.detj_deta_dy();
|
||||||
|
|
||||||
let rho = y.rho();
|
let rho = y.rho();
|
||||||
let rhou = y.rhou();
|
let rhou = y.rhou();
|
||||||
|
@ -871,12 +871,17 @@ pub fn extract_boundaries<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used for storing boundary elements
|
/// Used for storing boundary elements
|
||||||
pub type BoundaryStorage = Direction<Option<ndarray::Array2<Float>>>;
|
pub struct BoundaryStorage {
|
||||||
|
north: Option<ndarray::Array2<Float>>,
|
||||||
|
south: Option<ndarray::Array2<Float>>,
|
||||||
|
east: Option<ndarray::Array2<Float>>,
|
||||||
|
west: Option<ndarray::Array2<Float>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl BoundaryStorage {
|
impl BoundaryStorage {
|
||||||
pub fn new(bt: &BoundaryCharacteristics, grid: &Grid) -> Self {
|
pub fn new(bt: &BoundaryCharacteristics, grid: &Grid) -> Self {
|
||||||
Self {
|
Self {
|
||||||
north: match bt.north {
|
north: match bt.north() {
|
||||||
BoundaryCharacteristic::Vortex(_)
|
BoundaryCharacteristic::Vortex(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => {
|
| BoundaryCharacteristic::MultiGrid(_) => {
|
||||||
|
@ -884,7 +889,7 @@ impl BoundaryStorage {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
south: match bt.south {
|
south: match bt.south() {
|
||||||
BoundaryCharacteristic::Vortex(_)
|
BoundaryCharacteristic::Vortex(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => {
|
| BoundaryCharacteristic::MultiGrid(_) => {
|
||||||
|
@ -892,7 +897,7 @@ impl BoundaryStorage {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
east: match bt.east {
|
east: match bt.east() {
|
||||||
BoundaryCharacteristic::Vortex(_)
|
BoundaryCharacteristic::Vortex(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => {
|
| BoundaryCharacteristic::MultiGrid(_) => {
|
||||||
|
@ -900,7 +905,7 @@ impl BoundaryStorage {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
west: match bt.west {
|
west: match bt.west() {
|
||||||
BoundaryCharacteristic::Vortex(_)
|
BoundaryCharacteristic::Vortex(_)
|
||||||
| BoundaryCharacteristic::Interpolate(_, _)
|
| BoundaryCharacteristic::Interpolate(_, _)
|
||||||
| BoundaryCharacteristic::MultiGrid(_) => {
|
| BoundaryCharacteristic::MultiGrid(_) => {
|
||||||
|
@ -955,9 +960,9 @@ fn SAT_characteristics(
|
||||||
hi,
|
hi,
|
||||||
sign,
|
sign,
|
||||||
tau,
|
tau,
|
||||||
metrics.detj.slice(slice),
|
metrics.detj().slice(slice),
|
||||||
metrics.detj_deta_dx.slice(slice),
|
metrics.detj_deta_dx().slice(slice),
|
||||||
metrics.detj_deta_dy.slice(slice),
|
metrics.detj_deta_dy().slice(slice),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// South boundary
|
// South boundary
|
||||||
|
@ -977,9 +982,9 @@ fn SAT_characteristics(
|
||||||
hi,
|
hi,
|
||||||
sign,
|
sign,
|
||||||
tau,
|
tau,
|
||||||
metrics.detj.slice(slice),
|
metrics.detj().slice(slice),
|
||||||
metrics.detj_deta_dx.slice(slice),
|
metrics.detj_deta_dx().slice(slice),
|
||||||
metrics.detj_deta_dy.slice(slice),
|
metrics.detj_deta_dy().slice(slice),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// West Boundary
|
// West Boundary
|
||||||
|
@ -999,9 +1004,9 @@ fn SAT_characteristics(
|
||||||
hi,
|
hi,
|
||||||
sign,
|
sign,
|
||||||
tau,
|
tau,
|
||||||
metrics.detj.slice(slice),
|
metrics.detj().slice(slice),
|
||||||
metrics.detj_dxi_dx.slice(slice),
|
metrics.detj_dxi_dx().slice(slice),
|
||||||
metrics.detj_dxi_dy.slice(slice),
|
metrics.detj_dxi_dy().slice(slice),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// East Boundary
|
// East Boundary
|
||||||
|
@ -1021,9 +1026,9 @@ fn SAT_characteristics(
|
||||||
hi,
|
hi,
|
||||||
sign,
|
sign,
|
||||||
tau,
|
tau,
|
||||||
metrics.detj.slice(slice),
|
metrics.detj().slice(slice),
|
||||||
metrics.detj_dxi_dx.slice(slice),
|
metrics.detj_dxi_dx().slice(slice),
|
||||||
metrics.detj_dxi_dy.slice(slice),
|
metrics.detj_dxi_dy().slice(slice),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#![cfg(feature = "expensive_tests")]
|
#![cfg(feature = "expensive_tests")]
|
||||||
|
use euler::*;
|
||||||
use ndarray::prelude::*;
|
use ndarray::prelude::*;
|
||||||
use sbp::euler::*;
|
|
||||||
use sbp::Float;
|
use sbp::Float;
|
||||||
|
|
||||||
fn run_with_size(size: usize, op: impl sbp::operators::UpwindOperator2d + Copy) -> Float {
|
fn run_with_size(size: usize, op: impl sbp::operators::UpwindOperator2d + Copy) -> Float {
|
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "maxwell"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Magnus Ulimoen <flymagnus@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ndarray = "0.13.1"
|
||||||
|
sbp = { path = "../sbp" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = "0.3.1"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "bench"
|
||||||
|
harness = false
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use sbp::maxwell::System;
|
use maxwell::System;
|
||||||
use sbp::operators::{SbpOperator2d, Upwind4, UpwindOperator2d, SBP4};
|
use sbp::operators::{SbpOperator2d, Upwind4, UpwindOperator2d, SBP4};
|
||||||
use sbp::Float;
|
use sbp::Float;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use super::grid::{Grid, Metrics};
|
|
||||||
use super::integrate;
|
|
||||||
use super::operators::{SbpOperator2d, UpwindOperator2d};
|
|
||||||
use crate::Float;
|
|
||||||
use ndarray::azip;
|
use ndarray::azip;
|
||||||
use ndarray::prelude::*;
|
use ndarray::prelude::*;
|
||||||
|
use sbp::grid::{Grid, Metrics};
|
||||||
|
use sbp::integrate;
|
||||||
|
use sbp::operators::{SbpOperator2d, UpwindOperator2d};
|
||||||
|
use sbp::Float;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Field(pub(crate) Array3<Float>);
|
pub struct Field(pub(crate) Array3<Float>);
|
||||||
|
@ -113,7 +113,7 @@ impl<SBP: SbpOperator2d> System<SBP> {
|
||||||
let (ex, hz, ey) = self.sys.0.components_mut();
|
let (ex, hz, ey) = self.sys.0.components_mut();
|
||||||
ndarray::azip!(
|
ndarray::azip!(
|
||||||
(ex in ex, hz in hz, ey in ey,
|
(ex in ex, hz in hz, ey in ey,
|
||||||
&x in &self.grid.x, &y in &self.grid.y)
|
&x in &self.grid.x(), &y in &self.grid.y())
|
||||||
{
|
{
|
||||||
*ex = 0.0;
|
*ex = 0.0;
|
||||||
*ey = 0.0;
|
*ey = 0.0;
|
||||||
|
@ -166,7 +166,7 @@ impl<UO: UpwindOperator2d> System<UO> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gaussian(x: Float, x0: Float, y: Float, y0: Float) -> Float {
|
fn gaussian(x: Float, x0: Float, y: Float, y0: Float) -> Float {
|
||||||
use crate::consts::PI;
|
use sbp::consts::PI;
|
||||||
|
|
||||||
let x = x - x0;
|
let x = x - x0;
|
||||||
let y = y - y0;
|
let y = y - y0;
|
||||||
|
@ -211,7 +211,7 @@ fn RHS<SBP: SbpOperator2d>(
|
||||||
SAT_characteristics(op, k, y, metrics, &boundaries);
|
SAT_characteristics(op, k, y, metrics, &boundaries);
|
||||||
|
|
||||||
azip!((k in &mut k.0,
|
azip!((k in &mut k.0,
|
||||||
&detj in &metrics.detj.broadcast((3, y.ny(), y.nx())).unwrap()) {
|
&detj in &metrics.detj().broadcast((3, y.ny(), y.nx())).unwrap()) {
|
||||||
*k /= detj;
|
*k /= detj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -237,12 +237,12 @@ fn RHS_upwind<UO: UpwindOperator2d>(
|
||||||
SAT_characteristics(op, k, y, metrics, &boundaries);
|
SAT_characteristics(op, k, y, metrics, &boundaries);
|
||||||
|
|
||||||
azip!((k in &mut k.0,
|
azip!((k in &mut k.0,
|
||||||
&detj in &metrics.detj.broadcast((3, y.ny(), y.nx())).unwrap()) {
|
&detj in &metrics.detj().broadcast((3, y.ny(), y.nx())).unwrap()) {
|
||||||
*k /= detj;
|
*k /= detj;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluxes<SBP: super::operators::SbpOperator2d>(
|
fn fluxes<SBP: sbp::operators::SbpOperator2d>(
|
||||||
op: &SBP,
|
op: &SBP,
|
||||||
k: &mut Field,
|
k: &mut Field,
|
||||||
y: &Field,
|
y: &Field,
|
||||||
|
@ -252,14 +252,14 @@ fn fluxes<SBP: super::operators::SbpOperator2d>(
|
||||||
// ex = hz_y
|
// ex = hz_y
|
||||||
{
|
{
|
||||||
ndarray::azip!((a in &mut tmp.0,
|
ndarray::azip!((a in &mut tmp.0,
|
||||||
&dxi_dy in &metrics.detj_dxi_dy,
|
&dxi_dy in &metrics.detj_dxi_dy(),
|
||||||
&hz in &y.hz())
|
&hz in &y.hz())
|
||||||
*a = dxi_dy * hz
|
*a = dxi_dy * hz
|
||||||
);
|
);
|
||||||
op.diffxi(tmp.0.view(), tmp.1.view_mut());
|
op.diffxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
|
||||||
ndarray::azip!((b in &mut tmp.2,
|
ndarray::azip!((b in &mut tmp.2,
|
||||||
&deta_dy in &metrics.detj_deta_dy,
|
&deta_dy in &metrics.detj_deta_dy(),
|
||||||
&hz in &y.hz())
|
&hz in &y.hz())
|
||||||
*b = deta_dy * hz
|
*b = deta_dy * hz
|
||||||
);
|
);
|
||||||
|
@ -273,8 +273,8 @@ fn fluxes<SBP: super::operators::SbpOperator2d>(
|
||||||
{
|
{
|
||||||
// hz = -ey_x + ex_y
|
// hz = -ey_x + ex_y
|
||||||
ndarray::azip!((a in &mut tmp.0,
|
ndarray::azip!((a in &mut tmp.0,
|
||||||
&dxi_dx in &metrics.detj_dxi_dx,
|
&dxi_dx in &metrics.detj_dxi_dx(),
|
||||||
&dxi_dy in &metrics.detj_dxi_dy,
|
&dxi_dy in &metrics.detj_dxi_dy(),
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey())
|
&ey in &y.ey())
|
||||||
*a = dxi_dx * -ey + dxi_dy * ex
|
*a = dxi_dx * -ey + dxi_dy * ex
|
||||||
|
@ -282,8 +282,8 @@ fn fluxes<SBP: super::operators::SbpOperator2d>(
|
||||||
op.diffxi(tmp.0.view(), tmp.1.view_mut());
|
op.diffxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
|
||||||
ndarray::azip!((b in &mut tmp.2,
|
ndarray::azip!((b in &mut tmp.2,
|
||||||
&deta_dx in &metrics.detj_deta_dx,
|
&deta_dx in &metrics.detj_deta_dx(),
|
||||||
&deta_dy in &metrics.detj_deta_dy,
|
&deta_dy in &metrics.detj_deta_dy(),
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey())
|
&ey in &y.ey())
|
||||||
*b = deta_dx * -ey + deta_dy * ex
|
*b = deta_dx * -ey + deta_dy * ex
|
||||||
|
@ -298,14 +298,14 @@ fn fluxes<SBP: super::operators::SbpOperator2d>(
|
||||||
// ey = -hz_x
|
// ey = -hz_x
|
||||||
{
|
{
|
||||||
ndarray::azip!((a in &mut tmp.0,
|
ndarray::azip!((a in &mut tmp.0,
|
||||||
&dxi_dx in &metrics.detj_dxi_dx,
|
&dxi_dx in &metrics.detj_dxi_dx(),
|
||||||
&hz in &y.hz())
|
&hz in &y.hz())
|
||||||
*a = dxi_dx * -hz
|
*a = dxi_dx * -hz
|
||||||
);
|
);
|
||||||
op.diffxi(tmp.0.view(), tmp.1.view_mut());
|
op.diffxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
|
||||||
azip!((b in &mut tmp.2,
|
azip!((b in &mut tmp.2,
|
||||||
&deta_dx in &metrics.detj_deta_dx,
|
&deta_dx in &metrics.detj_deta_dx(),
|
||||||
&hz in &y.hz())
|
&hz in &y.hz())
|
||||||
*b = deta_dx * -hz
|
*b = deta_dx * -hz
|
||||||
);
|
);
|
||||||
|
@ -327,8 +327,8 @@ fn dissipation<UO: UpwindOperator2d>(
|
||||||
// ex component
|
// ex component
|
||||||
{
|
{
|
||||||
ndarray::azip!((a in &mut tmp.0,
|
ndarray::azip!((a in &mut tmp.0,
|
||||||
&kx in &metrics.detj_dxi_dx,
|
&kx in &metrics.detj_dxi_dx(),
|
||||||
&ky in &metrics.detj_dxi_dy,
|
&ky in &metrics.detj_dxi_dy(),
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey()) {
|
&ey in &y.ey()) {
|
||||||
let r = Float::hypot(kx, ky);
|
let r = Float::hypot(kx, ky);
|
||||||
|
@ -337,8 +337,8 @@ fn dissipation<UO: UpwindOperator2d>(
|
||||||
op.dissxi(tmp.0.view(), tmp.1.view_mut());
|
op.dissxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
|
||||||
ndarray::azip!((b in &mut tmp.2,
|
ndarray::azip!((b in &mut tmp.2,
|
||||||
&kx in &metrics.detj_deta_dx,
|
&kx in &metrics.detj_deta_dx(),
|
||||||
&ky in &metrics.detj_deta_dy,
|
&ky in &metrics.detj_deta_dy(),
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey()) {
|
&ey in &y.ey()) {
|
||||||
let r = Float::hypot(kx, ky);
|
let r = Float::hypot(kx, ky);
|
||||||
|
@ -354,8 +354,8 @@ fn dissipation<UO: UpwindOperator2d>(
|
||||||
// hz component
|
// hz component
|
||||||
{
|
{
|
||||||
ndarray::azip!((a in &mut tmp.0,
|
ndarray::azip!((a in &mut tmp.0,
|
||||||
&kx in &metrics.detj_dxi_dx,
|
&kx in &metrics.detj_dxi_dx(),
|
||||||
&ky in &metrics.detj_dxi_dy,
|
&ky in &metrics.detj_dxi_dy(),
|
||||||
&hz in &y.hz()) {
|
&hz in &y.hz()) {
|
||||||
let r = Float::hypot(kx, ky);
|
let r = Float::hypot(kx, ky);
|
||||||
*a = r * hz;
|
*a = r * hz;
|
||||||
|
@ -363,8 +363,8 @@ fn dissipation<UO: UpwindOperator2d>(
|
||||||
op.dissxi(tmp.0.view(), tmp.1.view_mut());
|
op.dissxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
|
||||||
ndarray::azip!((b in &mut tmp.2,
|
ndarray::azip!((b in &mut tmp.2,
|
||||||
&kx in &metrics.detj_deta_dx,
|
&kx in &metrics.detj_deta_dx(),
|
||||||
&ky in &metrics.detj_deta_dy,
|
&ky in &metrics.detj_deta_dy(),
|
||||||
&hz in &y.hz()) {
|
&hz in &y.hz()) {
|
||||||
let r = Float::hypot(kx, ky);
|
let r = Float::hypot(kx, ky);
|
||||||
*b = r * hz;
|
*b = r * hz;
|
||||||
|
@ -379,8 +379,8 @@ fn dissipation<UO: UpwindOperator2d>(
|
||||||
// ey
|
// ey
|
||||||
{
|
{
|
||||||
ndarray::azip!((a in &mut tmp.0,
|
ndarray::azip!((a in &mut tmp.0,
|
||||||
&kx in &metrics.detj_dxi_dx,
|
&kx in &metrics.detj_dxi_dx(),
|
||||||
&ky in &metrics.detj_dxi_dy,
|
&ky in &metrics.detj_dxi_dy(),
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey()) {
|
&ey in &y.ey()) {
|
||||||
let r = Float::hypot(kx, ky);
|
let r = Float::hypot(kx, ky);
|
||||||
|
@ -389,8 +389,8 @@ fn dissipation<UO: UpwindOperator2d>(
|
||||||
op.dissxi(tmp.0.view(), tmp.1.view_mut());
|
op.dissxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
|
||||||
ndarray::azip!((b in &mut tmp.2,
|
ndarray::azip!((b in &mut tmp.2,
|
||||||
&kx in &metrics.detj_deta_dx,
|
&kx in &metrics.detj_deta_dx(),
|
||||||
&ky in &metrics.detj_deta_dy,
|
&ky in &metrics.detj_deta_dy(),
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey()) {
|
&ey in &y.ey()) {
|
||||||
let r = Float::hypot(kx, ky);
|
let r = Float::hypot(kx, ky);
|
||||||
|
@ -462,8 +462,8 @@ fn SAT_characteristics<SBP: SbpOperator2d>(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(y.slice(s![.., .., nx - 1]).gencolumns())
|
.zip(y.slice(s![.., .., nx - 1]).gencolumns())
|
||||||
.zip(g.gencolumns())
|
.zip(g.gencolumns())
|
||||||
.zip(metrics.detj_dxi_dx.slice(s![.., nx - 1]))
|
.zip(metrics.detj_dxi_dx().slice(s![.., nx - 1]))
|
||||||
.zip(metrics.detj_dxi_dy.slice(s![.., nx - 1]))
|
.zip(metrics.detj_dxi_dy().slice(s![.., nx - 1]))
|
||||||
{
|
{
|
||||||
// East boundary, positive flux
|
// East boundary, positive flux
|
||||||
let tau = -1.0;
|
let tau = -1.0;
|
||||||
|
@ -500,8 +500,8 @@ fn SAT_characteristics<SBP: SbpOperator2d>(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(y.slice(s![.., .., 0]).gencolumns())
|
.zip(y.slice(s![.., .., 0]).gencolumns())
|
||||||
.zip(g.gencolumns())
|
.zip(g.gencolumns())
|
||||||
.zip(metrics.detj_dxi_dx.slice(s![.., 0]))
|
.zip(metrics.detj_dxi_dx().slice(s![.., 0]))
|
||||||
.zip(metrics.detj_dxi_dy.slice(s![.., 0]))
|
.zip(metrics.detj_dxi_dy().slice(s![.., 0]))
|
||||||
{
|
{
|
||||||
let tau = 1.0;
|
let tau = 1.0;
|
||||||
|
|
||||||
|
@ -543,8 +543,8 @@ fn SAT_characteristics<SBP: SbpOperator2d>(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(y.slice(s![.., ny - 1, ..]).gencolumns())
|
.zip(y.slice(s![.., ny - 1, ..]).gencolumns())
|
||||||
.zip(g.gencolumns())
|
.zip(g.gencolumns())
|
||||||
.zip(metrics.detj_deta_dx.slice(s![ny - 1, ..]))
|
.zip(metrics.detj_deta_dx().slice(s![ny - 1, ..]))
|
||||||
.zip(metrics.detj_deta_dy.slice(s![ny - 1, ..]))
|
.zip(metrics.detj_deta_dy().slice(s![ny - 1, ..]))
|
||||||
{
|
{
|
||||||
// North boundary, positive flux
|
// North boundary, positive flux
|
||||||
let tau = -1.0;
|
let tau = -1.0;
|
||||||
|
@ -580,8 +580,8 @@ fn SAT_characteristics<SBP: SbpOperator2d>(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(y.slice(s![.., 0, ..]).gencolumns())
|
.zip(y.slice(s![.., 0, ..]).gencolumns())
|
||||||
.zip(g.gencolumns())
|
.zip(g.gencolumns())
|
||||||
.zip(metrics.detj_deta_dx.slice(s![0, ..]))
|
.zip(metrics.detj_deta_dx().slice(s![0, ..]))
|
||||||
.zip(metrics.detj_deta_dy.slice(s![0, ..]))
|
.zip(metrics.detj_deta_dy().slice(s![0, ..]))
|
||||||
{
|
{
|
||||||
// South boundary, negative flux
|
// South boundary, negative flux
|
||||||
|
|
|
@ -7,7 +7,8 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sbp = { path = "../sbp", features = ["rayon"] }
|
sbp = { path = "../sbp", features = ["rayon"] }
|
||||||
hdf5 = "0.6.0"
|
euler = { path = "../euler" }
|
||||||
|
hdf5 = { version = "0.6.0", features = ["static"] }
|
||||||
rayon = "1.3.0"
|
rayon = "1.3.0"
|
||||||
indicatif = "0.14.0"
|
indicatif = "0.14.0"
|
||||||
structopt = "0.3.13"
|
structopt = "0.3.13"
|
||||||
|
|
|
@ -173,7 +173,14 @@ fn main() {
|
||||||
let max_ny = sys.grids.iter().map(|g| g.ny()).max().unwrap();
|
let max_ny = sys.grids.iter().map(|g| g.ny()).max().unwrap();
|
||||||
std::cmp::max(max_nx, max_ny)
|
std::cmp::max(max_nx, max_ny)
|
||||||
};
|
};
|
||||||
let dt = 0.2 / (max_n as Float);
|
// Add a robust method for determining CFL, use for example the maximum speed of the initial
|
||||||
|
// field along with \delta x / \delta y
|
||||||
|
// U_max = max(rhou/u, rhov/v)
|
||||||
|
// This requires scaling with the determinant to obtain the "true" speed in computational
|
||||||
|
// space
|
||||||
|
// CFL = 0.2
|
||||||
|
// \delta t = CFL min(\delta x, \delta y) / U_max
|
||||||
|
let dt = 0.02 / (max_n as Float);
|
||||||
|
|
||||||
let ntime = (integration_time / dt).round() as u64;
|
let ntime = (integration_time / dt).round() as u64;
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use super::DiffOp;
|
use super::DiffOp;
|
||||||
use crate::grid::Grid;
|
|
||||||
use crate::Float;
|
|
||||||
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;
|
||||||
|
|
||||||
pub fn json_to_grids(
|
pub fn json_to_grids(
|
||||||
mut jsongrids: JsonValue,
|
mut jsongrids: JsonValue,
|
||||||
vortexparams: sbp::euler::VortexParameters,
|
vortexparams: euler::VortexParameters,
|
||||||
) -> (
|
) -> (
|
||||||
Vec<String>,
|
Vec<String>,
|
||||||
Vec<sbp::grid::Grid>,
|
Vec<sbp::grid::Grid>,
|
||||||
Vec<sbp::euler::BoundaryCharacteristics>,
|
Vec<euler::BoundaryCharacteristics>,
|
||||||
Vec<DiffOp>,
|
Vec<DiffOp>,
|
||||||
) {
|
) {
|
||||||
let default = jsongrids.remove("default");
|
let default = jsongrids.remove("default");
|
||||||
|
@ -110,7 +110,7 @@ pub fn json_to_grids(
|
||||||
let determine_bc = |dir: Option<&str>| match dir {
|
let determine_bc = |dir: Option<&str>| match dir {
|
||||||
Some(dir) => {
|
Some(dir) => {
|
||||||
if dir == "vortex" {
|
if dir == "vortex" {
|
||||||
sbp::euler::BoundaryCharacteristic::Vortex(vortexparams.clone())
|
euler::BoundaryCharacteristic::Vortex(vortexparams.clone())
|
||||||
} else if let Some(grid) = dir.strip_prefix("interpolate:") {
|
} else if let Some(grid) = dir.strip_prefix("interpolate:") {
|
||||||
use sbp::operators::*;
|
use sbp::operators::*;
|
||||||
let (grid, int_op) = if let Some(rest) = grid.strip_prefix("4:") {
|
let (grid, int_op) = if let Some(rest) = grid.strip_prefix("4:") {
|
||||||
|
@ -139,13 +139,13 @@ pub fn json_to_grids(
|
||||||
Box::new(Interpolation4) as Box<dyn InterpolationOperator>,
|
Box::new(Interpolation4) as Box<dyn InterpolationOperator>,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
sbp::euler::BoundaryCharacteristic::Interpolate(
|
euler::BoundaryCharacteristic::Interpolate(
|
||||||
names.iter().position(|other| other == grid).unwrap(),
|
names.iter().position(|other| other == grid).unwrap(),
|
||||||
int_op,
|
int_op,
|
||||||
)
|
)
|
||||||
} else if let Some(multigrid) = dir.strip_prefix("multi:") {
|
} else if let Some(multigrid) = dir.strip_prefix("multi:") {
|
||||||
let grids = multigrid.split(':');
|
let grids = multigrid.split(':');
|
||||||
sbp::euler::BoundaryCharacteristic::MultiGrid(
|
euler::BoundaryCharacteristic::MultiGrid(
|
||||||
grids
|
grids
|
||||||
.map(|g| {
|
.map(|g| {
|
||||||
let rparen = g.find('(').unwrap();
|
let rparen = g.find('(').unwrap();
|
||||||
|
@ -165,12 +165,12 @@ pub fn json_to_grids(
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
sbp::euler::BoundaryCharacteristic::Grid(
|
euler::BoundaryCharacteristic::Grid(
|
||||||
names.iter().position(|other| other == dir).unwrap(),
|
names.iter().position(|other| other == dir).unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => sbp::euler::BoundaryCharacteristic::This,
|
None => euler::BoundaryCharacteristic::This,
|
||||||
};
|
};
|
||||||
for name in &names {
|
for name in &names {
|
||||||
let bc = &jsongrids[name]["boundary_conditions"];
|
let bc = &jsongrids[name]["boundary_conditions"];
|
||||||
|
@ -179,7 +179,7 @@ pub fn json_to_grids(
|
||||||
let bc_e = determine_bc(bc["east"].as_str());
|
let bc_e = determine_bc(bc["east"].as_str());
|
||||||
let bc_w = determine_bc(bc["west"].as_str());
|
let bc_w = determine_bc(bc["west"].as_str());
|
||||||
|
|
||||||
let bc = sbp::euler::BoundaryCharacteristics {
|
let bc = euler::BoundaryCharacteristics {
|
||||||
north: bc_n,
|
north: bc_n,
|
||||||
south: bc_s,
|
south: bc_s,
|
||||||
east: bc_e,
|
east: bc_e,
|
||||||
|
@ -349,7 +349,7 @@ fn json2grid(x: JsonValue, y: JsonValue) -> Result<Grid, String> {
|
||||||
Ok(Grid::new(x, y).unwrap())
|
Ok(Grid::new(x, y).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn json_to_vortex(mut json: JsonValue) -> super::euler::VortexParameters {
|
pub fn json_to_vortex(mut json: JsonValue) -> euler::VortexParameters {
|
||||||
let mach = json.remove("mach").as_number().unwrap().into();
|
let mach = json.remove("mach").as_number().unwrap().into();
|
||||||
|
|
||||||
// Get max length of any (potential) array
|
// Get max length of any (potential) array
|
||||||
|
@ -377,9 +377,9 @@ pub fn json_to_vortex(mut json: JsonValue) -> super::euler::VortexParameters {
|
||||||
let rstar = into_iterator(json.remove("rstar"));
|
let rstar = into_iterator(json.remove("rstar"));
|
||||||
let eps = into_iterator(json.remove("eps"));
|
let eps = into_iterator(json.remove("eps"));
|
||||||
|
|
||||||
let mut vortices = sbp::euler::ArrayVec::new();
|
let mut vortices = euler::ArrayVec::new();
|
||||||
for (((x0, y0), rstar), eps) in x0.zip(y0).zip(rstar).zip(eps).take(maxlen) {
|
for (((x0, y0), rstar), eps) in x0.zip(y0).zip(rstar).zip(eps).take(maxlen) {
|
||||||
vortices.push(sbp::euler::Vortice { x0, y0, rstar, eps })
|
vortices.push(euler::Vortice { x0, y0, rstar, eps })
|
||||||
}
|
}
|
||||||
|
|
||||||
if !json.is_empty() {
|
if !json.is_empty() {
|
||||||
|
@ -389,5 +389,5 @@ pub fn json_to_vortex(mut json: JsonValue) -> super::euler::VortexParameters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super::euler::VortexParameters { vortices, mach }
|
euler::VortexParameters { vortices, mach }
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,26 +9,14 @@ ndarray = { version = "0.13.1", features = ["approx"] }
|
||||||
approx = "0.3.2"
|
approx = "0.3.2"
|
||||||
packed_simd = "0.3.3"
|
packed_simd = "0.3.3"
|
||||||
rayon = { version = "1.3.0", optional = true }
|
rayon = { version = "1.3.0", optional = true }
|
||||||
arrayvec = "0.5.1"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Internal feature flag to gate the expensive tests
|
|
||||||
# which should be run only in release builds
|
|
||||||
expensive_tests = []
|
|
||||||
# Use f32 as precision, default is f64
|
# Use f32 as precision, default is f64
|
||||||
f32 = []
|
f32 = []
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.3.1"
|
criterion = "0.3.1"
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "maxwell"
|
|
||||||
harness = false
|
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "euler"
|
|
||||||
harness = false
|
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "sbpoperators"
|
name = "sbpoperators"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::operators::SbpOperator2d;
|
use super::operators::SbpOperator2d;
|
||||||
use crate::Float;
|
use crate::Float;
|
||||||
use ndarray::Array2;
|
use ndarray::{Array2, ArrayView2};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Grid {
|
pub struct Grid {
|
||||||
|
@ -115,3 +115,21 @@ impl Metrics {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Metrics {
|
||||||
|
pub fn detj(&self) -> ArrayView2<Float> {
|
||||||
|
self.detj.view()
|
||||||
|
}
|
||||||
|
pub fn detj_dxi_dx(&self) -> ArrayView2<Float> {
|
||||||
|
self.detj_dxi_dx.view()
|
||||||
|
}
|
||||||
|
pub fn detj_dxi_dy(&self) -> ArrayView2<Float> {
|
||||||
|
self.detj_dxi_dy.view()
|
||||||
|
}
|
||||||
|
pub fn detj_deta_dx(&self) -> ArrayView2<Float> {
|
||||||
|
self.detj_deta_dx.view()
|
||||||
|
}
|
||||||
|
pub fn detj_deta_dy(&self) -> ArrayView2<Float> {
|
||||||
|
self.detj_deta_dy.view()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,16 +6,14 @@ pub type Float = f32;
|
||||||
#[cfg(not(feature = "f32"))]
|
#[cfg(not(feature = "f32"))]
|
||||||
pub type Float = f64;
|
pub type Float = f64;
|
||||||
|
|
||||||
pub(crate) mod consts {
|
pub mod consts {
|
||||||
#[cfg(feature = "f32")]
|
#[cfg(feature = "f32")]
|
||||||
pub(crate) use std::f32::consts::*;
|
pub use std::f32::consts::*;
|
||||||
#[cfg(not(feature = "f32"))]
|
#[cfg(not(feature = "f32"))]
|
||||||
pub(crate) use std::f64::consts::*;
|
pub use std::f64::consts::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod euler;
|
|
||||||
pub mod grid;
|
pub mod grid;
|
||||||
pub mod integrate;
|
pub mod integrate;
|
||||||
pub mod maxwell;
|
|
||||||
pub mod operators;
|
pub mod operators;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
|
@ -7,6 +7,33 @@ pub struct Direction<T> {
|
||||||
pub east: T,
|
pub east: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Direction<T> {
|
||||||
|
pub fn north(&self) -> &T {
|
||||||
|
&self.north
|
||||||
|
}
|
||||||
|
pub fn north_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.north
|
||||||
|
}
|
||||||
|
pub fn south(&self) -> &T {
|
||||||
|
&self.south
|
||||||
|
}
|
||||||
|
pub fn south_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.south
|
||||||
|
}
|
||||||
|
pub fn east(&self) -> &T {
|
||||||
|
&self.east
|
||||||
|
}
|
||||||
|
pub fn east_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.east
|
||||||
|
}
|
||||||
|
pub fn west(&self) -> &T {
|
||||||
|
&self.west
|
||||||
|
}
|
||||||
|
pub fn west_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.west
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn h2linspace(start: Float, end: Float, n: usize) -> ndarray::Array1<Float> {
|
pub fn h2linspace(start: Float, end: Float, n: usize) -> ndarray::Array1<Float> {
|
||||||
let h = (end - start) / (n - 2) as Float;
|
let h = (end - start) / (n - 2) as Float;
|
||||||
ndarray::Array1::from_shape_fn(n, |i| match i {
|
ndarray::Array1::from_shape_fn(n, |i| match i {
|
||||||
|
|
|
@ -14,3 +14,5 @@ console_error_panic_hook = "0.1.6"
|
||||||
wee_alloc = "0.4.5"
|
wee_alloc = "0.4.5"
|
||||||
sbp = { path = "../sbp", features = ["f32"] }
|
sbp = { path = "../sbp", features = ["f32"] }
|
||||||
ndarray = "0.13.0"
|
ndarray = "0.13.0"
|
||||||
|
euler = { path = "../euler" }
|
||||||
|
maxwell = { path = "../maxwell" }
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
use sbp::{euler, maxwell, operators};
|
use euler;
|
||||||
|
use maxwell;
|
||||||
|
use sbp::operators;
|
||||||
|
|
||||||
#[cfg(feature = "wee_alloc")]
|
#[cfg(feature = "wee_alloc")]
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
|
|
Loading…
Reference in New Issue