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 - 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 "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.
Definition: BDSBeamline.hh:61
G4double GetTotalArcLength() const
Get the total ARC length for the beamline - ie the maximum s position.
Definition: BDSBeamline.hh:139
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.
Definition: BDSEventInfo.hh:42
void SetStopTime(const time_t &stopTimeIn)
Setters.
Definition: BDSEventInfo.hh:51
void SetStartTime(const time_t &startTimeIn)
Setters.
Definition: BDSEventInfo.hh:50
void SetDurationCPU(G4float durationCPUIn)
Setters.
Definition: BDSEventInfo.hh:53
void SetSeedStateAtStart(const G4String &seedStateAtStartIn)
Setters.
Definition: BDSEventInfo.hh:54
void SetDurationWall(G4float durationWallIn)
Setters.
Definition: BDSEventInfo.hh:52
General exception with possible name of object and message.
Definition: BDSException.hh:35
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:168
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:380
void FillParticleData(G4bool writeIons)
Fill the local structure particle data with information. Also calls WriteParticleData().
Definition: BDSOutput.cc:190
void FillBeam(const GMAD::BeamBase *beam)
Definition: BDSOutput.cc:208
void FillModel()
Definition: BDSOutput.cc:222
void FillOptions(const GMAD::OptionsBase *options)
Definition: BDSOutput.cc:215
virtual void CloseFile()=0
const GMAD::OptionsBase * GetOptionsBase() const
Return bare options base class.
Definition: BDSParser.hh:53
static BDSParser * Instance()
Access method.
Definition: BDSParser.cc:28
const GMAD::BeamBase * GetBeamBase() const
Return bare beam base class.
Definition: BDSParser.hh:62
void SetTrajectorySamplerIDs() const
BDSBunch * bunchGenerator
Cache of bunch generator.
Definition: BDSRunAction.hh:77
std::clock_t cpuStartTime
Start time of run.
Definition: BDSRunAction.hh:79
BDSEventAction * eventAction
Event action for updating information at start of run.
Definition: BDSRunAction.hh:80
G4String trajectorySamplerID
Copy of option.
Definition: BDSRunAction.hh:81
std::string seedStateAtStart
Seed state at start of the run.
Definition: BDSRunAction.hh:75
void CheckTrajectoryOptions() const
void PrintAllProcessesForAllParticles() const
const G4bool usingIons
Cache of whether ions are being used (for particle table writing out).
Definition: BDSRunAction.hh:78
BDSOutput * output
Cache of output instance. Not owned by this class.
Definition: BDSRunAction.hh:73
unsigned long long int nEventsRequested
Cache of ngenerate.
Definition: BDSRunAction.hh:82
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)