prototype multigrid
This commit is contained in:
		
							
								
								
									
										236
									
								
								sbp/examples/multigrid.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								sbp/examples/multigrid.rs
									
									
									
									
									
										Normal 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(),
 | 
			
		||||
    };
 | 
			
		||||
    */
 | 
			
		||||
}
 | 
			
		||||
@@ -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()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user