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