00001
00012 #include <math.h>
00013
00014
00015
00016
00017
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
00029 namespace {
00030 const G4double pi = 3.14159265358979323846264339;
00031 const G4double restE = 5.11e-4;
00032
00033 const G4double lowE_primary = 1.0;
00034 const G4double highE_primary = 100.0;
00035
00036
00037
00038
00039
00040
00041 const G4double INTEGRAL_primary = 4.3643;
00042
00043
00044
00045 inline G4double beta(G4double E )
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
00056 inline G4double rigidity(G4double E )
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
00067 inline G4double energy(G4double rigidity )
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;
00108 const G4double a_primary = 3.33;
00109
00110
00111
00112 inline G4double geomag_cut(G4double E , G4double cor )
00113 {
00114 return 1./(1 + pow(rigidity(E)/cor, -12.0));
00115 }
00116
00117
00118
00119 inline G4double org_spec(G4double E )
00120 {
00121 return A_primary * pow(rigidity(E), -a_primary);
00122 }
00123
00124
00125
00126 inline G4double mod_spec(G4double E , G4double phi )
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
00134 inline G4double primaryCRspec(G4double E , G4double cor , G4double phi )
00135 {
00136 return mod_spec(E, phi) * geomag_cut(E, cor) * beta(E);
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 inline G4double primaryCRenvelope1(G4double E , G4double cor , G4double phi )
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
00163 inline G4double primaryCRenvelope1_integral(G4double E , G4double cor , G4double phi )
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
00175 inline G4double primaryCRenvelope1_integral_rev(G4double value, G4double cor , G4double phi )
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
00187 inline G4double primaryCRenvelope2(G4double E , G4double cor , G4double phi )
00188 {
00189 return A_primary * pow(E, -a_primary);
00190 }
00191
00192
00193
00194 inline G4double primaryCRenvelope2_integral(G4double E , G4double cor , G4double phi )
00195 {
00196 return A_primary * pow(E, -a_primary+1) / (-a_primary+1);
00197 }
00198
00199
00200
00201 inline G4double primaryCRenvelope2_integral_rev(G4double value, G4double cor , G4double phi )
00202 {
00203 return pow(value * (-a_primary+1) / A_primary, 1./(-a_primary+1));
00204 }
00205
00206
00207
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
00216
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
00226 r = engine->flat() * (rand_max_1 - rand_min_1) + rand_min_1;
00227
00228 E = primaryCRenvelope1_integral_rev(r, cor, solarPotential);
00229
00230
00231 if (engine->flat() <= primaryCRspec(E, cor, solarPotential) / primaryCRenvelope1(E, cor, solarPotential))
00232 break;
00233 } else {
00234
00235 r = engine->flat() * (rand_max_2 - rand_min_2) + rand_min_2;
00236
00237 E = primaryCRenvelope2_integral_rev(r, cor, solarPotential);
00238
00239
00240 if (engine->flat() <= primaryCRspec(E, cor, solarPotential) / primaryCRenvelope2(E, cor, solarPotential))
00241 break;
00242 }
00243 }
00244 return E;
00245 }
00246 }
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
00267
00268
00269 {
00270
00271
00272
00273
00274 double zenith_angle = acos(engine->flat());
00275 double azimuth = engine->flat() * 2 * pi;
00276
00277 return std::pair<double,double>(cos(zenith_angle), azimuth);
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
00292
00293
00294
00295 return 0.5 * INTEGRAL_primary;
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
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
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