BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSGeometryComponent.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
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 "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSExtent.hh"
22#include "BDSGeometryComponent.hh"
23#include "BDSSDManager.hh"
24#include "BDSSDType.hh"
25
26#include "globals.hh"
27#include "G4AssemblyVolume.hh"
28#include "G4LogicalVolume.hh"
29#include "G4RotationMatrix.hh"
30#include "G4UserLimits.hh"
31#include "G4VisAttributes.hh"
32#include "G4VPhysicalVolume.hh"
33#include "G4VSolid.hh"
34
35#include <algorithm>
36#include <map>
37#include <set>
38
39class G4VSensitiveDetector;
40
41BDSGeometryComponent::BDSGeometryComponent(G4VSolid* containerSolidIn,
42 G4LogicalVolume* containerLVIn,
43 const BDSExtent& extentIn,
44 const BDSExtent& innerExtentIn,
45 const G4ThreeVector& placementOffsetIn,
46 G4RotationMatrix* placementRotationIn):
47 containerIsAssembly(false),
48 containerSolid(containerSolidIn),
49 containerLogicalVolume(containerLVIn),
50 containerAssembly(nullptr),
51 outerExtent(extentIn),
52 innerExtent(innerExtentIn),
53 overrideSensitivity(false),
54 placementOffset(placementOffsetIn),
55 placementRotation(placementRotationIn),
56 lvsExcludedFromBiasing(nullptr)
57{;}
58
59BDSGeometryComponent::BDSGeometryComponent(G4AssemblyVolume* containerAssemblyIn,
60 const BDSExtent& extentIn,
61 const BDSExtent& innerExtentIn,
62 const G4ThreeVector& placementOffsetIn,
63 G4RotationMatrix* placementRotationIn):
64 containerIsAssembly(true),
65 containerSolid(nullptr),
66 containerLogicalVolume(nullptr),
67 containerAssembly(containerAssemblyIn),
68 outerExtent(extentIn),
69 innerExtent(innerExtentIn),
70 overrideSensitivity(false),
71 placementOffset(placementOffsetIn),
72 placementRotation(placementRotationIn),
73 lvsExcludedFromBiasing(nullptr)
74{;}
75
76BDSGeometryComponent::BDSGeometryComponent(const BDSGeometryComponent& component):
77 containerIsAssembly(component.containerIsAssembly),
78 containerSolid(component.containerSolid),
79 containerLogicalVolume(component.containerLogicalVolume),
80 containerAssembly(component.containerAssembly),
81 outerExtent(component.outerExtent),
82 innerExtent(component.innerExtent),
83 allLogicalVolumes(component.allLogicalVolumes),
84 sensitivity(component.sensitivity),
85 overrideSensitivity(component.overrideSensitivity),
86 allPhysicalVolumes(component.allPhysicalVolumes),
87 placementOffset(component.placementOffset),
88 placementRotation(component.placementRotation),
89 lvsExcludedFromBiasing(nullptr)
90{;}
91
92BDSGeometryComponent::~BDSGeometryComponent()
93{
94 for (auto daughter : allDaughters)
95 {delete daughter;}
96
97 // we let Geant4 handle the deletion of physical volumes, logical volumes and solids
98
99 for (auto rm : allRotationMatrices)
100 {delete rm;}
101
102 for (auto vis : allVisAttributes)
103 {delete vis;}
104
105 for (auto ul : allUserLimits)
106 {delete ul;}
107
108 delete placementRotation;
109}
110
112{
113 outerExtent = anotherComponent->GetExtent();
114 innerExtent = anotherComponent->GetInnerExtent();
115}
116
118 const G4ThreeVector &offset)
119{
120 outerExtent = anotherComponent->GetExtent().Translate(offset);
121 innerExtent = anotherComponent->GetInnerExtent().Translate(offset);
122}
123
124void BDSGeometryComponent::RegisterSolid(const std::set<G4VSolid*>& solids)
125{
126 for (auto solid : solids)
127 {RegisterSolid(solid);}
128}
129
130void BDSGeometryComponent::RegisterLogicalVolume(const std::set<G4LogicalVolume*>& logicalVolumes)
131{
132 for (auto lv : logicalVolumes)
134}
135
136void BDSGeometryComponent::RegisterPhysicalVolume(const std::set<G4VPhysicalVolume*>& physicalVolumes)
137{
138 for (auto pv : physicalVolumes)
140}
141
142void BDSGeometryComponent::RegisterRotationMatrix(const std::set<G4RotationMatrix*>& rotationMatrices)
143{
144 for (auto rm : rotationMatrices)
146}
147
148void BDSGeometryComponent::RegisterSensitiveVolume(G4LogicalVolume* sensitiveVolume,
149 BDSSDType sensitivityType)
150{
151 if (!sensitiveVolume)
152 {return;} // can't register nullptr
153#ifdef BDSDEBUG
154 G4cout << __METHOD_NAME__ << sensitiveVolume->GetName() << " : " << sensitivityType << G4endl;
155#endif
156
157 // check and ensure the logical volume is registered in this component
158 RegisterLogicalVolume(sensitiveVolume);
159
160 // this may overwrite it if it's already in the map
161 sensitivity[sensitiveVolume] = sensitivityType;
162}
163
164void BDSGeometryComponent::RegisterSensitiveVolume(const std::set<G4LogicalVolume*>& sensitiveVolumes,
165 BDSSDType sensitivityType)
166{
167 for (auto sv : sensitiveVolumes)
168 {RegisterSensitiveVolume(sv, sensitivityType);}
169}
170
171void BDSGeometryComponent::RegisterSensitiveVolume(const std::map<G4LogicalVolume*, BDSSDType>& sensitiveVolumes)
172{
173 sensitivity.insert(sensitiveVolumes.begin(), sensitiveVolumes.end());
174}
175
176void BDSGeometryComponent::RegisterVisAttributes(const std::set<G4VisAttributes*>& visAttributes)
177{
178 for (auto va : visAttributes)
180}
181
182void BDSGeometryComponent::RegisterUserLimits(const std::set<G4UserLimits*>& userLimits)
183{
184 for (auto ul : userLimits)
185 {RegisterUserLimits(ul);}
186}
187
189{
190 RegisterSolid(component->GetAllSolids());
197}
198
199std::set<G4LogicalVolume*> BDSGeometryComponent::GetAllLogicalVolumes() const
200{
201 std::set<G4LogicalVolume*> result(allLogicalVolumes);
202 for (auto it : allDaughters)
203 {
204 auto dLVs = it->GetAllLogicalVolumes();
205 result.insert(dLVs.begin(), dLVs.end());
206 }
207 return result;
208}
209
210std::set<G4LogicalVolume*> BDSGeometryComponent::GetAllBiasingVolumes() const
211{
212 std::set<G4LogicalVolume*> result(allLogicalVolumes);
213
214 for (auto it : allDaughters) // do the same recursively for daughters
215 {
216 auto dLVs = it->GetAllBiasingVolumes();
217 result.insert(dLVs.begin(), dLVs.end());
218 }
219
221 {
222 for (const auto vol : *lvsExcludedFromBiasing)
223 {result.erase(vol);}
224 }
225 return result;
226}
227
228std::map<G4LogicalVolume*, BDSSDType> BDSGeometryComponent::GetAllSensitiveVolumes() const
229{
230 // start by copy sensitive volumes belonging to this object
231 std::map<G4LogicalVolume*, BDSSDType> result(sensitivity);
232 for (auto it : allDaughters)
233 {
234 auto dSVs = it->GetAllSensitiveVolumes();
235 result.insert(dSVs.begin(), dSVs.end()); // copy into result map
236 }
237 return result;
238}
239
241{
242 BDSSDManager* sdm = BDSSDManager::Instance();
243 for (auto mapping : sensitivity)
244 {mapping.first->SetSensitiveDetector(sdm->SensitiveDetector(mapping.second, !overrideSensitivity));}
245 for (auto daughter : allDaughters)
246 {daughter->AttachSensitiveDetectors();}
247}
248
250{
251 if (allLogicalVolumes.find(lv) == allLogicalVolumes.end())
252 {
253 throw BDSException(__METHOD_NAME__, "excluding volume \"" + lv->GetName()
254 + "\" from component \"" + GetName()
255 + "\" but it's not a member of this piece of geometry or its daughters.");
256 }
257
259 {lvsExcludedFromBiasing = new std::set<G4LogicalVolume*>();}
260 lvsExcludedFromBiasing->insert(lv);
261}
262
264{
266 {return;}
267 containerAssembly = new G4AssemblyVolume();
268 for (G4int i = 0; i < (G4int)containerLogicalVolume->GetNoDaughters(); i++)
269 {
270 auto daughterPV = containerLogicalVolume->GetDaughter(i);
271 auto daughterLV = daughterPV->GetLogicalVolume();
272 auto translation = daughterPV->GetObjectTranslation();
273 auto rotation = daughterPV->GetObjectRotation(); // could be nullptr
274 G4RotationMatrix* rm = rotation ? new G4RotationMatrix(*(rotation)) : nullptr;
275 containerAssembly->AddPlacedVolume(daughterLV, translation, rm);
276 }
277 containerIsAssembly = true;
278}
279
281 G4UserLimits* ul)
282{
283 std::set<G4LogicalVolume*> lvSet;
284 auto it = av->GetVolumesIterator();
285 for (G4int i = 0; i < (G4int)av->TotalImprintedVolumes(); i++, it++)
286 {lvSet.insert((*it)->GetLogicalVolume());}
287 for (auto& lv : lvSet)
288 {lv->SetUserLimits(ul);}
289}
General exception with possible name of object and message.
Definition: BDSException.hh:35
Holder for +- extents in 3 dimensions.
Definition: BDSExtent.hh:39
BDSExtent Translate(const G4ThreeVector &offset) const
Provide a new copy of this extent with an offset applied.
Definition: BDSExtent.hh:125
A generic geometry component for a bdsim model.
void InheritExtents(BDSGeometryComponent const *const anotherComponent)
Update the extents of this object with those of another object.
BDSExtent GetExtent() const
Accessor - see member for more info.
virtual G4String GetName() const
Accessor - see member for more info.
void RegisterRotationMatrix(G4RotationMatrix *rotationMatrix)
std::set< G4UserLimits * > allUserLimits
registry of all user limits belonging to this component
std::set< G4LogicalVolume * > * lvsExcludedFromBiasing
Volumes that should not be included when return GetAllBiasingVolumes().
virtual std::set< G4RotationMatrix * > GetAllRotationMatrices() const
Accessor - see member for more info.
virtual void AttachSensitiveDetectors()
Attach a sensitive detector class to all registered sensitive volumes in this component.
virtual std::set< G4LogicalVolume * > GetAllBiasingVolumes() const
Return all logical volumes that should be used for biasing minus any that are in the excluded set.
void RegisterLogicalVolume(G4LogicalVolume *logicalVolume)
virtual std::set< G4UserLimits * > GetAllUserLimits() const
Accessor - see member for more info.
std::map< G4LogicalVolume *, BDSSDType > sensitivity
virtual std::map< G4LogicalVolume *, BDSSDType > GetAllSensitiveVolumes() const
Access all sensitive volumes belonging to this component.
virtual std::set< G4LogicalVolume * > GetAllLogicalVolumes() const
Access all logical volumes belonging to this component.
void InheritObjects(BDSGeometryComponent *component)
static void AttachUserLimitsToAssembly(G4AssemblyVolume *av, G4UserLimits *ul)
Utility function to apply user limits to an assembly volume as there's not interface.
virtual std::set< G4VisAttributes * > GetAllVisAttributes() const
Accessor - see member for more info.
void RegisterPhysicalVolume(G4VPhysicalVolume *physicalVolume)
virtual std::set< G4VSolid * > GetAllSolids() const
Accessor - see member for more info.
std::set< BDSGeometryComponent * > allDaughters
registry of all daughter geometry components
void RegisterUserLimits(G4UserLimits *userLimit)
virtual void ExcludeLogicalVolumeFromBiasing(G4LogicalVolume *lv)
void StripOuterAndMakeAssemblyVolume()
Change from a container logical volume to an assembly volume.
std::set< G4VisAttributes * > allVisAttributes
registry of all visualisation attributes belonging to this component
std::set< G4RotationMatrix * > allRotationMatrices
registry of all rotation matrices belonging to this component
BDSExtent GetInnerExtent() const
Accessor - see member for more info.
virtual std::set< G4VPhysicalVolume * > GetAllPhysicalVolumes() const
Accessor - see member for more info.
void RegisterVisAttributes(G4VisAttributes *visAttribute)
void RegisterSolid(G4VSolid *solid)
G4RotationMatrix * placementRotation
G4bool containerIsAssembly
True if the 'container' is really an assembly; false if an LV.
void RegisterSensitiveVolume(G4LogicalVolume *sensitiveVolume, BDSSDType sensitivityType)
A singleton class that holds all required sensitive detector class instances.
Definition: BDSSDManager.hh:68
G4VSensitiveDetector * SensitiveDetector(const BDSSDType sdType, G4bool applyOptions=false) const
Improve type-safety of native enum data type in C++.