use approx::{assert_abs_diff_eq, assert_relative_eq};
use automatica::{signals::continuous, Seconds, Ss, Ssd, Tf, Tfz};
use polynomen::{poly, Poly};
#[test]
fn poles_eigenvalues() {
let num = [4.0_f64];
let den = Poly::new_from_roots(&[-1., -2., -3.]);
let tf = Tf::new(num, den).normalize();
let sys = Ss::new_observability_realization(&tf).unwrap();
assert_eq!(tf.complex_poles(), sys.poles());
}
#[test]
fn series_system() {
let tf1 = Tfz::new([1.0_f64], Poly::new_from_roots(&[-0.7, -0.5]));
let tf2 = Tfz::new([1.], Poly::new_from_roots(&[-0.2, -0.25]));
let stable_tf = &tf1 * &tf2;
assert!(stable_tf.is_stable());
let tf3 = Tfz::new([1.0_f64], Poly::new_from_roots(&[2., -0.25]));
let unstable_tf = tf1 * tf3;
assert!(!unstable_tf.is_stable());
}
#[test]
fn parallel_system() {
let tf1 = Tf::new([1.0_f64], Poly::new_from_roots(&[-1., -0.5]));
let tf2 = Tf::new([1.], Poly::new_from_roots(&[-2., -0.25]));
let stable_tf = &tf1 + &tf2;
assert!(stable_tf.is_stable());
let tf3 = Tf::new([1.], Poly::new_from_roots(&[2., -0.25]));
let unstable_tf = tf1 + tf3;
assert!(!unstable_tf.is_stable());
}
#[test]
fn initial_state_independence() {
let a = &[0.3_f32, 0., 0., 0.25];
let b = &[3., -1.];
let c = &[1., 1.];
let d = &[1.];
let sys = Ssd::new_from_slice(2, 1, 1, a, b, c, d);
let tf = Tfz::new_from_siso(&sys).unwrap();
let expected = tf.static_gain();
let iter = std::iter::repeat(vec![1.]);
let steps = 30;
let evolution1 = sys.evolution_iter(iter.clone(), &[0., 0.]);
let response1 = evolution1.take(steps).last().unwrap()[0];
assert_relative_eq!(expected, response1);
let evolution2 = sys.evolution_iter(iter, &[1., -1.]);
let response2 = evolution2.take(steps).last().unwrap()[0];
assert_relative_eq!(expected, response2);
}
#[test]
fn to_zero() {
let tf = Tf::new([1., 5.], poly!(1., 2.) * poly!(1., 1.));
let sys = Ss::new_observability_realization(&tf).unwrap();
let impulse = continuous::impulse(1., Seconds(0.), 1);
let evo = sys.rk2(&impulse, &[0., 0.], Seconds(0.1), 150);
let last = evo.last().unwrap();
assert_abs_diff_eq!(0., last.state()[0], epsilon = 1e-4);
assert_abs_diff_eq!(0., last.output()[0], epsilon = 1e-4);
}
#[test]
fn initial_value() {
let num = [1., 5.];
let den = poly!(1., 2.) * poly!(1., 1.);
let g = Tf::new(num, den);
let sys = Ss::new_observability_realization(&g).unwrap();
let limit = g.eval(&1e30);
let mut evo = sys.rk2(|_| vec![1.], &[0., 0.], Seconds(0.1), 25);
let init = evo.next().unwrap().output()[0];
assert_relative_eq!(0., limit);
assert_relative_eq!(0., init);
assert_relative_eq!(limit, init);
}