BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSPrimaryGeneratorAction.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
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 "BDSBunch.hh"
20#include "BDSBunchEventGenerator.hh"
21#include "BDSDebug.hh"
22#include "BDSEventInfo.hh"
23#include "BDSException.hh"
24#include "BDSExtent.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSIonDefinition.hh"
27#include "BDSOutputLoader.hh"
28#include "BDSParticleDefinition.hh"
29#include "BDSPhysicsUtilities.hh"
30#include "BDSPrimaryGeneratorAction.hh"
31#include "BDSPrimaryVertexInformation.hh"
32#include "BDSPTCOneTurnMap.hh"
33#include "BDSROOTSamplerReader.hh"
34#include "BDSRandom.hh"
35#include "BDSUtilities.hh"
36
37#ifdef USE_HEPMC3
38#include "BDSHepMC3Reader.hh"
39#endif
40
41#include "parser/beam.h"
42
43#include "CLHEP/Random/Random.h"
44
45#include "globals.hh" // geant4 types / globals
46#include "G4Event.hh"
47#include "G4HEPEvtInterface.hh"
48#include "G4IonTable.hh"
49#include "G4ParticleGun.hh"
50#include "G4ParticleDefinition.hh"
51
53 const GMAD::Beam& beam):
54 bunch(bunchIn),
55 recreateFile(nullptr),
56 eventOffset(0),
57 ionPrimary(bunchIn->BeamParticleIsAnIon()),
58 useEventGeneratorFile(false),
59 useSamplerLoader(false),
60 ionCached(false),
61 oneTurnMap(nullptr)
62#ifdef USE_HEPMC3
63 ,
64 hepMC3Reader(nullptr)
65#endif
66 ,
67 samplerReader(nullptr)
68{
69 particleGun = new G4ParticleGun(1); // 1-particle gun
70
73 useASCIISeedState = BDSGlobalConstants::Instance()->UseASCIISeedState();
74
75 if (recreate)
76 {
78 eventOffset = BDSGlobalConstants::Instance()->StartFromEvent();
80 }
81
82 particleGun->SetParticleMomentumDirection(G4ThreeVector(0.,0.,1.));
83 particleGun->SetParticlePosition(G4ThreeVector(0.*CLHEP::cm,0.*CLHEP::cm,0.*CLHEP::cm));
84 particleGun->SetParticleTime(0);
85
86 BDSBunchType egf = BDSBunchType::eventgeneratorfile;
87 useEventGeneratorFile = BDS::StrContains(G4String(beam.distrType), egf.ToString());
88 BDSBunchType samp = BDSBunchType::bdsimsampler;
89 useSamplerLoader = BDS::StrContains(beam.distrType, samp.ToString());
90
92 {
93#ifdef USE_HEPMC3
94 if (beam.distrFile.empty())
95 {throw BDSException(__METHOD_NAME__, "no distrFile specified for event generator beam distribution.");}
96 G4String filename = BDS::GetFullPath(beam.distrFile, false, beam.distrFileFromExecOptions);
97 BDSBunchEventGenerator* beg = dynamic_cast<BDSBunchEventGenerator*>(bunchIn);
98 if (!beg)
99 {throw BDSException(__METHOD_NAME__, "must be used with a BDSBunchEventGenerator instance");}
102 if (recreate)
104#else
105 throw BDSException(__METHOD_NAME__, "event generator file being used but BDSIM not compiled with HEPMC3");
106#endif
107 }
108 else if (useSamplerLoader)
109 {
110 if (beam.distrFile.empty())
111 {throw BDSException(__METHOD_NAME__, "no distrFile specified for event generator beam distribution.");}
112 G4String filename = BDS::GetFullPath(beam.distrFile, false, beam.distrFileFromExecOptions);
113 BDSBunchEventGenerator* beg = dynamic_cast<BDSBunchEventGenerator*>(bunchIn);
114 if (!beg)
115 {throw BDSException(__METHOD_NAME__, "must be used with a BDSBunchEventGenerator instance");}
116 samplerReader = new BDSROOTSamplerReader(beam.distrType, filename, beg, beam.eventGeneratorWarnSkippedParticles);
117 }
118}
119
120BDSPrimaryGeneratorAction::~BDSPrimaryGeneratorAction()
121{
122 delete particleGun;
123 delete recreateFile;
124#ifdef USE_HEPMC3
125 delete hepMC3Reader;
126#endif
127 delete samplerReader;
128}
129
131{
132 // load seed state if recreating.
133 if (recreate)
134 {
135 G4cout << __METHOD_NAME__ << "setting seed state from file" << G4endl;
136 BDSRandom::SetSeedState(recreateFile->SeedState(anEvent->GetEventID() + eventOffset));
137 }
138
139 // save the seed state in a file to recover potentially unrecoverable events
141 {BDSRandom::WriteSeedState();}
142
145 {
146 G4String fileName = globals->SeedStateFileName();
147 BDSRandom::LoadSeedState(fileName);
148 }
149
150 // always save seed state in output
151 BDSEventInfo* eventInfo = new BDSEventInfo();
152 anEvent->SetUserInformation(eventInfo);
153 eventInfo->SetSeedStateAtStart(BDSRandom::GetSeedState());
154
155#ifdef USE_HEPMC3
157 {
158 hepMC3Reader->GeneratePrimaryVertex(anEvent);
159 return; // don't need any further steps
160 }
161#endif
163 {
164 samplerReader->GeneratePrimaryVertex(anEvent);
165 return; // don't need any further steps
166 }
167
168 // update particle definition in the special case of an ion - can only be done here
169 // and not before due to Geant4 ion information availability only at run time
170 if (ionPrimary && !ionCached)
171 {
173 ionCached = true;
174 }
175
176 // generate set of coordinates - internally the bunch may try many times to generate
177 // coordinates with total energy above the rest mass and may throw an exception if
178 // it can't
180 try
181 {coords = bunch->GetNextParticleValid();}
182 catch (const BDSException& exception)
183 {// we couldn't safely generate a particle -> abort
184 // could be because of user input file
185 anEvent->SetEventAborted();
186 G4cout << exception.what() << G4endl;
187 G4cout << "Aborting this event (#" << anEvent->GetEventID() << ")" << G4endl;
188 return;
189 }
190
191 if (oneTurnMap)
192 {
193 G4bool offsetSAndOnFirstTurn = bunch->UseCurvilinearTransform();
194 oneTurnMap->SetInitialPrimaryCoordinates(coords, offsetSAndOnFirstTurn);
195 }
196
197 particleGun->SetParticleDefinition(bunch->ParticleDefinition()->ParticleDefinition());
198
199 // always update the charge - ok for normal particles; fixes purposively specified ions.
200 particleGun->SetParticleCharge(bunch->ParticleDefinition()->Charge());
201
202 // check that kinetic energy is positive and finite anyway and abort if not.
203 // get the mass from the beamParticle as this takes into account any electrons
204 G4double EK = coords.local.totalEnergy - bunch->ParticleDefinition()->Mass();
205 if (EK <= 0)
206 {
207 G4cout << __METHOD_NAME__ << "Event #" << anEvent->GetEventID()
208 << " - Particle kinetic energy smaller than 0! "
209 << "This will not be tracked." << G4endl;
210 anEvent->SetEventAborted();
211 return;
212 }
213
214 // write initial particle position and momentum
216 {
217 std::ofstream ofstr("output.primary.txt");
218 ofstr << coords.local.x << " " << coords.local.y << " " << coords.local.z << " "
219 << coords.local.xp << " " << coords.local.yp << " " << coords.local.zp << " "
220 << coords.local.T << " " << coords.local.totalEnergy << " " << coords.local.weight << std::endl;
221 ofstr.close();
222 }
223
224 // check the coordinates are valid
225 if (!worldExtent.Encompasses(coords.global))
226 {
227 G4cerr << __METHOD_NAME__ << "point: " << coords.global
228 << "mm lies outside the world volume with extent ("
229 << worldExtent << " - event aborted!" << G4endl << G4endl;
230 anEvent->SetEventAborted();
231 }
232
233#ifdef BDSDEBUG
234 G4cout << __METHOD_NAME__ << coords << G4endl;
235#endif
236
237 G4ThreeVector PartMomDir(coords.global.xp,coords.global.yp,coords.global.zp);
238 G4ThreeVector PartPosition(coords.global.x,coords.global.y,coords.global.z);
239
240 particleGun->SetParticlePosition(PartPosition);
241 particleGun->SetParticleEnergy(EK);
242 particleGun->SetParticleMomentumDirection(PartMomDir);
243 particleGun->SetParticleTime(coords.global.T);
244
245 particleGun->GeneratePrimaryVertex(anEvent);
246
247 // set the weight
248 auto vertex = anEvent->GetPrimaryVertex();
249 vertex->SetWeight(coords.local.weight);
250
251 // associate full set of coordinates with vertex for writing to output after event
252 vertex->SetUserInformation(new BDSPrimaryVertexInformation(coords,
254
255#ifdef BDSDEBUG
256 vertex->Print();
257#endif
258}
A wrapper of BDSBunch to include a filter for the events loaded by an event generator.
The base class for bunch distribution generators.
Definition: BDSBunch.hh:47
virtual void RecreateAdvanceToEvent(G4int)
Definition: BDSBunch.hh:115
virtual const BDSParticleDefinition * ParticleDefinition() const
Access the beam particle definition.
Definition: BDSBunch.hh:95
virtual void UpdateIonDefinition()
Definition: BDSBunch.cc:332
virtual BDSParticleCoordsFullGlobal GetNextParticleValid(G4int maxTries=100)
Definition: BDSBunch.cc:206
G4bool UseCurvilinearTransform() const
Access whether there's a finite S offset and therefore we're using a CL transform.
Definition: BDSBunch.hh:108
Interface to store event information use G4 hooks.
Definition: BDSEventInfo.hh:42
void SetSeedStateAtStart(const G4String &seedStateAtStartIn)
Setters.
Definition: BDSEventInfo.hh:54
General exception with possible name of object and message.
Definition: BDSException.hh:35
const char * what() const noexcept override
Override message in std::exception.
Definition: BDSException.hh:55
G4bool Encompasses(const G4ThreeVector &point) const
Return whether the extent encompasses the point. True if point lies inside the extent.
Definition: BDSExtent.cc:190
A class that holds global options and constants.
static BDSGlobalConstants * Instance()
Access method.
Loader to use any HepMC3 compatible file.
virtual void RecreateAdvanceToEvent(G4int eventOffset)
Advance to the correct event number in the file for recreation.
Loader of ROOT Event output for recreating events.
void SetInitialPrimaryCoordinates(const BDSParticleCoordsFullGlobal &coords, G4bool offsetS0)
Load initial coordinates where the beam started and convert to PTC coordinates.
A set of particle coordinates in both local and global.
G4double Mass() const
Accessor.
G4double Charge() const
Accessor.
G4ParticleDefinition * ParticleDefinition() const
Accessor.
G4bool recreate
Whether to load seed state at start of event from rootevent file.
G4ParticleGun * particleGun
Geant4 particle gun that creates single particles.
G4int eventOffset
The offset in the file to read events from when setting the seed.
G4bool useASCIISeedState
Whether to use the ascii seed state each time.
G4bool ionPrimary
The primary particle will be an ion.
BDSPrimaryGeneratorAction(BDSBunch *bunchIn, const GMAD::Beam &beam)
Bunch must have a valid particle definition (ie not nullptr).
G4bool useEventGeneratorFile
Whether to use event generator file.
BDSExtent worldExtent
World extent that particle coordinates are checked against to ensure they're inside it.
G4bool useSamplerLoader
Whether to use a sampler loader.
BDSBunch * bunch
BDSIM particle generator.
virtual void GeneratePrimaries(G4Event *)
Main interface for Geant4. Prepare primary(ies) for the event.
BDSHepMC3Reader * hepMC3Reader
Event generator file loader.
BDSPTCOneTurnMap * oneTurnMap
Cached OTM for setting first turn primary coords.
G4bool writeASCIISeedState
Cache of whether to write seed state as ASCII per event.
BDSOutputLoader * recreateFile
Optional output handler for restoring seed state.
Full set of coordinates for association with primary vertex.
Loader to read a specific sampler from a BDSIM ROOT output file.
virtual void GeneratePrimaryVertex(G4Event *anEvent)
Read the next non-empty sampler entry from the file.
Improve type-safety of native enum data type in C++.
bool eventGeneratorWarnSkippedParticles
Event generator file filter.
Definition: beamBase.h:153
std::string distrFile
beam parameters
Definition: beamBase.h:52
bool distrFileFromExecOptions
Required to know how to build the absolute path properly.
Definition: beamBase.h:54
bool removeUnstableWithoutDecay
beam parameters
Definition: beamBase.h:56
std::string distrType
beam parameters
Definition: beamBase.h:45
Beam class.
Definition: beam.h:44
G4bool StrContains(const G4String &str, const G4String &test)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
Definition: BDSUtilities.cc:66
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)