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