amari_calculus/fields/
multivector_field.rs1use crate::{CalculusError, CalculusResult};
4use amari_core::Multivector;
5
6#[derive(Clone)]
11pub struct MultivectorField<const P: usize, const Q: usize, const R: usize> {
12 function: fn(&[f64]) -> Multivector<P, Q, R>,
14 dim: usize,
16}
17
18impl<const P: usize, const Q: usize, const R: usize> MultivectorField<P, Q, R> {
19 pub fn new(function: fn(&[f64]) -> Multivector<P, Q, R>) -> Self {
21 Self {
22 function,
23 dim: P + Q + R,
24 }
25 }
26
27 pub fn with_dimension(function: fn(&[f64]) -> Multivector<P, Q, R>, dim: usize) -> Self {
29 Self { function, dim }
30 }
31
32 pub fn evaluate(&self, coords: &[f64]) -> Multivector<P, Q, R> {
34 (self.function)(coords)
35 }
36
37 pub fn dimension(&self) -> usize {
39 self.dim
40 }
41
42 pub fn partial_derivative(
50 &self,
51 coords: &[f64],
52 axis: usize,
53 h: f64,
54 ) -> CalculusResult<Multivector<P, Q, R>> {
55 if axis >= self.dim {
56 return Err(CalculusError::InvalidDimension {
57 expected: self.dim,
58 got: axis,
59 });
60 }
61
62 let mut coords_plus = coords.to_vec();
63 let mut coords_minus = coords.to_vec();
64
65 coords_plus[axis] += h;
66 coords_minus[axis] -= h;
67
68 let f_plus = self.evaluate(&coords_plus);
69 let f_minus = self.evaluate(&coords_minus);
70
71 let result = (f_plus - f_minus) * (1.0 / (2.0 * h));
73
74 Ok(result)
75 }
76}
77
78impl<const P: usize, const Q: usize, const R: usize> std::fmt::Debug for MultivectorField<P, Q, R> {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 f.debug_struct("MultivectorField")
81 .field("dim", &self.dim)
82 .field("signature", &format!("Cl({},{},{})", P, Q, R))
83 .finish()
84 }
85}