BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSMagnetOuterFactory.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 "BDSBeamPipe.hh"
19#include "BDSColours.hh"
20#include "BDSDebug.hh"
21#include "BDSException.hh"
22#include "BDSExtent.hh"
23#include "BDSGeometryComponent.hh"
24#include "BDSGeometryExternal.hh"
25#include "BDSGeometryFactory.hh"
26#include "BDSGlobalConstants.hh"
27#include "BDSMagnetOuter.hh"
28#include "BDSMagnetOuterFactory.hh"
29#include "BDSMagnetOuterFactoryBase.hh"
30#include "BDSMagnetOuterFactoryCylindrical.hh"
31#include "BDSMagnetOuterFactoryPolesCircular.hh"
32#include "BDSMagnetOuterFactoryPolesFacet.hh"
33#include "BDSMagnetOuterFactoryPolesFacetCrop.hh"
34#include "BDSMagnetOuterFactoryPolesSquare.hh"
35#include "BDSMagnetOuterFactoryLHCLeft.hh"
36#include "BDSMagnetOuterFactoryLHCRight.hh"
37#include "BDSMagnetOuterFactoryNone.hh"
38#include "BDSMagnetOuterInfo.hh"
39#include "BDSMagnetGeometryType.hh"
40#include "BDSMaterials.hh"
41#include "BDSWarning.hh"
42
43#include "globals.hh" // geant4 globals / types
44#include "G4Box.hh"
45#include "G4CutTubs.hh"
46#include "G4LogicalVolume.hh"
47#include "G4ThreeVector.hh"
48
49#include <algorithm>
50#include <cmath>
51#include <sstream>
52#include <string>
53
55
62
63BDSMagnetOuterFactory::BDSMagnetOuterFactory()
64{
65 lengthSafetyLarge = BDSGlobalConstants::Instance()->LengthSafetyLarge();
74 sensitiveOuter = BDSGlobalConstants::Instance()->SensitiveOuter();
75}
76
77BDSMagnetOuterFactory::~BDSMagnetOuterFactory()
78{
79 delete none;
80 delete cylindrical;
81 delete polescircular;
82 delete polessquare;
83 delete polesfacet;
84 delete polesfacetcrop;
85 delete lhcright;
86 delete lhcleft;
87 instance = nullptr;
88}
89
91{
92 switch (magnetTypeIn.underlying())
93 {
94 case BDSMagnetGeometryType::none:
95 {return none; break;}
96 case BDSMagnetGeometryType::cylindrical:
97 {return cylindrical; break;}
98 case BDSMagnetGeometryType::polescircular:
99 {return polescircular; break;}
100 case BDSMagnetGeometryType::polessquare:
101 {return polessquare; break;}
102 case BDSMagnetGeometryType::polesfacet:
103 {return polesfacet; break;}
104 case BDSMagnetGeometryType::polesfacetcrop:
105 {return polesfacetcrop; break;}
106 case BDSMagnetGeometryType::lhcleft:
107 {return lhcleft; break;}
108 case BDSMagnetGeometryType::lhcright:
109 {return lhcright; break;}
110 case BDSMagnetGeometryType::external:
111 {return nullptr; break;}
112 default:
113 {
114 throw BDSException(__METHOD_NAME__, "unknown type \"" + magnetTypeIn.ToString() + "\"");
115 break;
116 }
117 }
118}
119
121 BDSMagnetOuterInfo* outerInfo,
122 G4double outerLength,
123 G4double containerLength,
124 BDSBeamPipe* beamPipe)
125{
126 BDSMagnetOuter* outer = nullptr;
127
128 G4String name = outerInfo->name;
129 BDSMagnetGeometryType geometryType = outerInfo->geometryType;
130
131 if (geometryType == BDSMagnetGeometryType::external)
132 {
133 outer = CreateExternal(name, outerInfo, outerLength, containerLength, beamPipe);
134 G4double loadedLength = outer->GetExtent().DZ();
135 if (loadedLength > outerLength)
136 {
137 BDS::Warning(__METHOD_NAME__, "External geometry of length " + std::to_string(loadedLength/CLHEP::m)
138 + "m\nappears to be too long for magnet of length " + std::to_string(outerLength/CLHEP::m) + "m. ");
139 }
140 return outer;
141 }
142
143 // Check dimensions
144 if (geometryType != BDSMagnetGeometryType::none)
145 {CheckOuterBiggerThanBeamPipe(name, outerInfo, beamPipe);}
146
147 BDSMagnetOuterFactoryBase* factory = GetAppropriateFactory(geometryType);
148
149 switch(magnetType.underlying())
150 {
151 case BDSMagnetType::decapole:
152 {
153 outer = factory->CreateDecapole(name, outerLength, beamPipe, containerLength, outerInfo);
154 break;
155 }
156 case BDSMagnetType::vkicker:
157 {
158 outer = factory->CreateKicker(name, outerLength, beamPipe, containerLength, outerInfo, true);
159 break;
160 }
161 case BDSMagnetType::hkicker:
162 {
163 outer = factory->CreateKicker(name, outerLength, beamPipe, containerLength, outerInfo, false);
164 break;
165 }
166 case BDSMagnetType::muonspoiler:
167 {
168 outer = factory->CreateMuonSpoiler(name, outerLength, beamPipe, containerLength, outerInfo);
169 break;
170 }
171 case BDSMagnetType::octupole:
172 {
173 outer = factory->CreateOctupole(name, outerLength, beamPipe, containerLength, outerInfo);
174 break;
175 }
176 case BDSMagnetType::quadrupole:
177 {
178 outer = factory->CreateQuadrupole(name, outerLength, beamPipe, containerLength, outerInfo);
179 break;
180 }
181 case BDSMagnetType::rfcavity:
182 {
183 outer = factory->CreateRfCavity(name, outerLength, beamPipe, containerLength, outerInfo);
184 break;
185 }
186 case BDSMagnetType::sectorbend:
187 {
188 outer = factory->CreateSectorBend(name, outerLength, beamPipe,
189 containerLength, outerInfo);
190 break;
191 }
192 case BDSMagnetType::rectangularbend:
193 {
194 outer = factory->CreateRectangularBend(name, outerLength, beamPipe,
195 containerLength, outerInfo);
196 break;
197 }
198 case BDSMagnetType::sextupole:
199 {
200 outer = factory->CreateSextupole(name, outerLength, beamPipe, containerLength, outerInfo);
201 break;
202 }
203 case BDSMagnetType::solenoid:
204 {
205 outer = factory->CreateSolenoid(name, outerLength, beamPipe, containerLength, outerInfo);
206 break;
207 }
208 case BDSMagnetType::multipole:
209 {
210 outer = factory->CreateMultipole(name, outerLength, beamPipe, containerLength, outerInfo);
211 break;
212 }
213 case BDSMagnetType::thinmultipole:
214 case BDSMagnetType::dipolefringe:
215 case BDSMagnetType::undulator:
216 case BDSMagnetType::rmatrix:
217 case BDSMagnetType::paralleltransporter:
218 {break;} // leave as nullptr - no outer geometry for dipole fringe or thin multipole
219 default:
220 G4cout << __METHOD_NAME__ << "unknown magnet type " << magnetType << " - no outer volume built" << G4endl;
221 break;
222 }
223 return outer;
224}
225
227 BDSMagnetOuterInfo* info,
228 G4double /*length*/,
229 G4double magnetContainerLength,
230 BDSBeamPipe* beampipe)
231{
232 std::map<G4String, G4Colour*> defaultMap = {
233 {"coil", BDSColours::Instance()->GetColour("coil")},
234 {"bend", BDSColours::Instance()->GetColour("sectorbend")},
235 {"yoke", BDSColours::Instance()->GetColour("quadrupole")},
236 {"quad", BDSColours::Instance()->GetColour("quadrupole")},
237 {"sext", BDSColours::Instance()->GetColour("sextupole")},
238 {"oct", BDSColours::Instance()->GetColour("octupole")},
239 {"dec", BDSColours::Instance()->GetColour("decapole")}
240 };
242 info->geometryTypeAndPath,
243 &defaultMap,
244 info->autoColour,
245 0, 0,
246 nullptr,
248
249 BDSExtent bpExtent = beampipe->GetExtent();
250 BDSExtent magInner = geom->GetInnerExtent();
251
252 if (magInner.TransverselyLessThan(bpExtent))
253 {
254 std::stringstream ss, ss2, ss3;
255 ss << info->geometryTypeAndPath;
256 ss2 << magInner;
257 ss3 << bpExtent;
258 std::string sss = ss.str();
259 sss += " will not fit around beam pipe\nin element \"" + name + "\" and could potentially overlap with it\n";
260 sss += "Determined extents to be:\n";
261 sss += "External geometry inner: " + ss2.str() + "\n";
262 sss += "Beam pipe outer : " + ss3.str() + "\n";
263 sss += "Check for overlaps with /geometry/test/run";
264 BDS::Warning(__METHOD_NAME__, sss);
265 }
266
267 BDSGeometryComponent* container = CreateContainerForExternal(name, magnetContainerLength, geom, beampipe);
268
269 BDSMagnetOuter* outer = new BDSMagnetOuter(geom, container);
270 return outer;
271}
272
274 G4double length,
275 BDSGeometryExternal* external,
276 BDSBeamPipe* beampipe)
277{
278 G4ThreeVector inputFace = beampipe->InputFaceNormal();
279 G4ThreeVector outputFace = beampipe->OutputFaceNormal();
280
281 BDSExtent outer = external->GetExtent();
282 G4VSolid* containerSolid;
283 BDSExtent containerExt;
284 if ((inputFace.z() > -1) || (outputFace.z() < 1))
285 {// use a cut tubs for angled face
286 G4double posR = std::hypot(outer.XPos(),outer.YPos());
287 G4double negR = std::hypot(outer.XNeg(),outer.YNeg());
288 G4double magnetContainerRadius = std::max(posR, negR) + 1*CLHEP::mm; // generous margin
289 containerSolid = new G4CutTubs(name + "_container_solid", // name
290 0, // inner radius
291 magnetContainerRadius, // outer radius
292 length * 0.5, // z half length
293 0, // starting angle
294 CLHEP::twopi, // sweep angle
295 inputFace,
296 outputFace);
297 containerExt = BDSExtent(magnetContainerRadius, magnetContainerRadius, 0.5*length);
298 }
299 else
300 {// flat faces so use a box
301 G4double radius = outer.MaximumAbsTransverse() + 1*CLHEP::mm; // generous margin
302 containerSolid = new G4Box(name + "_container_solid", // name
303 radius,
304 radius,
305 length*0.5);
306 containerExt = BDSExtent(radius, radius, length*0.5);
307 }
308
309 G4Material* worldMaterial = BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->WorldMaterial());
310 G4LogicalVolume* containerLV = new G4LogicalVolume(containerSolid,
311 worldMaterial,
312 name + "_container_lv");
313
314 containerLV->SetVisAttributes(BDSGlobalConstants::Instance()->ContainerVisAttr());
315
316 BDSGeometryComponent* container = new BDSGeometryComponent(containerSolid,
317 containerLV,
318 containerExt);
319
320 return container;
321}
322
323void BDSMagnetOuterFactory::CheckOuterBiggerThanBeamPipe(const G4String& name,
324 const BDSMagnetOuterInfo* outerInfo,
325 const BDSBeamPipe* beamPipe) const
326{
327 G4double outerHorizontal = outerInfo->horizontalWidth;
328 G4double outerVertical = outerInfo->horizontalWidth * outerInfo->vhRatio;
329 BDSExtent bpExtent = beamPipe->GetExtent();
330 // 1x lsl between beam pipe and magnet container
331 // 1x lsl between magnet container and yoke
332 // 1x lsl for minimum yoke width -> takes us to minimum horizontalWidth required
333 G4double margin = 3*lengthSafetyLarge;
334 if (outerHorizontal < bpExtent.DX()+margin || outerVertical < bpExtent.DY()+margin)
335 {
336 std::string msg = "Magnet outer dimensions too small to encompass beam pipe for element " + name + "\n";
337 msg += "magnet horizontal full width -> " + std::to_string(outerHorizontal) + "mm\n";
338 msg += "magnet vertical full width -> " + std::to_string(outerVertical) + "mm\n";
339 msg += "Beam pipe width (mm): " + std::to_string(bpExtent.DX()) + ", height : ";
340 msg += std::to_string(bpExtent.DY());
341 throw BDSException(__METHOD_NAME__, msg);
342 }
343}
A holder class for a piece of beam pipe geometry.
G4ThreeVector InputFaceNormal() const
Accessor.
G4ThreeVector OutputFaceNormal() const
Accessor.
G4Colour * GetColour(G4double red, G4double green, G4double blue, G4double alpha=1)
Get a cached anonymous colour by values.
static BDSColours * Instance()
singleton pattern
Definition BDSColours.cc:32
General exception with possible name of object and message.
Holder for +- extents in 3 dimensions.
Definition BDSExtent.hh:38
G4double XPos() const
Accessor.
Definition BDSExtent.hh:65
G4double MaximumAbsTransverse() const
Return the maximum absolute value considering only x,y.
Definition BDSExtent.cc:170
G4double XNeg() const
Accessor.
Definition BDSExtent.hh:64
G4double DZ() const
The difference in a dimension.
Definition BDSExtent.hh:84
G4double YNeg() const
Accessor.
Definition BDSExtent.hh:66
G4double DX() const
The difference in a dimension.
Definition BDSExtent.hh:82
G4double DY() const
The difference in a dimension.
Definition BDSExtent.hh:83
G4bool TransverselyLessThan(const BDSExtent &r) const
Comparison operator for x,y only. Ignores z (length).
Definition BDSExtent.hh:190
G4double YPos() const
Accessor.
Definition BDSExtent.hh:67
A generic geometry component for a bdsim model.
BDSExtent GetExtent() const
Accessor - see member for more info.
BDSExtent GetInnerExtent() const
Accessor - see member for more info.
A loaded piece of externally provided geometry.
BDSGeometryExternal * BuildGeometry(G4String componentName, const G4String &formatAndFilePath, std::map< G4String, G4Colour * > *colourMapping=nullptr, G4bool autoColour=true, G4double suggestedLength=0, G4double suggestedHorizontalWidth=0, std::vector< G4String > *namedVacuumVolumes=nullptr, G4bool makeSensitive=true, BDSSDType sensitivityType=BDSSDType::energydep, BDSSDType vacuumSensitivityType=BDSSDType::energydepvacuum, G4bool stripOuterVolumeAndMakeAssembly=false, G4UserLimits *userLimitsToAttachToAllLVs=nullptr, G4bool dontReloadGeometry=false)
static BDSGeometryFactory * Instance()
Singleton accessor.
static BDSGlobalConstants * Instance()
Access method.
Abstract base class for magnet outer volume factories.
virtual BDSMagnetOuter * CreateQuadrupole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
quadrupole outer volume
virtual BDSMagnetOuter * CreateSolenoid(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
solenoid outer volume
virtual BDSMagnetOuter * CreateKicker(G4String name, G4double length, const BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe, G4bool vertical)=0
horizontal and vertical kicker outer volume
virtual BDSMagnetOuter * CreateRectangularBend(G4String name, G4double length, const BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
rectangular bend outer volume
virtual BDSMagnetOuter * CreateDecapole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
decapole outer volume
virtual BDSMagnetOuter * CreateSectorBend(G4String name, G4double length, const BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
sector bend outer volume
virtual BDSMagnetOuter * CreateMuonSpoiler(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
muon spoiler outer volume
virtual BDSMagnetOuter * CreateMultipole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
general multipole outer volume - could be any 2N order multipole
virtual BDSMagnetOuter * CreateOctupole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
octupole outer volume
virtual BDSMagnetOuter * CreateRfCavity(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
RF cavity outer volume.
virtual BDSMagnetOuter * CreateSextupole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
sextupole outer volume
Factory that produces cylindrical magnet geometry.
LHC outer magnet geometry offset to the left.
LHC outer magnet geometry offset to the right.
Factory that produces null outer geometry.
Factory class for outer volume of magnets. Produces magnets with 2N-poles around the beampipe with a ...
Factory class for outer volume of magnets.
Factory class for outer volume of magnets.
Factory class for outer volume of magnets.
The main interface for using the magnet outer factories.
static BDSMagnetOuterFactory * Instance()
Singleton accessor.
BDSMagnetOuterFactoryBase * lhcleft
Factory instance.
BDSMagnetOuterFactoryBase * polesfacetcrop
Factory instance.
BDSMagnetOuterFactoryBase * lhcright
Factory instance.
static BDSMagnetOuterFactory * instance
Singleton instance.
BDSGeometryComponent * CreateContainerForExternal(const G4String &name, G4double length, BDSGeometryExternal *external, BDSBeamPipe *beampipe)
BDSMagnetOuter * CreateExternal(const G4String &name, BDSMagnetOuterInfo *info, G4double length, G4double magnetContainerLength, BDSBeamPipe *beampipe)
BDSMagnetOuterFactoryBase * cylindrical
Factory instance.
BDSMagnetOuterFactoryBase * polessquare
Factory instance.
BDSMagnetOuter * CreateMagnetOuter(BDSMagnetType magnetType, BDSMagnetOuterInfo *outerInfo, G4double outerLength, G4double chordLength, BDSBeamPipe *beampipe)
BDSMagnetOuterFactoryBase * polescircular
Factory instance.
BDSMagnetOuterFactoryBase * GetAppropriateFactory(BDSMagnetGeometryType magnetTypeIn)
Get the appropriate derived factory for the required magnet style.
G4bool sensitiveOuter
Cache of global option.
BDSMagnetOuterFactoryBase * none
Factory instance.
BDSMagnetOuterFactoryBase * polesfacet
Factory instance.
Holder struct of all information required to create the outer geometry of a magnet.
An object for both the returned magnet outer body but also a tight fitting container for the whole ma...
static BDSMaterials * Instance()
Singleton pattern access.
G4Material * GetMaterial(G4String material) const
Get material by name.
type underlying() const
return underlying value (can be used in switch statement)