BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSFieldEMMuonCooler.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 "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSFieldEMMuonCooler.hh"
22#include "BDSFieldInfoExtra.hh"
23#include "BDSFieldMagSolenoidBlock.hh"
24#include "BDSFieldMagSolenoidSheet.hh"
25#include "BDSFieldMagSolenoidLoop.hh"
26#include "BDSFieldMagDipoleEnge.hh"
27#include "BDSFieldMagDipoleHardEdgeMuonCooler.hh"
28#include "BDSFieldMagVectorSum.hh"
29#include "BDSFieldMag.hh"
30#include "BDSFieldEMVectorSum.hh"
31#include "BDSFieldEMRFCavity.hh"
32#include "BDSFieldType.hh"
33
34#include "G4ThreeVector.hh"
35#include "G4Types.hh"
36
37#include <utility>
38
39BDSFieldEMMuonCooler::BDSFieldEMMuonCooler(const BDSFieldInfoExtraMuonCooler* info,
40 G4double /*brho*/):
41 coilField(nullptr),
42 dipoleField(nullptr),
43 rfField(nullptr)
44{
45 BuildMagnets(info);
46 BuildDipoles(info);
47 BuildRF(info);
48}
49
50void BDSFieldEMMuonCooler::BuildMagnets(const BDSFieldInfoExtraMuonCooler* info)
51{
52 switch (info->magneticFieldType.underlying())
53 {
54 case BDSFieldType::solenoidblock:
55 {
56 const auto& coilInfos = info->coilInfos;
57 std::vector<BDSFieldMag*> fields;
58 std::vector<G4ThreeVector> fieldOffsets;
59 for (const auto& ci : coilInfos)
60 {
61 fields.push_back(new BDSFieldMagSolenoidBlock(ci.current,
62 true,
63 ci.innerRadius,
64 ci.radialThickness,
65 ci.fullLengthZ,
66 ci.onAxisTolerance,
67 ci.nSheets));
68 fieldOffsets.emplace_back(0,0,ci.offsetZ);
69 }
70 coilField = new BDSFieldMagVectorSum(fields, fieldOffsets);
71 break;
72 }
73 case BDSFieldType::solenoidsheet:
74 {
75 const auto& coilInfos = info->coilInfos;
76 std::vector<BDSFieldMag*> fields;
77 std::vector<G4ThreeVector> fieldOffsets;
78 for (const auto& ci : coilInfos)
79 {
80 fields.push_back(new BDSFieldMagSolenoidSheet(ci.current,
81 true,
82 ci.innerRadius + 0.5*ci.radialThickness,
83 ci.fullLengthZ,
84 ci.onAxisTolerance));
85 fieldOffsets.emplace_back(0,0,ci.offsetZ);
86 }
87 coilField = new BDSFieldMagVectorSum(fields, fieldOffsets);
88 break;
89 }
90 case BDSFieldType::solenoidloop:
91 {
92 const auto& coilInfos = info->coilInfos;
93 std::vector<BDSFieldMag*> fields;
94 std::vector<G4ThreeVector> fieldOffsets;
95 for (const auto& ci : coilInfos)
96 {
97 fields.push_back(new BDSFieldMagSolenoidLoop(ci.current,
98 true,
99 ci.innerRadius + 0.5*ci.radialThickness));
100 fieldOffsets.emplace_back(0,0,ci.offsetZ);
101 }
102 coilField = new BDSFieldMagVectorSum(fields, fieldOffsets);
103 break;
104 }
105 default:
106 {
107 G4String msg = "\"" + info->magneticFieldType.ToString();
108 msg += "\" is not a valid field model for a muon cooler B field";
109 throw BDSException(__METHOD_NAME__, msg);
110 break;
111 }
112 }
113}
114
115void BDSFieldEMMuonCooler::BuildDipoles(const BDSFieldInfoExtraMuonCooler* info)
116{
117 switch (info->dipoleFieldType.underlying())
118 {
119 case BDSFieldType::dipole:
120 {
121 const auto& dipoleInfos = info->dipoleInfos;
122 std::vector<BDSFieldMag*> fields;
123 std::vector<G4ThreeVector> fieldOffsets;
124 for (const auto& di : dipoleInfos)
125 {
126 fields.push_back(new BDSFieldMagDipoleHardEdgeMuonCooler(di.fieldStrength,
127 di.apertureRadius,
128 di.fullLengthZ));
129 fieldOffsets.emplace_back(0,0,di.offsetZ);
130 }
131 dipoleField = new BDSFieldMagVectorSum(fields, fieldOffsets);
132 break;
133 }
134 case BDSFieldType::dipoleenge:
135 {
136 const auto& dipoleInfos = info->dipoleInfos;
137 std::vector<BDSFieldMag*> fields;
138 std::vector<G4ThreeVector> fieldOffsets;
139 for (const auto& di : dipoleInfos)
140 {
141 fields.push_back(new BDSFieldMagDipoleEnge(di.fieldStrength,
142 di.apertureRadius,
143 di.fullLengthZ,
144 di.engeCoefficient));
145 fieldOffsets.emplace_back(0,0,di.offsetZ);
146 }
147 dipoleField = new BDSFieldMagVectorSum(fields, fieldOffsets);
148 break;
149 }
150 default:
151 {
152 G4String msg = "\"" + info->dipoleFieldType.ToString();
153 msg += "\" is not a valid dipole field model for a muon cooler B field";
154 throw BDSException(__METHOD_NAME__, msg);
155 break;
156 }
157 }
158}
159
160void BDSFieldEMMuonCooler::BuildRF(const BDSFieldInfoExtraMuonCooler* info)
161{
162 const auto& cavityInfos = info->cavityInfos;
163 std::vector<G4ThreeVector> fieldOffsets;
165 for (const auto& ci : cavityInfos)
166 {
168 ci.peakEField,
169 ci.frequency,
170 ci.phaseOffset,
171 ci.cavityRadius,
172 0.0 // We provide a global tOffset instead
173 );
174 double lengthZ = ci.lengthZ;
175 G4ThreeVector posOffset(0.0, 0.0, ci.offsetZ);
176 double tOffset = ci.globalTimeOffset;
177 emSum->PushBackField(posOffset, tOffset, lengthZ, rfCav);
178 }
179 rfField = emSum;
180}
181
182BDSFieldEMMuonCooler::~BDSFieldEMMuonCooler()
183{
184 delete coilField;
185 delete dipoleField;
186 delete rfField;
187}
188
189std::pair<G4ThreeVector, G4ThreeVector> BDSFieldEMMuonCooler::GetField(const G4ThreeVector& position,
190 const G4double t) const
191{
192 auto result = rfField->GetField(position, t); // result is a pair like <Bfield, Efield>
193 G4ThreeVector solfieldOut = coilField->GetField(position, t);
194 G4ThreeVector dipolefieldOut = dipoleField->GetField(position, t);
195 result.first += solfieldOut;
196 result.first += dipolefieldOut;
197 return result;
198}
General exception with possible name of object and message.
virtual std::pair< G4ThreeVector, G4ThreeVector > GetField(const G4ThreeVector &position, const G4double t) const
Function to get B and E field.
Pill box cavity electromagnetic field.
A vector sum of multiple displaced EM fields.
virtual std::pair< G4ThreeVector, G4ThreeVector > GetField(const G4ThreeVector &position, const G4double t=0) const =0
necessary extra information for a muon cooler field.
BDSFieldType dipoleFieldType
Type of the dipole sub-field.
BDSFieldType magneticFieldType
Type of the magnetic sub-field.
A dipole field with Enge-type fringes. This follows the model and parameterisation described in: http...
This class represents a hard-edge dipole field. The field is calculated in cartesian coordinates.
Class that provides the magnetic field due to a square annulus of current.
Class that provides the magnetic field due to a cylinder of current.
Class that provides the magnetic field due to a cylinder of current.
A vector sum of multiple displaced magnetic fields.
virtual G4ThreeVector GetField(const G4ThreeVector &position, const G4double t=0) const =0
type underlying() const
return underlying value (can be used in switch statement)