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