use crate::kernels::relativity::quantities::SpacetimeVector;
use crate::error::PhysicsError;
use crate::kernels::quantum::quantities::PhaseAngle;
use deep_causality_multivector::{CausalMultiVector, Metric, MultiVector};
use deep_causality_num::{Field, Float, RealField};
pub fn spacetime_interval_kernel<R>(
x: &CausalMultiVector<R>,
metric: &Metric,
) -> Result<R, PhysicsError>
where
R: RealField,
{
if x.metric() != *metric {
return Err(PhysicsError::MetricSingularity(format!(
"Spacetime Interval Metric Mismatch: Vector has {:?}, Context expects {:?}",
x.metric(),
metric
)));
}
Ok(x.squared_magnitude())
}
pub fn time_dilation_angle_kernel<R>(
t1: &CausalMultiVector<R>,
t2: &CausalMultiVector<R>,
) -> Result<PhaseAngle<R>, PhysicsError>
where
R: RealField,
{
if t1.metric() != t2.metric() {
return Err(PhysicsError::MetricSingularity(
"Metric mismatch between vectors".into(),
));
}
if let Metric::Minkowski(_) = t1.metric() {
} else {
return Err(PhysicsError::MetricSingularity(
"Time dilation requires Minkowski metric".into(),
));
}
let inner = t1.inner_product(t2);
if inner.data().is_empty() {
return Err(PhysicsError::PhysicalInvariantBroken(
"Inner product did not yield any data".into(),
));
}
let mut non_scalar_magnitude = R::zero();
for v in inner.data().iter().skip(1) {
non_scalar_magnitude += v.abs();
}
let dot = inner.data()[0];
let eps_rel = R::epsilon().sqrt();
let dot_scale = if dot.abs() > R::one() {
dot.abs()
} else {
R::one()
};
let grade_tol = eps_rel * dot_scale;
if non_scalar_magnitude > grade_tol {
return Err(PhysicsError::PhysicalInvariantBroken(
"Inner product did not yield scalar grade".into(),
));
}
let s1 = t1.squared_magnitude();
let s2 = t2.squared_magnitude();
let zero = R::zero();
if !(s1 > zero && s2 > zero) {
return Err(PhysicsError::CausalityViolation(
"Non-timelike vector encountered".into(),
));
}
let mag1 = s1.sqrt();
let mag2 = s2.sqrt();
let denom = mag1 * mag2;
if denom == zero || !denom.is_finite() {
return Err(PhysicsError::NumericalInstability(
"Invalid normalization in gamma computation".into(),
));
}
let one = R::one();
let mut gamma = dot / denom;
if gamma < one && (one - gamma) <= eps_rel {
gamma = one;
}
if gamma < one {
return Err(PhysicsError::CausalityViolation(
"Invalid Lorentz factor < 1.0".into(),
));
}
let eta = (gamma + (gamma * gamma - one).sqrt()).ln();
PhaseAngle::new(eta)
}
pub fn chronometric_volume_kernel<R>(
a: &CausalMultiVector<R>,
b: &CausalMultiVector<R>,
c: &CausalMultiVector<R>,
) -> Result<SpacetimeVector<R>, PhysicsError>
where
R: RealField,
{
if a.metric() != b.metric() || a.metric() != c.metric() {
return Err(PhysicsError::MetricSingularity(
"chronometric_volume requires all vectors to share the same metric".into(),
));
}
let v = a.outer_product(b).outer_product(c);
Ok(SpacetimeVector(v))
}
pub fn generate_schwarzschild_metric<T>(
g_00: T,
g_11: T,
g_22: T,
g_33: T,
) -> Result<deep_causality_tensor::CausalTensor<T>, PhysicsError>
where
T: Field + Float,
{
let metric_data = vec![
g_00,
T::zero(),
T::zero(),
T::zero(),
T::zero(),
g_11,
T::zero(),
T::zero(),
T::zero(),
T::zero(),
g_22,
T::zero(),
T::zero(),
T::zero(),
T::zero(),
g_33,
];
deep_causality_tensor::CausalTensor::new(metric_data, vec![4, 4]).map_err(PhysicsError::from)
}
pub fn parallel_transport_kernel<T>(
initial_vector: &[T],
path: &[Vec<T>],
christoffel: &deep_causality_tensor::CausalTensor<T>,
) -> Result<Vec<T>, PhysicsError>
where
T: Field + Float + From<f64> + Copy,
{
if path.len() < 2 {
return Err(PhysicsError::DimensionMismatch(
"Path must have at least 2 points".into(),
));
}
let dim = initial_vector.len();
if christoffel.num_dim() != 3 {
return Err(PhysicsError::DimensionMismatch(format!(
"Christoffel symbols must be rank 3, got {}",
christoffel.num_dim()
)));
}
let shape = christoffel.shape();
if shape[0] != dim || shape[1] != dim || shape[2] != dim {
return Err(PhysicsError::DimensionMismatch(format!(
"Christoffel shape {:?} incompatible with dimension {}",
shape, dim
)));
}
for (i, point) in path.iter().enumerate() {
if point.len() != dim {
return Err(PhysicsError::DimensionMismatch(format!(
"Path point {} has dimension {}, expected {}",
i,
point.len(),
dim
)));
}
}
let christoffel_data = christoffel.as_slice();
let mut v = initial_vector.to_vec();
for i in 0..path.len() - 1 {
let dx: Vec<T> = path[i + 1]
.iter()
.zip(path[i].iter())
.map(|(x1, x0)| *x1 - *x0)
.collect();
let mut dv = vec![T::zero(); dim];
for mu in 0..dim {
for nu in 0..dim {
for rho in 0..dim {
let gamma = christoffel_data[mu * dim * dim + nu * dim + rho];
dv[mu] -= gamma * dx[nu] * v[rho];
}
}
}
for mu in 0..dim {
v[mu] += dv[mu];
}
if v.iter().any(|x| !x.is_finite()) {
return Err(PhysicsError::NumericalInstability(format!(
"Parallel transport diverged at segment {}",
i
)));
}
}
Ok(v)
}
pub fn proper_time_kernel<T>(
path: &[Vec<T>],
metric: &deep_causality_tensor::CausalTensor<T>,
) -> Result<T, PhysicsError>
where
T: Field + Float + From<f64> + Copy,
{
if path.len() < 2 {
return Ok(T::zero()); }
if metric.num_dim() != 2 {
return Err(PhysicsError::DimensionMismatch(format!(
"Metric must be rank 2, got {}",
metric.num_dim()
)));
}
let shape = metric.shape();
let dim = shape[0];
if shape[1] != dim {
return Err(PhysicsError::DimensionMismatch(format!(
"Metric must be square, got {:?}",
shape
)));
}
for (i, point) in path.iter().enumerate() {
if point.len() != dim {
return Err(PhysicsError::DimensionMismatch(format!(
"Path point {} has dimension {}, expected {}",
i,
point.len(),
dim
)));
}
}
let metric_data = metric.as_slice();
let mut total_tau = T::zero();
for i in 0..path.len() - 1 {
let dx: Vec<T> = path[i + 1]
.iter()
.zip(path[i].iter())
.map(|(x1, x0)| *x1 - *x0)
.collect();
let mut ds_squared = T::zero();
for mu in 0..dim {
for nu in 0..dim {
let g_munu = metric_data[mu * dim + nu];
ds_squared += g_munu * dx[mu] * dx[nu];
}
}
let dtau = ds_squared.abs().sqrt();
if !dtau.is_finite() {
return Err(PhysicsError::NumericalInstability(format!(
"Non-finite proper time increment at segment {}",
i
)));
}
total_tau += dtau;
}
Ok(total_tau)
}