#include "BEAM/Main/EPA.H" #include "ATOOLS/Org/Message.H" #include "ATOOLS/Org/Exception.H" #include "ATOOLS/Org/MyStrStream.H" #include "ATOOLS/Org/Scoped_Settings.H" #include "ATOOLS/Math/Gauss_Integrator.H" #include #include using namespace BEAM; using namespace ATOOLS; EPA::EPA(const Flavour _beam,const double _mass, const double _charge,const double _energy, const double _pol, const int _dir): Beam_Base("EPA",_beam,_energy,_pol,_dir), m_mass(_mass), m_charge(_charge) { Settings& s = Settings::GetMainSettings(); RegisterDefaults(); m_bunch=Flavour(kf_photon); m_vecout=Vec4D(m_energy,0.,0.,_dir*m_energy); std::vector q2Max{ s["EPA_q2Max"].GetVector() }; if (q2Max.size() != 1 && q2Max.size() != 2) THROW(fatal_error, "Specify either one or two values for `EPA_q2Max'."); m_q2Max = (_dir > 0) ? q2Max.front() : q2Max.back(); std::vector pt_min{ s["EPA_ptMin"].GetVector() }; if (pt_min.size() != 1 && pt_min.size() != 2) THROW(fatal_error, "Specify either one or two values for `EPA_ptMin'."); m_pt_min = (_dir > 0) ? pt_min.front() : pt_min.back(); m_aqed = s["EPA_AlphaQED"].Get(); std::vector formfactors{ s["EPA_Form_Factor"].GetVector() }; if (formfactors.size() != 1 && formfactors.size() != 2) THROW(fatal_error, "Specify either one or two values for `EPA_Form_Factor'."); m_formfactor = (_dir > 0) ? formfactors.front() : formfactors.back(); if (m_pt_min>1.0) { /* pt_min > 1 - according to approximation of 'qmi' calculation in CalculateWeight */ THROW(critical_error,"Too big p_T cut ( "+ToString(m_pt_min)+")"); } if (s["EPA_Debug"].Get()) { std::vector files{ s["EPA_Debug_Files"].GetVector() }; if (files.size() != 1 && files.size() != 2) THROW(fatal_error, "Specify either one or two values for `EPA_Debug_Files'."); std::string filename { (_dir > 0) ? files.front() : files.back() }; std::string num(_dir>0?"1":"2"); filename += num + ".log"; this->selfTest(filename); } } EPA::~EPA() { } void EPA::RegisterDefaults() { Settings& s = Settings::GetMainSettings(); s["EPA_q2Max"].SetDefault(2.0); s["EPA_ptMin"].SetDefault(0.0); s["EPA_Form_Factor"].SetDefault(m_beam.FormFactor()); s["EPA_AlphaQED"].SetDefault(0.0072992701); s["EPA_Debug"].SetDefault(false); s["EPA_Debug_Files"].SetDefault("EPA_debugOutput"); } double EPA::CosInt::GetCosInt(double X) { if (X<0.) exit(1); ATOOLS::Gauss_Integrator integrator(this); return integrator.Integrate(X,100000.,1.e-4,1); } double EPA::phi(double x, double qq) { if (m_beam.Kfcode() == kf_p_plus) { const double a = 7.16; const double b = -3.96; const double c = .028; double y,qq1,f; qq1=1+qq; y= x*x/(1-x); f=(1+a*y)*(-log(qq1/qq)+1/qq1+1/(2*qq1*qq1)+1/(3*qq1*qq1*qq1)); f+=(1-b)*y/(4*qq*qq1*qq1*qq1); f+=c*(1+y/4)*(log((qq1-b)/qq1)+b/qq1+b*b/(2*qq1*qq1)+b*b*b/(3*qq1*qq1*qq1)); return f; } if (m_beam.IsIon()) { // x := omega / omega0 is assumed in the following code! // ensure whether calls of phi for ions are done correctly // x_omega=x*E/omega0=x*E*R/gamma double f = 0.; // needed for gaussian shaped nucleus const double q0 = 0.06; const int atomicNumber = m_beam.GetAtomicNumber(); const double radius = 1.2/.197*pow(atomicNumber, 1./3.); CosInt Ci; // do form factor dependent calculation switch (m_formfactor) { //switch (2) { case 0: // point-like form factor f= log(1. + (1./(x*x)))/2. + 1./(1.+(1./(x*x)))/2.-1./2.; break; case 1: // homogeneously charged sphere f+= 3. / (16. * pow(x, 6.)); f+= 3. / (8. * pow(x, 4.)); f-= cos(2.*x)*3./(16*pow(x, 6.)) + cos(2.*x)*7./(40.*x*x); f-= cos(2.*x)*1./20.; f-= sin(2.*x)*3./(8*pow(x,5.)) + sin(2.*x)*1./(10.*x*x*x); f+= sin(2.*x)*9./(20.*x) - sin(2.*x)*x/10.; f-= Ci.GetCosInt(2.*x) * (1. + pow(x, 5.)/5.); // integral-cosine break; case 2: // gaussian shaped nucleus f=(1.+x*x / (q0*q0*radius*radius) ); f*=ExpIntegral(1, x*x / (q0*q0*radius*radius)); f-=exp(-x*x / (q0*q0*radius*radius)); f/=2.; break; case 3: // homogeneously charged sphere (smooth function at low and high x) if (x < 0.003) { // make n(x) smooth at low x f=1.83698*pow(x,-0.00652101)*M_PI*m_energy; //f=1.36549*pow(x,-0.059967)*M_PI*m_energy*atomicNumber; // prefactor*c*x^a with c and a from a fit to x_omega*n(x_omega) f/=(2*m_aqed*m_charge*m_charge*radius*m_beam.Mass()); } else if (x > 1.33086) { // cut off oscillating parts at high x f=0.; } else { // normal homogenously charged sphere f+= 3. / (16. * pow(x, 6.)); f+= 3. / (8. * pow(x, 4.)); f-= cos(2.*x)*3./(16*pow(x, 6.)) + cos(2.*x)*7./(40.*x*x); f-= cos(2.*x)*1./20.; f-= sin(2.*x)*3./(8*pow(x,5.)) + sin(2.*x)*1./(10.*x*x*x); f+= sin(2.*x)*9./(20.*x) - sin(2.*x)*x/10.; f-= Ci.GetCosInt(2.*x) * (1. + pow(x, 5.)/5.); // integral-cosine } break; default: THROW(fatal_error,"Unknown ion form factor chosen"); } return (double)f; } return 0.; } void EPA::selfTest(std::string filename) { std::ofstream debugOutput; debugOutput.open(filename.c_str()); debugOutput << "# EPA::selfTest() starting ..." << std::endl; // select output format debugOutput.setf(std::ios::scientific, std::ios::floatfield); debugOutput.precision(10); double x_omega=.1e-2; const int atomicNumber = m_beam.GetAtomicNumber(); const double radius = 1.2/.197*pow(atomicNumber, 1./3.); double omega0, gamma; gamma = m_energy / m_beam.Mass(); //gamma = m_energy * atomicNumber / m_beam.Mass(); // energy is defined as sqrt[s_NN], N=nucleon // but recalculated already in the Beam_Spectra_Handler omega0 = gamma / radius; // write parameters debugOutput << "# Form Factor: " << m_formfactor << std::endl; debugOutput << "# A= " << atomicNumber << std::endl; debugOutput << "# R= " << radius << std::endl; debugOutput << "# E= " << m_energy << std::endl; debugOutput << "# Z= " << m_charge << std::endl; debugOutput << "# M_Ion=" << m_beam.Mass() << std::endl; debugOutput << "# gamma= " << gamma << std::endl; debugOutput << "# omega0= " << omega0 << std::endl; // write spectrum while (x_omega < 5) { x_omega*=1.005; CalculateWeight(x_omega*omega0/m_energy, 0); // m_weight = n(x) debugOutput << x_omega << "\t" << x_omega * m_weight / m_energy << std::endl; } debugOutput << "# EPA::selfTest() finished" << std::endl << std::endl; debugOutput.close(); return; } bool EPA::CalculateWeight(double x,double q2) { // x = omega/E = (E-E')/E ; E,E' - incoming and outgoing protons energy // omega = E-E' - energy of emitted photon const double alpha = m_aqed; m_x = x; m_Q2 = q2; if (x>=1.) { m_weight=0.0; return 1; } if (m_beam.Kfcode() == kf_e) { double f = alpha/M_PI*(1+sqr(1-m_x))/m_x*log(2.*m_energy/m_mass); if (f < 0) f = 0.; m_weight = f; msg_Debugging()<