BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSTunnelFactoryElliptical.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 "BDSTunnelFactoryElliptical.hh"
20#include "BDSTunnelInfo.hh"
21
22#include "globals.hh" // geant4 globals / types
23#include "G4Box.hh"
24#include "G4CutTubs.hh"
25#include "G4EllipticalTube.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
39
40BDSTunnelFactoryElliptical::BDSTunnelFactoryElliptical()
41{;}
42
44 G4double length,
45 G4double tunnelThickness,
46 G4double tunnelSoilThickness,
47 G4Material* tunnelMaterial,
48 G4Material* tunnelSoilMaterial,
49 G4bool tunnelFloor,
50 G4double tunnelFloorOffset,
51 G4double tunnel1,
52 G4double tunnel2,
53 G4bool visible)
54{
55 // tidy up things from previous usage if any - base class method
56 CleanUp();
57
58 // test input parameters - set global options as default if not specified
59 TestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial,
60 tunnelSoilMaterial, tunnelFloorOffset, tunnel1, tunnel2);
61
62 // build the solids
63 G4VSolid* tunnelOuterSolid = new G4EllipticalTube(name + "_tunnel_outer_solid", // name
64 tunnel1 + tunnelThickness, // x radius
65 tunnel2 + tunnelThickness, // y radius
66 0.5*length - lengthSafety); // z half length (to fit in container)
67
68 G4VSolid* tunnelInnerSolid = new G4EllipticalTube(name + "_tunnel_outer_solid", // name
69 tunnel1 + lengthSafety, // x radius
70 tunnel2 + lengthSafety, // y radius
71 length); // z half length - long for unambiguous subtraction
72
73 // register solids
74 allSolids.insert(tunnelOuterSolid);
75 allSolids.insert(tunnelInnerSolid);
76
77 tunnelSolid = new G4SubtractionSolid(name + "_tunnel_solid", // name
78 tunnelOuterSolid, // this
79 tunnelInnerSolid); // minus this
80
81
82 G4double soil1R = tunnel1 + tunnelThickness + lengthSafety;
83 G4double soil2R = tunnel2 + tunnelThickness + lengthSafety;
84
85 G4double soilOuterRadius = std::max(soil1R, soil2R) + tunnelSoilThickness;
86
87 G4VSolid* soilOuterSolid = new G4Tubs(name + "_soil_outer_solid", // name
88 0, // inner radius
89 soilOuterRadius, // outer radius
90 0.5*length - lengthSafety, // z half angle
91 0, // start angle
92 CLHEP::twopi); // sweep angle
93
94 G4VSolid* soilInnerSolid = new G4EllipticalTube(name + "_soil_outer_solid", // name
95 soil1R + lengthSafety, // x radius
96 soil2R + lengthSafety, // y radius
97 length); // z half length - long for unambiguous subtraction
98
99 // register solids
100 allSolids.insert(soilOuterSolid);
101 allSolids.insert(soilInnerSolid);
102
103 soilSolid = new G4SubtractionSolid(name + "_soil_solid", // name
104 soilOuterSolid, // this
105 soilInnerSolid); // minus this
106
107 G4double containerXRadius = soil1R + tunnelSoilThickness + lengthSafety;
108 G4double containerYRadius = soil2R + tunnelSoilThickness + lengthSafety;
109
110 // build the floor if necessary
111 if (tunnelFloor)
112 {
113 G4double floorBoxRadius = 1.5 * std::max(tunnel1,tunnel2); // will definitely encompass the tunnel
114 G4double floorBoxDisplacement = tunnelFloorOffset + floorBoxRadius + lengthSafety;
115
116 G4VSolid* floorEllipse = new G4EllipticalTube(name + "_floor_ellipse_solid", // name
117 tunnel1, // x radius
118 tunnel2, // y radius
119 length*0.5 - lengthSafety); // z half length
120
121 G4VSolid* floorBox = new G4Box(name + "_floor_box_solid", // name
122 floorBoxRadius, // x half width
123 floorBoxRadius, // y half width
124 length); // z half length
125 // box z length extra long for unambiguous subtraction
126
127 // register solids
128 allSolids.insert(floorEllipse);
129 allSolids.insert(floorBox);
130
131 floorSolid = new G4IntersectionSolid(name + "_floor_solid", // name
132 floorEllipse, // this
133 floorBox, // minus this,
134 0, // rotation matrix
135 G4ThreeVector(0,-floorBoxDisplacement,0)); // translation
136
137 // need to create a container for the tunnel + floor that only just contains it
138 // need to do the same trick again - prepare small floor container segment and union
139 // it with tunnel container. Container has to be a wee bit bigger so can't use the same
140 // solids sadly.
141
142 // floor container cylinder has to definitely overlaps with outside cylinder -> tunnel1*1.1
143 G4VSolid* floorContainerEllipse = new G4EllipticalTube(name + "_floor_cont_ell_solid", // name
144 tunnel1*1.1, // x radius
145 tunnel2*1.1, // y radius
146 length*0.5); // z half length
147
148 // z long for unambiguous intersection
149
150 // calculate box container offset - should be just above floor by lengthsafety (floor actually lowered
151 // by length safety a la rest of geometry to fit within its dimensions)
152 G4double floorBoxContDisp = floorBoxDisplacement - lengthSafety;
153 G4VSolid* floorContainerSolid = new G4IntersectionSolid(name + "_floor_cont_solid", // name
154 floorContainerEllipse, // this
155 floorBox, // minus this,
156 0, // rotation matrix
157 G4ThreeVector(0,-floorBoxContDisp,0));// translation
158
159 G4VSolid* tunnelContainerSolidOuter = new G4Tubs(name + "_tunnel_cont_solid_outer", // name
160 0, // inner radius
161 soilOuterRadius + lengthSafety, // outer radius
162 0.5*length, // z half angle
163 0, // start angle
164 CLHEP::twopi); // sweep angle
165
166 G4VSolid* tunnelContainerSolidInner = new G4EllipticalTube(name + "_tunnel_cont_solid_inner", // name
167 tunnel1, // x radius
168 tunnel2, // y radius
169 length*0.5);
170
171 G4VSolid* tunnelContainerSolid = new G4SubtractionSolid(name + "_tunnel_cont_solid", // name
172 tunnelContainerSolidOuter, // this
173 tunnelContainerSolidInner); // minus this
174
175 // register solids
176 allSolids.insert(floorContainerEllipse);
177 allSolids.insert(floorContainerSolid);
178 allSolids.insert(tunnelContainerSolidOuter);
179 allSolids.insert(tunnelContainerSolidInner);
180 allSolids.insert(tunnelContainerSolid);
181
182 containerSolid = new G4UnionSolid(name + "_container_solid", // name
183 tunnelContainerSolid, // this
184 floorContainerSolid); // plus this
185 }
186 else
187 {
188 // have to do a subtraction with an elliptical tube
189 G4VSolid* tunnelContainerSolidOuter = new G4Tubs(name + "_tunnel_cont_solid_outer", // name
190 0, // inner radius
191 soilOuterRadius + lengthSafety, // outer radius
192 0.5*length, // z half angle
193 0, // start angle
194 CLHEP::twopi); // sweep angle
195
196 G4VSolid* tunnelContainerSolidInner = new G4EllipticalTube(name + "_tunnel_cont_solid_inner", // name
197 tunnel1, // x radius
198 tunnel2, // y radius
199 length*0.5);
200
201 // register solids
202 allSolids.insert(tunnelContainerSolidOuter);
203 allSolids.insert(tunnelContainerSolidInner);
204
205 containerSolid = new G4SubtractionSolid(name + "_tunnel_cont_solid", // name
206 tunnelContainerSolidOuter, // this
207 tunnelContainerSolidInner); // minus this
208 }
209
210 CommonConstruction(name, tunnelMaterial, tunnelSoilMaterial, length, containerXRadius, containerYRadius, visible);
211
212 return tunnelSection; // member variable geometry component that's assembled in base class
213}
214
215
217 G4double length,
218 G4ThreeVector inputFace,
219 G4ThreeVector outputFace,
220 G4double tunnelThickness,
221 G4double tunnelSoilThickness,
222 G4Material* tunnelMaterial,
223 G4Material* tunnelSoilMaterial,
224 G4bool tunnelFloor,
225 G4double tunnelFloorOffset,
226 G4double tunnel1,
227 G4double tunnel2,
228 G4bool visible)
229{
230 // tidy up things from previous usage if any - base class method
231 CleanUp();
232
233 // test input parameters - set global options as default if not specified
234 TestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial,
235 tunnelSoilMaterial, tunnelFloorOffset, tunnel1, tunnel2);
236
237 // build the solids
238 // create an intersection cut tubs to get the faces - make it bigger than everything else
239 // then make elliptical solids longer than they need to be
240 G4double intersectionRadius = ( std::max(tunnel1,tunnel2) + tunnelThickness + tunnelSoilThickness ) * 3;
241 G4VSolid* faceSolid = new G4CutTubs(name + "_face_intersection_solid", // name
242 0, // inner radius
243 intersectionRadius, // outer radius
244 length*0.5 - lengthSafety, // z half length
245 0, // start angle
246 CLHEP::twopi, // sweep angle
247 inputFace, // input face normal vector
248 outputFace); // output face normal vector
249
250
251 // tunnel
252 G4VSolid* tunnelOuterSolid = new G4EllipticalTube(name + "_tunnel_outer_solid", // name
253 tunnel1 + tunnelThickness, // x radius
254 tunnel2 + tunnelThickness, // y radius
255 length); // z half length
256
257 G4VSolid* tunnelInnerSolid = new G4EllipticalTube(name + "_tunnel_outer_solid", // name
258 tunnel1 + lengthSafety, // x radius
259 tunnel2 + lengthSafety, // y radius
260 length*1.5); // z half length - long for unambiguous subtraction
261
262 G4VSolid* tunnelSolidUnAngled = new G4SubtractionSolid(name + "_tunnel_square_solid", // name
263 tunnelOuterSolid, // this
264 tunnelInnerSolid); // minus this
265
266 // register solids
267 allSolids.insert(faceSolid);
268 allSolids.insert(tunnelOuterSolid);
269 allSolids.insert(tunnelInnerSolid);
270 allSolids.insert(tunnelSolidUnAngled);
271
272 // cut off the faces with the angled face solid
273 tunnelSolid = new G4IntersectionSolid(name + "_tunnel_solid", // name
274 tunnelSolidUnAngled,
275 faceSolid);
276
277 // soil solid
278 G4double soil1R = tunnel1 + tunnelThickness + lengthSafety;
279 G4double soil2R = tunnel2 + tunnelThickness + lengthSafety;
280
281 G4double soilOuterRadius = std::max(soil1R, soil2R) + tunnelSoilThickness;
282
283 G4VSolid* soilOuterSolid = new G4Tubs(name + "_soil_outer_solid", // name
284 0, // inner radius
285 soilOuterRadius, // outer radius
286 length, // z half angle
287 0, // start angle
288 CLHEP::twopi); // sweep angle
289
290 G4VSolid* soilInnerSolid = new G4EllipticalTube(name + "_soil_outer_solid", // name
291 soil1R + lengthSafety, // x radius
292 soil2R + lengthSafety, // y radius
293 1.5*length); // z half length - long for unambiguous subtraction
294
295 G4VSolid* soilSolidUnAngled = new G4SubtractionSolid(name + "_soil_square_solid", // name
296 soilOuterSolid, // this
297 soilInnerSolid); // minus this
298
299 // register solids
300 allSolids.insert(soilOuterSolid);
301 allSolids.insert(soilInnerSolid);
302 allSolids.insert(soilSolidUnAngled);
303
304 soilSolid = new G4IntersectionSolid(name + "_soil_soild", // name
305 soilSolidUnAngled,
306 faceSolid);
307
308 G4double containerXRadius = soil1R + tunnelSoilThickness + lengthSafety;
309 G4double containerYRadius = soil2R + tunnelSoilThickness + lengthSafety;
310
311 // build the floor if necessary
312 if (tunnelFloor)
313 {
314 // these three lines are a repeat of the same part in the first function (~L211)
315 G4double floorBoxRadius = 1.5 * std::max(tunnel1,tunnel2); // will definitely encompass the tunnel
316 G4double floorBoxDisplacement = tunnelFloorOffset + floorBoxRadius + lengthSafety;
317
318 G4VSolid* floorEllipse = new G4EllipticalTube(name + "_floor_ellipse_solid", // name
319 tunnel1, // x radius
320 tunnel2, // y radius
321 length); // z half length
322 // z long for unamibiguous intersection
323
324 // with the floor do the intersection first to avoid complications with the displacement
325 // of the subtraction box later
326 G4VSolid* floorEllipseAngled = new G4IntersectionSolid(name + "_floor_ell_angled_solid", // name
327 floorEllipse,
328 faceSolid);
329
330 G4VSolid* floorBox = new G4Box(name + "_floor_box_solid", // name
331 floorBoxRadius, // x half width
332 floorBoxRadius, // y half width
333 length*1.2); // z half length
334 // box z length extra long for unambiguous subtraction
335
336 // register solids
337 allSolids.insert(floorEllipse);
338 allSolids.insert(floorBox);
339
340 floorSolid = new G4IntersectionSolid(name + "_floor_solid", // name
341 floorEllipseAngled, // this
342 floorBox, // minus this,
343 0, // rotation matrix
344 G4ThreeVector(0,-floorBoxDisplacement,0)); // translation
345
346 // floor container cylinder has to definitely overlaps with outside cylinder -> tunnel1*1.1
347 G4VSolid* floorContainerEllAng = new G4EllipticalTube(name + "_floor_cont_ell_solid", // name
348 tunnel1*1.1, // x radius
349 tunnel2*1.1, // y radius
350 length*1.3); // z half length
351 // z long for unambiguous intersection
352
353 G4VSolid* floorContainerEllipseAngled = new G4IntersectionSolid(name + "+floor_cont_ell_ang_solid", // name
354 floorContainerEllAng,
355 faceSolid);
356
357 // calculate box container offset - should be just above floor by lengthsafety (floor actually lowered
358 // by length safety a la rest of geometry to fit within its dimensions)
359 G4double floorBoxContDisp = floorBoxDisplacement - lengthSafety;
360 G4VSolid* floorContainerSolid = new G4IntersectionSolid(name + "_floor_cont_solid", // name
361 floorContainerEllipseAngled, // this
362 floorBox, // minus this,
363 0, // rotation matrix
364 G4ThreeVector(0,-floorBoxContDisp,0));// translation
365
366 G4VSolid* tunnelContainerOuterSquare = new G4Tubs(name + "_tunnel_cont_solid_outer", // name
367 0, // inner radius
368 soilOuterRadius + lengthSafety, // outer radius
369 length, // z half angle
370 0, // start angle
371 CLHEP::twopi); // sweep angle
372
373 G4VSolid* tunnelContainerSolidOuterAngled = new G4IntersectionSolid(name + "_tunnel_cont_out_ang_solid", // name
374 tunnelContainerOuterSquare,
375 faceSolid);
376
377 G4VSolid* tunnelContainerSolidInner = new G4EllipticalTube(name + "_tunnel_cont_solid_inner", // name
378 tunnel1, // x radius
379 tunnel2, // y radius
380 length*2.4);
381
382 G4VSolid* tunnelContainerSolid = new G4SubtractionSolid(name + "_tunnel_cont_solid", // name
383 tunnelContainerSolidOuterAngled, // this
384 tunnelContainerSolidInner); // minus this
385
386 // register solids
387 allSolids.insert(floorContainerEllAng);
388 allSolids.insert(floorContainerEllipseAngled);
389 allSolids.insert(floorContainerSolid);
390 allSolids.insert(tunnelContainerOuterSquare);
391 allSolids.insert(tunnelContainerSolidOuterAngled);
392 allSolids.insert(tunnelContainerSolidInner);
393 allSolids.insert(tunnelContainerSolid);
394
395 containerSolid = new G4UnionSolid(name + "_container_solid", // name
396 tunnelContainerSolid, // this
397 floorContainerSolid); // plus this
398
399 }
400 else
401 {
402 G4VSolid* tunnelContainerOuterSquare = new G4Tubs(name + "_tunnel_cont_solid_outer", // name
403 0, // inner radius
404 soilOuterRadius + lengthSafety, // outer radius
405 length, // z half angle
406 0, // start angle
407 CLHEP::twopi); // sweep angle
408
409 G4VSolid* tunnelContainerSolidOuterAngled = new G4IntersectionSolid(name + "_tunnel_cont_out_ang_solid", // name
410 tunnelContainerOuterSquare,
411 faceSolid);
412
413 G4VSolid* tunnelContainerSolidInner = new G4EllipticalTube(name + "_tunnel_cont_solid_inner", // name
414 tunnel1, // x radius
415 tunnel2, // y radius
416 length*0.5);
417
418 // register solids
419 allSolids.insert(tunnelContainerOuterSquare);
420 allSolids.insert(tunnelContainerSolidOuterAngled);
421 allSolids.insert(tunnelContainerSolidInner);
422
423 containerSolid = new G4SubtractionSolid(name + "_tunnel_cont_solid", // name
424 tunnelContainerSolidOuterAngled, // this
425 tunnelContainerSolidInner); // minus this
426 }
427
428 CommonConstruction(name, tunnelMaterial, tunnelSoilMaterial, length, containerXRadius,
429 containerYRadius, visible);
430
431 return tunnelSection;
432}
433
436 G4double& tunnelThickness,
437 G4double& tunnelSoilThickness,
438 G4Material*& tunnelMaterial,
439 G4Material*& tunnelSoilMaterial,
440 G4double& tunnelFloorOffset,
441 G4double& tunnel1,
442 G4double& tunnel2)
443{
444 CommontTestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial, tunnelSoilMaterial);
445
446 if (tunnelFloorOffset < 1e-10)
447 {tunnelFloorOffset = defaultModel->floorOffset;}
448
449 if (tunnel1 < 1e-10)
450 {tunnel1 = defaultModel->aper1;}
451
452 if (tunnel2 < 1e-10)
453 {tunnel2 = defaultModel->aper2;}
454}
const G4String name
Const protected member variable that may not be changed by derived classes.
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, G4double &tunnel2)
functions below here are private to this particular factory
G4double aper2
Tunnel aperture / shape parameter 2.
G4double aper1
Tunnel aperture / shape parameter 1.
Class that represents a section of tunnel.