rustycoils 0.1.1

Fast method to compute off-axis magnetic fields for cylindrically symmetric systems of solenoids and current loops
Documentation
///
/// Test the ideal loop case against the analytic formula for the
/// ideal current loop.
///
#[cfg(test)]
extern crate rgsl;
use rustycoils;
const MU0: f64 = 1.25663706212 * 1e-6;
const PI: f64 = std::f64::consts::PI;
fn ellip_k(k: f64) -> f64 {
    rgsl::elliptic::legendre::complete::ellint_Kcomp(k, rgsl::Mode::PrecDouble)
}
fn ellip_e(k: f64) -> f64 {
    rgsl::elliptic::legendre::complete::ellint_Ecomp(k, rgsl::Mode::PrecDouble)
}
fn err_tol(x: f64, y: f64, tol: &f64) -> bool {
    if (x - y).abs() < *tol {
        true
    } else {
        false
    }
}
fn float_compare(a: f64, b: f64, epsilon: f64) -> bool {
    if a == b {
        return true;
    } else if ((a - b) / b).abs() < epsilon {
        return true;
    }
    false
}
#[test]
fn check_external_ellipticals_correct() {
    assert!(err_tol(ellip_k(0.1), 1.5747455615174, &1e-13));
    assert!(err_tol(ellip_k(0.2), 1.5868678474542, &1e-13));
    assert!(err_tol(ellip_k(-0.8), 1.9953027776647, &1e-13));
    assert!(err_tol(ellip_e(0.1), 1.5668619420217, &1e-13));
    assert!(err_tol(ellip_e(0.2), 1.5549685462425, &1e-13));
    assert!(err_tol(ellip_e(-0.8), 1.2763499431699, &1e-13));
}

fn get_x(z: f64, z0: f64, radius: f64) -> f64 {
    (z - z0) / radius
}
fn get_b0(current: f64, radius: f64) -> f64 {
    (MU0 * current) / (2.0 * radius)
}

fn get_nu(r: f64, radius: f64) -> f64 {
    r / radius
}
fn get_k_squared(nu: f64, x: f64) -> f64 {
    (2.0 * nu) / (1.0 + nu.powi(2) + x.powi(2))
}
fn get_t(k_squared: f64) -> f64 {
    ((2.0 * k_squared) / (1.0 + k_squared)).sqrt()
}

fn get_axial_field(r: f64, z: f64, z0: f64, radius: f64, current: f64) -> f64 {
    let x = get_x(z, z0, radius);
    let b0 = get_b0(current, radius);
    if r == 0.0 {
        return b0 * (1.0 / (1.0 + x.powi(2)).powf(1.5));
    } else {
        let nu = get_nu(r, radius);
        let k_squared = get_k_squared(nu, x);
        let t = get_t(k_squared);
        let overall_term = (b0 * t) / (2.0 * PI * nu.sqrt());
        let second_factor = (k_squared - nu) / (nu * (1.0 - k_squared));
        let first_ellip = ellip_k(t);
        let second_ellip = ellip_e(t);
        overall_term * (first_ellip + second_factor * second_ellip)
    }
}
fn get_radial_field(r: f64, z: f64, z0: f64, radius: f64, current: f64) -> f64 {
    let x = get_x(z, z0, radius);
    let b0 = get_b0(current, radius);
    if r == 0.0 {
        return 0.0;
    } else {
        let nu = get_nu(r, radius);
        let k_squared = get_k_squared(nu, x);
        let t = get_t(k_squared);
        let overall_term = (b0 * t * x) / (2.0 * PI * nu * nu.sqrt());
        let second_factor = 1.0 / (1.0 - k_squared);
        let first_ellip = ellip_k(t);
        let second_ellip = ellip_e(t);
        overall_term * (-first_ellip + second_factor * second_ellip)
    }
}

#[test]
fn compare_unit_loop_on_axis_center() {
    let mut myloop = rustycoils::AxialSystem::default();
    let radius = 1.0;
    let current = 1.0;
    let x0 = 0.0;
    let z = 1.0;
    let r = 0.0;
    let _res = myloop.add_loop("loop1".to_string(), radius, x0, current);
    let computed_field = myloop.get_field_axial(&[z, r], &1e-14);
    let ana_axial_field = get_axial_field(r, z, x0, radius, current);
    let ana_radial_field = get_radial_field(r, z, x0, radius, current);
    assert_eq!(computed_field[0], ana_axial_field);
    assert!(float_compare(computed_field[0], ana_axial_field, 0.001));
    assert!(float_compare(computed_field[1], ana_radial_field, 0.001));
}
#[test]
fn compare_unit_loop_off_axis_center() {
    let mut myloop = rustycoils::AxialSystem::default();
    let radius = 1.0;
    let current = 1.0;
    let x0 = 0.0;
    let z = 1.0;
    let r = 0.1;
    let _res = myloop.add_loop("loop1".to_string(), radius, x0, current);
    let computed_field = myloop.get_field_axial(&[z, r], &1e-14);
    let ana_axial_field = get_axial_field(r, z, x0, radius, current);
    let ana_radial_field = get_radial_field(r, z, x0, radius, current);
    assert!(float_compare(computed_field[0], ana_axial_field, 0.001));
    assert!(float_compare(computed_field[1], ana_radial_field, 0.001));
}
#[test]
fn compare_unit_loop_off_axis_center_arb_numbers() {
    let mut myloop = rustycoils::AxialSystem::default();
    let radius = 1.9;
    let current = 3.0;
    let x0 = 0.1;
    let z = 1.3;
    let r = 0.4;
    let _res = myloop.add_loop("loop1".to_string(), radius, x0, current);
    let computed_field = myloop.get_field_axial(&[z, r], &1e-14);
    let ana_axial_field = get_axial_field(r, z, x0, radius, current);
    let ana_radial_field = get_radial_field(r, z, x0, radius, current);
    assert!(float_compare(computed_field[0], ana_axial_field, 0.001));
    assert!(float_compare(computed_field[1], ana_radial_field, 0.001));
}
#[test]
fn compare_unit_loop_off_axis_center_xyz() {
    let mut myloop = rustycoils::AxialSystem::default();
    let radius = 1.9;
    let current = 3.0;
    let x0 = 0.1;
    let z = 1.3;
    let r = 0.4;
    let pos = [z, r, 0.0];
    let _res = myloop.add_loop("loop1".to_string(), radius, x0, current);
    let computed_field = myloop.get_field(pos, &1e-14);
    let ana_axial_field = get_axial_field(r, z, x0, radius, current);
    let ana_radial_field = get_radial_field(r, z, x0, radius, current);
    assert!(float_compare(computed_field[0], ana_axial_field, 0.001));
    assert!(float_compare(computed_field[1], ana_radial_field, 0.001));
}
#[test]
fn compare_unit_loop_off_axis_center_xyz_rotate() {
    let mut myloop = rustycoils::AxialSystem::default();
    let _res = myloop.transform_y();
    let radius = 1.9;
    let current = 3.0;
    let x0 = 0.1;
    let z = 1.3;
    let r = 0.4;
    let pos = [r, z, 0.0];
    let _res = myloop.add_loop("loop1".to_string(), radius, x0, current);
    let computed_field = myloop.get_field(pos, &1e-14);
    let ana_axial_field = get_axial_field(r, z, x0, radius, current);
    let ana_radial_field = get_radial_field(r, z, x0, radius, current);
    assert!(float_compare(computed_field[1], ana_axial_field, 0.001));
    assert!(float_compare(computed_field[0], ana_radial_field, 0.001));
}
//place the radial in both x and y.
#[test]
fn compare_unit_loop_off_axis_center_r_in_both() {
    let mut myloop = rustycoils::AxialSystem::default();
    let _res = myloop.transform_z();
    let radius = 1.9;
    let current = 3.0;
    let x0 = 0.1;
    let z = 1.3;
    let r = 0.4;
    let x = (r) / f64::sqrt(2.0);
    let y = x;
    let pos = [x, y, z];
    let _res = myloop.add_loop("loop1".to_string(), radius, x0, current);
    let computed_field = myloop.get_field(pos, &1e-14);
    let ana_axial_field = get_axial_field(r, z, x0, radius, current);
    let ana_radial_field = get_radial_field(r, z, x0, radius, current);
    let computed_radial =
        (f64::powi(computed_field[0], 2) + f64::powi(computed_field[1], 2)).sqrt();
    assert!(float_compare(computed_field[2], ana_axial_field, 0.001));
    assert!(float_compare(computed_radial, ana_radial_field, 0.001));
}