2020-06-14 19:59:22 +00:00
|
|
|
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> {
|
2020-06-15 19:24:19 +00:00
|
|
|
let eye = |n: usize| sprs::CsMat::eye(n);
|
2020-06-14 19:59:22 +00:00
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let fluxes = {
|
|
|
|
let d1_x = op.op_eta().diff_matrix(nx);
|
|
|
|
let d1_y = op.op_xi().diff_matrix(ny);
|
2020-06-14 19:59:22 +00:00
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let dx = sparse_sparse_outer_product(eye(ny).view(), d1_x.view());
|
|
|
|
let dy = sparse_sparse_outer_product(d1_y.view(), eye(nx).view());
|
2020-06-14 19:59:22 +00:00
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let mut a_flux = sprs::CsMat::zero((3, 3));
|
|
|
|
a_flux.insert(1, 2, -1.0);
|
|
|
|
a_flux.insert(2, 1, -1.0);
|
2020-06-14 19:59:22 +00:00
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let mut b_flux = sprs::CsMat::zero((3, 3));
|
|
|
|
b_flux.insert(0, 1, 1.0);
|
|
|
|
b_flux.insert(1, 0, 1.0);
|
2020-06-14 19:59:22 +00:00
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
&sparse_sparse_outer_product(a_flux.view(), dx.view())
|
|
|
|
+ &sparse_sparse_outer_product(b_flux.view(), dy.view())
|
|
|
|
};
|
2020-06-14 19:59:22 +00:00
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let sat_west = {
|
2020-06-14 19:59:22 +00:00
|
|
|
// West boundary
|
2020-06-15 19:24:19 +00:00
|
|
|
let aminus = {
|
|
|
|
let mut aminus = sprs::CsMat::zero((3, 3));
|
|
|
|
aminus.insert(1, 1, -0.5);
|
|
|
|
aminus.insert(1, 2, -0.5);
|
|
|
|
aminus.insert(2, 1, -0.5);
|
|
|
|
aminus.insert(2, 2, -0.5);
|
|
|
|
aminus
|
|
|
|
};
|
|
|
|
let e0 = {
|
|
|
|
let mut e0 = sprs::CsMat::zero((nx, 1));
|
|
|
|
e0.insert(0, 0, 1.0);
|
|
|
|
e0
|
|
|
|
};
|
|
|
|
let en = {
|
|
|
|
let mut en = sprs::CsMat::zero((nx, 1));
|
|
|
|
en.insert(nx - 1, 0, 1.0);
|
|
|
|
en
|
|
|
|
};
|
|
|
|
|
|
|
|
// Periodic => (e_0 - e_n)q => 0
|
|
|
|
let p = &e0 - &en;
|
|
|
|
|
|
|
|
// Forming the matrix of size (nx,nx)
|
|
|
|
let mat = &e0 * &p.transpose_view();
|
|
|
|
// Must be scaled by the h norm
|
|
|
|
let hi = op.op_xi().h_matrix(nx).map(|h| 1.0 / h);
|
|
|
|
let mat = &hi * &mat;
|
|
|
|
// Upscaling to (nx * ny, nx * ny)
|
|
|
|
let mat = sparse_sparse_outer_product(eye(ny).view(), mat.view());
|
|
|
|
|
|
|
|
let mut sat = sparse_sparse_outer_product(aminus.view(), mat.view());
|
2020-06-14 19:59:22 +00:00
|
|
|
|
|
|
|
let tau = 1.0;
|
2020-06-15 19:24:19 +00:00
|
|
|
// Scaling by tau
|
|
|
|
sat.map_inplace(|x| tau * x);
|
|
|
|
sat
|
2020-06-14 19:59:22 +00:00
|
|
|
};
|
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let sat_east = {
|
2020-06-14 19:59:22 +00:00
|
|
|
// East boundary
|
2020-06-15 19:24:19 +00:00
|
|
|
let aminus = {
|
|
|
|
let mut aplus = sprs::CsMat::zero((3, 3));
|
|
|
|
aplus.insert(1, 1, 0.5);
|
|
|
|
aplus.insert(1, 2, -0.5);
|
|
|
|
aplus.insert(2, 1, -0.5);
|
|
|
|
aplus.insert(2, 2, 0.5);
|
|
|
|
aplus
|
|
|
|
};
|
|
|
|
let e0 = {
|
|
|
|
let mut e0 = sprs::CsMat::zero((nx, 1));
|
|
|
|
e0.insert(0, 0, 1.0);
|
|
|
|
e0
|
|
|
|
};
|
|
|
|
let en = {
|
|
|
|
let mut en = sprs::CsMat::zero((nx, 1));
|
|
|
|
en.insert(nx - 1, 0, 1.0);
|
|
|
|
en
|
|
|
|
};
|
|
|
|
|
|
|
|
// Periodic => (e_0 - e_n) => 0
|
|
|
|
let p = &en - &e0;
|
|
|
|
|
|
|
|
// Forming the matrix of size (nx,nx)
|
|
|
|
let mat = &en * &p.transpose_view();
|
|
|
|
// Must be scaled by the h norm
|
|
|
|
let hi = op.op_xi().h_matrix(nx).map(|h| 1.0 / h);
|
|
|
|
let mat = &hi * &mat;
|
|
|
|
// Upscaling to (nx * ny, nx * ny)
|
|
|
|
let mat = sparse_sparse_outer_product(eye(ny).view(), mat.view());
|
|
|
|
|
|
|
|
let mut sat = sparse_sparse_outer_product(aminus.view(), mat.view());
|
2020-06-14 19:59:22 +00:00
|
|
|
|
|
|
|
let tau = -1.0;
|
2020-06-15 19:24:19 +00:00
|
|
|
// Scaling by tau
|
|
|
|
sat.map_inplace(|x| tau * x);
|
|
|
|
sat
|
2020-06-14 19:59:22 +00:00
|
|
|
};
|
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let sat_south = {
|
2020-06-14 19:59:22 +00:00
|
|
|
// South boundary
|
2020-06-15 19:24:19 +00:00
|
|
|
let bminus = {
|
|
|
|
let mut bminus = sprs::CsMat::zero((3, 3));
|
|
|
|
bminus.insert(0, 0, -0.5);
|
|
|
|
bminus.insert(0, 1, 0.5);
|
|
|
|
bminus.insert(1, 0, 0.5);
|
|
|
|
bminus.insert(1, 1, -0.5);
|
|
|
|
bminus
|
|
|
|
};
|
|
|
|
let e0 = {
|
|
|
|
let mut e0 = sprs::CsMat::zero((ny, 1));
|
|
|
|
e0.insert(0, 0, 1.0);
|
|
|
|
e0
|
|
|
|
};
|
|
|
|
let en = {
|
|
|
|
let mut en = sprs::CsMat::zero((ny, 1));
|
|
|
|
en.insert(ny - 1, 0, 1.0);
|
|
|
|
en
|
|
|
|
};
|
|
|
|
|
|
|
|
// Periodic => (e_0 - e_n) => 0
|
|
|
|
let p = &e0 - &en;
|
|
|
|
|
|
|
|
// Forming the matrix of size (ny,ny)
|
|
|
|
let mat = &e0 * &p.transpose_view();
|
|
|
|
// Must be scaled by the h norm
|
|
|
|
let hi = op.op_eta().h_matrix(ny).map(|h| 1.0 / h);
|
|
|
|
let mat = &hi * &mat;
|
|
|
|
// Upscaling to (nx * ny, nx * ny)
|
|
|
|
let mat = sparse_sparse_outer_product(mat.view(), eye(nx).view());
|
|
|
|
|
|
|
|
let mut sat = sparse_sparse_outer_product(bminus.view(), mat.view());
|
2020-06-14 19:59:22 +00:00
|
|
|
|
|
|
|
let tau = 1.0;
|
2020-06-15 19:24:19 +00:00
|
|
|
// Scaling by tau
|
|
|
|
sat.map_inplace(|x| tau * x);
|
|
|
|
sat
|
2020-06-14 19:59:22 +00:00
|
|
|
};
|
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let sat_north = {
|
2020-06-14 19:59:22 +00:00
|
|
|
// North boundary
|
2020-06-15 19:24:19 +00:00
|
|
|
let bplus = {
|
|
|
|
let mut bplus = sprs::CsMat::zero((3, 3));
|
|
|
|
bplus.insert(0, 0, 0.5);
|
|
|
|
bplus.insert(0, 1, 0.5);
|
|
|
|
bplus.insert(1, 0, 0.5);
|
|
|
|
bplus.insert(1, 1, 0.5);
|
|
|
|
bplus
|
|
|
|
};
|
|
|
|
let e0 = {
|
|
|
|
let mut e0 = sprs::CsMat::zero((ny, 1));
|
|
|
|
e0.insert(0, 0, 1.0);
|
|
|
|
e0
|
|
|
|
};
|
|
|
|
let en = {
|
|
|
|
let mut en = sprs::CsMat::zero((ny, 1));
|
|
|
|
en.insert(ny - 1, 0, 1.0);
|
|
|
|
en
|
|
|
|
};
|
|
|
|
|
|
|
|
// Periodic => (e_0 - e_n) => 0
|
|
|
|
let p = &en - &e0;
|
|
|
|
|
|
|
|
// Forming the matrix of size (ny,ny)
|
|
|
|
let mat = &en * &p.transpose_view();
|
|
|
|
// Must be scaled by the h norm
|
|
|
|
let hi = op.op_eta().h_matrix(ny).map(|h| 1.0 / h);
|
|
|
|
let mat = &hi * &mat;
|
|
|
|
// Upscaling to (nx * ny, nx * ny)
|
|
|
|
let mat = sparse_sparse_outer_product(mat.view(), eye(nx).view());
|
|
|
|
|
|
|
|
let mut sat = sparse_sparse_outer_product(bplus.view(), mat.view());
|
2020-06-14 19:59:22 +00:00
|
|
|
|
|
|
|
let tau = -1.0;
|
2020-06-15 19:24:19 +00:00
|
|
|
// Scaling by tau
|
|
|
|
sat.map_inplace(|x| tau * x);
|
|
|
|
sat
|
2020-06-14 19:59:22 +00:00
|
|
|
};
|
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
&fluxes + &(&(&sat_west + &sat_east) + &(&sat_north + &sat_south))
|
|
|
|
}
|
2020-06-14 19:59:22 +00:00
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
#[test]
|
|
|
|
fn dummy() {
|
|
|
|
let ny = 16;
|
|
|
|
let nx = 17;
|
2020-06-14 19:59:22 +00:00
|
|
|
|
2020-06-15 19:24:19 +00:00
|
|
|
let rhs = rhs_matrix(&sbp::operators::Upwind4, ny, nx);
|
|
|
|
let _lhs = implicit_matrix(rhs.view(), 1e-2);
|
2020-06-14 19:59:22 +00:00
|
|
|
}
|