BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSMagnetStrength.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 "BDSMagnetStrength.hh"
22
23#include "globals.hh" // geant4 globals / types
24
25#include "CLHEP/Units/SystemOfUnits.h"
26
27#include <algorithm>
28#include <iomanip>
29#include <map>
30#include <vector>
31
32const std::vector<G4String> BDSMagnetStrength::keys = {
33 "beta0", // relativistic beta for the primary particle - used in some integrators
34 "field", // constant field in G4units - magnitude of field only - use bx,by,bz to get direction
35 "efield", // electric field in G4units - magnitude of field only
36 "bx","by","bz", // (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 "frequency", // frequency for time varying field (presumably em)
62 "phase", // phase for time varying field
63 "equatorradius", // radius from axis at which field goes to 0
64 "nominalenergy", // nominal beam energy needed by some integrators
65 "scaling", // field scaling factor needed by dipolequadrupole integrator
66 "scalingOuter", // arbitrary scaling for yoke fields - kept as a separate scaling number
67 "isentrance", // bool to determine is integrator is for entrance (1) or exit (0) face
68 "kick1",
69 "kick2",
70 "kick3",
71 "kick4",
72 "rmat11",
73 "rmat12",
74 "rmat13",
75 "rmat14",
76 "rmat21",
77 "rmat22",
78 "rmat23",
79 "rmat24",
80 "rmat31",
81 "rmat32",
82 "rmat33",
83 "rmat34",
84 "rmat41",
85 "rmat42",
86 "rmat43",
87 "rmat44"
88};
89
90const std::map<G4String, BDSMagnetStrength::unitsFactors> BDSMagnetStrength::unitsFactorsMap = {
91 {"beta0" , {"", 1.0}},
92 {"field" , {"T", CLHEP::tesla}},
93 {"efield" , {"", CLHEP::megavolt}},
94 {"bx" , {"", 1.0}},
95 {"by" , {"", 1.0}},
96 {"bz" , {"", 1.0}},
97 {"e1" , {"rad", CLHEP::rad}},
98 {"e2" , {"rad", CLHEP::rad}},
99 {"h1" , {"rad", CLHEP::rad}},
100 {"h2" , {"rad", CLHEP::rad}},
101 {"angle" , {"rad", CLHEP::rad}},
102 {"length" , {"m", CLHEP::m}},
103 {"fint" , {"", 1.0}},
104 {"fintx" , {"", 1.0}},
105 {"fintk2" , {"", 1.0}},
106 {"fintxk2" , {"", 1.0}},
107 {"hgap" , {"m", CLHEP::m}},
108 {"hkick" , {"", 1.0}},
109 {"vkick" , {"", 1.0}},
110 {"ks" , {"", 1.0}},
111 {"k1" , {"", 1.0}},
112 {"k2" , {"", 1.0}},
113 {"k3" , {"", 1.0}},
114 {"k4" , {"", 1.0}},
115 {"k5" , {"", 1.0}},
116 {"k6" , {"", 1.0}},
117 {"k7" , {"", 1.0}},
118 {"k8" , {"", 1.0}},
119 {"k9" , {"", 1.0}},
120 {"k10" , {"", 1.0}},
121 {"k11" , {"", 1.0}},
122 {"k12" , {"", 1.0}},
123 {"k1s" , {"", 1.0}},
124 {"k2s" , {"", 1.0}},
125 {"k3s" , {"", 1.0}},
126 {"k4s" , {"", 1.0}},
127 {"k5s" , {"", 1.0}},
128 {"k6s" , {"", 1.0}},
129 {"k7s" , {"", 1.0}},
130 {"k8s" , {"", 1.0}},
131 {"k9s" , {"", 1.0}},
132 {"k10s" , {"", 1.0}},
133 {"k11s" , {"", 1.0}},
134 {"k12s" , {"", 1.0}},
135 {"frequency" , {"", CLHEP::megahertz}},
136 {"phase" , {"rad", CLHEP::rad}},
137 {"equatorradius" , {"m", CLHEP::m}},
138 {"nominalenergy" , {"GeV", CLHEP::GeV}},
139 {"scaling" , {"", 1.0}},
140 {"scalingOuter" , {"", 1.0}},
141 {"isentrance" , {"", 1.0}},
142 {"kick1" , {"", 1.0}},
143 {"kick2" , {"", 1.0}},
144 {"kick3" , {"", 1.0}},
145 {"kick4" , {"", 1.0}},
146 {"rmat11" , {"", 1.0}},
147 {"rmat12" , {"", 1.0}},
148 {"rmat13" , {"", 1.0}},
149 {"rmat14" , {"", 1.0}},
150 {"rmat21" , {"", 1.0}},
151 {"rmat22" , {"", 1.0}},
152 {"rmat23" , {"", 1.0}},
153 {"rmat24" , {"", 1.0}},
154 {"rmat31" , {"", 1.0}},
155 {"rmat32" , {"", 1.0}},
156 {"rmat33" , {"", 1.0}},
157 {"rmat34" , {"", 1.0}},
158 {"rmat41" , {"", 1.0}},
159 {"rmat42" , {"", 1.0}},
160 {"rmat43" , {"", 1.0}},
161 {"rmat44" , {"", 1.0}}
162};
163
164const std::vector<G4String> BDSMagnetStrength::normalComponentKeys = {
165 "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9", "k10", "k11", "k12"};
166
167const std::vector<G4String> BDSMagnetStrength::skewComponentKeys = {
168 "k1s", "k2s", "k3s", "k4s", "k5s", "k6s", "k7s", "k8s", "k9s", "k10s", "k11s", "k12s"};
169
170const G4double BDSMagnetStrength::zero = 0.0;
171G4double BDSMagnetStrength::variable = 0.0;
172
173BDSMagnetStrength::BDSMagnetStrength(const std::map<G4String, G4double>& sts)
174{
175 for (const auto& keyValue : sts)
176 {
177 if (ValidKey(keyValue.first))
178 {(*this)[keyValue.first] = keyValue.second;}
179 }
180}
181
182std::ostream& operator<<(std::ostream& out, BDSMagnetStrength const &st)
183{
184 for (const auto& key : BDSMagnetStrength::keys)
185 {out << key << ": " << st.GetValue(key) << ", ";}
186 return out;
187}
188
190 const G4int precision) const
191{
192 for (auto& key : keys)
193 {out << " " << std::setw(precision) << GetValue(key) / unitsFactorsMap.at(key).factor;}
194 return out;
195}
196
197G4String BDSMagnetStrength::UnitName(const G4String& key)
198{
199 if (ValidKey(key))
200 {return unitsFactorsMap.at(key).unit;}
201 else
202 {throw BDSException(__METHOD_NAME__, "Invalid key \"" + key + "\"");}
203}
204
205G4double BDSMagnetStrength::Unit(const G4String& key)
206{
207 if (ValidKey(key))
208 {return unitsFactorsMap.at(key).factor;}
209 else
210 {throw BDSException(__METHOD_NAME__, "Invalid key \"" + key + "\"");}
211}
212
213G4double& BDSMagnetStrength::operator[](const G4String& key)
214{
215 if (ValidKey(key))
216 {
217 // check if this key is initialised (non const version of this operator)
218 // if it's not, initialise it so assignment will work
219 auto it = strengths.find(key);
220 if (it != strengths.end())
221 {return it->second;}
222 else
223 {
224 strengths[key] = 0.0;
225 return strengths[key];
226 }
227 }
228 else
229 {throw BDSException(__METHOD_NAME__, "Invalid key \"" + key + "\"");}
230}
231
232const G4double& BDSMagnetStrength::operator[](const G4String& key) const
233{
234 if (ValidKey(key))
235 {return GetValue(key);}
236 else
237 {throw BDSException(__METHOD_NAME__, "Invalid key \"" + key + "\"");}
238}
239
240std::vector<G4double> BDSMagnetStrength::NormalComponents() const
241{
242 std::vector<G4double> result;
243 result.reserve(normalComponentKeys.size());
244 for (const auto& key : normalComponentKeys)
245 {result.push_back(GetValue(key));}
246 return result;
247}
248
249std::vector<G4double> BDSMagnetStrength::SkewComponents() const
250{
251 std::vector<G4double> result;
252 result.reserve(skewComponentKeys.size());
253 for (const auto& key : skewComponentKeys)
254 {result.push_back(GetValue(key));}
255 return result;
256}
257
258G4bool BDSMagnetStrength::ValidKey(const G4String& key)
259{
260 if (std::find(keys.begin(), keys.end(), key) != keys.end())
261 {return true;}
262 else
263 {return false;}
264}
265
266const G4double& BDSMagnetStrength::GetValue(const G4String& key) const
267{
268 auto it = strengths.find(key);
269 if (it != strengths.end())
270 {return it->second;}
271 else
272 {return zero;}
273}
274
275G4bool BDSMagnetStrength::KeyHasBeenSet(const G4String& key) const
276{
277 return strengths.find(key) != strengths.end();
278}
General exception with possible name of object and message.
Definition: BDSException.hh:35
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.