SND@LHC Software
Loading...
Searching...
No Matches
CosmicsGenerator.cxx
Go to the documentation of this file.
1// -------------------------------------------------------------------
2// ----- CosmicsGenerator source file for SHiP -----
3// ----- Version as of 15.09.15 by Martin Franke -----
4// ----- mailto: mfranke(at)physik.hu-berlin.de -----
5// -------------------------------------------------------------------
6
7#include "TROOT.h"
8#include "FairPrimaryGenerator.h"
9#include "CosmicsGenerator.h"
10#include "TDatabasePDG.h" // for TDatabasePDG
11#include "TMath.h"
12
13using namespace std;
14
15// ----- necessary functions -----------------------------------------
16double Co3Rng::fSpectrumL(double theta, double minE, Bool_t generateP = 1){
17 // 2 Options: a) generateP, b) calcInt
18 // see doi: 10.1016/j.nuclphysbps.2005.07.056. for flux details
19 // ad a) returns a random P between minE and 100GeV taken from the
20 // zenith angle dependend momentum distribution
21 // Here, the inverse of the function is computed and a random
22 // number between 0 and 1 mapped to the interval [minE, 100[ GeV
23 // ad b) return the momentum-integrated flux for a given zenith angle
24 // from minE to 100 GeV. Result in cm-2s-1
25
26 theta = 180*theta/TMath::Pi(); // theta in degrees
27 double a = -0.8816/10000 /(1/theta -0.1117/1000 * theta) - 0.1096 - 0.01966*TMath::Exp(-0.02040*theta);
28 double b = 0.4169/100 /(1/theta -0.9891/10000 * theta) + 4.0395 - 4.3118*TMath::Exp(0.9235/1000*theta);
29 double btilde = b + 1.0/TMath::Ln10();
30 double gamma = sqrt(-TMath::Ln10()*a);
31 double offset = 0.5*btilde/a;
32 double norm = TMath::Erf(gamma*(TMath::Log(100)+offset)) - TMath::Erf(gamma*(offset + TMath::Log(minE)));
33
34 if (generateP){
35 double r3 = rng->Uniform();
36 return exp(TMath::ErfInverse(r3*norm+TMath::Erf(gamma*(offset + TMath::Log(minE))))/gamma-offset);
37 }
38 else{
39 double c = -0.3516/1000 * theta*theta + 0.8861/100 * theta - 2.5985 -0.8745/100000*TMath::Exp(0.1457*theta);
40 double scale = 0.5*TMath::Sqrt(TMath::Pi())/gamma * TMath::Power(10,(-0.25/a*btilde*btilde + c));
41 return scale * norm;
42 }
43}
44
46 // check, if a given staring setup x,y,z,px,py,pz will lead to a
47 // close enough to the detector
48
49 if ((TMath::Abs(x-(y+yBox)*px/py) < xBox && TMath::Abs(z-z0-(y+yBox)*pz/py) < zBox) ||
50 (TMath::Abs(x-(y-yBox)*px/py) < xBox && TMath::Abs(z-z0-(y-yBox)*pz/py) < zBox) ||
51 (TMath::Abs(y-(x+xBox)*py/px) < yBox && TMath::Abs(z-z0-(x+xBox)*pz/px) < zBox) ||
52 (TMath::Abs(y-(x-xBox)*py/px) < yBox && TMath::Abs(z-z0-(x-xBox)*pz/px) < zBox)) {
53 return true;
54 }
55 return false;
56}
57
59 // generate starting conditions for CM until the DetectorBox is hit
60 do{
61 weighttest += weight; nTest++; //book keeping
62 //momentum components
63 double phi = fRandomEngine->Uniform(0,2*TMath::Pi());
64 theta = fRandomEngine->fTheta->GetRandom();
65 px = TMath::Sin(phi)*TMath::Sin(theta);
66 pz = TMath::Cos(phi)*TMath::Sin(theta);
67 py = -TMath::Cos(theta);
68 //staring location
70 z = fRandomEngine->Uniform(z0 - zdist/2, z0 + zdist/2);
71 }while(!DetectorBox());
72 nInside++;
73}
74// ----- Initiate the CMBG -----------------------------------------
75Bool_t CosmicsGenerator::Init(Bool_t largeMom){
76 //general
77 fRandomEngine = new Co3Rng();
78 TDatabasePDG* pdgBase = TDatabasePDG::Instance();
79 mass = pdgBase->GetParticle(13)->Mass(); // muons!
80 cout<<"----------------------------------------------------------------------"<<endl;
81 cout<<"configuration for the CMBG as defined in $FAIRSHIP/python/CMBG_conf.py: "<<endl;
82 cout<<"x_dist: "<<xdist<<endl;
83 cout<<"z_dist: "<<zdist<<endl;
84 cout<<"x_box: "<<xBox<<endl;
85 cout<<"y_box: "<<yBox<<endl;
86 cout<<"z_box: "<<zBox<<endl;
87 cout<<"n_EVENTS:"<<n_EVENTS<<endl;
88 cout<<"minE: "<<minE<<endl<<endl;
89 if (xdist*zdist*n_EVENTS == 0){cout<<"check the configuration for unphysical behavior."<<endl<<"We stop the execution."<<endl<<endl; return kFALSE;}
90
91 high = largeMom;
92 if (high) cout<<"Simulation for high momentum"<<endl;
93 else cout<<"Simulation for low momentum"<<endl;
94
95 // calculating weights for this run
96 // weight_flux: expected #muons per spill/ #simulated events per spill: FluxIntegral*xdist*zdist/EVENTS;
97 // the respective integrals are calculated from the fluxes
98 // weight_DetectorBox: only consider CM hitting the DetectorBox
99 // this is gained from a MC test of 10xEVENTS events
100 double weight_flux, weight_DetectorBox;
101 FluxIntegral = 0;
102 if (!high) { // momentum range 1 GeV - 100 GeV
103 if (minE > 100) {cout<<"choose minE < 100 !"<<endl; return kFALSE;}
104 double dt = TMath::Pi()/2/100;
105 for (double t= dt/2; t< TMath::Pi()/2; t += dt){
107 }
108 FluxIntegral = 2*TMath::Pi()/3*FluxIntegral*dt*10000;
109 cout<< "LowE CM flux with P < minE = "<<minE<<" : "<<FluxIntegral<< "m-2s-1"<<endl;
110 }
111 else { // momentum range 100 GeV - 1000 GeV
112 FluxIntegral = 2*TMath::Pi()/3*fRandomEngine->fSpectrumH->Integral(100,1000);
113 cout<< "HighE CM flux: "<<FluxIntegral<< "m-2s-1"<<endl;
114 }
115 weight_flux = FluxIntegral*xdist*zdist/n_EVENTS/10000;
116 nInside = 0; nTest = 0; weighttest = 0; // book keeping
117 y = 1900; //all muons start 19m over beam axis
118 for (; nInside < 10*n_EVENTS;){
120 }
121 weight_DetectorBox = 0.10 * nTest/n_EVENTS;
122 weight = weight_flux / weight_DetectorBox;
123 cout<<"weight_DetectorBox: "<< weight_DetectorBox<<", weight: "<< weight<<endl;
124 cout<<"----------------------------------------------------------------------"<<endl<<endl;
125 nInside = 0; nTest = 0; weighttest = 0; // book keeping
126
127 return kTRUE;
128}
129// ----- Passing the event -----------------------------------------
130Bool_t CosmicsGenerator::ReadEvent(FairPrimaryGenerator* cpg){
131 // muon or anti-muon
132 PID = 26*(fRandomEngine->Uniform(0,1) < 1.0/2.278) - 13;
133 // starting conditions
135 //momentum in the two regions, < or > 100 GeV
137 else P = fRandomEngine->fSpectrumH->GetRandom();
138 px = px*P;
139 py = py*P;
140 pz = pz*P;
141 // transfer to Geant4
142 cpg->AddTrack(PID,px,py,pz,x,y,z,-1,true,TMath::Sqrt(P*P+mass*mass),0,weight); // -1 = Mother ID, true = tracking, SQRT(x) = Energy, 0 = t
143 if (!nInside%10000){cout<<nInside/10000<<"10k events have been simulated"<<endl;}
144 return kTRUE;
145}
146// ---------------------------------------------------------------------
147
double fSpectrumL(double theta, double minE, Bool_t generateP)
TF1 * fSpectrumH
TRandom3 * rng
double Uniform(Float_t min, Float_t max)
Bool_t ReadEvent(FairPrimaryGenerator *)
virtual Bool_t Init(Bool_t largeMom)
ClassImp(ecalContFact) ecalContFact