outram_foam_basic_lib/primitives/
spherical_tensor.rs1use std::ops::{Add, Div, Mul, Neg, Sub};
30
31#[derive(Debug, Clone, Copy, PartialEq, Default)]
34pub struct SphericalTensor {
35 pub ii: f64,
36}
37
38impl SphericalTensor {
39 pub const ZERO: Self = Self { ii: 0.0 };
41 pub const IDENTITY: Self = Self { ii: 1.0 };
43
44 #[inline]
46 pub fn new(ii: f64) -> Self {
47 Self { ii }
48 }
49
50 #[inline]
52 pub fn tr(self) -> f64 {
53 3.0 * self.ii
54 }
55
56 #[inline]
58 pub fn mag_sqr(self) -> f64 {
59 3.0 * self.ii * self.ii
60 }
61
62 #[inline]
63 pub fn mag(self) -> f64 {
64 self.mag_sqr().sqrt()
65 }
66
67 #[inline]
69 pub fn diag_sqr(self) -> f64 {
70 3.0 * self.ii * self.ii
71 }
72
73 #[inline]
75 pub fn det(self) -> f64 {
76 self.ii * self.ii * self.ii
77 }
78
79 #[inline]
81 pub fn inv(self) -> Self {
82 Self { ii: 1.0 / self.ii }
83 }
84
85 #[inline]
87 pub fn double_inner(self, rhs: Self) -> f64 {
88 3.0 * self.ii * rhs.ii
89 }
90
91 #[inline]
93 pub fn lerp(a: Self, b: Self, t: f64) -> Self {
94 Self {
95 ii: (1.0 - t) * a.ii + t * b.ii,
96 }
97 }
98}
99
100impl Neg for SphericalTensor {
103 type Output = Self;
104 #[inline]
105 fn neg(self) -> Self {
106 Self { ii: -self.ii }
107 }
108}
109
110impl Add for SphericalTensor {
111 type Output = Self;
112 #[inline]
113 fn add(self, rhs: Self) -> Self {
114 Self {
115 ii: self.ii + rhs.ii,
116 }
117 }
118}
119
120impl Sub for SphericalTensor {
121 type Output = Self;
122 #[inline]
123 fn sub(self, rhs: Self) -> Self {
124 Self {
125 ii: self.ii - rhs.ii,
126 }
127 }
128}
129
130impl Mul<f64> for SphericalTensor {
131 type Output = Self;
132 #[inline]
133 fn mul(self, s: f64) -> Self {
134 Self { ii: self.ii * s }
135 }
136}
137
138impl Mul<SphericalTensor> for f64 {
139 type Output = SphericalTensor;
140 #[inline]
141 fn mul(self, st: SphericalTensor) -> SphericalTensor {
142 st * self
143 }
144}
145
146impl Div<f64> for SphericalTensor {
147 type Output = Self;
148 #[inline]
149 fn div(self, s: f64) -> Self {
150 Self { ii: self.ii / s }
151 }
152}
153
154impl Div<SphericalTensor> for f64 {
156 type Output = SphericalTensor;
157 #[inline]
158 fn div(self, st: SphericalTensor) -> SphericalTensor {
159 SphericalTensor { ii: self / st.ii }
160 }
161}
162
163#[inline]
167pub fn tr(st: SphericalTensor) -> f64 {
168 st.tr()
169}
170
171#[inline]
173pub fn det(st: SphericalTensor) -> f64 {
174 st.det()
175}
176
177#[inline]
179pub fn inv(st: SphericalTensor) -> SphericalTensor {
180 st.inv()
181}
182
183#[inline]
185pub fn mag_sqr(st: SphericalTensor) -> f64 {
186 st.mag_sqr()
187}
188
189#[inline]
191pub fn lerp(a: SphericalTensor, b: SphericalTensor, t: f64) -> SphericalTensor {
192 SphericalTensor::lerp(a, b, t)
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 #[test]
200 fn identity_properties() {
201 let i = SphericalTensor::IDENTITY;
202 assert_eq!(i.tr(), 3.0);
203 assert_eq!(i.det(), 1.0);
204 assert_eq!(i.inv().ii, 1.0);
205 assert_eq!(i.mag_sqr(), 3.0);
206 }
207
208 #[test]
209 fn arithmetic() {
210 let a = SphericalTensor::new(2.0);
211 let b = SphericalTensor::new(3.0);
212 assert_eq!((a + b).ii, 5.0);
213 assert_eq!((b - a).ii, 1.0);
214 assert_eq!((a * 3.0).ii, 6.0);
215 assert_eq!((3.0 * a).ii, 6.0);
216 assert_eq!((a / 2.0).ii, 1.0);
217 }
218
219 #[test]
220 fn double_inner() {
221 let a = SphericalTensor::new(2.0);
222 let b = SphericalTensor::new(3.0);
223 assert_eq!(a.double_inner(b), 3.0 * 2.0 * 3.0);
224 }
225}