BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSBunchPtc.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSBunchPtc.hh"
19#include "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSGlobalConstants.hh"
22#include "BDSParticleCoordsFull.hh"
23#include "BDSUtilities.hh"
24
25#include "parser/beam.h"
26
27#include "globals.hh"
28#include "G4String.hh"
29#include "G4Types.hh"
30
31#include "CLHEP/Units/PhysicalConstants.h"
32
33#include <array>
34#include <fstream>
35#include <regex>
36#include <string>
37#include <vector>
38
39
40BDSBunchPtc::BDSBunchPtc():
41 BDSBunchFileBased("ptc"),
42 matchDistrFileLength(false),
43 nRays(0),
44 iRay(0),
45 beta(1.0),
46 nlinesSkip(0),
47 lineCounter(0)
48{;}
49
50BDSBunchPtc::~BDSBunchPtc()
51{
52 ptcData.clear();
53}
54
56{
57 G4cout << "BDSBunchPtc::LoadPtcFile> opening " << fileName << G4endl;
58
59 // open file and read line by line and extract values
60 std::ifstream ifstr(fileName);
61
62 if (!ifstr)
63 {throw BDSException(__METHOD_NAME__, "\"" + fileName + "\" file doesn't exist - exiting as no input");}
64
65 std::string line;
66 lineCounter = 0;
67
68 for (G4int i = 0; i < nlinesSkip; i++)
69 {
70 std::getline(ifstr, line);
71 lineCounter++;
72 // we must check explicitly if we've gone past the end of the file
73 if (ifstr.eof())
74 {
75 G4String msg = "end of file reached on line " + std::to_string(lineCounter) + " before nlinesSkip + nlinesIgnore (";
76 msg += std::to_string(nlinesSkip) + " reached.";
77 throw BDSException(__METHOD_NAME__, msg);
78 }
79 }
80 IncrementNEventsInFileSkipped((unsigned long long int)nlinesSkip);
81
82 // create regular expressions
83 std::regex rex("\\sx\\s*=\\s*([0-9eE.+-]+)");
84 std::regex rey("\\sy\\s*=\\s*([0-9eE.+-]+)");
85 std::regex repx("px\\s*=\\s*([0-9eE.+-]+)");
86 std::regex repy("py\\s*=\\s*([0-9eE.+-]+)");
87 std::regex ret("\\st\\s*=\\s*([0-9eE.+-]+)");
88 std::regex rept("pt\\s*=\\s*([0-9eE.+-]+)");
89
90 // read single line
91 while (std::getline(ifstr,line))
92 {
93 lineCounter++;
94 int isComment = line.compare(0, 1, "!");
95 if (isComment == 0)
96 {continue;}
97 else
98 {
99 // variable for storage
100 double x = 0.0;
101 double y = 0.0;
102 double px = 0.0;
103 double py = 0.0;
104 double t = 0.0;
105 double pt = 0.0;
106
107 // return search match objects
108 std::smatch smx;
109 std::smatch smy;
110 std::smatch smpx;
111 std::smatch smpy;
112 std::smatch smt;
113 std::smatch smpt;
114
115 // perform search
116 std::regex_search(line,smx, rex);
117 std::regex_search(line,smy, rey);
118 std::regex_search(line,smpx,repx);
119 std::regex_search(line,smpy,repy);
120 std::regex_search(line,smt, ret);
121 std::regex_search(line,smpt, rept);
122
123 if(smx.size() == 2) x = std::stod(smx[1]);
124 if(smy.size() == 2) y = std::stod(smy[1]);
125 if(smpx.size() == 2) px = std::stod(smpx[1]);
126 if(smpy.size() == 2) py = std::stod(smpy[1]);
127 if(smt.size() == 2) t = std::stod(smt[1]);
128 if(smpt.size() == 2) pt = std::stod(smpt[1]);
129
130#ifdef BDSDEBUG
131 G4cout << __METHOD_NAME__ << "read line " << line << G4endl;
132 G4cout << __METHOD_NAME__ << "values " << x << " " << px << " " << y << " " << py << " " << t << " " << pt << G4endl;
133#endif
134 ptcData.emplace_back(std::array<double, 6>{x, px, y, py, t, pt});
135 }
136 }
137
138 // set number of available rays in options
139 nRays = (G4int)ptcData.size();
140}
141
143 const GMAD::Beam& beam,
144 const BDSBunchType& distrType,
145 G4Transform3D beamlineTransformIn,
146 const G4double beamlineSIn)
147{
148 BDSBunchFileBased::SetOptions(beamParticle, beam, distrType, beamlineTransformIn, beamlineSIn);
150 beta = beamParticle->Beta();
152 nlinesSkip = beam.nlinesSkip + beam.nlinesIgnore;
153}
154
156{
157 try
158 {LoadPtcFile();}
159 catch (BDSException& e)
160 {
161 std::string msg = "\nError on line " + std::to_string(lineCounter);
162 e.AppendToMessage(msg);
163 throw e;
164 }
165 catch (std::exception& e)
166 {
167 std::string msg = "Error on line " + std::to_string(lineCounter);
168 throw BDSException(__METHOD_NAME__, msg);
169 }
170
172 G4bool nGenerateHasBeenSet = g->NGenerateSet();
173 G4int nEventsPerLoop = nRays;
175 G4int nAvailable = nEventsPerLoop * distrFileLoopNTimes;
176 G4int nGenerate = g->NGenerate();
178 {
179 if (!nGenerateHasBeenSet)
180 {
181 g->SetNumberToGenerate(nAvailable);
182 G4cout << "BDSBunchPtc::Initialise> distrFileMatchLength is true -> simulating " << nRays << " events";
183 if (distrFileLoopNTimes > 1)
184 {G4cout << " " << distrFileLoopNTimes << " times";}
185 G4cout << G4endl;
186 if (g->Recreate())
187 {// have to do this now before the primary generator action is called already in the run
188 G4int nEventsRemaining = nAvailable - g->StartFromEvent();
189 g->SetNumberToGenerate(nEventsRemaining);
190 G4cout << "BDSBunchPtc::Initialise> distrFileMatchLength + recreation -> simulate the "
191 << nEventsRemaining << " lines left given startFromEvent including possible looping" << G4endl;
192 }
193 }
194 else
195 {// e.g. if recreating a lower number of events - match is on; but ngenerate is lower - must obey
196 G4cout << "BDSBunchPtc::Initialise> matchDistrFileLength has been requested "
197 << "but ngenerate has been specified -> use ngenerate" << G4endl;
198 // note we don't need to take care of a recreation offset - this is done later in primary generator action
199 if (nGenerate > nAvailable)
200 {
201 G4String msg = "ngenerate (" + std::to_string(nGenerate) + ") is greater than the number of valid lines (";
202 msg += std::to_string(nRays) + ") and distrFileMatchLength is on.\nChange ngenerate to <= # lines";
203 msg += ", or don't specifcy ngenerate.\n";
204 msg += "This includes nlinesSkip.";
205 throw BDSException("BDSBunchUserFile::Initialise>", msg);
206 }
207 }
208 }
209 else
210 {
211 if ( (nGenerate > nRays) && !distrFileLoop )
212 {
213 G4String msg = "ngenerate (" + std::to_string(nGenerate) + ") is greater than the number of inrays (";
214 msg += std::to_string(nRays) + ") but distrFileLoop is false in the beam command";
215 throw BDSException(__METHOD_NAME__, msg);
216 }
217 }
218}
219
221{
222 if ( iRay == nRays) // so that we're safe to still read the last entry
223 {
224 if (distrFileLoop)
225 {
226 iRay = 0;
227 G4cout << __METHOD_NAME__ << "End of file reached. Returning to beginning of file." << G4endl;
228 }
229 else
230 {throw BDSException(__METHOD_NAME__, "unable to read another event as file finished");}
231 }
232
233 G4double x = ptcData[iRay][0] * CLHEP::m + X0;
234 G4double y = ptcData[iRay][2] * CLHEP::m + Y0;
235 G4double z = ptcData[iRay][4] * CLHEP::m + Z0;
236 G4double xp = ptcData[iRay][1] * CLHEP::rad + Xp0;
237 G4double yp = ptcData[iRay][3] * CLHEP::rad + Yp0;
238 G4double t = (z-Z0)*CLHEP::m / CLHEP::c_light + T0 * CLHEP::s;
239 G4double zp = CalculateZp(xp,yp,Zp0);
240
241 G4double betaSquared = std::pow(beta,2.0);
242 G4double ptcVal = ptcData[iRay][5] * betaSquared;
243 G4double E = E0 * (ptcVal + 1.0);
244
245 BDSParticleCoordsFull result(x,y,z,xp,yp,zp,t,S0+z,E,/*weight=*/1.0);
246
247 iRay++;
248
249 return result;
250}
251
253{
254 G4int nAvailable = nRays * distrFileLoopNTimes;
255 G4int nEventsRemaining = nAvailable - eventOffset;
256 if (eventOffset >= nRays)
257 {
258 if (distrFileLoop)
259 {
260 G4int nToRoll = eventOffset % nRays;
261 eventOffset = nToRoll;
262 }
263 else
264 {
265 G4String msg = "eventOffset (" + std::to_string(eventOffset);
266 msg += ") is greater than the number of inrays in the PTC file";
267 throw BDSException(__METHOD_NAME__, msg);
268 }
269 }
270
271 iRay = eventOffset;
272 G4int nGenerate = BDSGlobalConstants::Instance()->NGenerate();
273 if (nGenerate > nEventsRemaining && !distrFileLoop)
274 {
275 G4String msg = "ngenerate (" + std::to_string(nGenerate) + ") requested in recreate mode is greater than number\n";
276 msg += "of remaining valid lines in file (" + std::to_string(nEventsRemaining) + ") and distrFileLoop is turned off.";
277 throw BDSException("BDSBunchPtc>", msg);
278 }
279 // note we cannot update ngenerate here as we're already being called from the primary
280 // generator action in the start of the event after BeamOn(nEvents) has been called
281 // therefore this adjustment for recreation + match is done earlier in this class
282}
An intermediate layer for any bunch classes that are file based.
unsigned long long int nEventsInFile
The number of entries in the file loaded.
virtual void SetOptions(const BDSParticleDefinition *beamParticle, const GMAD::Beam &beam, const BDSBunchType &distrType, G4Transform3D beamlineTransformIn=G4Transform3D::Identity, const G4double beamlineS=0)
Pull out the relevant options and then pass through to BDSBunch::SetOptions().
G4String fileName
File name.
virtual void RecreateAdvanceToEvent(G4int eventOffset)
void LoadPtcFile()
Load the PTC file into memory.
G4bool matchDistrFileLength
Whether to only run the number of particles in the file.
virtual BDSParticleCoordsFull GetNextParticleLocal()
G4int nRays
Number of rays in file (1 counting).
G4double beta
Velocity w.r.t. speed of light. Needed to convert mom. to energy.
virtual void Initialise()
Any initialisation - to be used after SetOptions, then CheckParameters.
G4int iRay
Iterator counter for current ray.
virtual void SetOptions(const BDSParticleDefinition *beamParticle, const GMAD::Beam &beam, const BDSBunchType &distrType, G4Transform3D beamlineTransformIn=G4Transform3D::Identity, const G4double beamlineS=0)
Pull out the relevant options and then pass through to BDSBunch::SetOptions().
std::vector< std::array< double, 6 > > ptcData
Data.
G4double Yp0
Centre of distributions.
Definition BDSBunch.hh:176
G4double T0
Centre of distributions.
Definition BDSBunch.hh:174
G4double S0
Centre of distributions.
Definition BDSBunch.hh:173
G4double Z0
Centre of distributions.
Definition BDSBunch.hh:172
G4double X0
Centre of distributions.
Definition BDSBunch.hh:170
G4double Zp0
Centre of distributions.
Definition BDSBunch.hh:177
G4double Xp0
Centre of distributions.
Definition BDSBunch.hh:175
G4double E0
Centre of distributions.
Definition BDSBunch.hh:178
G4double Y0
Centre of distributions.
Definition BDSBunch.hh:171
static G4double CalculateZp(G4double xp, G4double yp, G4double Zp0)
Calculate zp safely based on other components.
Definition BDSBunch.cc:373
General exception with possible name of object and message.
static BDSGlobalConstants * Instance()
Access method.
A set of particle coordinates including energy and weight.
Wrapper for particle definition.
G4double Beta() const
Accessor.
Improve type-safety of native enum data type in C++.
std::string distrFile
beam parameters
Definition beamBase.h:51
int nlinesIgnore
Ignore first lines in the input bunch file.
Definition beamBase.h:59
int nlinesSkip
Number of event lines to skip after the ignore lines.
Definition beamBase.h:60
bool distrFileMatchLength
beam parameters
Definition beamBase.h:54
Beam class.
Definition beam.h:43
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)