ATLAS Offline Software
Loading...
Searching...
No Matches
BeamHaloParticleBuffer.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
7#include "CLHEP/Random/RandFlat.h"
8#include <iostream>
9
10namespace{
11 char *
12 charAddress(auto &val){
13 return reinterpret_cast<char *> (&val);
14 }
15
16}
17
18//------------------------------------------------------------------------------
19
24
25//------------------------------------------------------------------------------
26
28 m_upperBinEdge = binnedInterval.m_upperBinEdge;
29 m_intervalUpperBinEdges = new std::vector<double>(*(binnedInterval.m_intervalUpperBinEdges));
30}
31
32//------------------------------------------------------------------------------
33
37
38//------------------------------------------------------------------------------
39
41 : m_fileName(fileName)
42 , m_ofstream()
43 , m_ifstream()
46 , m_upperBinEdge(0.)
49 , m_writeFlag(false) {
50 m_recordSize = sizeof(long) + sizeof(double)*8;
52}
53
54//------------------------------------------------------------------------------
55
57 m_writeFlag = true;
59 m_binnedIntervals.clear();
61
62 m_ofstream.open(m_fileName.c_str(), std::ios::out | std::ios::binary);
63 if(!m_ofstream) {
64 std::cerr << "Error: could not open output file" << m_fileName << std::endl;
65 return 1;
66 }
67
68 return 0;
69}
70
71//------------------------------------------------------------------------------
72
74 if(m_numberOfParticles <= 0) {
75 std::cerr << "Error: the number of particles in the input file is not known." << std::endl;
76 return 1;
77 }
78
79 m_writeFlag = false;
80
81 m_ifstream.open(m_fileName.c_str(), std::ios::in | std::ios::binary);
82 if(!m_ifstream) {
83 std::cerr << "Error: could not open input file" << m_fileName << std::endl;
84 return 1;
85 }
86
87 return 0;
88}
89
90//------------------------------------------------------------------------------
91
93 if(m_writeFlag) {
94 if(m_ofstream.is_open()) {
95 m_ofstream.close();
96
97 // Store the remaining bin edge vector.
98 if(m_intervalUpperBinEdges.size() > 0) {
100 m_binnedIntervals.push_back(binnedInterval);
103 }
104 }
105 }
106 else {
107 if(m_ifstream.is_open()) {
108 m_ifstream.close();
109 }
110 }
111
112 return 0;
113}
114
115//------------------------------------------------------------------------------
116
118 if(!m_writeFlag) {
119 std::cerr << "Error: the file " << m_fileName << " is currently open for reading." << std::endl;
120 return 0;
121 }
122
123 long pdgId = 0;
124 double px = 0., py = 0., pz = 0., e = 0., x = 0., y = 0., z = 0., t = 0., weight = 0.;
125
126 pdgId = particle->pdgId();
127 px = particle->fourVector().px();
128 py = particle->fourVector().py();
129 pz = particle->fourVector().pz();
130 e = particle->fourVector().e();
131 x = particle->positionAtScoringPlane().x();
132 y = particle->positionAtScoringPlane().y();
133 z = particle->positionAtScoringPlane().z();
134 t = particle->positionAtScoringPlane().t();
135 weight = particle->weight();
136
137 m_ofstream.write(charAddress(pdgId), sizeof(long)); if(m_ifstream.bad()) return 0;
138 m_ofstream.write(charAddress(px), sizeof(double)); if(m_ifstream.bad()) return 0;
139 m_ofstream.write(charAddress(py), sizeof(double)); if(m_ifstream.bad()) return 0;
140 m_ofstream.write(charAddress(pz), sizeof(double)); if(m_ifstream.bad()) return 0;
141 m_ofstream.write(charAddress(e), sizeof(double)); if(m_ifstream.bad()) return 0;
142 m_ofstream.write(charAddress(x), sizeof(double)); if(m_ifstream.bad()) return 0;
143 m_ofstream.write(charAddress(y), sizeof(double)); if(m_ifstream.bad()) return 0;
144 m_ofstream.write(charAddress(z), sizeof(double)); if(m_ifstream.bad()) return 0;
145 m_ofstream.write(charAddress(t), sizeof(double)); if(m_ifstream.bad()) return 0;
146 m_ofstream.write(charAddress(weight), sizeof(double)); if(m_ifstream.bad()) return 0;
147
149
150 // If 'm_particlesPerInterval' particles have been collected into
151 // this interval then push the interval into the map and clear the
152 // interval read for more particles.
155 m_binnedIntervals.push_back(binnedInterval);
158 }
159
160 // Append the weight to give the current upper bin edge. Then push
161 // the bin edge back.
162 m_intervalUpperBinEdge += weight;
164
165 // Increment the upper bin edge. This is a separate number to avoid
166 // problems relating to floating point precision which can cause
167 // (total weight) - (weight of particle) = (total weight)
168 // when the "total weight" is large and the "weight" is small. The
169 // solution is to factorise the problem into two steps:
170 // (1) "total weight", "weight of bin"
171 // (2) "total weight of bin", "weight of particle"
172 m_upperBinEdge += weight;
173
174 return 0;
175}
176
177//------------------------------------------------------------------------------
178
180 double generatedWeightSum;
181 bool found;
182 BeamHaloParticle *beamHaloParticle;
183
184 if(m_writeFlag) {
185 std::cerr << "Error: the file " << m_fileName << " is currently open for writing." << std::endl;
186 return 0;
187 }
188
189 if (!engine) {
190 std::cerr << "Error: the RandomEngine pointer is null." << std::endl;
191 return 0;
192 }
193
194 long particleIndex = 0;
195
196 // Generate a number between 0 and the total weight sum.
197 generatedWeightSum = CLHEP::RandFlat::shoot(engine)*m_upperBinEdge;
198
199 //std::cout << "Total weight sum = " << m_upperBinEdge << ", generated weight sum = " << generatedWeightSum << std::endl;
200
201 // Find the interval which corresponds to this weight sum.
202 std::vector<BinnedInterval>::iterator superBinItr = m_binnedIntervals.begin();
203 std::vector<BinnedInterval>::iterator superBinItr_end = m_binnedIntervals.end();
204 found = false;
205 while(superBinItr!=superBinItr_end && !found) {
206 //std::cout << "Upper bin edge = " << (*superBinItr).upperBinEdge() << std::endl;
207
208 // This works assuming the elements are correctly ordered.
209 if(generatedWeightSum <= (*superBinItr).upperBinEdge()) {
210 found = true;
211 }
212 else {
213 ++superBinItr;
214 particleIndex += (*superBinItr).intervalUpperBinEdges()->size();
215 }
216 }
217
218 // This should never happen.
219 if(!found) {
220 std::cerr << "Could not find an interval for the weight sum " << generatedWeightSum << std::endl;
221 return 0;
222 }
223
224 const std::vector<double> *intervalUpperBinEdges = (*superBinItr).intervalUpperBinEdges();
225
226 double intervalWeightSum = intervalUpperBinEdges->back();
227
228
229 // Generate a number between 0 and the total weight in this interval
230 generatedWeightSum = CLHEP::RandFlat::shoot(engine)*intervalWeightSum;
231
232 //std::cout << "Interval weight sum = " << intervalWeightSum << ", generated weight sum = " << generatedWeightSum << std::endl;
233
234 // Find the particle within this interval.
235 std::vector<double>::const_iterator intervalItr = intervalUpperBinEdges->begin();
236 std::vector<double>::const_iterator intervalItr_end = intervalUpperBinEdges->end();
237 found = false;
238 while(intervalItr!=intervalItr_end && !found) {
239 //std::cout << "Particle bin edge = " << (*intervalItr) << std::endl;
240
241 // This works assuming the elements are correctly ordered.
242 if(generatedWeightSum <= (*intervalItr)) {
243 found = true;
244 }
245 else {
246 ++intervalItr;
247 ++particleIndex;
248 }
249 }
250
251 // This should never happen.
252 if(!found) {
253 std::cerr << "Could not find a particle for the weight sum " << generatedWeightSum << std::endl;
254 return 0;
255 }
256
257 if(particleIndex >= m_numberOfParticles) {
258 std::cerr << "Particle index " << particleIndex << " is out of range." << std::endl;
259 return 0;
260 }
261
262 // Read this particle from the binary file.
263 m_ifstream.seekg(particleIndex*m_recordSize);
264 beamHaloParticle = readParticle();
265 if(!beamHaloParticle) return 0;
266
267 return beamHaloParticle;
268}
269
270//------------------------------------------------------------------------------
271
273 if(m_writeFlag) {
274 std::cerr << "Error: the file " << m_fileName << " is current open for writing." << std::endl;
275 return 0;
276 }
277
278 long pdgId = 0;
279 double px = 0., py = 0., pz = 0., e = 0., x = 0., y = 0., z = 0., t = 0., weight = 0.;
280
281 m_ifstream.read(charAddress(pdgId), sizeof(pdgId)); if(m_ifstream.bad()) return 0;
282 m_ifstream.read(charAddress(px), sizeof(px)); if(m_ifstream.bad()) return 0;
283 m_ifstream.read(charAddress(py), sizeof(py)); if(m_ifstream.bad()) return 0;
284 m_ifstream.read(charAddress(pz), sizeof(pz)); if(m_ifstream.bad()) return 0;
285 m_ifstream.read(charAddress(e), sizeof(e)); if(m_ifstream.bad()) return 0;
286 m_ifstream.read(charAddress(x), sizeof(x)); if(m_ifstream.bad()) return 0;
287 m_ifstream.read(charAddress(y), sizeof(y)); if(m_ifstream.bad()) return 0;
288 m_ifstream.read(charAddress(z), sizeof(z)); if(m_ifstream.bad()) return 0;
289 m_ifstream.read(charAddress(t), sizeof(t)); if(m_ifstream.bad()) return 0;
290 m_ifstream.read(charAddress(weight), sizeof(weight)); if(m_ifstream.bad()) return 0;
291
292 HepMC::FourVector fourVector(px,py,pz,e);
293 HepMC::FourVector positionAtScoringPlane(x,y,z,t);
294 BeamHaloParticle *beamHaloParticle = new BeamHaloParticle(pdgId, fourVector, positionAtScoringPlane, weight);
295
296 return beamHaloParticle;
297}
298
299//------------------------------------------------------------------------------
#define y
#define x
#define z
double m_intervalUpperBinEdge
The upper bin edge of a bin within a given interval.
BeamHaloParticle * readRandomParticle(CLHEP::HepRandomEngine *engine)
A member function to read a random particle from the binary file.
bool m_writeFlag
A flag to select read or write.
unsigned int m_particlesPerInterval
The number of particles per interval.
int writeParticle(BeamHaloParticle *particle)
A member function to append a particle to the binary file.
BeamHaloParticle * readParticle(void)
A member function to read a particle from the current position in the binary file.
BeamHaloParticleBuffer(const std::string &fileName)
std::ofstream m_ofstream
A data member to store the output file stream.
std::string m_fileName
File name.
double m_upperBinEdge
The upper edge of the bin.
std::vector< double > m_intervalUpperBinEdges
A vector of bin limits for a given interval.
std::vector< BinnedInterval > m_binnedIntervals
A map of the upper bin limits and an vector of bin limits within the given interval.
int m_recordSize
The size of 1 binary data record.
long m_numberOfParticles
The number of particles present within the output or input file.
std::ifstream m_ifstream
A data member to store the input file stream.
A class to describe a generic beam halo particle.
BinnedInterval(double upperBinEdge, const std::vector< double > &intervalUpperBinEdges)
const std::vector< double > * intervalUpperBinEdges() const
std::vector< double > * m_intervalUpperBinEdges
double upperBinEdge() const