amari_calculus/fields/
multivector_field.rs

1//! General multivector field implementation
2
3use crate::{CalculusError, CalculusResult};
4use amari_core::Multivector;
5
6/// A general multivector field F: ℝⁿ → Cl(p,q,r)
7///
8/// Represents a function that maps points in n-dimensional space to general multivectors
9/// (not necessarily grade-1).
10#[derive(Clone)]
11pub struct MultivectorField<const P: usize, const Q: usize, const R: usize> {
12    /// The function defining the field
13    function: fn(&[f64]) -> Multivector<P, Q, R>,
14    /// Domain dimension
15    dim: usize,
16}
17
18impl<const P: usize, const Q: usize, const R: usize> MultivectorField<P, Q, R> {
19    /// Create a new multivector field from a function
20    pub fn new(function: fn(&[f64]) -> Multivector<P, Q, R>) -> Self {
21        Self {
22            function,
23            dim: P + Q + R,
24        }
25    }
26
27    /// Create a multivector field with explicit dimension
28    pub fn with_dimension(function: fn(&[f64]) -> Multivector<P, Q, R>, dim: usize) -> Self {
29        Self { function, dim }
30    }
31
32    /// Evaluate the multivector field at a point
33    pub fn evaluate(&self, coords: &[f64]) -> Multivector<P, Q, R> {
34        (self.function)(coords)
35    }
36
37    /// Get the domain dimension
38    pub fn dimension(&self) -> usize {
39        self.dim
40    }
41
42    /// Compute numerical derivative of multivector field component along coordinate axis
43    ///
44    /// # Arguments
45    ///
46    /// * `coords` - Point at which to compute derivative
47    /// * `axis` - Coordinate axis index
48    /// * `h` - Step size (default: 1e-5)
49    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        // Compute (f_plus - f_minus) / (2h)
72        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}