use crate::PhysicsError;
use crate::constants::FERMI_CONSTANT;
use deep_causality_num::RealField;
use std::f64::consts::PI;
#[derive(Debug, Clone, Copy, Default)]
pub struct RadiativeCorrections<T> {
pub delta_rho: T,
pub delta_r: T,
pub w_mass_corrected: T,
pub sin2_theta_eff: T,
}
pub fn calculate_delta_rho<T>(top_mass: T) -> T
where
T: RealField + From<f64>,
{
let gf = <T as From<f64>>::from(FERMI_CONSTANT);
let pi = <T as From<f64>>::from(PI);
let sqrt2 = <T as From<f64>>::from(2.0).sqrt();
let numerator = <T as From<f64>>::from(3.0) * gf * top_mass * top_mass;
let denominator = <T as From<f64>>::from(8.0) * pi * pi * sqrt2;
numerator / denominator
}
pub fn calculate_delta_r_weak<T>(sin2_theta_w: T, delta_rho: T) -> T
where
T: RealField + From<f64>,
{
let one = <T as From<f64>>::from(1.0);
let cos2_theta_w = one - sin2_theta_w;
let cot2_theta_w = cos2_theta_w / sin2_theta_w;
-cot2_theta_w * delta_rho
}
pub fn calculate_effective_angle<T>(sin2_theta_w: T, delta_rho: T) -> T
where
T: RealField + From<f64>,
{
let one = <T as From<f64>>::from(1.0);
let cos2 = one - sin2_theta_w;
sin2_theta_w + cos2 * delta_rho
}
pub fn solve_w_mass<T>(
mz: T,
top_mass: T,
alpha_mz: T,
alpha_0: T, g_f: T,
) -> Result<RadiativeCorrections<T>, PhysicsError>
where
T: RealField + From<f64>,
{
let delta_rho = calculate_delta_rho(top_mass);
let mut mw = <T as From<f64>>::from(80.30);
let target_accuracy = <T as From<f64>>::from(1e-6);
let max_iters = 20;
let mut delta_r_weak = <T as From<f64>>::from(0.0);
let mut sin2_eff = <T as From<f64>>::from(0.0);
for _ in 0..max_iters {
let sin2_on_shell = <T as From<f64>>::from(1.0) - (mw * mw) / (mz * mz);
delta_r_weak = calculate_delta_r_weak(sin2_on_shell, delta_rho);
sin2_eff = calculate_effective_angle(sin2_on_shell, delta_rho);
let pi = <T as From<f64>>::from(PI);
let sqrt2 = <T as From<f64>>::from(2.0).sqrt();
let numerator = pi * alpha_mz;
let denominator = sqrt2 * g_f * (<T as From<f64>>::from(1.0) - delta_r_weak);
let a = numerator / denominator;
let mz2 = mz * mz;
let discriminant = mz2 * mz2 - <T as From<f64>>::from(4.0) * mz2 * a;
if discriminant < <T as From<f64>>::from(0.0) {
return Err(PhysicsError::NumericalInstability(
"Radiative correction solver failed: Negative discriminant".into(),
));
}
let mw2_new = (mz2 + discriminant.sqrt()) / <T as From<f64>>::from(2.0);
let mw_new = mw2_new.sqrt();
if (mw_new - mw).abs() < target_accuracy {
mw = mw_new;
break;
}
mw = mw_new;
}
let term = (alpha_0 / alpha_mz) * (<T as From<f64>>::from(1.0) - delta_r_weak);
let delta_r_std = <T as From<f64>>::from(1.0) - term;
Ok(RadiativeCorrections {
delta_rho,
delta_r: delta_r_std,
w_mass_corrected: mw,
sin2_theta_eff: sin2_eff,
})
}