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