19#include "BDSBunchUserFile.hh"
21#include "BDSException.hh"
22#include "BDSGlobalConstants.hh"
23#include "BDSIonDefinition.hh"
24#include "BDSParticleDefinition.hh"
25#include "BDSUtilities.hh"
26#include "BDSWarning.hh"
28#include "parser/beam.h"
30#include "G4IonTable.hh"
31#include "G4ParticleDefinition.hh"
32#include "G4ParticleTable.hh"
36#include "src-external/gzstream/gzstream.h"
57 printedOutFirstTime(false),
58 anEnergyCoordinateInUse(false),
59 changingParticleType(false),
60 matchDistrFileLength(false)
69 if (distrFile.empty())
70 {
throw BDSException(
"BDSBunchUserFile::CheckParameters",
"No input file specified for userfile distribution");}
82 if (!printedOutFirstTime)
84 G4cout <<
"BDSBunchUserFile::OpenBunchFile> opening " << distrFilePath << G4endl;
85 printedOutFirstTime =
true;
88 InputBunchFile.open(distrFilePath);
89 if (!InputBunchFile.good())
90 {
throw BDSException(
"BDSBunchUserFile::OpenBunchFile>",
"Cannot open bunch file " + distrFilePath);}
96 InputBunchFile.clear();
97 InputBunchFile.close();
105 std::regex colons(
":");
106 std::vector<std::string> results;
108 std::sregex_token_iterator end;
109 for (; iter != end; ++iter)
111 std::string res = (*iter).str();
112 results.push_back(res);
114 for (
auto const& token : results)
118 if(token.substr(0,1)==
"E" || token.substr(0,1)==
"P")
121 if(token.substr(0,2)==
"Ek")
123 vari = token.substr(0,2);
124 rest = token.substr(2);
128 vari = token.substr(0,1);
129 rest = token.substr(1);
133 else if(token.substr(0,1)==
"t")
135 vari = token.substr(0, 1);
136 rest = token.substr(1);
139 else if( ( token.substr(0,1)==
"x" && token.substr(1,1)!=
"p" ) ||
140 ( token.substr(0,1)==
"y" && token.substr(1,1)!=
"p" ) ||
141 ( token.substr(0,1)==
"z" && token.substr(1,1)!=
"p" ) )
143 vari = token.substr(0,1);
144 rest = token.substr(1);
147 else if ( (token.substr(0,2)==
"xp") ||
148 (token.substr(0,2)==
"yp") ||
149 (token.substr(0,2)==
"zp") )
151 vari = token.substr(0,2);
152 rest = token.substr(2);
155 else if (token.substr(0, 1) ==
"S")
157 vari = token.substr(0, 1);
158 rest = token.substr(1);
162 else if(token.substr(0,5)==
"pdgid")
169 else if(token.substr(0,1)==
"w")
175 else if (token.substr(0,1)==
"-")
184 G4String message =
"Cannot determine bunch data format. Failed at token: " + token;
189 std::set<G4String> energyKeys = {
"E",
"Ek",
"P"};
192 std::set<G4String> zKeys = {
"z",
"S"};
199 auto inSet = [=](
const G4String& v){
return s.find(v) != s.end();};
201 int count = std::count_if(
fields.begin(),
fields.end(), inSetD);
204 G4String message =
"More than one of the following set in user file columns (\"distrFileFormat\") ";
205 for (
const auto& st : s)
210 message +=
"\nPossibly conflicting information. Ensure only one by skipping others with \"-\" symbol";
211 throw BDSException(
"BDSBunchUserFile::CheckConflictingParameters>", message);
218 const G4String& rest,
230 G4int pos1 = rest.find(
"[");
231 G4int pos2 = rest.find(
"]");
232 if (pos1 < 0 || pos2 < 0)
234 G4String message =
"Missing bracket [] in units of \"distrFileFormat\"\n";
235 message +=
"variable : \"" + uName +
"\" and unit \"" + rest +
"\"";
236 throw BDSException(
"BDSBunchUserFile::CheckAndParseUnits>", message);
240 G4String fmt = rest.substr(pos1 + 1, pos2 - 1);
242 sd.unit = unitParser(fmt);
251 for (G4int i = 0; i < nValues; i++)
260 G4cout <<
"BDSBunchUserFile> ignoring " <<
nlinesIgnore <<
", skipping "
275 G4Transform3D beamlineTransformIn,
276 const G4double beamlineSIn)
297 std::regex comment(
"^\\#.*");
300 if (std::all_of(line.begin(), line.end(), isspace) || std::regex_search(line, comment))
312 if (matchDistrFileLength && !nGenerateHasBeenSet)
316 G4cout <<
"BDSBunchUserFile::Initialise> matchDistrFileLength is True -> simulation " << nGenerate <<
" events" << G4endl;
327 G4cout <<
"BDSBunchUserFile> End of file reached. Returning to beginning of file for next event." << G4endl;
336 G4cout <<
"BDSBunchUserFile::RecreateAdvanceToEvent> Advancing file to event: " << eventOffset << G4endl;
340 for (G4int i = 0; i < eventOffset; i++)
362 G4double E = 0, Ek = 0, P = 0, x = 0, y = 0, z = 0, xp = 0, yp = 0, zp = 0, t = 0;
366 G4bool zpdef =
false;
370 G4bool updateParticleDefinition =
false;
378 std::regex comment(
"^\\s*\\#|\\!.*");
379 G4bool lineIsBad =
true;
382 if (std::all_of(line.begin(), line.end(), isspace) || std::regex_search(line, comment))
400 std::vector<std::string> results;
401 std::regex wspace(
"\\s+");
403 std::sregex_token_iterator iter(line.begin(), line.end(), wspace, -1);
404 std::sregex_token_iterator end;
405 for (; iter != end; ++iter)
407 std::string res = (*iter).str();
408 results.push_back(res);
411 if (results.size() <
fields.size())
413 std::string message =
"Invalid line at line " + std::to_string(
lineCounter) +
414 ". Expected " + std::to_string(
fields.size()) +
415 " columns , but got " + std::to_string(results.size()) +
420 std::stringstream ss(line);
425 else if(it->name==
"Ek")
426 {
ReadValue(ss, Ek); Ek *= (CLHEP::GeV * it->unit);}
427 else if(it->name==
"E")
428 {
ReadValue(ss, E); E *= (CLHEP::GeV * it->unit);}
429 else if(it->name==
"P")
430 {
ReadValue(ss, P); P *= (CLHEP::GeV * it->unit);}
431 else if(it->name==
"t")
432 {
ReadValue(ss, t); t *= (CLHEP::s * it->unit); tdef =
true;}
433 else if(it->name==
"x")
434 {
ReadValue(ss, x); x *= (CLHEP::m * it->unit);}
435 else if(it->name==
"y")
436 {
ReadValue(ss, y); y *= (CLHEP::m * it->unit);}
437 else if(it->name==
"z")
438 {
ReadValue(ss, z); z *= (CLHEP::m * it->unit);}
439 else if(it->name==
"xp") {
ReadValue(ss, xp); xp *= ( CLHEP::radian * it->unit );}
440 else if(it->name==
"yp") {
ReadValue(ss, yp); yp *= ( CLHEP::radian * it->unit );}
441 else if(it->name==
"zp") {
ReadValue(ss, zp); zp *= ( CLHEP::radian * it->unit ); zpdef =
true;}
442 else if(it->name==
"pdgid")
445 updateParticleDefinition =
true;
447 else if (it->name ==
"S")
450 z *= CLHEP::m * it->unit;
452 else if(it->name==
"weight")
465 {updateParticleDefinition =
true;}
482 G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
483 G4ParticleDefinition* particleDef =
nullptr;
486 {particleDef = particleTable->FindParticle(type);}
489 G4IonTable* ionTable = particleTable->GetIonTable();
490 G4int ionA, ionZ, ionLevel;
492 G4IonTable::GetNucleusByEncoding(type, ionZ, ionA, ionE, ionLevel);
498 {
throw BDSException(
"BDSBunchUserFile> Particle \"" + std::to_string(type) +
"\" not found");}
519template <
typename Type>
536 if (fmt==
"TeV")
unit=1.e3;
537 else if(fmt==
"GeV")
unit=1;
538 else if(fmt==
"MeV")
unit=1.e-3;
539 else if(fmt==
"KeV")
unit=1.e-6;
540 else if(fmt==
"eV")
unit=1.e-9;
542 {
throw BDSException(__METHOD_NAME__,
"Unrecognised energy unit! " +fmt);}
550 else if(fmt==
"cm")
unit=1.e-2;
551 else if(fmt==
"mm")
unit=1.e-3;
552 else if(fmt==
"mum" || fmt==
"um")
unit=1.e-6;
553 else if(fmt==
"nm")
unit=1.e-9;
555 {
throw BDSException(__METHOD_NAME__,
"Unrecognised length unit! " + fmt);}
562 if(fmt==
"rad")
unit=1;
563 else if(fmt==
"mrad")
unit=1.e-3;
564 else if(fmt==
"murad" || fmt==
"urad")
unit=1.e-6;
565 else if(fmt==
"nrad")
unit=1.e-9;
567 {
throw BDSException(__METHOD_NAME__,
"Unrecognised angle unit! " + fmt);}
575 else if(fmt==
"ms")
unit=1.e-3;
576 else if(fmt==
"mus" || fmt==
"us")
unit=1.e-6;
577 else if(fmt==
"ns")
unit=1.e-9;
578 else if(fmt==
"mm/c")
unit=(CLHEP::mm/CLHEP::c_light)/CLHEP::s;
579 else if(fmt==
"nm/c")
unit=(CLHEP::nm/CLHEP::c_light)/CLHEP::s;
581 {
throw BDSException(__METHOD_NAME__,
"Unrecognised time unit! " + fmt);}
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)
void SkipLines()
Read lines according to nlinesIgnore.
G4int lineCounter
Line counter.
G4int nlinesIgnore
Number of lines that will be ignored at the start the file.
G4int CountLinesInFile()
Open the file, skip lines, then count number of lines, then close file again.
T InputBunchFile
The file handler. Templated as could be std::ifstream or igzstream for example.
G4int nlinesSkip
Number of lines that will be skipped after the nlinesIgnore.
virtual BDSParticleCoordsFullGlobal GetNextParticleValid(G4int maxTries)
G4bool changingParticleType
Whether the particle type is a column.
void skip(std::stringstream &stream, G4int nvalues)
void ParseFileFormat()
Parse the column tokens and units factors.
virtual void SetOptions(const BDSParticleDefinition *beamParticle, const GMAD::Beam &beam, const BDSBunchType &distrType, G4Transform3D beamlineTransformIn=G4Transform3D::Identity, const G4double beamlineS=0)
G4String distrFilePath
Bunch file including absolute path.
G4String bunchFormat
Format of the file.
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.
The base class for bunch distribution generators.
G4double Yp0
Centre of distributions.
G4bool particleDefinitionHasBeenUpdated
G4bool useCurvilinear
Whether to ignore z and use s and transform for curvilinear coordinates.
G4double Z0
Centre of distributions.
G4double X0
Centre of distributions.
G4double Xp0
Centre of distributions.
G4double E0
Centre of distributions.
G4double Y0
Centre of distributions.
virtual void SetOptions(const BDSParticleDefinition *beamParticle, const GMAD::Beam &beam, const BDSBunchType &distrType, G4Transform3D beamlineTransformIn=G4Transform3D::Identity, const G4double beamlineS=0)
BDSParticleCoordsFullGlobal GetNextParticle()
static G4double CalculateZp(G4double xp, G4double yp, G4double Zp0)
Calculate zp safely based on other components.
BDSParticleDefinition * particleDefinition
Particle definition for bunch - this class owns it.
virtual void CheckParameters()
General exception with possible name of object and message.
void SetNumberToGenerate(G4int number)
Setter.
static BDSGlobalConstants * Instance()
Access method.
Class to parse an ion particle definition.
G4double ExcitationEnergy() 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++.
bool matchDistrFileLength
beam parameters
std::string distrFileFormat
beam parameters
std::string distrFile
beam parameters
int nlinesIgnore
Ignore first lines in the input bunch file.
int nlinesSkip
Number of event lines to skip after the ignore lines.
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.