BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSTunnelFactoryBase.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 "BDSAcceleratorComponentRegistry.hh"
20#include "BDSColours.hh"
21#include "BDSDebug.hh"
22#include "BDSException.hh"
23#include "BDSExtent.hh"
24#include "BDSGeometryComponent.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSMaterials.hh"
27#include "BDSSDType.hh"
28#include "BDSTunnelInfo.hh"
29#include "BDSTunnelFactoryBase.hh"
30#include "BDSTunnelSection.hh"
31#include "BDSUtilities.hh" // for calculateorientation
32
33#include "globals.hh" // geant4 globals / types
34#include "G4LogicalVolume.hh"
35#include "G4Material.hh"
36#include "G4PVPlacement.hh"
37#include "G4ThreeVector.hh"
38#include "G4VisAttributes.hh"
39#include "G4UserLimits.hh"
40
41#include <set>
42
44 tunnelComponent(nullptr),
45 tunnelSection(nullptr),
46 containerSolid(nullptr),
47 tunnelSolid(nullptr),
48 soilSolid(nullptr),
49 floorSolid(nullptr),
50 intersectionSolid(nullptr),
51 containerLV(nullptr),
52 tunnelLV(nullptr),
53 soilLV(nullptr),
54 floorLV(nullptr),
55 floorDisplacement(G4ThreeVector(0,0,0)),
56 cumulativeAngle(0)
57{
58 defaultModel = BDSGlobalConstants::Instance()->TunnelInfo();
59}
60
62 G4double length,
63 G4double angleIn,
64 G4double tunnelThickness,
65 G4double tunnelSoilThickness,
66 G4Material* tunnelMaterial,
67 G4Material* tunnelSoilMaterial,
68 G4bool tunnelFloor,
69 G4double tunnelFloorOffset,
70 G4double tunnel1,
71 G4double tunnel2,
72 G4bool visible)
73{
74 return CreateTunnelSectionAngledInOut(name, length, angleIn, 0, tunnelThickness,
75 tunnelSoilThickness, tunnelMaterial, tunnelSoilMaterial,
76 tunnelFloor, tunnelFloorOffset, tunnel1, tunnel2, visible);
77}
78
80 G4double length,
81 G4double angleOut,
82 G4double tunnelThickness,
83 G4double tunnelSoilThickness,
84 G4Material* tunnelMaterial,
85 G4Material* tunnelSoilMaterial,
86 G4bool tunnelFloor,
87 G4double tunnelFloorOffset,
88 G4double tunnel1,
89 G4double tunnel2,
90 G4bool visible)
91{
92 return CreateTunnelSectionAngledInOut(name, length, 0, angleOut, tunnelThickness,
93 tunnelSoilThickness, tunnelMaterial, tunnelSoilMaterial,
94 tunnelFloor, tunnelFloorOffset, tunnel1, tunnel2, visible);
95}
96
98 G4double length,
99 G4double angleIn,
100 G4double angleOut,
101 G4double tunnelThickness,
102 G4double tunnelSoilThickness,
103 G4Material* tunnelMaterial,
104 G4Material* tunnelSoilMaterial,
105 G4bool tunnelFloor,
106 G4double tunnelFloorOffset,
107 G4double tunnel1,
108 G4double tunnel2,
109 G4bool visible)
110{
111 auto faces = BDS::CalculateFaces(angleIn,angleOut);
112 return CreateTunnelSectionAngled(name, length, faces.first, faces.second, tunnelThickness,
113 tunnelSoilThickness, tunnelMaterial, tunnelSoilMaterial,
114 tunnelFloor, tunnelFloorOffset, tunnel1, tunnel2, visible);
115}
116
118 G4double& tunnelThickness,
119 G4double& tunnelSoilThickness,
120 G4Material*& tunnelMaterial,
121 G4Material*& tunnelSoilMaterial)
122{
123 if (length < 4*lengthSafety)
124 {throw BDSException(__METHOD_NAME__, "tunnel section too short - length < 4*length safety");}
125 if (tunnelThickness < 2*lengthSafety)
126 {throw BDSException(__METHOD_NAME__, "tunnel section thickness too thin - thickness < 2*length safety");}
127 if (tunnelSoilThickness < 2*lengthSafety)
128 {throw BDSException(__METHOD_NAME__, "tunnel section soil thickness too thin - thickness < 2*length safety");}
129 if (!tunnelMaterial)
130 {tunnelMaterial = defaultModel->material;}
131
132 if (!tunnelSoilMaterial)
133 {tunnelSoilMaterial = defaultModel->soilMaterial;}
134}
135
136void BDSTunnelFactoryBase::CommonConstruction(G4String name,
137 G4Material* tunnelMaterial,
138 G4Material* tunnelSoilMaterial,
139 G4double length,
140 G4double containerXRadius,
141 G4double containerYRadius,
142 G4bool visible)
143
144{
145 BuildLogicalVolumes(name, tunnelMaterial, tunnelSoilMaterial);
146 SetVisAttributes(visible);
148 PlaceComponents(name);
149 PrepareGeometryComponent(containerXRadius, containerYRadius, 0.5*length);
151 PrepareTunnelSection(name, length);
152}
153
155 G4Material* tunnelMaterial,
156 G4Material* tunnelSoilMaterial)
157{
158 // build logical volumes
159 G4Material* worldMaterial = BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->WorldMaterial());
160 containerLV = new G4LogicalVolume(containerSolid,
161 worldMaterial,
162 name + "_container_lv");
163
164 tunnelLV = new G4LogicalVolume(tunnelSolid,
165 tunnelMaterial,
166 name + "_tunnel_lv");
167
168 if (soilSolid)
169 {
170 soilLV = new G4LogicalVolume(soilSolid,
171 tunnelSoilMaterial,
172 name + "_soil_lv");
173 }
174 // remember the floor is optional
175 if (floorSolid)
176 {
177 floorLV = new G4LogicalVolume(floorSolid,
178 tunnelMaterial,
179 name + "_floor_lv");
180 }
181}
182
184{
185 // note these could actually be owned by the factory or kept in one place as they're
186 // always the same - this would however mean that the objects would have a dependency
187 // on the factory which shouldn't happen - so waste a little memory just now on visattrs
188
189 // tunnel & floor - a nice grey
190 G4VisAttributes* tunnelVisAttr = new G4VisAttributes(*BDSColours::Instance()->GetColour("tunnel"));
191 if (visible)
192 {tunnelVisAttr->SetVisibility(true);}
193 tunnelVisAttr->SetForceLineSegmentsPerCircle(BDSGlobalConstants::Instance()->NSegmentsPerCircle()*2);
194 tunnelLV->SetVisAttributes(tunnelVisAttr);
195 allVisAttributes.insert(tunnelVisAttr);
196 if (floorLV)
197 {
198 G4VisAttributes* floorVisAttr = new G4VisAttributes(*BDSColours::Instance()->GetColour("tunnelfloor"));
199 if (visible)
200 {floorVisAttr->SetVisibility(true);}
201 floorVisAttr->SetForceLineSegmentsPerCircle(BDSGlobalConstants::Instance()->NSegmentsPerCircle()*2);
202 floorLV->SetVisAttributes(floorVisAttr);
203 allVisAttributes.insert(floorVisAttr);
204 }
205 // soil - brown
206 if (soilLV)
207 {
208 G4VisAttributes* soilVisAttr = new G4VisAttributes(*BDSColours::Instance()->GetColour("soil"));
209 if (visible)
210 {soilVisAttr->SetVisibility(true);}
211 soilVisAttr->SetForceLineSegmentsPerCircle(BDSGlobalConstants::Instance()->NSegmentsPerCircle());
212 soilLV->SetVisAttributes(soilVisAttr);
213 allVisAttributes.insert(soilVisAttr);
214 }
215 // container & read out
216 containerLV->SetVisAttributes(BDSGlobalConstants::Instance()->ContainerVisAttr());
217}
218
220 G4double containerYRadius,
221 G4double containerZRadius)
222{
223 // prepare final object and register logical volumes
224 tunnelComponent = new BDSGeometryComponent(containerSolid, containerLV);
225 tunnelComponent->RegisterLogicalVolume(tunnelLV);
226 tunnelComponent->RegisterLogicalVolume(soilLV);
227 if (floorLV)
228 {tunnelComponent->RegisterLogicalVolume(floorLV);}
229
230 // register objects
231 tunnelComponent->RegisterSolid(allSolids);
232 tunnelComponent->RegisterVisAttributes(allVisAttributes);
233
234 // record extents
235 // use the read out geometry for the limits as it's the maximum of x and y
236 // in radius. The read out world is a duplicate of the real mass world so
237 // we fiddle the extents here as the extents of the read out don't exist and
238 // this is relatively safe as nothing will be placed against the outside edge
239 // of the soil.
240 tunnelComponent->SetExtent(BDSExtent(containerXRadius, containerYRadius, containerZRadius));
241}
242
244 G4double chordLength)
245{
246 tunnelSection = new BDSTunnelSection(name,
247 chordLength,
249 tunnelComponent,
250 intersectionSolid);
251
252 // nominally, we'd leave this to something outside the factory, but seeing as this is
253 // the only place where these are constructed, it's easier to do here.
255}
256
258{
259 // Register components as sensitive with BDSGeometryComponent instance.
260 // As they use a (tunnel specific) read out geometry, the require attaching
261 // only once the beamline has been constructed - done in BDSDetectorConstruction.
262 // World must be already constructed, which requires beam line to be already constructed.
263 tunnelComponent->RegisterSensitiveVolume(tunnelLV, BDSSDType::energydeptunnel);
264 if (soilLV)
265 {tunnelComponent->RegisterSensitiveVolume(soilLV, BDSSDType::energydeptunnel);}
266 if (floorLV)
267 {tunnelComponent->RegisterSensitiveVolume(floorLV, BDSSDType::energydeptunnel);}
268}
269
271{
272 auto tunnelUserLimits = BDSGlobalConstants::Instance()->DefaultUserLimitsTunnel();
273 //attach cuts to volumes
274 tunnelLV->SetUserLimits(tunnelUserLimits);
275 if (soilLV)
276 {soilLV->SetUserLimits(tunnelUserLimits);}
277 if (floorLV)
278 {floorLV->SetUserLimits(tunnelUserLimits);}
279 containerLV->SetUserLimits(tunnelUserLimits);
280}
281
283{
284 // PLACEMENT
285 // place the components inside the container
286 // note we don't need the pointer for anything - it's registered upon construction with g4
287 new G4PVPlacement(nullptr, // no rotation
288 G4ThreeVector(), // position
289 tunnelLV, // lv to be placed
290 name + "_tunnel_pv", // name
291 containerLV, // mother lv to be placed in
292 false, // no boolean operation
293 0, // copy number
294 checkOverlaps); // whether to check overlaps
295 if (soilLV)
296 {
297 new G4PVPlacement(nullptr, // no rotation
298 G4ThreeVector(), // position
299 soilLV, // lv to be placed
300 name + "_soil_pv", // name
301 containerLV, // mother lv to be placed in
302 false, // no boolean operation
303 0, // copy number
304 checkOverlaps); // whether to check overlaps
305 }
306 if (floorLV)
307 {
308 new G4PVPlacement(nullptr, // no rotation
309 floorDisplacement, // position
310 floorLV, // lv to be placed
311 name + "_floor_pv", // name
312 containerLV, // mother lv to be placed in
313 false, // no boolean operation
314 0, // copy number
315 checkOverlaps); // whether to check overlaps
316 }
317}
318
320{
322 tunnelSection = nullptr;
323 containerSolid = nullptr;
324 tunnelSolid = nullptr;
325 soilSolid = nullptr;
326 floorSolid = nullptr;
327 intersectionSolid = nullptr;
328 containerLV = nullptr;
329 tunnelLV = nullptr;
330 soilLV = nullptr;
331 floorLV = nullptr;
332 floorDisplacement = G4ThreeVector(0,0,0);
333 cumulativeAngle = 0;
334}
static BDSAcceleratorComponentRegistry * Instance()
Singleton accessor.
void RegisterTunnelComponent(BDSAcceleratorComponent *component)
static BDSColours * Instance()
singleton pattern
Definition: BDSColours.cc:33
General exception with possible name of object and message.
Definition: BDSException.hh:35
Holder for +- extents in 3 dimensions.
Definition: BDSExtent.hh:39
G4bool checkOverlaps
Cache of global constants variable.
G4double lengthSafety
Cache of global constants variable.
virtual void FactoryBaseCleanUp()
Empty containers for next use - factories are never deleted so can't rely on scope.
A generic geometry component for a bdsim model.
void RegisterLogicalVolume(G4LogicalVolume *logicalVolume)
void SetExtent(const BDSExtent &extIn)
Set extent.
void RegisterVisAttributes(G4VisAttributes *visAttribute)
void RegisterSolid(G4VSolid *solid)
void RegisterSensitiveVolume(G4LogicalVolume *sensitiveVolume, BDSSDType sensitivityType)
static BDSGlobalConstants * Instance()
Access method.
static BDSMaterials * Instance()
Singleton pattern access.
Definition: BDSMaterials.cc:38
G4Material * GetMaterial(G4String material) const
Get material by name.
BDSTunnelFactoryBase()
protected default constructor so only derived classes can use it
virtual BDSTunnelSection * CreateTunnelSectionAngledInOut(G4String name, G4double length, G4double angleIn, G4double angleOut, G4double tunnelThickness, G4double tunnelSoilThickness, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial, G4bool tunnelFloor, G4double tunnelFloorOffset, G4double tunnel1, G4double tunnel2, G4bool visible)
virtual void PrepareGeometryComponent(G4double containerXRadius, G4double containerYRadius, G4double containerZRadius)
Prepare the assembled geometry component.
virtual void SetSensitiveVolumes()
Set the sensitive volumes.
void CommontTestInputParameters(G4double &length, G4double &tunnelThickness, G4double &tunnelSoilThickness, G4Material *&tunnelMaterial, G4Material *&tunnelSoilMaterial)
virtual void SetUserLimits()
Set user limits for all logical volumes in the tunnel section.
virtual BDSTunnelSection * CreateTunnelSectionAngled(G4String name, G4double length, G4ThreeVector inputFaceIn, G4ThreeVector outputFaceIn, G4double tunnelThickness, G4double tunnelSoilThickness, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial, G4bool tunnelFloor, G4double tunnelFloorOffset, G4double tunnel1, G4double tunnel2, G4bool visible)=0
Create a tunnel section with an angled input and output face. Pure virtual.
virtual BDSTunnelSection * CreateTunnelSectionAngledIn(G4String name, G4double length, G4double angleIn, G4double tunnelThickness, G4double tunnelSoilThickness, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial, G4bool tunnelFloor, G4double tunnelFloorOffset, G4double tunnel1, G4double tunnel2, G4bool visible)
virtual void SetVisAttributes(G4bool visible)
Set the visual attributes for each logical volume.
virtual BDSTunnelSection * CreateTunnelSectionAngledOut(G4String name, G4double length, G4double angleOut, G4double tunnelThickness, G4double tunnelSoilThickness, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial, G4bool tunnelFloor, G4double tunnelFloorOffset, G4double tunnel1, G4double tunnel2, G4bool visible)
virtual void PlaceComponents(G4String name)
Place components in container volume.
virtual void PrepareTunnelSection(G4String name, G4double chordLength)
Prepare the output BDSTunnelSection instance.
virtual void BuildLogicalVolumes(G4String name, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial)
Build logical volumes from solids + materials.
Class that represents a section of tunnel.
std::pair< G4ThreeVector, G4ThreeVector > CalculateFaces(G4double angleInIn, G4double angleOutIn)
Calculate input and output normal vector.