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