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