prototype multigrid

This commit is contained in:
Magnus Ulimoen 2020-04-01 00:08:55 +02:00
parent 3bffd18488
commit 7f0b5b8430
3 changed files with 248 additions and 5 deletions

236
sbp/examples/multigrid.rs Normal file
View File

@ -0,0 +1,236 @@
use ndarray::prelude::*;
use sbp::*;
/*
* A 2D grid divided in four parts, spanning the rectangle [-5, 5] x [-5, 5]
*
* / \ y
* |
* | 5.0 000 333
* | 000 333
* | 000 333
* | 0.0
* | 111 222
* | 111 222
* |-5.0 111 222
* |
* | -5.0 0.0 5.0 x
* ------------------------->
*/
struct System<T: operators::UpwindOperator> {
fnow: Vec<euler::Field>,
fnext: Vec<euler::Field>,
wb: Vec<(
euler::Field,
euler::Field,
euler::Field,
euler::Field,
euler::Field,
euler::Field,
)>,
k: [Vec<euler::Field>; 4],
grids: Vec<grid::Grid<T>>,
}
impl<T: operators::UpwindOperator> System<T> {
fn new(grids: Vec<grid::Grid<T>>) -> Self {
let fnow = grids
.iter()
.map(|g| euler::Field::new(g.ny(), g.nx()))
.collect::<Vec<_>>();
let fnext = fnow.clone();
let wb = grids
.iter()
.map(|g| {
let f = euler::Field::new(g.ny(), g.nx());
(f.clone(), f.clone(), f.clone(), f.clone(), f.clone(), f)
})
.collect();
let k = [fnow.clone(), fnow.clone(), fnow.clone(), fnow.clone()];
Self {
fnow,
fnext,
k,
wb,
grids,
}
}
fn vortex(&mut self, t: Float, vortex_params: euler::VortexParameters) {
for (f, g) in self.fnow.iter_mut().zip(&self.grids) {
f.vortex(g.x(), g.y(), t, vortex_params);
}
}
fn advance(&mut self, dt: Float) {
for i in 0.. {
let fnext;
match i {
0 => {
for (prev, fut) in self.fnow.iter().zip(self.fnext.iter_mut()) {
fut.assign(prev);
}
fnext = &mut self.k[i];
}
1 | 2 => {
for ((prev, fut), k) in self
.fnow
.iter()
.zip(self.fnext.iter_mut())
.zip(&self.k[i - 1])
{
fut.assign(prev);
fut.scaled_add(1.0 / 2.0 * dt, k);
}
fnext = &mut self.k[i];
}
3 => {
for ((prev, fut), k) in self
.fnow
.iter()
.zip(self.fnext.iter_mut())
.zip(&self.k[i - 1])
{
fut.assign(prev);
fut.scaled_add(dt, k);
}
fnext = &mut self.k[i];
}
4 => {
for (((((prev, fut), k0), k1), k2), k3) in self
.fnow
.iter()
.zip(self.fnext.iter_mut())
.zip(&self.k[0])
.zip(&self.k[1])
.zip(&self.k[2])
.zip(&self.k[3])
{
ndarray::Zip::from(&mut **fut)
.and(&**prev)
.and(&**k0)
.and(&**k1)
.and(&**k2)
.and(&**k3)
.apply(|y1, &y0, &k1, &k2, &k3, &k4| {
*y1 = y0 + dt / 6.0 * (k1 + 2.0 * k2 + 2.0 * k3 + k4)
});
}
return;
}
_ => {
unreachable!();
}
}
let bt = vec![
euler::BoundaryTerms {
north: self.fnext[1].north(),
south: self.fnext[1].south(),
east: self.fnext[3].west(),
west: self.fnext[3].east(),
},
euler::BoundaryTerms {
north: self.fnext[0].north(),
south: self.fnext[0].south(),
east: self.fnext[2].west(),
west: self.fnext[2].east(),
},
euler::BoundaryTerms {
north: self.fnext[3].north(),
south: self.fnext[3].south(),
east: self.fnext[0].west(),
west: self.fnext[0].east(),
},
euler::BoundaryTerms {
north: self.fnext[2].north(),
south: self.fnext[2].south(),
east: self.fnext[1].west(),
west: self.fnext[1].east(),
},
];
for ((((prev, fut), grid), wb), bt) in self
.fnext
.iter()
.zip(fnext)
.zip(&self.grids)
.zip(&mut self.wb)
.zip(bt)
{
euler::RHS_upwind(fut, prev, grid, &bt, wb)
}
}
}
}
fn mesh(x: (f64, f64, usize), y: (f64, f64, usize)) -> (Array2<f64>, Array2<f64>) {
let arrx = Array1::linspace(x.0, x.1, x.2);
let arry = Array1::linspace(y.0, y.1, y.2);
let gx = arrx.broadcast((y.2, x.2)).unwrap();
let mut gy = arry.broadcast((x.2, y.2)).unwrap();
gy.swap_axes(0, 1);
(gx.into_owned(), gy.into_owned())
}
fn main() {
let n = 20;
let mut grids = Vec::with_capacity(4);
let (x0, y0) = mesh((-5.0, 0.0, n), (0.0, 5.0, n));
grids.push(grid::Grid::<operators::Upwind4>::new(x0, y0).unwrap());
let (x1, y1) = mesh((-5.0, 0.0, n), (-5.0, 0.0, n));
grids.push(grid::Grid::<operators::Upwind4>::new(x1, y1).unwrap());
let (x2, y2) = mesh((0.0, 5.0, n), (-5.0, 0.0, n));
grids.push(grid::Grid::<operators::Upwind4>::new(x2, y2).unwrap());
let (x3, y3) = mesh((0.0, 5.0, n), (0.0, 5.0, n));
grids.push(grid::Grid::<operators::Upwind4>::new(x3, y3).unwrap());
let mut sys = System::new(grids);
sys.vortex(
0.0,
euler::VortexParameters {
x0: 0.0,
y0: 0.0,
mach: 0.5,
rstar: 0.5,
eps: 1.0,
},
);
sys.advance(0.05);
/*
let bt0 = euler::BoundaryTerms {
north: sys1.field().north(),
south: sys1.field().south(),
east: sys3.field().west(),
west: sys3.field().east(),
};
let bt1 = euler::BoundaryTerms {
north: sys0.field().north(),
south: sys0.field().south(),
east: sys2.field().west(),
west: sys2.field().east(),
};
let bt2 = euler::BoundaryTerms {
north: sys3.field().north(),
south: sys3.field().south(),
east: sys0.field().west(),
west: sys0.field().east(),
};
let bt3 = euler::BoundaryTerms {
north: sys2.field().north(),
south: sys2.field().south(),
east: sys1.field().west(),
west: sys1.field().east(),
};
*/
}

View File

@ -203,16 +203,16 @@ impl Field {
(rho, rhou, rhov, e) (rho, rhou, rhov, e)
} }
fn north(&self) -> ArrayView2<Float> { pub fn north(&self) -> ArrayView2<Float> {
self.slice(s![.., self.ny() - 1, ..]) self.slice(s![.., self.ny() - 1, ..])
} }
fn south(&self) -> ArrayView2<Float> { pub fn south(&self) -> ArrayView2<Float> {
self.slice(s![.., 0, ..]) self.slice(s![.., 0, ..])
} }
fn east(&self) -> ArrayView2<Float> { pub fn east(&self) -> ArrayView2<Float> {
self.slice(s![.., .., self.nx() - 1]) self.slice(s![.., .., self.nx() - 1])
} }
fn west(&self) -> ArrayView2<Float> { pub fn west(&self) -> ArrayView2<Float> {
self.slice(s![.., .., 0]) self.slice(s![.., .., 0])
} }
fn north_mut(&mut self) -> ArrayViewMut2<Float> { fn north_mut(&mut self) -> ArrayViewMut2<Float> {
@ -413,7 +413,7 @@ pub(crate) fn RHS_trad<SBP: SbpOperator>(
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub(crate) fn RHS_upwind<UO: UpwindOperator>( pub fn RHS_upwind<UO: UpwindOperator>(
k: &mut Field, k: &mut Field,
y: &Field, y: &Field,
grid: &Grid<UO>, grid: &Grid<UO>,

View File

@ -73,4 +73,11 @@ impl<SBP: super::operators::SbpOperator> Grid<SBP> {
pub fn ny(&self) -> usize { pub fn ny(&self) -> usize {
self.x.shape()[0] self.x.shape()[0]
} }
pub fn x(&self) -> ndarray::ArrayView2<Float> {
self.x.view()
}
pub fn y(&self) -> ndarray::ArrayView2<Float> {
self.y.view()
}
} }