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