pub trait LorentzianN<N, R, C>
where N: Scalar, R: DimName, C: DimName,
{
Show 27 methods // Required methods fn metric() -> Self where ShapeConstraint: SameDimension<R, C>; fn dual(&self) -> Self; fn r_dual(&self) -> Self; fn c_dual(&self) -> Self; fn dual_mut(&mut self); fn r_dual_mut(&mut self); fn c_dual_mut(&mut self); fn contr<R2, C2, SB>( &self, rhs: &Matrix<N, R2, C2, SB> ) -> OMatrix<N, R, C2> where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: AreMultipliable<R, C, R2, C2>, DefaultAllocator: Allocator<N, R, C2>; fn tr_contr<R2, C2, SB>( &self, rhs: &Matrix<N, R2, C2, SB> ) -> OMatrix<N, C, C2> where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: SameNumberOfRows<R, R2>, DefaultAllocator: Allocator<N, C, C2>; fn scalar<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> N where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: DimEq<R, R2> + DimEq<C, C2>; fn tr_scalar<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> N where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: DimEq<C, R2> + DimEq<R, C2>; fn timelike_norm(&self) -> N; fn spacelike_norm(&self) -> N; fn interval(&self, rhs: &Self) -> (N, LightCone) where N: AbsDiffEq, ShapeConstraint: DimEq<U1, C>; fn interval_fn<P, L>( &self, rhs: &Self, is_present: P, is_lightlike: L ) -> (N, LightCone) where ShapeConstraint: DimEq<U1, C>, P: Fn(N) -> bool, L: Fn(N) -> bool; fn new_boost<D>(frame: &FrameN<N, D>) -> Self where D: DimNameSub<U1>, ShapeConstraint: AreMultipliable<R, C, R, C> + DimEq<R, D>, DefaultAllocator: Allocator<N, DimNameDiff<D, U1>>; fn boost<D>(&self, frame: &FrameN<N, D>) -> Self where R: DimNameSub<U1>, D: DimNameSub<U1>, ShapeConstraint: SameNumberOfRows<R, D> + SameNumberOfColumns<C, U1> + DimEq<<R as DimNameSub<U1>>::Output, <D as DimNameSub<U1>>::Output> + SameNumberOfRows<<R as DimNameSub<U1>>::Output, <D as DimNameSub<U1>>::Output>, DefaultAllocator: Allocator<N, DimNameDiff<D, U1>>; fn boost_mut<D>(&mut self, frame: &FrameN<N, D>) where R: DimNameSub<U1>, D: DimNameSub<U1>, ShapeConstraint: SameNumberOfRows<R, D> + SameNumberOfColumns<C, U1> + DimEq<<R as DimNameSub<U1>>::Output, <D as DimNameSub<U1>>::Output> + SameNumberOfRows<<R as DimNameSub<U1>>::Output, <D as DimNameSub<U1>>::Output>, DefaultAllocator: Allocator<N, DimNameDiff<D, U1>>; fn new_velocity<D>(frame: &FrameN<N, D>) -> OVector<N, D> where D: DimNameSub<U1>, ShapeConstraint: SameNumberOfRows<R, D> + SameNumberOfColumns<C, U1>, DefaultAllocator: Allocator<N, DimNameDiff<D, U1>> + Allocator<N, D>; fn frame(&self) -> FrameN<N, R> where R: DimNameSub<U1>, ShapeConstraint: SameNumberOfColumns<C, U1>, DefaultAllocator: Allocator<N, DimNameDiff<R, U1>>; fn from_split<D>( temporal: &N, spatial: &OVector<N, DimNameDiff<D, U1>> ) -> OVector<N, D> where D: DimNameSub<U1>, ShapeConstraint: SameNumberOfRows<R, D> + SameNumberOfColumns<C, U1>, DefaultAllocator: Allocator<N, DimNameDiff<D, U1>> + Allocator<N, D>, <DefaultAllocator as Allocator<N, D, U1>>::Buffer: StorageMut<N, D, U1, RStride = U1, CStride = D>; fn split(&self) -> (&N, MatrixView<'_, N, DimNameDiff<R, U1>, C, U1, R>) where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: Storage<N, R, C, RStride = U1, CStride = R>; fn split_mut( &mut self ) -> (&mut N, MatrixViewMut<'_, N, DimNameDiff<R, U1>, C>) where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: Storage<N, R, C, RStride = U1, CStride = R>; fn temporal(&self) -> &N where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>; fn temporal_mut(&mut self) -> &mut N where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>; fn spatial(&self) -> MatrixView<'_, N, DimNameDiff<R, U1>, C, U1, R> where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: Storage<N, R, C, RStride = U1, CStride = R>; fn spatial_mut( &mut self ) -> MatrixViewMut<'_, N, DimNameDiff<R, U1>, C, U1, R> where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: StorageMut<N, R, C, RStride = U1, CStride = R>;
}
Expand description

Extension for $n$-dimensional Lorentzian space $\R^{-,+} = \R^{1,n-1}$ with metric signature in spacelike sign convention.

In four dimensions also known as Minkowski space $\R^{-,+} = \R^{1,3}$.

A statically sized column-major matrix whose R rows and C columns coincide with degree-1/degree-2 tensor indices.

Required Methods§

source

fn metric() -> Self

Lorentzian metric tensor $\eta_{\mu \nu}$:

$$ \eta_{\mu \nu} = \begin{pmatrix} -1 & 0 & \dots & 0 \\ 0 & 1 & \ddots & \vdots \\ \vdots & \ddots & \ddots & 0 \\ 0 & \dots & 0 & 1 \end{pmatrix} $$

Avoid matrix multiplication by preferring:

The spacelike sign convention $\R^{-,+} = \R^{1,n-1}$ requires less negations than its timelike alternative $\R^{+,-} = \R^{1,n-1}$. In four dimensions or Minkowski space $\R^{-,+} = \R^{1,3}$ it requires:

  • $n - 2 = 2$ less for degree-1 tensors, and
  • $n (n - 2) = 8$ less for one index of degree-2 tensors, but
  • $0$ less for two indices of degree-2 tensors.

Choosing the component order of $\R^{-,+} = \R^{1,n-1}$ over $\R^{+,-} = \R^{n-1,1}$ identifies the time component of $x^\mu$ as $x^0$ in compliance with the convention of identifying spatial components $x^i$ with Latin alphabet indices starting from $i=1$.

use approx::assert_ulps_eq;
use nalgebra::{Matrix4, Vector4};
use nalgebra_spacetime::LorentzianN;

let eta = Matrix4::<f64>::metric();
let sc = Vector4::new(-1.0, 1.0, 1.0, 1.0);
assert_ulps_eq!(eta, Matrix4::from_diagonal(&sc));

let x = Vector4::<f64>::new_random();
assert_ulps_eq!(x.dual(), eta * x);

let f = Matrix4::<f64>::new_random();
assert_ulps_eq!(f.dual(), eta * f * eta);
assert_ulps_eq!(f.dual(), f.r_dual().c_dual());
assert_ulps_eq!(f.dual(), f.c_dual().r_dual());
assert_ulps_eq!(f.r_dual(), eta * f);
assert_ulps_eq!(f.c_dual(), f * eta);
source

fn dual(&self) -> Self

Raises/Lowers all of its degree-1/degree-2 tensor indices.

Negates the appropriate components avoiding matrix multiplication.

source

fn r_dual(&self) -> Self

Raises/Lowers its degree-1/degree-2 row tensor index.

Prefer Self::dual over self.r_dual().c_dual() to half negations.

source

fn c_dual(&self) -> Self

Raises/Lowers its degree-1/degree-2 column tensor index.

Prefer Self::dual over self.r_dual().c_dual() to half negations.

source

fn dual_mut(&mut self)

Raises/Lowers all of its degree-1/degree-2 tensor indices in-place.

Negates the appropriate components avoiding matrix multiplication.

source

fn r_dual_mut(&mut self)

Raises/Lowers its degree-1/degree-2 row tensor index in-place.

Prefer Self::dual over self.r_dual_mut().c_dual_mut() to half negations.

source

fn c_dual_mut(&mut self)

Raises/Lowers its degree-1/degree-2 column tensor index in-place.

Prefer Self::dual over self.r_dual_mut().c_dual_mut() to half negations.

source

fn contr<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> OMatrix<N, R, C2>
where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: AreMultipliable<R, C, R2, C2>, DefaultAllocator: Allocator<N, R, C2>,

Lorentzian matrix multiplication of degree-1/degree-2 tensors.

Equals self.c_dual() * rhs, the metric contraction of its column index with rhs’s row index.

source

fn tr_contr<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> OMatrix<N, C, C2>
where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: SameNumberOfRows<R, R2>, DefaultAllocator: Allocator<N, C, C2>,

Same as Self::contr but with transposed tensor indices.

Equals self.r_dual().tr_mul(rhs), the metric contraction of its transposed row index with rhs’s row index.

source

fn scalar<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> N
where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: DimEq<R, R2> + DimEq<C, C2>,

Lorentzian inner product of degree-1/degree-2 tensors.

Equals self.dual().dot(rhs), the metric contraction of:

  • one index for degree-1 tensors, and
  • two indices for degree-2 tensors.

Also known as:

  • Minkowski inner product,
  • relativistic dot product,
  • Lorentz scalar, invariant under Lorentz transformations, or
  • spacetime interval between two events, see Self::interval.
source

fn tr_scalar<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> N
where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: DimEq<C, R2> + DimEq<R, C2>,

Same as Self::scalar but with transposed tensor indices.

Equals self.dual().tr_dot(rhs).

source

fn timelike_norm(&self) -> N

Lorentzian norm of timelike degree-1/degree-2 tensors.

Equals self.scalar(self).neg().sqrt().

If spacelike, returns NaN or panics if N doesn’t support it.

source

fn spacelike_norm(&self) -> N

Lorentzian norm of spacelike degree-1/degree-2 tensors.

Equals self.scalar(self).sqrt().

If timelike, returns NaN or panics if N doesn’t support it.

source

fn interval(&self, rhs: &Self) -> (N, LightCone)

Spacetime interval between two events and region of self’s light cone.

Same as Self::interval_fn but with AbsDiffEq::default_epsilon as in:

  • is_present = |time| abs_diff_eq!(time, N::zero()), and
  • is_lightlike = |interval| abs_diff_eq!(interval, N::zero()).
source

fn interval_fn<P, L>( &self, rhs: &Self, is_present: P, is_lightlike: L ) -> (N, LightCone)
where ShapeConstraint: DimEq<U1, C>, P: Fn(N) -> bool, L: Fn(N) -> bool,

Spacetime interval between two events and region of self’s light cone.

Equals (rhs - self).scalar(&(rhs - self)) where self is subtracted from rhs to depict rhs in self’s light cone.

Requires you to approximate when N equals N::zero() via:

  • is_present for the time component of rhs - self, and
  • is_lightlike for the interval.

Their signs are only evaluated in the false branches of is_present and is_lightlike.

See Self::interval for using defaults and approx for further details.

source

fn new_boost<D>(frame: &FrameN<N, D>) -> Self

$ \gdef \uk {\hat u \cdot \vec K} \gdef \Lmu {\Lambda^{\mu’}_{\phantom {\mu’} \mu}} \gdef \Lnu {(\Lambda^T)_\nu^{\phantom \nu \nu’}} $ Lorentz transformation $\Lmu(\hat u, \zeta)$ boosting degree-1/degree-2 tensors to inertial frame of reference.

$$ \Lmu(\hat u, \zeta) = I - \sinh \zeta (\uk) + (\cosh \zeta - 1) (\uk)^2 $$

Where $\uk$ is the generator of the boost along $\hat{u}$ with its spatial componentsi $(u^1, \dots, u^{n-1})$:

$$ \uk = \begin{pmatrix} 0 & u^1 & \dots & u^{n-1} \\ u^1 & 0 & \dots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ u^{n-1} & 0 & \dots & 0 \end{pmatrix} $$

Boosts degree-1 tensors by multiplying it from the left:

$$ x^{\mu’} = \Lmu x^\mu $$

Boosts degree-2 tensors by multiplying it from the left and its transpose (symmetric for pure boosts) from the right:

$$ F^{\mu’ \nu’} = \Lmu F^{\mu \nu} \Lnu $$

use approx::assert_ulps_eq;
use nalgebra::{Matrix4, Vector3, Vector4};
use nalgebra_spacetime::{Frame4, LorentzianN};

let event = Vector4::new_random();
let frame = Frame4::from_beta(Vector3::new(0.3, -0.4, 0.6));
let boost = Matrix4::new_boost(&frame);
assert_ulps_eq!(boost * event, event.boost(&frame), epsilon = 1e-14);
source

fn boost<D>(&self, frame: &FrameN<N, D>) -> Self

Boosts this degree-1 tensor $x^\mu$ to inertial frame of reference along $\hat u$ with $\zeta$.

use approx::assert_ulps_eq;
use nalgebra::{Vector3, Vector4};
use nalgebra_spacetime::{Frame4, LorentzianN};

let muon_lifetime_at_rest = Vector4::new(2.2e-6, 0.0, 0.0, 0.0);
let muon_frame = Frame4::from_axis_beta(Vector3::z_axis(), 0.9952);
let muon_lifetime = muon_lifetime_at_rest.boost(&muon_frame);
let time_dilation_factor = muon_lifetime[0] / muon_lifetime_at_rest[0];
assert_ulps_eq!(time_dilation_factor, 10.218, epsilon = 1e-3);

See boost_mut() for further details.

source

fn boost_mut<D>(&mut self, frame: &FrameN<N, D>)

$ \gdef \xu {(\vec x \cdot \hat u)} $ Boosts this degree-1 tensor $x^\mu$ to inertial frame of reference along $\hat u$ with $\zeta$ in-place.

$$ \begin{pmatrix} x^0 \\ \vec x \end{pmatrix}’ = \begin{pmatrix} x^0 \cosh \zeta - \xu \sinh \zeta \\ \vec x + (\xu (\cosh \zeta - 1) - x^0 \sinh \zeta) \hat u \end{pmatrix} $$

use approx::assert_ulps_eq;
use nalgebra::Vector4;
use nalgebra_spacetime::LorentzianN;

// Arbitrary timelike four-momentum.
let mut momentum = Vector4::new(24.3, 5.22, 16.8, 9.35);

// Rest mass.
let mass = momentum.timelike_norm();
// Four-momentum in center-of-momentum frame.
let mass_at_rest = Vector4::new(mass, 0.0, 0.0, 0.0);

// Rest mass is ratio of four-momentum to four-velocity.
let velocity = momentum / mass;
// Four-momentum boosted to center-of-momentum frame.
momentum.boost_mut(&velocity.frame());

// Verify boosting four-momentum to center-of-momentum frame.
assert_ulps_eq!(momentum, mass_at_rest, epsilon = 1e-14);
source

fn new_velocity<D>(frame: &FrameN<N, D>) -> OVector<N, D>

Velocity $u^\mu$ of inertial frame of reference.

source

fn frame(&self) -> FrameN<N, R>

Inertial frame of reference of this velocity $u^\mu$.

source

fn from_split<D>( temporal: &N, spatial: &OVector<N, DimNameDiff<D, U1>> ) -> OVector<N, D>
where D: DimNameSub<U1>, ShapeConstraint: SameNumberOfRows<R, D> + SameNumberOfColumns<C, U1>, DefaultAllocator: Allocator<N, DimNameDiff<D, U1>> + Allocator<N, D>, <DefaultAllocator as Allocator<N, D, U1>>::Buffer: StorageMut<N, D, U1, RStride = U1, CStride = D>,

From temporal and spatial spacetime split.

source

fn split(&self) -> (&N, MatrixView<'_, N, DimNameDiff<R, U1>, C, U1, R>)
where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: Storage<N, R, C, RStride = U1, CStride = R>,

Spacetime split into Self::temporal and Self::spatial.

source

fn split_mut(&mut self) -> (&mut N, MatrixViewMut<'_, N, DimNameDiff<R, U1>, C>)
where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: Storage<N, R, C, RStride = U1, CStride = R>,

Mutable spacetime split into Self::temporal_mut and Self::spatial_mut.

use approx::assert_ulps_eq;
use nalgebra::Vector4;
use nalgebra_spacetime::LorentzianN;

let mut spacetime = Vector4::new(1.0, 2.0, 3.0, 4.0);
let (temporal, mut spatial) = spacetime.split_mut();
*temporal += 1.0;
spatial[0] += 2.0;
spatial[1] += 3.0;
spatial[2] += 4.0;
assert_ulps_eq!(spacetime, Vector4::new(2.0, 4.0, 6.0, 8.0));
source

fn temporal(&self) -> &N

Temporal component.

source

fn temporal_mut(&mut self) -> &mut N

Mutable temporal component.

source

fn spatial(&self) -> MatrixView<'_, N, DimNameDiff<R, U1>, C, U1, R>
where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: Storage<N, R, C, RStride = U1, CStride = R>,

Spatial components.

source

fn spatial_mut(&mut self) -> MatrixViewMut<'_, N, DimNameDiff<R, U1>, C, U1, R>
where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: StorageMut<N, R, C, RStride = U1, CStride = R>,

Mutable spatial components.

Object Safety§

This trait is not object safe.

Implementations on Foreign Types§

source§

impl<N, R, C> LorentzianN<N, R, C> for OMatrix<N, R, C>

source§

fn metric() -> Self

source§

fn dual(&self) -> Self

source§

fn r_dual(&self) -> Self

source§

fn c_dual(&self) -> Self

source§

fn dual_mut(&mut self)

source§

fn r_dual_mut(&mut self)

source§

fn c_dual_mut(&mut self)

source§

fn contr<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> OMatrix<N, R, C2>
where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: AreMultipliable<R, C, R2, C2>, DefaultAllocator: Allocator<N, R, C2>,

source§

fn tr_contr<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> OMatrix<N, C, C2>
where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: SameNumberOfRows<R, R2>, DefaultAllocator: Allocator<N, C, C2>,

source§

fn scalar<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> N
where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: DimEq<R, R2> + DimEq<C, C2>,

source§

fn tr_scalar<R2, C2, SB>(&self, rhs: &Matrix<N, R2, C2, SB>) -> N
where R2: Dim, C2: Dim, SB: Storage<N, R2, C2>, ShapeConstraint: DimEq<C, R2> + DimEq<R, C2>,

source§

fn timelike_norm(&self) -> N

source§

fn spacelike_norm(&self) -> N

source§

fn interval(&self, rhs: &Self) -> (N, LightCone)

source§

fn interval_fn<P, L>( &self, rhs: &Self, is_present: P, is_lightlike: L ) -> (N, LightCone)
where ShapeConstraint: DimEq<U1, C>, P: Fn(N) -> bool, L: Fn(N) -> bool,

source§

fn new_boost<D>(frame: &FrameN<N, D>) -> Self

source§

fn boost<D>(&self, frame: &FrameN<N, D>) -> Self

source§

fn boost_mut<D>(&mut self, frame: &FrameN<N, D>)

source§

fn new_velocity<D>(frame: &FrameN<N, D>) -> OVector<N, D>

source§

fn frame(&self) -> FrameN<N, R>

source§

fn from_split<D>( temporal: &N, spatial: &OVector<N, DimNameDiff<D, U1>> ) -> OVector<N, D>
where D: DimNameSub<U1>, ShapeConstraint: SameNumberOfRows<R, D> + SameNumberOfColumns<C, U1>, DefaultAllocator: Allocator<N, DimNameDiff<D, U1>> + Allocator<N, D>, <DefaultAllocator as Allocator<N, D, U1>>::Buffer: StorageMut<N, D, U1, RStride = U1, CStride = D>,

source§

fn split(&self) -> (&N, MatrixView<'_, N, DimNameDiff<R, U1>, C, U1, R>)
where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: Storage<N, R, C, RStride = U1, CStride = R>,

source§

fn split_mut(&mut self) -> (&mut N, MatrixViewMut<'_, N, DimNameDiff<R, U1>, C>)
where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, DefaultAllocator: Allocator<N, R, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: Storage<N, R, C, RStride = U1, CStride = R>,

source§

fn temporal(&self) -> &N

source§

fn temporal_mut(&mut self) -> &mut N

source§

fn spatial(&self) -> MatrixView<'_, N, DimNameDiff<R, U1>, C, U1, R>
where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: RawStorage<N, R, C, RStride = U1, CStride = R>,

source§

fn spatial_mut(&mut self) -> MatrixViewMut<'_, N, DimNameDiff<R, U1>, C, U1, R>
where R: DimNameSub<U1>, ShapeConstraint: DimEq<U1, C>, <DefaultAllocator as Allocator<N, R, C>>::Buffer: RawStorageMut<N, R, C, RStride = U1, CStride = R>,

Implementors§