BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSTunnelFactoryRectangular.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 "BDSTunnelFactoryRectangular.hh"
20#include "BDSTunnelInfo.hh"
21
22#include "globals.hh" // geant4 globals / types
23#include "G4Box.hh"
24#include "G4CutTubs.hh"
25#include "G4IntersectionSolid.hh"
26#include "G4LogicalVolume.hh"
27#include "G4SubtractionSolid.hh"
28#include "G4ThreeVector.hh"
29#include "G4VSolid.hh"
30
31#include <cmath> // sin, cos, fabs
32#include <set>
33#include <utility> // for std::pair
34
35class G4Material;
36
37BDSTunnelFactoryRectangular::BDSTunnelFactoryRectangular()
38{;}
39
41 G4double length,
42 G4double tunnelThickness,
43 G4double tunnelSoilThickness,
44 G4Material* tunnelMaterial,
45 G4Material* tunnelSoilMaterial,
46 G4bool tunnelFloor,
47 G4double tunnelFloorOffset,
48 G4double tunnel1,
49 G4double tunnel2,
50 G4bool visible)
51{
52 // tidy up things from previous usage if any - base class method
53 CleanUp();
54
55 // test input parameters - set global options as default if not specified
56 TestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial,
57 tunnelSoilMaterial, tunnelFloorOffset, tunnel1, tunnel2);
58
59 // build the solids
60 G4VSolid* tunnelOuterSolid = new G4Box(name + "_tunnel_outer_solid", // name
61 tunnel1 + tunnelThickness, // x radius
62 tunnel2 + tunnelThickness, // y radius
63 0.5*length - lengthSafety); // z half length (to fit in container)
64
65 G4VSolid* tunnelInnerSolid = new G4Box(name + "_tunnel_outer_solid", // name
66 tunnel1 + lengthSafety, // x radius
67 tunnel2 + lengthSafety, // y radius
68 length); // z half length - long for unambiguous subtraction
69
70 // register solids
71 allSolids.insert(tunnelOuterSolid);
72 allSolids.insert(tunnelInnerSolid);
73
74 tunnelSolid = new G4SubtractionSolid(name + "_tunnel_solid", // name
75 tunnelOuterSolid, // this
76 tunnelInnerSolid); // minus this
77
78
79 G4double soilInnerX = tunnel1 + tunnelThickness + lengthSafety;
80 G4double soilInnerY = tunnel2 + tunnelThickness + lengthSafety;
81
82 G4double soilOuterX = soilInnerX + tunnelSoilThickness;
83 G4double soilOuterY = soilInnerY + tunnelSoilThickness;
84
85 G4double containerX = soilOuterX + lengthSafety;
86 G4double containerY = soilOuterY + lengthSafety;
87
88 G4VSolid* soilOuterSolid = new G4Box(name + "_soild_outer_solid", // name
89 soilOuterX, // x half width
90 soilOuterY, // y half width
91 0.5*length); // z half width
92
93 G4VSolid* soilInnerSolid = new G4Box(name + "_soil_outer_solid", // name
94 soilInnerX, // x radius
95 soilInnerY, // y radius
96 length); // z half length - long for unambiguous subtraction
97
98 // register solids
99 allSolids.insert(soilOuterSolid);
100 allSolids.insert(soilInnerSolid);
101
102 soilSolid = new G4SubtractionSolid(name + "_soil_solid", // name
103 soilOuterSolid, // this
104 soilInnerSolid); // minus this
105
106 // container solid depends on whether the floor is there or not, but can prepare the outer part for subtraction
107 G4VSolid* containerSolidOuter = new G4Box(name + "_container_outer_solid", // name
108 containerX, // x half width
109 containerY, // y half width
110 length*0.5); // z half width
111 G4ThreeVector contInsideDisplacement;
112 G4VSolid* containerSolidInner = nullptr;
113
114 // build the floor if necessary
115 if (tunnelFloor)
116 {
117 G4double floorThickness = tunnel2 - tunnelFloorOffset - lengthSafety;
118
119 // placement vector for floor - assinging default 0,0,0 in base class
120 floorDisplacement = G4ThreeVector(0, -(tunnelFloorOffset + floorThickness*0.5), 0);
121 floorSolid = new G4Box(name + "_floor_solid", // name
122 tunnel1 - lengthSafety, // x half width
123 floorThickness*0.5 - lengthSafety, // y half width
124 0.5*length - lengthSafety); // z half width
125
126 G4double tunnelContInnerYRadius = tunnel2 - 0.5*floorThickness - lengthSafety;
127
128 containerSolidInner = new G4Box(name + "_tunnel_cont_solid_inner", // name
129 tunnel1, // x radius
130 tunnelContInnerYRadius, // y radius
131 length); // long z for unambiguous subtraction
132
133 // offset the centre cut out by the difference between the vertical half widths of tunnel2 and tunnel2+floor
134 contInsideDisplacement = G4ThreeVector(0, floorThickness*0.5, 0);
135 }
136 else
137 {
138 containerSolidInner = new G4Box(name + "_tunnel_cont_solid_inner", // name
139 tunnel1, // x radius
140 tunnel2, // y radius
141 length); // long z for unambiguous subtraction
142 contInsideDisplacement = G4ThreeVector(0,0,0);
143 }
144
145 containerSolid = new G4SubtractionSolid(name + "_tunnel_cont_solid", // name
146 containerSolidOuter, // this
147 containerSolidInner, // minus this
148 0, // rotate by this
149 contInsideDisplacement);
150
151 CommonConstruction(name, tunnelMaterial, tunnelSoilMaterial, length, containerX, containerY, visible);
152
153 return tunnelSection;
154}
155
156
158 G4double length,
159 G4ThreeVector inputFace,
160 G4ThreeVector outputFace,
161 G4double tunnelThickness,
162 G4double tunnelSoilThickness,
163 G4Material* tunnelMaterial,
164 G4Material* tunnelSoilMaterial,
165 G4bool tunnelFloor,
166 G4double tunnelFloorOffset,
167 G4double tunnel1,
168 G4double tunnel2,
169 G4bool visible)
170{
171 // tidy up things from previous usage if any - base class method
172 CleanUp();
173
174 // test input parameters - set global options as default if not specified
175 TestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial,
176 tunnelSoilMaterial, tunnelFloorOffset, tunnel1, tunnel2);
177
178 // build the solids
179 // create an intersection cut tubs to get the faces - make it bigger than everything else
180 // then make elliptical solids longer than they need to be
181 G4double intersectionRadius = ( std::max(tunnel1,tunnel2) + tunnelThickness + tunnelSoilThickness ) * 3;
182 G4VSolid* faceSolid = new G4CutTubs(name + "_face_intersection_solid", // name
183 0, // inner radius
184 intersectionRadius, // 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
192 // tunnel
193 G4VSolid* tunnelOuterSolid = new G4Box(name + "_tunnel_outer_solid", // name
194 tunnel1 + tunnelThickness, // x radius
195 tunnel2 + tunnelThickness, // y radius
196 length); // z half length
197
198 G4VSolid* tunnelInnerSolid = new G4Box(name + "_tunnel_outer_solid", // name
199 tunnel1 + lengthSafety, // x radius
200 tunnel2 + lengthSafety, // y radius
201 length*1.5); // z half length - long for unambiguous subtraction
202
203 G4VSolid* tunnelSolidUnAngled = new G4SubtractionSolid(name + "_tunnel_square_solid", // name
204 tunnelOuterSolid, // this
205 tunnelInnerSolid); // minus this
206
207 // register solids
208 allSolids.insert(faceSolid);
209 allSolids.insert(tunnelOuterSolid);
210 allSolids.insert(tunnelInnerSolid);
211 allSolids.insert(tunnelSolidUnAngled);
212
213 // cut off the faces with the angled face solid
214 tunnelSolid = new G4IntersectionSolid(name + "_tunnel_solid", // name
215 tunnelSolidUnAngled,
216 faceSolid);
217
218 // soil solid
219 G4double soilInnerX = tunnel1 + tunnelThickness + lengthSafety;
220 G4double soilInnerY = tunnel2 + tunnelThickness + lengthSafety;
221
222 G4double soilOuterX = soilInnerX + tunnelSoilThickness;
223 G4double soilOuterY = soilInnerY + tunnelSoilThickness;
224
225 G4double containerX = soilOuterX + lengthSafety;
226 G4double containerY = soilOuterY + lengthSafety;
227
228 G4VSolid* soilOuterSolid = new G4Box(name + "_soil_outer_solid", // name
229 soilOuterX, // x half width
230 soilOuterY, // y half width
231 length); // z half length
232
233 G4VSolid* soilInnerSolid = new G4Box(name + "_soil_inner_solid", // name
234 soilInnerX, // x radius
235 soilInnerY, // y radius
236 1.5*length); // z half length - long for unambiguous subtraction
237
238 // cut out inside of big box of soil to get rectangular tube - purposively long for upcoming intersection
239 G4VSolid* soilSolidUnAngled = new G4SubtractionSolid(name + "_soil_square_solid", // name
240 soilOuterSolid, // this
241 soilInnerSolid); // minus this
242
243 // register solids
244 allSolids.insert(soilOuterSolid);
245 allSolids.insert(soilInnerSolid);
246 allSolids.insert(soilSolidUnAngled);
247
248 // make it angled
249 soilSolid = new G4IntersectionSolid(name + "_soil_soild", // name
250 soilSolidUnAngled,
251 faceSolid);
252
253
254 // container solid depends on whether the floor is there or not, but can prepare the outer part for subtraction
255 G4VSolid* containerSolidOuter = new G4Box(name + "_container_outer_solid", // name
256 containerX, // x half width
257 containerY, // y half width
258 length); // z long for unambiguous intersection later
259 G4ThreeVector contInsideDisplacement;
260 G4VSolid* containerSolidInner = nullptr;
261 G4VSolid* containerSolidSquare = nullptr;
262
263 allSolids.insert(containerSolidOuter);
264
265 // build the floor if necessary
266 if (tunnelFloor)
267 {
268 G4double floorThickness = tunnel2 - tunnelFloorOffset - lengthSafety;
269
270 // placement vector for floor - assinging default 0,0,0 in base class
271 floorDisplacement = G4ThreeVector(0, -(tunnelFloorOffset + floorThickness*0.5), 0);
272
273 G4VSolid* floorSolidSquare = new G4Box(name + "_floor_box_solid", // name
274 tunnel1, // x half width
275 floorThickness*0.5, // y half width
276 length); // z half width
277
278 floorSolid = new G4IntersectionSolid(name + "_floor_solid", // name
279 floorSolidSquare,
280 faceSolid);
281
282 allSolids.insert(floorSolidSquare);
283
284 // need to create a container for the tunnel + floor that only just contains it
285 G4double tunnelContInnerYRadius = ( tunnelFloorOffset + tunnel2 ) * 0.5;
286 containerSolidInner = new G4Box(name + "_tunnel_cont_solid_inner", // name
287 tunnel1, // x radius
288 tunnelContInnerYRadius, // y radius
289 2*length); // z long for unambiguous subtraction
290
291 // offset the centre cut out by the difference between the vertical half widths of tunnel2 and tunnel2+floor
292 contInsideDisplacement = G4ThreeVector(0, -(tunnelContInnerYRadius - tunnel2), 0);
293 }
294 else
295 {
296 containerSolidInner = new G4Box(name + "_tunnel_cont_solid_inner", // name
297 tunnel1, // x radius
298 tunnel2, // y radius
299 2*length); // z half length - long for unambiguous subtraction
300 contInsideDisplacement = G4ThreeVector(0,0,0);
301 }
302
303 containerSolidSquare = new G4SubtractionSolid(name + "_container_square_solid", // name
304 containerSolidOuter, // this
305 containerSolidInner, // minus this
306 0, // rotate by this
307 contInsideDisplacement); // with this displacment
308
309 containerSolid = new G4IntersectionSolid(name + "_container_solid", // name
310 containerSolidSquare,
311 faceSolid);
312
313 CommonConstruction(name, tunnelMaterial, tunnelSoilMaterial, length, containerX,
314 containerY, visible);
315
316 return tunnelSection;
317}
318
321 G4double& tunnelThickness,
322 G4double& tunnelSoilThickness,
323 G4Material*& tunnelMaterial,
324 G4Material*& tunnelSoilMaterial,
325 G4double& tunnelFloorOffset,
326 G4double& tunnel1,
327 G4double& tunnel2)
328{
329 CommontTestInputParameters(length, tunnelThickness, tunnelSoilThickness, tunnelMaterial, tunnelSoilMaterial);
330
331 if (tunnelFloorOffset < 1e-10)
332 {tunnelFloorOffset = defaultModel->floorOffset;}
333
334 if (tunnel1 < 1e-10)
335 {tunnel1 = defaultModel->aper1;}
336
337 if (tunnel2 < 1e-10)
338 {tunnel2 = defaultModel->aper2;}
339}
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.