BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSRunAction.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 "BDSAcceleratorModel.hh"
20#include "BDSAuxiliaryNavigator.hh"
21#include "BDSBeamline.hh"
22#include "BDSBunch.hh"
23#include "BDSBunchFileBased.hh"
24#include "BDSDebug.hh"
25#include "BDSEventAction.hh"
26#include "BDSEventInfo.hh"
27#include "BDSException.hh"
28#include "BDSGlobalConstants.hh"
29#include "BDSOutput.hh"
30#include "BDSParser.hh"
31#include "BDSRunAction.hh"
32#include "BDSSamplerPlacementRecord.hh"
33#include "BDSSamplerRegistry.hh"
34#include "BDSWarning.hh"
35
36#include "parser/beamBase.h"
37#include "parser/optionsBase.h"
38
39#include "globals.hh" // geant4 globals / types
40#include "G4ParticleTable.hh"
41#include "G4ProcessManager.hh"
42#include "G4ProcessVector.hh"
43#include "G4Run.hh"
44#include "G4Version.hh"
45
46#include "CLHEP/Random/Random.h"
47
48#include <chrono>
49#include <ctime>
50#include <sstream>
51#include <string>
52#include <vector>
53
54#if G4VERSION_NUMBER > 1049
55#include "BDSPhysicsUtilities.hh"
56#include "G4Positron.hh"
57#include "G4Electron.hh"
58#endif
59
60BDSRunAction::BDSRunAction(BDSOutput* outputIn,
61 BDSBunch* bunchGeneratorIn,
62 G4bool usingIonsIn,
63 BDSEventAction* eventActionIn,
64 const G4String& trajectorySamplerIDIn):
65 output(outputIn),
66 starttime(time(nullptr)),
67 info(nullptr),
68 bunchGenerator(bunchGeneratorIn),
69 usingIons(usingIonsIn),
70 cpuStartTime(std::clock_t()),
71 eventAction(eventActionIn),
72 trajectorySamplerID(trajectorySamplerIDIn),
73 nEventsRequested(0)
74{;}
75
76BDSRunAction::~BDSRunAction()
77{
78 delete info;
79}
80
81void BDSRunAction::BeginOfRunAction(const G4Run* aRun)
82{
83 if (BDSGlobalConstants::Instance()->PrintPhysicsProcesses())
85
86 BDSAuxiliaryNavigator::ResetNavigatorStates();
87
88 // Bunch generator beginning of run action (optional mean subtraction).
89 bunchGenerator->BeginOfRunAction(aRun->GetNumberOfEventToBeProcessed(), BDSGlobalConstants::Instance()->Batch());
90 nEventsRequested = aRun->GetNumberOfEventToBeProcessed();
91
94
95 info = new BDSEventInfo();
96
97 // save the random engine state
98 std::stringstream ss;
99 CLHEP::HepRandom::saveFullState(ss);
100 seedStateAtStart = ss.str();
102
103 // get the current time
104 starttime = time(nullptr);
105 info->SetStartTime(starttime);
106
107 // Output feedback
108 G4cout << __METHOD_NAME__ << "Run " << aRun->GetRunID()
109 << " start. Time is " << asctime(localtime(&starttime)) << G4endl;
110
112 output->NewFile();
113
114 // Write options now file open.
116 output->FillOptions(ob);
117
118 // Write beam
120 output->FillBeam(bb);
121
122 // Write model now file open.
123 output->FillModel();
124
125 // Write out geant4 data including particle tables.
127
128#if G4VERSION_NUMBER > 1049
129 // this apparently has to be done in the run action and doesn't work if done earlier
131 BDS::FixGeant105ThreshholdsForParticle(G4Positron::Definition());
132 BDS::FixGeant105ThreshholdsForParticle(G4Electron::Definition());
133#endif
134
135 cpuStartTime = std::clock();
136}
137
138void BDSRunAction::EndOfRunAction(const G4Run* aRun)
139{
140 // Get the current time
141 time_t stoptime = time(nullptr);
142 info->SetStopTime(stoptime);
143 // Run duration
144 G4float duration = static_cast<G4float>(difftime(stoptime, starttime));
145 info->SetDurationWall(duration);
146
147 // Calculate the elapsed CPU time for the event.
148 auto cpuEndTime = std::clock();
149 G4float durationCPU = static_cast<G4float>(cpuEndTime - cpuStartTime) / CLOCKS_PER_SEC;
150 info->SetDurationCPU(durationCPU);
151
152 // Output feedback
153 G4cout << G4endl << __METHOD_NAME__ << "Run " << aRun->GetRunID() << " end. Time is " << asctime(localtime(&stoptime));
154
155 // Write output
156 // In the case of a file-based bunch generator, it will have cached these numbers - get them.
157 unsigned long long int nOriginalEvents = nEventsRequested; // default for normal bunch class
158 unsigned long long int nEventsDistrFileSkipped = 0;
159 unsigned long long int nEventsInOriginalDistrFile = 0;
160 unsigned int distrFileLoopNTimes = 1;
161 if (auto beg = dynamic_cast<BDSBunchFileBased*>(bunchGenerator))
162 {
163 nOriginalEvents = beg->NOriginalEvents();
164 nEventsDistrFileSkipped = beg->NEventsInFileSkipped();
165 nEventsInOriginalDistrFile = beg->NEventsInFile();
166 distrFileLoopNTimes = (unsigned int)beg->DistrFileLoopNTimes();
167 if (nEventsDistrFileSkipped > 0)
168 {G4cout << __METHOD_NAME__ << nEventsDistrFileSkipped << " events were skipped as no particles passed the filters in them." << G4endl;}
169 if (nEventsDistrFileSkipped == nEventsInOriginalDistrFile)
170 {
171 G4String msg = "no events were simulated at all as none contained any particles that passed the filters.";
172 BDS::Warning(__METHOD_NAME__, msg);
173 }
174 }
175 output->FillRun(info, nOriginalEvents, nEventsRequested, nEventsInOriginalDistrFile, nEventsDistrFileSkipped, distrFileLoopNTimes);
176 output->CloseFile();
177 info->Flush();
178
179 // note difftime only calculates to the integer second
180 G4cout << __METHOD_NAME__ << "Run Duration >> " << (int)duration << " s" << G4endl;
181}
182
184{
185 G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
186 G4ParticleTable::G4PTblDicIterator* particleIterator = particleTable->GetIterator();
187 particleIterator->reset();
188 while ((*particleIterator)())
189 {
190 G4ParticleDefinition* particle = particleIterator->value();
191 G4cout << "Particle: \"" << particle->GetParticleName() << "\", defined processes are: " << G4endl;
192 G4ProcessManager* pManager = particle->GetProcessManager();
193 if (!pManager)
194 {continue;}
195 G4ProcessVector* processList = pManager->GetProcessList();
196 if (!processList)
197 {continue;}
198 for (G4int i = 0; i < (G4int)processList->size(); i++)
199 {G4cout << "\"" << (*processList)[i]->GetProcessName() << "\"" << G4endl;}
200 G4cout << G4endl;
201 }
202}
203
205{
206 if (trajectorySamplerID.empty())
207 {return;}
208
209 std::vector<G4int> samplerIDs;
210 std::istringstream is(trajectorySamplerID);
211 G4String tok;
212 while (is >> tok)
213 {
215 G4int i = 0;
216 G4bool found = false;
217 for (const auto& samplerInfo : *samplerRegistry)
218 {
219 if (samplerInfo.UniqueName() == tok)
220 {
221 samplerIDs.push_back(i);
222 found = true;
223 break;
224 }
225 i++;
226 }
227 if (!found)
228 {throw BDSException(__METHOD_NAME__, "Error: sampler \"" + tok + "\" named in the option storeTrajectorySamplerID was not found.");}
229 }
230
232}
233
235{
236 // TODO - with multiple beam lines this will have to check for the maximum S coordinate
237 G4double maxS = 1*CLHEP::m; // 1m for margin
238 const BDSBeamline* blm = BDSAcceleratorModel::Instance()->BeamlineMain();
239 if (blm)
240 {maxS += blm->GetTotalArcLength();}
241 std::vector<std::pair<double,double>> sRangeToStore = BDSGlobalConstants::Instance()->StoreTrajectoryELossSRange();
242 for (const auto& range : sRangeToStore)
243 {
244 if (range.first > maxS)
245 {throw BDSException(__METHOD_NAME__, "S coordinate " + std::to_string(range.first / CLHEP::m) + "m in option storeTrajectoryElossSRange is beyond the length of the beam line (2m margin).");}
246 }
247}
const BDSBeamline * BeamlineMain() const
Accessor.
A vector of BDSBeamlineElement instances - a beamline.
G4double GetTotalArcLength() const
Get the total ARC length for the beamline - ie the maximum s position.
An intermediate layer for any bunch classes that are file based.
The base class for bunch distribution generators.
Definition BDSBunch.hh:47
virtual void BeginOfRunAction(G4int numberOfEvents, G4bool batchMode)
Definition BDSBunch.cc:285
virtual const BDSParticleDefinition * ParticleDefinition() const
Access the beam particle definition.
Definition BDSBunch.hh:96
Process information at the event level.
void SetSamplerIDsForTrajectories(const std::vector< G4int > &samplerIDsIn)
Update the vector of sampler IDs to match for trajectories.
Interface to store event information use G4 hooks.
void SetStopTime(const time_t &stopTimeIn)
Setters.
void SetStartTime(const time_t &startTimeIn)
Setters.
void SetDurationCPU(G4float durationCPUIn)
Setters.
void SetSeedStateAtStart(const G4String &seedStateAtStartIn)
Setters.
void SetDurationWall(G4float durationWallIn)
Setters.
General exception with possible name of object and message.
static BDSGlobalConstants * Instance()
Access method.
Output base class that defines interface for all output types.
Definition BDSOutput.hh:73
virtual void NewFile()=0
Open a new file. This should call WriteHeader() in it.
virtual void InitialiseGeometryDependent()
Definition BDSOutput.cc:171
void FillRun(const BDSEventInfo *info, unsigned long long int nOriginalEventsIn, unsigned long long int nEventsRequestedIn, unsigned long long int nEventsInOriginalDistrFileIn, unsigned long long int nEventsDistrFileSkippedIn, unsigned int distrFileLoopNTimesIn)
Copy run information to output structure.
Definition BDSOutput.cc:382
void FillParticleData(G4bool writeIons)
Fill the local structure particle data with information. Also calls WriteParticleData().
Definition BDSOutput.cc:193
void FillBeam(const GMAD::BeamBase *beam)
Definition BDSOutput.cc:211
void FillModel()
Definition BDSOutput.cc:225
void FillOptions(const GMAD::OptionsBase *options)
Definition BDSOutput.cc:218
virtual void CloseFile()=0
const GMAD::OptionsBase * GetOptionsBase() const
Return bare options base class.
Definition BDSParser.hh:54
static BDSParser * Instance()
Access method.
Definition BDSParser.cc:30
const GMAD::BeamBase * GetBeamBase() const
Return bare beam base class.
Definition BDSParser.hh:63
void SetTrajectorySamplerIDs() const
BDSBunch * bunchGenerator
Cache of bunch generator.
std::clock_t cpuStartTime
Start time of run.
BDSEventAction * eventAction
Event action for updating information at start of run.
G4String trajectorySamplerID
Copy of option.
std::string seedStateAtStart
Seed state at start of the run.
void CheckTrajectoryOptions() const
void PrintAllProcessesForAllParticles() const
const G4bool usingIons
Cache of whether ions are being used (for particle table writing out).
BDSOutput * output
Cache of output instance. Not owned by this class.
unsigned long long int nEventsRequested
Cache of ngenerate.
Associated information for the placement of a sampler.
static BDSSamplerRegistry * Instance()
Accessor for registry.
Options for a beam distribution.
Definition beamBase.h:35
Basic options class independent of Geant4.
Definition optionsBase.h:36
void FixGeant105ThreshholdsForBeamParticle(const BDSParticleDefinition *particleDefinition)
Apply FixGeant105ThreshholdsForParticle to the beam particle definition.
void FixGeant105ThreshholdsForParticle(const G4ParticleDefinition *particleDefinition)
STL namespace.