use crate::PhysicsError;
use deep_causality_metric::{EastCoastMetric, LorentzianMetric};
use deep_causality_tensor::CausalTensor;
use std::f64::consts::PI;
pub fn minkowski_metric() -> CausalTensor<f64> {
let metric = EastCoastMetric::minkowski_4d().into_metric();
let sign_0 = metric.sign_of_sq(0) as f64;
let sign_1 = metric.sign_of_sq(1) as f64;
let sign_2 = metric.sign_of_sq(2) as f64;
let sign_3 = metric.sign_of_sq(3) as f64;
let data = vec![
sign_0, 0.0, 0.0, 0.0, 0.0, sign_1, 0.0, 0.0, 0.0, 0.0, sign_2, 0.0, 0.0, 0.0, 0.0, sign_3,
];
CausalTensor::from_vec(data, &[4, 4])
}
pub fn kerr_metric_at(
mass: f64,
a: f64,
r: f64,
theta: f64,
) -> Result<CausalTensor<f64>, PhysicsError> {
if r < 0.0 {
return Err(PhysicsError::DimensionMismatch(
"Radius must be non-negative".into(),
));
}
let r2 = r * r;
let a2 = a * a;
let cos_theta = theta.cos();
let sin_theta = theta.sin();
let sin2_theta = sin_theta * sin_theta;
let cos2_theta = cos_theta * cos_theta;
let sigma = r2 + a2 * cos2_theta;
let delta = r2 - 2.0 * mass * r + a2;
if delta.abs() < 1e-10 {
return Err(PhysicsError::NumericalInstability(
"Coordinate singularity at horizon".into(),
));
}
if sigma.abs() < 1e-10 {
return Err(PhysicsError::NumericalInstability(
"Ring singularity".into(),
));
}
let g_tt = -(1.0 - 2.0 * mass * r / sigma);
let g_rr = sigma / delta;
let g_theta = sigma;
let g_phi = (r2 + a2 + 2.0 * mass * a2 * r * sin2_theta / sigma) * sin2_theta;
let g_tphi = -2.0 * mass * r * a * sin2_theta / sigma;
let mut data = vec![0.0; 16];
data[0] = g_tt;
data[5] = g_rr;
data[10] = g_theta;
data[15] = g_phi;
data[3] = g_tphi;
data[12] = g_tphi;
Ok(CausalTensor::from_vec(data, &[4, 4]))
}
pub fn flrw_metric_at(
scale_factor: f64,
curvature_k: f64,
r: f64,
theta: f64,
) -> Result<CausalTensor<f64>, PhysicsError> {
if scale_factor <= 0.0 {
return Err(PhysicsError::DimensionMismatch(
"Scale factor must be positive".into(),
));
}
let a2 = scale_factor * scale_factor;
let kr2 = curvature_k * r * r;
if (1.0 - kr2).abs() < 1e-10 {
return Err(PhysicsError::NumericalInstability(
"Singularity at 1-kr^2=0".into(),
));
}
let g_tt = -1.0;
let g_rr = a2 / (1.0 - kr2);
let g_theta = a2 * r * r;
let g_phi = a2 * r * r * theta.sin().powi(2);
let data = vec![
g_tt, 0.0, 0.0, 0.0, 0.0, g_rr, 0.0, 0.0, 0.0, 0.0, g_theta, 0.0, 0.0, 0.0, 0.0, g_phi,
];
Ok(CausalTensor::from_vec(data, &[4, 4]))
}
pub fn schwarzschild_metric_at(mass: f64, r: f64) -> Result<CausalTensor<f64>, PhysicsError> {
if r <= 0.0 {
return Err(PhysicsError::DimensionMismatch(
"Radius must be positive".into(),
));
}
let r_s = 2.0 * mass; if r <= r_s {
return Err(PhysicsError::NumericalInstability(format!(
"Radius {} is at or inside horizon r_s = {}",
r, r_s
)));
}
let f = 1.0 - r_s / r;
let theta = PI / 2.0;
let g_tt = -f;
let g_rr = 1.0 / f;
let g_theta = r * r;
let g_phi = r * r * theta.sin().powi(2);
let data = vec![
g_tt, 0.0, 0.0, 0.0, 0.0, g_rr, 0.0, 0.0, 0.0, 0.0, g_theta, 0.0, 0.0, 0.0, 0.0, g_phi,
];
Ok(CausalTensor::from_vec(data, &[4, 4]))
}
#[allow(clippy::identity_op, clippy::erasing_op)]
pub fn schwarzschild_christoffel_at(mass: f64, r: f64) -> Result<CausalTensor<f64>, PhysicsError> {
if r <= 0.0 {
return Err(PhysicsError::DimensionMismatch(
"Radius must be positive".into(),
));
}
let r_s = 2.0 * mass;
if r <= r_s {
return Err(PhysicsError::NumericalInstability(format!(
"Radius {} is at or inside horizon r_s = {}",
r, r_s
)));
}
let f = 1.0 - r_s / r;
let f_prime = r_s / (r * r);
let theta = PI / 2.0;
let dim = 4;
let mut gamma = vec![0.0; dim * dim * dim];
let g_t_tr = f_prime / (2.0 * f);
gamma[0 * 16 + 1 * 4 + 0] = g_t_tr; gamma[0 * 16 + 0 * 4 + 1] = g_t_tr;
gamma[1 * 16 + 0 * 4 + 0] = f * f_prime / 2.0;
gamma[1 * 16 + 1 * 4 + 1] = -f_prime / (2.0 * f);
gamma[1 * 16 + 2 * 4 + 2] = -(r - r_s);
gamma[1 * 16 + 3 * 4 + 3] = -(r - r_s) * theta.sin().powi(2);
gamma[2 * 16 + 1 * 4 + 2] = 1.0 / r;
gamma[2 * 16 + 2 * 4 + 1] = 1.0 / r;
gamma[2 * 16 + 3 * 4 + 3] = -theta.sin() * theta.cos();
gamma[3 * 16 + 1 * 4 + 3] = 1.0 / r;
gamma[3 * 16 + 3 * 4 + 1] = 1.0 / r;
gamma[3 * 16 + 2 * 4 + 3] = theta.cos() / theta.sin();
gamma[3 * 16 + 3 * 4 + 2] = theta.cos() / theta.sin();
Ok(CausalTensor::from_vec(gamma, &[dim, dim, dim]))
}
pub fn schwarzschild_kretschmann(mass: f64, r: f64) -> f64 {
48.0 * mass * mass / r.powi(6)
}