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 - 2023.
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.
Definition: BDSBunchPtc.hh:59
virtual void RecreateAdvanceToEvent(G4int eventOffset)
Definition: BDSBunchPtc.cc:253
void LoadPtcFile()
Load the PTC file into memory.
Definition: BDSBunchPtc.cc:56
G4bool matchDistrFileLength
Whether to only run the number of particles in the file.
Definition: BDSBunchPtc.hh:57
virtual BDSParticleCoordsFull GetNextParticleLocal()
Definition: BDSBunchPtc.cc:221
G4int nRays
Number of rays in file (1 counting).
Definition: BDSBunchPtc.hh:58
G4double beta
Velocity w.r.t. speed of light. Needed to convert mom. to energy.
Definition: BDSBunchPtc.hh:62
virtual void Initialise()
Any initialisation - to be used after SetOptions, then CheckParameters.
Definition: BDSBunchPtc.cc:156
G4int iRay
Iterator counter for current ray.
Definition: BDSBunchPtc.hh:60
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().
Definition: BDSBunchPtc.cc:143
std::vector< std::array< double, 6 > > ptcData
Data.
Definition: BDSBunchPtc.hh:61
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:367
General exception with possible name of object and message.
Definition: BDSException.hh:35
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)