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

CrProtonPrimary.cxx

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

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