diffsol_la/linear_solver/nalgebra/
lu.rs1use nalgebra::Dyn;
2
3use crate::{
4 error::LaError, linear_solver_error, matrix::dense_nalgebra_serial::NalgebraMat, LinearOp,
5 LinearSolver, Matrix, NalgebraContext, NalgebraScalar, NalgebraVec,
6};
7
8#[derive(Clone)]
10pub struct LU<T>
11where
12 T: NalgebraScalar,
13{
14 matrix: Option<NalgebraMat<T>>,
15 lu: Option<nalgebra::LU<T, Dyn, Dyn>>,
16}
17
18impl<T> Default for LU<T>
19where
20 T: NalgebraScalar,
21{
22 fn default() -> Self {
23 Self {
24 lu: None,
25 matrix: None,
26 }
27 }
28}
29
30impl<T: NalgebraScalar> LinearSolver<NalgebraMat<T>> for LU<T> {
31 fn solve_in_place(&self, state: &mut NalgebraVec<T>) -> Result<(), LaError> {
32 if self.lu.is_none() {
33 return Err(linear_solver_error!(LuNotInitialized));
34 }
35 let lu = self.lu.as_ref().unwrap();
36 match lu.solve_mut(&mut state.data) {
37 true => Ok(()),
38 false => Err(linear_solver_error!(LuSolveFailed))?,
39 }
40 }
41
42 fn set_linearisation<
43 C: LinearOp<T = T, V = NalgebraVec<T>, M = NalgebraMat<T>, C = NalgebraContext>,
44 >(
45 &mut self,
46 op: &C,
47 ) {
48 let matrix = self.matrix.as_mut().expect("Matrix not set");
49 op.matrix_inplace(matrix);
50 self.lu = Some(matrix.data.clone().lu());
51 }
52
53 fn set_sparsity<
54 C: LinearOp<T = T, V = NalgebraVec<T>, M = NalgebraMat<T>, C = NalgebraContext>,
55 >(
56 &mut self,
57 op: &C,
58 ) {
59 let ncols = op.ncols();
60 let nrows = op.nrows();
61 let matrix = C::M::new_from_sparsity(nrows, ncols, op.sparsity(), *op.context());
62 self.matrix = Some(matrix);
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use crate::{linear_solver::tests::diagonal_op, Vector};
70
71 #[test]
72 fn test_lu() {
73 let mut s = LU::<f64>::default();
74 let op = diagonal_op::<NalgebraMat<f64>>(2.0);
75 s.set_sparsity(&op);
76 s.set_linearisation(&op);
77 let b = NalgebraVec::from_vec(vec![2.0, 4.0], Default::default());
78 let x = s.solve(&b).unwrap();
79 x.assert_eq_st(
80 &NalgebraVec::from_vec(vec![1.0, 2.0], Default::default()),
81 1e-10,
82 );
83 }
84}