00001 #include "GenDecay/Radiation.h"
00002
00003 #include "GaudiKernel/ServiceHandle.h"
00004 #include "GaudiKernel/IRndmGenSvc.h"
00005 #include "GaudiKernel/IMessageSvc.h"
00006 #include "GaudiKernel/MsgStream.h"
00007 #include "GaudiKernel/GaudiException.h"
00008
00009 #include "CLHEP/Units/PhysicalConstants.h"
00010 #include "CLHEP/Units/SystemOfUnits.h"
00011
00012 #include <cmath>
00013 #include <sstream>
00014
00015 using namespace std;
00016 using namespace GenDecay;
00017
00018 std::ostream& operator<<(std::ostream& o, const Radiation& r)
00019 {
00020 return o << r.asString();
00021 }
00022
00023
00024
00025 Radiation::Radiation(double energy) : m_energy(energy)
00026 {
00027 }
00028
00029 Radiation::~Radiation()
00030 {
00031 }
00032
00033 double Radiation::kineticEnergy() const
00034 {
00035 return m_energy;
00036 }
00037
00038
00039
00040 AlphaRadiation::AlphaRadiation(double energy, int parentA)
00041 : Radiation(energy), m_parentA(parentA)
00042 {
00043 }
00044 AlphaRadiation::~AlphaRadiation()
00045 {
00046 }
00047
00048 std::string AlphaRadiation::asString() const
00049 {
00050 stringstream ss;
00051 ss << "alpha: A=" << m_parentA << ", KE=" << m_energy << ends;
00052 return ss.str().c_str();
00053 }
00054
00055 double AlphaRadiation::kineticEnergy() const
00056 {
00057
00058
00059 return m_energy;
00060 }
00061
00062 int AlphaRadiation::pid() const
00063 {
00064 return 1000020040;
00065 }
00066 double AlphaRadiation::mass() const
00067 {
00068 return 3.727000*CLHEP::GeV;
00069 }
00070
00071
00072
00073 BetaRadiation::BetaRadiation(double energy, int parentZ)
00074 : Radiation(energy)
00075 , m_parentZ(parentZ)
00076 , m_daughterZ(0)
00077 , m_betaSign(0)
00078 , m_endpoint(0.0)
00079 {
00080 if (parentZ < 0) {
00081 m_parentZ = -parentZ;
00082 m_daughterZ = m_parentZ - 1;
00083 m_betaSign = +1;
00084 m_endpoint = m_energy - 2.0*CLHEP::electron_mass_c2;
00085 }
00086 else {
00087 m_parentZ = parentZ;
00088 m_daughterZ = m_parentZ + 1;
00089 m_betaSign = -1;
00090 m_endpoint = m_energy;
00091 }
00092
00093 ServiceHandle<IRndmGenSvc> rgsh("RndmGenSvc","BetaRadiation");
00094 IRndmGenSvc *rgs = rgsh.operator->();
00095 if (m_rand.initialize(rgs, Rndm::Flat(0,1)).isFailure()) {
00096 throw GaudiException("Failed to initialize uniform random numbers",
00097 "GenDecay::Radiation",StatusCode::FAILURE);
00098 }
00099 if (!m_rand) {
00100 throw GaudiException("Got null Rndm::Numbers object",
00101 "GenDecay::Radiation",StatusCode::FAILURE);
00102 }
00103
00104 this->normalize();
00105 }
00106
00107 void BetaRadiation::normalize()
00108 {
00109 const int steps = 1000;
00110 double dx = m_endpoint/steps;
00111 double lo = dx/2.0;
00112
00113 m_norm = 1.0;
00114 double sum = 0.0;
00115 for (int ind=0; ind<steps; ++ind) {
00116 sum += dx * this->dnde(ind*dx+lo);
00117 }
00118 m_norm = sum;
00119
00120 double max = 0;
00121 for (int ind=0; ind<steps; ++ind) {
00122 double tmp = this->dnde(ind*dx+lo);
00123 if (tmp > max) max = tmp;
00124 }
00125 m_maximum = max;
00126 }
00127
00128 BetaRadiation::~BetaRadiation()
00129 {
00130 }
00131
00132 std::string BetaRadiation::asString() const
00133 {
00134 stringstream ss;
00135 ss << "beta"<< (m_betaSign < 0 ? '-' : '+') <<": Z="
00136 << m_parentZ << ", E_endpoint=" << m_energy << ends;
00137 return ss.str().c_str();
00138 }
00139
00140 double BetaRadiation::kineticEnergy() const
00141 {
00142
00143 while (true) {
00144 double T = m_rand() * m_endpoint;
00145 double P = m_rand() * m_maximum;
00146 if (P <= this->dnde(T)) return T;
00147 }
00148 return 0.0;
00149 }
00150
00151 double BetaRadiation::dnde(double kineticEnergy) const
00152 {
00153 if (kineticEnergy > m_endpoint) return 0.0;
00154 if (kineticEnergy < 0.0) return 0.0;
00155 return this->fermi_function(kineticEnergy) * this->dnde_noff(kineticEnergy) / m_norm;
00156 }
00157
00158 double BetaRadiation::dnde_noff(double kineticEnergy) const
00159 {
00160 double W = m_endpoint / CLHEP::electron_mass_c2 + 1.0;
00161 double E = kineticEnergy / CLHEP::electron_mass_c2 + 1.0;
00162 return sqrt(E*E-1.0) * (W-E)*(W-E) * E;
00163 }
00164
00165 double BetaRadiation::fermi_function(double kineticEnergy) const
00166 {
00167 double E = kineticEnergy / CLHEP::electron_mass_c2 + 1.0;
00168 double P = sqrt(E*E-1.0);
00169 double U = -1*m_betaSign*m_daughterZ/137.0;
00170 double S = sqrt(1.0 - U*U) - 1.0;
00171 double Y = 2.0*M_PI*U*E/P;
00172 double A1 = U*U * E*E + P*P/4.0;
00173 double A2 = fabs(Y/(1.0-exp(-Y)));
00174 return pow(A1,S)*A2;
00175 }
00176
00177 int BetaRadiation::pid() const
00178 {
00179 return -1*m_betaSign*11;
00180 }
00181 double BetaRadiation::mass() const
00182 {
00183 return CLHEP::electron_mass_c2;
00184 }
00185
00186 GammaRadiation::GammaRadiation(double energy)
00187 : Radiation(energy)
00188 {
00189 }
00190 GammaRadiation::~GammaRadiation()
00191 {
00192 }
00193
00194 std::string GammaRadiation::asString() const
00195 {
00196 stringstream ss;
00197 ss << "gamma: Energy=" << m_energy << ends;
00198 return ss.str().c_str();
00199 }
00200
00201 int GammaRadiation::pid() const
00202 {
00203 return 22;
00204 }
00205
00206 double GammaRadiation::mass() const
00207 {
00208 return 0;
00209 }
00210
00211 ElectronCapture::ElectronCapture(double characteristic_energy)
00212 : Radiation(characteristic_energy)
00213 {
00214 }
00215 ElectronCapture::~ElectronCapture()
00216 {
00217 }
00218
00219 std::string ElectronCapture::asString() const
00220 {
00221 stringstream ss;
00222 ss << "electroncapture: Energy=" << m_energy << ends;
00223 return ss.str().c_str();
00224 }
00225
00226 int ElectronCapture::pid() const
00227 {
00228 return 0;
00229 }
00230
00231 double ElectronCapture::mass() const
00232 {
00233 return 0.0;
00234 }
00235