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