BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSMuonCooler.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
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 "BDSAcceleratorComponent.hh"
20#include "BDSBeamPipe.hh"
21#include "BDSBeamPipeFactory.hh"
22#include "BDSBeamPipeInfo.hh"
23#include "BDSCavity.hh"
24#include "BDSCavityFactory.hh"
25#include "BDSCavityInfo.hh"
26#include "BDSCavityType.hh"
27#include "BDSColours.hh"
28#include "BDSColourFromMaterial.hh"
29#include "BDSDebug.hh"
30#include "BDSException.hh"
31#include "BDSExtent.hh"
32#include "BDSFieldBuilder.hh"
33#include "BDSGlobalConstants.hh"
34#include "BDSMaterials.hh"
35#include "BDSMuonCooler.hh"
36
37#include "G4Colour.hh"
38#include "G4ExtrudedSolid.hh"
39#include "G4LogicalVolume.hh"
40#include "G4PVPlacement.hh"
41#include "G4RotationMatrix.hh"
42#include "G4String.hh"
43#include "G4ThreeVector.hh"
44#include "G4Tubs.hh"
45#include "G4Types.hh"
46#include "G4VisAttributes.hh"
47#include "G4TwoVector.hh"
48
49#include "CLHEP/Units/SystemOfUnits.h"
50
51#include <cmath>
52#include <map>
53#include <set>
54#include <string>
55#include <vector>
56
57class G4Material;
58
59BDSMuonCooler::BDSMuonCooler(const G4String& nameIn,
60 G4double lengthIn,
61 G4double containerRadiusIn,
62 G4Material* surroundingMaterialIn,
63 const std::vector<BDS::MuonCoolerCoilInfo>& coilInfosIn,
64 const std::vector<BDS::MuonCoolerDipoleInfo>& dipoleInfosIn,
65 const std::vector<BDS::MuonCoolerCavityInfo>& cavityInfosIn,
66 const std::vector<BDS::MuonCoolerAbsorberInfo>& absorberInfosIn,
67 BDSBeamPipeInfo* beamPipeTemplateIn,
68 BDSFieldInfo* outerFieldRecipeIn):
69 BDSAcceleratorComponent(nameIn, lengthIn, 0, "muoncooler", nullptr),
70 containerRadius(containerRadiusIn),
71 surroundingMaterial(surroundingMaterialIn),
72 coilInfos(coilInfosIn),
73 dipoleInfos(dipoleInfosIn),
74 cavityInfos(cavityInfosIn),
75 absorberInfos(absorberInfosIn),
76 beamPipeTemplate(beamPipeTemplateIn),
77 outerFieldRecipe(outerFieldRecipeIn)
78{;}
79
80BDSMuonCooler::~BDSMuonCooler()
81{;}
82
84{
86 BuildCoils();
87 BuildDipoles();
88 BuildAbsorbers();
89 BuildCavities();
90 BuildField();
91}
92
94{
95 containerSolid = new G4Tubs(name + "_container_solid",
96 0,
97 containerRadius,
98 0.5*chordLength,
99 0,
100 CLHEP::twopi);
101
102 containerLogicalVolume = new G4LogicalVolume(containerSolid,
103 surroundingMaterial,
104 name + "_container_lv");
105
106 BDSExtent ext(containerRadius, containerRadius, chordLength * 0.5);
107 SetExtent(ext);
108
110 containerLogicalVolume->SetUserLimits(userLimits);
111
112 auto containerVis = new G4VisAttributes(*BDSColours::Instance()->GetColour("opaquebox"));
113 containerVis->SetVisibility(true);
114 containerVis->SetForceLineSegmentsPerCircle(BDSGlobalConstants::Instance()->NSegmentsPerCircle());
115 containerLogicalVolume->SetVisAttributes(containerVis);
116 RegisterVisAttributes(containerVis);
117}
118
119void BDSMuonCooler::BuildCoils()
120{
121 // make a unique set of coil visualisations - only what we need
122 std::set<G4Material*> coilMaterials;
123 for (const auto& info : coilInfos)
124 {coilMaterials.insert(info.material);}
125 std::map<G4Material*, G4VisAttributes*> coilVises;
126 for (const auto& material : coilMaterials)
127 {
128 auto coilVis = new G4VisAttributes(*BDSColourFromMaterial::Instance()->GetColour(material));
129 coilVis->SetVisibility(true);
130 coilVis->SetForceLineSegmentsPerCircle(BDSGlobalConstants::Instance()->NSegmentsPerCircle());
131 RegisterVisAttributes(coilVis);
132 coilVises[material] = coilVis;
133 }
134
135 // loop over coils and build and place them
136 G4int i = 0;
137 for (const auto& info : coilInfos)
138 {
139 G4String iStr = std::to_string(i);
140 G4String baseName = name + "_coil_" + iStr;
141 auto coilSolid = new G4Tubs(baseName + "_solid",
142 info.innerRadius,
143 info.innerRadius + info.radialThickness,
144 0.5*info.fullLengthZ,
145 0,
146 CLHEP::twopi);
147 RegisterSolid(coilSolid);
148 auto coilLV = new G4LogicalVolume(coilSolid, info.material, baseName + "_lv");
149 RegisterLogicalVolume(coilLV);
150 coilLV->SetVisAttributes(coilVises[info.material]);
151
152 auto coilPV = new G4PVPlacement(nullptr,
153 G4ThreeVector(0,0,info.offsetZ),
154 coilLV,
155 baseName + "_pv",
156 containerLogicalVolume,
157 false,
158 0,
161 i++;
162 }
163}
164
165void BDSMuonCooler::BuildDipoles()
166{
167 // do not need magnet visualisations yet
168
169 // loop over dipoles and build and place them
170 G4int i = 0;
171 for (const auto& info : dipoleInfos)
172 {
173 G4String iStr = std::to_string(i);
174 G4String baseName = name + "_dipole_" + iStr;
175 auto dipoleSolid = new G4Tubs(baseName + "_solid",
176 info.apertureRadius,
177 info.apertureRadius*1.000001,
178 0.5*info.fullLengthZ,
179 0,
180 CLHEP::twopi);
181 RegisterSolid(dipoleSolid);
182 auto dipoleLV = new G4LogicalVolume(dipoleSolid, BDSMaterials::Instance()->GetMaterial("vacuum"), baseName + "_lv");
183 RegisterLogicalVolume(dipoleLV);
184 i++;
185 }
186}
187
188void BDSMuonCooler::BuildAbsorbers()
189{
190 // make a unique set of absorber visualisations - only what we need
191 std::set<G4Material*> absorberMaterials;
192 for (const auto& info : absorberInfos)
193 {absorberMaterials.insert(info.material);}
194 std::map<G4Material*, G4VisAttributes*> absorberVises;
195 for (const auto& material : absorberMaterials)
196 {
197 auto absVis = new G4VisAttributes(*BDSColourFromMaterial::Instance()->GetColour(material));
198 absVis->SetVisibility(true);
199 absVis->SetForceLineSegmentsPerCircle(BDSGlobalConstants::Instance()->NSegmentsPerCircle());
200 RegisterVisAttributes(absVis);
201 absorberVises[material] = absVis;
202 }
203
204 // loop over absorbers and build and place them
205 G4int i = 0;
206 for (const auto& info : absorberInfos)
207 {
208 G4String iStr = std::to_string(i);
209 G4String baseName = name + "_absorber_" + iStr;
210 G4VSolid* absSolid;
211 G4RotationMatrix* rm = nullptr;
212 if (info.absorberType == "wedge")
213 {
214 G4double halfHeight = 0.5*info.wedgeApexToBase;
215 G4double dy = std::tan(info.wedgeOpeningAngle * 0.5) * info.wedgeApexToBase;
216 std::vector<G4TwoVector> polygons = { {-halfHeight,0}, {halfHeight,dy}, {halfHeight,-dy} };
217 absSolid = new G4ExtrudedSolid(baseName + "_solid",
218 polygons,
219 info.wedgeHeight*0.5,
220 G4TwoVector(), 1.0,
221 G4TwoVector(), 1.0);
222 rm = new G4RotationMatrix();
223 rm->rotate(CLHEP::halfpi, G4ThreeVector(1,0,0));
224 rm->rotate(info.wedgeRotationAngle, G4ThreeVector(0,1,0));
226 }
227 else if (info.absorberType == "cylinder")
228 {
229 absSolid = new G4Tubs(baseName + "_solid",
230 0,
231 info.cylinderRadius,
232 0.5 * info.cylinderLength,
233 0,
234 CLHEP::twopi);
235 }
236 else
237 {throw BDSException(__METHOD_NAME__,"unknown absorber type \"" + info.absorberType + "\"");}
238 RegisterSolid(absSolid);
239 auto absLV = new G4LogicalVolume(absSolid, info.material, baseName + "_lv");
241 absLV->SetVisAttributes(absorberVises[info.material]);
242
243 auto coilPV = new G4PVPlacement(rm,
244 info.placement,
245 absLV,
246 baseName + "_pv",
247 containerLogicalVolume,
248 false,
249 0,
252 i++;
253 }
254}
255
256void BDSMuonCooler::BuildCavities()
257{
258 struct DriftSpec
259 {
260 BDSBeamPipeInfo* bpRecipe;
261 G4ThreeVector position;
262 };
263 std::vector<DriftSpec> beampipeInfos;
264 for (G4int i = 0; i < (G4int)cavityInfos.size() - 1; i++)
265 {
266 G4double zA = cavityInfos[i].offsetZ + 0.5*cavityInfos[i].lengthZ;
267 G4double zB = cavityInfos[i+1].offsetZ - 0.5*cavityInfos[i+1].lengthZ;
268 G4double dZ = zB - zA;
269 if (dZ >= 1*CLHEP::mm)
270 {
271 G4ThreeVector position = {0,0,zB-0.5*dZ};
272 beampipeInfos.emplace_back(DriftSpec{beamPipeTemplate,position});
273 }
274 }
275
276 std::vector<BDSCavityInfo> recipes;
277 for (const auto& info : cavityInfos)
278 {
279 auto r = BDSCavityInfo(BDSCavityType::pillbox,
280 info.cavityMaterial,
281 info.windowRadius,
282 info.cavityThickness,
283 info.cavityRadius,
284 info.lengthZ * 0.5);
285 r.inputWindowMaterial = info.windowMaterial;
286 r.inputWindowThickness = info.windowThickness;
287 r.outputWindowMaterial = info.windowMaterial;
288 r.outputWindowThickness = info.windowThickness;
289 recipes.push_back(r);
290 }
291
292 std::vector<BDSCavity*> cavities;
293 for (G4int i = 0; i < (G4int)recipes.size(); i++)
294 {
295 G4String cavityName = name + "_cavity_" + std::to_string(i);
296 auto cavity = BDSCavityFactory::Instance()->CreateCavity(cavityName,
297 cavityInfos[i].lengthZ,
298 &recipes[i],
299 cavityInfos[i].vacuumMaterial);
300
301 auto cavityPV = new G4PVPlacement(nullptr,
302 G4ThreeVector(0,0,cavityInfos[i].offsetZ),
303 cavity->GetContainerLogicalVolume(),
304 cavityName + "_pv",
305 containerLogicalVolume,
306 false,
307 0,
309 RegisterPhysicalVolume(cavityPV);
310 RegisterDaughter(cavity);
311 }
312}
313
314void BDSMuonCooler::BuildField()
315{
317 containerLogicalVolume,
318 true);
319}
Abstract class that represents a component of an accelerator.
G4UserLimits * userLimits
Cache of user limits.
const G4String name
Const protected member variable that may not be changed by derived classes.
static G4bool checkOverlaps
Useful variable often used in construction.
G4double chordLength
Protected member variable that can be modified by derived classes.
Holder class for all information required to describe a beam pipe model.
static BDSCavityFactory * Instance()
Singleton accessor.
BDSCavity * CreateCavity(const G4String &name, G4double totalChordLength, const BDSCavityInfo *info, G4Material *vacuumMaterial)
Main function to create a piece of cavity geometry.
Holder for all Geometrical information required to create an RF cavity.
static BDSColourFromMaterial * Instance()
Singleton pattern.
static BDSColours * Instance()
singleton pattern
Definition BDSColours.cc:33
General exception with possible name of object and message.
Holder for +- extents in 3 dimensions.
Definition BDSExtent.hh:39
void RegisterFieldForConstruction(const BDSFieldInfo *info, G4LogicalVolume *logicalVolume, const G4bool propagateToDaughters=false, const BDSMagnetStrength *magnetStrengthForScaling=nullptr, const G4String &scalingKey="none")
static BDSFieldBuilder * Instance()
Singleton pattern accessor.
All info required to build complete field of any type.
void RegisterRotationMatrix(G4RotationMatrix *rotationMatrix)
void RegisterDaughter(BDSGeometryComponent *anotherComponent)
void RegisterLogicalVolume(G4LogicalVolume *logicalVolume)
void RegisterPhysicalVolume(G4VPhysicalVolume *physicalVolume)
void SetExtent(const BDSExtent &extIn)
Set extent.
void RegisterVisAttributes(G4VisAttributes *visAttribute)
void RegisterSolid(G4VSolid *solid)
static BDSGlobalConstants * Instance()
Access method.
static BDSMaterials * Instance()
Singleton pattern access.
virtual void BuildContainerLogicalVolume()
Void function to fulfill BDSAcceleratorComponent requirements.
virtual void Build()
Construct geometry.