1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/*!
**diffgeom** is a crate aiming to leverage the Rust type system to provide
a type-safe API for tensor calculus on arbitrary manifolds.

What is tensor calculus?
========================

Tensors are, in a way, a generalized idea similar to vectors and matrices. They are
multidimensional arrays of numbers, but not all such arrays are tensors. What makes
them tensors is how they behave in coordinate transformations. The details are a
topic for a whole academic lecture, so I won't go into them. What's important
is that tensors can be used for describing properties of curved spaces and it is
the intended use case of this crate.

Problems
========

Unfortunately, Rust currently doesn't support generics over static values, so
another representation of type-level numbers is required. In this crate one
provided by [typenum](https://github.com/paholg/typenum) is being used. This
makes it necessary to use a lot of trait bounds, which break the compiler in
a few ways, so some operations require the usage of a pretty cumbersome syntax.

Example
=======

Below you can see a code sample presenting some simple operations.

```
# extern crate diffgeom;
# extern crate generic_array;
use std::ops::Mul;
use generic_array::{GenericArray, ArrayLength};
use diffgeom::coordinates::{CoordinateSystem, Point};
use diffgeom::tensors::{Vector, Covector, Matrix, InnerProduct};
use generic_array::arr;
use generic_array::typenum::consts::{U0, U1, U2};

fn main() {
    // First, a coordinate system must be defined
    struct SomeSystem;
    impl CoordinateSystem for SomeSystem {
        type Dimension = U2;    // a two-dimensional coordinate system
    }

    // Each tensor should be anchored at a point, so let's create one
    let point = Point::<SomeSystem>::new(arr![f64; 0.0, 0.0]);

    // A vector can be defined like that:
    let vector = Vector::<SomeSystem>::new(point, arr![f64; 1.0, 2.0]);

    // There are also covectors
    let covector = Covector::<SomeSystem>::new(point, arr![f64; 2.0, 0.5]);

    // They can be multiplied, yielding a matrix
    let matrix = <Vector<SomeSystem> as Mul<Covector<SomeSystem>>>::mul(vector, covector);
    // Unfortunately this causes infinite recursion in the compiler:
    // let matrix = vector * covector;

    // They can be contracted
    let scalar = <Vector<SomeSystem> as InnerProduct<Covector<SomeSystem>, U0, U1>>
        ::inner_product(vector, covector);

    // scalars returned by tensor functions need to be dereffed to f64
    assert_eq!(*scalar, *matrix.trace::<U0, U1>());
}
```
*/
pub extern crate generic_array;
pub use generic_array::typenum;

pub mod coordinates;
pub mod macros;
pub mod metric;
pub mod tensors;

#[cfg(test)]
mod tests;