differential_equations/
traits.rs

1//! Defines Generics for the library. Includes generics for the floating point numbers.
2
3use nalgebra::{RealField, SMatrix};
4use num_complex::Complex;
5use std::ops::{Add, AddAssign, Div, Mul, Sub};
6
7/// Real Number Trait
8///
9/// This trait specifies the acceptable types for real numbers.
10/// Currently implemented for:
11/// * `f32` - 32-bit floating point
12/// * `f64` - 64-bit floating point
13///
14/// Provides additional functionality required for ODE solvers beyond
15/// what's provided by nalgebra's RealField trait.
16///
17pub trait Real: Copy + RealField {
18    fn infinity() -> Self;
19    fn to_f64(self) -> f64;
20}
21
22impl Real for f32 {
23    fn infinity() -> Self {
24        std::f32::INFINITY
25    }
26
27    fn to_f64(self) -> f64 {
28        f64::from(self)
29    }
30}
31
32impl Real for f64 {
33    fn infinity() -> Self {
34        std::f64::INFINITY
35    }
36
37    fn to_f64(self) -> f64 {
38        self
39    }
40}
41
42/// State vector trait
43/// 
44/// Represents the state of the system being solved.
45/// 
46/// Implements for the following types:
47/// * `f32` - 32-bit floating point
48/// * `f64` - 64-bit floating point
49/// * `SMatrix` - Matrix type from nalgebra
50/// * `Complex` - Complex number type from num-complex
51/// * `Struct<T>` - Any struct with all fields of type T using #[derive(State)] from the `derive` module
52/// 
53pub trait State<T>:
54    Clone
55    + Copy
56    + Add<Output = Self>
57    + Sub<Output = Self>
58    + AddAssign
59    + Mul<T, Output = Self>
60    + Div<T, Output = Self>
61{
62    fn len(&self) -> usize;
63
64    fn get(&self, i: usize) -> T;
65
66    fn set(&mut self, i: usize, value: T);
67
68    fn zeros() -> Self;
69}
70
71impl<T: Real> State<T> for T {
72    fn len(&self) -> usize {
73        1
74    }
75
76    fn get(&self, i: usize) -> T {
77        if i == 0 {
78            *self
79        } else {
80            panic!("Index out of bounds")
81        }
82    }
83
84    fn set(&mut self, i: usize, value: T) {
85        if i == 0 {
86            *self = value;
87        } else {
88            panic!("Index out of bounds")
89        }
90    }
91
92    fn zeros() -> Self {
93        T::zero()
94    }
95}
96
97impl<T, const R: usize, const C: usize> State<T> for SMatrix<T, R, C>
98where
99    T: Real,
100{
101    fn len(&self) -> usize {
102        R * C
103    }
104
105    fn get(&self, i: usize) -> T {
106        if i < self.len() {
107            self[(i / C, i % C)]
108        } else {
109            panic!("Index out of bounds")
110        }
111    }
112
113    fn set(&mut self, i: usize, value: T) {
114        if i < self.len() {
115            self[(i / C, i % C)] = value;
116        } else {
117            panic!("Index out of bounds")
118        }
119    }
120
121    fn zeros() -> Self {
122        SMatrix::<T, R, C>::zeros()
123    }
124}
125
126impl<T> State<T> for Complex<T>
127where
128    T: Real,
129{
130    fn len(&self) -> usize {
131        2
132    }
133
134    fn get(&self, i: usize) -> T {
135        if i == 0 {
136            self.re
137        } else if i == 1 {
138            self.im
139        } else {
140            panic!("Index out of bounds")
141        }
142    }
143
144    fn set(&mut self, i: usize, value: T) {
145        if i == 0 {
146            self.re = value;
147        } else if i == 1 {
148            self.im = value;
149        } else {
150            panic!("Index out of bounds")
151        }
152    }
153
154    fn zeros() -> Self {
155        Complex::new(T::zero(), T::zero())
156    }
157}
158
159/// Callback data trait
160///
161/// This trait represents data that can be returned from functions
162/// that are used to control the solver's execution flow. The
163/// Clone and Debug traits are required for internal use but anything
164/// that implements this trait can be used as callback data.
165/// For example, this can be a string, a number, or any other type
166/// that implements the Clone and Debug traits.
167///
168pub trait CallBackData: Clone + std::fmt::Debug {}
169
170// Implement for any type that already satisfies the bounds
171impl<T: Clone + std::fmt::Debug> CallBackData for T {}