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) 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 "BDSArrayReflectionType.hh"
19#include "BDSFieldInfo.hh"
20#include "BDSFieldInfoExtra.hh"
21#include "BDSFieldType.hh"
22#include "BDSIntegratorType.hh"
23#include "BDSInterpolatorType.hh"
24#include "BDSMagnetStrength.hh"
25#include "BDSModulatorInfo.hh"
26#include "BDSUtilities.hh"
27
28#include "globals.hh" // geant4 types / globals
29#include "G4RotationMatrix.hh"
30#include "G4ThreeVector.hh"
31#include "G4Track.hh"
32#include "G4Transform3D.hh"
33#include "G4UserLimits.hh"
34
35#include <algorithm>
36#include <ostream>
37
38G4UserLimits* BDSFieldInfo::defaultUL = nullptr;
39
41 fieldType(BDSFieldType::none),
42 brho(0),
43 integratorType(BDSIntegratorType::none),
44 magnetStrength(nullptr),
45 provideGlobalTransform(false),
46 transform(nullptr),
47 magneticFieldFilePath(""),
48 magneticFieldFormat(BDSFieldFormat::none),
49 magneticInterpolatorType(BDSInterpolatorType::nearest3d),
50 magneticArrayReflectionTypeSet(BDSArrayReflectionTypeSet()),
51 electricFieldFilePath(""),
52 electricFieldFormat(BDSFieldFormat::none),
53 electricInterpolatorType(BDSInterpolatorType::nearest3d),
54 electricArrayReflectionTypeSet(BDSArrayReflectionTypeSet()),
55 cacheTransforms(true),
56 eScaling(1.0),
57 bScaling(1.0),
58 timeOffset(0),
59 autoScale(false),
60 stepLimit(nullptr),
61 poleTipRadius(1),
62 beamPipeRadius(0),
63 chordStepMinimum(-1),
64 tilt(0),
65 secondFieldOnLeft(false),
66 magneticSubFieldName(""),
67 electricSubFieldName(""),
68 usePlacementWorldTransform(false),
69 modulatorInfo(nullptr),
70 ignoreUpdateOfMaximumStepSize(false),
71 isThin(false),
72 transformBeamline(nullptr),
73 extraInfo(nullptr),
74 nameOfParserDefinition("")
75{;}
76
78 G4double brhoIn,
79 BDSIntegratorType integratorTypeIn,
80 BDSMagnetStrength* magnetStrengthIn,
81 G4bool provideGlobalTransformIn,
82 const G4Transform3D& transformIn,
83 const G4String& magneticFieldFilePathIn,
84 BDSFieldFormat magneticFieldFormatIn,
85 BDSInterpolatorType magneticInterpolatorTypeIn,
86 const G4String& electricFieldFilePathIn,
87 BDSFieldFormat electricFieldFormatIn,
88 BDSInterpolatorType electricInterpolatorTypeIn,
89 G4bool cacheTransformsIn,
90 G4double eScalingIn,
91 G4double bScalingIn,
92 G4double timeOffsetIn,
93 G4bool autoScaleIn,
94 G4UserLimits* stepLimitIn,
95 G4double poleTipRadiusIn,
96 G4double beamPipeRadiusIn,
97 G4bool leftIn,
98 const G4String& magneticSubFieldNameIn,
99 const G4String& electricSubFieldNameIn):
100 fieldType(fieldTypeIn),
101 brho(brhoIn),
102 integratorType(integratorTypeIn),
103 magnetStrength(magnetStrengthIn),
104 provideGlobalTransform(provideGlobalTransformIn),
105 transform(nullptr),
106 magneticFieldFilePath(magneticFieldFilePathIn),
107 magneticFieldFormat(magneticFieldFormatIn),
108 magneticInterpolatorType(magneticInterpolatorTypeIn),
109 magneticArrayReflectionTypeSet(BDSArrayReflectionTypeSet()),
110 electricFieldFilePath(electricFieldFilePathIn),
111 electricFieldFormat(electricFieldFormatIn),
112 electricInterpolatorType(electricInterpolatorTypeIn),
113 electricArrayReflectionTypeSet(BDSArrayReflectionTypeSet()),
114 cacheTransforms(cacheTransformsIn),
115 eScaling(eScalingIn),
116 bScaling(bScalingIn),
117 timeOffset(timeOffsetIn),
118 autoScale(autoScaleIn),
119 stepLimit(stepLimitIn),
120 poleTipRadius(poleTipRadiusIn),
121 beamPipeRadius(beamPipeRadiusIn),
122 chordStepMinimum(-1),
123 secondFieldOnLeft(leftIn),
124 magneticSubFieldName(magneticSubFieldNameIn),
125 electricSubFieldName(electricSubFieldNameIn),
126 usePlacementWorldTransform(false),
127 modulatorInfo(nullptr),
128 ignoreUpdateOfMaximumStepSize(false),
129 isThin(false),
130 transformBeamline(nullptr),
131 extraInfo(nullptr),
132 nameOfParserDefinition("")
133{
134 if (transformIn != G4Transform3D::Identity)
135 {transform = new G4Transform3D(transformIn);}
136
137 // back calculate tilt angle from field transform
138 G4ThreeVector unitY(0,1,0);
139 G4ThreeVector unitYR = unitY.transform(transformIn.getRotation());
140 tilt = -(CLHEP::halfpi - unitYR.getPhi()); // halfpi offset for which axis we choose by convention
141}
142
143BDSFieldInfo::~BDSFieldInfo()
144{
145 delete magnetStrength;
146 delete transform;
147 if (stepLimit != defaultUL)
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)