use std::sync::Arc;
use crate::symbolic::core::Expr;
#[must_use]
pub fn lorentz_factor(velocity: &Expr) -> Expr {
let c = Expr::new_variable("c");
let v_sq = Expr::new_pow(velocity.clone(), Expr::Constant(2.0));
let c_sq = Expr::new_pow(c, Expr::Constant(2.0));
let beta_sq = Expr::new_div(v_sq, c_sq);
Expr::new_pow(
Expr::new_sub(Expr::Constant(1.0), beta_sq),
Expr::Constant(-0.5),
)
}
#[must_use]
pub fn lorentz_transformation_x(
x: &Expr,
t: &Expr,
v: &Expr,
) -> (Expr, Expr) {
let gamma = lorentz_factor(v);
let c = Expr::new_variable("c");
let c_sq = Expr::new_pow(c, Expr::Constant(2.0));
let x_prime = Expr::new_mul(
gamma.clone(),
Expr::new_sub(x.clone(), Expr::new_mul(v.clone(), t.clone())),
);
let t_prime = Expr::new_mul(
gamma,
Expr::new_sub(
t.clone(),
Expr::new_div(Expr::new_mul(v.clone(), x.clone()), c_sq),
),
);
(x_prime, t_prime)
}
#[must_use]
pub fn velocity_addition(
v: &Expr,
u_prime: &Expr,
) -> Expr {
let c = Expr::new_variable("c");
let c_sq = Expr::new_pow(c, Expr::Constant(2.0));
let numerator = Expr::new_add(v.clone(), u_prime.clone());
let denominator = Expr::new_add(
Expr::Constant(1.0),
Expr::new_div(Expr::new_mul(v.clone(), u_prime.clone()), c_sq),
);
Expr::new_div(numerator, denominator)
}
#[must_use]
pub fn mass_energy_equivalence(mass: &Expr) -> Expr {
let c = Expr::new_variable("c");
let c_sq = Expr::new_pow(c, Expr::Constant(2.0));
Expr::new_mul(mass.clone(), c_sq)
}
#[must_use]
pub fn relativistic_momentum(
mass: &Expr,
velocity: &Expr,
) -> Expr {
let gamma = lorentz_factor(velocity);
Expr::new_mul(gamma, Expr::new_mul(mass.clone(), velocity.clone()))
}
#[must_use]
pub fn doppler_effect(
f_src: &Expr,
v: &Expr,
) -> Expr {
let c = Expr::new_variable("c");
let beta = Expr::new_div(v.clone(), c);
let ratio = Expr::new_div(
Expr::new_sub(Expr::Constant(1.0), beta.clone()),
Expr::new_add(Expr::Constant(1.0), beta),
);
Expr::new_mul(f_src.clone(), Expr::new_pow(ratio, Expr::Constant(0.5)))
}
#[must_use]
pub fn schwarzschild_radius(mass: &Expr) -> Expr {
let g = Expr::new_variable("G");
let c = Expr::new_variable("c");
let c_sq = Expr::new_pow(c, Expr::Constant(2.0));
Expr::new_div(
Expr::new_mul(Expr::Constant(2.0), Expr::new_mul(g, mass.clone())),
c_sq,
)
}
#[must_use]
pub fn gravitational_time_dilation(
t_far: &Expr,
r: &Expr,
mass: &Expr,
) -> Expr {
let r_s = schwarzschild_radius(mass);
let ratio = Expr::new_div(r_s, r.clone());
Expr::new_mul(
t_far.clone(),
Expr::new_pow(
Expr::new_sub(Expr::Constant(1.0), ratio),
Expr::Constant(0.5),
),
)
}
#[must_use]
pub fn einstein_tensor(
ricci_tensor: &Expr,
scalar_curvature: &Expr,
metric: &Expr,
) -> Expr {
Expr::new_sub(
ricci_tensor.clone(),
Expr::new_mul(
Expr::Constant(0.5),
Expr::new_mul(scalar_curvature.clone(), metric.clone()),
),
)
}
#[must_use]
pub fn geodesic_acceleration(
christoffel: &Expr,
u_alpha: &Expr,
u_beta: &Expr,
) -> Expr {
Expr::new_neg(Arc::new(Expr::new_mul(
christoffel.clone(),
Expr::new_mul(u_alpha.clone(), u_beta.clone()),
)))
}
#[must_use]
pub fn lorentz_transformation(
x: &Expr,
t: &Expr,
v: &Expr,
) -> (Expr, Expr) {
lorentz_transformation_x(x, t, v)
}
#[must_use]
pub fn einstein_field_equations(
ricci: &Expr,
scalar: &Expr,
metric: &Expr,
_stress: &Expr,
) -> Expr {
einstein_tensor(ricci, scalar, metric)
}
#[must_use]
pub fn geodesic_equation(
christoffel: &Expr,
u_alpha: &Expr,
u_beta: &Expr,
_tau: &str,
) -> Expr {
geodesic_acceleration(christoffel, u_alpha, u_beta)
}