Add interpolation grid generators
This commit is contained in:
parent
5b7f407af9
commit
5bbc13158a
|
@ -6,6 +6,7 @@ members = [
|
||||||
"euler",
|
"euler",
|
||||||
"maxwell",
|
"maxwell",
|
||||||
"shallow_water",
|
"shallow_water",
|
||||||
|
"gridgeneration",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = ["sbp", "euler", "maxwell", "shallow_water"]
|
default-members = ["sbp", "euler", "maxwell", "shallow_water"]
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "gridgeneration"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Magnus Ulimoen <magnus@ulimoen.dev>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ndarray = { version = "0.13.1", default-features = false }
|
||||||
|
plotters = { version = "0.3.0", default-features = false, features = ["svg_backend", "line_series", "point_series"] }
|
||||||
|
sbp = { path = "../sbp" }
|
||||||
|
json5 = { version = "0.2.8", optional = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
serde = ["sbp/serde1", "json5"]
|
|
@ -0,0 +1,125 @@
|
||||||
|
use ndarray::Array2;
|
||||||
|
|
||||||
|
pub use sbp::{consts::*, grid::Grid, Float};
|
||||||
|
|
||||||
|
pub fn unit(ny: usize, nx: usize) -> Grid {
|
||||||
|
let x = Array2::from_shape_fn((ny, nx), |(_j, i)| i as Float / (nx - 1) as Float);
|
||||||
|
let y = Array2::from_shape_fn((ny, nx), |(j, _i)| j as Float / (ny - 1) as Float);
|
||||||
|
Grid::new(x, y).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shell(ny: usize, nx: usize, mut inner: Float, mut outer: Float) -> Grid {
|
||||||
|
let mut unit = unit(ny, nx);
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
enum Mode {
|
||||||
|
Log,
|
||||||
|
Exp,
|
||||||
|
Normal,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mode = Mode::Log;
|
||||||
|
match mode {
|
||||||
|
Mode::Exp => {
|
||||||
|
inner = inner.exp();
|
||||||
|
outer = outer.exp();
|
||||||
|
}
|
||||||
|
Mode::Log => {
|
||||||
|
inner = inner.ln();
|
||||||
|
outer = outer.ln();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (mut gx, mut gy) = unit.components();
|
||||||
|
gx.iter_mut().zip(gy.iter_mut()).for_each(|(x, y)| {
|
||||||
|
let mut r = (*x) * (outer - inner) + inner;
|
||||||
|
match mode {
|
||||||
|
Mode::Exp => {
|
||||||
|
r = r.ln();
|
||||||
|
}
|
||||||
|
Mode::Log => {
|
||||||
|
r = r.exp();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
let theta = *y * 2.0 * PI;
|
||||||
|
|
||||||
|
*x = r * theta.cos();
|
||||||
|
*y = r * theta.sin();
|
||||||
|
});
|
||||||
|
|
||||||
|
unit
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vertical_interpolation(jlen: usize, north: &[Float], south: &[Float]) -> Grid {
|
||||||
|
let ilen = north.len();
|
||||||
|
assert_eq!(north.len(), south.len());
|
||||||
|
let mut grid = unit(jlen, ilen);
|
||||||
|
|
||||||
|
for j in 0..jlen {
|
||||||
|
for i in 0..ilen {
|
||||||
|
let y = grid.y()[(j, i)];
|
||||||
|
grid.y_mut()[(j, i)] = (north[i] - south[i]) * y + south[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grid
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn horizontal_interpolation(ilen: usize, east: &[Float], west: &[Float]) -> Grid {
|
||||||
|
let jlen = east.len();
|
||||||
|
assert_eq!(east.len(), west.len());
|
||||||
|
let mut grid = unit(jlen, ilen);
|
||||||
|
|
||||||
|
for j in 0..jlen {
|
||||||
|
for i in 0..ilen {
|
||||||
|
let x = grid.x()[(j, i)];
|
||||||
|
grid.x_mut()[(j, i)] = (east[j] - west[j]) * x + west[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grid
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn horizontal_interpolation_dual(
|
||||||
|
ilen: usize,
|
||||||
|
east: (&[Float], &[Float]),
|
||||||
|
west: (&[Float], &[Float]),
|
||||||
|
) -> Grid {
|
||||||
|
let jlen = east.0.len();
|
||||||
|
assert_eq!(east.0.len(), east.1.len());
|
||||||
|
assert_eq!(east.0.len(), west.0.len());
|
||||||
|
assert_eq!(east.0.len(), west.1.len());
|
||||||
|
let mut grid = unit(jlen, ilen);
|
||||||
|
|
||||||
|
for j in 0..jlen {
|
||||||
|
for i in 0..ilen {
|
||||||
|
let x = grid.x()[(j, i)];
|
||||||
|
grid.x_mut()[(j, i)] = (east.1[j] - west.1[j]) * x + west.1[j];
|
||||||
|
grid.y_mut()[(j, i)] = (east.0[j] - west.0[j]) * x + west.0[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grid
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [east] : fn([0, 1]) -> (y, x)
|
||||||
|
/// [west] : fn([0, 1]) -> (y, x)
|
||||||
|
pub fn horizontal_interpolation_dual2(
|
||||||
|
ilen: usize,
|
||||||
|
jlen: usize,
|
||||||
|
east: impl Fn(Float) -> (Float, Float),
|
||||||
|
west: impl Fn(Float) -> (Float, Float),
|
||||||
|
) -> Grid {
|
||||||
|
let mut grid = unit(jlen, ilen);
|
||||||
|
|
||||||
|
for j in 0..jlen {
|
||||||
|
for i in 0..ilen {
|
||||||
|
let x = grid.x()[(j, i)];
|
||||||
|
let y = grid.y()[(j, i)];
|
||||||
|
let east = east(y);
|
||||||
|
let west = west(y);
|
||||||
|
grid.x_mut()[(j, i)] = (east.1 - west.1) * x + west.1;
|
||||||
|
grid.y_mut()[(j, i)] = (east.0 - west.0) * x + west.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grid
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
#![allow(unused)]
|
||||||
|
use gridgeneration::*;
|
||||||
|
use plotters::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// let grid = Grid::unit(10, 11);
|
||||||
|
// let grid = shell(30, 21, 0.1, 3.1);
|
||||||
|
let grid = {
|
||||||
|
let ybot = (0..100)
|
||||||
|
.map(|x| (x as Float / 30.0).sin())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let ytop = (0..100)
|
||||||
|
.map(|x| 2.5 + (x as Float / 10.0).sin())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
// vertical_interpolation(10, &ytop, &ybot)
|
||||||
|
// horizontal_interpolation(10, &ytop, &ybot)
|
||||||
|
/*
|
||||||
|
horizontal_interpolation_dual(
|
||||||
|
30,
|
||||||
|
(&[0.0, 0.0, 1.0, 3.0], &[0.0, 2.0, 4.0, 6.0]),
|
||||||
|
(&[3.0, 5.0, 6.0, 7.0], &[0.0, 2.0, 3.0, 10.0]),
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
horizontal_interpolation_dual2(
|
||||||
|
30,
|
||||||
|
40,
|
||||||
|
move |t| ((t * 3.0).sin(), t + 0.2),
|
||||||
|
move |t| ((5.0 * t).sin() + 2.5, t),
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
horizontal_interpolation_dual2(
|
||||||
|
30,
|
||||||
|
40,
|
||||||
|
move |t| (2.0 * t * std::f64::consts::PI).sin_cos(),
|
||||||
|
move |t| {
|
||||||
|
let (y, x) = (2.0 * t * std::f64::consts::PI).sin_cos();
|
||||||
|
(0.1 * y, 0.1 * x)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
draw_grid(&grid, "grid.svg");
|
||||||
|
|
||||||
|
let grid = horizontal_interpolation_dual2(
|
||||||
|
200,
|
||||||
|
200,
|
||||||
|
move |t| {
|
||||||
|
let ts = [0.05, 0.25, 0.75, 0.95];
|
||||||
|
if t < ts[0] {
|
||||||
|
let t = t / (ts[0] - 0.0);
|
||||||
|
(t, 5.0)
|
||||||
|
} else if t < ts[1] {
|
||||||
|
let t = (t - ts[0]) / (ts[1] - ts[0]);
|
||||||
|
(1.0, 5.0 - 5.0 * t)
|
||||||
|
} else if t < ts[2] {
|
||||||
|
let t = (t - ts[1]) / (ts[2] - ts[1]);
|
||||||
|
(std::f64::consts::PI * (t + 0.5)).sin_cos()
|
||||||
|
} else if t < ts[3] {
|
||||||
|
let t = (t - ts[2]) / (ts[3] - ts[2]);
|
||||||
|
(-1.0, 5.0 * t)
|
||||||
|
} else {
|
||||||
|
let t = (t - ts[3]) / (1.0 - ts[3]);
|
||||||
|
(-1.0 + t, 5.0)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
move |t| {
|
||||||
|
let (y, x) = (2.0 * t * std::f64::consts::PI).sin_cos();
|
||||||
|
(0.2 * y, 0.2 * x)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
draw_grid(&grid, "ctype.svg");
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
println!("{}", json5::to_string(&grid).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn linspace(range: std::ops::Range<Float>, steps: usize) -> Vec<Float> {
|
||||||
|
let start = range.start;
|
||||||
|
let end = range.end;
|
||||||
|
|
||||||
|
let dx = (end - start) / (steps - 1) as Float;
|
||||||
|
|
||||||
|
(0..steps).map(|i| i as Float * dx).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_grid(grid: &Grid, name: &str) {
|
||||||
|
let drawing_area = SVGBackend::new(name, (1000, 1000)).into_drawing_area();
|
||||||
|
drawing_area.fill(&WHITE).unwrap();
|
||||||
|
|
||||||
|
let x_minmax = grid
|
||||||
|
.x()
|
||||||
|
.iter()
|
||||||
|
.fold((Float::INFINITY, -Float::INFINITY), |(min, max), &x| {
|
||||||
|
(min.min(x), max.max(x))
|
||||||
|
});
|
||||||
|
let y_minmax = grid
|
||||||
|
.y()
|
||||||
|
.iter()
|
||||||
|
.fold((Float::INFINITY, -Float::INFINITY), |(min, max), &y| {
|
||||||
|
(min.min(y), max.max(y))
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut chart = ChartBuilder::on(&drawing_area)
|
||||||
|
.x_label_area_size(40)
|
||||||
|
.y_label_area_size(40)
|
||||||
|
.build_cartesian_2d(x_minmax.0..x_minmax.1, y_minmax.0..y_minmax.1)
|
||||||
|
.unwrap();
|
||||||
|
chart
|
||||||
|
.configure_mesh()
|
||||||
|
.x_desc("x")
|
||||||
|
.y_desc("y")
|
||||||
|
.disable_mesh()
|
||||||
|
.draw()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let style = &BLACK.stroke_width(1);
|
||||||
|
for axes in &[ndarray::Axis(1), ndarray::Axis(0)] {
|
||||||
|
for (linex, liney) in grid.x().axis_iter(*axes).zip(grid.y().axis_iter(*axes)) {
|
||||||
|
chart
|
||||||
|
.draw_series(LineSeries::new(
|
||||||
|
linex.iter().zip(&liney).map(|(&x, &y)| (x, y)),
|
||||||
|
style.clone(),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
let coord = |idx| (grid.x()[idx], grid.y()[idx]);
|
||||||
|
let zero = coord((0, 0));
|
||||||
|
let up = coord((1, 0));
|
||||||
|
let right = coord((0, 1));
|
||||||
|
chart
|
||||||
|
.draw_series(PointSeries::of_element(
|
||||||
|
[zero].iter().copied(),
|
||||||
|
5,
|
||||||
|
ShapeStyle::from(&RED).filled(),
|
||||||
|
&|coord, size, style| {
|
||||||
|
EmptyElement::at(coord)
|
||||||
|
+ Circle::new((0, 0), size, style)
|
||||||
|
+ Text::new("η", (1, 1), ("arial", 10))
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
*/
|
||||||
|
}
|
Loading…
Reference in New Issue