use std::sync::Arc;
use crate::symbolic::core::Expr;
use crate::symbolic::simplify_dag::simplify;
#[must_use]
pub fn dirac_adjoint(psi: &Expr) -> Expr {
let gamma_0 = Expr::new_variable("gamma_0");
simplify(&Expr::new_mul(psi.clone(), gamma_0))
}
#[must_use]
pub fn feynman_slash(v_mu: &Expr) -> Expr {
let gamma_mu = Expr::new_variable("gamma_mu");
simplify(&Expr::new_mul(gamma_mu, v_mu.clone()))
}
#[must_use]
pub fn scalar_field_lagrangian(
phi: &Expr,
m: &Expr,
) -> Expr {
let half = Expr::Constant(0.5);
let d_mu_phi = Expr::new_variable("partial_mu_phi");
let d_mu_phi_sq = Expr::new_pow(d_mu_phi, Expr::Constant(2.0));
let m_sq = Expr::new_pow(m.clone(), Expr::Constant(2.0));
let phi_sq = Expr::new_pow(phi.clone(), Expr::Constant(2.0));
let mass_term = Expr::new_mul(m_sq, phi_sq);
let diff = Expr::new_sub(d_mu_phi_sq, mass_term);
simplify(&Expr::new_mul(half, diff))
}
#[must_use]
pub fn qed_lagrangian(
psi_bar: &Expr,
psi: &Expr,
a_mu: &Expr,
m: &Expr,
e: &Expr,
) -> Expr {
let i = Expr::new_complex(Expr::Constant(0.0), Expr::Constant(1.0));
let partial_slash = feynman_slash(&Expr::new_variable("partial_mu"));
let a_slash = feynman_slash(a_mu);
let id_slash = Expr::new_sub(
Expr::new_mul(i, partial_slash),
Expr::new_mul(e.clone(), a_slash),
);
let dirac_part = Expr::new_mul(
psi_bar.clone(),
Expr::new_mul(Expr::new_sub(id_slash, m.clone()), psi.clone()),
);
let f_mu_nu = Expr::new_variable("F_mu_nu");
let f_sq = Expr::new_pow(f_mu_nu, Expr::Constant(2.0));
let gauge_part = Expr::new_mul(Expr::Constant(-0.25), f_sq);
simplify(&Expr::new_add(dirac_part, gauge_part))
}
#[must_use]
pub fn qcd_lagrangian(
psi_bar: &Expr,
psi: &Expr,
g_mu: &Expr,
m: &Expr,
gs: &Expr,
) -> Expr {
let i = Expr::new_complex(Expr::Constant(0.0), Expr::Constant(1.0));
let partial_slash = feynman_slash(&Expr::new_variable("partial_mu"));
let g_slash = feynman_slash(g_mu);
let id_slash = Expr::new_add(
Expr::new_mul(i, partial_slash),
Expr::new_mul(gs.clone(), g_slash),
);
let quark_part = Expr::new_mul(
psi_bar.clone(),
Expr::new_mul(Expr::new_sub(id_slash, m.clone()), psi.clone()),
);
let g_strength = Expr::new_variable("G_mu_nu_a");
let g_sq = Expr::new_pow(g_strength, Expr::Constant(2.0));
let gluon_part = Expr::new_mul(Expr::Constant(-0.25), g_sq);
simplify(&Expr::new_add(quark_part, gluon_part))
}
#[must_use]
pub fn propagator(
p: &Expr,
m: &Expr,
is_fermion: bool,
) -> Expr {
let i = Expr::new_complex(Expr::Constant(0.0), Expr::Constant(1.0));
let p_sq = Expr::new_pow(p.clone(), Expr::Constant(2.0));
let m_sq = Expr::new_pow(m.clone(), Expr::Constant(2.0));
let eps = Expr::new_mul(i.clone(), Expr::new_variable("epsilon"));
let denominator = Expr::new_add(Expr::new_sub(p_sq, m_sq), eps);
if is_fermion {
let p_slash = feynman_slash(p);
let numerator = Expr::new_mul(i, Expr::new_add(p_slash, m.clone()));
simplify(&Expr::new_div(numerator, denominator))
} else {
simplify(&Expr::new_div(i, denominator))
}
}
#[must_use]
pub fn scattering_cross_section(
matrix_element: &Expr,
flux: &Expr,
phase_space: &Expr,
) -> Expr {
let m_sq = Expr::new_pow(Expr::new_abs(matrix_element.clone()), Expr::Constant(2.0));
simplify(&Expr::new_mul(
Expr::new_div(m_sq, flux.clone()),
phase_space.clone(),
))
}
#[must_use]
pub fn feynman_propagator_position_space(
x: &Expr,
y: &Expr,
m: &Expr,
) -> Expr {
let p = Expr::new_variable("p");
let prop_p = propagator(&p, m, false);
let diff = Expr::new_sub(x.clone(), y.clone());
let exponent = Expr::new_mul(
Expr::new_complex(Expr::Constant(0.0), Expr::Constant(-1.0)),
Expr::new_mul(p.clone(), diff),
);
let integrand = Expr::new_mul(prop_p, Expr::new_exp(exponent));
simplify(&Expr::Integral {
integrand: Arc::new(integrand),
var: Arc::new(p),
lower_bound: Arc::new(Expr::NegativeInfinity),
upper_bound: Arc::new(Expr::Infinity),
})
}