russell_ode 2.7.0

Solvers for ordinary differential equations and differential algebraic equations
Documentation
use russell_lab::{Vector, approx_eq};
use russell_ode::{Method, OdeSolver, Params, Samples};

#[test]
fn test_bweuler_hairer_wanner_eq1() {
    // get ODE system
    let (system, x0, mut y0, mut args, y_fn_x) = Samples::hairer_wanner_eq1();
    let ndim = system.get_ndim();

    // final x
    let x1 = 1.5;

    // set configuration parameters
    let params = Params::new(Method::BwEuler);
    let mut solver = OdeSolver::new(params, system).unwrap();

    // solve the ODE system
    let h_equal = Some(1.875 / 50.0);
    solver.solve(&mut y0, x0, x1, h_equal, &mut args, None).unwrap();

    // get statistics
    let stat = solver.stats();

    // compare with a previous implementation
    approx_eq(y0[0], 0.09060476604187756, 1e-15);
    assert_eq!(stat.h_accepted, h_equal.unwrap());

    // compare with the analytical solution
    let mut y1_correct = Vector::new(ndim);
    y_fn_x(&mut y1_correct, x1, &mut args);
    approx_eq(y0[0], y1_correct[0], 5e-5);

    // print and check statistics
    println!("{}", stat);
    assert_eq!(stat.n_function, 80);
    assert_eq!(stat.n_jacobian, 40);
    assert_eq!(stat.n_factor, 40);
    assert_eq!(stat.n_lin_sol, 40);
    assert_eq!(stat.n_steps, 40);
    assert_eq!(stat.n_accepted, 40);
    assert_eq!(stat.n_rejected, 0);
    assert_eq!(stat.n_iterations, 2);
    assert_eq!(stat.n_iterations_max, 2);
}

#[test]
fn test_bweuler_hairer_wanner_eq1_num_jac() {
    // get ODE system
    let (system, x0, mut y0, mut args, y_fn_x) = Samples::hairer_wanner_eq1();
    let ndim = system.get_ndim();

    // final x
    let x1 = 1.5;

    // set configuration parameters
    let mut params = Params::new(Method::BwEuler);
    params.newton.use_numerical_jacobian = true;

    // solve the ODE system
    let mut solver = OdeSolver::new(params, system).unwrap();
    let h_equal = Some(1.875 / 50.0);
    solver.solve(&mut y0, x0, x1, h_equal, &mut args, None).unwrap();

    // get statistics
    let stat = solver.stats();

    // compare with a previous implementation
    approx_eq(y0[0], 0.09060476598021044, 1e-11);
    assert_eq!(stat.h_accepted, h_equal.unwrap());

    // compare with the analytical solution
    let mut y1_correct = Vector::new(ndim);
    y_fn_x(&mut y1_correct, x1, &mut args);
    approx_eq(y0[0], y1_correct[0], 5e-5);

    // print and check statistics
    println!("{}", stat);
    assert_eq!(stat.n_function, 120);
    assert_eq!(stat.n_jacobian, 40);
    assert_eq!(stat.n_factor, 40);
    assert_eq!(stat.n_lin_sol, 40);
    assert_eq!(stat.n_steps, 40);
    assert_eq!(stat.n_accepted, 40);
    assert_eq!(stat.n_rejected, 0);
    assert_eq!(stat.n_iterations, 2);
    assert_eq!(stat.n_iterations_max, 2);
}

#[test]
fn test_bweuler_hairer_wanner_eq1_modified_newton() {
    // get ODE system
    let (system, x0, mut y0, mut args, y_fn_x) = Samples::hairer_wanner_eq1();
    let ndim = system.get_ndim();

    // final x
    let x1 = 1.5;

    // set configuration parameters
    let mut params = Params::new(Method::BwEuler);
    params.bweuler.use_modified_newton = true;

    // solve the ODE system
    let mut solver = OdeSolver::new(params, system).unwrap();
    let h_equal = Some(1.875 / 50.0);
    solver.solve(&mut y0, x0, x1, h_equal, &mut args, None).unwrap();

    // get statistics
    let stat = solver.stats();

    // compare with a previous implementation
    approx_eq(y0[0], 0.09060476604187756, 1e-15);
    assert_eq!(stat.h_accepted, h_equal.unwrap());

    // compare with the analytical solution
    let mut y1_correct = Vector::new(ndim);
    y_fn_x(&mut y1_correct, x1, &mut args);
    approx_eq(y0[0], y1_correct[0], 5e-5);

    // print and check statistics
    println!("{}", stat);
    assert_eq!(stat.n_function, 80);
    assert_eq!(stat.n_jacobian, 1);
    assert_eq!(stat.n_factor, 1);
    assert_eq!(stat.n_lin_sol, 40);
    assert_eq!(stat.n_steps, 40);
    assert_eq!(stat.n_accepted, 40);
    assert_eq!(stat.n_rejected, 0);
    assert_eq!(stat.n_iterations, 2);
    assert_eq!(stat.n_iterations_max, 2);
}