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