move sparse to maxwell
This commit is contained in:
		@@ -4,14 +4,17 @@ version = "0.1.0"
 | 
			
		||||
authors = ["Magnus Ulimoen <flymagnus@gmail.com>"]
 | 
			
		||||
edition = "2018"
 | 
			
		||||
 | 
			
		||||
[features]
 | 
			
		||||
sparse = ["sbp/sparse", "sprs"]
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
ndarray = "0.13.1"
 | 
			
		||||
sbp = { path = "../sbp" }
 | 
			
		||||
sprs = { version = "0.7.1", optional = true }
 | 
			
		||||
 | 
			
		||||
[dev-dependencies]
 | 
			
		||||
criterion = "0.3.1"
 | 
			
		||||
criterion = "0.3.2"
 | 
			
		||||
 | 
			
		||||
[[bench]]
 | 
			
		||||
name = "bench"
 | 
			
		||||
harness = false
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,9 @@ use sbp::integrate;
 | 
			
		||||
use sbp::operators::{SbpOperator2d, UpwindOperator2d};
 | 
			
		||||
use sbp::Float;
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "sparse")]
 | 
			
		||||
mod sparse;
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct Field(pub(crate) Array3<Float>);
 | 
			
		||||
 | 
			
		||||
@@ -85,6 +88,10 @@ pub struct System<SBP: SbpOperator2d> {
 | 
			
		||||
    grid: Grid,
 | 
			
		||||
    metrics: Metrics,
 | 
			
		||||
    op: SBP,
 | 
			
		||||
    #[cfg(feature = "sparse")]
 | 
			
		||||
    rhs: sprs::CsMat<Float>,
 | 
			
		||||
    #[cfg(feature = "sparse")]
 | 
			
		||||
    lhs: sprs::CsMat<Float>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<SBP: SbpOperator2d> System<SBP> {
 | 
			
		||||
@@ -96,12 +103,22 @@ impl<SBP: SbpOperator2d> System<SBP> {
 | 
			
		||||
        let grid = Grid::new(x, y).unwrap();
 | 
			
		||||
        let metrics = grid.metrics(&op).unwrap();
 | 
			
		||||
 | 
			
		||||
        #[cfg(feature = "sparse")]
 | 
			
		||||
        let rhs = sparse::rhs_matrix(&op, ny, nx);
 | 
			
		||||
 | 
			
		||||
        #[cfg(feature = "sparse")]
 | 
			
		||||
        let lhs = sparse::implicit_matrix(rhs.view(), 0.2 / std::cmp::max(ny, nx) as Float);
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            op,
 | 
			
		||||
            sys: (Field::new(ny, nx), Field::new(ny, nx)),
 | 
			
		||||
            grid,
 | 
			
		||||
            metrics,
 | 
			
		||||
            wb: WorkBuffers::new(ny, nx),
 | 
			
		||||
            #[cfg(feature = "sparse")]
 | 
			
		||||
            rhs,
 | 
			
		||||
            #[cfg(feature = "sparse")]
 | 
			
		||||
            lhs,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -140,6 +157,44 @@ impl<SBP: SbpOperator2d> System<SBP> {
 | 
			
		||||
        );
 | 
			
		||||
        std::mem::swap(&mut self.sys.0, &mut self.sys.1);
 | 
			
		||||
    }
 | 
			
		||||
    #[cfg(feature = "sparse")]
 | 
			
		||||
    pub fn advance_sparse(&mut self, dt: Float) {
 | 
			
		||||
        let rhs = self.rhs.view();
 | 
			
		||||
        let rhs_f = |next: &mut Field, now: &Field, _t: Float| {
 | 
			
		||||
            next.fill(0.0);
 | 
			
		||||
            sprs::prod::mul_acc_mat_vec_csr(
 | 
			
		||||
                rhs,
 | 
			
		||||
                now.as_slice().unwrap(),
 | 
			
		||||
                next.as_slice_mut().unwrap(),
 | 
			
		||||
            );
 | 
			
		||||
        };
 | 
			
		||||
        sbp::integrate::integrate::<sbp::integrate::Rk4, _, _>(
 | 
			
		||||
            rhs_f,
 | 
			
		||||
            &self.sys.0,
 | 
			
		||||
            &mut self.sys.1,
 | 
			
		||||
            &mut 0.0,
 | 
			
		||||
            dt,
 | 
			
		||||
            &mut self.wb.k[..],
 | 
			
		||||
        );
 | 
			
		||||
        std::mem::swap(&mut self.sys.0, &mut self.sys.1);
 | 
			
		||||
    }
 | 
			
		||||
    #[cfg(feature = "sparse")]
 | 
			
		||||
    pub fn advance_implicit(&mut self) {
 | 
			
		||||
        let lhs = self.lhs.view();
 | 
			
		||||
 | 
			
		||||
        let b = self.sys.0.clone();
 | 
			
		||||
 | 
			
		||||
        let tnow = std::time::Instant::now();
 | 
			
		||||
        sbp::utils::jacobi_method(
 | 
			
		||||
            lhs,
 | 
			
		||||
            b.as_slice().unwrap(),
 | 
			
		||||
            self.sys.0.as_slice_mut().unwrap(),
 | 
			
		||||
            self.sys.1.as_slice_mut().unwrap(),
 | 
			
		||||
            10,
 | 
			
		||||
        );
 | 
			
		||||
        let elapsed = tnow.elapsed();
 | 
			
		||||
        println!("{:?}", elapsed);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<UO: UpwindOperator2d> System<UO> {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										254
									
								
								maxwell/src/sparse.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								maxwell/src/sparse.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
use super::Float;
 | 
			
		||||
use sbp::operators::SbpOperator2d;
 | 
			
		||||
use sbp::utils::sparse_sparse_outer_product;
 | 
			
		||||
 | 
			
		||||
/// Implicit version of the system
 | 
			
		||||
/// C u_{t+1} = u_t
 | 
			
		||||
pub fn implicit_matrix(rhs: sprs::CsMatView<Float>, dt: Float) -> sprs::CsMat<Float> {
 | 
			
		||||
    let n = rhs.rows();
 | 
			
		||||
    let i_kyx = sprs::CsMat::eye(n);
 | 
			
		||||
    let f = rhs.map(|x| x * dt);
 | 
			
		||||
    &i_kyx - &f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Assumes self boundaries
 | 
			
		||||
pub fn rhs_matrix(op: &dyn SbpOperator2d, ny: usize, nx: usize) -> sprs::CsMat<Float> {
 | 
			
		||||
    let d1_x = op.op_eta().diff_matrix(nx);
 | 
			
		||||
    let d1_y = op.op_xi().diff_matrix(ny);
 | 
			
		||||
 | 
			
		||||
    let ix = sprs::CsMat::<Float>::eye(nx);
 | 
			
		||||
    let iy = sprs::CsMat::eye(ny);
 | 
			
		||||
 | 
			
		||||
    let dx = sparse_sparse_outer_product(iy.view(), d1_x.view());
 | 
			
		||||
    let dy = sparse_sparse_outer_product(d1_y.view(), ix.view());
 | 
			
		||||
 | 
			
		||||
    let mut a_flux = sprs::TriMat::new((3, 3));
 | 
			
		||||
    a_flux.add_triplet(1, 2, -1.0);
 | 
			
		||||
    a_flux.add_triplet(2, 1, -1.0);
 | 
			
		||||
    let a_flux = a_flux.to_csr();
 | 
			
		||||
 | 
			
		||||
    let mut b_flux = sprs::TriMat::new((3, 3));
 | 
			
		||||
    b_flux.add_triplet(0, 1, 1.0);
 | 
			
		||||
    b_flux.add_triplet(1, 0, 1.0);
 | 
			
		||||
    let b_flux = b_flux.to_csr();
 | 
			
		||||
 | 
			
		||||
    let f = &sparse_sparse_outer_product(a_flux.view(), dx.view())
 | 
			
		||||
        + &sparse_sparse_outer_product(b_flux.view(), dy.view());
 | 
			
		||||
 | 
			
		||||
    let mut hx = sparse_sparse_outer_product(iy.view(), op.op_xi().h_matrix(nx).view());
 | 
			
		||||
    hx.map_inplace(|h| 1.0 / h);
 | 
			
		||||
    let ihx = hx;
 | 
			
		||||
    let mut hy = sparse_sparse_outer_product(op.op_eta().h_matrix(ny).view(), ix.view());
 | 
			
		||||
    hy.map_inplace(|h| 1.0 / h);
 | 
			
		||||
    let ihy = hy;
 | 
			
		||||
 | 
			
		||||
    let _f = {
 | 
			
		||||
        // West boundary
 | 
			
		||||
        let mut aminus = sprs::TriMat::new((3, 3));
 | 
			
		||||
        aminus.add_triplet(1, 1, -0.5);
 | 
			
		||||
        aminus.add_triplet(1, 2, -0.5);
 | 
			
		||||
        aminus.add_triplet(2, 1, -0.5);
 | 
			
		||||
        aminus.add_triplet(2, 2, -0.5);
 | 
			
		||||
        let aminus = aminus.to_csr();
 | 
			
		||||
 | 
			
		||||
        let mut e0x = sprs::TriMat::new((nx, 1));
 | 
			
		||||
        e0x.add_triplet(0, 0, 1.0);
 | 
			
		||||
        let e0x = e0x.to_csr();
 | 
			
		||||
        let e0x_nt = &e0x * &e0x.transpose_view();
 | 
			
		||||
        let e0x_nt = sparse_sparse_outer_product(iy.view(), e0x_nt.view());
 | 
			
		||||
 | 
			
		||||
        let sat0 = &ihx * &e0x_nt;
 | 
			
		||||
        let mut sat0 = sparse_sparse_outer_product(aminus.view(), sat0.view());
 | 
			
		||||
 | 
			
		||||
        let tau = 1.0;
 | 
			
		||||
        sat0.map_inplace(|x| tau * x);
 | 
			
		||||
 | 
			
		||||
        &f + &sat0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let _f = {
 | 
			
		||||
        // East boundary
 | 
			
		||||
        let mut aplus = sprs::TriMat::new((3, 3));
 | 
			
		||||
        aplus.add_triplet(1, 1, 0.5);
 | 
			
		||||
        aplus.add_triplet(1, 2, -0.5);
 | 
			
		||||
        aplus.add_triplet(2, 1, -0.5);
 | 
			
		||||
        aplus.add_triplet(2, 2, 0.5);
 | 
			
		||||
        let aplus = aplus.to_csr();
 | 
			
		||||
 | 
			
		||||
        let mut enx = sprs::TriMat::new((nx, 1));
 | 
			
		||||
        enx.add_triplet(nx - 1, 0, 1.0);
 | 
			
		||||
        let enx = enx.to_csr();
 | 
			
		||||
        let enx_nt = &enx * &enx.transpose_view();
 | 
			
		||||
        let enx_nt = sparse_sparse_outer_product(iy.view(), enx_nt.view());
 | 
			
		||||
 | 
			
		||||
        let satn = &ihx * &enx_nt;
 | 
			
		||||
        let mut satn = sparse_sparse_outer_product(aplus.view(), satn.view());
 | 
			
		||||
 | 
			
		||||
        let tau = -1.0;
 | 
			
		||||
        satn.map_inplace(|x| tau * x);
 | 
			
		||||
 | 
			
		||||
        &f + &satn
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let _f = {
 | 
			
		||||
        // South boundary
 | 
			
		||||
        let mut bminus = sprs::TriMat::new((3, 3));
 | 
			
		||||
        bminus.add_triplet(0, 0, -0.5);
 | 
			
		||||
        bminus.add_triplet(0, 1, 0.5);
 | 
			
		||||
        bminus.add_triplet(1, 0, 0.5);
 | 
			
		||||
        bminus.add_triplet(1, 1, -0.5);
 | 
			
		||||
        let bminus = bminus.to_csr();
 | 
			
		||||
 | 
			
		||||
        let mut e0y = sprs::TriMat::new((ny, 1));
 | 
			
		||||
        e0y.add_triplet(0, 0, 1.0);
 | 
			
		||||
        let e0y = e0y.to_csr();
 | 
			
		||||
        let e0y_nt = &e0y * &e0y.transpose_view();
 | 
			
		||||
        let e0y_nt = sparse_sparse_outer_product(e0y_nt.view(), ix.view());
 | 
			
		||||
 | 
			
		||||
        let sat0 = &ihx * &e0y_nt;
 | 
			
		||||
        let mut sat0 = sparse_sparse_outer_product(bminus.view(), sat0.view());
 | 
			
		||||
 | 
			
		||||
        let tau = 1.0;
 | 
			
		||||
        sat0.map_inplace(|x| tau * x);
 | 
			
		||||
 | 
			
		||||
        &f + &sat0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let _f = {
 | 
			
		||||
        // North boundary
 | 
			
		||||
        let mut bplus = sprs::TriMat::new((3, 3));
 | 
			
		||||
        bplus.add_triplet(0, 0, 0.5);
 | 
			
		||||
        bplus.add_triplet(0, 1, 0.5);
 | 
			
		||||
        bplus.add_triplet(1, 0, 0.5);
 | 
			
		||||
        bplus.add_triplet(1, 1, 0.5);
 | 
			
		||||
        let bplus = bplus.to_csr();
 | 
			
		||||
 | 
			
		||||
        let mut eny = sprs::TriMat::new((ny, 1));
 | 
			
		||||
        eny.add_triplet(ny - 1, 0, 1.0);
 | 
			
		||||
        let eny = eny.to_csr();
 | 
			
		||||
        let eny_nt = &eny * &eny.transpose_view();
 | 
			
		||||
        let eny_nt = sparse_sparse_outer_product(eny_nt.view(), ix.view());
 | 
			
		||||
 | 
			
		||||
        let satn = &ihy * &eny_nt;
 | 
			
		||||
        let mut satn = sparse_sparse_outer_product(bplus.view(), satn.view());
 | 
			
		||||
 | 
			
		||||
        let tau = -1.0;
 | 
			
		||||
        satn.map_inplace(|x| tau * x);
 | 
			
		||||
 | 
			
		||||
        &f + &satn
 | 
			
		||||
    };
 | 
			
		||||
    // Setting up the periodic boundaries
 | 
			
		||||
    let _f = {
 | 
			
		||||
        // West
 | 
			
		||||
        let mut aminus = sprs::TriMat::new((3, 3));
 | 
			
		||||
        aminus.add_triplet(1, 1, -0.5);
 | 
			
		||||
        aminus.add_triplet(1, 2, -0.5);
 | 
			
		||||
        aminus.add_triplet(2, 1, -0.5);
 | 
			
		||||
        aminus.add_triplet(2, 2, -0.5);
 | 
			
		||||
        let aminus = aminus.to_csr();
 | 
			
		||||
 | 
			
		||||
        let mut e0x = sprs::TriMat::new((nx, 1));
 | 
			
		||||
        e0x.add_triplet(0, 0, 1.0);
 | 
			
		||||
        let e0x = e0x.to_csr();
 | 
			
		||||
        let mut enx = sprs::TriMat::new((nx, 1));
 | 
			
		||||
        enx.add_triplet(nx - 1, 0, 1.0);
 | 
			
		||||
        let enx = enx.to_csr();
 | 
			
		||||
 | 
			
		||||
        let e0nx_nt = &e0x * &enx.transpose_view();
 | 
			
		||||
        let e0nx_nt = sparse_sparse_outer_product(iy.view(), e0nx_nt.view());
 | 
			
		||||
 | 
			
		||||
        let sat0 = &ihx * &e0nx_nt;
 | 
			
		||||
        let mut sat0 = sparse_sparse_outer_product(aminus.view(), sat0.view());
 | 
			
		||||
 | 
			
		||||
        let tau = 1.0;
 | 
			
		||||
        // Negative => subtracting this boundary
 | 
			
		||||
        sat0.map_inplace(|x| -tau * x);
 | 
			
		||||
 | 
			
		||||
        &f + &sat0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let _f = {
 | 
			
		||||
        // East boundary
 | 
			
		||||
        let mut aplus = sprs::TriMat::new((3, 3));
 | 
			
		||||
        aplus.add_triplet(1, 1, 0.5);
 | 
			
		||||
        aplus.add_triplet(1, 2, -0.5);
 | 
			
		||||
        aplus.add_triplet(2, 1, -0.5);
 | 
			
		||||
        aplus.add_triplet(2, 2, 0.5);
 | 
			
		||||
        let aplus = aplus.to_csr();
 | 
			
		||||
 | 
			
		||||
        let mut enx = sprs::TriMat::new((nx, 1));
 | 
			
		||||
        enx.add_triplet(nx - 1, 0, 1.0);
 | 
			
		||||
        let enx = enx.to_csr();
 | 
			
		||||
        let mut e0x = sprs::TriMat::new((nx, 1));
 | 
			
		||||
        e0x.add_triplet(0, 0, 1.0);
 | 
			
		||||
        let e0x = e0x.to_csr();
 | 
			
		||||
 | 
			
		||||
        let en0x_nt = &enx * &e0x.transpose_view();
 | 
			
		||||
        let en0x_nt = sparse_sparse_outer_product(iy.view(), en0x_nt.view());
 | 
			
		||||
 | 
			
		||||
        let satn = &ihx * &en0x_nt;
 | 
			
		||||
        let mut satn = sparse_sparse_outer_product(aplus.view(), satn.view());
 | 
			
		||||
 | 
			
		||||
        let tau = -1.0;
 | 
			
		||||
        satn.map_inplace(|x| -tau * x);
 | 
			
		||||
 | 
			
		||||
        &f + &satn
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let _f = {
 | 
			
		||||
        // South boundary
 | 
			
		||||
        let mut bminus = sprs::TriMat::new((3, 3));
 | 
			
		||||
        bminus.add_triplet(0, 0, -0.5);
 | 
			
		||||
        bminus.add_triplet(0, 1, 0.5);
 | 
			
		||||
        bminus.add_triplet(1, 0, 0.5);
 | 
			
		||||
        bminus.add_triplet(1, 1, -0.5);
 | 
			
		||||
        let bminus = bminus.to_csr();
 | 
			
		||||
 | 
			
		||||
        let mut e0y = sprs::TriMat::new((ny, 1));
 | 
			
		||||
        e0y.add_triplet(0, 0, 1.0);
 | 
			
		||||
        let e0y = e0y.to_csr();
 | 
			
		||||
        let mut eny = sprs::TriMat::new((ny, 1));
 | 
			
		||||
        eny.add_triplet(ny - 1, 0, 1.0);
 | 
			
		||||
        let eny = eny.to_csr();
 | 
			
		||||
 | 
			
		||||
        let e0ny_nt = &e0y * &eny.transpose_view();
 | 
			
		||||
        let e0ny_nt = sparse_sparse_outer_product(e0ny_nt.view(), ix.view());
 | 
			
		||||
 | 
			
		||||
        let sat0 = &ihx * &e0ny_nt;
 | 
			
		||||
        let mut sat0 = sparse_sparse_outer_product(bminus.view(), sat0.view());
 | 
			
		||||
 | 
			
		||||
        let tau = 1.0;
 | 
			
		||||
        sat0.map_inplace(|x| -tau * x);
 | 
			
		||||
 | 
			
		||||
        &f + &sat0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let _f = {
 | 
			
		||||
        // North boundary
 | 
			
		||||
        let mut bplus = sprs::TriMat::new((3, 3));
 | 
			
		||||
        bplus.add_triplet(0, 0, 0.5);
 | 
			
		||||
        bplus.add_triplet(0, 1, 0.5);
 | 
			
		||||
        bplus.add_triplet(1, 0, 0.5);
 | 
			
		||||
        bplus.add_triplet(1, 1, 0.5);
 | 
			
		||||
        let bplus = bplus.to_csr();
 | 
			
		||||
 | 
			
		||||
        let mut eny = sprs::TriMat::new((ny, 1));
 | 
			
		||||
        eny.add_triplet(ny - 1, 0, 1.0);
 | 
			
		||||
        let eny = eny.to_csr();
 | 
			
		||||
        let mut e0y = sprs::TriMat::new((ny, 1));
 | 
			
		||||
        e0y.add_triplet(0, 0, 1.0);
 | 
			
		||||
        let e0y = e0y.to_csr();
 | 
			
		||||
 | 
			
		||||
        let en0y_nt = &eny * &e0y.transpose_view();
 | 
			
		||||
        let en0y_nt = sparse_sparse_outer_product(en0y_nt.view(), ix.view());
 | 
			
		||||
 | 
			
		||||
        let satn = &ihy * &en0y_nt;
 | 
			
		||||
        let mut satn = sparse_sparse_outer_product(bplus.view(), satn.view());
 | 
			
		||||
 | 
			
		||||
        let tau = -1.0;
 | 
			
		||||
        satn.map_inplace(|x| -tau * x);
 | 
			
		||||
 | 
			
		||||
        &f + &satn
 | 
			
		||||
    };
 | 
			
		||||
    f
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user