20#include "marley/marley_utils.hh"
21#include "marley/CoulombCorrector.hh"
22#include "marley/Error.hh"
23#include "marley/Logger.hh"
24#include "marley/MassTable.hh"
28std::map< CMode, std::string > marley::CoulombCorrector
29 ::coulomb_mode_string_map_ =
31 { CMode::NO_CORRECTION,
"none" },
32 { CMode::FERMI_FUNCTION,
"Fermi" },
33 { CMode::EMA,
"EMA" },
34 { CMode::MEMA,
"MEMA" },
35 { CMode::FERMI_AND_EMA,
"Fermi-EMA" },
36 { CMode::FERMI_AND_MEMA,
"Fermi-MEMA" },
43 double nuclear_radius_natural_units(
int A ) {
45 double R = marley_utils::r0 * std::pow( A, marley_utils::ONE_THIRD );
48 double R_nat = R / marley_utils::hbar_c;
53 bool is_charged_lepton_or_antilepton(
int pdg ) {
54 int abs_pdg = std::abs( pdg );
55 if ( abs_pdg != marley_utils::ELECTRON && abs_pdg != marley_utils::MUON
56 && abs_pdg != marley_utils::TAU )
return false;
66 Af_ = marley_utils::get_particle_A( pdg_d );
67 Zf_ = marley_utils::get_particle_Z( pdg_d );
76 if ( !is_charged_lepton_or_antilepton(
pdg_c_) ) {
91 bool c_minus = (
pdg_c_ > 0 );
94 double gamma_c = std::pow( 1. - beta_c*beta_c, -marley_utils::ONE_HALF );
96 double s = std::sqrt( 1. - std::pow(marley_utils::alpha *
Zf_, 2) );
99 double rho = nuclear_radius_natural_units(
Af_ );
102 double eta = marley_utils::alpha *
Zf_ / beta_c;
106 if ( !c_minus ) eta *= -1;
109 std::complex<double> a( s, eta );
110 double b = std::tgamma( 1 + 2*s );
112 return 2. * ( 1. + s ) * std::pow( 2.*beta_c*gamma_c*rho*
mc_, 2.*s - 2. )
113 * std::exp( marley_utils::pi*eta ) * std::norm( marley_utils::gamma(a) )
122 MARLEY_LOG( TRACE,
"physics.coulomb" ) <<
"Coulomb correction factor = 1"
123 " (NO_CORRECTION mode)";
133 MARLEY_LOG( TRACE,
"physics.coulomb" ) <<
"Coulomb correction factor = "
134 << fermi_func <<
" (Fermi function, beta_rel = " << beta_rel_cd <<
")";
138 bool use_mema =
false;
147 double factor_EMA =
ema_factor( beta_rel_cd, EMA_ok, use_mema );
152 if ( EMA_ok )
return factor_EMA;
154 std::string model_name(
"EMA" );
155 if (
coulomb_mode_ == CoulombMode::MEMA ) model_name =
"MEMA";
156 throw marley::Error(
"Invalid " + model_name +
" factor encountered"
157 " in marley::CoulombCorrector::coulomb_correction_factor()" );
164 throw marley::Error(
"Unrecognized Coulomb correction mode encountered"
165 " in marley::CoulombCorrector::coulomb_correction_factor()" );
173 if ( !EMA_ok )
return fermi_func;
177 double diff_Fermi = std::abs( fermi_func - 1. );
178 double diff_EMA = std::abs( factor_EMA - 1. );
180 double result = ( diff_Fermi < diff_EMA ) ? fermi_func : factor_EMA;
181 MARLEY_LOG( TRACE,
"physics.coulomb" ) <<
"Coulomb correction factor = "
182 << result <<
" (beta_rel = " << beta_rel_cd
183 <<
", Fermi = " << fermi_func <<
", EMA = " << factor_EMA <<
")";
189 bool modified_ema)
const
193 bool minus_c = (
pdg_c_ > 0 );
196 double R_nuc = nuclear_radius_natural_units(
Af_ );
199 double Vc = ( -3. *
Zf_ * marley_utils::alpha ) / ( 2. * R_nuc );
201 if ( !minus_c ) Vc *= -1;
209 double gamma_rel_cd = std::pow( 1. - std::pow(beta_rel_cd, 2), -0.5 );
212 if ( !std::isfinite(gamma_rel_cd) ) {
213 MARLEY_LOG( WARN,
"physics.coulomb" ) <<
"Invalid beta_rel = "
215 <<
" encountered in marley::CoulombCorrector::ema_factor()";
219 double E_c_FNR = gamma_rel_cd *
mc_;
222 double p_c_FNR = beta_rel_cd * E_c_FNR;
225 double E_c_FNR_eff = E_c_FNR - Vc;
231 ok = ( E_c_FNR_eff >=
mc_ );
234 double p_c_FNR_eff = marley_utils::real_sqrt(
235 std::pow(E_c_FNR_eff, 2) -
mc_*
mc_ );
238 double F_EMA = std::pow( p_c_FNR_eff / p_c_FNR, 2 );
241 double F_MEMA = ( p_c_FNR_eff * E_c_FNR_eff ) / ( p_c_FNR * E_c_FNR );
243 if ( modified_ema )
return F_MEMA;
249 const std::string& str )
252 if ( str == pair.second )
return pair.first;
254 throw marley::Error(
"The string \"" + str +
"\" was not recognized"
255 " as a valid Coloumb mode setting" );
262 else throw marley::Error(
"Unrecognized CoulombMode value encountered in"
263 " marley::CoulombCorrector::string_from_coulomb_mode()" );
int Zf_
Residue atomic number.
CoulombCorrector(int pdg_c, int pdg_d, CoulombMode mode=CoulombMode::FERMI_AND_MEMA)
double coulomb_correction_factor(double beta_rel_cd) const
static CoulombMode coulomb_mode_from_string(const std::string &str)
Convert a string to a CoulombMode value.
void set_coulomb_mode(CoulombMode mode)
Set the method for handling Coulomb corrections for this reaction.
static std::map< CoulombMode, std::string > coulomb_mode_string_map_
double ema_factor(double beta_rel_cd, bool &ok, bool modified_ema) const
int pdg_c_
Ejectile PDG code.
CoulombMode
Enumerated type used to set the method for handling Coulomb corrections for CC nuclear reactions.
int Af_
Residue mass number.
CoulombMode coulomb_mode_
The method to use when computing Coulomb corrections.
double fermi_function(double beta_c) const
Compute the Fermi function
static std::string string_from_coulomb_mode(CoulombMode mode)
Convert a CoulombMode value to a string.
Base class for all exceptions thrown by MARLEY functions.
Singleton lookup table for particle and atomic masses.
static const MassTable & Instance()
Get a const reference to the singleton instance of the MassTable.
double get_particle_mass(int pdg_code) const
Get the mass of a particle.