00001
00010 #include <cmath>
00011
00012
00013
00014
00015
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
00027 namespace {
00028 const G4double pi = 3.14159265358979323846264339;
00029
00030 const G4double restE = 0.938;
00031
00032 const G4double lowE_primary = 1.0;
00033 const G4double highE_primary = 100.0;
00034
00035
00036
00037
00038
00039
00040
00041
00042 const G4double INTEGRAL_primary = 329.67;
00043
00044
00045
00046
00047 inline G4double beta(G4double E ){
00048 return sqrt(1 - pow(E/restE+1, -2));
00049 }
00050
00051
00052 inline G4double rigidity(G4double E ){
00053 return sqrt(pow(E + restE, 2) - pow(restE, 2));
00054 }
00055
00056
00057 inline G4double energy(G4double rigidity ){
00058 return sqrt(pow(rigidity, 2) + pow(restE, 2)) - restE;
00059 }
00060
00061
00090 const G4double A_primary = 16.9;
00091 const G4double a_primary = 2.79;
00092
00093
00094
00095
00096 inline G4double geomag_cut(G4double E, G4double cor ){
00097 return 1./(1 + pow(rigidity(E)/cor, -12.0));
00098 }
00099
00100
00101 inline G4double org_spec(G4double E )
00102 {
00103 return A_primary * pow(rigidity(E), -a_primary);
00104 }
00105
00106
00107 inline G4double mod_spec(G4double E , G4double phi ){
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
00113 inline G4double primaryCRspec(G4double E , G4double cor , G4double phi ){
00114 return mod_spec(E, phi) * geomag_cut(E, cor) * beta(E);
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 inline G4double primaryCRenvelope1(G4double E , G4double cor , G4double phi ){
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
00138 inline G4double primaryCRenvelope1_integral
00139 (G4double E , G4double cor , G4double phi ){
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
00149
00150 inline G4double primaryCRenvelope1_integral_inv
00151 (G4double value, G4double cor , G4double phi ){
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
00161 inline G4double primaryCRenvelope2(G4double E , G4double cor , G4double phi ){
00162 return A_primary * pow(E, -a_primary);
00163 }
00164
00165
00166 inline G4double primaryCRenvelope2_integral(G4double E , G4double cor , G4double phi ){
00167 return A_primary/(-a_primary+1) * pow(E, -a_primary+1);
00168 }
00169
00170
00171
00172 inline G4double primaryCRenvelope2_integral_inv(G4double value, G4double cor , G4double phi ){
00173 return pow((-a_primary+1)/ A_primary * value , 1./(-a_primary+1));
00174 }
00175
00176
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
00188
00189
00190
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;
00197 while(1){
00198 if (engine->flat() <= envelope1_area/(envelope1_area + envelope2_area)){
00199
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
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;
00214 }
00215
00216
00217 }
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
00238
00239
00240 {
00241
00242
00243
00244
00245 double zenith_angle = acos(engine->flat());
00246 double azimuth = engine->flat() * 2 * pi;
00247
00248 return std::pair<double,double>(cos(zenith_angle), azimuth);
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
00262
00263
00264
00265 return 0.5 * INTEGRAL_primary;
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
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
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