Belle II Software development
CRY.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <generators/cry/CRY.h>
10
11#include <framework/gearbox/Unit.h>
12#include <framework/logging/Logger.h>
13#include <framework/utilities/IOIntercept.h>
14#include <mdst/dataobjects/MCParticleGraph.h>
15
16#include <Math/Vector3D.h>
17#include <Math/Vector4D.h>
18#include <TDatabasePDG.h>
19#include <TRandom3.h>
20
21#include <VecGeom/volumes/UnplacedBox.h>
22#include <VecGeom/volumes/UnplacedOrb.h>
23#include <VecGeom/volumes/UnplacedTube.h>
24#include <geometry/GeometryManager.h>
25#include "G4VPhysicalVolume.hh"
26#include "G4LogicalVolume.hh"
27#include "G4Box.hh"
28
29#include <string>
30#include <vector>
31#include <sstream>
32
33namespace Belle2 {
38 void CRY::init()
39 {
40 std::stringstream setupString;
41 setupString << " returnGammas " << m_returnGammas << std::endl;
42 setupString << " returnKaons " << m_returnKaons << std::endl;
43 setupString << " returnPions " << m_returnPions << std::endl;
44 setupString << " returnProtons " << m_returnProtons << std::endl;
45 setupString << " returnNeutrons " << m_returnNeutrons << std::endl;
46 setupString << " returnElectrons " << m_returnElectrons << std::endl;
47 setupString << " returnMuons " << m_returnMuons << std::endl;
48 setupString << " date " << m_date << std::endl;
49 setupString << " latitude " << 36.0 << std::endl;
50 setupString << " altitude " << 0 << std::endl;
51 setupString << " subboxLength " << m_subboxLength << std::endl;
52
54 initLogCapture.start();
55
56 // CRY setup
57 m_crySetup.reset(new CRYSetup(setupString.str(), m_cosmicDataDir));
58 // Set the random generator to the setup
59 m_crySetup->setRandomFunction([]()->double { return gRandom->Rndm(); });
60 // Set up the generator
61 m_cryGenerator.reset(new CRYGenerator(m_crySetup.get()));
62
63 initLogCapture.finish();
64
65 // set up the acceptance box
66 const auto coords = m_acceptSize.size();
67 if (coords == 1) {
68 m_acceptance.reset(new vecgeom::UnplacedOrb(m_acceptSize[0]));
69 } else if (coords == 2) {
70 m_acceptance.reset(new vecgeom::SUnplacedTube<vecgeom::TubeTypes::NonHollowTube>(0, m_acceptSize[0], m_acceptSize[1], 0, 2 * M_PI));
71 } else if (coords == 3) {
72 m_acceptance.reset(new vecgeom::UnplacedBox(m_acceptSize[0], m_acceptSize[1], m_acceptSize[2]));
73 } else {
74 B2FATAL("Acceptance volume needs to have one, two or three values for sphere, cylinder and box respectively");
75 }
76 //get information from geometry and create the world box
77 G4VPhysicalVolume* volume = geometry::GeometryManager::getInstance().getTopVolume();
78 if (!volume) {
79 B2FATAL("No geometry found -> Add the Geometry module to the path before the CRY module.");
80 }
81 G4Box* topbox = (G4Box*) volume->GetLogicalVolume()->GetSolid();
82 if (!topbox) {
83 B2FATAL("No G4Box found -> Check the logical volume of the geometry.");
84 }
85
86 // Wrap the world coordinates (G4 coordinates are mm, Belle 2 units are currently cm)
87 double halfLength_x = topbox->GetXHalfLength() * Belle2::Unit::mm;
88 double halfLength_y = topbox->GetYHalfLength() * Belle2::Unit::mm;
89 double halfLength_z = topbox->GetZHalfLength() * Belle2::Unit::mm;
90
91 // m_world.reset(new vecgeom::UnplacedBox(m_subboxLength / 2. * Unit::m, m_subboxLength / 2. * Unit::m,
92 // m_subboxLength / 2. * Unit::m));
93 m_world.reset(new vecgeom::UnplacedBox(halfLength_x / Unit::cm, halfLength_y / Unit::cm,
94 halfLength_z / Unit::cm));
95 B2INFO("World size [" << halfLength_x / Unit::cm << ", " << halfLength_x / Unit::cm << ", " << halfLength_x / Unit::cm << "]");
96
97 const double maxSize = *std::max_element(m_acceptSize.begin(), m_acceptSize.end());
98 const double minWorld = std::min({halfLength_x, halfLength_y, halfLength_z, });
99 if (maxSize > (minWorld / Unit::cm)) {
100 B2FATAL("Acceptance bigger than world volume " << LogVar("acceptance", maxSize)
101 << LogVar("World size", minWorld / Unit::cm));
102 }
103
104 }
105
107 {
108 bool eventInAcceptance = 0;
109 static std::vector<CRYParticle*> ev;
110
111 //force at least particle in acceptance box
112 for (int iTrial = 0; iTrial < m_maxTrials; ++iTrial) {
114 // Generate one event
115 ev.clear();
116 m_cryGenerator->genEvent(&ev);
117 // check all particles
118 for (auto* p : ev) {
119 const int pdg = p->PDGid();
120 const double kineticEnergy = p->ke() * Unit::MeV;
121 if (kineticEnergy < m_kineticEnergyThreshold) continue;
122
123 const double mass = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
124 const double etot = kineticEnergy + mass;
125 // since etot is at least mass this cannot be negative
126 const double ptot = sqrt(etot * etot - mass * mass);
127
128 // Momentum
129 // We have x horizontal, y up and z along the beam. So uvw -> zxy, xc yc zc -> zxy
130 const double px = ptot * p->v();
131 const double py = ptot * p->w();
132 const double pz = ptot * p->u();
133 // Vertex
134 const double vx = p->y() * Unit::m;
135 const double vy = p->z() * Unit::m;
136 const double vz = p->x() * Unit::m;
137
138 // Time
139 /* In basf2, it is assumed that t = 0 when an event was produced,
140 For the cosmic case, we set t = 0 when particle cross y=0 plane;
141 The output time from CRY (p->t()) is too large (order of second) and also
142 increase as simulated time, so it is impossible to handle in basf2.
143 For event which has more then one particle, the difference between their production
144 times is also too large (> micro-second) to keep in basf2, so the time relation
145 between particles in each event is also reset. Production of each particle in event is set t=0 at y=0.
146 if one need production from CRY for a special study, you have to find a way to handle it...*/
147 double time = 0;
148
149 vecgeom::Vector3D<double> pos(vx, vy, vz);
150 const ROOT::Math::PxPyPzEVector mom(px, py, pz, etot);
151 const ROOT::Math::XYZVector momVec(mom.Px(), mom.Py(), mom.Pz());
152 const auto momDir = momVec.Unit();
153 const double speed = (mass == 0 ? 1 : mom.Beta()) * Const::speedOfLight;
154
155 // Project on the boundary of the world box
156 auto inside = m_world->Inside(pos);
157 if (inside == vecgeom::kInside) {
158 // inside the world volume, go backwards in time to the world box
159 const vecgeom::Vector3D<double> dir(-momDir.X(), -momDir.Y(), -momDir.Z());
160 double dist = m_world->DistanceToOut(pos, dir);
161 pos += dist * dir;
162 time -= dist / speed;
163 } else if (inside == vecgeom::kOutside) {
164 // outside the world volume, go forwards in time to the world box
165 // this should not happen but better safe then sorry ...
166 const vecgeom::Vector3D<double> dir(momDir.X(), momDir.Y(), momDir.Z());
167 double dist = m_world->DistanceToIn(pos, dir);
168 if (dist == vecgeom::InfinityLength<double>()) continue;
169 pos += dist * dir;
170 time += dist / speed;
171 }
172 // Intersect with the acceptance box
173 const vecgeom::Vector3D<double> dir(momDir.X(), momDir.Y(), momDir.Z());
174 double dist = m_acceptance->DistanceToIn(pos, dir);
175 if (dist == vecgeom::InfinityLength<double>()) continue;
176
177 // We want to keep this one
178 auto& particle = mcGraph.addParticle();
179 // all particle of a generator are primary
180 particle.addStatus(MCParticle::c_PrimaryParticle);
181 // all particle of CRY are stable
182 particle.addStatus(MCParticle::c_StableInGenerator);
183 particle.setPDG(pdg);
184 particle.setFirstDaughter(0);
185 particle.setLastDaughter(0);
186 particle.setMomentum(momVec);
187 particle.setMass(mass);
188 particle.setEnergy(mom.E());
189 particle.setProductionVertex(ROOT::Math::XYZVector(pos.x(), pos.y(), pos.z()));
190 particle.setProductionTime(time);
191 eventInAcceptance = true;
192 }
193 // clean up CRY event
194 for (auto* p : ev) delete p;
195 // and if we have something in the acceptance then we're done
196 if (eventInAcceptance) {
197 return;
198 }
199
200 }
201 B2ERROR("Number of trials exceeds maxTrials increase number of maxTrials" << LogVar("maxTrials", m_maxTrials));
202 }
203
205 {
206 B2RESULT("Total time simulated: " << m_cryGenerator->timeSimulated() << " seconds");
207 B2RESULT("Total number of events simulated: " << m_totalTrials);
208 }
209
210
212}
bool m_returnElectrons
Whether or not CRY should return electrons.
Definition CRY.h:154
std::string m_cosmicDataDir
directory that holds cosmic data files.
Definition CRY.h:141
std::unique_ptr< vecgeom::VUnplacedVolume > m_acceptance
acceptance shape
Definition CRY.h:160
bool m_returnKaons
Whether or not CRY should return kaons.
Definition CRY.h:150
bool m_returnMuons
Whether or not CRY should return muons.
Definition CRY.h:155
int m_subboxLength
length of the square n-n plane in Cry in meters
Definition CRY.h:142
bool m_returnGammas
Whether or not CRY should return gammas.
Definition CRY.h:149
std::vector< double > m_acceptSize
Shape parameters for the acceptance shape.
Definition CRY.h:143
std::string m_date
date used for generation (month-day-year).
Definition CRY.h:146
std::unique_ptr< vecgeom::VUnplacedVolume > m_world
world box shape
Definition CRY.h:159
double m_kineticEnergyThreshold
kinetic energy threshold.
Definition CRY.h:145
std::unique_ptr< CRYGenerator > m_cryGenerator
The CRY generator.
Definition CRY.h:158
std::unique_ptr< CRYSetup > m_crySetup
The CRY generator setup.
Definition CRY.h:157
bool m_returnProtons
Whether or not CRY should return protons.
Definition CRY.h:152
bool m_returnNeutrons
Whether or not CRY should return neutrons.
Definition CRY.h:153
int m_totalTrials
total number of thrown events.
Definition CRY.h:148
bool m_returnPions
Whether or not CRY should return pions.
Definition CRY.h:151
int m_maxTrials
number of trials per event.
Definition CRY.h:147
static const double speedOfLight
[cm/ns]
Definition Const.h:695
bool start()
Start intercepting the output.
Capture stdout and stderr and convert into log messages.
bool finish()
Finish the capture and emit the message if output has appeard on stdout or stderr.
@ c_Debug
Debug: for code development.
Definition LogConfig.h:26
@ c_Warning
Warning: for potential problems that the user should pay attention to.
Definition LogConfig.h:29
Class to build, validate and sort a particle decay chain.
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition MCParticle.h:47
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
Definition MCParticle.h:49
static const double mm
[millimeters]
Definition Unit.h:70
static const double m
[meters]
Definition Unit.h:69
static const double MeV
[megaelectronvolt]
Definition Unit.h:114
static const double cm
Standard units with the value = 1.
Definition Unit.h:47
G4VPhysicalVolume * getTopVolume()
Return a pointer to the top volume.
static GeometryManager & getInstance()
Return a reference to the instance.
Class to store variables with their name which were sent to the logging service.
void init()
Initializes the generator.
Definition CRY.cc:38
void generateEvent(MCParticleGraph &mcGraph)
Generates one single event.
Definition CRY.cc:106
void term()
Terminates the generator.
Definition CRY.cc:204
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.