conspire/math/tensor/rank_3/
mod.rs

1#[cfg(test)]
2mod test;
3
4#[cfg(test)]
5use super::test::ErrorTensor;
6
7pub mod list;
8pub mod list_2d;
9pub mod list_3d;
10
11use std::{
12    array::from_fn,
13    fmt::{Display, Formatter, Result},
14    ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign},
15};
16
17use super::{
18    Tensor, TensorArray,
19    rank_0::TensorRank0,
20    rank_2::{
21        TensorRank2, get_identity_1010_parts_1, get_identity_1010_parts_2,
22        get_identity_1010_parts_3, get_levi_civita_parts,
23    },
24};
25
26/// Returns the rank-3 Levi-Civita symbol.
27pub fn levi_civita<const I: usize, const J: usize, const K: usize>() -> TensorRank3<3, I, J, K> {
28    TensorRank3::new([
29        [[0.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, -1.0, 0.0]],
30        [[0.0, 0.0, -1.0], [0.0, 0.0, 0.0], [1.0, 0.0, 0.0]],
31        [[0.0, 1.0, 0.0], [-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
32    ])
33}
34
35/// A *d*-dimensional tensor of rank 3.
36///
37/// `D` is the dimension, `I`, `J`, `K` are the configurations.
38#[derive(Clone, Debug, PartialEq)]
39pub struct TensorRank3<const D: usize, const I: usize, const J: usize, const K: usize>(
40    [TensorRank2<D, J, K>; D],
41);
42
43pub const LEVI_CIVITA: TensorRank3<3, 1, 1, 1> = TensorRank3(get_levi_civita_parts());
44
45pub const fn get_identity_1010_parts<const I: usize, const J: usize, const K: usize>()
46-> [TensorRank3<3, I, J, K>; 3] {
47    [
48        TensorRank3(get_identity_1010_parts_1()),
49        TensorRank3(get_identity_1010_parts_2()),
50        TensorRank3(get_identity_1010_parts_3()),
51    ]
52}
53
54impl<const D: usize, const I: usize, const J: usize, const K: usize> Display
55    for TensorRank3<D, I, J, K>
56{
57    fn fmt(&self, _f: &mut Formatter) -> Result {
58        Ok(())
59    }
60}
61
62#[cfg(test)]
63impl<const D: usize, const I: usize, const J: usize, const K: usize> ErrorTensor
64    for TensorRank3<D, I, J, K>
65{
66    fn error(
67        &self,
68        comparator: &Self,
69        tol_abs: &TensorRank0,
70        tol_rel: &TensorRank0,
71    ) -> Option<usize> {
72        let error_count = self
73            .iter()
74            .zip(comparator.iter())
75            .map(|(self_i, comparator_i)| {
76                self_i
77                    .iter()
78                    .zip(comparator_i.iter())
79                    .map(|(self_ij, comparator_ij)| {
80                        self_ij
81                            .iter()
82                            .zip(comparator_ij.iter())
83                            .filter(|&(&self_ijk, &comparator_ijk)| {
84                                &(self_ijk - comparator_ijk).abs() >= tol_abs
85                                    && &(self_ijk / comparator_ijk - 1.0).abs() >= tol_rel
86                            })
87                            .count()
88                    })
89                    .sum::<usize>()
90            })
91            .sum();
92        if error_count > 0 {
93            Some(error_count)
94        } else {
95            None
96        }
97    }
98    fn error_fd(&self, comparator: &Self, epsilon: &TensorRank0) -> Option<(bool, usize)> {
99        let error_count = self
100            .iter()
101            .zip(comparator.iter())
102            .map(|(self_i, comparator_i)| {
103                self_i
104                    .iter()
105                    .zip(comparator_i.iter())
106                    .map(|(self_ij, comparator_ij)| {
107                        self_ij
108                            .iter()
109                            .zip(comparator_ij.iter())
110                            .filter(|&(&self_ijk, &comparator_ijk)| {
111                                &(self_ijk / comparator_ijk - 1.0).abs() >= epsilon
112                                    && (&self_ijk.abs() >= epsilon
113                                        || &comparator_ijk.abs() >= epsilon)
114                            })
115                            .count()
116                    })
117                    .sum::<usize>()
118            })
119            .sum();
120        if error_count > 0 {
121            Some((true, error_count))
122        } else {
123            None
124        }
125    }
126}
127
128impl<const D: usize, const I: usize, const J: usize, const K: usize> Tensor
129    for TensorRank3<D, I, J, K>
130{
131    type Item = TensorRank2<D, J, K>;
132    fn iter(&self) -> impl Iterator<Item = &Self::Item> {
133        self.0.iter()
134    }
135    fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Item> {
136        self.0.iter_mut()
137    }
138}
139
140impl<const D: usize, const I: usize, const J: usize, const K: usize> IntoIterator
141    for TensorRank3<D, I, J, K>
142{
143    type Item = TensorRank2<D, J, K>;
144    type IntoIter = std::array::IntoIter<Self::Item, D>;
145    fn into_iter(self) -> Self::IntoIter {
146        self.0.into_iter()
147    }
148}
149
150impl<const D: usize, const I: usize, const J: usize, const K: usize> TensorArray
151    for TensorRank3<D, I, J, K>
152{
153    type Array = [[[TensorRank0; D]; D]; D];
154    type Item = TensorRank2<D, J, K>;
155    fn as_array(&self) -> Self::Array {
156        let mut array = [[[0.0; D]; D]; D];
157        array
158            .iter_mut()
159            .zip(self.iter())
160            .for_each(|(entry_rank_2, tensor_rank_2)| *entry_rank_2 = tensor_rank_2.as_array());
161        array
162    }
163    fn identity() -> Self {
164        panic!()
165    }
166    fn new(array: Self::Array) -> Self {
167        array.into_iter().map(Self::Item::new).collect()
168    }
169    fn zero() -> Self {
170        Self(from_fn(|_| Self::Item::zero()))
171    }
172}
173
174impl<const D: usize, const I: usize, const J: usize, const K: usize>
175    FromIterator<TensorRank2<D, J, K>> for TensorRank3<D, I, J, K>
176{
177    fn from_iter<Ii: IntoIterator<Item = TensorRank2<D, J, K>>>(into_iterator: Ii) -> Self {
178        let mut tensor_rank_3 = Self::zero();
179        tensor_rank_3
180            .iter_mut()
181            .zip(into_iterator)
182            .for_each(|(tensor_rank_3_i, value_i)| *tensor_rank_3_i = value_i);
183        tensor_rank_3
184    }
185}
186
187impl<const D: usize, const I: usize, const J: usize, const K: usize> Index<usize>
188    for TensorRank3<D, I, J, K>
189{
190    type Output = TensorRank2<D, J, K>;
191    fn index(&self, index: usize) -> &Self::Output {
192        &self.0[index]
193    }
194}
195
196impl<const D: usize, const I: usize, const J: usize, const K: usize> IndexMut<usize>
197    for TensorRank3<D, I, J, K>
198{
199    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
200        &mut self.0[index]
201    }
202}
203
204impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<TensorRank0>
205    for TensorRank3<D, I, J, K>
206{
207    type Output = Self;
208    fn div(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
209        self /= &tensor_rank_0;
210        self
211    }
212}
213
214impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<TensorRank0>
215    for &TensorRank3<D, I, J, K>
216{
217    type Output = TensorRank3<D, I, J, K>;
218    fn div(self, tensor_rank_0: TensorRank0) -> Self::Output {
219        self.iter().map(|self_i| self_i / tensor_rank_0).collect()
220    }
221}
222
223impl<const D: usize, const I: usize, const J: usize, const K: usize> Div<&TensorRank0>
224    for TensorRank3<D, I, J, K>
225{
226    type Output = Self;
227    fn div(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
228        self /= tensor_rank_0;
229        self
230    }
231}
232
233impl<const D: usize, const I: usize, const J: usize, const K: usize> DivAssign<TensorRank0>
234    for TensorRank3<D, I, J, K>
235{
236    fn div_assign(&mut self, tensor_rank_0: TensorRank0) {
237        self.iter_mut().for_each(|self_i| *self_i /= &tensor_rank_0);
238    }
239}
240
241impl<const D: usize, const I: usize, const J: usize, const K: usize> DivAssign<&TensorRank0>
242    for TensorRank3<D, I, J, K>
243{
244    fn div_assign(&mut self, tensor_rank_0: &TensorRank0) {
245        self.iter_mut().for_each(|self_i| *self_i /= tensor_rank_0);
246    }
247}
248
249impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank0>
250    for TensorRank3<D, I, J, K>
251{
252    type Output = Self;
253    fn mul(mut self, tensor_rank_0: TensorRank0) -> Self::Output {
254        self *= &tensor_rank_0;
255        self
256    }
257}
258
259impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank0>
260    for TensorRank3<D, I, J, K>
261{
262    type Output = Self;
263    fn mul(mut self, tensor_rank_0: &TensorRank0) -> Self::Output {
264        self *= tensor_rank_0;
265        self
266    }
267}
268
269impl<const D: usize, const I: usize, const J: usize, const K: usize> MulAssign<TensorRank0>
270    for TensorRank3<D, I, J, K>
271{
272    fn mul_assign(&mut self, tensor_rank_0: TensorRank0) {
273        self.iter_mut().for_each(|self_i| *self_i *= &tensor_rank_0);
274    }
275}
276
277impl<const D: usize, const I: usize, const J: usize, const K: usize> MulAssign<&TensorRank0>
278    for TensorRank3<D, I, J, K>
279{
280    fn mul_assign(&mut self, tensor_rank_0: &TensorRank0) {
281        self.iter_mut().for_each(|self_i| *self_i *= tensor_rank_0);
282    }
283}
284
285impl<const D: usize, const I: usize, const J: usize, const K: usize> Add
286    for TensorRank3<D, I, J, K>
287{
288    type Output = Self;
289    fn add(mut self, tensor_rank_3: Self) -> Self::Output {
290        self += tensor_rank_3;
291        self
292    }
293}
294
295impl<const D: usize, const I: usize, const J: usize, const K: usize> Add<&Self>
296    for TensorRank3<D, I, J, K>
297{
298    type Output = Self;
299    fn add(mut self, tensor_rank_3: &Self) -> Self::Output {
300        self += tensor_rank_3;
301        self
302    }
303}
304
305impl<const D: usize, const I: usize, const J: usize, const K: usize> Add<TensorRank3<D, I, J, K>>
306    for &TensorRank3<D, I, J, K>
307{
308    type Output = TensorRank3<D, I, J, K>;
309    fn add(self, mut tensor_rank_3: TensorRank3<D, I, J, K>) -> Self::Output {
310        tensor_rank_3 += self;
311        tensor_rank_3
312    }
313}
314
315impl<const D: usize, const I: usize, const J: usize, const K: usize> AddAssign
316    for TensorRank3<D, I, J, K>
317{
318    fn add_assign(&mut self, tensor_rank_3: Self) {
319        self.iter_mut()
320            .zip(tensor_rank_3.iter())
321            .for_each(|(self_i, tensor_rank_3_i)| *self_i += tensor_rank_3_i);
322    }
323}
324
325impl<const D: usize, const I: usize, const J: usize, const K: usize> AddAssign<&Self>
326    for TensorRank3<D, I, J, K>
327{
328    fn add_assign(&mut self, tensor_rank_3: &Self) {
329        self.iter_mut()
330            .zip(tensor_rank_3.iter())
331            .for_each(|(self_i, tensor_rank_3_i)| *self_i += tensor_rank_3_i);
332    }
333}
334
335impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub
336    for TensorRank3<D, I, J, K>
337{
338    type Output = Self;
339    fn sub(mut self, tensor_rank_3: Self) -> Self::Output {
340        self -= tensor_rank_3;
341        self
342    }
343}
344
345impl<const D: usize, const I: usize, const J: usize, const K: usize> Sub<&Self>
346    for TensorRank3<D, I, J, K>
347{
348    type Output = Self;
349    fn sub(mut self, tensor_rank_3: &Self) -> Self::Output {
350        self -= tensor_rank_3;
351        self
352    }
353}
354
355impl<const D: usize, const I: usize, const J: usize, const K: usize> SubAssign
356    for TensorRank3<D, I, J, K>
357{
358    fn sub_assign(&mut self, tensor_rank_3: Self) {
359        self.iter_mut()
360            .zip(tensor_rank_3.iter())
361            .for_each(|(self_i, tensor_rank_3_i)| *self_i -= tensor_rank_3_i);
362    }
363}
364
365impl<const D: usize, const I: usize, const J: usize, const K: usize> SubAssign<&Self>
366    for TensorRank3<D, I, J, K>
367{
368    fn sub_assign(&mut self, tensor_rank_3: &Self) {
369        self.iter_mut()
370            .zip(tensor_rank_3.iter())
371            .for_each(|(self_i, tensor_rank_3_i)| *self_i -= tensor_rank_3_i);
372    }
373}