BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSBunchUserFile.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 "BDSBunchUserFile.hh"
19#include "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSGlobalConstants.hh"
22#include "BDSIonDefinition.hh"
23#include "BDSParticleDefinition.hh"
24#include "BDSUtilities.hh"
25#include "BDSWarning.hh"
26
27#include "parser/beam.h"
28
29#include "G4IonTable.hh"
30#include "G4ParticleDefinition.hh"
31#include "G4ParticleTable.hh"
32#include "G4String.hh"
33
34#ifdef USE_GZSTREAM
35#include "src-external/gzstream/gzstream.h"
36#endif
37
38#include <algorithm>
39#include <fstream>
40#include <regex>
41#include <set>
42#include <string>
43#include <sstream>
44#include <vector>
45
46template <class T>
48 BDSBunchFileBased("userfile"),
49 nlinesIgnore(0),
50 nlinesSkip(0),
51 nLinesValidData(0),
52 particleMass(0),
53 lineCounter(0),
54 printedOutFirstTime(false),
55 anEnergyCoordinateInUse(false),
56 changingParticleType(false),
57 endOfFileReached(false),
58 matchDistrFileLength(false)
59{
60 ffact = BDSGlobalConstants::Instance()->FFact();
61 comment = std::regex("^\\s*\\#|\\!.*");
62}
63
64template<class T>
66{
68 if (distrFile.empty())
69 {throw BDSException("BDSBunchUserFile::CheckParameters", "No input file specified for userfile distribution");}
70}
71
72template<class T>
74{
75 CloseBunchFile();
76}
77
78template<class T>
80{
81 endOfFileReached = false;
82 if (!printedOutFirstTime)
83 {
84 G4cout << "BDSBunchUserFile::OpenBunchFile> opening " << distrFilePath << G4endl;
85 printedOutFirstTime = true;
86 }
87 lineCounter = 0;
88 InputBunchFile.open(distrFilePath);
89 if (!InputBunchFile.good())
90 {throw BDSException("BDSBunchUserFile::OpenBunchFile>", "Cannot open bunch file " + distrFilePath);}
91}
92
93template<class T>
95{
96 InputBunchFile.clear(); // igzstream doesn't reset eof flags when closing - do manually
97 InputBunchFile.close();
98 endOfFileReached = true;
99}
100
101template<class T>
103{
105
106 std::regex colons(":");
107 std::vector<std::string> results;
108 std::sregex_token_iterator iter(bunchFormat.begin(), bunchFormat.end(), colons, -1);
109 std::sregex_token_iterator end;
110 for (; iter != end; ++iter)
111 {
112 std::string res = (*iter).str();
113 results.push_back(res);
114 }
115 for (auto const& token : results)
116 {
117 G4String vari = "";
118 G4String rest = "";
119 if(token.substr(0,1)=="E" || token.substr(0,1)=="P")
120 {
122 if (token.substr(0,2)=="Ek")
123 {//Kinetic energy (longer name).
124 vari = token.substr(0,2);
125 rest = token.substr(2);
126 }
127 else
128 {
129 vari = token.substr(0,1);
130 rest = token.substr(1);
131 }
132 CheckAndParseUnits(vari, rest, BDS::ParseEnergyUnit);
133 }
134 else if (token.substr(0,1)=="t")
135 {
136 vari = token.substr(0, 1);
137 rest = token.substr(1);
138 CheckAndParseUnits(vari, rest, BDS::ParseTimeUnit);
139 }
140 else if ( ( token.substr(0,1)=="x" && token.substr(1,1)!="p" ) ||
141 ( token.substr(0,1)=="y" && token.substr(1,1)!="p" ) ||
142 ( token.substr(0,1)=="z" && token.substr(1,1)!="p" ) )
143 {
144 vari = token.substr(0,1);
145 rest = token.substr(1);
146 CheckAndParseUnits(vari, rest, BDS::ParseLengthUnit);
147 }
148 else if ( (token.substr(0,2)=="xp") ||
149 (token.substr(0,2)=="yp") ||
150 (token.substr(0,2)=="zp") )
151 {
152 vari = token.substr(0,2);
153 rest = token.substr(2);
154 CheckAndParseUnits(vari, rest, BDS::ParseAngleUnit);
155 }
156 else if (token.substr(0, 1) == "S")
157 {
158 vari = token.substr(0, 1);
159 rest = token.substr(1);
160 CheckAndParseUnits(vari, rest, BDS::ParseLengthUnit);
161 useCurvilinear = true;
162 }
163 else if(token.substr(0,5)=="pdgid")
164 {
166 sd.name="pdgid";
167 sd.unit=1;
168 fields.push_back(sd);
169 }
170 else if(token.substr(0,1)=="w")
171 {
172 sd.name="weight";
173 sd.unit=1;
174 fields.push_back(sd);
175 }
176 else if (token.substr(0,1)=="-")
177 {
178 // skip
179 sd.name="skip";
180 sd.unit=1;
181 fields.push_back(sd);
182 }
183 else
184 {
185 G4String message = "Cannot determine bunch data format. Failed at token: " + token;
186 throw BDSException(__METHOD_NAME__, message);
187 }
188 }
189
190 std::set<G4String> energyKeys = {"E", "Ek", "P"};
191 CheckConflictingParameters(energyKeys);
192
193 std::set<G4String> zKeys = {"z", "S"};
195}
196
197template <typename T>
198void BDSBunchUserFile<T>::CheckConflictingParameters(const std::set<G4String>& s) const
199{
200 auto inSet = [=](const G4String& v){return s.find(v) != s.end();};
201 auto inSetD = [=](const BDSBunchUserFile::Doublet& v){return inSet(v.name);};
202 int count = std::count_if(fields.begin(), fields.end(), inSetD);
203 if (count > 1)
204 {
205 G4String message = "More than one of the following set in user file columns (\"distrFileFormat\") ";
206 for (const auto& st : s)
207 {
208 message += st;
209 message += ", ";
210 }
211 message += "\nPossibly conflicting information. Ensure only one by skipping others with \"-\" symbol";
212 throw BDSException("BDSBunchUserFile::CheckConflictingParameters>", message);
213 }
214}
215
216template <typename T>
217template <typename U>
218void BDSBunchUserFile<T>::CheckAndParseUnits(const G4String& uName,
219 const G4String& rest,
220 U unitParser)
221{
223 if (rest.empty())
224 {
225 sd.name = uName;
226 sd.unit = 1.0;
227 fields.push_back(sd);
228 return;
229 }
230
231 G4int pos1 = (G4int)rest.find("[");
232 G4int pos2 = (G4int)rest.find("]");
233 if (pos1 < 0 || pos2 < 0)
234 {
235 G4String message = "Missing bracket [] in units of \"distrFileFormat\"\n";
236 message += "variable : \"" + uName + "\" and unit \"" + rest + "\"";
237 throw BDSException("BDSBunchUserFile::CheckAndParseUnits>", message);
238 }
239 else
240 {
241 G4String fmt = rest.substr(pos1 + 1, pos2 - 1);
242 sd.name = uName;
243 sd.unit = unitParser(fmt);
244 fields.push_back(sd);
245 }
246}
247
248template<class T>
249void BDSBunchUserFile<T>::skip(std::stringstream& ss, G4int nValues)
250{
251 G4double dummyValue;
252 for (G4int i = 0; i < nValues; i++)
253 {ReadValue(ss, dummyValue);}
254}
255
256template<class T>
258{
260 {
261 if (usualPrintOut)
262 {G4cout << "BDSBunchUserFile> ignoring " << nlinesIgnore << " lines" << G4endl;}
263 std::string line;
264 for (G4int i = 0; i < (G4int)nlinesIgnore; i++)
265 {
266 std::getline(InputBunchFile, line);
267 lineCounter++;
268 // we must check explicitly if we've gone past the end of the file
269 if (InputBunchFile.eof())
270 {
271 G4String msg = "end of file reached after line " + std::to_string(lineCounter);
272 msg += " before nlinesIgnore ("+std::to_string(nlinesIgnore)+") was reached.";
273 throw BDSException("BDSBunchUserFile::SkipNLinesIgnoreIntoFile>", msg);
274 }
275 }
276 }
277}
278
279template<class T>
280void BDSBunchUserFile<T>::SkipNLinesSkip(G4bool usualPrintOut)
281{
283 {
284 if (usualPrintOut)
285 {G4cout << "BDSBunchUserFile> skipping " << nlinesSkip << " valid lines" << G4endl;}
286
287 // We can read into the file safely without checking eof() because we know from earlier
288 // counting of the number of valid lines in the file that nlinesSkip is not beyond the
289 // end of the file (including nlinesIgnore).
290 std::string line;
291 G4int nLinesValidRead = 0;
292 while (nLinesValidRead < nlinesSkip)
293 {
294 std::getline(InputBunchFile, line);
295 if (SkippableLine(line))
296 {continue;}
297 nLinesValidRead++;
298 }
299 IncrementNEventsInFileSkipped((unsigned long long int)nlinesSkip);
300 }
301}
302
303template<class T>
305 const GMAD::Beam& beam,
306 const BDSBunchType& distrType,
307 G4Transform3D beamlineTransformIn,
308 const G4double beamlineSIn)
309{
310 BDSBunchFileBased::SetOptions(beamParticle, beam, distrType, beamlineTransformIn, beamlineSIn);
311 particleMass = beamParticle->Mass();
312 distrFile = beam.distrFile;
315 nlinesIgnore = (G4long)beam.nlinesIgnore;
316 nlinesSkip = (G4long)beam.nlinesSkip;
317 matchDistrFileLength = beam.distrFileMatchLength;
319}
320
321template<class T>
322G4bool BDSBunchUserFile<T>::SkippableLine(const std::string& line) const
323{
324 return std::all_of(line.begin(), line.end(), isspace) || std::regex_search(line, comment);
325}
326
327template<class T>
329{
332
333 std::string line;
334 G4long nLinesValid = 0;
335 while ( std::getline(InputBunchFile, line) )
336 {
337 if (SkippableLine(line))
338 {continue;} // don't count it
339 nLinesValid++;
340 }
342 return nLinesValid;
343}
344
345template<class T>
347{
348 nLinesValidData = CountNLinesValidDataInFile();
349
350 if (nLinesValidData < nlinesSkip)
351 {
352 G4String msg = "nlinesSkip is greater than the number of valid lines (" + std::to_string(nLinesValidData);
353 msg += ") in the user file \"" + distrFilePath + "\"";
354 throw BDSException("BDSBunchUserFile::Initialise>", msg);
355 }
356
358 G4bool nGenerateHasBeenSet = g->NGenerateSet();
359 G4int nEventsPerLoop = (G4int)(nLinesValidData - nlinesSkip);
360 nEventsInFile = nEventsPerLoop;
361 G4int nAvailable = nEventsPerLoop * distrFileLoopNTimes;
362 G4int nGenerate = g->NGenerate();
363 if (matchDistrFileLength)
364 {
365 if (!nGenerateHasBeenSet)
366 {
367 g->SetNumberToGenerate(nAvailable);
368 G4cout << "BDSBunchUserFile::Initialise> distrFileMatchLength is true -> simulating " << nEventsPerLoop << " events";
369 if (distrFileLoopNTimes > 1)
370 {G4cout << " " << distrFileLoopNTimes << " times";}
371 G4cout << G4endl;
372 if (g->Recreate())
373 {// have to do this now before the primary generator action is called already in the run
374 // we need to start the run with a number of events so we need to calculate here
375 G4int nEventsRemaining = nAvailable - g->StartFromEvent();
376 g->SetNumberToGenerate(nEventsRemaining);
377 G4cout << "BDSBunchUserFile::Initialise> distrFileMatchLength + recreation -> simulate the "
378 << nEventsRemaining << " lines left given startFromEvent including possible looping" << G4endl;
379 }
380 }
381 else
382 {// e.g. if recreating a lower number of events - match is on; but ngenerate is lower - must obey
383 G4cout << "BDSBunchUserFile::Initialise> matchDistrFileLength has been requested "
384 << "but ngenerate has been specified -> use ngenerate" << G4endl;
385 // note we don't need to take care of a recreation offset - this is done later in primary generator action
386 if (nGenerate > nAvailable)
387 {
388 G4String msg = "ngenerate (" + std::to_string(nGenerate) + ") is greater than the number of valid lines (";
389 msg += std::to_string(nLinesValidData) + ") and distrFileMatchLength is on.\nChange ngenerate to <= # lines";
390 msg += ", or don't specifcy ngenerate.\n";
391 msg += "This includes nlinesSkip.";
392 throw BDSException("BDSBunchUserFile::Initialise>", msg);
393 }
394 }
395 }
396 else
397 {
398 if ((nGenerate > nEventsPerLoop) && !distrFileLoop)
399 {
400 G4String msg = "ngenerate (" + std::to_string(nGenerate) + ") is greater than the number of valid lines (";
401 msg += std::to_string(nLinesValidData) + ") but distrFileLoop is false in the beam command";
402 throw BDSException("BDSBunchUserFile::Initialise>", msg);
403 }
404 }
408}
409
410template<class T>
412{
413 // If the end of the file is reached go back to the beginning of the file.
414 // this re-reads the same file again - must always print warning
415 G4cout << "BDSBunchUserFile> End of file reached." << G4endl;
417 if (distrFileLoop)
418 {
419 G4cout << "BDSBunchUserFile> Returning to beginning of file (including nlinesIgnore & nlinesSkip) for next event." << G4endl;
422 SkipNLinesSkip(false);
423 }
424 else
425 {throw BDSException(__METHOD_NAME__, "distrFileLoop off but requesting another set of coordinates.");}
426}
427
428template<class T>
430{
432 G4cout << "BDSBunchUserFile::RecreateAdvanceToEvent> Advancing file to event: " << eventOffset << G4endl;
433 G4int nEventsPerLoop = nLinesValidData - nlinesSkip;
434 G4int nAvailable = nEventsPerLoop * distrFileLoopNTimes;
435 G4int nEventsRemaining = nAvailable - eventOffset;
436 if (eventOffset > nEventsPerLoop)
437 {
438 if (distrFileLoop)
439 {
440 // we're recreating a file where we looped on the data - don't repeatedly read - just read up to
441 // the right point as if we'd looped the file
442 G4int nToRoll = eventOffset % nEventsPerLoop;
443 eventOffset = nToRoll;
444 }
445 else
446 {
447 G4String msg = "eventOffset (" + std::to_string(eventOffset) + ") is greater than the number of valid data lines in this file.\n";
448 msg += "This includes nlinesSkip.";
449 throw BDSException("BDSBunchUserFile::RecreateAdvanceToEvent>", msg);
450 }
451 }
452
453 G4int nGenerate = BDSGlobalConstants::Instance()->NGenerate();
454 if (nGenerate > nEventsRemaining && !distrFileLoop)
455 {
456 G4String msg = "ngenerate (" + std::to_string(nGenerate) + ") requested in recreate mode is greater than number\n";
457 msg += "of remaining valid lines in file (" + std::to_string(nEventsRemaining) + ") and distrFileLoop is turned off.";
458 throw BDSException("BDSBunchUserFile>", msg);
459 }
460 // note we cannot update ngenerate here as we're already being called from the primary
461 // generator action in the start of the event after BeamOn(nEvents) has been called
462 // therefore this adjustment for recreation + match is done earlier in this class
463
464 // we should now be completely safe to read into the file ignoring comment lines and
465 // without checking eof()
466 std::string line;
467 for (G4int i = 0; i < eventOffset; i++)
468 {
469 std::getline(InputBunchFile, line);
470 if (SkippableLine(line))
471 {continue;}
472 lineCounter++;
473 }
474}
475
476template<class T>
478{
479 // no looping - just read one particle from file
480 return GetNextParticle();
481}
482
483template<class T>
485{
486 if (InputBunchFile.eof() || InputBunchFile.fail())
487 {EndOfFileAction();}
488
489 G4double E = 0, Ek = 0, P = 0, x = 0, y = 0, z = 0, xp = 0, yp = 0, zp = 0, t = 0;
490 G4double weight = 1;
491 G4int type = 0;
492
493 G4bool zpdef = false; //keeps record whether zp has been read from file
494 G4bool tdef = false; //keeps record whether t has been read from file
495
496 // flag whether we're going to update the particle definition
497 G4bool updateParticleDefinition = false;
498
499 // read a whole line at a time for safety - no partially read lines
500 std::string line;
501 std::getline(InputBunchFile, line);
502 lineCounter++;
503
504 // skip empty lines and comment lines (starting with # or !)
505 G4bool lineIsBad = true;
506 while (lineIsBad)
507 {
508 if (SkippableLine(line))
509 {
510 if (InputBunchFile.eof() || InputBunchFile.fail())
511 {EndOfFileAction();}
512 else
513 {
514 std::getline(InputBunchFile, line);
515 lineCounter++;
516 continue;
517 }
518 }
519 else
520 {lineIsBad = false;}
521 }
522
523 // no check the line has the right number of 'words' in it ->
524 // split line on white space - doesn't inspect words themselves
525 // checks number of words, ie number of columns is correct
526 std::vector<std::string> results;
527 std::regex wspace("\\s+"); // any whitepsace
528 // -1 here makes it point to the suffix, ie the word rather than the wspace
529 std::sregex_token_iterator iter(line.begin(), line.end(), wspace, -1);
530 std::sregex_token_iterator end;
531 for (; iter != end; ++iter)
532 {
533 std::string res = (*iter).str();
534 results.push_back(res);
535 }
536
537 if (results.size() < fields.size())
538 {// ensure enough columns
539 std::string message = "Invalid line at line " + std::to_string(lineCounter) +
540 ". Expected " + std::to_string(fields.size()) +
541 " columns , but got " + std::to_string(results.size()) +
542 ".";
543 throw BDSException(__METHOD_NAME__, message);
544 }
545
546 std::stringstream ss(line);
547 for (auto it=fields.begin();it!=fields.end();it++)
548 {
549 if(it->name=="skip")
550 {double dummy; ReadValue(ss, dummy);}
551 else if(it->name=="Ek")
552 {ReadValue(ss, Ek); Ek *= (CLHEP::GeV * it->unit);}
553 else if(it->name=="E")
554 {ReadValue(ss, E); E *= (CLHEP::GeV * it->unit);}
555 else if(it->name=="P")
556 {ReadValue(ss, P); P *= (CLHEP::GeV * it->unit);}
557 else if(it->name=="t")
558 {ReadValue(ss, t); t *= (CLHEP::s * it->unit); tdef = true;}
559 else if(it->name=="x")
560 {ReadValue(ss, x); x *= (CLHEP::m * it->unit);}
561 else if(it->name=="y")
562 {ReadValue(ss, y); y *= (CLHEP::m * it->unit);}
563 else if(it->name=="z")
564 {ReadValue(ss, z); z *= (CLHEP::m * it->unit);}
565 else if(it->name=="xp") {ReadValue(ss, xp); xp *= ( CLHEP::radian * it->unit );}
566 else if(it->name=="yp") {ReadValue(ss, yp); yp *= ( CLHEP::radian * it->unit );}
567 else if(it->name=="zp") {ReadValue(ss, zp); zp *= ( CLHEP::radian * it->unit ); zpdef = true;}
568 else if(it->name=="pdgid")
569 {// particle type
570 ReadValue(ss, type);
571 updateParticleDefinition = true; // update particle definition after finished reading line
572 delete particleDefinition;
573 particleDefinition = nullptr;
574 }
575 else if (it->name == "S")
576 {
577 ReadValue(ss, z);
578 z *= CLHEP::m * it->unit;
579 }
580 else if(it->name=="weight")
581 {ReadValue(ss, weight);}
582 }
583
584 // coordinate checks
586 {
588 {// no checking here that only one variable is set - must ensure in this class
591 }
592 else // we must update this call of this function to ensure valid particle definition
593 {updateParticleDefinition = true;}
594 }
595 else // If energy isn't specified, use the central beam energy
596 {E = E0;}
597
598 // compute zp from xp and yp if it hasn't been read from file
599 xp += Xp0;
600 yp += Yp0;
601 if (!zpdef)
602 {zp = CalculateZp(xp,yp,1);}
603 // compute t from z if it hasn't been read from file
604 if (!tdef)
605 {t=0;} //TBC
606
607 if (updateParticleDefinition || changingParticleType)
608 {
609 // type is an int so FindParticle(int) is used here
610 G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
611 G4ParticleDefinition* g4ParticleDef = nullptr;
612 BDSIonDefinition* ionDef = nullptr;
613 if (type < 1e9) // not a pdg ion
614 {g4ParticleDef = particleTable->FindParticle(type);}
615 else
616 {
617 G4IonTable* ionTable = particleTable->GetIonTable();
618 G4int ionA, ionZ, ionLevel;
619 G4double ionE;
620 G4IonTable::GetNucleusByEncoding(type, ionZ, ionA, ionE, ionLevel);
621 ionDef = new BDSIonDefinition(ionA, ionZ, ionZ);
622 g4ParticleDef = ionTable->GetIon(ionDef->Z(), ionDef->A(), ionDef->ExcitationEnergy());
623 }
624
625 if (!g4ParticleDef)
626 {throw BDSException("BDSBunchUserFile> Particle \"" + std::to_string(type) + "\" not found");}
627 // Wrap in our class that calculates momentum and kinetic energy.
628 // Requires that one of E, Ek, P be non-zero (only one).
629 delete particleDefinition;
630 try
631 {
632 particleDefinition = new BDSParticleDefinition(g4ParticleDef, E, Ek, P, ffact, ionDef);
635 }
636 catch (const BDSException& e)
637 {// if we throw an exception the object is invalid for the delete on the next loop
638 particleDefinition = nullptr; // reset back to nullptr for safe delete
639 throw e; // rethrow
640 }
641 }
642
643 return BDSParticleCoordsFull(X0+x,Y0+y,Z0+z,xp,yp,zp,t,z,E,weight);
644}
645
646template <class T>
647template <typename Type>
648void BDSBunchUserFile<T>::ReadValue(std::stringstream& stream, Type& value)
649{
650 stream >> value;
651}
652
654
655#ifdef USE_GZSTREAM
656template class BDSBunchUserFile<igzstream>;
657#endif
658
659namespace BDS
660{
661G4double ParseEnergyUnit(const G4String& fmt)
662{
663 G4double unit= 1.0;
664 if (fmt == "TeV")
665 {unit = 1e3;}
666 else if (fmt == "GeV")
667 {unit = 1.0 ;}
668 else if (fmt == "MeV")
669 {unit = 1e-3;}
670 else if (fmt == "KeV")
671 {unit = 1e-6;}
672 else if (fmt == "eV")
673 {unit = 1e-9;}
674 else
675 {throw BDSException(__METHOD_NAME__, "Unrecognised energy unit! " +fmt);}
676 return unit;
677}
678
679G4double ParseLengthUnit(const G4String& fmt)
680{
681 G4double unit = 1.0;
682 if (fmt == "m")
683 {unit = 1;}
684 else if (fmt == "cm")
685 {unit = 1e-2;}
686 else if (fmt == "mm")
687 {unit = 1e-3;}
688 else if (fmt == "mum" || fmt == "um")
689 {unit = 1e-6;}
690 else if (fmt == "nm")
691 {unit = 1e-9;}
692 else
693 {throw BDSException(__METHOD_NAME__, "Unrecognised length unit! " + fmt);}
694 return unit;
695}
696
697G4double ParseAngleUnit(const G4String& fmt)
698{
699 G4double unit = 1.0;
700 if (fmt == "rad")
701 {unit = 1;}
702 else if (fmt == "mrad")
703 {unit = 1e-3;}
704 else if (fmt == "murad" || fmt == "urad")
705 {unit = 1e-6;}
706 else if (fmt == "nrad")
707 {unit=1e-9;}
708 else
709 {throw BDSException(__METHOD_NAME__, "Unrecognised angle unit! " + fmt);}
710 return unit;
711}
712
713G4double ParseTimeUnit(const G4String& fmt)
714{
715 G4double unit = 1.0;
716 if (fmt == "s")
717 {unit = 1;}
718 else if (fmt == "ms")
719 {unit = 1.e-3;}
720 else if (fmt == "mus" || fmt == "us")
721 {unit = 1e-6;}
722 else if (fmt == "ns")
723 {unit = 1e-9;}
724 else if (fmt == "mm/c")
725 {unit = (CLHEP::mm/CLHEP::c_light)/CLHEP::s;}
726 else if (fmt == "nm/c")
727 {unit = (CLHEP::nm/CLHEP::c_light)/CLHEP::s;}
728 else
729 {throw BDSException(__METHOD_NAME__, "Unrecognised time unit! " + fmt);}
730 return unit;
731}
732
733}
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().
A bunch distribution that reads a user specified column file.
void CheckConflictingParameters(const std::set< G4String > &s) const
Check conflicting columns aren't specified in file, e.g. P and Ek. Throw exception if wrong.
virtual void RecreateAdvanceToEvent(G4int eventOffset)
G4double ffact
Cache of flip factor from global constants.
void ReadValue(std::stringstream &stream, Type &value)
G4int lineCounter
Line counter.
G4long CountNLinesValidDataInFile()
void SkipNLinesSkip(G4bool usualPrintOut=true)
T InputBunchFile
The file handler. Templated as could be std::ifstream or igzstream for example.
G4bool SkippableLine(const std::string &line) const
Return true if a line is all whitespace or is commented out (starts with '#').
virtual BDSParticleCoordsFullGlobal GetNextParticleValid(G4int maxTries)
G4bool changingParticleType
Whether the particle type is a column.
void skip(std::stringstream &stream, G4int nvalues)
void SkipNLinesIgnoreIntoFile(G4bool usualPrintOut=true)
void ParseFileFormat()
Parse the column tokens and units factors.
G4long nlinesIgnore
Number of lines that will be ignored at the start the file.
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 distrFilePath
Bunch file including absolute path.
G4String bunchFormat
Format of the file.
G4long nlinesSkip
Number of lines that will be skipped after the nlinesIgnore.
G4double particleMass
Cache of nominal beam particle mass.
std::list< Doublet > fields
List of variables to parse on each line.
void CloseBunchFile()
Close the file handler.
virtual void CheckParameters()
virtual BDSParticleCoordsFull GetNextParticleLocal()
Get the next particle.
virtual void Initialise()
Open the file and skip lines.
G4String distrFile
Bunch file.
void OpenBunchFile()
Open the file and check it's open.
G4bool anEnergyCoordinateInUse
Whether Et, Ek or P are in the columns.
G4double Yp0
Centre of distributions.
Definition BDSBunch.hh:176
virtual void RecreateAdvanceToEvent(G4int eventOffset)
Definition BDSBunch.cc:279
G4bool particleDefinitionHasBeenUpdated
Definition BDSBunch.hh:202
G4bool useCurvilinear
Whether to ignore z and use s and transform for curvilinear coordinates.
Definition BDSBunch.hh:195
G4double Z0
Centre of distributions.
Definition BDSBunch.hh:172
G4double X0
Centre of distributions.
Definition BDSBunch.hh:170
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
BDSParticleCoordsFullGlobal GetNextParticle()
Definition BDSBunch.cc:261
static G4double CalculateZp(G4double xp, G4double yp, G4double Zp0)
Calculate zp safely based on other components.
Definition BDSBunch.cc:373
BDSParticleDefinition * particleDefinition
Particle definition for bunch - this class owns it.
Definition BDSBunch.hh:198
virtual void CheckParameters()
Definition BDSBunch.cc:222
General exception with possible name of object and message.
static BDSGlobalConstants * Instance()
Access method.
Class to parse an ion particle definition.
G4int A() const
Accessor.
G4double ExcitationEnergy() const
Accessor.
G4int Z() const
Accessor.
A set of particle coordinates in both local and global.
A set of particle coordinates including energy and weight.
Wrapper for particle definition.
G4double Mass() const
Accessor.
void SetEnergies(G4double totalEnergyIn, G4double kineticEnergyIn, G4double momentumIn)
G4double TotalEnergy() const
Accessor.
Improve type-safety of native enum data type in C++.
std::string distrFileFormat
beam parameters
Definition beamBase.h:52
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
Return either G4Tubs or G4CutTubs depending on flat face.
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4double ParseTimeUnit(const G4String &fmt)
G4double ParseEnergyUnit(const G4String &fmt)
G4double ParseAngleUnit(const G4String &fmt)
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
G4double ParseLengthUnit(const G4String &fmt)
Struct for name and unit pair.
G4double unit
relative to SI units, i.e. mm=0.001 etc.