BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSOutputStructures.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 "BDSBeamline.hh"
21#include "BDSBeamlineElement.hh"
22#include "BDSDebug.hh"
23#include "BDSHitEnergyDeposition.hh"
24#include "BDSEventInfo.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSOutputStructures.hh"
27#include "BDSOutputROOTEventAperture.hh"
28#include "BDSOutputROOTEventBeam.hh"
29#include "BDSOutputROOTEventCollimator.hh"
30#include "BDSOutputROOTEventCoords.hh"
31#include "BDSOutputROOTEventHeader.hh"
32#include "BDSOutputROOTEventHistograms.hh"
33#include "BDSOutputROOTEventInfo.hh"
34#include "BDSOutputROOTEventLoss.hh"
35#include "BDSOutputROOTEventLossWorld.hh"
36#include "BDSOutputROOTEventModel.hh"
37#include "BDSOutputROOTEventOptions.hh"
38#include "BDSOutputROOTEventRunInfo.hh"
39#include "BDSOutputROOTEventSampler.hh"
40#include "BDSOutputROOTEventSamplerC.hh"
41#include "BDSOutputROOTEventSamplerS.hh"
42#include "BDSOutputROOTEventTrajectory.hh"
43#include "BDSOutputROOTParticleData.hh"
44#include "BDSHitSampler.hh"
45#include "BDSSamplerRegistry.hh"
46#include "BDSTrajectoryPoint.hh"
47
48#include "globals.hh"
49#include "G4Material.hh"
50#include "G4MaterialTable.hh"
51
52#include "CLHEP/Units/SystemOfUnits.h"
53
54#include <algorithm>
55#include <map>
56#include <string>
57#include <vector>
58#include <utility>
59
61 nCollimators(0),
62 nCavities(0),
63 localSamplersInitialised(false),
64 localCollimatorsInitialised(false)
65{
66 G4bool storeCollimatorInfo = globals->StoreCollimatorInfo();
67 G4bool storeCavityInfo = globals->StoreCavityInfo();
68 G4bool storeTurn = globals->StoreELossTurn();
69 G4bool storeLinks = globals->StoreELossLinks();
70 G4bool storeLocal = globals->StoreELossLocal();
71 G4bool storeGlobal = globals->StoreELossGlobal();
72 G4bool storeTime = globals->StoreELossTime();
73 G4bool storeStepLength = globals->StoreELossStepLength();
74 G4bool storePreStepKineticEnergy = globals->StoreELossPreStepKineticEnergy();
75 G4bool storeModelID = globals->StoreELossModelID();
76 G4bool storeELPhysics = globals->StoreELossPhysicsProcesses();
77 // store the model id if either modelID requested or store links
78 storeModelID = storeModelID || storeLinks;
79
80 particleDataOutput = new BDSOutputROOTParticleData();
81 headerOutput = new BDSOutputROOTEventHeader();
82 beamOutput = new BDSOutputROOTEventBeam();
83 optionsOutput = new BDSOutputROOTEventOptions();
84 modelOutput = new BDSOutputROOTEventModel(storeCollimatorInfo, storeCavityInfo);
85
86 eLoss = new BDSOutputROOTEventLoss(storeTurn, storeLinks, storeModelID, storeLocal,
87 storeGlobal, storeTime, storeStepLength,
88 storePreStepKineticEnergy, storeELPhysics);
89 eLossVacuum = new BDSOutputROOTEventLoss(storeTurn, storeLinks, storeModelID, storeLocal,
90 storeGlobal, storeTime, storeStepLength,
91 storePreStepKineticEnergy, storeELPhysics);
92 eLossTunnel = new BDSOutputROOTEventLoss(storeTurn, storeLinks, storeModelID, storeLocal,
93 storeGlobal, storeTime, storeStepLength,
94 storePreStepKineticEnergy, storeELPhysics);
95 eLossWorld = new BDSOutputROOTEventLossWorld();
96 eLossWorldExit = new BDSOutputROOTEventLossWorld();
97 eLossWorldContents = new BDSOutputROOTEventLossWorld();
98
99 pFirstHit = new BDSOutputROOTEventLoss(true, true, true, true, true, true, false, true, true);
100 pLastHit = new BDSOutputROOTEventLoss(true, true, true, true, true, true, false, true, true);
101
102 apertureImpacts = new BDSOutputROOTEventAperture();
103
104 traj = new BDSOutputROOTEventTrajectory();
105 evtHistos = new BDSOutputROOTEventHistograms();
106 evtInfo = new BDSOutputROOTEventInfo();
107 runHistos = new BDSOutputROOTEventHistograms();
108 runInfo = new BDSOutputROOTEventRunInfo();
109
110#ifndef __ROOTDOUBLE__
111 primary = new BDSOutputROOTEventSampler<float>("Primary");
112#else
113 primary = new BDSOutputROOTEventSampler<double>("Primary");
114#endif
115 primaryGlobal = new BDSOutputROOTEventCoords();
116}
117
118BDSOutputStructures::~BDSOutputStructures()
119{
120 delete particleDataOutput;
121 delete headerOutput;
122 delete beamOutput;
123 delete optionsOutput;
124 delete modelOutput;
125 delete primaryGlobal;
126 delete eLoss;
127 delete eLossVacuum;
128 delete eLossTunnel;
129 delete eLossWorld;
130 delete eLossWorldExit;
131 delete eLossWorldContents;
132 delete pFirstHit;
133 delete pLastHit;
134 delete apertureImpacts;
135 delete traj;
136 delete evtHistos;
137 delete evtInfo;
138 delete runHistos;
139 delete runInfo;
140 for (auto sampler : samplerTrees)
141 {delete sampler;}
142 for (auto sampler : samplerCTrees)
143 {delete sampler;}
144 for (auto sampler : samplerSTrees)
145 {delete sampler;}
146 for (auto collimator : collimators)
147 {delete collimator;}
148 delete primary;
149}
150
151G4int BDSOutputStructures::Create1DHistogram(G4String name, G4String title,
152 G4int nbins, G4double xmin, G4double xmax)
153{
154 G4int result = evtHistos->Create1DHistogram(name, title, nbins, xmin, xmax);
155 // index from runHistos will be the same as used only through interfaces in this class
156 runHistos->Create1DHistogram(name, title, nbins, xmin, xmax);
157 return result;
158}
159
160G4int BDSOutputStructures::Create1DHistogram(G4String name, G4String title,
161 std::vector<double>& edges)
162{
163 G4int result = evtHistos->Create1DHistogram(name,title,edges);
164 runHistos->Create1DHistogram(name,title,edges);
165 return result;
166}
167
168G4int BDSOutputStructures::Create3DHistogram(G4String name, G4String title,
169 G4int nBinsX, G4double xMin, G4double xMax,
170 G4int nBinsY, G4double yMin, G4double yMax,
171 G4int nBinsZ, G4double zMin, G4double zMax)
172{
173 G4int result = evtHistos->Create3DHistogram(name, title,
174 nBinsX, xMin, xMax,
175 nBinsY, yMin, yMax,
176 nBinsZ, zMin, zMax);
177 // index from runHistos will be the same as used only through interfaces in this class
178 runHistos->Create3DHistogram(name, title,
179 nBinsX, xMin, xMax,
180 nBinsY, yMin, yMax,
181 nBinsZ, zMin, zMax);
182 return result;
183}
184
185G4int BDSOutputStructures::Create4DHistogram(const G4String& name,
186 const G4String& title,
187 const G4String& eScale,
188 const std::vector<double>& eBinsEdges,
189 G4int nBinsX, G4double xMin, G4double xMax,
190 G4int nBinsY, G4double yMin, G4double yMax,
191 G4int nBinsZ, G4double zMin, G4double zMax,
192 G4int nBinsE, G4double eMin, G4double eMax)
193{
194 G4int result = evtHistos->Create4DHistogram(name, title, eScale, eBinsEdges,
195 nBinsX, xMin, xMax,
196 nBinsY, yMin, yMax,
197 nBinsZ, zMin, zMax,
198 nBinsE, eMin, eMax);
199
200 runHistos->Create4DHistogram(name, title, eScale, eBinsEdges,
201 nBinsX, xMin, xMax,
202 nBinsY, yMin, yMax,
203 nBinsZ, zMin, zMax,
204 nBinsE, eMin, eMax);
205 return result;
206}
207
209{
211 {
212 auto samplerRegistry = BDSSamplerRegistry::Instance();
213 const auto sNames = samplerRegistry->GetUniqueNamesPlane();
214#ifdef USE_SIXTRACKLINK
215 // TODO hardcoded because of sixtrack dynamic buildup
216 // Sixtrack does lazy initialisation for collimators in link to Geant4 so we don't know
217 // a priori how many link elements there'll be. If we allow it to be dynamically built up
218 // we risk the vector expanding and moving in memory, therefore breaking all the && (address
219 // of pointer) links of TTree::SetBranchAddress in the output. Therefore, we reserve a size
220 // of 300 in the hope that this is less than the LHC 120 collimators for both beams. Ideally,
221 // the sixtrack interface should be rewritten so we know at construction time how many will
222 // be built.
223 samplerTrees.reserve(300);
224#else
225 samplerTrees.reserve(sNames.size());
226#endif
228 for (const auto& samplerName : sNames)
229 {
230#ifndef __ROOTDOUBLE__
232#else
234#endif
235 samplerTrees.push_back(res);
236 samplerNames.push_back(samplerName);
237 }
238 const auto planeIDs = samplerRegistry->GetSamplerIDsPlane();
239 G4int i = 0;
240 for (const auto& ID : planeIDs)
241 {samplerIDToIndexPlane[ID] = i; i++;}
242
243 // cylindrical samplers
244 const auto scNames = samplerRegistry->GetUniqueNamesCylinder();
245 samplerCTrees.reserve(scNames.size());
246 for (const auto& samplerName : scNames)
247 {
248 samplerCTrees.emplace_back(new BDSOutputROOTEventSamplerC(samplerName));
249 samplerCNames.emplace_back(samplerName);
250 }
251 const auto cylinderIDs = samplerRegistry->GetSamplerIDsCylinder();
252 i = 0;
253 for (const auto& ID : cylinderIDs)
254 {samplerIDToIndexCylinder[ID] = i; i++;}
255
256 // spherical samplers
257 const auto ssNames = samplerRegistry->GetUniqueNamesSphere();
258 samplerSTrees.reserve(ssNames.size());
259 for (const auto& samplerName : ssNames)
260 {
261 samplerSTrees.emplace_back(new BDSOutputROOTEventSamplerS(samplerName));
262 samplerSNames.emplace_back(samplerName);
263 }
264 const auto sphereIDs = samplerRegistry->GetSamplerIDsSphere();
265 i = 0;
266 for (const auto& ID : sphereIDs)
267 {samplerIDToIndexSphere[ID] = i; i++;}
268 }
269}
270
272{
273 materialToID.clear();
274 materialIDToNameUnique.clear();
275
276 const auto materialTable = G4Material::GetMaterialTable(); // should be an std::vector<G4Material*>*
277
278 // It's completely permitted to use degenerate material names as the geometry is constructed by
279 // pointer. We need a way to sort the materials for a given input irrespective of pointer or memory
280 // location so the result is the same for multiple runs of bdsim.
281
282 // Use a pair of <name, density>. A c++ map will be internally sorted by keys and the various
283 // comparison operators are defined by pairs in <utility>. Once sorted, by a map, we then loop
284 // over that map and generate integer IDs for each material.
285
286 // This may seem overkill as we ensure in BDSMaterials we don't make materials with
287 // degenerate names and ultimately, we can't define degenerate materials in GMAD so
288 // this shouldn't happen. But, if someone turns off preprocessGDML and they have degenerate
289 // material names in multiple GDML files or a repeated definition of the same material
290 // in multiple GDML files, we will end up with different G4Material instances but still
291 // need a way to distinguish them withouth using the pointer.
292
293 std::map<std::pair<G4String, G4double>, G4Material*> sortingMap;
294 std::map<G4String, int> nameCount;
295 std::map<G4Material*, G4String> matToUniqueName;
296
297 for (const auto& mat : *materialTable)
298 {
299 G4String matName = mat->GetName();
300 G4String matNameUnique = matName;
301
302 auto search = nameCount.find(matName);
303 if (search != nameCount.end())
304 {
305 search->second += 1;
306 matNameUnique = matName + std::to_string(search->second);
307 matToUniqueName[mat] = matNameUnique;
308 }
309 else
310 {
311 nameCount[matName] = 0;
312 matToUniqueName[mat] = matName;
313 }
314 sortingMap[std::make_pair(matNameUnique, mat->GetDensity())] = mat;
315 }
316
317 short int i = 0;
318 for (const auto& kv : sortingMap)
319 {
320 materialToID[kv.second] = i;
321 materialIDToNameUnique[i] = matToUniqueName[kv.second];
322 i++;
323 }
324}
325
327{
328 G4int result = 0;
329 for (auto const& samplerName : BDSSamplerRegistry::Instance()->GetUniqueNames())
330 {// only put it in if it doesn't exist already
331 if (std::find(samplerNames.begin(), samplerNames.end(), samplerName) == samplerNames.end())
332 {
333 result++;
334#ifndef __ROOTDOUBLE__
336#else
338#endif
339 samplerTrees.push_back(res);
340 samplerNames.push_back(samplerName);
341 }
342 }
344 return result;
345}
346
348{
349 const G4String collimatorPrefix = "COLL_";
350 const BDSBeamline* flatBeamline = BDSAcceleratorModel::Instance()->BeamlineMain();
351 if (flatBeamline)
352 {collimatorIndices = flatBeamline->GetIndicesOfCollimators();}
353 nCollimators = (G4int)collimatorIndices.size();
354
355 for (auto index : collimatorIndices)
356 {
357 // prepare output structure name
358 const BDSBeamlineElement* el = flatBeamline->at(index);
359 // use the 'placement' name for a unique name (with copy number included)
360 G4String collimatorName = collimatorPrefix + el->GetPlacementName();
361 collimatorNames.push_back(collimatorName);
362 collimatorIndicesByName[el->GetName()] = index;
364
366 info.Fill(el);
367 collimatorInfo.push_back(info);
368
369 // cache difference in apertures for efficient interpolation and avoid
370 // repeated calculation. not required in info for output though.
371 G4double xDiff = info.xSizeOut - info.xSizeIn;
372 G4double yDiff = info.ySizeOut - info.ySizeIn;
373 collimatorDifferences.emplace_back(xDiff, yDiff); // construct in place
374 }
375}
376
378{
379 const G4String cavityPrefix = "CAV_";
380 const BDSBeamline* flatBeamline = BDSAcceleratorModel::Instance()->BeamlineMain();
381 if (flatBeamline)
382 {
383 std::vector<G4int> pillboxIndices = flatBeamline->GetIndicesOfElementsOfType("cavity_pillbox");
384 std::vector<G4int> rectIndices = flatBeamline->GetIndicesOfElementsOfType("cavity_rectangular");
385 std::vector<G4int> ellipticalIndices = flatBeamline->GetIndicesOfElementsOfType("cavity_elliptical");
386 cavityIndices = pillboxIndices;
387 cavityIndices.insert(std::end(cavityIndices), std::begin(rectIndices), std::end(rectIndices));
388 cavityIndices.insert(std::end(cavityIndices), std::begin(ellipticalIndices), std::end(ellipticalIndices));
389 nCavities = (G4int) cavityIndices.size();
390 }
391 for (auto index : cavityIndices)
392 {
393 // prepare output structure name
394 const BDSBeamlineElement* el = flatBeamline->at(index);
395 // use the 'placement' name for a unique name (with copy number included)
396 G4String cavityName = cavityPrefix + el->GetPlacementName();
397 cavityNames.push_back(cavityName);
398 cavityIndicesByName[el->GetName()] = index;
400
402 info.Fill(el);
403 cavityInfo.push_back(info);
404 }
405}
406
408{
410 {
412 for (int i = 0; i < (int)collimatorIndices.size(); i++)
413 {collimators.push_back(new BDSOutputROOTEventCollimator());}
414 }
415}
416
418{
420}
421
423{
424 headerOutput->Flush();
425}
426
428{
430}
431
433{
434 *beamOutput = BDSOutputROOTEventBeam(); // default
435}
436
438{
440}
441
443{
444 primary->Flush();
445 for (auto sampler : samplerTrees)
446 {sampler->Flush();}
447 for (auto sampler : samplerCTrees)
448 {sampler->Flush();}
449 for (auto sampler : samplerSTrees)
450 {sampler->Flush();}
451 for (auto collimator : collimators)
452 {collimator->Flush();}
453 primaryGlobal->Flush();
454 eLoss->Flush();
455 eLossVacuum->Flush();
456 eLossTunnel->Flush();
457 eLossWorld->Flush();
458 eLossWorldExit->Flush();
459 eLossWorldContents->Flush();
460 pFirstHit->Flush();
461 pLastHit->Flush();
462 apertureImpacts->Flush();
463 traj->Flush();
464 evtHistos->Flush();
465 evtInfo->Flush();
466}
467
469{
470 runInfo->Flush();
471}
const BDSBeamline * BeamlineMain() const
Accessor.
A class that holds a fully constructed BDSAcceleratorComponent as well as any information relevant to...
G4String GetPlacementName() const
Accessor.
G4String GetName() const
Accessor.
A vector of BDSBeamlineElement instances - a beamline.
Definition: BDSBeamline.hh:61
const BDSBeamlineElement * at(int iElement) const
Return a reference to the element at i.
Definition: BDSBeamline.hh:120
std::vector< G4int > GetIndicesOfElementsOfType(const G4String &type) const
Return vector of indices for this beam line where element of type name 'type' is found.
Definition: BDSBeamline.cc:934
std::vector< G4int > GetIndicesOfCollimators() const
Return indices in order of ecol, rcol, jcol and crystalcol elements.
Definition: BDSBeamline.cc:957
A class that holds global options and constants.
Data stored for energy deposition hits per event.
Class to store all beam options for a BDSIM run.
Data stored for each cavity in the model.
Data stored for each collimator in the model.
Data stored for each collimator per event.
Information about the software and the file.
Holder for a set of histograms to be stored.
virtual void Flush()
Flush the contents.
Information pertaining to an individual event.
Data stored for world hits per event.
Data stored for energy deposition hits per event.
Information stored per model representing accelerator.
void Flush()
Initialise all members.
Class to store all options for a BDSIM run.
Information pertaining to a run.
Information stored per cylindrical sampler per event.
Information stored per spherical sampler per event.
Information stored per sampler per event.
virtual void Flush()
Clean Sampler.
Structure to record a trajectory.
void Flush()
add comment to avoid warning (no need to make persistent, see issue #191)
Geant4 particle data for particles used in simulation.
virtual void Flush()
Clear maps.
void InitialiseCollimators()
Construct collimators.
BDSOutputROOTEventModel * modelOutput
Model output.
G4int Create1DHistogram(G4String name, G4String title, G4int nbins, G4double xmin, G4double xmax)
Create histograms for both evtHistos and runHistos. Return index from evtHistos.
std::vector< G4String > collimatorNames
Names of collimators in output structures.
std::vector< BDSOutputROOTEventCollimator * > collimators
Collimator output structures.
G4int nCavities
Number of cavities in beam line.
std::vector< std::string > samplerNames
Sampler names to use.
BDSOutputROOTEventSampler< double > * primary
Primary sampler structure.
BDSOutputROOTEventRunInfo * runInfo
Run information.
void InitialiseMaterialMap()
Construct a map of material pointer to integer ID and name.
void ClearStructuresOptions()
Clear the local options structure.
std::vector< G4String > cavityNames
Names of cavities in output structures.
BDSOutputROOTEventHistograms * runHistos
Run level histograms.
BDSOutputROOTEventLossWorld * eLossWorldExit
World exit hits.
std::vector< G4int > cavityIndices
Indices in beam line that are cavities.
void ClearStructuresRunLevel()
Clear the local structures in this class in preparation for a new run.
BDSOutputStructures()=delete
Unused default constructors.
void InitialiseSamplers()
Construct samplers.
void ClearStructuresBeam()
Clear the local beam structure.
std::vector< BDSOutputROOTEventCavityInfo > cavityInfo
Cavity parameters.
std::map< G4String, G4int > collimatorIndicesByName
Indices mapped to their name.
BDSOutputROOTEventLossWorld * eLossWorldContents
Externally supplied world contents hits.
G4int nCollimators
Number of collimators in beam line.
std::vector< BDSOutputROOTEventSampler< double > * > samplerTrees
Sampler structures.
std::vector< std::pair< G4double, G4double > > collimatorDifferences
void ClearStructuresModel()
Clear the local model structure.
void ClearStructuresHeader()
Clear the local header structure.
G4int Create4DHistogram(const G4String &name, const G4String &title, const G4String &eScale, const std::vector< double > &eBinsEdges, G4int nBinsX, G4double xMin, G4double xMax, G4int nBinsY, G4double yMin, G4double yMax, G4int nBinsZ, G4double zMin, G4double zMax, G4int nBinsE, G4double eMin, G4double eMax)
Create histograms for both evtHistos and runHistos. Return index from evtHistos.
BDSOutputROOTEventHeader * headerOutput
Information about the file.
BDSOutputROOTEventLossWorld * eLossWorld
World energy deposition.
BDSOutputROOTEventLoss * eLossVacuum
General energy deposition.
std::vector< G4int > collimatorIndices
Indices in beam line that are collimators.
BDSOutputROOTEventInfo * evtInfo
Event information.
BDSOutputROOTEventLoss * pLastHit
Primary loss point.
BDSOutputROOTEventHistograms * evtHistos
Event level histograms.
BDSOutputROOTEventLoss * eLossTunnel
Tunnel energy deposition.
G4int UpdateSamplerStructures()
Interface to allow setting up samplers later for dynamic geometry construction a la SixTrack....
G4int Create3DHistogram(G4String name, G4String title, G4int nBinsX, G4double xMin, G4double xMax, G4int nBinsY, G4double yMin, G4double yMax, G4int nBinsZ, G4double zMin, G4double zMax)
Create histograms for both evtHistos and runHistos. Return index from evtHistos.
void ClearStructuresEventLevel()
Clear the local structures in this class in preparation for a new event.
BDSOutputROOTEventLoss * pFirstHit
Primary hit point.
BDSOutputROOTEventTrajectory * traj
Trajectories.
BDSOutputROOTEventBeam * beamOutput
Beam output.
BDSOutputROOTEventLoss * eLoss
General energy deposition.
std::vector< BDSOutputROOTEventCollimatorInfo > collimatorInfo
void PrepareCavityInformation()
Extract number of collimators and their names from beam line.
void ClearStructuresParticleData()
Clear the local particle data structure.
G4bool localCollimatorsInitialised
Whether we've setup the member vector of collimators. Similarly to localSamplersInitialised.
BDSOutputROOTEventAperture * apertureImpacts
Impacts on the aperture.
BDSOutputROOTParticleData * particleDataOutput
Geant4 information / particle tables.
BDSOutputROOTEventOptions * optionsOutput
Options output.
std::map< G4String, G4int > cavityIndicesByName
Indices mapped to their name.
static BDSSamplerRegistry * Instance()
Accessor for registry.