make precision selectable using feature
This commit is contained in:
parent
afa2ce655f
commit
ba420b1554
|
@ -14,6 +14,8 @@ json = "0.12.1"
|
||||||
# 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 = []
|
||||||
|
# Use f32 as precision, default is f64
|
||||||
|
f32 = []
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.3.0"
|
criterion = "0.3.0"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use sbp::maxwell::System;
|
use sbp::maxwell::System;
|
||||||
use sbp::operators::{SbpOperator, Upwind4, UpwindOperator, SBP4};
|
use sbp::operators::{SbpOperator, Upwind4, UpwindOperator, SBP4};
|
||||||
|
use sbp::Float;
|
||||||
|
|
||||||
fn advance_system<SBP: SbpOperator>(universe: &mut System<SBP>, n: usize) {
|
fn advance_system<SBP: SbpOperator>(universe: &mut System<SBP>, n: usize) {
|
||||||
for _ in 0..n {
|
for _ in 0..n {
|
||||||
|
@ -20,8 +21,8 @@ fn performance_benchmark(c: &mut Criterion) {
|
||||||
|
|
||||||
let w = 40;
|
let w = 40;
|
||||||
let h = 26;
|
let h = 26;
|
||||||
let x = ndarray::Array2::from_shape_fn((h, w), |(_, i)| i as f32 / (w - 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 f32 / (h - 1) as f32);
|
let y = ndarray::Array2::from_shape_fn((h, w), |(j, _)| j as Float / (h - 1) as Float);
|
||||||
|
|
||||||
let mut universe = System::<Upwind4>::new(x.clone(), y.clone());
|
let mut universe = System::<Upwind4>::new(x.clone(), y.clone());
|
||||||
group.bench_function("advance", |b| {
|
group.bench_function("advance", |b| {
|
||||||
|
|
145
sbp/src/euler.rs
145
sbp/src/euler.rs
|
@ -1,10 +1,11 @@
|
||||||
use super::grid::Grid;
|
use super::grid::Grid;
|
||||||
use super::integrate;
|
use super::integrate;
|
||||||
use super::operators::{SbpOperator, UpwindOperator};
|
use super::operators::{SbpOperator, UpwindOperator};
|
||||||
|
use super::Float;
|
||||||
use ndarray::azip;
|
use ndarray::azip;
|
||||||
use ndarray::prelude::*;
|
use ndarray::prelude::*;
|
||||||
|
|
||||||
pub const GAMMA: f32 = 1.4;
|
pub const GAMMA: Float = 1.4;
|
||||||
|
|
||||||
// A collection of buffers that allows one to efficiently
|
// A collection of buffers that allows one to efficiently
|
||||||
// move to the next state
|
// move to the next state
|
||||||
|
@ -16,7 +17,7 @@ pub struct System<SBP: SbpOperator> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SBP: SbpOperator> System<SBP> {
|
impl<SBP: SbpOperator> System<SBP> {
|
||||||
pub fn new(x: ndarray::Array2<f32>, y: ndarray::Array2<f32>) -> Self {
|
pub fn new(x: ndarray::Array2<Float>, y: ndarray::Array2<Float>) -> Self {
|
||||||
let grid = Grid::new(x, y).expect(
|
let grid = Grid::new(x, y).expect(
|
||||||
"Could not create grid. Different number of elements compared to width*height?",
|
"Could not create grid. Different number of elements compared to width*height?",
|
||||||
);
|
);
|
||||||
|
@ -29,7 +30,7 @@ impl<SBP: SbpOperator> System<SBP> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 rhs_trad = |k: &mut Field, y: &Field, grid: &_, wb: &mut _| {
|
||||||
let boundaries = BoundaryTerms {
|
let boundaries = BoundaryTerms {
|
||||||
north: y.south(),
|
north: y.south(),
|
||||||
|
@ -51,14 +52,14 @@ impl<SBP: SbpOperator> System<SBP> {
|
||||||
std::mem::swap(&mut self.sys.0, &mut self.sys.1);
|
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
|
self.sys
|
||||||
.0
|
.0
|
||||||
.vortex(self.grid.x.view(), self.grid.y.view(), t, vortex_parameters);
|
.vortex(self.grid.x.view(), self.grid.y.view(), t, vortex_parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::many_single_char_names)]
|
#[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
|
// Should parametrise such that we have radius, drop in pressure at center, etc
|
||||||
let vortex_parameters = VortexParameters {
|
let vortex_parameters = VortexParameters {
|
||||||
x0,
|
x0,
|
||||||
|
@ -80,16 +81,16 @@ impl<SBP: SbpOperator> System<SBP> {
|
||||||
&self.sys.0
|
&self.sys.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn x(&self) -> ArrayView2<f32> {
|
pub fn x(&self) -> ArrayView2<Float> {
|
||||||
self.grid.x.view()
|
self.grid.x.view()
|
||||||
}
|
}
|
||||||
pub fn y(&self) -> ArrayView2<f32> {
|
pub fn y(&self) -> ArrayView2<Float> {
|
||||||
self.grid.y.view()
|
self.grid.y.view()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<UO: UpwindOperator> System<UO> {
|
impl<UO: UpwindOperator> System<UO> {
|
||||||
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 rhs_upwind = |k: &mut Field, y: &Field, grid: &_, wb: &mut _| {
|
||||||
let boundaries = BoundaryTerms {
|
let boundaries = BoundaryTerms {
|
||||||
north: y.south(),
|
north: y.south(),
|
||||||
|
@ -114,10 +115,10 @@ impl<UO: UpwindOperator> System<UO> {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
/// A 4 x ny x nx array
|
/// A 4 x ny x nx array
|
||||||
pub struct Field(pub(crate) Array3<f32>);
|
pub struct Field(pub(crate) Array3<Float>);
|
||||||
|
|
||||||
impl std::ops::Deref for Field {
|
impl std::ops::Deref for Field {
|
||||||
type Target = Array3<f32>;
|
type Target = Array3<Float>;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
@ -143,29 +144,29 @@ impl Field {
|
||||||
self.0.shape()[1]
|
self.0.shape()[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rho(&self) -> ArrayView2<f32> {
|
pub fn rho(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![0, .., ..])
|
self.slice(s![0, .., ..])
|
||||||
}
|
}
|
||||||
pub fn rhou(&self) -> ArrayView2<f32> {
|
pub fn rhou(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![1, .., ..])
|
self.slice(s![1, .., ..])
|
||||||
}
|
}
|
||||||
pub fn rhov(&self) -> ArrayView2<f32> {
|
pub fn rhov(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![2, .., ..])
|
self.slice(s![2, .., ..])
|
||||||
}
|
}
|
||||||
pub fn e(&self) -> ArrayView2<f32> {
|
pub fn e(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![3, .., ..])
|
self.slice(s![3, .., ..])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rho_mut(&mut self) -> ArrayViewMut2<f32> {
|
pub fn rho_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![0, .., ..])
|
self.slice_mut(s![0, .., ..])
|
||||||
}
|
}
|
||||||
pub fn rhou_mut(&mut self) -> ArrayViewMut2<f32> {
|
pub fn rhou_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![1, .., ..])
|
self.slice_mut(s![1, .., ..])
|
||||||
}
|
}
|
||||||
pub fn rhov_mut(&mut self) -> ArrayViewMut2<f32> {
|
pub fn rhov_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![2, .., ..])
|
self.slice_mut(s![2, .., ..])
|
||||||
}
|
}
|
||||||
pub fn e_mut(&mut self) -> ArrayViewMut2<f32> {
|
pub fn e_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![3, .., ..])
|
self.slice_mut(s![3, .., ..])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,10 +174,10 @@ impl Field {
|
||||||
pub fn components(
|
pub fn components(
|
||||||
&self,
|
&self,
|
||||||
) -> (
|
) -> (
|
||||||
ArrayView2<f32>,
|
ArrayView2<Float>,
|
||||||
ArrayView2<f32>,
|
ArrayView2<Float>,
|
||||||
ArrayView2<f32>,
|
ArrayView2<Float>,
|
||||||
ArrayView2<f32>,
|
ArrayView2<Float>,
|
||||||
) {
|
) {
|
||||||
(self.rho(), self.rhou(), self.rhov(), self.e())
|
(self.rho(), self.rhou(), self.rhov(), self.e())
|
||||||
}
|
}
|
||||||
|
@ -184,10 +185,10 @@ impl Field {
|
||||||
pub fn components_mut(
|
pub fn components_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> (
|
) -> (
|
||||||
ArrayViewMut2<f32>,
|
ArrayViewMut2<Float>,
|
||||||
ArrayViewMut2<f32>,
|
ArrayViewMut2<Float>,
|
||||||
ArrayViewMut2<f32>,
|
ArrayViewMut2<Float>,
|
||||||
ArrayViewMut2<f32>,
|
ArrayViewMut2<Float>,
|
||||||
) {
|
) {
|
||||||
let mut iter = self.0.outer_iter_mut();
|
let mut iter = self.0.outer_iter_mut();
|
||||||
|
|
||||||
|
@ -200,38 +201,38 @@ impl Field {
|
||||||
(rho, rhou, rhov, e)
|
(rho, rhou, rhov, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn north(&self) -> ArrayView2<f32> {
|
fn north(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![.., self.ny() - 1, ..])
|
self.slice(s![.., self.ny() - 1, ..])
|
||||||
}
|
}
|
||||||
fn south(&self) -> ArrayView2<f32> {
|
fn south(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![.., 0, ..])
|
self.slice(s![.., 0, ..])
|
||||||
}
|
}
|
||||||
fn east(&self) -> ArrayView2<f32> {
|
fn east(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![.., .., self.nx() - 1])
|
self.slice(s![.., .., self.nx() - 1])
|
||||||
}
|
}
|
||||||
fn west(&self) -> ArrayView2<f32> {
|
fn west(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![.., .., 0])
|
self.slice(s![.., .., 0])
|
||||||
}
|
}
|
||||||
fn north_mut(&mut self) -> ArrayViewMut2<f32> {
|
fn north_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
let ny = self.ny();
|
let ny = self.ny();
|
||||||
self.slice_mut(s![.., ny - 1, ..])
|
self.slice_mut(s![.., ny - 1, ..])
|
||||||
}
|
}
|
||||||
fn south_mut(&mut self) -> ArrayViewMut2<f32> {
|
fn south_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![.., 0, ..])
|
self.slice_mut(s![.., 0, ..])
|
||||||
}
|
}
|
||||||
fn east_mut(&mut self) -> ArrayViewMut2<f32> {
|
fn east_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
let nx = self.nx();
|
let nx = self.nx();
|
||||||
self.slice_mut(s![.., .., nx - 1])
|
self.slice_mut(s![.., .., nx - 1])
|
||||||
}
|
}
|
||||||
fn west_mut(&mut self) -> ArrayViewMut2<f32> {
|
fn west_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![.., .., 0])
|
self.slice_mut(s![.., .., 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vortex(
|
pub fn vortex(
|
||||||
&mut self,
|
&mut self,
|
||||||
x: ArrayView2<f32>,
|
x: ArrayView2<Float>,
|
||||||
y: ArrayView2<f32>,
|
y: ArrayView2<Float>,
|
||||||
t: f32,
|
t: Float,
|
||||||
vortex_param: VortexParameters,
|
vortex_param: VortexParameters,
|
||||||
) {
|
) {
|
||||||
assert_eq!(x.shape(), y.shape());
|
assert_eq!(x.shape(), y.shape());
|
||||||
|
@ -251,14 +252,18 @@ impl Field {
|
||||||
x in x,
|
x in x,
|
||||||
y in y)
|
y in y)
|
||||||
{
|
{
|
||||||
|
#[cfg(feature = "f32")]
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
#[cfg(not(feature = "f32"))]
|
||||||
|
use std::f64::consts::PI;
|
||||||
|
|
||||||
let dx = (x - vortex_param.x0) - t;
|
let dx = (x - vortex_param.x0) - t;
|
||||||
let dy = y - vortex_param.y0;
|
let dy = y - vortex_param.y0;
|
||||||
let f = (1.0 - (dx*dx + dy*dy))/(rstar*rstar);
|
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);
|
assert!(*rho > 0.0);
|
||||||
let p = f32::powf(*rho, GAMMA)*p_inf;
|
let p = Float::powf(*rho, GAMMA)*p_inf;
|
||||||
assert!(p > 0.0);
|
assert!(p > 0.0);
|
||||||
let u = 1.0 - eps*dy/(2.0*PI*p_inf.sqrt()*rstar*rstar)*(f/2.0).exp();
|
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();
|
let v = eps*dx/(2.0*PI*p_inf.sqrt()*rstar*rstar)*(f/2.0).exp();
|
||||||
|
@ -271,7 +276,7 @@ impl Field {
|
||||||
|
|
||||||
impl Field {
|
impl Field {
|
||||||
/// sqrt((self-other)^T*H*(self-other))
|
/// sqrt((self-other)^T*H*(self-other))
|
||||||
pub fn h2_err<SBP: SbpOperator>(&self, other: &Self) -> f32 {
|
pub fn h2_err<SBP: SbpOperator>(&self, other: &Self) -> Float {
|
||||||
assert_eq!(self.nx(), other.nx());
|
assert_eq!(self.nx(), other.nx());
|
||||||
assert_eq!(self.ny(), other.ny());
|
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)],
|
// This chains the h block into the form [h, 1, 1, 1, rev(h)],
|
||||||
// and multiplies with a factor
|
// and multiplies with a factor
|
||||||
let itermaker = move |n: usize, factor: f32| {
|
let itermaker = move |n: usize, factor: Float| {
|
||||||
h.iter()
|
h.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.chain(std::iter::repeat(1.0).take(n - 2 * h.len()))
|
.chain(std::iter::repeat(1.0).take(n - 2 * h.len()))
|
||||||
|
@ -293,12 +298,12 @@ impl Field {
|
||||||
.map(move |x| x * factor)
|
.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
|
// Repeating to get the form
|
||||||
// [[hx0, hx1, ..., hxn], [hx0, hx1, ..., hxn], ..., [hx0, hx1, ..., hxn]]
|
// [[hx0, hx1, ..., hxn], [hx0, hx1, ..., hxn], ..., [hx0, hx1, ..., hxn]]
|
||||||
let hxiterator = hxiterator.into_iter().cycle().take(self.nx() * self.ny());
|
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
|
// Repeating to get the form
|
||||||
// [[hy0, hy0, ..., hy0], [hy1, hy1, ..., hy1], ..., [hym, hym, ..., hym]]
|
// [[hy0, hy0, ..., hy0], [hy1, hy1, ..., hy1], ..., [hym, hym, ..., hym]]
|
||||||
let hyiterator = hyiterator
|
let hyiterator = hyiterator
|
||||||
|
@ -312,7 +317,7 @@ impl Field {
|
||||||
.zip(self.0.iter())
|
.zip(self.0.iter())
|
||||||
.zip(other.0.iter())
|
.zip(other.0.iter())
|
||||||
.map(|(((hx, hy), r0), r1)| (*r0 - *r1).powi(2) * hx * hy)
|
.map(|(((hx, hy), r0), r1)| (*r0 - *r1).powi(2) * hx * hy)
|
||||||
.sum::<f32>()
|
.sum::<Float>()
|
||||||
.sqrt()
|
.sqrt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,14 +338,14 @@ fn h2_diff() {
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct VortexParameters {
|
pub struct VortexParameters {
|
||||||
pub x0: f32,
|
pub x0: Float,
|
||||||
pub y0: f32,
|
pub y0: Float,
|
||||||
pub rstar: f32,
|
pub rstar: Float,
|
||||||
pub eps: f32,
|
pub eps: Float,
|
||||||
pub mach: f32,
|
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))
|
(gamma - 1.0) * (e - (rhou * rhou + rhov * rhov) / (2.0 * rho))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,10 +539,10 @@ fn fluxes<SBP: SbpOperator>(k: (&mut Field, &mut Field), y: &Field, grid: &Grid<
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BoundaryTerms<'a> {
|
pub struct BoundaryTerms<'a> {
|
||||||
pub north: ArrayView2<'a, f32>,
|
pub north: ArrayView2<'a, Float>,
|
||||||
pub south: ArrayView2<'a, f32>,
|
pub south: ArrayView2<'a, Float>,
|
||||||
pub east: ArrayView2<'a, f32>,
|
pub east: ArrayView2<'a, Float>,
|
||||||
pub west: ArrayView2<'a, f32>,
|
pub west: ArrayView2<'a, Float>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -550,7 +555,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
) {
|
) {
|
||||||
// North boundary
|
// 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 sign = -1.0;
|
||||||
let tau = 1.0;
|
let tau = 1.0;
|
||||||
let slice = s![y.ny() - 1, ..];
|
let slice = s![y.ny() - 1, ..];
|
||||||
|
@ -568,7 +573,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
}
|
}
|
||||||
// South boundary
|
// 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 sign = 1.0;
|
||||||
let tau = -1.0;
|
let tau = -1.0;
|
||||||
let slice = s![0, ..];
|
let slice = s![0, ..];
|
||||||
|
@ -586,7 +591,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
}
|
}
|
||||||
// West Boundary
|
// 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 sign = 1.0;
|
||||||
let tau = -1.0;
|
let tau = -1.0;
|
||||||
let slice = s![.., 0];
|
let slice = s![.., 0];
|
||||||
|
@ -604,7 +609,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
}
|
}
|
||||||
// East Boundary
|
// 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 sign = -1.0;
|
||||||
let tau = 1.0;
|
let tau = 1.0;
|
||||||
let slice = s![.., y.nx() - 1];
|
let slice = s![.., y.nx() - 1];
|
||||||
|
@ -627,15 +632,15 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
/// Boundary conditions (SAT)
|
/// Boundary conditions (SAT)
|
||||||
fn SAT_characteristic(
|
fn SAT_characteristic(
|
||||||
mut k: ArrayViewMut2<f32>,
|
mut k: ArrayViewMut2<Float>,
|
||||||
y: ArrayView2<f32>,
|
y: ArrayView2<Float>,
|
||||||
z: ArrayView2<f32>, // Size 4 x n (all components in line)
|
z: ArrayView2<Float>, // Size 4 x n (all components in line)
|
||||||
hi: f32,
|
hi: Float,
|
||||||
sign: f32,
|
sign: Float,
|
||||||
tau: f32,
|
tau: Float,
|
||||||
detj: ArrayView1<f32>,
|
detj: ArrayView1<Float>,
|
||||||
detj_d_dx: ArrayView1<f32>,
|
detj_d_dx: ArrayView1<Float>,
|
||||||
detj_d_dy: ArrayView1<f32>,
|
detj_d_dy: ArrayView1<Float>,
|
||||||
) {
|
) {
|
||||||
assert_eq!(detj.shape(), detj_d_dx.shape());
|
assert_eq!(detj.shape(), detj_d_dx.shape());
|
||||||
assert_eq!(detj.shape(), detj_d_dy.shape());
|
assert_eq!(detj.shape(), detj_d_dy.shape());
|
||||||
|
@ -660,7 +665,7 @@ fn SAT_characteristic(
|
||||||
let ky_ = detj_d_dy / detj;
|
let ky_ = detj_d_dy / detj;
|
||||||
|
|
||||||
let (kx, ky) = {
|
let (kx, ky) = {
|
||||||
let r = f32::hypot(kx_, ky_);
|
let r = Float::hypot(kx_, ky_);
|
||||||
(kx_ / r, ky_ / r)
|
(kx_ / r, ky_ / r)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -690,8 +695,8 @@ fn SAT_characteristic(
|
||||||
let L = [
|
let L = [
|
||||||
U,
|
U,
|
||||||
U,
|
U,
|
||||||
U + c * f32::hypot(kx_, ky_),
|
U + c * Float::hypot(kx_, ky_),
|
||||||
U - c * f32::hypot(kx_, ky_),
|
U - c * Float::hypot(kx_, ky_),
|
||||||
];
|
];
|
||||||
let beta = 1.0 / (2.0 * c * c);
|
let beta = 1.0 / (2.0 * c * c);
|
||||||
let TI = [
|
let TI = [
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::Float;
|
||||||
use ndarray::Array2;
|
use ndarray::Array2;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -5,20 +6,20 @@ pub struct Grid<SBP>
|
||||||
where
|
where
|
||||||
SBP: super::operators::SbpOperator,
|
SBP: super::operators::SbpOperator,
|
||||||
{
|
{
|
||||||
pub(crate) x: Array2<f32>,
|
pub(crate) x: Array2<Float>,
|
||||||
pub(crate) y: Array2<f32>,
|
pub(crate) y: Array2<Float>,
|
||||||
|
|
||||||
pub(crate) detj: Array2<f32>,
|
pub(crate) detj: Array2<Float>,
|
||||||
pub(crate) detj_dxi_dx: Array2<f32>,
|
pub(crate) detj_dxi_dx: Array2<Float>,
|
||||||
pub(crate) detj_dxi_dy: Array2<f32>,
|
pub(crate) detj_dxi_dy: Array2<Float>,
|
||||||
pub(crate) detj_deta_dx: Array2<f32>,
|
pub(crate) detj_deta_dx: Array2<Float>,
|
||||||
pub(crate) detj_deta_dy: Array2<f32>,
|
pub(crate) detj_deta_dy: Array2<Float>,
|
||||||
|
|
||||||
operator: std::marker::PhantomData<SBP>,
|
operator: std::marker::PhantomData<SBP>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SBP: super::operators::SbpOperator> Grid<SBP> {
|
impl<SBP: super::operators::SbpOperator> Grid<SBP> {
|
||||||
pub fn new(x: Array2<f32>, y: Array2<f32>) -> Result<Self, ndarray::ShapeError> {
|
pub fn new(x: Array2<Float>, y: Array2<Float>) -> Result<Self, ndarray::ShapeError> {
|
||||||
assert_eq!(x.shape(), y.shape());
|
assert_eq!(x.shape(), y.shape());
|
||||||
let ny = x.shape()[0];
|
let ny = x.shape()[0];
|
||||||
let nx = x.shape()[1];
|
let nx = x.shape()[1];
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
use super::grid::Grid;
|
use super::grid::Grid;
|
||||||
use super::operators::SbpOperator;
|
use super::operators::SbpOperator;
|
||||||
|
use super::Float;
|
||||||
use ndarray::{Array3, Zip};
|
use ndarray::{Array3, Zip};
|
||||||
|
|
||||||
pub(crate) fn rk4<'a, F: 'a, SBP, RHS, WB>(
|
pub(crate) fn rk4<'a, F: 'a, SBP, RHS, WB>(
|
||||||
rhs: RHS,
|
rhs: RHS,
|
||||||
prev: &F,
|
prev: &F,
|
||||||
fut: &mut F,
|
fut: &mut F,
|
||||||
dt: f32,
|
dt: Float,
|
||||||
grid: &Grid<SBP>,
|
grid: &Grid<SBP>,
|
||||||
k: &mut [F; 4],
|
k: &mut [F; 4],
|
||||||
mut wb: &mut WB,
|
mut wb: &mut WB,
|
||||||
) where
|
) where
|
||||||
F: std::ops::Deref<Target = Array3<f32>> + std::ops::DerefMut<Target = Array3<f32>>,
|
F: std::ops::Deref<Target = Array3<Float>> + std::ops::DerefMut<Target = Array3<Float>>,
|
||||||
SBP: SbpOperator,
|
SBP: SbpOperator,
|
||||||
RHS: Fn(&mut F, &F, &Grid<SBP>, &mut WB),
|
RHS: Fn(&mut F, &F, &Grid<SBP>, &mut WB),
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
#[cfg(feature = "f32")]
|
||||||
|
pub type Float = f32;
|
||||||
|
#[cfg(not(feature = "f32"))]
|
||||||
|
pub type Float = f64;
|
||||||
|
|
||||||
pub mod euler;
|
pub mod euler;
|
||||||
pub mod grid;
|
pub mod grid;
|
||||||
pub mod integrate;
|
pub mod integrate;
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
use super::grid::Grid;
|
use super::grid::Grid;
|
||||||
use super::integrate;
|
use super::integrate;
|
||||||
use super::operators::{SbpOperator, UpwindOperator};
|
use super::operators::{SbpOperator, UpwindOperator};
|
||||||
|
use crate::Float;
|
||||||
use ndarray::azip;
|
use ndarray::azip;
|
||||||
use ndarray::prelude::*;
|
use ndarray::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Field(pub(crate) Array3<f32>);
|
pub struct Field(pub(crate) Array3<Float>);
|
||||||
|
|
||||||
impl std::ops::Deref for Field {
|
impl std::ops::Deref for Field {
|
||||||
type Target = Array3<f32>;
|
type Target = Array3<Float>;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
@ -34,29 +35,33 @@ impl Field {
|
||||||
self.0.shape()[1]
|
self.0.shape()[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ex(&self) -> ArrayView2<f32> {
|
pub fn ex(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![0, .., ..])
|
self.slice(s![0, .., ..])
|
||||||
}
|
}
|
||||||
pub fn hz(&self) -> ArrayView2<f32> {
|
pub fn hz(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![1, .., ..])
|
self.slice(s![1, .., ..])
|
||||||
}
|
}
|
||||||
pub fn ey(&self) -> ArrayView2<f32> {
|
pub fn ey(&self) -> ArrayView2<Float> {
|
||||||
self.slice(s![2, .., ..])
|
self.slice(s![2, .., ..])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ex_mut(&mut self) -> ArrayViewMut2<f32> {
|
pub fn ex_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![0, .., ..])
|
self.slice_mut(s![0, .., ..])
|
||||||
}
|
}
|
||||||
pub fn hz_mut(&mut self) -> ArrayViewMut2<f32> {
|
pub fn hz_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![1, .., ..])
|
self.slice_mut(s![1, .., ..])
|
||||||
}
|
}
|
||||||
pub fn ey_mut(&mut self) -> ArrayViewMut2<f32> {
|
pub fn ey_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||||
self.slice_mut(s![2, .., ..])
|
self.slice_mut(s![2, .., ..])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn components_mut(
|
pub fn components_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> (ArrayViewMut2<f32>, ArrayViewMut2<f32>, ArrayViewMut2<f32>) {
|
) -> (
|
||||||
|
ArrayViewMut2<Float>,
|
||||||
|
ArrayViewMut2<Float>,
|
||||||
|
ArrayViewMut2<Float>,
|
||||||
|
) {
|
||||||
let mut iter = self.0.outer_iter_mut();
|
let mut iter = self.0.outer_iter_mut();
|
||||||
|
|
||||||
let ex = iter.next().unwrap();
|
let ex = iter.next().unwrap();
|
||||||
|
@ -76,7 +81,7 @@ pub struct System<SBP: SbpOperator> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SBP: SbpOperator> System<SBP> {
|
impl<SBP: SbpOperator> System<SBP> {
|
||||||
pub fn new(x: Array2<f32>, y: Array2<f32>) -> Self {
|
pub fn new(x: Array2<Float>, y: Array2<Float>) -> Self {
|
||||||
assert_eq!(x.shape(), y.shape());
|
assert_eq!(x.shape(), y.shape());
|
||||||
let ny = x.shape()[0];
|
let ny = x.shape()[0];
|
||||||
let nx = x.shape()[1];
|
let nx = x.shape()[1];
|
||||||
|
@ -94,7 +99,7 @@ impl<SBP: SbpOperator> System<SBP> {
|
||||||
&self.sys.0
|
&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();
|
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,
|
||||||
|
@ -106,7 +111,7 @@ impl<SBP: SbpOperator> System<SBP> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advance(&mut self, dt: f32) {
|
pub fn advance(&mut self, dt: Float) {
|
||||||
integrate::rk4(
|
integrate::rk4(
|
||||||
RHS,
|
RHS,
|
||||||
&self.sys.0,
|
&self.sys.0,
|
||||||
|
@ -122,7 +127,7 @@ impl<SBP: SbpOperator> System<SBP> {
|
||||||
|
|
||||||
impl<UO: UpwindOperator> System<UO> {
|
impl<UO: UpwindOperator> System<UO> {
|
||||||
/// Using artificial dissipation with the upwind operator
|
/// 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(
|
integrate::rk4(
|
||||||
RHS_upwind,
|
RHS_upwind,
|
||||||
&self.sys.0,
|
&self.sys.0,
|
||||||
|
@ -136,14 +141,18 @@ impl<UO: UpwindOperator> System<UO> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gaussian(x: f32, x0: f32, y: f32, y0: f32) -> f32 {
|
fn gaussian(x: Float, x0: Float, y: Float, y0: Float) -> Float {
|
||||||
use std::f32;
|
#[cfg(feature = "f32")]
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
#[cfg(not(feature = "f32"))]
|
||||||
|
use std::f64::consts::PI;
|
||||||
|
|
||||||
let x = x - x0;
|
let x = x - x0;
|
||||||
let y = y - y0;
|
let y = y - y0;
|
||||||
|
|
||||||
let sigma = 0.05;
|
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)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -166,7 +175,7 @@ fn RHS<SBP: SbpOperator>(
|
||||||
k: &mut Field,
|
k: &mut Field,
|
||||||
y: &Field,
|
y: &Field,
|
||||||
grid: &Grid<SBP>,
|
grid: &Grid<SBP>,
|
||||||
tmp: &mut (Array2<f32>, Array2<f32>, Array2<f32>, Array2<f32>),
|
tmp: &mut (Array2<Float>, Array2<Float>, Array2<Float>, Array2<Float>),
|
||||||
) {
|
) {
|
||||||
fluxes(k, y, grid, tmp);
|
fluxes(k, y, grid, tmp);
|
||||||
|
|
||||||
|
@ -189,7 +198,7 @@ fn RHS_upwind<UO: UpwindOperator>(
|
||||||
k: &mut Field,
|
k: &mut Field,
|
||||||
y: &Field,
|
y: &Field,
|
||||||
grid: &Grid<UO>,
|
grid: &Grid<UO>,
|
||||||
tmp: &mut (Array2<f32>, Array2<f32>, Array2<f32>, Array2<f32>),
|
tmp: &mut (Array2<Float>, Array2<Float>, Array2<Float>, Array2<Float>),
|
||||||
) {
|
) {
|
||||||
fluxes(k, y, grid, tmp);
|
fluxes(k, y, grid, tmp);
|
||||||
dissipation(k, y, grid, tmp);
|
dissipation(k, y, grid, tmp);
|
||||||
|
@ -212,7 +221,7 @@ fn fluxes<SBP: SbpOperator>(
|
||||||
k: &mut Field,
|
k: &mut Field,
|
||||||
y: &Field,
|
y: &Field,
|
||||||
grid: &Grid<SBP>,
|
grid: &Grid<SBP>,
|
||||||
tmp: &mut (Array2<f32>, Array2<f32>, Array2<f32>, Array2<f32>),
|
tmp: &mut (Array2<Float>, Array2<Float>, Array2<Float>, Array2<Float>),
|
||||||
) {
|
) {
|
||||||
// ex = hz_y
|
// ex = hz_y
|
||||||
{
|
{
|
||||||
|
@ -286,7 +295,7 @@ fn dissipation<UO: UpwindOperator>(
|
||||||
k: &mut Field,
|
k: &mut Field,
|
||||||
y: &Field,
|
y: &Field,
|
||||||
grid: &Grid<UO>,
|
grid: &Grid<UO>,
|
||||||
tmp: &mut (Array2<f32>, Array2<f32>, Array2<f32>, Array2<f32>),
|
tmp: &mut (Array2<Float>, Array2<Float>, Array2<Float>, Array2<Float>),
|
||||||
) {
|
) {
|
||||||
// ex component
|
// ex component
|
||||||
{
|
{
|
||||||
|
@ -295,7 +304,7 @@ fn dissipation<UO: UpwindOperator>(
|
||||||
&ky in &grid.detj_dxi_dy,
|
&ky in &grid.detj_dxi_dy,
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey()) {
|
&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;
|
*a = ky*ky/r * ex + -kx*ky/r*ey;
|
||||||
});
|
});
|
||||||
UO::dissxi(tmp.0.view(), tmp.1.view_mut());
|
UO::dissxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
@ -305,7 +314,7 @@ fn dissipation<UO: UpwindOperator>(
|
||||||
&ky in &grid.detj_deta_dy,
|
&ky in &grid.detj_deta_dy,
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey()) {
|
&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;
|
*b = ky*ky/r * ex + -kx*ky/r*ey;
|
||||||
});
|
});
|
||||||
UO::disseta(tmp.2.view(), tmp.3.view_mut());
|
UO::disseta(tmp.2.view(), tmp.3.view_mut());
|
||||||
|
@ -321,7 +330,7 @@ fn dissipation<UO: UpwindOperator>(
|
||||||
&kx in &grid.detj_dxi_dx,
|
&kx in &grid.detj_dxi_dx,
|
||||||
&ky in &grid.detj_dxi_dy,
|
&ky in &grid.detj_dxi_dy,
|
||||||
&hz in &y.hz()) {
|
&hz in &y.hz()) {
|
||||||
let r = f32::hypot(kx, ky);
|
let r = Float::hypot(kx, ky);
|
||||||
*a = r * hz;
|
*a = r * hz;
|
||||||
});
|
});
|
||||||
UO::dissxi(tmp.0.view(), tmp.1.view_mut());
|
UO::dissxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
@ -330,7 +339,7 @@ fn dissipation<UO: UpwindOperator>(
|
||||||
&kx in &grid.detj_deta_dx,
|
&kx in &grid.detj_deta_dx,
|
||||||
&ky in &grid.detj_deta_dy,
|
&ky in &grid.detj_deta_dy,
|
||||||
&hz in &y.hz()) {
|
&hz in &y.hz()) {
|
||||||
let r = f32::hypot(kx, ky);
|
let r = Float::hypot(kx, ky);
|
||||||
*b = r * hz;
|
*b = r * hz;
|
||||||
});
|
});
|
||||||
UO::disseta(tmp.2.view(), tmp.3.view_mut());
|
UO::disseta(tmp.2.view(), tmp.3.view_mut());
|
||||||
|
@ -347,7 +356,7 @@ fn dissipation<UO: UpwindOperator>(
|
||||||
&ky in &grid.detj_dxi_dy,
|
&ky in &grid.detj_dxi_dy,
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey()) {
|
&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;
|
*a = -kx*ky/r * ex + kx*kx/r*ey;
|
||||||
});
|
});
|
||||||
UO::dissxi(tmp.0.view(), tmp.1.view_mut());
|
UO::dissxi(tmp.0.view(), tmp.1.view_mut());
|
||||||
|
@ -357,7 +366,7 @@ fn dissipation<UO: UpwindOperator>(
|
||||||
&ky in &grid.detj_deta_dy,
|
&ky in &grid.detj_deta_dy,
|
||||||
&ex in &y.ex(),
|
&ex in &y.ex(),
|
||||||
&ey in &y.ey()) {
|
&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;
|
*b = -kx*ky/r * ex + kx*kx/r*ey;
|
||||||
});
|
});
|
||||||
UO::disseta(tmp.2.view(), tmp.3.view_mut());
|
UO::disseta(tmp.2.view(), tmp.3.view_mut());
|
||||||
|
@ -392,7 +401,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
let ny = y.ny();
|
let ny = y.ny();
|
||||||
let nx = y.nx();
|
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();
|
let r = (kx * kx + ky * ky).sqrt();
|
||||||
[
|
[
|
||||||
[ky * ky / r / 2.0, ky / 2.0, -kx * ky / r / 2.0],
|
[ky * ky / r / 2.0, ky / 2.0, -kx * ky / r / 2.0],
|
||||||
|
@ -400,7 +409,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
[-kx * ky / r / 2.0, -kx / 2.0, kx * kx / r / 2.0],
|
[-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();
|
let r = (kx * kx + ky * ky).sqrt();
|
||||||
[
|
[
|
||||||
[-ky * ky / r / 2.0, ky / 2.0, kx * ky / r / 2.0],
|
[-ky * ky / r / 2.0, ky / 2.0, kx * ky / r / 2.0],
|
||||||
|
@ -414,7 +423,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
Boundary::This => y.slice(s![.., .., 0]),
|
Boundary::This => y.slice(s![.., .., 0]),
|
||||||
};
|
};
|
||||||
// East boundary
|
// 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
|
for ((((mut k, v), g), &kx), &ky) in k
|
||||||
.slice_mut(s![.., .., nx - 1])
|
.slice_mut(s![.., .., nx - 1])
|
||||||
.gencolumns_mut()
|
.gencolumns_mut()
|
||||||
|
@ -448,7 +457,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
let g = match boundaries.east {
|
let g = match boundaries.east {
|
||||||
Boundary::This => y.slice(s![.., .., nx - 1]),
|
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
|
for ((((mut k, v), g), &kx), &ky) in k
|
||||||
.slice_mut(s![.., .., 0])
|
.slice_mut(s![.., .., 0])
|
||||||
.gencolumns_mut()
|
.gencolumns_mut()
|
||||||
|
@ -487,7 +496,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
let g = match boundaries.north {
|
let g = match boundaries.north {
|
||||||
Boundary::This => y.slice(s![.., 0, ..]),
|
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
|
for ((((mut k, v), g), &kx), &ky) in k
|
||||||
.slice_mut(s![.., ny - 1, ..])
|
.slice_mut(s![.., ny - 1, ..])
|
||||||
.gencolumns_mut()
|
.gencolumns_mut()
|
||||||
|
@ -520,7 +529,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
let g = match boundaries.south {
|
let g = match boundaries.south {
|
||||||
Boundary::This => y.slice(s![.., ny - 1, ..]),
|
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
|
for ((((mut k, v), g), &kx), &ky) in k
|
||||||
.slice_mut(s![.., 0, ..])
|
.slice_mut(s![.., 0, ..])
|
||||||
.gencolumns_mut()
|
.gencolumns_mut()
|
||||||
|
@ -560,7 +569,7 @@ fn SAT_characteristics<SBP: SbpOperator>(
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct WorkBuffers {
|
pub struct WorkBuffers {
|
||||||
k: [Field; 4],
|
k: [Field; 4],
|
||||||
tmp: (Array2<f32>, Array2<f32>, Array2<f32>, Array2<f32>),
|
tmp: (Array2<Float>, Array2<Float>, Array2<Float>, Array2<Float>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkBuffers {
|
impl WorkBuffers {
|
||||||
|
|
|
@ -1,29 +1,31 @@
|
||||||
#![allow(clippy::excessive_precision)]
|
#![allow(clippy::excessive_precision)]
|
||||||
#![allow(clippy::unreadable_literal)]
|
#![allow(clippy::unreadable_literal)]
|
||||||
|
|
||||||
|
use crate::Float;
|
||||||
|
|
||||||
use ndarray::{ArrayView2, ArrayViewMut2};
|
use ndarray::{ArrayView2, ArrayViewMut2};
|
||||||
|
|
||||||
pub trait SbpOperator {
|
pub trait SbpOperator {
|
||||||
fn diffxi(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>);
|
fn diffxi(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>);
|
||||||
fn diffeta(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>);
|
fn diffeta(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>);
|
||||||
fn h() -> &'static [f32];
|
fn h() -> &'static [Float];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UpwindOperator: SbpOperator {
|
pub trait UpwindOperator: SbpOperator {
|
||||||
fn dissxi(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>);
|
fn dissxi(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>);
|
||||||
fn disseta(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>);
|
fn disseta(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! diff_op_1d {
|
macro_rules! diff_op_1d {
|
||||||
($self: ty, $name: ident, $BLOCK: expr, $DIAG: expr, $symmetric: expr) => {
|
($self: ty, $name: ident, $BLOCK: expr, $DIAG: expr, $symmetric: expr) => {
|
||||||
impl $self {
|
impl $self {
|
||||||
fn $name(prev: ArrayView1<f32>, mut fut: ArrayViewMut1<f32>) {
|
fn $name(prev: ArrayView1<Float>, mut fut: ArrayViewMut1<Float>) {
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
let nx = prev.shape()[0];
|
let nx = prev.shape()[0];
|
||||||
assert!(nx >= 2 * $BLOCK.len());
|
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 idx = 1.0 / dx;
|
||||||
|
|
||||||
let block = ::ndarray::arr2($BLOCK);
|
let block = ::ndarray::arr2($BLOCK);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::SbpOperator;
|
use super::SbpOperator;
|
||||||
use crate::diff_op_1d;
|
use crate::diff_op_1d;
|
||||||
|
use crate::Float;
|
||||||
use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2};
|
use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -9,15 +10,15 @@ diff_op_1d!(SBP4, diff_1d, SBP4::BLOCK, SBP4::DIAG, false);
|
||||||
|
|
||||||
impl SBP4 {
|
impl SBP4 {
|
||||||
#[rustfmt::skip]
|
#[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,
|
17.0 / 48.0, 59.0 / 48.0, 43.0 / 48.0, 49.0 / 48.0,
|
||||||
];
|
];
|
||||||
#[rustfmt::skip]
|
#[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,
|
1.0 / 12.0, -2.0 / 3.0, 0.0, 2.0 / 3.0, -1.0 / 12.0,
|
||||||
];
|
];
|
||||||
#[rustfmt::skip]
|
#[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],
|
[-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],
|
[-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],
|
[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 {
|
impl SbpOperator for SBP4 {
|
||||||
fn diffxi(prev: ArrayView2<f32>, mut fut: ArrayViewMut2<f32>) {
|
fn diffxi(prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
||||||
|
|
||||||
|
@ -35,12 +36,12 @@ impl SbpOperator for SBP4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diffeta(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>) {
|
fn diffeta(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>) {
|
||||||
// transpose then use diffxi
|
// transpose then use diffxi
|
||||||
Self::diffxi(prev.reversed_axes(), fut.reversed_axes());
|
Self::diffxi(prev.reversed_axes(), fut.reversed_axes());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn h() -> &'static [f32] {
|
fn h() -> &'static [Float] {
|
||||||
Self::HBLOCK
|
Self::HBLOCK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::SbpOperator;
|
use super::SbpOperator;
|
||||||
use crate::diff_op_1d;
|
use crate::diff_op_1d;
|
||||||
|
use crate::Float;
|
||||||
use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2};
|
use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -9,15 +10,15 @@ diff_op_1d!(SBP8, diff_1d, SBP8::BLOCK, SBP8::DIAG, false);
|
||||||
|
|
||||||
impl SBP8 {
|
impl SBP8 {
|
||||||
#[rustfmt::skip]
|
#[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
|
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]
|
#[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
|
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]
|
#[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],
|
[-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],
|
[-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],
|
[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 {
|
impl SbpOperator for SBP8 {
|
||||||
fn diffxi(prev: ArrayView2<f32>, mut fut: ArrayViewMut2<f32>) {
|
fn diffxi(prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
||||||
|
|
||||||
|
@ -39,12 +40,12 @@ impl SbpOperator for SBP8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diffeta(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>) {
|
fn diffeta(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>) {
|
||||||
// transpose then use diffxi
|
// transpose then use diffxi
|
||||||
Self::diffxi(prev.reversed_axes(), fut.reversed_axes());
|
Self::diffxi(prev.reversed_axes(), fut.reversed_axes());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn h() -> &'static [f32] {
|
fn h() -> &'static [Float] {
|
||||||
Self::HBLOCK
|
Self::HBLOCK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
use super::{SbpOperator, UpwindOperator};
|
use super::{SbpOperator, UpwindOperator};
|
||||||
use crate::diff_op_1d;
|
use crate::diff_op_1d;
|
||||||
|
use crate::Float;
|
||||||
use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2, Axis};
|
use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2, Axis};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Upwind4 {}
|
pub struct Upwind4 {}
|
||||||
|
|
||||||
/// Simdtype used in diff_simd_col
|
/// Simdtype used in diff_simd_col
|
||||||
|
#[cfg(feature = "f32")]
|
||||||
type SimdT = packed_simd::f32x8;
|
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!(Upwind4, diff_1d, Upwind4::BLOCK, Upwind4::DIAG, false);
|
||||||
diff_op_1d!(
|
diff_op_1d!(
|
||||||
|
@ -21,44 +25,48 @@ macro_rules! diff_simd_row_7_47 {
|
||||||
($self: ident, $name: ident, $BLOCK: expr, $DIAG: expr, $symmetric: expr) => {
|
($self: ident, $name: ident, $BLOCK: expr, $DIAG: expr, $symmetric: expr) => {
|
||||||
impl $self {
|
impl $self {
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn $name(prev: ArrayView2<f32>, mut fut: ArrayViewMut2<f32>) {
|
fn $name(prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
use packed_simd::{f32x8, u32x8};
|
#[cfg(feature = "f32")]
|
||||||
|
type SimdIndex = packed_simd::u32x8;
|
||||||
|
#[cfg(not(feature = "f32"))]
|
||||||
|
type SimdIndex = packed_simd::u64x8;
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert!(prev.len_of(Axis(1)) >= 2 * $BLOCK.len());
|
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
|
// The prev and fut array must have contigous last dimension
|
||||||
assert_eq!(prev.strides()[1], 1);
|
assert_eq!(prev.strides()[1], 1);
|
||||||
assert_eq!(fut.strides()[1], 1);
|
assert_eq!(fut.strides()[1], 1);
|
||||||
|
|
||||||
let nx = prev.len_of(Axis(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;
|
let idx = 1.0 / dx;
|
||||||
|
|
||||||
for j in 0..prev.len_of(Axis(0)) {
|
for j in 0..prev.len_of(Axis(0)) {
|
||||||
use std::slice;
|
use std::slice;
|
||||||
let prev =
|
let prev =
|
||||||
unsafe { slice::from_raw_parts(prev.uget((j, 0)) as *const f32, nx) };
|
unsafe { slice::from_raw_parts(prev.uget((j, 0)) as *const Float, nx) };
|
||||||
let fut =
|
let fut = unsafe {
|
||||||
unsafe { slice::from_raw_parts_mut(fut.uget_mut((j, 0)) as *mut f32, nx) };
|
slice::from_raw_parts_mut(fut.uget_mut((j, 0)) as *mut Float, nx)
|
||||||
|
};
|
||||||
//let mut fut = fut.slice_mut(s![j, ..]);
|
//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 block = {
|
||||||
let bl = $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][0], bl[0][1], bl[0][2], bl[0][3], bl[0][4], bl[0][5],
|
||||||
bl[0][6], 0.0,
|
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][0], bl[1][1], bl[1][2], bl[1][3], bl[1][4], bl[1][5],
|
||||||
bl[1][6], 0.0,
|
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][0], bl[2][1], bl[2][2], bl[2][3], bl[2][4], bl[2][5],
|
||||||
bl[2][6], 0.0,
|
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][0], bl[3][1], bl[3][2], bl[3][3], bl[3][4], bl[3][5],
|
||||||
bl[3][6], 0.0,
|
bl[3][6], 0.0,
|
||||||
),
|
),
|
||||||
|
@ -71,7 +79,7 @@ macro_rules! diff_simd_row_7_47 {
|
||||||
|
|
||||||
let diag = {
|
let diag = {
|
||||||
let diag = $DIAG;
|
let diag = $DIAG;
|
||||||
f32x8::new(
|
SimdT::new(
|
||||||
diag[0], diag[1], diag[2], diag[3], diag[4], diag[5], diag[6], 0.0,
|
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()
|
.iter_mut()
|
||||||
.skip(block.len())
|
.skip(block.len())
|
||||||
.zip(
|
.zip(
|
||||||
prev.windows(f32x8::lanes())
|
prev.windows(SimdT::lanes())
|
||||||
.map(f32x8::from_slice_unaligned)
|
.map(SimdT::from_slice_unaligned)
|
||||||
.skip(1),
|
.skip(1),
|
||||||
)
|
)
|
||||||
.take(nx - 2 * block.len())
|
.take(nx - 2 * block.len())
|
||||||
|
@ -89,8 +97,8 @@ macro_rules! diff_simd_row_7_47 {
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_elems =
|
let last_elems =
|
||||||
unsafe { f32x8::from_slice_unaligned_unchecked(&prev[nx - 8..]) }
|
unsafe { SimdT::from_slice_unaligned_unchecked(&prev[nx - 8..]) }
|
||||||
.shuffle1_dyn(u32x8::new(7, 6, 5, 4, 3, 2, 1, 0));
|
.shuffle1_dyn(SimdIndex::new(7, 6, 5, 4, 3, 2, 1, 0));
|
||||||
if $symmetric {
|
if $symmetric {
|
||||||
fut[nx - 4] = idx * (block[3] * last_elems).sum();
|
fut[nx - 4] = idx * (block[3] * last_elems).sum();
|
||||||
fut[nx - 3] = idx * (block[2] * 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) => {
|
($self: ident, $name: ident, $BLOCK: expr, $DIAG: expr, $symmetric: expr) => {
|
||||||
impl $self {
|
impl $self {
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn $name(prev: ArrayView2<f32>, mut fut: ArrayViewMut2<f32>) {
|
fn $name(prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
use std::slice;
|
use std::slice;
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert_eq!(prev.stride_of(Axis(0)), 1);
|
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());
|
||||||
assert!(ny % SimdT::lanes() == 0);
|
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;
|
let idx = 1.0 / dx;
|
||||||
|
|
||||||
for j in (0..ny).step_by(SimdT::lanes()) {
|
for j in (0..ny).step_by(SimdT::lanes()) {
|
||||||
let a = unsafe {
|
let a = unsafe {
|
||||||
[
|
[
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
||||||
prev.uget((j, 6)) as *const f32,
|
prev.uget((j, 6)) as *const Float,
|
||||||
SimdT::lanes(),
|
SimdT::lanes(),
|
||||||
)),
|
)),
|
||||||
]
|
]
|
||||||
|
@ -180,7 +188,7 @@ macro_rules! diff_simd_col_7_47 {
|
||||||
+ a[6] * bl[6]);
|
+ a[6] * bl[6]);
|
||||||
unsafe {
|
unsafe {
|
||||||
b.write_to_slice_unaligned(slice::from_raw_parts_mut(
|
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(),
|
SimdT::lanes(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -191,7 +199,7 @@ macro_rules! diff_simd_col_7_47 {
|
||||||
// Push a onto circular buffer
|
// Push a onto circular buffer
|
||||||
a = [a[1], a[2], a[3], a[4], a[5], a[6], unsafe {
|
a = [a[1], a[2], a[3], a[4], a[5], a[6], unsafe {
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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(),
|
SimdT::lanes(),
|
||||||
))
|
))
|
||||||
}];
|
}];
|
||||||
|
@ -205,7 +213,7 @@ macro_rules! diff_simd_col_7_47 {
|
||||||
+ a[6] * $DIAG[6]);
|
+ a[6] * $DIAG[6]);
|
||||||
unsafe {
|
unsafe {
|
||||||
b.write_to_slice_unaligned(slice::from_raw_parts_mut(
|
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(),
|
SimdT::lanes(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -214,31 +222,31 @@ macro_rules! diff_simd_col_7_47 {
|
||||||
let a = unsafe {
|
let a = unsafe {
|
||||||
[
|
[
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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::lanes(),
|
||||||
)),
|
)),
|
||||||
SimdT::from_slice_unaligned(slice::from_raw_parts(
|
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(),
|
SimdT::lanes(),
|
||||||
)),
|
)),
|
||||||
]
|
]
|
||||||
|
@ -256,7 +264,7 @@ macro_rules! diff_simd_col_7_47 {
|
||||||
+ a[6] * bl[6]);
|
+ a[6] * bl[6]);
|
||||||
unsafe {
|
unsafe {
|
||||||
b.write_to_slice_unaligned(slice::from_raw_parts_mut(
|
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(),
|
SimdT::lanes(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -278,15 +286,15 @@ diff_simd_col_7_47!(
|
||||||
|
|
||||||
impl Upwind4 {
|
impl Upwind4 {
|
||||||
#[rustfmt::skip]
|
#[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
|
49.0 / 144.0, 61.0 / 48.0, 41.0 / 48.0, 149.0 / 144.0
|
||||||
];
|
];
|
||||||
#[rustfmt::skip]
|
#[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
|
-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]
|
#[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],
|
[ -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],
|
[-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],
|
[ 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]
|
#[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 / 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 / 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],
|
[-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]
|
#[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
|
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 {
|
impl SbpOperator for Upwind4 {
|
||||||
fn diffxi(prev: ArrayView2<f32>, mut fut: ArrayViewMut2<f32>) {
|
fn diffxi(prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
||||||
|
|
||||||
|
@ -329,12 +337,12 @@ impl SbpOperator for Upwind4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diffeta(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>) {
|
fn diffeta(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>) {
|
||||||
// transpose then use diffxi
|
// transpose then use diffxi
|
||||||
Self::diffxi(prev.reversed_axes(), fut.reversed_axes());
|
Self::diffxi(prev.reversed_axes(), fut.reversed_axes());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn h() -> &'static [f32] {
|
fn h() -> &'static [Float] {
|
||||||
Self::HBLOCK
|
Self::HBLOCK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,13 +351,13 @@ impl SbpOperator for Upwind4 {
|
||||||
fn upwind4_test() {
|
fn upwind4_test() {
|
||||||
use ndarray::prelude::*;
|
use ndarray::prelude::*;
|
||||||
let nx = 20;
|
let nx = 20;
|
||||||
let dx = 1.0 / (nx - 1) as f32;
|
let dx = 1.0 / (nx - 1) as Float;
|
||||||
let mut source: ndarray::Array1<f32> = ndarray::Array1::zeros(nx);
|
let mut source: ndarray::Array1<Float> = ndarray::Array1::zeros(nx);
|
||||||
let mut res = ndarray::Array1::zeros(nx);
|
let mut res = ndarray::Array1::zeros(nx);
|
||||||
let mut target = ndarray::Array1::zeros(nx);
|
let mut target = ndarray::Array1::zeros(nx);
|
||||||
|
|
||||||
for i in 0..nx {
|
for i in 0..nx {
|
||||||
source[i] = i as f32 * dx;
|
source[i] = i as Float * dx;
|
||||||
target[i] = 1.0;
|
target[i] = 1.0;
|
||||||
}
|
}
|
||||||
res.fill(0.0);
|
res.fill(0.0);
|
||||||
|
@ -374,7 +382,7 @@ fn upwind4_test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..nx {
|
for i in 0..nx {
|
||||||
let x = i as f32 * dx;
|
let x = i as Float * dx;
|
||||||
source[i] = x * x;
|
source[i] = x * x;
|
||||||
target[i] = 2.0 * x;
|
target[i] = 2.0 * x;
|
||||||
}
|
}
|
||||||
|
@ -400,7 +408,7 @@ fn upwind4_test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..nx {
|
for i in 0..nx {
|
||||||
let x = i as f32 * dx;
|
let x = i as Float * dx;
|
||||||
source[i] = x * x * x;
|
source[i] = x * x * x;
|
||||||
target[i] = 3.0 * x * x;
|
target[i] = 3.0 * x * x;
|
||||||
}
|
}
|
||||||
|
@ -428,7 +436,7 @@ fn upwind4_test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpwindOperator for Upwind4 {
|
impl UpwindOperator for Upwind4 {
|
||||||
fn dissxi(prev: ArrayView2<f32>, mut fut: ArrayViewMut2<f32>) {
|
fn dissxi(prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
||||||
|
|
||||||
|
@ -449,7 +457,7 @@ impl UpwindOperator for Upwind4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disseta(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>) {
|
fn disseta(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>) {
|
||||||
// diffeta = transpose then use dissxi
|
// diffeta = transpose then use dissxi
|
||||||
Self::dissxi(prev.reversed_axes(), fut.reversed_axes());
|
Self::dissxi(prev.reversed_axes(), fut.reversed_axes());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{SbpOperator, UpwindOperator};
|
use super::{SbpOperator, UpwindOperator};
|
||||||
use crate::diff_op_1d;
|
use crate::diff_op_1d;
|
||||||
|
use crate::Float;
|
||||||
use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2};
|
use ndarray::{s, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -16,15 +17,15 @@ diff_op_1d!(
|
||||||
|
|
||||||
impl Upwind9 {
|
impl Upwind9 {
|
||||||
#[rustfmt::skip]
|
#[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
|
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]
|
#[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,
|
-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]
|
#[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],
|
[-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],
|
[-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],
|
[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]
|
#[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.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],
|
[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],
|
[-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]
|
#[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,
|
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 {
|
impl SbpOperator for Upwind9 {
|
||||||
fn diffxi(prev: ArrayView2<f32>, mut fut: ArrayViewMut2<f32>) {
|
fn diffxi(prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
||||||
|
|
||||||
|
@ -63,18 +64,18 @@ impl SbpOperator for Upwind9 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diffeta(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>) {
|
fn diffeta(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>) {
|
||||||
// transpose then use diffxi
|
// transpose then use diffxi
|
||||||
Self::diffxi(prev.reversed_axes(), fut.reversed_axes());
|
Self::diffxi(prev.reversed_axes(), fut.reversed_axes());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn h() -> &'static [f32] {
|
fn h() -> &'static [Float] {
|
||||||
Self::HBLOCK
|
Self::HBLOCK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpwindOperator for Upwind9 {
|
impl UpwindOperator for Upwind9 {
|
||||||
fn dissxi(prev: ArrayView2<f32>, mut fut: ArrayViewMut2<f32>) {
|
fn dissxi(prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
assert!(prev.shape()[1] >= 2 * Self::BLOCK.len());
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ impl UpwindOperator for Upwind9 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disseta(prev: ArrayView2<f32>, fut: ArrayViewMut2<f32>) {
|
fn disseta(prev: ArrayView2<Float>, fut: ArrayViewMut2<Float>) {
|
||||||
// diffeta = transpose then use dissxi
|
// diffeta = transpose then use dissxi
|
||||||
Self::dissxi(prev.reversed_axes(), fut.reversed_axes());
|
Self::dissxi(prev.reversed_axes(), fut.reversed_axes());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
use crate::Float;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SimpleGrid {
|
pub struct SimpleGrid {
|
||||||
pub x: ndarray::Array2<f32>,
|
pub x: ndarray::Array2<Float>,
|
||||||
pub y: ndarray::Array2<f32>,
|
pub y: ndarray::Array2<Float>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub dire: Option<String>,
|
pub dire: Option<String>,
|
||||||
pub dirw: Option<String>,
|
pub dirw: Option<String>,
|
||||||
|
@ -32,9 +34,9 @@ pub fn json_to_grids(json: &str) -> Result<Vec<SimpleGrid>, String> {
|
||||||
enum ArrayForm {
|
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<f32>),
|
Array1(ndarray::Array1<Float>),
|
||||||
/// The usize is the inner dimension (nx)
|
/// The usize is the inner dimension (nx)
|
||||||
Array2(ndarray::Array2<f32>),
|
Array2(ndarray::Array2<Float>),
|
||||||
}
|
}
|
||||||
if grid.is_empty() {
|
if grid.is_empty() {
|
||||||
return Err(format!("empty object"));
|
return Err(format!("empty object"));
|
||||||
|
@ -54,12 +56,12 @@ pub fn json_to_grids(json: &str) -> Result<Vec<SimpleGrid>, String> {
|
||||||
assert_eq!(name, "linspace");
|
assert_eq!(name, "linspace");
|
||||||
|
|
||||||
let start = iter.next();
|
let start = iter.next();
|
||||||
let start: f32 = match start {
|
let start: Float = match start {
|
||||||
Some(x) => x.parse().map_err(|e| format!("linspace: {}", e))?,
|
Some(x) => x.parse().map_err(|e| format!("linspace: {}", e))?,
|
||||||
None => return Err(format!("")),
|
None => return Err(format!("")),
|
||||||
};
|
};
|
||||||
let end = iter.next();
|
let end = iter.next();
|
||||||
let end: f32 = match end {
|
let end: Float = match end {
|
||||||
Some(x) => x.parse().map_err(|e| format!("linspace: {}", e))?,
|
Some(x) => x.parse().map_err(|e| format!("linspace: {}", e))?,
|
||||||
None => return Err(format!("")),
|
None => return Err(format!("")),
|
||||||
};
|
};
|
||||||
|
@ -85,10 +87,10 @@ pub fn json_to_grids(json: &str) -> Result<Vec<SimpleGrid>, String> {
|
||||||
if !x[0].is_array() {
|
if !x[0].is_array() {
|
||||||
let v = x
|
let v = x
|
||||||
.members()
|
.members()
|
||||||
.map(|x: &JsonValue| -> Result<f32, String> {
|
.map(|x: &JsonValue| -> Result<Float, String> {
|
||||||
Ok(x.as_number().ok_or_else(|| format!("Array contained something that could not be converted to an array"))?.into())
|
Ok(x.as_number().ok_or_else(|| format!("Array contained something that could not be converted to an array"))?.into())
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<f32>, _>>()?;
|
.collect::<Result<Vec<Float>, _>>()?;
|
||||||
Ok(ArrayForm::Array1(ndarray::Array::from(v)))
|
Ok(ArrayForm::Array1(ndarray::Array::from(v)))
|
||||||
} else {
|
} else {
|
||||||
let arrlen2 = x[0].len();
|
let arrlen2 = x[0].len();
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#![cfg(feature = "expensive_tests")]
|
#![cfg(feature = "expensive_tests")]
|
||||||
use ndarray::prelude::*;
|
use ndarray::prelude::*;
|
||||||
use sbp::euler::*;
|
use sbp::euler::*;
|
||||||
|
use sbp::Float;
|
||||||
|
|
||||||
fn run_with_size<SBP: sbp::operators::UpwindOperator>(size: usize) -> f32 {
|
fn run_with_size<SBP: sbp::operators::UpwindOperator>(size: usize) -> Float {
|
||||||
let nx = size;
|
let nx = size;
|
||||||
let ny = size;
|
let ny = size;
|
||||||
let x = Array1::linspace(-5.0, 5.0, nx);
|
let x = Array1::linspace(-5.0, 5.0, nx);
|
||||||
|
@ -28,7 +29,7 @@ fn run_with_size<SBP: sbp::operators::UpwindOperator>(size: usize) -> f32 {
|
||||||
sys.vortex(0.0, vortex_params);
|
sys.vortex(0.0, vortex_params);
|
||||||
|
|
||||||
let time = 0.2;
|
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;
|
let nsteps = (time / dt) as usize;
|
||||||
for _ in 0..nsteps {
|
for _ in 0..nsteps {
|
||||||
|
@ -36,15 +37,15 @@ fn run_with_size<SBP: sbp::operators::UpwindOperator>(size: usize) -> f32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut verifield = Field::new(ny, nx);
|
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::<SBP>(sys.field())
|
verifield.h2_err::<SBP>(sys.field())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn convergence() {
|
fn convergence() {
|
||||||
let sizes = [25, 35, 50, 71, 100, 150];
|
let sizes = [25, 35, 50, 71, 100, 150, 200];
|
||||||
let mut prev: Option<(usize, f32)> = None;
|
let mut prev: Option<(usize, Float)> = None;
|
||||||
println!("Size\tError(h2)\tq");
|
println!("Size\tError(h2)\tq");
|
||||||
for size in &sizes {
|
for size in &sizes {
|
||||||
print!("{:3}x{:3}", size, size);
|
print!("{:3}x{:3}", size, size);
|
||||||
|
@ -57,7 +58,8 @@ fn convergence() {
|
||||||
let (size1, e1) = prev;
|
let (size1, e1) = prev;
|
||||||
let m1 = size1 * size1;
|
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);
|
print!("\t{}", q);
|
||||||
}
|
}
|
||||||
println!();
|
println!();
|
||||||
|
|
|
@ -12,5 +12,5 @@ path = "lib.rs"
|
||||||
wasm-bindgen = "0.2.58"
|
wasm-bindgen = "0.2.58"
|
||||||
console_error_panic_hook = "0.1.6"
|
console_error_panic_hook = "0.1.6"
|
||||||
wee_alloc = "0.4.5"
|
wee_alloc = "0.4.5"
|
||||||
sbp = { path = "../sbp" }
|
sbp = { path = "../sbp", features = ["f32"] }
|
||||||
ndarray = "0.13.0"
|
ndarray = "0.13.0"
|
||||||
|
|
Loading…
Reference in New Issue