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