BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSOutputROOTEventModel.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 "BDSOutputROOTEventModel.hh"
20
21#ifndef __ROOTBUILD__
22#include "BDSAcceleratorModel.hh"
23#include "BDSBeamline.hh"
24#include "BDSBeamlineElement.hh"
25#include "BDSBeamPipeInfo.hh"
26#include "BDSMagnet.hh"
27#include "BDSMagnetStrength.hh"
28#include "BDSPhysicalVolumeInfoRegistry.hh"
29#include "BDSSamplerRegistry.hh"
30
31#include "G4RotationMatrix.hh"
32#include "G4String.hh"
33#include "G4Types.hh"
34
35#include <algorithm>
36#include <iterator>
37#include <map>
38#include <set>
39#include <sstream>
40#include <string>
41#include <vector>
42#include <utility>
43#endif
44
46
48 n(0),
49 storeCollimatorInfo(false),
50 storeCavityInfo(false),
51 nCavities(0),
52 nCollimators(0)
53{
54 Flush();
55}
56
59
60int BDSOutputROOTEventModel::findNearestElement(const TVector3& point) const
61{
62 // we make a vector of pairs of the distance between the mid of each element
63 // and the specified point along with the index. We then sort this vector by
64 // the distance (first part of pair only). Could use a map as it's sorted but
65 // can't guarantee access with a double or float as a key due to binary representation.
66 std::vector<std::pair<float, int> > distanceAndIndex;
67 distanceAndIndex.reserve(midRefPos.size());
68 for (int i = 0; i < (int)midRefPos.size(); i++)
69 {distanceAndIndex.emplace_back(std::make_pair((midRefPos[i]-point).Mag(), i));}
70
71 struct customLess
72 {bool operator()(std::pair<float, int>& a, std::pair<float, int>& b) const {return a.first < b.first;};};
73 std::sort(distanceAndIndex.begin(), distanceAndIndex.end(), customLess());
74 return distanceAndIndex[0].second;
75}
76
78{
79 n = 0;
80 componentName.clear();
81 placementName.clear();
82 componentType.clear();
83 length.clear();
84 angle.clear();
85 staPos.clear();
86 midPos.clear();
87 endPos.clear();
88 staRot.clear();
89 midRot.clear();
90 endRot.clear();
91 staRefPos.clear();
92 midRefPos.clear();
93 endRefPos.clear();
94 staRefRot.clear();
95 midRefRot.clear();
96 endRefRot.clear();
97 tilt.clear();
98 offsetX.clear();
99 offsetY.clear();
100 staS.clear();
101 midS.clear();
102 endS.clear();
103 beamPipeType.clear();
104 beamPipeAper1.clear();
105 beamPipeAper2.clear();
106 beamPipeAper3.clear();
107 beamPipeAper4.clear();
108 material.clear();
109 k1.clear();
110 k2.clear();
111 k3.clear();
112 k4.clear();
113 k5.clear();
114 k6.clear();
115 k7.clear();
116 k8.clear();
117 k9.clear();
118 k10.clear();
119 k11.clear();
120 k12.clear();
121 k1s.clear();
122 k2s.clear();
123 k3s.clear();
124 k4s.clear();
125 k5s.clear();
126 k6s.clear();
127 k7s.clear();
128 k8s.clear();
129 k9s.clear();
130 k10s.clear();
131 k11s.clear();
132 k12s.clear();
133 ks.clear();
134 hkick.clear();
135 vkick.clear();
136 bField.clear();
137 eField.clear();
138 e1.clear();
139 e2.clear();
140 fint.clear();
141 fintx.clear();
142 fintk2.clear();
143 fintxk2.clear();
144 pvName.clear();
145 pvNameWPointer.clear();
146 midT.clear();
147 staP.clear();
148 staEk.clear();
149
150 storeCavityInfo = false;
151 cavityIndices.clear();
152 cavityIndicesByName.clear();
153 nCavities = 0;
154 cavityInfo.clear();
156 storeCollimatorInfo = false;
157 collimatorIndices.clear();
159 nCollimators = 0;
160 collimatorInfo.clear();
162 scoringMeshTranslation.clear();
163 scoringMeshRotation.clear();
164 scoringMeshName.clear();
165
166 materialIDToName.clear();
167 materialNameToID.clear();
168
169 samplerNamesUnique.clear();
170 samplerSPosition.clear();
171 samplerCNamesUnique.clear();
172 samplerSNamesUnique.clear();
173 samplerCRadius.clear();
174 samplerSRadius.clear();
175}
176
177#ifndef __ROOTBUILD__
179 G4bool storeCavityInfoIn):
180 n(0),
181 storeCollimatorInfo(storeCollimatorInfoIn),
182 storeCavityInfo(storeCavityInfoIn),
183 nCavities(0),
184 nCollimators(0)
185{;}
186
187TRotation BDSOutputROOTEventModel::ConvertToROOT(const G4RotationMatrix* rm) const
188{
189 TRotation rr = TRotation();
190 rr.SetToIdentity();
191 if (!rm)
192 {return rr;}
193
194 double rotAngle;
195 CLHEP::Hep3Vector axis;
196
197 rm->getAngleAxis(rotAngle, axis);
198 rr.Rotate(rotAngle, TVector3(axis.x(), axis.y(), axis.z()));
199 return rr;
200}
201
202TRotation BDSOutputROOTEventModel::ConvertToROOT(const G4RotationMatrix& rm) const
203{
204 return ConvertToROOT(&rm);
205}
206
207TVector3 BDSOutputROOTEventModel::ConvertToROOT(const G4ThreeVector& v) const
208{
209 return TVector3(v.x() / CLHEP::m, v.y() / CLHEP::m, v.z() / CLHEP::m);
210}
211
212void BDSOutputROOTEventModel::Fill(const std::vector<G4int>& collimatorIndicesIn,
213 const std::map<G4String, G4int>& collimatorIndicesByNameIn,
214 const std::vector<BDSOutputROOTEventCollimatorInfo>& collimatorInfoIn,
215 const std::vector<G4String>& collimatorBranchNamesIn,
216 const std::vector<G4int>& cavityIndicesIn,
217 const std::map<G4String, G4int>& cavityIndicesByNameIn,
218 const std::vector<BDSOutputROOTEventCavityInfo>& cavityInfoIn,
219 const std::vector<G4String>& cavityBranchNamesIn,
220 const std::map<G4String, G4Transform3D>* scorerMeshPlacements,
221 const std::map<short int, G4String>* materialIDToNameUnique,
222 G4bool storeTrajectory)
223{
225 for (const auto& nameSPos : sr->GetUniquePlaneNamesAndSPosition())
226 {
227 samplerNamesUnique.push_back(std::string(nameSPos.first) + ".");
228 samplerSPosition.push_back((double) nameSPos.second / CLHEP::m);
229 }
230 for (const auto& name : sr->GetUniqueNamesCylinder())
231 {samplerCNamesUnique.push_back(std::string(name) + ".");}
232 for (const auto& name : sr->GetUniqueNamesSphere())
233 {samplerSNamesUnique.push_back(std::string(name) + ".");}
234 samplerCRadius = sr->GetUniqueNameToRadiusCylinder();
235 samplerSRadius = sr->GetUniqueNameToRadiusSphere();
236
237 for (const auto& name : collimatorBranchNamesIn)
238 {collimatorBranchNamesUnique.push_back(std::string(name) + ".");}
239 for (const auto& name : cavityBranchNamesIn)
240 {cavityBranchNamesUnique.push_back(std::string(name) + ".");}
241
242 if (scorerMeshPlacements)
243 {
244 for (const auto& kv : *scorerMeshPlacements)
245 {
246 const G4String& name = kv.first;
247 scoringMeshTranslation[name] = ConvertToROOT(kv.second.getTranslation());
248 scoringMeshRotation[name] = ConvertToROOT(kv.second.getRotation());
249 scoringMeshName.emplace_back(name);
250 }
251 }
252
253 const BDSBeamline* beamline = BDSAcceleratorModel::Instance()->BeamlineMain();
254 if (!beamline)
255 {return;} // in case of generatePrimariesOnly there is no model - return
256
258 {
259 for (const auto value : collimatorIndicesIn)
260 {collimatorIndices.push_back((int)value);}
261
263
264 for (const auto& kv : collimatorIndicesByNameIn)
265 {collimatorIndicesByName[(std::string)kv.first] = (int)kv.second;}
266
267 collimatorInfo = collimatorInfoIn;
268 }
269
270 if (storeCavityInfo)
271 {
272 for (const auto value : cavityIndicesIn)
273 {cavityIndices.push_back((int)value);}
274
275 nCavities = (int)cavityIndices.size();
276
277 for (const auto& kv : cavityIndicesByNameIn)
278 {cavityIndicesByName[(std::string)kv.first] = (int)kv.second;}
279
280 cavityInfo = cavityInfoIn;
281 }
282
283 if (materialIDToNameUnique && storeTrajectory)
284 {
285 for (const auto& kv : *materialIDToNameUnique)
286 {
287 materialIDToName[kv.first] = (std::string)kv.second;
288 materialNameToID[(std::string)kv.second] = kv.first;
289 }
290 }
291
292 n = (int)beamline->size();
293
294 for (auto i = beamline->begin(); i != beamline->end(); ++i)
295 {
296 componentName.push_back((*i)->GetName());
297 placementName.push_back((*i)->GetPlacementName());
298 componentType.push_back((*i)->GetType());
299 length.push_back((float)((*i)->GetAcceleratorComponent()->GetArcLength() / CLHEP::m));
300 angle.push_back((float)((*i)->GetAcceleratorComponent()->GetAngle() / CLHEP::radian));
301 staPos.push_back(ConvertToROOT((*i)->GetPositionStart()));
302 midPos.push_back(ConvertToROOT((*i)->GetPositionMiddle()));
303 endPos.push_back(ConvertToROOT((*i)->GetPositionEnd()));
304 staRot.push_back(ConvertToROOT((*i)->GetRotationStart()));
305 midRot.push_back(ConvertToROOT((*i)->GetRotationMiddle()));
306 endRot.push_back(ConvertToROOT((*i)->GetRotationEnd()));
307 staRefPos.emplace_back(ConvertToROOT((*i)->GetReferencePositionStart()));
308 midRefPos.emplace_back(ConvertToROOT((*i)->GetReferencePositionMiddle()));
309 endRefPos.emplace_back(ConvertToROOT((*i)->GetReferencePositionEnd()));
310 staRefRot.push_back(ConvertToROOT((*i)->GetReferenceRotationStart()));
311 midRefRot.push_back(ConvertToROOT((*i)->GetReferenceRotationMiddle()));
312 endRefRot.push_back(ConvertToROOT((*i)->GetReferenceRotationEnd()));
313
314 // tilt and offset
315 BDSTiltOffset* to = (*i)->GetTiltOffset();
316 if (to)
317 {
318 tilt.push_back((float)(to->GetTilt() / CLHEP::rad));
319 offsetX.push_back((float)(to->GetXOffset() / CLHEP::m));
320 offsetY.push_back((float)(to->GetYOffset() / CLHEP::m));
321 }
322 else
323 {
324 tilt.push_back(0);
325 offsetX.push_back(0);
326 offsetY.push_back(0);
327 }
328
329 // S positions
330 staS.push_back((float)((*i)->GetSPositionStart() / CLHEP::m));
331 midS.push_back((float)((*i)->GetSPositionMiddle() / CLHEP::m));
332 endS.push_back((float)((*i)->GetSPositionEnd() / CLHEP::m));
333
334 // beam pipe
335 BDSBeamPipeInfo* beampipeinfo = (*i)->GetBeamPipeInfo();
336 beamPipeType.push_back(beampipeinfo ? beampipeinfo->beamPipeType.ToString() : "");
337 beamPipeAper1.push_back(beampipeinfo ? beampipeinfo->aper1 / CLHEP::m : 0);
338 beamPipeAper2.push_back(beampipeinfo ? beampipeinfo->aper2 / CLHEP::m : 0);
339 beamPipeAper3.push_back(beampipeinfo ? beampipeinfo->aper3 / CLHEP::m : 0);
340 beamPipeAper4.push_back(beampipeinfo ? beampipeinfo->aper4 / CLHEP::m : 0);
341
342 // associated material if any
343 const auto accComp = (*i)->GetAcceleratorComponent();
344 material.push_back(accComp->Material());
345
346 // helper shortcuts to all the member vectors
347 std::vector<std::vector<float>*> localNorm = {&k1,&k2,&k3,&k4,&k5,&k6,&k7,&k8,&k9,&k10,&k11,&k12};
348 std::vector<std::vector<float>*> localSkew = {&k1s,&k2s,&k3s,&k4s,&k5s,&k6s,&k7s,&k8s,&k9s,&k10s,&k11s,&k12s};
349
350 // helper lambda to avoid duplication
351 auto fillzero = [&]
352 {
353 for (int j = 0; j < (int)localNorm.size(); j++)
354 {localNorm[j]->push_back(0);}
355 for (int j = 0; j < (int)localSkew.size(); j++)
356 {localSkew[j]->push_back(0);}
357 ks.push_back(0);
358 hkick.push_back(0);
359 vkick.push_back(0);
360 bField.push_back(0);
361 eField.push_back(0);
362 e1.push_back(0);
363 e2.push_back(0);
364 hgap.push_back(0);
365 fint.push_back(0);
366 fintx.push_back(0);
367 fintk2.push_back(0);
368 fintxk2.push_back(0);
369 };
370
371 // do this bit first as we test for magnet strengths later and then do a 'continue' in the for loop
373 std::vector<std::string> localPVNames;
374 std::vector<std::string> localPVNamesWPointer;
375 if (setOfPVs)
376 {
377 auto name = [](G4VPhysicalVolume* pv){return pv->GetName();};
378 std::transform(setOfPVs->begin(), setOfPVs->end(), std::back_inserter(localPVNames), name);
379 auto fullName = [](G4VPhysicalVolume* pv)
380 {
381 std::stringstream ss;
382 ss << static_cast<const void*>(pv);
383 std::string addressName = ss.str();
384 return pv->GetName() + addressName;
385 };
386 std::transform(setOfPVs->begin(), setOfPVs->end(), std::back_inserter(localPVNamesWPointer), fullName);
387 }
388 // always push it back even if an empty vector
389 pvName.push_back(localPVNames);
390 pvNameWPointer.push_back(localPVNamesWPointer);
391
392 midT.push_back((float)(*i)->GetSynchronousTMiddle()/CLHEP::ns);
393 staP.push_back((float)(*i)->GetStartMomentum()/CLHEP::GeV);
394 staEk.push_back((float)(*i)->GetStartKineticEnergy()/CLHEP::GeV);
395
396 // fill magnet strength data
397 // NOTE - has a 'continue'
398 if (BDSMagnet* mag = dynamic_cast<BDSMagnet*>(accComp))
399 {
400 const BDSMagnetStrength* ms = mag->MagnetStrength();
401 if (!ms)
402 {
403 fillzero();
404 continue;
405 }
406 // assume localNorm and normComponents are same size
407 std::vector<G4double> normComponents = ms->NormalComponents();
408 for (int j = 0; j < (int)localNorm.size(); j++)
409 {localNorm[j]->push_back((float)normComponents[j]);}
410 std::vector<G4double> skewComponents = ms->SkewComponents();
411 for (int j = 0; j < (int)localSkew.size(); j++)
412 {localSkew[j]->push_back((float)skewComponents[j]);}
413
414 ks.push_back((float)((*ms)["ks"]/BDSMagnetStrength::Unit("ks")));
415 hkick.push_back( (float)((*ms)["hkick"]/BDSMagnetStrength::Unit("hkick")));
416 vkick.push_back( (float)((*ms)["vkick"]/BDSMagnetStrength::Unit("vkick")));
417 bField.push_back((float)((*ms)["field"]/BDSMagnetStrength::Unit("field")));
418 eField.push_back((float)((*ms)["efield"]/BDSMagnetStrength::Unit("efield")));
419 e1.push_back((float)((*ms)["e1"]/BDSMagnetStrength::Unit("e1")));
420 e2.push_back((float)((*ms)["e2"]/BDSMagnetStrength::Unit("e2")));
421 hgap.push_back((float)((*ms)["hgap"]/BDSMagnetStrength::Unit("hgap")));
422 fint.push_back((float)(*ms)["fint"]);
423 fintx.push_back((float)(*ms)["fintx"]);
424 fintk2.push_back((float)(*ms)["fintk2"]);
425 fintxk2.push_back((float)(*ms)["fintxk2"]);
426 }
427 else
428 {// not a magnet
429 fillzero();
430 }
431 }
432}
433#endif
const BDSBeamline * BeamlineMain() const
Accessor.
Holder class for all information required to describe a beam pipe model.
G4double aper3
Public member for direct access.
G4double aper1
Public member for direct access.
G4double aper4
Public member for direct access.
G4double aper2
Public member for direct access.
BDSBeamPipeType beamPipeType
Public member for direct access.
A vector of BDSBeamlineElement instances - a beamline.
BeamlineVector::size_type size() const
Get the number of elements.
iterator begin()
Iterator mechanics.
iterator end()
Iterator mechanics.
Efficient storage of magnet strengths.
std::vector< G4double > NormalComponents() const
Accessor for all normal components - k1 - k12.
std::vector< G4double > SkewComponents() const
Accessor for all skew components - k1 - k12.
static G4double Unit(const G4String &key)
Access a unit factor for a given key.
Abstract base class that implements features common to all magnets.
Definition BDSMagnet.hh:45
Information stored per model representing accelerator.
std::vector< BDSOutputROOTEventCollimatorInfo > collimatorInfo
Collimator information explicitly.
bool storeCollimatorInfo
Whether optional collimator information was stored.
std::vector< float > vkick
Vertical fractional momentum kick.
std::vector< float > eField
E field in V/m.
std::vector< std::string > collimatorBranchNamesUnique
Vector of all collimator branch names in event tree used to load data.
int nCollimators
Number of collimators in beam line.
int nCavities
Number of cavities in beam line.
virtual ~BDSOutputROOTEventModel()
Destructor.
int findNearestElement(const TVector3 &point) const
Find element index closest to point.
std::vector< float > bField
B field in T.
std::vector< float > hkick
Horizontal fractional momentum kick.
std::vector< std::string > material
Material associated with element if any.
std::vector< BDSOutputROOTEventCavityInfo > cavityInfo
cavity information explicitly.
void Flush()
Initialise all members.
virtual void Fill(const std::vector< G4int > &collimatorIndicesIn={}, const std::map< G4String, G4int > &collimatorIndicesByNameIn={}, const std::vector< BDSOutputROOTEventCollimatorInfo > &collimatorInfoIn={}, const std::vector< G4String > &collimatorBranchNamesIn={}, const std::vector< G4int > &cavityIndicesIn={}, const std::map< G4String, G4int > &cavityIndicesByNameIn={}, const std::vector< BDSOutputROOTEventCavityInfo > &cavityInfoIn={}, const std::vector< G4String > &cavityBranchNamesIn={}, const std::map< G4String, G4Transform3D > *scorerMeshPlacements=nullptr, const std::map< short int, G4String > *materialIDToNameUnique=nullptr, G4bool storeTrajectory=false)
Fill root output.
std::vector< std::string > cavityBranchNamesUnique
Vector of all cavity branch names in event tree used to load data.
BDSOutputROOTEventModel()
Default constructor.
std::map< std::string, int > collimatorIndicesByName
Similar cache but by name of collimator as built by BDSIM.
std::vector< float > ks
Solenoid strength.
bool storeCavityInfo
Whether optional cavity information was stored.
TRotation ConvertToROOT(const G4RotationMatrix *rm) const
Utility function.
std::map< std::string, int > cavityIndicesByName
Similar cache but by name of cavity as built by BDSIM.
const std::set< G4VPhysicalVolume * > * PVsForBeamlineElement(BDSBeamlineElement *element) const
Access a set of volumes registered for the placement of a beamline element.
static BDSPhysicalVolumeInfoRegistry * Instance()
Singleton accessor.
static BDSSamplerRegistry * Instance()
Accessor for registry.
A holder for any placement offsets and rotations for a BDSAcceleratorComponent.
G4double GetYOffset() const
Accessor.
G4double GetXOffset() const
Accessor.
G4double GetTilt() const
Accessor.