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