00001
00002
00003
00004
00005
00006
00007
00008 #include <CLHEP/Random/RandomEngine.h>
00009 #include <CLHEP/Random/JamesRandom.h>
00010
00011 #include "GeneratorInterface/CosmicMuonGenerator/interface/CMSCGEN.h"
00012
00013 CMSCGEN::CMSCGEN() : initialization(0), RanGen2(0), delRanGen(false)
00014 {
00015 }
00016
00017 CMSCGEN::~CMSCGEN()
00018 {
00019 if (delRanGen)
00020 delete RanGen2;
00021 }
00022
00023 int CMSCGEN::initialize(double pmin_in, double pmax_in, double thetamin_in, double thetamax_in, CLHEP::HepRandomEngine *rnd, bool TIFOnly_constant, bool TIFOnly_linear)
00024 {
00025 if (delRanGen)
00026 delete RanGen2;
00027 RanGen2 = rnd;
00028 delRanGen = false;
00029
00030
00031 TIFOnly_const = TIFOnly_constant;
00032 TIFOnly_lin = TIFOnly_linear;
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 cmin_in = - TMath::Cos(thetamin_in);
00047 cmax_in = - TMath::Cos(thetamax_in);
00048
00049
00050
00051 pmin_min = 3.;
00052
00053 pmin_max = 3000.;
00054 pmax = 3000.;
00055
00056
00057 cmax_max = -0.01,
00058 cmax_min = -0.9999;
00059
00060 if(TIFOnly_const == true || TIFOnly_lin == true) pmin_min = 0.;
00061
00062
00063 if(pmin_in < pmin_min || pmin_in > pmin_max){
00064 std::cout << " >>> CMSCGEN.initialize <<< warning: illegal pmin_in =" << pmin_in;
00065 return(-1);
00066 } else if(pmax_in > pmax ){
00067 std::cout << " >>> CMSCGEN.initialize <<< warning: illegal pmax_in =" << pmax_in;
00068 return(-1);
00069 }else{
00070 pmin = pmin_in;
00071 pmax = pmax_in;
00072 xemax = 1./(pmin*pmin);
00073 xemin = 1./(pmax*pmax);
00074 }
00075
00076
00077
00078 if(cmax_in < cmax_min || cmax_in > cmax_max)
00079 {
00080 std::cout << " >>> CMSCGEN.initialize <<< warning: illegal cmax_in =" << cmax_in;
00081 return(-1);
00082 }
00083 else
00084 {
00085 cmax = cmax_in;
00086 cmin = cmin_in;
00087 }
00088
00089
00090 initialization = 1;
00091
00092 if(TIFOnly_const == true || TIFOnly_lin == true) pmin_min = 3.;
00093
00094
00095 Lmin = log10(pmin);
00096 Lmax = log10(pmax);
00097 Lfac = 100./(Lmax-Lmin);
00098
00099
00100
00101
00102
00103 pe[0] = -1.;
00104 pe[1] = 6.22176;
00105 pe[2] = -13.9404;
00106 pe[3] = 18.1643;
00107 pe[4] = -9.22784;
00108 pe[5] = 1.99234;
00109 pe[6] = -0.156434;
00110 pe[7] = 0.;
00111 pe[8] = 0.;
00112
00113
00114
00115
00116
00117 b0c[0] = 0.6639;
00118 b0c[1] = -0.9587;
00119 b0c[2] = 0.2772;
00120
00121 b1c[0] = 5.820;
00122 b1c[1] = -6.864;
00123 b1c[2] = 1.367;
00124
00125 b2c[0] = 10.39;
00126 b2c[1] = -8.593;
00127 b2c[2] = 1.547;
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 c1 = -1.;
00144 c2 = -0.1;
00145
00146 double cemax0 = 1.0;
00147 double L, L2;
00148 double s;
00149 double p, p1, p2;
00150 double integral_here, integral_ref;
00151 double c_cut;
00152
00153 integrated_flux = 0.;
00154
00155 for(int k=1; k<=100; k++)
00156 {
00157 L = Lmin + (k-0.5)/Lfac;
00158 L2 = L*L;
00159 p = pow(10,L);
00160 p1 = pow(10,L-0.5/Lfac);
00161 p2 = pow(10,L+0.5/Lfac);
00162
00163 b0 = b0c[0] + b0c[1] * L + b0c[2]* L2;
00164 b1 = b1c[0] + b1c[1] * L + b1c[2]* L2;
00165 b2 = b2c[0] + b2c[1] * L + b2c[2]* L2;
00166
00167
00168
00169
00170
00171
00172 c_cut = -0.42 + L*0.35;
00173
00174 if (c_cut > c2) c_cut = c2;
00175
00176 integral_ref = b0 * (c_cut - c1)
00177 + b1/2. * (c_cut*c_cut - c1*c1)
00178 + b2/3. * (c_cut*c_cut*c_cut - c1*c1*c1);
00179
00180 if (c_cut > cmax) c_cut = cmax;
00181
00182 integral_here = b0 * (c_cut - cmin)
00183 + b1/2. * (c_cut*c_cut - cmin*cmin)
00184 + b2/3. * (c_cut*c_cut*c_cut - cmin*cmin*cmin);
00185
00186 corr[k] = integral_here/integral_ref;
00187
00188 s = (((((((pe[8]*L
00189 +pe[7])*L
00190 +pe[6])*L
00191 +pe[5])*L
00192 +pe[4])*L
00193 +pe[3])*L
00194 +pe[2])*L
00195 +pe[1])*L
00196 +pe[0];
00197
00198 integrated_flux += 1./pow(p,3) * s * corr[k] * (p2-p1);
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 }
00213
00214 integrated_flux *= 1.27E3;
00215 std::cout << " >>> CMSCGEN.initialize <<< " <<
00216 " Integrated flux = " << integrated_flux << " /m**2/s " << std::endl;
00217
00218
00219
00220
00221 double ce;
00222
00223 ce = (((((((pe[8]*2.
00224 +pe[7])*2.
00225 +pe[6])*2.
00226 +pe[5])*2.
00227 +pe[4])*2.
00228 +pe[3])*2.
00229 +pe[2])*2.
00230 +pe[1])*2.
00231 +pe[0];
00232
00233
00234
00235 ce = 0.5/ce;
00236
00237 for (int k=0; k<9; k++)
00238 {
00239 pe[k] = pe[k]*ce;
00240 }
00241
00242 cemax = cemax0*corr[50];
00243
00244 return initialization;
00245 }
00246
00247 int CMSCGEN::initialize(double pmin_in, double pmax_in, double thetamin_in, double thetamax_in, int RanSeed, bool TIFOnly_constant, bool TIFOnly_linear)
00248 {
00249 CLHEP::HepRandomEngine *rnd = new CLHEP::HepJamesRandom;
00250
00251 rnd->setSeed(RanSeed, 0);
00252 delRanGen = true;
00253 return initialize(pmin_in, pmax_in, thetamin_in, thetamax_in, rnd, TIFOnly_constant, TIFOnly_linear);
00254 }
00255
00256 int CMSCGEN::generate()
00257 {
00258
00259 if(initialization==0)
00260 {
00261 std::cout << " >>> CMSCGEN <<< warning: not initialized" << std::endl;
00262 return -1;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 double r1, r2, r3;
00280 double xe, e, ce, L, L2;
00281 int k;
00282 double prob;
00283
00284 double c_max;
00285 double z, z_max;
00286
00287 while (1)
00288 {
00289 prob = RanGen2->flat();
00290 r1 = double(prob);
00291 prob = RanGen2->flat();
00292 r2 = double(prob);
00293
00294 xe = xemin+r1*(xemax-xemin);
00295
00296 if( (1./sqrt(xe)<3) && TIFOnly_const == true) {
00297
00298 e=3.;
00299 L = log10(e);
00300 L2 = L*L;
00301
00302 ce = (((((((pe[8]*L
00303 +pe[7])*L
00304 +pe[6])*L
00305 +pe[5])*L
00306 +pe[4])*L
00307 +pe[3])*L
00308 +pe[2])*L
00309 +pe[1])*L
00310 +pe[0];
00311
00312 k = int ((L-Lmin)*Lfac+1.);
00313 k = TMath::Max(1,TMath::Min(k,100));
00314 ce = ce * corr[k];
00315
00316 e = 1./sqrt(xe);
00317 if(r2 < ( e*e*e*ce/(cemax*3.*3.*3.) )) break;
00318
00319 }else if( (1./sqrt(xe)<3) && TIFOnly_lin == true) {
00320
00321 e=3.;
00322 L = log10(e);
00323 L2 = L*L;
00324
00325 ce = (((((((pe[8]*L
00326 +pe[7])*L
00327 +pe[6])*L
00328 +pe[5])*L
00329 +pe[4])*L
00330 +pe[3])*L
00331 +pe[2])*L
00332 +pe[1])*L
00333 +pe[0];
00334
00335 k = int ((L-Lmin)*Lfac+1.);
00336 k = TMath::Max(1,TMath::Min(k,100));
00337 ce = ce * corr[k];
00338
00339 e = 1./sqrt(xe);
00340 if(r2 < ( e*e*e*e*ce/(cemax*3.*3.*3.*3.) )) break;
00341
00342 }else{
00343
00344 e = 1./sqrt(xe);
00345 L = log10(e);
00346 L2 = L*L;
00347
00348 ce = (((((((pe[8]*L
00349 +pe[7])*L
00350 +pe[6])*L
00351 +pe[5])*L
00352 +pe[4])*L
00353 +pe[3])*L
00354 +pe[2])*L
00355 +pe[1])*L
00356 +pe[0];
00357
00358 k = int ((L-Lmin)*Lfac+1.);
00359 k = TMath::Max(1,TMath::Min(k,100));
00360 ce = ce * corr[k];
00361
00362 if(cemax*r2 < ce) break;
00363
00364 }
00365 }
00366
00367 pq = e;
00368
00369
00370
00371
00372 prob = RanGen2->flat();
00373 r3 = double(prob);
00374
00375 double charg = 1.;
00376 if(r3 < 0.439) charg=-1.;
00377
00378 pq = pq*charg;
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 if(TIFOnly_const == true && e<3.){
00389 L = log10(3.);
00390 L2 = L*L;
00391 }
00392 if(TIFOnly_lin == true && e<3.){
00393 L = log10(3.);
00394 L2 = L*L;
00395 }
00396
00397 b0 = b0c[0] + b0c[1] * L + b0c[2]* L2;
00398 b1 = b1c[0] + b1c[1] * L + b1c[2]* L2;
00399 b2 = b2c[0] + b2c[1] * L + b2c[2]* L2;
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 c_max = -1.;
00416
00417 if(b2<0.) {
00418 c_max = - 0.5 * b1/b2;
00419 if(c_max < -1.) c_max = -1.;
00420 if(c_max > -0.1) c_max = -0.1;
00421 }
00422
00423 z_max = b0 + b1 * c_max + b2 * c_max * c_max;
00424
00425
00426 double c_cut = -0.42 + L*0.35;
00427 if (c_cut > cmax) c_cut = cmax;
00428
00429
00430
00431 while (1)
00432 {
00433 prob = RanGen2->flat();
00434 r1 = double(prob);
00435 prob = RanGen2->flat();
00436 r2 = double(prob);
00437 c = cmin + (c_cut-cmin)*r1;
00438 z = b0 + b1 * c + b2 * c*c;
00439 if (z > z_max*r2) break;
00440 }
00441
00442 return 0;
00443
00444 }
00445
00446
00447 double CMSCGEN::momentum_times_charge()
00448 {
00449
00450 if(initialization==1)
00451 {
00452 return pq;
00453 }
00454 else
00455 {
00456 std::cout << " >>> CMSCGEN <<< warning: not initialized" << std::endl;
00457 return -9999.;
00458 }
00459
00460 }
00461
00462 double CMSCGEN::cos_theta()
00463 {
00464
00465 if(initialization==1)
00466 {
00467
00468 return -c;
00469 }
00470 else
00471 {
00472 std::cout << " >>> CMSCGEN <<< warning: not initialized" << std::endl;
00473 return -0.9999;
00474 }
00475
00476 }
00477
00478 double CMSCGEN::flux()
00479 {
00480
00481 if(initialization==1)
00482 {
00483 return integrated_flux;
00484 }
00485 else
00486 {
00487 std::cout << " >>> CMSCGEN <<< warning: not initialized" << std::endl;
00488 return -0.9999;
00489 }
00490
00491 }
00492
00493
00494
00495 int CMSCGEN::initializeNuMu(double pmin_in, double pmax_in, double thetamin_in, double thetamax_in, double Enumin_in, double Enumax_in, double Phimin_in, double Phimax_in, double ProdAlt_in, CLHEP::HepRandomEngine *rnd)
00496 {
00497 if (delRanGen)
00498 delete RanGen2;
00499 RanGen2 = rnd;
00500 delRanGen = false;
00501
00502 ProdAlt = ProdAlt_in;
00503
00504 Rnunubar = 1.2;
00505
00506 sigma = (0.72*Rnunubar+0.09)/(1+Rnunubar)*1.e-38;
00507
00508 AR = (0.69+0.06*Rnunubar)/(0.09+0.72*Rnunubar);
00509
00510
00511
00512 pmin = pmin_in;
00513 pmax = pmax_in;
00514 cmin = TMath::Cos(thetamin_in);
00515 cmax = TMath::Cos(thetamax_in);
00516 enumin = (Enumin_in < 10.) ? 10. : Enumin_in;
00517 enumax = Enumax_in;
00518
00519
00520
00521 integrated_flux = 0.;
00522 dNdEmudEnuMax = 0.;
00523 negabs = 0.;
00524 negfrac = 0.;
00525 int trials = 100000;
00526 for (int i=0; i<trials; ++i) {
00527 double ctheta = cmin + (cmax-cmin)*RanGen2->flat();
00528 double Emu = pmin + (pmax-pmin)*RanGen2->flat();
00529 double Enu = enumin + (enumax-enumin)*RanGen2->flat();
00530 double rate = dNdEmudEnu(Enu, Emu, ctheta);
00531
00532
00533
00534
00535
00536 if (rate > 0.) {
00537 integrated_flux += rate;
00538 if (rate > dNdEmudEnuMax)
00539 dNdEmudEnuMax = rate;
00540 }
00541 else negabs++;
00542 }
00543 negfrac = negabs/trials;
00544 integrated_flux /= trials;
00545
00546 std::cout << "CMSCGEN::initializeNuMu: After " << trials << " trials:" << std::endl;
00547 std::cout << "dNdEmudEnuMax=" << dNdEmudEnuMax << std::endl;
00548 std::cout << "negfrac=" << negfrac << std::endl;
00549
00550
00551 integrated_flux *= (cmin-cmax);
00552 integrated_flux *= (Phimax_in-Phimin_in);
00553 integrated_flux *= (pmax-pmin);
00554 integrated_flux *= (enumax-enumin);
00555
00556 integrated_flux *= (1.-negfrac);
00557 std::cout << " >>> CMSCGEN.initializeNuMu <<< " <<
00558 " Integrated flux = " << integrated_flux << " units??? " << std::endl;
00559
00560
00561 initialization = 1;
00562
00563 return initialization;
00564
00565 }
00566
00567 int CMSCGEN::initializeNuMu(double pmin_in, double pmax_in, double thetamin_in, double thetamax_in, double Enumin_in, double Enumax_in, double Phimin_in, double Phimax_in, double ProdAlt_in, int RanSeed)
00568 {
00569 CLHEP::HepRandomEngine *rnd = new CLHEP::HepJamesRandom;
00570
00571 rnd->setSeed(RanSeed, 0);
00572 delRanGen = true;
00573 return initializeNuMu(pmin_in, pmax_in, thetamin_in, thetamax_in, Enumin_in, Enumax_in, Phimin_in, Phimax_in, ProdAlt_in, rnd);
00574 }
00575
00576
00577 double CMSCGEN::dNdEmudEnu(double Enu, double Emu, double ctheta) {
00578 double cthetaNu = 1. + ctheta;
00579 double thetas = asin(sin(acos(cthetaNu))*(Rearth-SurfaceOfEarth)/(Rearth+ProdAlt));
00580 double costhetas = cos(thetas);
00581 double dNdEnudW = 0.0286*pow(Enu,-2.7)*(1./(1.+(6.*Enu*costhetas)/115.)+0.213/(1.+(1.44*Enu*costhetas)/850.));
00582 double dNdEmudEnu = N_A*sigma/alpha*dNdEnudW*1./(1.+Emu/epsilon)*
00583 (Enu-Emu+AR/3*(Enu*Enu*Enu-Emu*Emu*Emu)/(Enu*Enu));
00584 return dNdEmudEnu;
00585 }
00586
00587
00588 int CMSCGEN::generateNuMu() {
00589 if(initialization==0)
00590 {
00591 std::cout << " >>> CMSCGEN <<< warning: not initialized" << std::endl;
00592 return -1;
00593 }
00594
00595 double ctheta, Emu;
00596 while (1) {
00597 ctheta = cmin + (cmax-cmin)*RanGen2->flat();
00598 Emu = pmin + (pmax-pmin)*RanGen2->flat();
00599 double Enu = enumin + (enumax-enumin)*RanGen2->flat();
00600 double rate = dNdEmudEnu(Enu, Emu, ctheta);
00601 if (rate > dNdEmudEnuMax*RanGen2->flat()) break;
00602 }
00603
00604 c = -ctheta;
00605
00606 pq = Emu;
00607
00608
00609
00610 double charg = 1.;
00611 if (RanGen2->flat() > Rnunubar/(1.+Rnunubar))
00612 charg = -1.;
00613
00614 pq = pq*charg;
00615
00616
00617
00618
00619 return 1;
00620 }