use crate::{NEWTONIAN_CONSTANT_OF_GRAVITATION, PhysicsError, SPEED_OF_LIGHT};
use deep_causality_num::{Field, Float};
use deep_causality_tensor::CausalTensor;
pub type GeodesicState<S> = (Vec<S>, Vec<S>);
pub trait GrOps<S>
where
S: Field + Float + Clone + From<f64> + Into<f64>,
{
fn ricci_tensor(&self) -> Result<CausalTensor<S>, PhysicsError>;
fn ricci_scalar(&self) -> Result<S, PhysicsError>;
fn einstein_tensor(&self) -> Result<CausalTensor<S>, PhysicsError>;
fn kretschmann_scalar(&self) -> Result<S, PhysicsError>;
fn kretschmann_curvature_radius(&self) -> Result<S, PhysicsError> {
let k = self.kretschmann_scalar()?;
if k <= S::zero() {
return Ok(S::infinity()); }
let quart = <S as From<f64>>::from(0.25);
Ok(S::one() / k.powf(quart))
}
fn geodesic_deviation(&self, velocity: &[S], separation: &[S]) -> Result<Vec<S>, PhysicsError>;
fn geodesic_deviation_si(
&self,
velocity: &[S],
separation: &[S],
) -> Result<Vec<S>, PhysicsError> {
let geometric = self.geodesic_deviation(velocity, separation)?;
let c = <S as From<f64>>::from(SPEED_OF_LIGHT);
let c2 = c * c;
Ok(geometric.into_iter().map(|v| v * c2).collect())
}
fn solve_geodesic(
&self,
initial_position: &[S],
initial_velocity: &[S],
proper_time_step: S,
num_steps: usize,
) -> Result<Vec<GeodesicState<S>>, PhysicsError>;
fn proper_time(&self, path: &[Vec<S>]) -> Result<S, PhysicsError>;
fn proper_time_si(&self, path: &[Vec<S>]) -> Result<S, PhysicsError> {
let geometric = self.proper_time(path)?;
let c = <S as From<f64>>::from(SPEED_OF_LIGHT);
Ok(geometric / c)
}
fn parallel_transport(
&self,
initial_vector: &[S],
path: &[Vec<S>],
) -> Result<Vec<S>, PhysicsError>;
fn metric_tensor(&self) -> &CausalTensor<S>;
fn schwarzschild_radius(mass_kg: S) -> S {
let two = <S as From<f64>>::from(2.0);
let g = <S as From<f64>>::from(NEWTONIAN_CONSTANT_OF_GRAVITATION);
let c = <S as From<f64>>::from(SPEED_OF_LIGHT);
(two * g * mass_kg) / (c * c)
}
fn compute_riemann_from_christoffel(&self) -> CausalTensor<S>;
fn momentum_constraint_field(
&self,
extrinsic_curvature: &CausalTensor<S>,
matter_momentum: Option<&CausalTensor<S>>,
) -> Result<CausalTensor<S>, PhysicsError>;
}