BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSBeamPipeFactoryLHC.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 "BDSBeamPipeFactoryBase.hh"
19#include "BDSBeamPipeFactoryLHC.hh"
20#include "BDSBeamPipe.hh"
21#include "BDSExtent.hh"
22#include "BDSUtilities.hh"
23
24#include "globals.hh" // geant4 globals / types
25#include "G4Box.hh"
26#include "G4CutTubs.hh"
27#include "G4IntersectionSolid.hh"
28#include "G4LogicalVolume.hh"
29#include "G4SubtractionSolid.hh"
30#include "G4ThreeVector.hh"
31#include "G4Tubs.hh"
32#include "G4VSolid.hh"
33
34#include <cmath>
35#include <set>
36#include <utility> // for std::pair
37
38BDSBeamPipeFactoryLHC::BDSBeamPipeFactoryLHC()
39{;}
40
42 G4double lengthIn,
43 G4double aper1In,
44 G4double aper2In,
45 G4double aper3In,
46 G4double /*aper4In*/,
47 G4Material* vacuumMaterialIn,
48 G4double beamPipeThicknessIn,
49 G4Material* beamPipeMaterialIn,
50 const G4String& /*pointsFileIn*/,
51 const G4String& /*pointsUnitIn*/)
52{
53 // clean up after last usage
54 CleanUp();
55
56 // build the solids
57 //vacuum cylindrical solid (circular cross-section)
58 G4VSolid* vacCylSolid = new G4Tubs(nameIn + "_vacuum_cylinder", // name
59 0, // inner radius
60 aper3In, // outer radius
61 lengthIn*0.5-lengthSafety, // half length
62 0, // rotation start angle
63 CLHEP::twopi); // rotation finish angle
64 //vacuum box solid (rectangular cross-section)
65 G4VSolid* vacRectSolid = new G4Box(nameIn + "_vacuum_box", // name
66 aper1In, // x half width
67 aper2In, // y half width
68 lengthIn); // z full width (long for unambiguous intersection)
69 allSolids.insert(vacCylSolid);
70 allSolids.insert(vacRectSolid);
71 //intersection of both of these gives the desired shape
72 vacuumSolid = new G4IntersectionSolid(nameIn + "_vacuum_solid", // name
73 vacCylSolid, // solid 1
74 vacRectSolid); // solid 2
75
76 //beampipe cylindrical solid (circular cross-section)
77 //beampipe inner edge for subtraction (actually just like vacuum + lengthSafety)x
78 G4VSolid* bpInnerCylSolid = new G4Tubs(nameIn + "_pipe_inner_cylinder", // name
79 0, // inner radius
80 aper3In + lengthSafetyLarge, // outer radius
81 1.5*lengthIn, // length big for unambiguous subtraction (but < outerlength)
82 0, // rotation start angle
83 CLHEP::twopi); // rotation finish angle
84 //beampipe inner edge box solid (rectangular cross-section)
85 G4VSolid* bpInnerRectSolid = new G4Box(nameIn + "_pipe_inner_box", // name
86 aper1In + lengthSafetyLarge,// x half width
87 aper2In + lengthSafetyLarge,// y half width
88 1.7*lengthIn); // z long for unambiguous intersection
89 //beampipe inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
90 G4VSolid* bpInnerSolid = new G4IntersectionSolid(nameIn + "_pipe_inner_solid", // name
91 bpInnerCylSolid, // solid 1
92 bpInnerRectSolid); // solid 2
93
94 //beampipe outer edge for subtraction (actually just like vacuum + lengthSafety)
95 G4double extraWidth = lengthSafetyLarge + beamPipeThicknessIn;
96 G4VSolid* bpOuterCylSolid = new G4Tubs(nameIn + "_pipe_inner_cylinder", // name
97 0, // inner radius (0 for unambiguous subtraction)
98 aper3In + extraWidth, // outer radius
99 (lengthIn*0.5)-lengthSafety, // half length
100 0, // rotation start angle
101 CLHEP::twopi); // rotation finish angle
102 //beampipe outer edge box solid (rectangular cross-section)
103 G4VSolid* bpOuterRectSolid = new G4Box(nameIn + "_pipe_inner_box", // name
104 aper1In + extraWidth, // x half width
105 aper2In + extraWidth, // y half width
106 lengthIn); // z full width (long for unambiguous intersection)
107 G4VSolid* bpOuterSolid = new G4IntersectionSolid(nameIn + "_pipe_inner_solid", // name
108 bpOuterCylSolid, // solid 1
109 bpOuterRectSolid); // solid 2
110 allSolids.insert(bpInnerCylSolid);
111 allSolids.insert(bpInnerRectSolid);
112 allSolids.insert(bpInnerSolid);
113 allSolids.insert(bpOuterCylSolid);
114 allSolids.insert(bpOuterRectSolid);
115 allSolids.insert(bpOuterSolid);
116
117 beamPipeSolid = new G4SubtractionSolid(nameIn + "_pipe_solid", // name
118 bpOuterSolid, // this
119 bpInnerSolid); // minus this
120
121 //container cylindrical solid (circular cross-section)
122 G4VSolid* contCylSolid = new G4Tubs(nameIn + "_vacuum_cylinder", // name
123 0, // inner radius
124 aper3In + extraWidth + lengthSafetyLarge, // outer radius
125 lengthIn*0.5, // half length
126 0, // rotation start angle
127 CLHEP::twopi); // rotation finish angle
128 //vacuum box solid (rectangular cross-section)
129 G4VSolid* contRectSolid = new G4Box(nameIn + "_vacuum_box", // name
130 aper1In + extraWidth + lengthSafetyLarge, // x half width
131 aper2In + extraWidth + lengthSafetyLarge, // y half width
132 lengthIn); // z full width (long for unambiguous intersection)
133
134 allSolids.insert(contCylSolid);
135 allSolids.insert(contRectSolid);
136 //intersection of both of these gives the desired shape
137 containerSolid = new G4IntersectionSolid(nameIn + "_vacuum_solid", // name
138 contCylSolid, // solid 1
139 contRectSolid); // solid 2
140
141 G4double width = aper3In + extraWidth + lengthSafetyLarge;
142 G4double height = aper2In + extraWidth + lengthSafetyLarge;
143
144 CreateContainerSubtractionSolid(nameIn, lengthIn, beamPipeThicknessIn, aper1In, aper2In, aper3In);
145
146 return CommonFinalConstruction(nameIn, vacuumMaterialIn, beamPipeMaterialIn, lengthIn, width, height);
147}
148
150 G4double lengthIn,
151 const G4ThreeVector& inputFaceNormalIn,
152 const G4ThreeVector& outputFaceNormalIn,
153 G4double aper1In,
154 G4double aper2In,
155 G4double aper3In,
156 G4double /*aper4In*/,
157 G4Material* vacuumMaterialIn,
158 G4double beamPipeThicknessIn,
159 G4Material* beamPipeMaterialIn,
160 const G4String& /*pointsFileIn*/,
161 const G4String& /*pointsUnitIn*/)
162{
163 // clean up after last usage
164 CleanUp();
165
166 inputFaceNormal = inputFaceNormalIn;
167 outputFaceNormal = outputFaceNormalIn;
168
169 G4double width = aper3In + beamPipeThicknessIn + 2*lengthSafetyLarge;
170 G4double height = aper2In + beamPipeThicknessIn + 2*lengthSafetyLarge;
171
172 CreateGeneralAngledSolids(nameIn, lengthIn, aper1In, aper2In, aper3In, beamPipeThicknessIn,
174 CreateContainerSubtractionSolid(nameIn, lengthIn, beamPipeThicknessIn,
175 aper1In, aper2In, aper3In);
176
177 return CommonFinalConstruction(nameIn, vacuumMaterialIn, beamPipeMaterialIn,
178 lengthIn, width, height);
179}
180
182 G4Material* vacuumMaterialIn,
183 G4Material* beamPipeMaterialIn,
184 G4double lengthIn,
185 G4double containerWidthIn,
186 G4double containerHeightIn)
187{
188 BDSBeamPipeFactoryBase::CommonConstruction(nameIn, vacuumMaterialIn,
189 beamPipeMaterialIn, lengthIn);
190
191 // record extents
192 BDSExtent ext = BDSExtent(containerWidthIn, containerHeightIn, lengthIn*0.5);
193
194 // build the BDSBeamPipe instance and return it
195 return BuildBeamPipeAndRegisterVolumes(ext, containerWidthIn);
196}
197
198
202 G4double lengthIn,
203 G4double aper1In,
204 G4double aper2In,
205 G4double aper3In,
206 G4double beamPipeThicknessIn,
207 const G4ThreeVector& inputfaceIn,
208 const G4ThreeVector& outputfaceIn)
209{
210 // long length for unambiguous boolean - ensure no gaps in beam pipe geometry
211 G4double angledVolumeLength = BDS::CalculateSafeAngledVolumeLength(inputfaceIn, outputfaceIn, lengthIn, aper1In);
212
213 // build the solids
214 //vacuum cylindrical solid (circular cross-section)
215 G4VSolid* vacCylSolid = new G4CutTubs(nameIn + "_vacuum_cylinder", // name
216 0, // inner radius
217 aper3In, // outer radius
218 lengthIn*0.5-lengthSafety, // half length
219 0, // rotation start angle
220 CLHEP::twopi, // rotation finish angle
221 inputfaceIn, // input face normal
222 outputfaceIn); // output face normal
223 //vacuum box solid (rectangular cross-section)
224 G4VSolid* vacRectSolid = new G4Box(nameIn + "_vacuum_box", // name
225 aper1In, // x half width
226 aper2In, // y half width
227 angledVolumeLength); // z full width (long for unambiguous intersection)
228 allSolids.insert(vacCylSolid);
229 allSolids.insert(vacRectSolid);
230 //intersection of both of these gives the desired shape
231 vacuumSolid = new G4IntersectionSolid(nameIn + "_vacuum_solid", // name
232 vacCylSolid, // solid 1
233 vacRectSolid); // solid 2
234
235 //beampipe cylindrical solid (circular cross-section)
236 //beampipe inner edge for subtraction (actually just like vacuum + lengthSafety)x
237 G4VSolid* bpInnerCylSolid = new G4CutTubs(nameIn + "_pipe_inner_cylinder", // name
238 0, // inner radius
239 aper3In + lengthSafetyLarge, // outer radius
240 1.5*lengthIn, // length big for unambiguous subtraction (but < outerlength)
241 0, // rotation start angle
242 CLHEP::twopi, // rotation finish angle
243 inputfaceIn, // input face normal
244 outputfaceIn); // output face normal
245
246 //beampipe inner edge box solid (rectangular cross-section)
247 G4VSolid* bpInnerRectSolid = new G4Box(nameIn + "_pipe_inner_box", // name
248 aper1In + lengthSafetyLarge,// x half width
249 aper2In + lengthSafetyLarge,// y half width
250 angledVolumeLength); // z long for unambiguous intersection
251 //beampipe inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
252 G4VSolid* bpInnerSolid = new G4IntersectionSolid(nameIn + "_pipe_inner_solid", // name
253 bpInnerCylSolid, // solid 1
254 bpInnerRectSolid); // solid 2
255
256 //beampipe outer edge for subtraction (actually just like vacuum + lengthSafety)
257 G4double extraWidth = lengthSafetyLarge + beamPipeThicknessIn;
258 G4VSolid* bpOuterCylSolid = new G4CutTubs(nameIn + "_pipe_inner_cylinder", // name
259 0, // inner radius (0 for unambiguous subtraction)
260 aper3In + extraWidth, // outer radius
261 (lengthIn*0.5)-lengthSafety, // half length
262 0, // rotation start angle
263 CLHEP::twopi, // rotation finish angle
264 inputfaceIn, // input face normal
265 outputfaceIn); // output face normal
266
267 //beampipe outer edge box solid (rectangular cross-section)
268 G4VSolid* bpOuterRectSolid = new G4Box(nameIn + "_pipe_inner_box", // name
269 aper1In + beamPipeThicknessIn, // x half width
270 aper2In + beamPipeThicknessIn, // y half width
271 angledVolumeLength); // z full width (long for unambiguous intersection)
272 G4VSolid* bpOuterSolid = new G4IntersectionSolid(nameIn + "_pipe_inner_solid", // name
273 bpOuterCylSolid, // solid 1
274 bpOuterRectSolid); // solid 2
275
276 allSolids.insert(bpInnerCylSolid);
277 allSolids.insert(bpInnerRectSolid);
278 allSolids.insert(bpInnerSolid);
279 allSolids.insert(bpOuterCylSolid);
280 allSolids.insert(bpOuterRectSolid);
281 allSolids.insert(bpOuterSolid);
282
283 beamPipeSolid = new G4SubtractionSolid(nameIn + "_pipe_solid", // name
284 bpOuterSolid, // this
285 bpInnerSolid); // minus this
286
287 //container cylindrical solid (circular cross-section)
288 G4VSolid* contCylSolid = new G4CutTubs(nameIn + "_vacuum_cylinder", // name
289 0, // inner radius
290 aper3In + extraWidth + lengthSafetyLarge, // outer radius
291 lengthIn*0.5, // half length
292 0, // rotation start angle
293 CLHEP::twopi, // rotation finish angle
294 inputfaceIn, // input face normal
295 outputfaceIn); // output face normal
296
297 //vacuum box solid (rectangular cross-section)
298 G4VSolid* contRectSolid = new G4Box(nameIn + "_vacuum_box", // name
299 aper1In + beamPipeThicknessIn + lengthSafety, // x half width
300 aper2In + beamPipeThicknessIn + lengthSafety, // y half width
301 angledVolumeLength); // z full width (long for unambiguous intersection)
302
303 allSolids.insert(contCylSolid);
304 allSolids.insert(contRectSolid);
305 //intersection of both of these gives the desired shape
306 containerSolid = new G4IntersectionSolid(nameIn + "_vacuum_solid", // name
307 contCylSolid, // solid 1
308 contRectSolid); // solid 2
309}
310
312 G4double& lengthIn,
313 G4double& beamPipeThicknessIn,
314 G4double& aper1In,
315 G4double& aper2In,
316 G4double& aper3In)
317{
318 //container cylindrical solid (circular cross-section)
319 G4VSolid* contSubCylSolid = new G4Tubs(nameIn + "_subtraction_cylinder", // name
320 0, // inner radius
321 aper3In + beamPipeThicknessIn + 2*lengthSafetyLarge, // outer radius
322 2*lengthIn, // long length for unambiguous subtraction
323 0, // rotation start angle
324 CLHEP::twopi); // rotation finish angle
325 //vacuum box solid (rectangular cross-section)
326 G4VSolid* contSubRectSolid = new G4Box(nameIn + "_subtraction_box", // name
327 aper1In + beamPipeThicknessIn + 2*lengthSafetyLarge, // x half width
328 aper2In + beamPipeThicknessIn + 2*lengthSafetyLarge, // y half width
329 1.7*lengthIn); // z full width (long for unambiguous intersection)
330 allSolids.insert(contSubCylSolid);
331 allSolids.insert(contSubRectSolid);
332 //intersection of both of these gives the desired shape
333 containerSubtractionSolid = new G4IntersectionSolid(nameIn + "_subtraction_solid", // name
334 contSubCylSolid, // solid 1
335 contSubRectSolid); // solid 2
336}
G4ThreeVector outputFaceNormal
For recording the face normals in the finished pipe component.
G4ThreeVector inputFaceNormal
For recording the face normals in the finished pipe component.
void CommonConstruction(const G4String &nameIn, G4Material *vacuumMaterialIn, G4Material *beamPipeMaterialIn, G4double length)
finalise beampipe construction
BDSBeamPipe * BuildBeamPipeAndRegisterVolumes(BDSExtent extent, G4double containerRadius, G4bool containerIsCircular=false)
build beampipe and register logical volumes
G4VSolid * containerSubtractionSolid
Longer (in length) version of container solid for unambiguous subtraction.
virtual BDSBeamPipe * CreateBeamPipe(const G4String &nameIn, G4double lengthIn, G4double aper1=0, G4double aper2=0, G4double aper3=0, G4double aper4=0, G4Material *vacuumMaterialIn=nullptr, G4double beamPipeThicknessIn=0, G4Material *beamPipeMaterialIn=nullptr, const G4String &pointsFileIn="", const G4String &pointsUnitIn="")
create a flat ended beampipe
BDSBeamPipe * CommonFinalConstruction(const G4String &nameIn, G4Material *vacuumMaterialIn, G4Material *beamPipeMaterialIn, G4double lengthIn, G4double widthIn, G4double heightIn)
void CreateContainerSubtractionSolid(const G4String &nameIn, G4double &lengthIn, G4double &beamPipeThicknessIn, G4double &aper1In, G4double &aper2In, G4double &aper3In)
function to create the container subtraction solid and avoid passing aper1,2,3 around further
void CreateGeneralAngledSolids(const G4String &nameIn, G4double lengthIn, G4double aper1In, G4double aper2In, G4double aper3In, G4double beamPipeThicknessIn, const G4ThreeVector &inputfaceIn, const G4ThreeVector &outputfaceIn)
A holder class for a piece of beam pipe geometry.
Holder for +- extents in 3 dimensions.
Definition BDSExtent.hh:38
G4double lengthSafety
Cache of global constants variable.
G4double lengthSafetyLarge
Cache of global constants variable.
G4double CalculateSafeAngledVolumeLength(G4double angleIn, G4double angleOut, G4double length, G4double containerWidth, G4double containerHeight=0)
Calculate safe length of an angled volume so it fills the length of its container.