extern crate ohsl;
pub use ohsl::vector::{Vector, Vec64};
pub use ohsl::matrix::{Matrix, Mat64};
use ohsl::sparse::Sparse;
use std::time::Instant;
fn main() {
println!( "------------------ Laplace's equation ------------------" );
println!( " * Solve Laplace's equation on the unit square subject");
println!( " * to the given boundary conditions. The exact solution");
println!( " * is u(x,y) = y/[(1+x)^2 + y^2].");
let start = Instant::now();
let n: usize = 64; let dx: f64 = 1.0 / ( n as f64 ); let size: usize = ( n + 1 ) * ( n + 1 ); let mut rhs = Vec64::zeros( size );
let mut triplets = Vec::new();
let mut row: usize = 0;
let i = 0;
for j in 0..n+1 {
let y = (j as f64) * dx;
triplets.push( ( row, i * ( n + 1 ) + j, 1.0 ) );
rhs[ row ] = y / ( 1.0 + y * y );
row += 1;
}
for i in 1..n {
let x = (i as f64) * dx;
let j = 0;
triplets.push( ( row, i * ( n + 1 ) + j, 1.0 ) );
rhs[ row ] = 0.0;
row += 1;
for j in 1..n {
triplets.push( ( row, ( i - 1 ) * ( n + 1 ) + j, 1.0 ) );
triplets.push( ( row, ( i + 1 ) * ( n + 1 ) + j, 1.0 ) );
triplets.push( ( row, i * ( n + 1 ) + j - 1, 1.0 ) );
triplets.push( ( row, i * ( n + 1 ) + j + 1, 1.0 ) );
triplets.push( ( row, i * ( n + 1 ) + j, - 4.0 ) );
rhs[ row ] = 0.0;
row += 1;
}
let j = n;
triplets.push( ( row, i * ( n + 1 ) + j, 1.0 ) );
rhs[ row ] = 1. / ( ( 1. + x ) * ( 1. + x ) + 1. );
row += 1;
}
let i = n;
for j in 0..n+1 {
let y = (j as f64) * dx;
triplets.push( ( row, i * ( n + 1 ) + j, 1.0 ) );
rhs[ row ] = y / ( 4. + y * y );
row += 1;
}
let mut u_exact = Vec64::zeros( size );
row = 0;
for i in 0..n+1 {
let x = (i as f64) * dx;
for j in 0..n+1 {
let y = (j as f64) * dx;
u_exact[ row ] = y / ( ( 1. + x ) * ( 1. + x ) + y * y );
row += 1;
}
}
let sparse = Sparse::<f64>::from_triplets( size, size, &mut triplets );
let duration = start.elapsed();
println!(" * Time to create the matrix: {:?}", duration);
let mut u_guess = Vector::<f64>::random( size ); let max_iter = 1000;
let tol = 1e-8;
let result = sparse.solve_qmr( &rhs, &mut u_guess, max_iter, tol );
let duration = start.elapsed();
match result {
Ok( iter ) => println!( " * The sparse system converged in {} iterations.", iter ),
Err( error ) => println!( " * The sparse system failed to converge, error = {}", error )
}
println!(" * Time to solve the system: {:?}", duration);
let u_diff = u_guess - u_exact;
println!(" * Solution error = {}", u_diff.norm_2() );
println!( "-------------------- FINISHED ---------------------" );
}