BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSMagnetStrength.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 "BDSDebug.hh"
19#include "BDSException.hh"
20#include "BDSMagnetStrength.hh"
21
22#include "globals.hh" // geant4 globals / types
23
24#include "CLHEP/Units/SystemOfUnits.h"
25
26#include <algorithm>
27#include <iomanip>
28#include <map>
29#include <vector>
30
31const std::vector<G4String> BDSMagnetStrength::keys = {
32 "beta0", // relativistic beta for the primary particle - used in some integrators
33 "field", // constant field in G4units - magnitude of field only - use bx,by,bz to get direction
34 "efield", // electric field in G4units - magnitude of field only - use ex,ey,ez to get direction
35 "bx","by","bz", // (assumed) unit vector components for field direction
36 "ex","ey","ez", // (assumed) unit vector components for field direction
37 "e1", // entrance poleface rotation angle
38 "e2", // entrance poleface rotation angle
39 "h1", // poleface curvature for entrance face
40 "h2", // poleface curvature for exit face
41 "angle", "length", // (rad, mm)
42 "fint", // fringe field integral value for entrance face
43 "fintx", // fringe field integral value for exit face
44 "fintk2", // second fringe field integral value for entrance face
45 "fintxk2", // second fringe field integral value for exit face
46 "hgap", // fringe field vertical half-gap
47 "hkick", "vkick", // fractional horizontal and vertical dPx (w.r.t. rigidity)
48 "ks", // not in G4 units
49 "k1", "k1s",
50 "k2", "k2s",
51 "k3", "k3s",
52 "k4", "k4s",
53 "k5", "k5s",
54 "k6", "k6s",
55 "k7", "k7s",
56 "k8", "k8s",
57 "k9", "k9s",
58 "k10", "k10s",
59 "k11", "k11s",
60 "k12", "k12s",
61 "kg", // gabor lens focusing strength
62 "plasmaEfield", // magnitude of electric strength of confined Gabor lens plasma
63 "frequency", // frequency for time varying field (presumably em)
64 "phase", // phase for time varying field
65 "synchronousT0", // global T0 for the synchronous particle at the centre of the object
66 "equatorradius", // radius from axis at which field goes to 0
67 "nominalenergy", // nominal beam energy needed by some integrators
68 "scaling", // field scaling factor needed by dipolequadrupole integrator
69 "scalingOuter", // arbitrary scaling for yoke fields - kept as a separate scaling number
70 "isentrance", // bool to determine is integrator is for entrance (1) or exit (0) face
71 "kick1",
72 "kick2",
73 "kick3",
74 "kick4",
75 "rmat11",
76 "rmat12",
77 "rmat13",
78 "rmat14",
79 "rmat21",
80 "rmat22",
81 "rmat23",
82 "rmat24",
83 "rmat31",
84 "rmat32",
85 "rmat33",
86 "rmat34",
87 "rmat41",
88 "rmat42",
89 "rmat43",
90 "rmat44"
91};
92
93const std::map<G4String, BDSMagnetStrength::unitsFactors> BDSMagnetStrength::unitsFactorsMap = {
94 {"beta0" , {"", 1.0}},
95 {"field" , {"T", CLHEP::tesla}},
96 {"efield" , {"", CLHEP::megavolt}},
97 {"bx" , {"", 1.0}},
98 {"by" , {"", 1.0}},
99 {"bz" , {"", 1.0}},
100 {"ex" , {"", 1.0}},
101 {"ey" , {"", 1.0}},
102 {"ez" , {"", 1.0}},
103 {"e1" , {"rad", CLHEP::rad}},
104 {"e2" , {"rad", CLHEP::rad}},
105 {"h1" , {"rad", CLHEP::rad}},
106 {"h2" , {"rad", CLHEP::rad}},
107 {"angle" , {"rad", CLHEP::rad}},
108 {"length" , {"m", CLHEP::m}},
109 {"fint" , {"", 1.0}},
110 {"fintx" , {"", 1.0}},
111 {"fintk2" , {"", 1.0}},
112 {"fintxk2" , {"", 1.0}},
113 {"hgap" , {"m", CLHEP::m}},
114 {"hkick" , {"", 1.0}},
115 {"vkick" , {"", 1.0}},
116 {"ks" , {"", 1.0}},
117 {"k1" , {"", 1.0}},
118 {"k2" , {"", 1.0}},
119 {"k3" , {"", 1.0}},
120 {"k4" , {"", 1.0}},
121 {"k5" , {"", 1.0}},
122 {"k6" , {"", 1.0}},
123 {"k7" , {"", 1.0}},
124 {"k8" , {"", 1.0}},
125 {"k9" , {"", 1.0}},
126 {"k10" , {"", 1.0}},
127 {"k11" , {"", 1.0}},
128 {"k12" , {"", 1.0}},
129 {"k1s" , {"", 1.0}},
130 {"k2s" , {"", 1.0}},
131 {"k3s" , {"", 1.0}},
132 {"k4s" , {"", 1.0}},
133 {"k5s" , {"", 1.0}},
134 {"k6s" , {"", 1.0}},
135 {"k7s" , {"", 1.0}},
136 {"k8s" , {"", 1.0}},
137 {"k9s" , {"", 1.0}},
138 {"k10s" , {"", 1.0}},
139 {"k11s" , {"", 1.0}},
140 {"k12s" , {"", 1.0}},
141 {"frequency" , {"", CLHEP::megahertz}},
142 {"phase" , {"rad", CLHEP::rad}},
143 {"synchronousT0" , {"s", CLHEP::s}},
144 {"equatorradius" , {"m", CLHEP::m}},
145 {"kg" , {"", 1.0}},
146 {"plasmaEfield" , {"", 1.0}},
147 {"nominalenergy" , {"GeV", CLHEP::GeV}},
148 {"scaling" , {"", 1.0}},
149 {"scalingOuter" , {"", 1.0}},
150 {"isentrance" , {"", 1.0}},
151 {"kick1" , {"", 1.0}},
152 {"kick2" , {"", 1.0}},
153 {"kick3" , {"", 1.0}},
154 {"kick4" , {"", 1.0}},
155 {"rmat11" , {"", 1.0}},
156 {"rmat12" , {"", 1.0}},
157 {"rmat13" , {"", 1.0}},
158 {"rmat14" , {"", 1.0}},
159 {"rmat21" , {"", 1.0}},
160 {"rmat22" , {"", 1.0}},
161 {"rmat23" , {"", 1.0}},
162 {"rmat24" , {"", 1.0}},
163 {"rmat31" , {"", 1.0}},
164 {"rmat32" , {"", 1.0}},
165 {"rmat33" , {"", 1.0}},
166 {"rmat34" , {"", 1.0}},
167 {"rmat41" , {"", 1.0}},
168 {"rmat42" , {"", 1.0}},
169 {"rmat43" , {"", 1.0}},
170 {"rmat44" , {"", 1.0}},
171 {"coilRadialThickness", {"m", CLHEP::m}}
172};
173
174const std::vector<G4String> BDSMagnetStrength::normalComponentKeys = {
175 "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9", "k10", "k11", "k12"};
176
177const std::vector<G4String> BDSMagnetStrength::skewComponentKeys = {
178 "k1s", "k2s", "k3s", "k4s", "k5s", "k6s", "k7s", "k8s", "k9s", "k10s", "k11s", "k12s"};
179
180const G4double BDSMagnetStrength::zero = 0.0;
181G4double BDSMagnetStrength::variable = 0.0;
182
183BDSMagnetStrength::BDSMagnetStrength(const std::map<G4String, G4double>& sts)
184{
185 for (const auto& keyValue : sts)
186 {
187 if (ValidKey(keyValue.first))
188 {(*this)[keyValue.first] = keyValue.second;}
189 }
190}
191
192std::ostream& operator<<(std::ostream& out, BDSMagnetStrength const &st)
193{
194 for (const auto& key : BDSMagnetStrength::keys)
195 {out << key << ": " << st.GetValue(key) << ", ";}
196 return out;
197}
198
200 const G4int precision) const
201{
202 for (auto& key : keys)
203 {out << " " << std::setw(precision) << GetValue(key) / unitsFactorsMap.at(key).factor;}
204 return out;
205}
206
207G4String BDSMagnetStrength::UnitName(const G4String& key)
208{
209 if (ValidKey(key))
210 {return unitsFactorsMap.at(key).unit;}
211 else
212 {throw BDSException(__METHOD_NAME__, "Invalid key \"" + key + "\"");}
213}
214
215G4double BDSMagnetStrength::Unit(const G4String& key)
216{
217 if (ValidKey(key))
218 {return unitsFactorsMap.at(key).factor;}
219 else
220 {throw BDSException(__METHOD_NAME__, "Invalid key \"" + key + "\"");}
221}
222
223G4double& BDSMagnetStrength::operator[](const G4String& key)
224{
225 if (ValidKey(key))
226 {
227 // check if this key is initialised (non const version of this operator)
228 // if it's not, initialise it so assignment will work
229 auto it = strengths.find(key);
230 if (it != strengths.end())
231 {return it->second;}
232 else
233 {
234 strengths[key] = 0.0;
235 return strengths[key];
236 }
237 }
238 else
239 {throw BDSException(__METHOD_NAME__, "Invalid key \"" + key + "\"");}
240}
241
242const G4double& BDSMagnetStrength::operator[](const G4String& key) const
243{
244 if (ValidKey(key))
245 {return GetValue(key);}
246 else
247 {throw BDSException(__METHOD_NAME__, "Invalid key \"" + key + "\"");}
248}
249
250std::vector<G4double> BDSMagnetStrength::NormalComponents() const
251{
252 std::vector<G4double> result;
253 result.reserve(normalComponentKeys.size());
254 for (const auto& key : normalComponentKeys)
255 {result.push_back(GetValue(key));}
256 return result;
257}
258
259std::vector<G4double> BDSMagnetStrength::SkewComponents() const
260{
261 std::vector<G4double> result;
262 result.reserve(skewComponentKeys.size());
263 for (const auto& key : skewComponentKeys)
264 {result.push_back(GetValue(key));}
265 return result;
266}
267
268G4bool BDSMagnetStrength::ValidKey(const G4String& key)
269{
270 if (std::find(keys.begin(), keys.end(), key) != keys.end())
271 {return true;}
272 else
273 {return false;}
274}
275
276const G4double& BDSMagnetStrength::GetValue(const G4String& key) const
277{
278 auto it = strengths.find(key);
279 if (it != strengths.end())
280 {return it->second;}
281 else
282 {return zero;}
283}
284
285G4bool BDSMagnetStrength::KeyHasBeenSet(const G4String& key) const
286{
287 return strengths.find(key) != strengths.end();
288}
General exception with possible name of object and message.
Efficient storage of magnet strengths.
std::vector< G4double > NormalComponents() const
Accessor for all normal components - k1 - k12.
std::vector< G4double > SkewComponents() const
Accessor for all skew components - k1 - k12.
G4bool KeyHasBeenSet(const G4String &key) const
Whether a key has been set.
std::ostream & WriteValuesInSIUnitsForSuvey(std::ostream &out, const G4int precision=14) const
static G4double variable
Dummy variable that can be overwritten.
static G4bool ValidKey(const G4String &key)
Whether or not the supplied key is a valid magnet strength parameter.
const G4double & GetValue(const G4String &key) const
G4double & operator[](const G4String &key)
Accessors with array / map [] operator.
static const std::vector< G4String > keys
Vector of the allowed strength parameters.
BDSMagnetStrength()
Default constructor does nothing as class will return 0 for uninitialised keys.
static const G4double zero
Keep a single copy of 0.0 as it needs to be returned as a reference not a value.
static const std::vector< G4String > skewComponentKeys
Vector of the normal component strength parameters.
static const std::map< G4String, unitsFactors > unitsFactorsMap
Map of each unit name and numerical factor to each key.
static G4String UnitName(const G4String &key)
Access a unit name for a given key.
static G4double Unit(const G4String &key)
Access a unit factor for a given key.
static const std::vector< G4String > normalComponentKeys
Vector of the normal component strength parameters.