1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#![deny(missing_docs)]

//! Simulates N-body pendulums.
//!
//! This crate is designed to solve [the governing equations](https://naokihori.github.io/Pendulum/equation/main.html) describing the motion of N-body pendulums.
//! The central function is [`simulator::integrate()`], which integrates the system *for
//! one step*.
//! For instance,
//! ```rust
//! let mut p: pendulum::Pendulum = pendulum::simulator::init(nitems);
//! // call as many times as you want
//! let dt: f64 = pendulum::simulator::integrate(&mut p);
//! ```
//! Note that the time step size `dt` is *decided by the integrator* and not to be specified.

/// Stores the state of the pendulum.
pub struct Pendulum {
    /// Number of mass points.
    nitems: usize,
    /// Angles.
    poss: Vec<f64>,
    /// Angular velocities.
    vels: Vec<f64>,
    /// Time step size, which is used as a reference to decide the next value.
    dt: f64,
}

/// Getters.
impl Pendulum {
    /// Getter, number of items.
    pub fn get_nitems(&self) -> usize {
        return self.nitems;
    }
    /// Getter, positions (angles).
    pub fn get_positions(&self) -> &Vec<f64> {
        return &self.poss;
    }
    /// Getter, (angular) velocities.
    pub fn get_velocities(&self) -> &Vec<f64> {
        return &self.vels;
    }
}

/// Stores kinetic and the potential energies.
pub struct Energy {
    /// Kinetic energy
    pub t: f64,
    /// Potential energy
    pub u: f64,
}

/// Has methods to manipulate the pendulum.
pub mod simulator {
    mod init;
    mod integrate;
    /// Initialises a pendulum and return it.
    pub fn init(nitems: usize) -> crate::Pendulum {
        let p: crate::Pendulum = init::entrypoint(nitems);
        return p;
    }
    /// Integrates the pendulum in time for one time step.
    pub fn integrate(p: &mut crate::Pendulum) -> f64 {
        // time step size is determined by the solver
        let dt: f64 = integrate::entrypoint(p);
        return dt;
    }
}

/// Calculates the current statistics of the system.
pub mod logger {
    mod energy;
    /// Calculates current energies.
    pub fn check_energies(p: &crate::Pendulum) -> crate::Energy {
        return energy::check(p);
    }
}