19#include "BDSFieldMagDipole.hh"
20#include "BDSGlobalConstants.hh"
21#include "BDSIntegratorDipoleFringe.hh"
22#include "BDSMagnetStrength.hh"
24#include "BDSUtilities.hh"
26#include "G4Mag_EqRhs.hh"
27#include "G4ThreeVector.hh"
36 G4double minimumRadiusOfCurvatureIn,
37 const G4double& tiltIn):
40 fieldArcLength((*strengthIn)[
"length"]),
41 fieldAngle((*strengthIn)[
"angle"]),
44 multipoleIntegrator(nullptr)
46 if (thinElementLength < 0)
49 if (G4bool((*strengthIn)[
"isentrance"]))
51 polefaceAngle = (*strengthIn)[
"e1"];
52 polefaceCurvature = (*strengthIn)[
"h1"];
58 polefaceAngle = (*strengthIn)[
"e2"];
59 polefaceCurvature = (*strengthIn)[
"h2"];
66 isEntrance = (*strengthIn)[
"isentrance"];
71 {zeroStrength =
true;}
75 rho = (std::abs(brhoIn)/(*strengthIn)[
"field"]) * (*strengthIn)[
"scaling"];
79 G4double thinSextStrength = (-polefaceCurvature / rho) * 1.0 / std::pow(std::cos(polefaceAngle),3);
83 (*sextStrength)[
"k2"] = thinSextStrength;
85 (*sextStrength)[
"length"] = 1*CLHEP::m;
92 unitField = (dipoleField->FieldValue()).unit();
95 bx = (*strengthIn)[
"bx"];
96 by = (*strengthIn)[
"by"];
101BDSIntegratorDipoleFringe::~BDSIntegratorDipoleFringe()
103 delete multipoleIntegrator;
107 const G4double dydx[6],
113 const G4double fcof =
eqOfM->FCof();
119 const G4double dydx[6],
123 const G4double& fcof,
124 const G4double& momScaling)
135 G4double yMultipoleOut[6];
137 for (G4int i = 0; i < 3; i++)
139 yMultipoleOut[i] = yIn[i];
140 yMultipoleOut[i + 3] = yIn[i + 3];
143 if (multipoleIntegrator)
158 for (G4int i = 0; i < 6; i++)
159 {yTemp[i] = yMultipoleOut[i];}
173 if ((h > 1*CLHEP::cm) || (lengthFraction < 0.501))
179 for (G4int i = 0; i < 3; i++)
182 yOut[i + 3] = yTemp[i + 3];
189 G4ThreeVector pos = G4ThreeVector(yTemp[0], yTemp[1], yTemp[2]);
190 G4ThreeVector mom = G4ThreeVector(yTemp[3], yTemp[4], yTemp[5]);
194 {localPosMom = localPosMom.
rotateZ(-tilt);}
197 G4ThreeVector localMomU = localMom.unit();
209 for (G4int i = 0; i < 3; i++)
212 yOut[i + 3] = yTemp[i + 3];
219 G4ThreeVector localCLPosOut;
220 G4ThreeVector localCLMomOut;
223 G4double charge = fcof / std::abs(fcof);
224 G4double bendingRad =
rho * charge;
227 bendingRad *= momScaling;
233 G4double sign = bx < 0 ? -1 : 1;
234 G4double verticalFringeTiltAngle = 0.5*CLHEP::pi * sign;
236 localPos.rotateZ(-verticalFringeTiltAngle);
237 localMomU.rotateZ(-verticalFringeTiltAngle);
238 OneStep(localPos, localMomU, localCLPosOut, localCLMomOut, bendingRad);
239 localCLPosOut.rotateZ(verticalFringeTiltAngle);
240 localCLMomOut.rotateZ(verticalFringeTiltAngle);
243 {
OneStep(localPos, localMomU, localCLPosOut, localCLMomOut, bendingRad);}
249 localCLMomOut = localCLMomOut.rotateZ(tilt);
253 globalMom *= mom.mag();
255 G4ThreeVector globalMomU = globalMom.unit();
259 G4double yTempOut[6];
262 for (G4int i = 0; i < 3; i++)
264 yTempOut[i] = pos[i];
265 yTempOut[i + 3] = globalMom[i];
266 yErr[i] = globalMomU[i]*1e-10;
279 for (G4int i = 0; i < 6; i++)
280 {yOut[i] = yTempOut[i];}
285 const G4ThreeVector& momUIn,
286 G4ThreeVector& posOut,
287 G4ThreeVector& momOut,
288 const G4double& bendingRadius)
const
290 G4double x0 = posIn.x() / CLHEP::m;
291 G4double y0 = posIn.y() / CLHEP::m;
292 G4double s0 = posIn.z();
293 G4double xp = momUIn.x();
294 G4double yp = momUIn.y();
295 G4double zp = momUIn.z();
304 G4double X11=0,X12=0,X21=0,X22 = 0;
305 G4double Y11=0,Y12=0,Y21=0,Y22 = 0;
316 Y21 = -std::tan(
polefaceAngle - fringeFieldCorrection) / (bendingRadius / CLHEP::m);
319 x1 = X11*x0 + X12*xp;
320 xp1 = X21*x0 + X22*xp;
321 y1 = Y11*y0 + Y12*yp;
322 yp1 = Y21*y0 + Y22*yp;
325 zp1 = std::sqrt(1 - xp1*xp1 - yp1*yp1);
329 momOut = G4ThreeVector(xp1, yp1, zp1);
330 posOut = G4ThreeVector(x1*CLHEP::m, y1*CLHEP::m, s1);
334 G4double yMultipoleOut[6],
338 G4ThreeVector pos = G4ThreeVector(yIn[0], yIn[1], yIn[2]);
339 G4ThreeVector mom = G4ThreeVector(yIn[3], yIn[4], yIn[5]);
344 G4ThreeVector localMomU = localMom.unit();
347 G4ThreeVector localCLPosOut = localPos;
348 G4ThreeVector localCLMomOut = localMomU;
351 multipoleIntegrator->
OneStep(localPos, localMomU, localMom.mag(), localCLPosOut, localCLMomOut, 0);
354 globalMom *= mom.mag();
357 for (G4int i = 0; i < 3; i++)
359 yMultipoleOut[i] = pos[i];
360 yMultipoleOut[i + 3] = globalMom[i];
376 fint = (*strength)[
"fint"];
377 pfAngle = (*strength)[
"e1"];
381 fint = (*strength)[
"fintx"];
382 pfAngle = (*strength)[
"e2"];
384 G4double hgap = (*strength)[
"hgap"];
385 G4double vertGap = 2 * hgap;
386 G4double corrValue = fint * vertGap * (1.0 + std::pow(std::sin(pfAngle),2)) / std::cos(pfAngle);
398 fint = (*strength)[
"fint"];
399 fintK2 = (*strength)[
"fintk2"];
400 pfAngle = (*strength)[
"e1"];
404 fint = (*strength)[
"fintx"];
405 fintK2 = (*strength)[
"fintxk2"];
406 pfAngle = (*strength)[
"e2"];
408 G4double hgap = (*strength)[
"hgap"];
409 G4double vertGap = 2 * hgap;
410 G4double corrValue = fint * fintK2 * vertGap * std::tan(pfAngle);
BDSStep GlobalToCurvilinear(const G4double fieldArcLength, const G4ThreeVector &unitField, const G4double angle, const G4ThreeVector &position, const G4ThreeVector &unitMomentum, const G4double h, const G4bool useCurvilinearWorld, const G4double FCof, const G4double tilt=0)
G4ThreeVector ConvertAxisToGlobal(const G4ThreeVector &localAxis, const G4bool useCurvilinear=true) const
static BDSGlobalConstants * Instance()
Access method.
G4double secondFringeCorr
Second fringe field correction term.
void OneStep(const G4ThreeVector &posIn, const G4ThreeVector &momUIn, G4ThreeVector &posOut, G4ThreeVector &momOut, const G4double &bendingRadius) const
static G4double thinElementLength
G4double rho
Nominal magnet bending radius.
G4double backupStepperMomLimit
G4double polefaceAngle
Poleface rotation angle.
G4bool isEntrance
store if fringe is entrance or exit
G4double fringeCorr
Fringe field correction term.
void BaseStepper(const G4double yIn[6], const G4double dydx[6], const G4double &h, G4double yOut[6], G4double yErr[6], const G4double &fcof, const G4double &momScaling)
virtual void Stepper(const G4double yIn[6], const G4double dydx[6], const G4double h, G4double yOut[6], G4double yErr[6])
The stepper for integration. Calls base class stepper.
BDSIntegratorDipoleFringe()=delete
Private default constructor to enforce use of supplied constructor.
void MultipoleStep(const G4double yIn[6], G4double yMultipoleOut[6], const G4double &h)
Exact helix through pure dipole field.
G4Mag_EqRhs * eqOfM
Cache of equation of motion. This class does not own it.
virtual void Stepper(const G4double yIn[6], const G4double dydx[], G4double h, G4double yOut[6], G4double yErr[6])
Output error array.
void FudgeDistChordToZero()
void AdvanceDriftMag(const G4double yIn[], const G4double h, G4double yOut[], G4double yErr[]) const
Error array [6] all 0.
Integrator that ignores the field and uses the analytical solution to a multipole.
void OneStep(const G4ThreeVector &posIn, const G4ThreeVector &momUIn, const G4double momIn, G4ThreeVector &posOut, G4ThreeVector &momOut, G4double h) const
Efficient storage of magnet strengths.
A simple class to represent the positions of a step.
G4ThreeVector PostStepPoint() const
Accessor.
BDSStep rotateZ(const G4double &angle)
Mirror function to G4ThreeVector::rotateZ(). Returns copy that's rotated.
G4ThreeVector PreStepPoint() const
Accessor.
Return either G4Tubs or G4CutTubs depending on flat face.
G4double SecondFringeFieldCorrection(BDSMagnetStrength const *strength, G4bool entranceOrExit)
Function to calculate the value of the second fringe field correction term.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
G4bool IsFiniteStrength(G4double variable)
G4double FringeFieldCorrection(BDSMagnetStrength const *strength, G4bool entranceOrExit)
Function to calculate the value of the fringe field correction term.