BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSMagnetOuterFactoryPolesSquare.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 "BDSExtent.hh"
19#include "BDSGlobalConstants.hh"
20#include "BDSMagnetOuter.hh"
21#include "BDSMagnetOuterFactoryPolesSquare.hh"
22#include "BDSMaterials.hh"
23#include "BDSSDType.hh"
24
25#include "globals.hh"
26#include "G4Box.hh"
27#include "G4Colour.hh"
28#include "G4IntersectionSolid.hh"
29#include "G4LogicalVolume.hh"
30#include "G4Material.hh"
31#include "G4PVPlacement.hh"
32#include "G4SubtractionSolid.hh"
33#include "G4Tubs.hh"
34#include "G4VisAttributes.hh"
35#include "G4VSolid.hh"
36
37#include <map>
38#include <set>
39#include <vector>
40
41BDSMagnetOuterFactoryPolesSquare::BDSMagnetOuterFactoryPolesSquare():
42 BDSMagnetOuterFactoryPolesBase(/*poleStopFactor=*/1.5)
43{
44 CleanUp();
45}
46
52
54{
55 poleRotations.clear();
56 poleSolids.clear();
57 poleLVs.clear();
58 order = 0;
59}
60
62 G4double length,
63 G4int /*order*/,
64 G4double magnetContainerLength,
65 G4double magnetContainerRadiusIn)
66{
67 // square yoke - have to do subtraction between two solid boxes
68 G4VSolid* yokeOuter = new G4Box(name + "_yoke_outer_solid", // name
69 yokeFinishRadius, // x half width
70 yokeFinishRadius, // y half width
71 length*0.5 - lengthSafety); // z half length
72
73 G4VSolid* yokeInner = new G4Box(name + "_yoke_inner_solid", // name
74 yokeStartRadius, // x half width
75 yokeStartRadius, // y half width
76 length); // z half length
77 // inner length is 2x as long for unambiguous subtraction
78 allSolids.insert(yokeOuter);
79 allSolids.insert(yokeInner);
80
81 yokeSolid = new G4SubtractionSolid(name + "_yoke_solid", // name
82 yokeOuter,
83 yokeInner);
84
85 // note container must have hole in it for the beampipe to fit in!
86 // poled geometry doesn't fit tightly to beampipe so can alays use a circular aperture
87
88 G4VSolid* containerOuter = new G4Box(name + "_container_outer_solid", // name
89 yokeFinishRadius, // x half width
90 yokeFinishRadius, // y half width
91 length*0.5); // x half width
92
93 G4VSolid* containerInner = new G4Tubs(name + "_container_inner_solid", // name
94 0, // inner radius
95 poleStartRadius, // finish radius
96 length, // z half length
97 0, // start angle
98 CLHEP::twopi); // sweep angle
99 // length of inner is long for unambiguous subtraction
100 allSolids.insert(containerOuter);
101 allSolids.insert(containerInner);
102
103 // pole intersection solid
104 G4double croppingBoxRadius = yokeStartRadius - lengthSafety;
105 poleIntersectionSolid = new G4Box(name + "_pole_intersection_solid", // name
106 croppingBoxRadius, // x half width
107 croppingBoxRadius, // y half width
108 length); // z length
109 allSolids.insert(poleIntersectionSolid);
110 // z length long for unambiguous intersection
111
112 containerSolid = new G4SubtractionSolid(name + "_outer_container_solid", // name
113 containerOuter,
114 containerInner);
115
116 magnetContainerSolid = new G4Box(name + "_container_solid", // name
117 magnetContainerRadiusIn, // x half length
118 magnetContainerRadiusIn, // y half length
119 magnetContainerLength*0.5);// z half length
120
121 magContExtent = BDSExtent(magnetContainerRadiusIn, magnetContainerRadiusIn, magnetContainerLength*0.5);
122}
123
125 G4double /*length*/,
126 G4int orderIn)
127{
128 order = orderIn; // copy to member variable - this is the first function to be called with order
129
130 G4int nPoles = 2*orderIn;
131 segmentAngle = CLHEP::twopi/nPoles; // angle per pole
132 // create different poles to fit inside square yoke
133 for (G4int i = 0; i < nPoles; ++i)
134 {
135 G4RotationMatrix* iPoleRM = new G4RotationMatrix();
136 G4double rotationAngle = (0.5-i)*segmentAngle + CLHEP::pi*0.5;
137 iPoleRM->rotateZ(rotationAngle);
138 allRotationMatrices.insert(iPoleRM);
139 // crop the singlepolesolid with the cropping box so it'll fit inside the outer square yoke
140 G4IntersectionSolid* aSolid = new G4IntersectionSolid(name + "_pole_solid", // name
141 poleSolid, // solid 1 - the pole
142 poleIntersectionSolid,// solid 2 - the one to be shifted
143 iPoleRM, // rotation matrix
144 G4ThreeVector()); // translation vector
145
146 poleSolids.push_back(aSolid);
147 }
148}
149
151 G4Colour* colour,
152 G4Material* outerMaterial)
153{
154 G4VisAttributes* outerVisAttr = new G4VisAttributes(*colour);
155 outerVisAttr->SetVisibility(true);
156 outerVisAttr->SetForceLineSegmentsPerCircle(nSegmentsPerCircle);
157 allVisAttributes.insert(outerVisAttr);
158
159 for (G4int n = 0; n < 2*order; ++n)
160 {
161 G4LogicalVolume* thisPole = new G4LogicalVolume(poleSolids[n],
162 outerMaterial,
163 name + "_pole_lv");
164 thisPole->SetVisAttributes(outerVisAttr);
165 poleLVs.push_back(thisPole);
166 allLogicalVolumes.insert(thisPole);
167 }
168
169 // yoke
170 yokeLV = new G4LogicalVolume(yokeSolid,
171 outerMaterial,
172 name + "_yoke_lv");
173 yokeLV->SetVisAttributes(outerVisAttr);
174
175 // container
176 G4Material* worldMaterial = BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->WorldMaterial());
177 containerLV = new G4LogicalVolume(containerSolid,
178 worldMaterial,
179 name + "_container_lv");
180 containerLV->SetVisAttributes(containerVisAttr);
181
182 magnetContainerLV = new G4LogicalVolume(magnetContainerSolid,
183 worldMaterial,
184 name + "_container_lv");
185 magnetContainerLV->SetVisAttributes(containerVisAttr);
186
187 // user limits
188 yokeLV->SetUserLimits(defaultUserLimits);
189 containerLV->SetUserLimits(defaultUserLimits);
190 magnetContainerLV->SetUserLimits(defaultUserLimits);
191 for (auto& lv : poleLVs)
192 {lv->SetUserLimits(defaultUserLimits);}
193 for (auto& lv : allLogicalVolumes)
194 {lv->SetUserLimits(defaultUserLimits);}
195
196 // create logical volumes for the coils using base class method
198}
199
201 G4int orderIn)
202{
203 // PLACEMENT
204 // place the components inside the container
205 // note we don't need the pointer for placements - it's registered upon construction with g4
206 yokePV = new G4PVPlacement(nullptr, // no rotation
207 G4ThreeVector(), // position
208 yokeLV, // lv to be placed
209 name + "_yoke_pv", // name
210 containerLV, // mother lv to be placed in
211 false, // no boolean operation
212 0, // copy number
213 checkOverlaps); // whether to check overlaps
214
215 // place poles
216 if (!buildPole)
217 {return;}
218 G4double nPoles = 2*orderIn;
219 segmentAngle = CLHEP::twopi/nPoles; // angle per pole
220 G4PVPlacement* aPlacement = nullptr;
221 for (G4int n = 0; n < 2*orderIn; ++n)
222 {
223 G4RotationMatrix* rm = new G4RotationMatrix();
224 G4double rotationAngle = (0.5-n)*segmentAngle + CLHEP::pi*0.5;
225 rm->rotateZ(-rotationAngle);
226 allRotationMatrices.insert(rm);
227 G4String pvName = name + "_pole_" + std::to_string(n) + "_pv";
228 // only need to test the end of one iterator as both should be the same length
229 aPlacement = new G4PVPlacement(rm, // rotation
230 G4ThreeVector(), // position
231 poleLVs[n], // logical volume
232 pvName, // name
233 containerLV, // mother lv to be placed in
234 false, // no boolean operation
235 n, // copy number
236 checkOverlaps); // check overlaps
237 allPhysicalVolumes.insert(aPlacement);
238 }
239}
240
242 G4double length,
243 BDSBeamPipe* beamPipe,
244 G4int orderIn,
245 G4double magnetContainerRadiusIn,
246 const BDSMagnetOuterInfo* recipe)
247{
249 orderIn, magnetContainerRadiusIn, recipe);
250
251 std::set<G4LogicalVolume*> tempLVs(poleLVs.begin(), poleLVs.end());
252 outer->RegisterLogicalVolume(tempLVs);
253 if (sensitiveOuter)
254 {outer->RegisterSensitiveVolume(tempLVs, BDSSDType::energydep);}
255
256 return outer;
257}
258
A holder class for a piece of beam pipe geometry.
Holder for +- extents in 3 dimensions.
Definition BDSExtent.hh:38
G4bool checkOverlaps
Cache of global constants variable.
G4double lengthSafety
Cache of global constants variable.
G4VisAttributes * containerVisAttr
Cache of global constants variable.
G4int nSegmentsPerCircle
Cache of global constants variable.
G4UserLimits * defaultUserLimits
Cache of global constants variable.
void RegisterLogicalVolume(G4LogicalVolume *logicalVolume)
void RegisterSensitiveVolume(G4LogicalVolume *sensitiveVolume, BDSSDType sensitivityType)
static BDSGlobalConstants * Instance()
Access method.
G4VSolid * poleSolid
Solid for an individual pole that will be placed multiple times.
G4bool sensitiveOuter
Cache of global constants variable.
G4VSolid * yokeSolid
Solid for outer part that connects all poles.
Factory class for outer volume of magnets. Produces magnets with 2N-poles around the beampipe with a ...
G4double yokeFinishRadius
Finish radius of yoke geometry from magnet centre - less than horizontalWidth.
G4double segmentAngle
2PI / # of poles - angle per segment allocated for each pole.
G4VSolid * poleIntersectionSolid
Solid used to chop off pole.
virtual void CleanUp()
Empty containers for next use - this class is never deleted so can't rely on scope.
virtual void CreateLogicalVolumesCoil(const G4String &name)
G4double poleStartRadius
Start radius of the pole from magnet centre.
G4bool buildPole
Whether or not to build poles (and therefore coils).
G4double yokeStartRadius
Start radius of yoke geometry from magnet cetnre.
virtual BDSMagnetOuter * CommonConstructor(const G4String &name, G4double length, BDSBeamPipe *beamPipe, G4int order, G4double magnetContainerLength, const BDSMagnetOuterInfo *recipe)
Common construction tasks to all methods - assemble yoke and poles in container.
void CleanUpPolesSquare()
Clean up for this factory. Non-virtual as used in constructor.
virtual void IntersectPoleWithYoke(const G4String &name, G4double length, G4int orderIn)
Chop off the top of the pole to match the appropriate yoke geometry.
virtual BDSMagnetOuter * CommonConstructor(const G4String &name, G4double length, BDSBeamPipe *beamPipe, G4int order, G4double magnetContainerLength, const BDSMagnetOuterInfo *recipe)
virtual void CreateLogicalVolumes(const G4String &name, G4Colour *colour, G4Material *outerMaterial)
std::vector< G4RotationMatrix * > poleRotations
virtual void PlaceComponents(const G4String &name, G4int order)
Place the poles and yoke in the container volume.
virtual void CreateYokeAndContainerSolid(const G4String &name, G4double length, G4int order, G4double magnetContainerLength, G4double magnetContainerRadiusIn)
Create yoke that connects poles and container to put them in.
virtual void CleanUp()
Clean up all memebers used.
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.