Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

CrElectronPrimary.cxx

Go to the documentation of this file.
00001 
00012 #include <math.h>
00013 
00014 // Geant4
00015 //#include "Randomize.hh"               // in source/global/HEPRandom/include/
00016 //#include "SystemOfUnits.h"    // in source/global/management/include/
00017 // CLHEP
00018 #include <CLHEP/Random/RandomEngine.h>
00019 #include <CLHEP/Random/RandGeneral.h>
00020 #include <CLHEP/Random/JamesRandom.h>
00021 
00022 #include "CrElectronPrimary.h"
00023 
00024 
00025 typedef  double G4double;
00026 
00027 
00028 // private function definitions.
00029 namespace {
00030   const G4double pi    = 3.14159265358979323846264339;
00031   const G4double restE = 5.11e-4; // rest energy of electron in [GeV]
00032   // lower and higher energy limit of primary electron in units of GeV
00033   const G4double lowE_primary  = 1.0;
00034   const G4double highE_primary = 100.0;
00035 
00036   // The following value were computed from the model in advance.
00037   // This should be changed when the COR or force-field potential changes.
00038   // Currently it is computed for 4.44 [GV] and 1100 [MV], respectively.
00039   // The integral should be done from lowE_* to highE_*.
00040   // FIX ME!!
00041   const G4double INTEGRAL_primary = 4.3643; // [m**-2 s**-1 Sr**-1]
00042 
00043 
00044   // gives v/c as a function of kinetic Energy
00045   inline G4double beta(G4double E /* GeV */)
00046   {
00047 #if 0   // if E ~ restE
00048     return sqrt(1 - pow(E/restE+1, -2));
00049 #else   // if E >> restE
00050     return 1.0;
00051 #endif
00052   }
00053 
00054 
00055   // gives rigidity (GV) as a function of kinetic Energy
00056   inline G4double rigidity(G4double E /* GeV */)
00057   {
00058 #if 0   // if E ~ restE
00059     return sqrt(pow(E + restE, 2) - pow(restE, 2));
00060 #else   // if E >> restE
00061     return E;
00062 #endif
00063   }
00064 
00065 
00066   // gives kinetic energy (GeV) as a function of rigidity
00067   inline G4double energy(G4double rigidity /* GV */)
00068   {
00069 #if 0   // if energy ~ restE
00070     return sqrt(pow(rigidity, 2) + pow(restE, 2)) - restE;
00071 #else   // if energy >> restE
00072     return rigidity;
00073 #endif
00074   }
00075 
00076 
00077 
00078   //=====================================================================
00107   const G4double A_primary = 7.23e-1;   // Normalization factor of the original spec.
00108   const G4double a_primary = 3.33;      // Differential spectral index
00109 
00110 
00111   // Geomagnetic cut off factor of primary cosmic rays
00112   inline G4double geomag_cut(G4double E /* GeV */, G4double cor /* GV */)
00113   {
00114     return 1./(1 + pow(rigidity(E)/cor, -12.0));
00115   }
00116 
00117 
00118   // Unmodulated cosmic ray spectrum outside the Solar system
00119   inline G4double org_spec(G4double E /* GeV */)
00120   {
00121     return A_primary * pow(rigidity(E), -a_primary);
00122   }
00123 
00124 
00125   // Force-field approximation of the Solar modulation
00126   inline G4double mod_spec(G4double E /* GeV */, G4double phi /* MV */)
00127   {
00128     return org_spec(E + phi * 1e-3) * (pow(E+restE, 2) - pow(restE, 2))
00129       / (pow(E+restE+phi*1e-3, 2) - pow(restE, 2));
00130   }
00131 
00132 
00133   // The property function that the primary component should obey.
00134   inline G4double primaryCRspec(G4double E /* GeV */, G4double cor /* GV */, G4double phi /* MV */)
00135   {
00136     return mod_spec(E, phi) * geomag_cut(E, cor) * beta(E);
00137   }
00138 
00139 
00140   // envelope function in lower energy
00141   // If we express rigidity as R, energy as E, cutoff rigidity as Rc,
00142   // and cutoff energy as Ec, geomagnetic cutoff function
00143   // is enveloped as follows.
00144   //=============================================================
00145   // 1/(1+(R/Rc)^-12.0) < (R/Rc)^12.0 < C * E^(a_envelope) / Rc^12.0
00146   //=============================================================
00147   // Here, C and a_primary are determined as
00148   //  R(lowE_primary)^12.0 = C*(lowE_primary)^(a_envelope)
00149   // and a_envelope is determined as
00150   //  (Rc/Rc)^12.0 = C * Ec^(a_envelope) / Rc^12.0
00151   inline G4double primaryCRenvelope1(G4double E /* GeV */, G4double cor /* GV */, G4double phi /* MV */)
00152   {
00153     G4double a_envelope =
00154       12.0*log(cor/rigidity(lowE_primary))/log(energy(cor));
00155     G4double A_envelope =
00156       pow(rigidity(lowE_primary),12.0)/pow(lowE_primary,a_envelope);
00157     return A_primary * A_envelope * pow(cor, -12.0) *
00158       pow(E, a_envelope - a_primary);
00159   }
00160 
00161 
00162   // integrated envelope function in lower energy
00163   inline G4double primaryCRenvelope1_integral(G4double E /* GeV */, G4double cor /* GV */, G4double phi /* MV */)
00164   {
00165     G4double a_envelope =
00166       12.0*log(cor/rigidity(lowE_primary))/log(energy(cor));
00167     G4double A_envelope =
00168       pow(rigidity(lowE_primary),12.0)/pow(lowE_primary,a_envelope);
00169     return A_primary * A_envelope * pow(cor, -12.0) *
00170       1./(a_envelope - a_primary + 1) * pow(E, a_envelope - a_primary + 1);
00171   }
00172 
00173 
00174   // inverse function of integrated envelope function in lower energy
00175   inline G4double primaryCRenvelope1_integral_rev(G4double value, G4double cor /* GV */, G4double phi /* MV */)
00176   {
00177     G4double a_envelope =
00178       12.0*log(cor/rigidity(lowE_primary))/log(energy(cor));
00179     G4double A_envelope =
00180       pow(rigidity(lowE_primary),12.0)/pow(lowE_primary,a_envelope);
00181     return pow( (a_envelope-a_primary+1) / (A_primary * A_envelope * pow(cor, -12.0))
00182                 * value, 1./(a_envelope-a_primary+1));
00183   }
00184 
00185 
00186   // envelope function in higher energy
00187   inline G4double primaryCRenvelope2(G4double E /* GeV */, G4double cor /* GV */, G4double phi /* MV */)
00188   {
00189     return A_primary * pow(E, -a_primary);
00190   }
00191 
00192 
00193   // integrated envelope function in higher energy
00194   inline G4double primaryCRenvelope2_integral(G4double E /* GeV */, G4double cor /* GV */, G4double phi /* MV */)
00195   {
00196     return A_primary * pow(E, -a_primary+1) / (-a_primary+1);
00197   }
00198 
00199 
00200   // inverse function of integrated envelope function in higher energy
00201   inline G4double primaryCRenvelope2_integral_rev(G4double value, G4double cor /* GV */, G4double phi /* MV */)
00202   {
00203     return pow(value * (-a_primary+1) / A_primary, 1./(-a_primary+1));
00204   }
00205 
00206 
00207   // The rundam number generator for the primary component.
00208   G4double primaryCRenergy(HepRandomEngine* engine, G4double cor, G4double solarPotential)
00209   {
00210     G4double rand_min_1 = primaryCRenvelope1_integral(lowE_primary, cor, solarPotential);
00211     G4double rand_max_1 = primaryCRenvelope1_integral(energy(cor), cor, solarPotential);
00212     G4double rand_min_2 = primaryCRenvelope2_integral(energy(cor), cor, solarPotential);
00213     G4double rand_max_2 = primaryCRenvelope2_integral(highE_primary, cor, solarPotential);
00214 
00215     //G4cerr << "rand_min_1: " << rand_min_1 << ", rand_max_1: " << rand_max_1 << ", ";
00216     //     << "rand_min_2: " << rand_min_2 << ", rand_max_2: " << rand_max_2 << G4endl;
00217 
00218     G4double envelope1_area = rand_max_1 - rand_min_1;
00219     G4double envelope2_area = rand_max_2 - rand_min_2;
00220 
00221     double r, E;
00222 
00223     while (1){
00224       if (engine->flat() <= envelope1_area / (envelope1_area + envelope2_area)){
00225         // envelope in lower energy
00226         r = engine->flat() * (rand_max_1 - rand_min_1) + rand_min_1;
00227         //G4cerr << "r: " << r << ", ";
00228         E = primaryCRenvelope1_integral_rev(r, cor, solarPotential);
00229         // G4cerr << "E: " << E << ", primarySpec: " << primaryCRspec(E, cor, solarPotential) << ", ";
00230         // G4cerr << "primaryEnvelope1: " << primaryCRenvelope1(E, cor, solarPotential) << G4endl;
00231         if (engine->flat() <= primaryCRspec(E, cor, solarPotential) / primaryCRenvelope1(E, cor, solarPotential))
00232           break;
00233       } else {
00234         // envelope in higher energy
00235         r = engine->flat() * (rand_max_2 - rand_min_2) + rand_min_2;
00236         // G4cerr << "r: " << r << ", ";
00237         E = primaryCRenvelope2_integral_rev(r, cor, solarPotential);
00238         // G4cerr << "E: " << E << ", primarySpec: " << primaryCRspec(E, cor, solarPotential) << ", ";
00239         // G4cerr << "primaryEnvelope2: " << primaryCRenvelope2(E, cor, solarPotential) << G4endl;
00240         if (engine->flat() <= primaryCRspec(E, cor, solarPotential) / primaryCRenvelope2(E, cor, solarPotential))
00241           break;
00242       }
00243     }
00244     return E;//THB * GeV;
00245   }
00246 } // End of noname-namespace: private function definitions.
00247 
00248 
00249 //
00250 //
00251 //
00252 
00253 CrElectronPrimary::CrElectronPrimary()
00254 {
00255   ;
00256 }
00257 
00258 
00259 CrElectronPrimary::~CrElectronPrimary()
00260 {
00261   ;
00262 }
00263 
00264 
00265 std::pair<double,double> CrElectronPrimary::dir(double energy, HepRandomEngine* engine) const
00266   // return: cos(zenith_angle) and azimuth [rad]
00267   // The downward has plus sign in cos(zenith_angle),
00268   // and azimuth = 0 from the east, +pi/2 from the north.
00269 {
00270   // Assuming isotropic from the upper (i.e. sky side) hemisphere.
00271   // With the cosine correction, the zenith-angle distribution should
00272   // be sin(theta).
00273 
00274   double  zenith_angle = acos(engine->flat());//THB * rad;
00275   double  azimuth      = engine->flat() * 2 * pi;
00276 
00277   return std::pair<double,double>(cos(zenith_angle), azimuth); //THB / rad);
00278 }
00279 
00280 
00281 
00282 double CrElectronPrimary::energySrc(HepRandomEngine* engine) const
00283 {
00284   return primaryCRenergy(engine, m_cutOffRigidity, m_solarWindPotential);
00285 }
00286 
00287 
00288 double CrElectronPrimary::flux() const
00289 {
00290   /*****
00291   // Integrated over the upper (sky-side) hemisphere.
00292   return  2 * pi * INTEGRAL_primary;  // [m**-2 s**-1]
00293   *****/
00294   // Integrated over the upper (sky-side) hemisphere.
00295   return  0.5 * INTEGRAL_primary;  // [m**-2 s**-1 Sr**-1]
00296 }
00297 
00298 
00299 double CrElectronPrimary::solidAngle() const
00300 {
00301   return  2 * pi;
00302 }
00303 
00304 
00305 const char* CrElectronPrimary::particleName() const
00306 {
00307   return "e-";
00308 }
00309 
00310 
00311 float CrElectronPrimary::operator()(float r)
00312 {
00313   HepJamesRandom  engine;
00314   engine.setSeed(r * 900000000);
00315   // 900000000 comes from HepJamesRandom::setSeed function's comment...
00316 
00317   return (float)energySrc(&engine);
00318 }
00319 
00320 
00321 double CrElectronPrimary::calculate_rate(double old_rate)
00322 {
00323   return  old_rate;
00324 }
00325 
00326 
00327 float CrElectronPrimary::flux(float latitude, float longitude) const
00328 {
00329   return  flux();
00330 }
00331 
00332 
00333 float CrElectronPrimary::flux(std::pair<double,double> coords) const
00334 {
00335   return  flux();
00336 }
00337 
00338 
00339 std::string CrElectronPrimary::title() const
00340 {
00341   return  "CrElectronPrimary";
00342 }
00343 
00344 
00345 float CrElectronPrimary::fraction(float energy)
00346 // This function doesn't work in this class... :-(
00347 {
00348   return  0;
00349 }
00350 
00351 
00352 std::pair<float,float> CrElectronPrimary::dir(float energy) const
00353 {
00354   HepJamesRandom  engine;
00355   std::pair<double,double>  d = dir(energy, &engine);
00356   return  std::pair<float,float>(d.first, d.second);
00357 }
00358 

Generated at Wed Nov 21 12:20:33 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000