diff --git a/sbp/Cargo.toml b/sbp/Cargo.toml index a84bb47..6c3bc23 100644 --- a/sbp/Cargo.toml +++ b/sbp/Cargo.toml @@ -14,6 +14,8 @@ json = "0.12.1" # 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 +f32 = [] [dev-dependencies] criterion = "0.3.0" diff --git a/sbp/benches/maxwell.rs b/sbp/benches/maxwell.rs index 5521cc3..f532e5e 100644 --- a/sbp/benches/maxwell.rs +++ b/sbp/benches/maxwell.rs @@ -1,6 +1,7 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use sbp::maxwell::System; use sbp::operators::{SbpOperator, Upwind4, UpwindOperator, SBP4}; +use sbp::Float; fn advance_system(universe: &mut System, n: usize) { for _ in 0..n { @@ -20,8 +21,8 @@ fn performance_benchmark(c: &mut Criterion) { let w = 40; let h = 26; - let x = ndarray::Array2::from_shape_fn((h, w), |(_, i)| i as f32 / (w - 1) as f32); - let y = ndarray::Array2::from_shape_fn((h, w), |(j, _)| j as f32 / (h - 1) as f32); + let x = ndarray::Array2::from_shape_fn((h, w), |(_, i)| i as Float / (w - 1) as Float); + let y = ndarray::Array2::from_shape_fn((h, w), |(j, _)| j as Float / (h - 1) as Float); let mut universe = System::::new(x.clone(), y.clone()); group.bench_function("advance", |b| { diff --git a/sbp/src/euler.rs b/sbp/src/euler.rs index a9d2512..1181597 100644 --- a/sbp/src/euler.rs +++ b/sbp/src/euler.rs @@ -1,10 +1,11 @@ use super::grid::Grid; use super::integrate; use super::operators::{SbpOperator, UpwindOperator}; +use super::Float; use ndarray::azip; use ndarray::prelude::*; -pub const GAMMA: f32 = 1.4; +pub const GAMMA: Float = 1.4; // A collection of buffers that allows one to efficiently // move to the next state @@ -16,7 +17,7 @@ pub struct System { } impl System { - pub fn new(x: ndarray::Array2, y: ndarray::Array2) -> Self { + pub fn new(x: ndarray::Array2, y: ndarray::Array2) -> Self { let grid = Grid::new(x, y).expect( "Could not create grid. Different number of elements compared to width*height?", ); @@ -29,7 +30,7 @@ impl System { } } - pub fn advance(&mut self, dt: f32) { + pub fn advance(&mut self, dt: Float) { let rhs_trad = |k: &mut Field, y: &Field, grid: &_, wb: &mut _| { let boundaries = BoundaryTerms { north: y.south(), @@ -51,14 +52,14 @@ impl System { std::mem::swap(&mut self.sys.0, &mut self.sys.1); } - pub fn vortex(&mut self, t: f32, vortex_parameters: VortexParameters) { + pub fn vortex(&mut self, t: Float, vortex_parameters: VortexParameters) { self.sys .0 .vortex(self.grid.x.view(), self.grid.y.view(), t, vortex_parameters); } #[allow(clippy::many_single_char_names)] - pub fn init_with_vortex(&mut self, x0: f32, y0: f32) { + pub fn init_with_vortex(&mut self, x0: Float, y0: Float) { // Should parametrise such that we have radius, drop in pressure at center, etc let vortex_parameters = VortexParameters { x0, @@ -80,16 +81,16 @@ impl System { &self.sys.0 } - pub fn x(&self) -> ArrayView2 { + pub fn x(&self) -> ArrayView2 { self.grid.x.view() } - pub fn y(&self) -> ArrayView2 { + pub fn y(&self) -> ArrayView2 { self.grid.y.view() } } impl System { - pub fn advance_upwind(&mut self, dt: f32) { + pub fn advance_upwind(&mut self, dt: Float) { let rhs_upwind = |k: &mut Field, y: &Field, grid: &_, wb: &mut _| { let boundaries = BoundaryTerms { north: y.south(), @@ -114,10 +115,10 @@ impl System { #[derive(Clone, Debug)] /// A 4 x ny x nx array -pub struct Field(pub(crate) Array3); +pub struct Field(pub(crate) Array3); impl std::ops::Deref for Field { - type Target = Array3; + type Target = Array3; fn deref(&self) -> &Self::Target { &self.0 } @@ -143,29 +144,29 @@ impl Field { self.0.shape()[1] } - pub fn rho(&self) -> ArrayView2 { + pub fn rho(&self) -> ArrayView2 { self.slice(s![0, .., ..]) } - pub fn rhou(&self) -> ArrayView2 { + pub fn rhou(&self) -> ArrayView2 { self.slice(s![1, .., ..]) } - pub fn rhov(&self) -> ArrayView2 { + pub fn rhov(&self) -> ArrayView2 { self.slice(s![2, .., ..]) } - pub fn e(&self) -> ArrayView2 { + pub fn e(&self) -> ArrayView2 { self.slice(s![3, .., ..]) } - pub fn rho_mut(&mut self) -> ArrayViewMut2 { + pub fn rho_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![0, .., ..]) } - pub fn rhou_mut(&mut self) -> ArrayViewMut2 { + pub fn rhou_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![1, .., ..]) } - pub fn rhov_mut(&mut self) -> ArrayViewMut2 { + pub fn rhov_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![2, .., ..]) } - pub fn e_mut(&mut self) -> ArrayViewMut2 { + pub fn e_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![3, .., ..]) } @@ -173,10 +174,10 @@ impl Field { pub fn components( &self, ) -> ( - ArrayView2, - ArrayView2, - ArrayView2, - ArrayView2, + ArrayView2, + ArrayView2, + ArrayView2, + ArrayView2, ) { (self.rho(), self.rhou(), self.rhov(), self.e()) } @@ -184,10 +185,10 @@ impl Field { pub fn components_mut( &mut self, ) -> ( - ArrayViewMut2, - ArrayViewMut2, - ArrayViewMut2, - ArrayViewMut2, + ArrayViewMut2, + ArrayViewMut2, + ArrayViewMut2, + ArrayViewMut2, ) { let mut iter = self.0.outer_iter_mut(); @@ -200,38 +201,38 @@ impl Field { (rho, rhou, rhov, e) } - fn north(&self) -> ArrayView2 { + fn north(&self) -> ArrayView2 { self.slice(s![.., self.ny() - 1, ..]) } - fn south(&self) -> ArrayView2 { + fn south(&self) -> ArrayView2 { self.slice(s![.., 0, ..]) } - fn east(&self) -> ArrayView2 { + fn east(&self) -> ArrayView2 { self.slice(s![.., .., self.nx() - 1]) } - fn west(&self) -> ArrayView2 { + fn west(&self) -> ArrayView2 { self.slice(s![.., .., 0]) } - fn north_mut(&mut self) -> ArrayViewMut2 { + fn north_mut(&mut self) -> ArrayViewMut2 { let ny = self.ny(); self.slice_mut(s![.., ny - 1, ..]) } - fn south_mut(&mut self) -> ArrayViewMut2 { + fn south_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![.., 0, ..]) } - fn east_mut(&mut self) -> ArrayViewMut2 { + fn east_mut(&mut self) -> ArrayViewMut2 { let nx = self.nx(); self.slice_mut(s![.., .., nx - 1]) } - fn west_mut(&mut self) -> ArrayViewMut2 { + fn west_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![.., .., 0]) } pub fn vortex( &mut self, - x: ArrayView2, - y: ArrayView2, - t: f32, + x: ArrayView2, + y: ArrayView2, + t: Float, vortex_param: VortexParameters, ) { assert_eq!(x.shape(), y.shape()); @@ -251,14 +252,18 @@ impl Field { x in x, y in y) { + #[cfg(feature = "f32")] use std::f32::consts::PI; + #[cfg(not(feature = "f32"))] + use std::f64::consts::PI; + let dx = (x - vortex_param.x0) - t; let dy = y - vortex_param.y0; let f = (1.0 - (dx*dx + dy*dy))/(rstar*rstar); - *rho = f32::powf(1.0 - eps*eps*(GAMMA - 1.0)*m*m/(8.0*PI*PI*p_inf*rstar*rstar)*f.exp(), 1.0/(GAMMA - 1.0)); + *rho = Float::powf(1.0 - eps*eps*(GAMMA - 1.0)*m*m/(8.0*PI*PI*p_inf*rstar*rstar)*f.exp(), 1.0/(GAMMA - 1.0)); assert!(*rho > 0.0); - let p = f32::powf(*rho, GAMMA)*p_inf; + let p = Float::powf(*rho, GAMMA)*p_inf; assert!(p > 0.0); let u = 1.0 - eps*dy/(2.0*PI*p_inf.sqrt()*rstar*rstar)*(f/2.0).exp(); let v = eps*dx/(2.0*PI*p_inf.sqrt()*rstar*rstar)*(f/2.0).exp(); @@ -271,7 +276,7 @@ impl Field { impl Field { /// sqrt((self-other)^T*H*(self-other)) - pub fn h2_err(&self, other: &Self) -> f32 { + pub fn h2_err(&self, other: &Self) -> Float { assert_eq!(self.nx(), other.nx()); assert_eq!(self.ny(), other.ny()); @@ -285,7 +290,7 @@ impl Field { // This chains the h block into the form [h, 1, 1, 1, rev(h)], // and multiplies with a factor - let itermaker = move |n: usize, factor: f32| { + let itermaker = move |n: usize, factor: Float| { h.iter() .copied() .chain(std::iter::repeat(1.0).take(n - 2 * h.len())) @@ -293,12 +298,12 @@ impl Field { .map(move |x| x * factor) }; - let hxiterator = itermaker(self.nx(), 1.0 / (self.nx() - 1) as f32); + let hxiterator = itermaker(self.nx(), 1.0 / (self.nx() - 1) as Float); // Repeating to get the form // [[hx0, hx1, ..., hxn], [hx0, hx1, ..., hxn], ..., [hx0, hx1, ..., hxn]] let hxiterator = hxiterator.into_iter().cycle().take(self.nx() * self.ny()); - let hyiterator = itermaker(self.ny(), 1.0 / (self.ny() - 1) as f32); + let hyiterator = itermaker(self.ny(), 1.0 / (self.ny() - 1) as Float); // Repeating to get the form // [[hy0, hy0, ..., hy0], [hy1, hy1, ..., hy1], ..., [hym, hym, ..., hym]] let hyiterator = hyiterator @@ -312,7 +317,7 @@ impl Field { .zip(self.0.iter()) .zip(other.0.iter()) .map(|(((hx, hy), r0), r1)| (*r0 - *r1).powi(2) * hx * hy) - .sum::() + .sum::() .sqrt() } } @@ -333,14 +338,14 @@ fn h2_diff() { #[derive(Copy, Clone)] pub struct VortexParameters { - pub x0: f32, - pub y0: f32, - pub rstar: f32, - pub eps: f32, - pub mach: f32, + pub x0: Float, + pub y0: Float, + pub rstar: Float, + pub eps: Float, + pub mach: Float, } -fn pressure(gamma: f32, rho: f32, rhou: f32, rhov: f32, e: f32) -> f32 { +fn pressure(gamma: Float, rho: Float, rhou: Float, rhov: Float, e: Float) -> Float { (gamma - 1.0) * (e - (rhou * rhou + rhov * rhov) / (2.0 * rho)) } @@ -534,10 +539,10 @@ fn fluxes(k: (&mut Field, &mut Field), y: &Field, grid: &Grid< #[derive(Clone, Debug)] pub struct BoundaryTerms<'a> { - pub north: ArrayView2<'a, f32>, - pub south: ArrayView2<'a, f32>, - pub east: ArrayView2<'a, f32>, - pub west: ArrayView2<'a, f32>, + pub north: ArrayView2<'a, Float>, + pub south: ArrayView2<'a, Float>, + pub east: ArrayView2<'a, Float>, + pub west: ArrayView2<'a, Float>, } #[allow(non_snake_case)] @@ -550,7 +555,7 @@ fn SAT_characteristics( ) { // North boundary { - let hi = (k.ny() - 1) as f32 * SBP::h()[0]; + let hi = (k.ny() - 1) as Float * SBP::h()[0]; let sign = -1.0; let tau = 1.0; let slice = s![y.ny() - 1, ..]; @@ -568,7 +573,7 @@ fn SAT_characteristics( } // South boundary { - let hi = (k.ny() - 1) as f32 * SBP::h()[0]; + let hi = (k.ny() - 1) as Float * SBP::h()[0]; let sign = 1.0; let tau = -1.0; let slice = s![0, ..]; @@ -586,7 +591,7 @@ fn SAT_characteristics( } // West Boundary { - let hi = (k.nx() - 1) as f32 * SBP::h()[0]; + let hi = (k.nx() - 1) as Float * SBP::h()[0]; let sign = 1.0; let tau = -1.0; let slice = s![.., 0]; @@ -604,7 +609,7 @@ fn SAT_characteristics( } // East Boundary { - let hi = (k.nx() - 1) as f32 * SBP::h()[0]; + let hi = (k.nx() - 1) as Float * SBP::h()[0]; let sign = -1.0; let tau = 1.0; let slice = s![.., y.nx() - 1]; @@ -627,15 +632,15 @@ fn SAT_characteristics( #[allow(clippy::too_many_arguments)] /// Boundary conditions (SAT) fn SAT_characteristic( - mut k: ArrayViewMut2, - y: ArrayView2, - z: ArrayView2, // Size 4 x n (all components in line) - hi: f32, - sign: f32, - tau: f32, - detj: ArrayView1, - detj_d_dx: ArrayView1, - detj_d_dy: ArrayView1, + mut k: ArrayViewMut2, + y: ArrayView2, + z: ArrayView2, // Size 4 x n (all components in line) + hi: Float, + sign: Float, + tau: Float, + detj: ArrayView1, + detj_d_dx: ArrayView1, + detj_d_dy: ArrayView1, ) { assert_eq!(detj.shape(), detj_d_dx.shape()); assert_eq!(detj.shape(), detj_d_dy.shape()); @@ -660,7 +665,7 @@ fn SAT_characteristic( let ky_ = detj_d_dy / detj; let (kx, ky) = { - let r = f32::hypot(kx_, ky_); + let r = Float::hypot(kx_, ky_); (kx_ / r, ky_ / r) }; @@ -690,8 +695,8 @@ fn SAT_characteristic( let L = [ U, U, - U + c * f32::hypot(kx_, ky_), - U - c * f32::hypot(kx_, ky_), + U + c * Float::hypot(kx_, ky_), + U - c * Float::hypot(kx_, ky_), ]; let beta = 1.0 / (2.0 * c * c); let TI = [ diff --git a/sbp/src/grid.rs b/sbp/src/grid.rs index 126ab0e..8c0cdec 100644 --- a/sbp/src/grid.rs +++ b/sbp/src/grid.rs @@ -1,3 +1,4 @@ +use crate::Float; use ndarray::Array2; #[derive(Debug, Clone)] @@ -5,20 +6,20 @@ pub struct Grid where SBP: super::operators::SbpOperator, { - pub(crate) x: Array2, - pub(crate) y: Array2, + pub(crate) x: Array2, + pub(crate) y: Array2, - pub(crate) detj: Array2, - pub(crate) detj_dxi_dx: Array2, - pub(crate) detj_dxi_dy: Array2, - pub(crate) detj_deta_dx: Array2, - pub(crate) detj_deta_dy: Array2, + pub(crate) detj: Array2, + pub(crate) detj_dxi_dx: Array2, + pub(crate) detj_dxi_dy: Array2, + pub(crate) detj_deta_dx: Array2, + pub(crate) detj_deta_dy: Array2, operator: std::marker::PhantomData, } impl Grid { - pub fn new(x: Array2, y: Array2) -> Result { + pub fn new(x: Array2, y: Array2) -> Result { assert_eq!(x.shape(), y.shape()); let ny = x.shape()[0]; let nx = x.shape()[1]; diff --git a/sbp/src/integrate.rs b/sbp/src/integrate.rs index dcd691c..7969561 100644 --- a/sbp/src/integrate.rs +++ b/sbp/src/integrate.rs @@ -1,17 +1,18 @@ use super::grid::Grid; use super::operators::SbpOperator; +use super::Float; use ndarray::{Array3, Zip}; pub(crate) fn rk4<'a, F: 'a, SBP, RHS, WB>( rhs: RHS, prev: &F, fut: &mut F, - dt: f32, + dt: Float, grid: &Grid, k: &mut [F; 4], mut wb: &mut WB, ) where - F: std::ops::Deref> + std::ops::DerefMut>, + F: std::ops::Deref> + std::ops::DerefMut>, SBP: SbpOperator, RHS: Fn(&mut F, &F, &Grid, &mut WB), { diff --git a/sbp/src/lib.rs b/sbp/src/lib.rs index e27982a..9438284 100644 --- a/sbp/src/lib.rs +++ b/sbp/src/lib.rs @@ -1,3 +1,8 @@ +#[cfg(feature = "f32")] +pub type Float = f32; +#[cfg(not(feature = "f32"))] +pub type Float = f64; + pub mod euler; pub mod grid; pub mod integrate; diff --git a/sbp/src/maxwell.rs b/sbp/src/maxwell.rs index 3e98063..ac46dc3 100644 --- a/sbp/src/maxwell.rs +++ b/sbp/src/maxwell.rs @@ -1,14 +1,15 @@ use super::grid::Grid; use super::integrate; use super::operators::{SbpOperator, UpwindOperator}; +use crate::Float; use ndarray::azip; use ndarray::prelude::*; #[derive(Clone, Debug)] -pub struct Field(pub(crate) Array3); +pub struct Field(pub(crate) Array3); impl std::ops::Deref for Field { - type Target = Array3; + type Target = Array3; fn deref(&self) -> &Self::Target { &self.0 } @@ -34,29 +35,33 @@ impl Field { self.0.shape()[1] } - pub fn ex(&self) -> ArrayView2 { + pub fn ex(&self) -> ArrayView2 { self.slice(s![0, .., ..]) } - pub fn hz(&self) -> ArrayView2 { + pub fn hz(&self) -> ArrayView2 { self.slice(s![1, .., ..]) } - pub fn ey(&self) -> ArrayView2 { + pub fn ey(&self) -> ArrayView2 { self.slice(s![2, .., ..]) } - pub fn ex_mut(&mut self) -> ArrayViewMut2 { + pub fn ex_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![0, .., ..]) } - pub fn hz_mut(&mut self) -> ArrayViewMut2 { + pub fn hz_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![1, .., ..]) } - pub fn ey_mut(&mut self) -> ArrayViewMut2 { + pub fn ey_mut(&mut self) -> ArrayViewMut2 { self.slice_mut(s![2, .., ..]) } pub fn components_mut( &mut self, - ) -> (ArrayViewMut2, ArrayViewMut2, ArrayViewMut2) { + ) -> ( + ArrayViewMut2, + ArrayViewMut2, + ArrayViewMut2, + ) { let mut iter = self.0.outer_iter_mut(); let ex = iter.next().unwrap(); @@ -76,7 +81,7 @@ pub struct System { } impl System { - pub fn new(x: Array2, y: Array2) -> Self { + pub fn new(x: Array2, y: Array2) -> Self { assert_eq!(x.shape(), y.shape()); let ny = x.shape()[0]; let nx = x.shape()[1]; @@ -94,7 +99,7 @@ impl System { &self.sys.0 } - pub fn set_gaussian(&mut self, x0: f32, y0: f32) { + pub fn set_gaussian(&mut self, x0: Float, y0: Float) { let (ex, hz, ey) = self.sys.0.components_mut(); ndarray::azip!( (ex in ex, hz in hz, ey in ey, @@ -106,7 +111,7 @@ impl System { }); } - pub fn advance(&mut self, dt: f32) { + pub fn advance(&mut self, dt: Float) { integrate::rk4( RHS, &self.sys.0, @@ -122,7 +127,7 @@ impl System { impl System { /// Using artificial dissipation with the upwind operator - pub fn advance_upwind(&mut self, dt: f32) { + pub fn advance_upwind(&mut self, dt: Float) { integrate::rk4( RHS_upwind, &self.sys.0, @@ -136,14 +141,18 @@ impl System { } } -fn gaussian(x: f32, x0: f32, y: f32, y0: f32) -> f32 { - use std::f32; +fn gaussian(x: Float, x0: Float, y: Float, y0: Float) -> Float { + #[cfg(feature = "f32")] + use std::f32::consts::PI; + #[cfg(not(feature = "f32"))] + use std::f64::consts::PI; + let x = x - x0; let y = y - y0; let sigma = 0.05; - 1.0 / (2.0 * f32::consts::PI * sigma * sigma) * (-(x * x + y * y) / (2.0 * sigma * sigma)).exp() + 1.0 / (2.0 * PI * sigma * sigma) * (-(x * x + y * y) / (2.0 * sigma * sigma)).exp() } #[allow(non_snake_case)] @@ -166,7 +175,7 @@ fn RHS( k: &mut Field, y: &Field, grid: &Grid, - tmp: &mut (Array2, Array2, Array2, Array2), + tmp: &mut (Array2, Array2, Array2, Array2), ) { fluxes(k, y, grid, tmp); @@ -189,7 +198,7 @@ fn RHS_upwind( k: &mut Field, y: &Field, grid: &Grid, - tmp: &mut (Array2, Array2, Array2, Array2), + tmp: &mut (Array2, Array2, Array2, Array2), ) { fluxes(k, y, grid, tmp); dissipation(k, y, grid, tmp); @@ -212,7 +221,7 @@ fn fluxes( k: &mut Field, y: &Field, grid: &Grid, - tmp: &mut (Array2, Array2, Array2, Array2), + tmp: &mut (Array2, Array2, Array2, Array2), ) { // ex = hz_y { @@ -286,7 +295,7 @@ fn dissipation( k: &mut Field, y: &Field, grid: &Grid, - tmp: &mut (Array2, Array2, Array2, Array2), + tmp: &mut (Array2, Array2, Array2, Array2), ) { // ex component { @@ -295,7 +304,7 @@ fn dissipation( &ky in &grid.detj_dxi_dy, &ex in &y.ex(), &ey in &y.ey()) { - let r = f32::hypot(kx, ky); + let r = Float::hypot(kx, ky); *a = ky*ky/r * ex + -kx*ky/r*ey; }); UO::dissxi(tmp.0.view(), tmp.1.view_mut()); @@ -305,7 +314,7 @@ fn dissipation( &ky in &grid.detj_deta_dy, &ex in &y.ex(), &ey in &y.ey()) { - let r = f32::hypot(kx, ky); + let r = Float::hypot(kx, ky); *b = ky*ky/r * ex + -kx*ky/r*ey; }); UO::disseta(tmp.2.view(), tmp.3.view_mut()); @@ -321,7 +330,7 @@ fn dissipation( &kx in &grid.detj_dxi_dx, &ky in &grid.detj_dxi_dy, &hz in &y.hz()) { - let r = f32::hypot(kx, ky); + let r = Float::hypot(kx, ky); *a = r * hz; }); UO::dissxi(tmp.0.view(), tmp.1.view_mut()); @@ -330,7 +339,7 @@ fn dissipation( &kx in &grid.detj_deta_dx, &ky in &grid.detj_deta_dy, &hz in &y.hz()) { - let r = f32::hypot(kx, ky); + let r = Float::hypot(kx, ky); *b = r * hz; }); UO::disseta(tmp.2.view(), tmp.3.view_mut()); @@ -347,7 +356,7 @@ fn dissipation( &ky in &grid.detj_dxi_dy, &ex in &y.ex(), &ey in &y.ey()) { - let r = f32::hypot(kx, ky); + let r = Float::hypot(kx, ky); *a = -kx*ky/r * ex + kx*kx/r*ey; }); UO::dissxi(tmp.0.view(), tmp.1.view_mut()); @@ -357,7 +366,7 @@ fn dissipation( &ky in &grid.detj_deta_dy, &ex in &y.ex(), &ey in &y.ey()) { - let r = f32::hypot(kx, ky); + let r = Float::hypot(kx, ky); *b = -kx*ky/r * ex + kx*kx/r*ey; }); UO::disseta(tmp.2.view(), tmp.3.view_mut()); @@ -392,7 +401,7 @@ fn SAT_characteristics( let ny = y.ny(); let nx = y.nx(); - fn positive_flux(kx: f32, ky: f32) -> [[f32; 3]; 3] { + fn positive_flux(kx: Float, ky: Float) -> [[Float; 3]; 3] { let r = (kx * kx + ky * ky).sqrt(); [ [ky * ky / r / 2.0, ky / 2.0, -kx * ky / r / 2.0], @@ -400,7 +409,7 @@ fn SAT_characteristics( [-kx * ky / r / 2.0, -kx / 2.0, kx * kx / r / 2.0], ] } - fn negative_flux(kx: f32, ky: f32) -> [[f32; 3]; 3] { + fn negative_flux(kx: Float, ky: Float) -> [[Float; 3]; 3] { let r = (kx * kx + ky * ky).sqrt(); [ [-ky * ky / r / 2.0, ky / 2.0, kx * ky / r / 2.0], @@ -414,7 +423,7 @@ fn SAT_characteristics( Boundary::This => y.slice(s![.., .., 0]), }; // East boundary - let hinv = 1.0 / (SBP::h()[0] / (nx - 1) as f32); + let hinv = 1.0 / (SBP::h()[0] / (nx - 1) as Float); for ((((mut k, v), g), &kx), &ky) in k .slice_mut(s![.., .., nx - 1]) .gencolumns_mut() @@ -448,7 +457,7 @@ fn SAT_characteristics( let g = match boundaries.east { Boundary::This => y.slice(s![.., .., nx - 1]), }; - let hinv = 1.0 / (SBP::h()[0] / (nx - 1) as f32); + let hinv = 1.0 / (SBP::h()[0] / (nx - 1) as Float); for ((((mut k, v), g), &kx), &ky) in k .slice_mut(s![.., .., 0]) .gencolumns_mut() @@ -487,7 +496,7 @@ fn SAT_characteristics( let g = match boundaries.north { Boundary::This => y.slice(s![.., 0, ..]), }; - let hinv = 1.0 / (SBP::h()[0] / (ny - 1) as f32); + let hinv = 1.0 / (SBP::h()[0] / (ny - 1) as Float); for ((((mut k, v), g), &kx), &ky) in k .slice_mut(s![.., ny - 1, ..]) .gencolumns_mut() @@ -520,7 +529,7 @@ fn SAT_characteristics( let g = match boundaries.south { Boundary::This => y.slice(s![.., ny - 1, ..]), }; - let hinv = 1.0 / (SBP::h()[0] / (ny - 1) as f32); + let hinv = 1.0 / (SBP::h()[0] / (ny - 1) as Float); for ((((mut k, v), g), &kx), &ky) in k .slice_mut(s![.., 0, ..]) .gencolumns_mut() @@ -560,7 +569,7 @@ fn SAT_characteristics( #[derive(Clone, Debug)] pub struct WorkBuffers { k: [Field; 4], - tmp: (Array2, Array2, Array2, Array2), + tmp: (Array2, Array2, Array2, Array2), } impl WorkBuffers { diff --git a/sbp/src/operators.rs b/sbp/src/operators.rs index e128b73..1457429 100644 --- a/sbp/src/operators.rs +++ b/sbp/src/operators.rs @@ -1,29 +1,31 @@ #![allow(clippy::excessive_precision)] #![allow(clippy::unreadable_literal)] +use crate::Float; + use ndarray::{ArrayView2, ArrayViewMut2}; pub trait SbpOperator { - fn diffxi(prev: ArrayView2, fut: ArrayViewMut2); - fn diffeta(prev: ArrayView2, fut: ArrayViewMut2); - fn h() -> &'static [f32]; + fn diffxi(prev: ArrayView2, fut: ArrayViewMut2); + fn diffeta(prev: ArrayView2, fut: ArrayViewMut2); + fn h() -> &'static [Float]; } pub trait UpwindOperator: SbpOperator { - fn dissxi(prev: ArrayView2, fut: ArrayViewMut2); - fn disseta(prev: ArrayView2, fut: ArrayViewMut2); + fn dissxi(prev: ArrayView2, fut: ArrayViewMut2); + fn disseta(prev: ArrayView2, fut: ArrayViewMut2); } #[macro_export] macro_rules! diff_op_1d { ($self: ty, $name: ident, $BLOCK: expr, $DIAG: expr, $symmetric: expr) => { impl $self { - fn $name(prev: ArrayView1, mut fut: ArrayViewMut1) { + fn $name(prev: ArrayView1, mut fut: ArrayViewMut1) { assert_eq!(prev.shape(), fut.shape()); let nx = prev.shape()[0]; assert!(nx >= 2 * $BLOCK.len()); - let dx = 1.0 / (nx - 1) as f32; + let dx = 1.0 / (nx - 1) as Float; let idx = 1.0 / dx; let block = ::ndarray::arr2($BLOCK); diff --git a/sbp/src/operators/traditional4.rs b/sbp/src/operators/traditional4.rs index 10051f1..f1b546b 100644 --- a/sbp/src/operators/traditional4.rs +++ b/sbp/src/operators/traditional4.rs @@ -1,5 +1,6 @@ use super::SbpOperator; use crate::diff_op_1d; +use crate::Float; use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2}; #[derive(Debug)] @@ -9,15 +10,15 @@ diff_op_1d!(SBP4, diff_1d, SBP4::BLOCK, SBP4::DIAG, false); impl SBP4 { #[rustfmt::skip] - const HBLOCK: &'static [f32] = &[ + const HBLOCK: &'static [Float] = &[ 17.0 / 48.0, 59.0 / 48.0, 43.0 / 48.0, 49.0 / 48.0, ]; #[rustfmt::skip] - const DIAG: &'static [f32] = &[ + const DIAG: &'static [Float] = &[ 1.0 / 12.0, -2.0 / 3.0, 0.0, 2.0 / 3.0, -1.0 / 12.0, ]; #[rustfmt::skip] - const BLOCK: &'static [[f32; 6]] = &[ + const BLOCK: &'static [[Float; 6]] = &[ [-1.41176470588235e+00, 1.73529411764706e+00, -2.35294117647059e-01, -8.82352941176471e-02, 0.00000000000000e+00, 0.00000000000000e+00], [-5.00000000000000e-01, 0.00000000000000e+00, 5.00000000000000e-01, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], [9.30232558139535e-02, -6.86046511627907e-01, 0.00000000000000e+00, 6.86046511627907e-01, -9.30232558139535e-02, 0.00000000000000e+00], @@ -26,7 +27,7 @@ impl SBP4 { } impl SbpOperator for SBP4 { - fn diffxi(prev: ArrayView2, mut fut: ArrayViewMut2) { + fn diffxi(prev: ArrayView2, mut fut: ArrayViewMut2) { assert_eq!(prev.shape(), fut.shape()); assert!(prev.shape()[1] >= 2 * Self::BLOCK.len()); @@ -35,12 +36,12 @@ impl SbpOperator for SBP4 { } } - fn diffeta(prev: ArrayView2, fut: ArrayViewMut2) { + fn diffeta(prev: ArrayView2, fut: ArrayViewMut2) { // transpose then use diffxi Self::diffxi(prev.reversed_axes(), fut.reversed_axes()); } - fn h() -> &'static [f32] { + fn h() -> &'static [Float] { Self::HBLOCK } } diff --git a/sbp/src/operators/traditional8.rs b/sbp/src/operators/traditional8.rs index eb656ad..fb390cc 100644 --- a/sbp/src/operators/traditional8.rs +++ b/sbp/src/operators/traditional8.rs @@ -1,5 +1,6 @@ use super::SbpOperator; use crate::diff_op_1d; +use crate::Float; use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2}; #[derive(Debug)] @@ -9,15 +10,15 @@ diff_op_1d!(SBP8, diff_1d, SBP8::BLOCK, SBP8::DIAG, false); impl SBP8 { #[rustfmt::skip] - const HBLOCK: &'static [f32] = &[ + const HBLOCK: &'static [Float] = &[ 2.94890676177879e-01, 1.52572062389771e+00, 2.57452876984127e-01, 1.79811370149912e+00, 4.12708057760141e-01, 1.27848462301587e+00, 9.23295579805997e-01, 1.00933386085916e+00 ]; #[rustfmt::skip] - const DIAG: &'static [f32] = &[ + const DIAG: &'static [Float] = &[ 3.57142857142857e-03, -3.80952380952381e-02, 2.00000000000000e-01, -8.00000000000000e-01, -0.00000000000000e+00, 8.00000000000000e-01, -2.00000000000000e-01, 3.80952380952381e-02, -3.57142857142857e-03 ]; #[rustfmt::skip] - const BLOCK: &'static [[f32; 12]] = &[ + const BLOCK: &'static [[Float; 12]] = &[ [-1.69554360443190e+00, 2.24741246341404e+00, -3.38931922601500e-02, -7.81028168126749e-01, 2.54881486107905e-02, 3.43865227388873e-01, -8.62858162633335e-02, -2.00150583315761e-02, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], [-4.34378988266985e-01, 0.00000000000000e+00, 9.18511925072956e-02, 4.94008626807984e-01, -2.46151762937235e-02, -1.86759403432935e-01, 5.27267838475813e-02, 7.16696483080115e-03, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], [3.88218088704253e-02, -5.44329744454984e-01, 0.00000000000000e+00, 3.89516189693211e-01, 1.36433486528546e-01, 1.03290582800845e-01, -1.79720579323281e-01, 5.59882558852296e-02, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], @@ -30,7 +31,7 @@ impl SBP8 { } impl SbpOperator for SBP8 { - fn diffxi(prev: ArrayView2, mut fut: ArrayViewMut2) { + fn diffxi(prev: ArrayView2, mut fut: ArrayViewMut2) { assert_eq!(prev.shape(), fut.shape()); assert!(prev.shape()[1] >= 2 * Self::BLOCK.len()); @@ -39,12 +40,12 @@ impl SbpOperator for SBP8 { } } - fn diffeta(prev: ArrayView2, fut: ArrayViewMut2) { + fn diffeta(prev: ArrayView2, fut: ArrayViewMut2) { // transpose then use diffxi Self::diffxi(prev.reversed_axes(), fut.reversed_axes()); } - fn h() -> &'static [f32] { + fn h() -> &'static [Float] { Self::HBLOCK } } diff --git a/sbp/src/operators/upwind4.rs b/sbp/src/operators/upwind4.rs index 95633ec..34aea39 100644 --- a/sbp/src/operators/upwind4.rs +++ b/sbp/src/operators/upwind4.rs @@ -1,12 +1,16 @@ use super::{SbpOperator, UpwindOperator}; use crate::diff_op_1d; +use crate::Float; use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2, Axis}; #[derive(Debug)] pub struct Upwind4 {} /// Simdtype used in diff_simd_col +#[cfg(feature = "f32")] type SimdT = packed_simd::f32x8; +#[cfg(not(feature = "f32"))] +type SimdT = packed_simd::f64x8; diff_op_1d!(Upwind4, diff_1d, Upwind4::BLOCK, Upwind4::DIAG, false); diff_op_1d!( @@ -21,44 +25,48 @@ macro_rules! diff_simd_row_7_47 { ($self: ident, $name: ident, $BLOCK: expr, $DIAG: expr, $symmetric: expr) => { impl $self { #[inline(never)] - fn $name(prev: ArrayView2, mut fut: ArrayViewMut2) { - use packed_simd::{f32x8, u32x8}; + fn $name(prev: ArrayView2, mut fut: ArrayViewMut2) { + #[cfg(feature = "f32")] + type SimdIndex = packed_simd::u32x8; + #[cfg(not(feature = "f32"))] + type SimdIndex = packed_simd::u64x8; assert_eq!(prev.shape(), fut.shape()); assert!(prev.len_of(Axis(1)) >= 2 * $BLOCK.len()); - assert!(prev.len() >= f32x8::lanes()); + assert!(prev.len() >= SimdT::lanes()); // The prev and fut array must have contigous last dimension assert_eq!(prev.strides()[1], 1); assert_eq!(fut.strides()[1], 1); let nx = prev.len_of(Axis(1)); - let dx = 1.0 / (nx - 1) as f32; + let dx = 1.0 / (nx - 1) as Float; let idx = 1.0 / dx; for j in 0..prev.len_of(Axis(0)) { use std::slice; let prev = - unsafe { slice::from_raw_parts(prev.uget((j, 0)) as *const f32, nx) }; - let fut = - unsafe { slice::from_raw_parts_mut(fut.uget_mut((j, 0)) as *mut f32, nx) }; + unsafe { slice::from_raw_parts(prev.uget((j, 0)) as *const Float, nx) }; + let fut = unsafe { + slice::from_raw_parts_mut(fut.uget_mut((j, 0)) as *mut Float, nx) + }; //let mut fut = fut.slice_mut(s![j, ..]); - let first_elems = unsafe { f32x8::from_slice_unaligned_unchecked(prev) }; + let first_elems = unsafe { SimdT::from_slice_unaligned_unchecked(prev) }; let block = { let bl = $BLOCK; [ - f32x8::new( + SimdT::new( bl[0][0], bl[0][1], bl[0][2], bl[0][3], bl[0][4], bl[0][5], bl[0][6], 0.0, ), - f32x8::new( + SimdT::new( bl[1][0], bl[1][1], bl[1][2], bl[1][3], bl[1][4], bl[1][5], bl[1][6], 0.0, ), - f32x8::new( + SimdT::new( bl[2][0], bl[2][1], bl[2][2], bl[2][3], bl[2][4], bl[2][5], bl[2][6], 0.0, ), - f32x8::new( + SimdT::new( bl[3][0], bl[3][1], bl[3][2], bl[3][3], bl[3][4], bl[3][5], bl[3][6], 0.0, ), @@ -71,7 +79,7 @@ macro_rules! diff_simd_row_7_47 { let diag = { let diag = $DIAG; - f32x8::new( + SimdT::new( diag[0], diag[1], diag[2], diag[3], diag[4], diag[5], diag[6], 0.0, ) }; @@ -79,8 +87,8 @@ macro_rules! diff_simd_row_7_47 { .iter_mut() .skip(block.len()) .zip( - prev.windows(f32x8::lanes()) - .map(f32x8::from_slice_unaligned) + prev.windows(SimdT::lanes()) + .map(SimdT::from_slice_unaligned) .skip(1), ) .take(nx - 2 * block.len()) @@ -89,8 +97,8 @@ macro_rules! diff_simd_row_7_47 { } let last_elems = - unsafe { f32x8::from_slice_unaligned_unchecked(&prev[nx - 8..]) } - .shuffle1_dyn(u32x8::new(7, 6, 5, 4, 3, 2, 1, 0)); + unsafe { SimdT::from_slice_unaligned_unchecked(&prev[nx - 8..]) } + .shuffle1_dyn(SimdIndex::new(7, 6, 5, 4, 3, 2, 1, 0)); if $symmetric { fut[nx - 4] = idx * (block[3] * last_elems).sum(); fut[nx - 3] = idx * (block[2] * last_elems).sum(); @@ -121,7 +129,7 @@ macro_rules! diff_simd_col_7_47 { ($self: ident, $name: ident, $BLOCK: expr, $DIAG: expr, $symmetric: expr) => { impl $self { #[inline(never)] - fn $name(prev: ArrayView2, mut fut: ArrayViewMut2) { + fn $name(prev: ArrayView2, mut fut: ArrayViewMut2) { use std::slice; assert_eq!(prev.shape(), fut.shape()); assert_eq!(prev.stride_of(Axis(0)), 1); @@ -132,38 +140,38 @@ macro_rules! diff_simd_col_7_47 { assert!(ny >= SimdT::lanes()); assert!(ny % SimdT::lanes() == 0); - let dx = 1.0 / (nx - 1) as f32; + let dx = 1.0 / (nx - 1) as Float; let idx = 1.0 / dx; for j in (0..ny).step_by(SimdT::lanes()) { let a = unsafe { [ SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, 0)) as *const f32, + prev.uget((j, 0)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, 1)) as *const f32, + prev.uget((j, 1)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, 2)) as *const f32, + prev.uget((j, 2)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, 3)) as *const f32, + prev.uget((j, 3)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, 4)) as *const f32, + prev.uget((j, 4)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, 5)) as *const f32, + prev.uget((j, 5)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, 6)) as *const f32, + prev.uget((j, 6)) as *const Float, SimdT::lanes(), )), ] @@ -180,7 +188,7 @@ macro_rules! diff_simd_col_7_47 { + a[6] * bl[6]); unsafe { b.write_to_slice_unaligned(slice::from_raw_parts_mut( - fut.uget_mut((j, i)) as *mut f32, + fut.uget_mut((j, i)) as *mut Float, SimdT::lanes(), )); } @@ -191,7 +199,7 @@ macro_rules! diff_simd_col_7_47 { // Push a onto circular buffer a = [a[1], a[2], a[3], a[4], a[5], a[6], unsafe { SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, i + 3)) as *const f32, + prev.uget((j, i + 3)) as *const Float, SimdT::lanes(), )) }]; @@ -205,7 +213,7 @@ macro_rules! diff_simd_col_7_47 { + a[6] * $DIAG[6]); unsafe { b.write_to_slice_unaligned(slice::from_raw_parts_mut( - fut.uget_mut((j, i)) as *mut f32, + fut.uget_mut((j, i)) as *mut Float, SimdT::lanes(), )); } @@ -214,31 +222,31 @@ macro_rules! diff_simd_col_7_47 { let a = unsafe { [ SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, nx - 1)) as *const f32, + prev.uget((j, nx - 1)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, nx - 2)) as *const f32, + prev.uget((j, nx - 2)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, nx - 3)) as *const f32, + prev.uget((j, nx - 3)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, nx - 4)) as *const f32, + prev.uget((j, nx - 4)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, nx - 5)) as *const f32, + prev.uget((j, nx - 5)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, nx - 6)) as *const f32, + prev.uget((j, nx - 6)) as *const Float, SimdT::lanes(), )), SimdT::from_slice_unaligned(slice::from_raw_parts( - prev.uget((j, nx - 7)) as *const f32, + prev.uget((j, nx - 7)) as *const Float, SimdT::lanes(), )), ] @@ -256,7 +264,7 @@ macro_rules! diff_simd_col_7_47 { + a[6] * bl[6]); unsafe { b.write_to_slice_unaligned(slice::from_raw_parts_mut( - fut.uget_mut((j, nx - 1 - i)) as *mut f32, + fut.uget_mut((j, nx - 1 - i)) as *mut Float, SimdT::lanes(), )); } @@ -278,15 +286,15 @@ diff_simd_col_7_47!( impl Upwind4 { #[rustfmt::skip] - const HBLOCK: &'static [f32] = &[ + const HBLOCK: &'static [Float] = &[ 49.0 / 144.0, 61.0 / 48.0, 41.0 / 48.0, 149.0 / 144.0 ]; #[rustfmt::skip] - const DIAG: &'static [f32] = &[ + const DIAG: &'static [Float] = &[ -1.0 / 24.0, 1.0 / 4.0, -7.0 / 8.0, 0.0, 7.0 / 8.0, -1.0 / 4.0, 1.0 / 24.0 ]; #[rustfmt::skip] - const BLOCK: &'static [[f32; 7]] = &[ + const BLOCK: &'static [[Float; 7]] = &[ [ -72.0 / 49.0, 187.0 / 98.0, -20.0 / 49.0, -3.0 / 98.0, 0.0, 0.0, 0.0], [-187.0 / 366.0, 0.0, 69.0 / 122.0, -16.0 / 183.0, 2.0 / 61.0, 0.0, 0.0], [ 20.0 / 123.0, -69.0 / 82.0, 0.0, 227.0 / 246.0, -12.0 / 41.0, 2.0 / 41.0, 0.0], @@ -294,7 +302,7 @@ impl Upwind4 { ]; #[rustfmt::skip] - const DISS_BLOCK: &'static [[f32; 7]; 4] = &[ + const DISS_BLOCK: &'static [[Float; 7]; 4] = &[ [-3.0 / 49.0, 9.0 / 49.0, -9.0 / 49.0, 3.0 / 49.0, 0.0, 0.0, 0.0], [ 3.0 / 61.0, -11.0 / 61.0, 15.0 / 61.0, -9.0 / 61.0, 2.0 / 61.0, 0.0, 0.0], [-3.0 / 41.0, 15.0 / 41.0, -29.0 / 41.0, 27.0 / 41.0, -12.0 / 41.0, 2.0 / 41.0, 0.0], @@ -302,13 +310,13 @@ impl Upwind4 { ]; #[rustfmt::skip] - const DISS_DIAG: &'static [f32; 7] = &[ + const DISS_DIAG: &'static [Float; 7] = &[ 1.0 / 24.0, -1.0 / 4.0, 5.0 / 8.0, -5.0 / 6.0, 5.0 / 8.0, -1.0 / 4.0, 1.0 / 24.0 ]; } impl SbpOperator for Upwind4 { - fn diffxi(prev: ArrayView2, mut fut: ArrayViewMut2) { + fn diffxi(prev: ArrayView2, mut fut: ArrayViewMut2) { assert_eq!(prev.shape(), fut.shape()); assert!(prev.shape()[1] >= 2 * Self::BLOCK.len()); @@ -329,12 +337,12 @@ impl SbpOperator for Upwind4 { } } - fn diffeta(prev: ArrayView2, fut: ArrayViewMut2) { + fn diffeta(prev: ArrayView2, fut: ArrayViewMut2) { // transpose then use diffxi Self::diffxi(prev.reversed_axes(), fut.reversed_axes()); } - fn h() -> &'static [f32] { + fn h() -> &'static [Float] { Self::HBLOCK } } @@ -343,13 +351,13 @@ impl SbpOperator for Upwind4 { fn upwind4_test() { use ndarray::prelude::*; let nx = 20; - let dx = 1.0 / (nx - 1) as f32; - let mut source: ndarray::Array1 = ndarray::Array1::zeros(nx); + let dx = 1.0 / (nx - 1) as Float; + let mut source: ndarray::Array1 = ndarray::Array1::zeros(nx); let mut res = ndarray::Array1::zeros(nx); let mut target = ndarray::Array1::zeros(nx); for i in 0..nx { - source[i] = i as f32 * dx; + source[i] = i as Float * dx; target[i] = 1.0; } res.fill(0.0); @@ -374,7 +382,7 @@ fn upwind4_test() { } for i in 0..nx { - let x = i as f32 * dx; + let x = i as Float * dx; source[i] = x * x; target[i] = 2.0 * x; } @@ -400,7 +408,7 @@ fn upwind4_test() { } for i in 0..nx { - let x = i as f32 * dx; + let x = i as Float * dx; source[i] = x * x * x; target[i] = 3.0 * x * x; } @@ -428,7 +436,7 @@ fn upwind4_test() { } impl UpwindOperator for Upwind4 { - fn dissxi(prev: ArrayView2, mut fut: ArrayViewMut2) { + fn dissxi(prev: ArrayView2, mut fut: ArrayViewMut2) { assert_eq!(prev.shape(), fut.shape()); assert!(prev.shape()[1] >= 2 * Self::BLOCK.len()); @@ -449,7 +457,7 @@ impl UpwindOperator for Upwind4 { } } - fn disseta(prev: ArrayView2, fut: ArrayViewMut2) { + fn disseta(prev: ArrayView2, fut: ArrayViewMut2) { // diffeta = transpose then use dissxi Self::dissxi(prev.reversed_axes(), fut.reversed_axes()); } diff --git a/sbp/src/operators/upwind9.rs b/sbp/src/operators/upwind9.rs index d745641..d5cb69b 100644 --- a/sbp/src/operators/upwind9.rs +++ b/sbp/src/operators/upwind9.rs @@ -1,5 +1,6 @@ use super::{SbpOperator, UpwindOperator}; use crate::diff_op_1d; +use crate::Float; use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2}; #[derive(Debug)] @@ -16,15 +17,15 @@ diff_op_1d!( impl Upwind9 { #[rustfmt::skip] - const HBLOCK: &'static [f32] = &[ + const HBLOCK: &'static [Float] = &[ 1070017.0/3628800.0, 5537111.0/3628800.0, 103613.0/403200.0, 261115.0/145152.0, 298951.0/725760.0, 515677.0/403200.0, 3349879.0/3628800.0, 3662753.0/3628800.0 ]; #[rustfmt::skip] - const DIAG: &'static [f32] = &[ + const DIAG: &'static [Float] = &[ -1.0/1260.0, 5.0/504.0, -5.0/84.0, 5.0/21.0, -5.0/6.0, 0.0, 5.0/6.0, -5.0/21.0, 5.0/84.0, -5.0/504.0, 1.0/1260.0, ]; #[rustfmt::skip] - const BLOCK: &'static [[f32; 13]] = &[ + const BLOCK: &'static [[Float; 13]] = &[ [-1.69567399396458e+00, 2.29023358159400e+00, -2.16473500425698e-01, -5.05879766354449e-01, -1.01161106778154e-01, 2.59147072064383e-01, 1.93922119400659e-02, -4.95844980755642e-02, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], [-4.42575354959737e-01, 0.00000000000000e+00, 1.91582959381899e-01, 2.82222626681305e-01, 1.12083989713257e-01, -1.51334868892111e-01, -2.23600502721044e-02, 3.03806983474913e-02, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], [2.48392603571843e-01, -1.13758367065272e+00, 0.00000000000000e+00, 1.95334726810969e+00, -1.58879011773212e+00, 3.93797129320378e-01, 2.52140821030291e-01, -1.21304033647356e-01, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], @@ -36,7 +37,7 @@ impl Upwind9 { ]; #[rustfmt::skip] - const DISS_BLOCK: &'static [[f32; 13]] = &[ + const DISS_BLOCK: &'static [[Float; 13]] = &[ [-3.99020778658945e-04, 2.05394169917502e-03, -4.24493243399805e-03, 4.38126393542801e-03, -2.18883813216888e-03, 2.98565988131608e-04, 1.38484104084115e-04, -3.94643819928825e-05, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], [3.96913216138553e-04, -2.28230530115522e-03, 5.43069719436758e-03, -6.81086901935894e-03, 4.69064759201504e-03, -1.61429862514855e-03, 1.62083873811316e-04, 2.71310693302277e-05, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], [-4.87084939816571e-03, 3.22464611075207e-02, -9.06094757860846e-02, 1.39830191253413e-01, -1.27675500367419e-01, 6.87310321912961e-02, -2.00917702215270e-02, 2.43991122096699e-03, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00, 0.00000000000000e+00], @@ -48,13 +49,13 @@ impl Upwind9 { ]; #[rustfmt::skip] - const DISS_DIAG: &'static [f32] = &[ + const DISS_DIAG: &'static [Float] = &[ 1.0/1260.0, -1.0/126.0, 1.0/28.0, -2.0/21.0, 1.0/6.0, -1.0/5.0, 1.0/6.0, -2.0/21.0, 1.0/28.0, -1.0/126.0, 1.0/1260.0, ]; } impl SbpOperator for Upwind9 { - fn diffxi(prev: ArrayView2, mut fut: ArrayViewMut2) { + fn diffxi(prev: ArrayView2, mut fut: ArrayViewMut2) { assert_eq!(prev.shape(), fut.shape()); assert!(prev.shape()[1] >= 2 * Self::BLOCK.len()); @@ -63,18 +64,18 @@ impl SbpOperator for Upwind9 { } } - fn diffeta(prev: ArrayView2, fut: ArrayViewMut2) { + fn diffeta(prev: ArrayView2, fut: ArrayViewMut2) { // transpose then use diffxi Self::diffxi(prev.reversed_axes(), fut.reversed_axes()); } - fn h() -> &'static [f32] { + fn h() -> &'static [Float] { Self::HBLOCK } } impl UpwindOperator for Upwind9 { - fn dissxi(prev: ArrayView2, mut fut: ArrayViewMut2) { + fn dissxi(prev: ArrayView2, mut fut: ArrayViewMut2) { assert_eq!(prev.shape(), fut.shape()); assert!(prev.shape()[1] >= 2 * Self::BLOCK.len()); @@ -83,7 +84,7 @@ impl UpwindOperator for Upwind9 { } } - fn disseta(prev: ArrayView2, fut: ArrayViewMut2) { + fn disseta(prev: ArrayView2, fut: ArrayViewMut2) { // diffeta = transpose then use dissxi Self::dissxi(prev.reversed_axes(), fut.reversed_axes()); } diff --git a/sbp/src/utils.rs b/sbp/src/utils.rs index 459e5c9..fe4338c 100644 --- a/sbp/src/utils.rs +++ b/sbp/src/utils.rs @@ -1,7 +1,9 @@ +use crate::Float; + #[derive(Debug, Clone)] pub struct SimpleGrid { - pub x: ndarray::Array2, - pub y: ndarray::Array2, + pub x: ndarray::Array2, + pub y: ndarray::Array2, pub name: Option, pub dire: Option, pub dirw: Option, @@ -32,9 +34,9 @@ pub fn json_to_grids(json: &str) -> Result, String> { enum ArrayForm { /// Only know the one dimension, will broadcast to /// two dimensions once we know about both dims - Array1(ndarray::Array1), + Array1(ndarray::Array1), /// The usize is the inner dimension (nx) - Array2(ndarray::Array2), + Array2(ndarray::Array2), } if grid.is_empty() { return Err(format!("empty object")); @@ -54,12 +56,12 @@ pub fn json_to_grids(json: &str) -> Result, String> { assert_eq!(name, "linspace"); let start = iter.next(); - let start: f32 = match start { + let start: Float = match start { Some(x) => x.parse().map_err(|e| format!("linspace: {}", e))?, None => return Err(format!("")), }; let end = iter.next(); - let end: f32 = match end { + let end: Float = match end { Some(x) => x.parse().map_err(|e| format!("linspace: {}", e))?, None => return Err(format!("")), }; @@ -85,10 +87,10 @@ pub fn json_to_grids(json: &str) -> Result, String> { if !x[0].is_array() { let v = x .members() - .map(|x: &JsonValue| -> Result { + .map(|x: &JsonValue| -> Result { Ok(x.as_number().ok_or_else(|| format!("Array contained something that could not be converted to an array"))?.into()) }) - .collect::, _>>()?; + .collect::, _>>()?; Ok(ArrayForm::Array1(ndarray::Array::from(v))) } else { let arrlen2 = x[0].len(); diff --git a/sbp/tests/convergence.rs b/sbp/tests/convergence.rs index aee9f46..1d5759b 100644 --- a/sbp/tests/convergence.rs +++ b/sbp/tests/convergence.rs @@ -1,8 +1,9 @@ #![cfg(feature = "expensive_tests")] use ndarray::prelude::*; use sbp::euler::*; +use sbp::Float; -fn run_with_size(size: usize) -> f32 { +fn run_with_size(size: usize) -> Float { let nx = size; let ny = size; let x = Array1::linspace(-5.0, 5.0, nx); @@ -28,7 +29,7 @@ fn run_with_size(size: usize) -> f32 { sys.vortex(0.0, vortex_params); let time = 0.2; - let dt = 0.2 * f32::min(1.0 / (nx - 1) as f32, 1.0 / (ny - 1) as f32); + let dt = 0.2 * Float::min(1.0 / (nx - 1) as Float, 1.0 / (ny - 1) as Float); let nsteps = (time / dt) as usize; for _ in 0..nsteps { @@ -36,15 +37,15 @@ fn run_with_size(size: usize) -> f32 { } let mut verifield = Field::new(ny, nx); - verifield.vortex(sys.x(), sys.y(), nsteps as f32 * dt, vortex_params); + verifield.vortex(sys.x(), sys.y(), nsteps as Float * dt, vortex_params); verifield.h2_err::(sys.field()) } #[test] fn convergence() { - let sizes = [25, 35, 50, 71, 100, 150]; - let mut prev: Option<(usize, f32)> = None; + let sizes = [25, 35, 50, 71, 100, 150, 200]; + let mut prev: Option<(usize, Float)> = None; println!("Size\tError(h2)\tq"); for size in &sizes { print!("{:3}x{:3}", size, size); @@ -57,7 +58,8 @@ fn convergence() { let (size1, e1) = prev; let m1 = size1 * size1; - let q = f32::log10(e0 / e1) / f32::log10((m0 as f32 / m1 as f32).powf(1.0 / 2.0)); + let q = + Float::log10(e0 / e1) / Float::log10((m0 as Float / m1 as Float).powf(1.0 / 2.0)); print!("\t{}", q); } println!(); diff --git a/webfront/Cargo.toml b/webfront/Cargo.toml index 0e70c41..73a5398 100644 --- a/webfront/Cargo.toml +++ b/webfront/Cargo.toml @@ -12,5 +12,5 @@ path = "lib.rs" wasm-bindgen = "0.2.58" console_error_panic_hook = "0.1.6" wee_alloc = "0.4.5" -sbp = { path = "../sbp" } +sbp = { path = "../sbp", features = ["f32"] } ndarray = "0.13.0"