BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSFieldInfo.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2024.
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 "BDSArrayReflectionType.hh"
20#include "BDSFieldInfo.hh"
21#include "BDSFieldInfoExtra.hh"
22#include "BDSFieldType.hh"
23#include "BDSIntegratorType.hh"
24#include "BDSInterpolatorType.hh"
25#include "BDSMagnetStrength.hh"
26#include "BDSModulatorInfo.hh"
27#include "BDSUtilities.hh"
28
29#include "globals.hh" // geant4 types / globals
30#include "G4RotationMatrix.hh"
31#include "G4ThreeVector.hh"
32#include "G4Track.hh"
33#include "G4Transform3D.hh"
34#include "G4UserLimits.hh"
35
36#include <algorithm>
37#include <ostream>
38
39G4UserLimits* BDSFieldInfo::defaultUL = nullptr;
40
42 fieldType(BDSFieldType::none),
43 brho(0),
44 integratorType(BDSIntegratorType::none),
45 magnetStrength(nullptr),
46 provideGlobalTransform(false),
47 transform(nullptr),
48 magneticFieldFilePath(""),
49 magneticFieldFormat(BDSFieldFormat::none),
50 magneticInterpolatorType(BDSInterpolatorType::nearest3d),
51 magneticArrayReflectionTypeSet(BDSArrayReflectionTypeSet()),
52 electricFieldFilePath(""),
53 electricFieldFormat(BDSFieldFormat::none),
54 electricInterpolatorType(BDSInterpolatorType::nearest3d),
55 electricArrayReflectionTypeSet(BDSArrayReflectionTypeSet()),
56 cacheTransforms(true),
57 eScaling(1.0),
58 bScaling(1.0),
59 timeOffset(0),
60 autoScale(false),
61 stepLimit(nullptr),
62 poleTipRadius(1),
63 beamPipeRadius(0),
64 chordStepMinimum(-1),
65 tilt(0),
66 secondFieldOnLeft(false),
67 magneticSubFieldName(""),
68 electricSubFieldName(""),
69 usePlacementWorldTransform(false),
70 modulatorInfo(nullptr),
71 ignoreUpdateOfMaximumStepSize(false),
72 isThin(false),
73 transformBeamline(nullptr),
74 extraInfo(nullptr),
75 nameOfParserDefinition("")
76{;}
77
79 G4double brhoIn,
80 BDSIntegratorType integratorTypeIn,
81 BDSMagnetStrength* magnetStrengthIn,
82 G4bool provideGlobalTransformIn,
83 const G4Transform3D& transformIn,
84 const G4String& magneticFieldFilePathIn,
85 BDSFieldFormat magneticFieldFormatIn,
86 BDSInterpolatorType magneticInterpolatorTypeIn,
87 const G4String& electricFieldFilePathIn,
88 BDSFieldFormat electricFieldFormatIn,
89 BDSInterpolatorType electricInterpolatorTypeIn,
90 G4bool cacheTransformsIn,
91 G4double eScalingIn,
92 G4double bScalingIn,
93 G4double timeOffsetIn,
94 G4bool autoScaleIn,
95 G4UserLimits* stepLimitIn,
96 G4double poleTipRadiusIn,
97 G4double beamPipeRadiusIn,
98 G4bool leftIn,
99 const G4String& magneticSubFieldNameIn,
100 const G4String& electricSubFieldNameIn):
101 fieldType(fieldTypeIn),
102 brho(brhoIn),
103 integratorType(integratorTypeIn),
104 magnetStrength(magnetStrengthIn),
105 provideGlobalTransform(provideGlobalTransformIn),
106 transform(nullptr),
107 magneticFieldFilePath(magneticFieldFilePathIn),
108 magneticFieldFormat(magneticFieldFormatIn),
109 magneticInterpolatorType(magneticInterpolatorTypeIn),
110 magneticArrayReflectionTypeSet(BDSArrayReflectionTypeSet()),
111 electricFieldFilePath(electricFieldFilePathIn),
112 electricFieldFormat(electricFieldFormatIn),
113 electricInterpolatorType(electricInterpolatorTypeIn),
114 electricArrayReflectionTypeSet(BDSArrayReflectionTypeSet()),
115 cacheTransforms(cacheTransformsIn),
116 eScaling(eScalingIn),
117 bScaling(bScalingIn),
118 timeOffset(timeOffsetIn),
119 autoScale(autoScaleIn),
120 stepLimit(stepLimitIn),
121 poleTipRadius(poleTipRadiusIn),
122 beamPipeRadius(beamPipeRadiusIn),
123 chordStepMinimum(-1),
124 secondFieldOnLeft(leftIn),
125 magneticSubFieldName(magneticSubFieldNameIn),
126 electricSubFieldName(electricSubFieldNameIn),
127 usePlacementWorldTransform(false),
128 modulatorInfo(nullptr),
129 ignoreUpdateOfMaximumStepSize(false),
130 isThin(false),
131 transformBeamline(nullptr),
132 extraInfo(nullptr),
133 nameOfParserDefinition("")
134{
135 if (transformIn != G4Transform3D::Identity)
136 {transform = new G4Transform3D(transformIn);}
137
138 // back calculate tilt angle from field transform
139 G4ThreeVector unitY(0,1,0);
140 G4ThreeVector unitYR = unitY.transform(transformIn.getRotation());
141 tilt = -(CLHEP::halfpi - unitYR.getPhi()); // halfpi offset for which axis we choose by convention
142}
143
144BDSFieldInfo::~BDSFieldInfo()
145{
146 delete magnetStrength;
147 delete transform;
148 delete stepLimit;
149 delete transformBeamline;
150 delete extraInfo;
151}
152
154 fieldType(other.fieldType),
155 brho(other.brho),
156 integratorType(other.integratorType),
157 provideGlobalTransform(other.provideGlobalTransform),
158 transform(nullptr),
159 magneticFieldFilePath(other.magneticFieldFilePath),
160 magneticFieldFormat(other.magneticFieldFormat),
161 magneticInterpolatorType(other.magneticInterpolatorType),
162 magneticArrayReflectionTypeSet(other.magneticArrayReflectionTypeSet),
163 electricFieldFilePath(other.electricFieldFilePath),
164 electricFieldFormat(other.electricFieldFormat),
165 electricInterpolatorType(other.electricInterpolatorType),
166 electricArrayReflectionTypeSet(other.electricArrayReflectionTypeSet),
167 cacheTransforms(other.cacheTransforms),
168 eScaling(other.eScaling),
169 bScaling(other.bScaling),
170 timeOffset(other.timeOffset),
171 autoScale(other.autoScale),
172 poleTipRadius(other.poleTipRadius),
173 beamPipeRadius(other.beamPipeRadius),
174 chordStepMinimum(other.chordStepMinimum),
175 tilt(other.tilt),
176 secondFieldOnLeft(other.secondFieldOnLeft),
177 magneticSubFieldName(other.magneticSubFieldName),
178 electricSubFieldName(other.electricSubFieldName),
179 usePlacementWorldTransform(other.usePlacementWorldTransform),
180 modulatorInfo(other.modulatorInfo),
181 ignoreUpdateOfMaximumStepSize(other.ignoreUpdateOfMaximumStepSize),
182 isThin(other.isThin),
183 transformBeamline(nullptr),
184 extraInfo(nullptr),
185 nameOfParserDefinition(other.nameOfParserDefinition)
186{
187 if (other.transform)
188 {transform = new G4Transform3D(*other.transform);}
189
190 if (other.magnetStrength)
191 {magnetStrength = new BDSMagnetStrength(*other.magnetStrength);}
192 else
193 {magnetStrength = nullptr;} // also nullptr
194
195 if (other.stepLimit)
196 {stepLimit = new G4UserLimits(*other.stepLimit);}
197 else
198 {stepLimit = nullptr;}
199
200 if (other.transformBeamline)
201 {transformBeamline = new G4Transform3D(*other.transformBeamline);}
202
203 if (other.extraInfo)
204 {extraInfo = other.extraInfo->Clone();}
205}
206
207void BDSFieldInfo::SetUserLimits(G4UserLimits* userLimitsIn)
208{
209 if (stepLimit != defaultUL)
210 {delete stepLimit;} // shouldn't delete global default step limit!
211 stepLimit = userLimitsIn;
212}
213
215 G4bool warn) const
216{
218 {return;}
219
220 if (stepLimit && (stepLimit != defaultUL))
221 {
222 G4UserLimits* old = stepLimit;
223 stepLimit = BDS::CreateUserLimits(stepLimit, maximumStepSize, 1.0);
224 if (stepLimit == old)
225 {warn = false;} // no change and warning would print out wrong number
226 if ((stepLimit != old) && (old != defaultUL))
227 {delete old;}
228 }
229 else
230 {stepLimit = new G4UserLimits(maximumStepSize);}
231
232 if (warn)
233 {
234 G4cout << "Reducing maximum step size of field definition \"" << nameOfParserDefinition
235 << "\" to " << maximumStepSize << " mm " << G4endl;
236 }
237}
238
239std::ostream& operator<< (std::ostream& out, BDSFieldInfo const& info)
240{
241 out << "Parser definition name: \"" << info.nameOfParserDefinition << "\"" << G4endl;
242 out << "Field type: " << info.fieldType << G4endl;
243 out << "Rigidity: " << info.brho << G4endl;
244 out << "Integrator: " << info.integratorType << G4endl;
245 out << "Global transform? " << info.provideGlobalTransform << G4endl;
246 out << "B map file: " << info.magneticFieldFilePath << G4endl;
247 out << "B map file format: " << info.magneticFieldFormat << G4endl;
248 out << "B interpolator " << info.magneticInterpolatorType << G4endl;
249 out << "B array reflection: " << info.magneticArrayReflectionTypeSet << G4endl;
250 out << "E map file: " << info.electricFieldFilePath << G4endl;
251 out << "E map file format: " << info.electricFieldFormat << G4endl;
252 out << "E interpolator " << info.electricInterpolatorType << G4endl;
253 out << "E array reflection: " << info.electricArrayReflectionTypeSet << G4endl;
254 out << "Transform caching: " << info.cacheTransforms << G4endl;
255 out << "E Scaling: " << info.eScaling << G4endl;
256 out << "B Scaling: " << info.bScaling << G4endl;
257 out << "t offset " << info.timeOffset << G4endl;
258 out << "Auto scale " << info.autoScale << G4endl;
259 out << "Pole tip radius: " << info.poleTipRadius << G4endl;
260 out << "Beam pipe radius: " << info.beamPipeRadius << G4endl;
261 out << "Chord Step Min: " << info.chordStepMinimum << G4endl;
262 out << "Tilt: " << info.tilt << G4endl;
263 out << "Second field on left " << info.secondFieldOnLeft << G4endl;
264 out << "Magnetic sub field " << info.magneticSubFieldName << G4endl;
265 out << "Electric sub field " << info.electricSubFieldName << G4endl;
266 if (info.modulatorInfo)
267 {out << "Modulator " << *(info.modulatorInfo) << G4endl;}
268 out << "Use placement world transform " << info.usePlacementWorldTransform << G4endl;
269 out << "Ignore update of maximum step size " << info.ignoreUpdateOfMaximumStepSize << G4endl;
270 if (info.magnetStrength)
271 {out << "Magnet strength: " << *(info.magnetStrength) << G4endl;}
272 if (info.stepLimit)
273 {
274 G4Track t = G4Track(); // dummy track
275 G4double maxStep = info.stepLimit->GetMaxAllowedStep(t);
276 out << "Step limit: " << maxStep << G4endl;
277 }
278 out << "extra info " << (info.extraInfo ? "present" : "not present") << G4endl;
279 return out;
280}
281
282void BDSFieldInfo::Translate(const G4ThreeVector& translationIn)
283{
284 if (!transform)
285 {transform = new G4Transform3D();}
286 G4RotationMatrix rm = transform->getRotation();
287 G4ThreeVector translation = transform->getTranslation();
288 translation += translationIn;
289 G4Transform3D* newTransform = new G4Transform3D(rm, translation);
290 delete transform;
291 transform = newTransform;
292}
293
294G4double BDSFieldInfo::SynchronousT() const
295{
296 if (!magnetStrength)
297 {return 0;}
298 else
299 {return (*magnetStrength)["synchronousT0"];}
300}
301
302G4Transform3D BDSFieldInfo::Transform() const
303{
304 return transform ? *transform : G4Transform3D::Identity;
305}
306
308{
309 return transformBeamline ? *transformBeamline : G4Transform3D::Identity;
310}
311
313{
314 return Transform() * TransformBeamline();
315}
316
317void BDSFieldInfo::SetTransform(const G4Transform3D& transformIn)
318{
319 delete transform;
320 transform = new G4Transform3D(transformIn);
321}
322
323void BDSFieldInfo::SetTransformBeamline(const G4Transform3D& transformIn)
324{
325 delete transformBeamline;
326 transformBeamline = new G4Transform3D(transformIn);
327}
328
330{
331 isThin = true;
332}
virtual BDSFieldInfoExtra * Clone() const =0
Derived class must implement for copying.
All info required to build complete field of any type.
G4double beamPipeRadius
Optional radius of beam pipe.
void UpdateUserLimitsLengthMaximumStepSize(G4double maximumStepSize, G4bool warn=false) const
static G4UserLimits * defaultUL
Cache of default user limits.
G4Transform3D * transformBeamline
Transform from curvilinear frame to this field - ie beam line bit only.
G4Transform3D TransformComplete() const
Compound transform of field + beam line transform.
void SetTransformBeamline(const G4Transform3D &transformIn)
Set the beam line transform.
G4bool ignoreUpdateOfMaximumStepSize
To be used when enforcing a larger maximum step size value.
G4double poleTipRadius
Radius at which point the field will be scaled to.
G4double tilt
Cache of tilt of field.
void SetTransform(const G4Transform3D &transformIn)
Set the field definition transform.
G4Transform3D Transform() const
Transform for the field definition only.
G4bool secondFieldOnLeft
Flag for case of two-beam field - if not left, it's right.
void SetFieldAsThin()
Set thin to allow geant tracking error controls to be set seperately for thin elements.
void Translate(const G4ThreeVector &translationIn)
G4Transform3D TransformBeamline() const
Transform from the curvilinear coordinates to the beam line component.
void SetUserLimits(G4UserLimits *userLimitsIn)
Delete and replace the user limits which this class owns (only if not default ul).
G4Transform3D * transform
Transform w.r.t. solid field will be attached to.
BDSFieldInfo()
Default constructor for zero field effectively.
Efficient storage of magnet strengths.
G4UserLimits * CreateUserLimits(G4UserLimits *defaultUL, G4double length, G4double fraction=1.6)