prototype multigrid
This commit is contained in:
parent
3bffd18488
commit
7f0b5b8430
|
@ -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(),
|
||||
};
|
||||
*/
|
||||
}
|
|
@ -203,16 +203,16 @@ impl Field {
|
|||
(rho, rhou, rhov, e)
|
||||
}
|
||||
|
||||
fn north(&self) -> ArrayView2<Float> {
|
||||
pub fn north(&self) -> ArrayView2<Float> {
|
||||
self.slice(s![.., self.ny() - 1, ..])
|
||||
}
|
||||
fn south(&self) -> ArrayView2<Float> {
|
||||
pub fn south(&self) -> ArrayView2<Float> {
|
||||
self.slice(s![.., 0, ..])
|
||||
}
|
||||
fn east(&self) -> ArrayView2<Float> {
|
||||
pub fn east(&self) -> ArrayView2<Float> {
|
||||
self.slice(s![.., .., self.nx() - 1])
|
||||
}
|
||||
fn west(&self) -> ArrayView2<Float> {
|
||||
pub fn west(&self) -> ArrayView2<Float> {
|
||||
self.slice(s![.., .., 0])
|
||||
}
|
||||
fn north_mut(&mut self) -> ArrayViewMut2<Float> {
|
||||
|
@ -413,7 +413,7 @@ pub(crate) fn RHS_trad<SBP: SbpOperator>(
|
|||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub(crate) fn RHS_upwind<UO: UpwindOperator>(
|
||||
pub fn RHS_upwind<UO: UpwindOperator>(
|
||||
k: &mut Field,
|
||||
y: &Field,
|
||||
grid: &Grid<UO>,
|
||||
|
|
|
@ -73,4 +73,11 @@ impl<SBP: super::operators::SbpOperator> Grid<SBP> {
|
|||
pub fn ny(&self) -> usize {
|
||||
self.x.shape()[0]
|
||||
}
|
||||
|
||||
pub fn x(&self) -> ndarray::ArrayView2<Float> {
|
||||
self.x.view()
|
||||
}
|
||||
pub fn y(&self) -> ndarray::ArrayView2<Float> {
|
||||
self.y.view()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue