BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSBeamPipeFactoryRectangular.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 "BDSBeamPipeFactoryRectangular.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 "G4VSolid.hh"
32
33#include <cmath> // sin, cos, fabs
34
35
36BDSBeamPipeFactoryRectangular::BDSBeamPipeFactoryRectangular()
37{;}
38
40 G4double lengthIn,
41 G4double aper1In,
42 G4double aper2In,
43 G4double /*aper3In*/,
44 G4double /*aper4In*/,
45 G4Material* vacuumMaterialIn,
46 G4double beamPipeThicknessIn,
47 G4Material* beamPipeMaterialIn,
48 const G4String& /*pointsFileIn*/,
49 const G4String& /*pointsUnitIn*/)
50{
51 // clean up after last usage
52 CleanUp();
53
54 // build the solids
55 vacuumSolid = new G4Box(nameIn + "_vacuum_solid", // name
56 aper1In, // x half width
57 aper2In, // y half width
58 (lengthIn*0.5)-lengthSafety); // half length
59
60 G4VSolid* beamPipeSolidInner; // construct rectangular beam pipe by subtracting an inner
61 G4VSolid* beamPipeSolidOuter; // box from an outer one - only way
62 // beamPipeSolidInner will be the inner edge of the metal beampipe
63 // therefore it has to be the width of the aperture + lengthSafety
64 beamPipeSolidInner = new G4Box(nameIn + "_pipe_solid_inner",// name
65 aper1In + lengthSafetyLarge, // x half width - length safety to avoid overlaps
66 aper2In + lengthSafetyLarge, // y half width
67 lengthIn); // length - full length for unambiguous subtraction
68 // beamPipeSolidOuter will be the outer edge of the metal beampipe
69 // therefore it has to be the width of the aperture + beampipeThickness
70 G4double extraWidth = beamPipeThicknessIn + lengthSafetyLarge;
71 beamPipeSolidOuter = new G4Box(nameIn + "_pipe_solid_outer", // name
72 aper1In + extraWidth, // x half width
73 aper2In + extraWidth, // y half width
74 (lengthIn*0.5)-lengthSafety); // half length - lengthSafety to fit in container
75 allSolids.insert(beamPipeSolidInner);
76 allSolids.insert(beamPipeSolidOuter);
77 beamPipeSolid = new G4SubtractionSolid(nameIn + "_pipe_solid",
78 beamPipeSolidOuter,
79 beamPipeSolidInner); // outer minus inner
80
81 G4double containerHalfWidthX = aper1In + extraWidth + lengthSafetyLarge;
82 G4double containerHalfWidthY = aper2In + extraWidth + lengthSafetyLarge;
83 containerSolid = new G4Box(nameIn + "_container_solid", // name
84 containerHalfWidthX, // x half width
85 containerHalfWidthY, // y half width
86 lengthIn*0.5); // half length
87
88 return CommonFinalConstruction(nameIn, vacuumMaterialIn, beamPipeMaterialIn,
89 lengthIn, containerHalfWidthX, containerHalfWidthY);
90}
91
93 G4double lengthIn,
94 const G4ThreeVector& inputFaceNormalIn,
95 const G4ThreeVector& outputFaceNormalIn,
96 G4double aper1In,
97 G4double aper2In,
98 G4double /*aper3In*/,
99 G4double /*aper4In */,
100 G4Material* vacuumMaterialIn,
101 G4double beamPipeThicknessIn,
102 G4Material* beamPipeMaterialIn,
103 const G4String& /*pointsFileIn*/,
104 const G4String& /*pointsUnitIn*/)
105{
106 // clean up after last usage
107 CleanUp();
108
109 inputFaceNormal = inputFaceNormalIn;
110 outputFaceNormal = outputFaceNormalIn;
111
112 G4double containerHalfWidthX = 0;
113 G4double containerHalfWidthY = 0;
114 CreateGeneralAngledSolids(nameIn, lengthIn, aper1In, aper2In, beamPipeThicknessIn,
115 inputFaceNormal, outputFaceNormal, containerHalfWidthX, containerHalfWidthY);
116
117 return CommonFinalConstruction(nameIn, vacuumMaterialIn, beamPipeMaterialIn,
118 lengthIn, containerHalfWidthX, containerHalfWidthY);
119}
120
121
123 G4Material* vacuumMaterialIn,
124 G4Material* beamPipeMaterialIn,
125 G4double lengthIn,
126 G4double containerHalfWidthX,
127 G4double containerHalfWidthY)
128{
129 // doesn't have to be angled as it's only used for transverse subtraction
130 containerSubtractionSolid = new G4Box(nameIn + "_container_solid", // name
131 containerHalfWidthX, // x half width
132 containerHalfWidthY, // y half width
133 4*lengthIn); // full length for unambiguous subtraction
134
135 BDSBeamPipeFactoryBase::CommonConstruction(nameIn, vacuumMaterialIn,
136 beamPipeMaterialIn, lengthIn);
137
138 // record extents
139 BDSExtent ext = BDSExtent(containerHalfWidthX, containerHalfWidthY, lengthIn*0.5);
140
141 // calculate radius if a tube were to be place around it
142 G4double containerRadius = std::hypot(containerHalfWidthX, containerHalfWidthY);
143
144 BDSBeamPipe* aPipe = BuildBeamPipeAndRegisterVolumes(ext, containerRadius);
145
146 return aPipe;
147}
148
150 G4double lengthIn,
151 G4double aper1In,
152 G4double aper2In,
153 G4double beamPipeThicknessIn,
154 const G4ThreeVector& inputfaceIn,
155 const G4ThreeVector& outputfaceIn,
156 G4double& containerHalfWidthX,
157 G4double& containerHalfWidthY)
158{
159 // this function will make a longer normal rectangular beampipe and chop it off
160 // to make angled faces as required
161 // achieve this using the intersection of the normal beampipe (but a little longer)
162 // with a large G4CutTubs to get the angled faces.
163 // note even if one face is flat, we don't save a boolean operation as the intersection
164 // can be on both sides using a G4CutTubs. Also, keeping one side flat would require
165 // shifting the volume from 0 which causes headaches later with SDs.
166
167 // build the solids - vacuum, beampipe and container solids
168 // extra solids required for booleans
169 G4VSolid* vacuumSolidLong;
170 G4VSolid* beamPipeSolidLong;
171 G4VSolid* angledFaceSolid;
172 G4VSolid* containerSolidLong;
173 G4VSolid* angledFaceSolidContainer;
174
175 // build the solid with angled faces for intersection
176 G4double angledFaceRadius = (std::max(aper1In,aper2In) + beamPipeThicknessIn)*2.0; //huge for unambiguous intersection
177
178 // long length for unambiguous boolean - ensure no gaps in beam pipe geometry
179 G4double angledVolumeLength = BDS::CalculateSafeAngledVolumeLength(inputfaceIn, outputfaceIn, lengthIn, angledFaceRadius);
180
181 // check extent of volume's angled face - if it can be built, remaining volumes can be built
182 CheckAngledVolumeCanBeBuilt(lengthIn, inputfaceIn, outputfaceIn, angledFaceRadius, nameIn);
183
184 angledFaceSolid = new G4CutTubs(nameIn + "_angled_face", // name
185 0, // inner radius
186 angledFaceRadius, // outer radius
187 (lengthIn*0.5)-lengthSafety, // half length - must fit within container
188 0, // rotation start angle
189 CLHEP::twopi, // rotation sweep angle
190 inputfaceIn, // input face normal
191 outputfaceIn); // output face normal
192
193 vacuumSolidLong = new G4Box(nameIn + "_vacuum_solid_long", // name
194 aper1In, // x half width
195 aper2In, // y half width
196 angledVolumeLength); // long length for unambiguous boolean
197
198 allSolids.insert(angledFaceSolid);
199 allSolids.insert(vacuumSolidLong);
200
201 vacuumSolid = new G4IntersectionSolid(nameIn + "_vacuum_solid",
202 vacuumSolidLong,
203 angledFaceSolid);
204
205 G4VSolid* beamPipeSolidInner; // construct rectangular beam pipe by subtracting an inner
206 G4VSolid* beamPipeSolidOuter; // box from an outer one - only way
207 // beamPipeSolidInner will be the inner edge of the metal beampipe
208 // therefore it has to be the width of the aperture + lengthSafety
209 beamPipeSolidInner = new G4Box(nameIn + "_pipe_solid_inner", // name
210 aper1In + lengthSafetyLarge, // x half width - length safety to avoid overlaps
211 aper2In + lengthSafetyLarge, // y half width
212 angledVolumeLength); // long length for unambiguous subtraction
213 // beamPipeSolidOuter will be the outer edge of the metal beampipe
214 // therefore it has to be the width of the aperture + beampipeThickness
215 G4double extraWidth = beamPipeThicknessIn + lengthSafetyLarge;
216 beamPipeSolidOuter = new G4Box(nameIn + "_pipe_solid_outer", // name
217 aper1In + extraWidth, // x half width
218 aper2In + extraWidth, // y half width
219 angledVolumeLength); // full length for unambiguous intersection
220 beamPipeSolidLong = new G4SubtractionSolid(nameIn + "_pipe_solid_long",
221 beamPipeSolidOuter,
222 beamPipeSolidInner); // outer minus inner
223 beamPipeSolid = new G4IntersectionSolid(nameIn + "_pipe_solid",
224 beamPipeSolidLong,
225 angledFaceSolid);
226
227 allSolids.insert(beamPipeSolidInner);
228 allSolids.insert(beamPipeSolidOuter);
229 allSolids.insert(beamPipeSolidLong);
230
231 containerHalfWidthX = aper1In + extraWidth + lengthSafetyLarge;
232 containerHalfWidthY = aper2In + extraWidth + lengthSafetyLarge;
233 containerSolidLong = new G4Box(nameIn + "_container_solid_long",// name
234 containerHalfWidthX, // x half width
235 containerHalfWidthY, // y half width
236 angledVolumeLength); // full length for unambiguous intersection
237 angledFaceSolidContainer = new G4CutTubs(nameIn + "_angled_face_container",// name
238 0, // inner radius
239 angledFaceRadius, // outer radius
240 (lengthIn*0.5), // half length
241 0, // rotation start angle
242 CLHEP::twopi, // rotation finish angle
243 inputfaceIn, // input face normal
244 outputfaceIn); // output face normal
245 allSolids.insert(containerSolidLong);
246 allSolids.insert(angledFaceSolidContainer);
247 containerSolid = new G4IntersectionSolid(nameIn + "_container_solid",
248 containerSolidLong,
249 angledFaceSolidContainer);
250}
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
static void CheckAngledVolumeCanBeBuilt(G4double length, const G4ThreeVector &inputfaceAngle, const G4ThreeVector &outputfaceAngle, G4double horizontalWidth, const G4String &name)
check if a beam pipe volume with angled faces can be constructed
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
void CreateGeneralAngledSolids(const G4String &nameIn, G4double lengthIn, G4double aper1In, G4double aper2In, G4double beamPipeThicknessIn, const G4ThreeVector &inputfaceIn, const G4ThreeVector &outputfaceIn, G4double &containerHalfWidthX, G4double &containerHalfWidthY)
BDSBeamPipe * CommonFinalConstruction(const G4String &nameIn, G4Material *vacuumMaterialIn, G4Material *beamPipeMaterialIn, G4double lengthIn, G4double containerHalfWidthX, G4double containerHalfWidthY)
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.