BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSTunnelFactoryCircular.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 "BDSTunnelFactoryBase.hh"
19#include "BDSTunnelFactoryCircular.hh"
20#include "BDSTunnelInfo.hh"
21#include "BDSTunnelSection.hh"
22
23#include "globals.hh" // geant4 globals / types
24#include "G4Box.hh"
25#include "G4CutTubs.hh"
26#include "G4IntersectionSolid.hh"
27#include "G4LogicalVolume.hh"
28#include "G4SubtractionSolid.hh"
29#include "G4ThreeVector.hh"
30#include "G4Tubs.hh"
31#include "G4UnionSolid.hh"
32#include "G4VSolid.hh"
33
34#include <cmath> // sin, cos, fabs
35#include <set>
36#include <utility> // for std::pair
37
38BDSTunnelFactoryCircular::BDSTunnelFactoryCircular()
39{;}
40
42 G4double length,
43 G4double tunnelThickness,
44 G4double tunnelSoilThickness,
45 G4Material* tunnelMaterial,
46 G4Material* tunnelSoilMaterial,
47 G4bool tunnelFloor,
48 G4double tunnelFloorOffset,
49 G4double tunnel1,
50 G4double /*tunnel2*/,
51 G4bool visible)
52{
53 // tidy up things from previous usage if any - base class method
54 CleanUp();
55
56 // test input parameters - set global options as default if not specified
57 TestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial,
58 tunnelSoilMaterial, tunnelFloorOffset, tunnel1);
59
60 // build the solids
61 tunnelSolid = new G4Tubs(name + "_tunnel_solid", // name
62 tunnel1 + lengthSafety, // inner radius
63 tunnel1 + tunnelThickness, // outer radius
64 length*0.5 - lengthSafety, // z half length
65 0, // start angle
66 CLHEP::twopi); // sweep angle
67
68 G4double soilInnerR = tunnel1 + tunnelThickness + lengthSafety;
69 G4double soilOuterR = soilInnerR + tunnelSoilThickness;
70 soilSolid = new G4Tubs(name + "_soil_solid", // name
71 soilInnerR, // inner radius
72 soilOuterR, // outer radius
73 length*0.5 - lengthSafety, // z half length
74 0, // start angle
75 CLHEP::twopi); // sweep angle
76
77 G4double containerRadius = soilOuterR + lengthSafety;
78
79 // build the floor if necessary
80 if (tunnelFloor)
81 {
82 G4double floorBoxRadius = 1.5*tunnel1; // will definitely encompass the tunnel
83 G4double floorCylinderRadius = tunnel1 - lengthSafety; // so it fits within the tunnel
84 G4double floorBoxDisplacement = tunnelFloorOffset + floorBoxRadius + lengthSafety;
85
86 G4VSolid* floorCylinder = new G4Tubs(name + "_floor_cylinder_solid", // name
87 0, // inner radius
88 floorCylinderRadius, // outer radius
89 length*0.5 - lengthSafety, // z half length
90 0, // start angle
91 CLHEP::twopi); // sweep angle
92
93 G4VSolid* floorBox = new G4Box(name + "_floor_box_solid", // name
94 floorBoxRadius, // x half width
95 floorBoxRadius, // y half width
96 length); // z half length
97 // box z length extra long for unambiguous subtraction
98
99 floorSolid = new G4IntersectionSolid(name + "_floor_solid", // name
100 floorCylinder, // this
101 floorBox, // minus this,
102 0, // rotation matrix
103 G4ThreeVector(0,-floorBoxDisplacement,0)); // translation
104
105 // need to create a container for the tunnel + floor that only just contains it
106 // need to do the same trick again - prepare small floor container segment and union
107 // it with tunnel container. Container has to be a wee bit bigger so can't use the same
108 // solids sadly.
109
110 // floor container cylinder has to definitely overlaps with outside cylinder -> tunnel1*1.1
111 G4VSolid* floorContainerCylinder = new G4Tubs(name + "_floor_cont_cyl_solid", // name
112 0, // inner radius
113 tunnel1*1.1, // outer radius
114 length*0.5, // z half length
115 0, // start angle
116 CLHEP::twopi); // sweep angle
117
118 G4VSolid* floorContainerBox = new G4Box(name + "_floor_cont_box_solid", // name
119 floorBoxRadius, // x half width
120 floorBoxRadius, // y half width
121 length); // z half length
122 // z long for unambiguous intersection
123
124 // calculate box container offset - should be just above floor by lengthsafety (floor actually lowered
125 // by length safety a la rest of geometry to fit within its dimensions)
126 G4double floorBoxContDisp = floorBoxDisplacement - lengthSafety;
127 G4VSolid* floorContainerSolid = new G4IntersectionSolid(name + "_floor_cont_solid", // name
128 floorContainerCylinder, // this
129 floorContainerBox, // minus this,
130 0, // rotation matrix
131 G4ThreeVector(0,-floorBoxContDisp,0));// translation
132
133 G4VSolid* tunnelContainerSolid = new G4Tubs(name + "_tunnel_solid", // name
134 tunnel1, // inner radius
135 containerRadius, // outer radius
136 length*0.5, // z half length
137 0, // start angle
138 CLHEP::twopi); // sweep angle
139
140 containerSolid = new G4UnionSolid(name + "_container_solid", // name
141 tunnelContainerSolid, // this
142 floorContainerSolid); // plus this
143 }
144 else
145 {
146 containerSolid = new G4Tubs(name + "_tunnel_container_solid", // name
147 tunnel1, // inner radius
148 containerRadius, // outer radius,
149 0.5*length, // z half length
150 0, // start angle
151 CLHEP::twopi); // sweep angle
152 }
153
154 CommonConstruction(name, tunnelMaterial, tunnelSoilMaterial, length, containerRadius, containerRadius, visible);
155
156 return tunnelSection;
157}
158
159
161 G4double length,
162 G4ThreeVector inputFace,
163 G4ThreeVector outputFace,
164 G4double tunnelThickness,
165 G4double tunnelSoilThickness,
166 G4Material* tunnelMaterial,
167 G4Material* tunnelSoilMaterial,
168 G4bool tunnelFloor,
169 G4double tunnelFloorOffset,
170 G4double tunnel1,
171 G4double /*tunnel2*/,
172 G4bool visible)
173{
174 // tidy up things from previous usage if any - base class method
175 CleanUp();
176
177 // test input parameters - set global options as default if not specified
178 TestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial,
179 tunnelSoilMaterial, tunnelFloorOffset, tunnel1);
180
181 // build the solids
182 tunnelSolid = new G4CutTubs(name + "_tunnel_solid", // name
183 tunnel1, // inner radius
184 tunnel1 + tunnelThickness, // outer radius
185 length*0.5 - lengthSafety, // z half length
186 0, // start angle
187 CLHEP::twopi, // sweep angle
188 inputFace, // input face normal vector
189 outputFace); // output face normal vector
190
191 G4double soilInnerR = tunnel1 + tunnelThickness + lengthSafety;
192 G4double soilOuterR = soilInnerR + tunnelSoilThickness;
193 soilSolid = new G4CutTubs(name + "_soil_solid", // name
194 soilInnerR, // inner radius
195 soilOuterR, // outer radius
196 length*0.5 - lengthSafety, // z half length
197 0, // start angle
198 CLHEP::twopi, // sweep angle
199 inputFace, // input face normal vector
200 outputFace); // output face normal vector
201
202 G4double containerRadius = soilOuterR + lengthSafety;
203
204 // build the floor if necessary
205 if (tunnelFloor)
206 {
207 // these three lines are a repeat of the same part in the first function (~L211)
208 G4double floorBoxRadius = 1.5*tunnel1; // will definitely encompass the tunnel
209 G4double floorCylinderRadius = tunnel1 - lengthSafety; // so it fits within the tunnel
210 G4double floorBoxDisplacement = tunnelFloorOffset + floorBoxRadius + lengthSafety;
211
212 G4VSolid* floorCylinder = new G4CutTubs(name + "_floor_cylinder_solid", // name
213 0, // inner radius
214 floorCylinderRadius, // outer radius
215 length*0.5 - lengthSafety, // z half length
216 0, // start angle
217 CLHEP::twopi, // sweep angle
218 inputFace, // input face normal vector
219 outputFace); // output face normal vector
220
221 G4VSolid* floorBox = new G4Box(name + "_floor_box_solid", // name
222 floorBoxRadius, // x half width
223 floorBoxRadius, // y half width
224 length); // z half length
225 // z long for unambiguous intersection
226
227 // register solids
228 allSolids.insert(floorCylinder);
229 allSolids.insert(floorBox);
230
231 floorSolid = new G4IntersectionSolid(name + "_floor_solid", // name
232 floorCylinder, // this
233 floorBox, // minus this,
234 0, // rotation matrix
235 G4ThreeVector(0,-floorBoxDisplacement,0)); // translation
236
237 // floor container cylinder has to definitely overlaps with outside cylinder -> tunnel1*1.1
238 G4VSolid* floorContainerCylinder = new G4CutTubs(name + "_floor_cont_cyl_solid", // name
239 0, // inner radius
240 tunnel1*1.1, // outer radius
241 length*0.5, // z half length
242 0, // start angle
243 CLHEP::twopi, // sweep angle
244 inputFace, // input face normal
245 outputFace); // output face normal
246
247 G4VSolid* floorContainerBox = new G4Box(name + "_floor_cont_box_solid", // name
248 1.5*tunnel1, // x half width
249 1.5*tunnel1, // y half width
250 length); // z half length
251 // floor container box z long for unambiguous intersection
252
253 // register solids
254 allSolids.insert(floorContainerCylinder);
255 allSolids.insert(floorContainerBox);
256
257 // calculate box container offset - should be just above floor by lengthsafety (floor actually lowered
258 // by length safety a la rest of geometry to fit within its dimensions)
259 G4double floorBoxContDisp = floorBoxDisplacement - lengthSafety;
260 G4VSolid* floorContainerSolid = new G4IntersectionSolid(name + "_floor_cont_solid", // name
261 floorContainerCylinder, // this
262 floorContainerBox, // minus this,
263 0, // rotation matrix
264 G4ThreeVector(0,-floorBoxContDisp,0));// translation
265
266 G4VSolid* tunnelContainerSolid = new G4CutTubs(name + "_tunnel_solid", // name
267 tunnel1 - lengthSafety, // inner radius
268 containerRadius, // outer radius
269 length*0.5, // z half length
270 0, // start angle
271 CLHEP::twopi, // sweep angle
272 inputFace, // input face normal vector
273 outputFace); // output face normal vector
274
275 // register solids
276 allSolids.insert(floorContainerSolid);
277 allSolids.insert(tunnelContainerSolid);
278
279 containerSolid = new G4UnionSolid(name + "_container_solid", // name
280 tunnelContainerSolid, // this
281 floorContainerSolid); // plus this
282
283 G4VSolid* intersectionSolidCylinder = new G4CutTubs(name + "_int_cyl_solid", // name
284 0, // inner radius
285 tunnel1 - 2*lengthSafety, // outer radius
286 length*0.5, // z half length
287 0, // start angle
288 CLHEP::twopi, // sweep angle
289 inputFace, // input face normal vector
290 outputFace); // output face normal vector
291 allSolids.insert(intersectionSolidCylinder);
292
293 intersectionSolid = new G4SubtractionSolid(name + "_intersection_solid", // name
294 intersectionSolidCylinder, // this
295 floorContainerSolid, // minus this,
296 0, // rotation
297 G4ThreeVector(0,-floorBoxContDisp+lengthSafety,0)); // translation
298 }
299 else
300 {
301 containerSolid = new G4CutTubs(name + "_tunnel_container_solid", // name
302 tunnel1, // inner radius
303 containerRadius, // outer radius,
304 length*0.5, // z half length
305 0, // start angle
306 CLHEP::twopi, // sweep angle
307 inputFace, // input face normal vector
308 outputFace); // output face normal vector
309
310 intersectionSolid = new G4CutTubs(name + "_tunnel_intersection_solid", // name
311 0, // inner radius
312 tunnel1 - 2*lengthSafety, // outer radius
313 length*0.5, // z half length
314 0, // start angle
315 CLHEP::twopi, // sweep angle
316 inputFace, // input face normal vector
317 outputFace); // output face normal vector
318 }
319
320 CommonConstruction(name, tunnelMaterial, tunnelSoilMaterial, length, containerRadius,
321 containerRadius, visible);
322
323 return tunnelSection;
324}
325
328 G4double& tunnelThickness,
329 G4double& tunnelSoilThickness,
330 G4Material*& tunnelMaterial,
331 G4Material*& tunnelSoilMaterial,
332 G4double& tunnelFloorOffset,
333 G4double& tunnel1)
334{
335 CommontTestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial, tunnelSoilMaterial);
336
337 if (tunnelFloorOffset < 1e-10)
338 {tunnelFloorOffset = defaultModel->floorOffset;}
339
340 if (tunnel1 < 1e-10)
341 {tunnel1 = defaultModel->aper1;}
342}
G4double lengthSafety
Cache of global constants variable.
void CommontTestInputParameters(G4double &length, G4double &tunnelThickness, G4double &tunnelSoilThickness, G4Material *&tunnelMaterial, G4Material *&tunnelSoilMaterial)
virtual BDSTunnelSection * CreateTunnelSection(G4String name, G4double length, G4double tunnelThickness, G4double tunnelSoilThickness, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial, G4bool tunnelFloor, G4double tunnelFloorOffset, G4double tunnel1, G4double tunnel2, G4bool visible)
Create a tunnel section with flat input and output faces.
virtual BDSTunnelSection * CreateTunnelSectionAngled(G4String name, G4double length, G4ThreeVector inputFace, G4ThreeVector outputFace, G4double tunnelThickness, G4double tunnelSoilThickness, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial, G4bool tunnelFloor, G4double tunnelFloorOffset, G4double tunnel1, G4double tunnel2, G4bool visible)
Create a tunnel section with an angled input and output face.
void TestInputParameters(G4double &length, G4double &tunnelThickness, G4double &tunnelSoilThickness, G4Material *&tunnelMaterial, G4Material *&tunnelSoildMaterial, G4double &tunnelFloorOffset, G4double &tunnel1)
functions below here are private to this particular factory
G4double aper1
Tunnel aperture / shape parameter 1.
Class that represents a section of tunnel.