20#include "BDSFieldMagDipole.hh"
21#include "BDSGlobalConstants.hh"
22#include "BDSIntegratorDipoleFringe.hh"
23#include "BDSMagnetStrength.hh"
25#include "BDSUtilities.hh"
27#include "G4Mag_EqRhs.hh"
28#include "G4ThreeVector.hh"
37 G4double minimumRadiusOfCurvatureIn,
38 const G4double& tiltIn):
41 fieldArcLength((*strengthIn)[
"length"]),
42 fieldAngle((*strengthIn)[
"angle"]),
45 multipoleIntegrator(nullptr)
47 if (thinElementLength < 0)
50 if ((*strengthIn)[
"isentrance"])
52 polefaceAngle = (*strengthIn)[
"e1"];
53 polefaceCurvature = (*strengthIn)[
"h1"];
59 polefaceAngle = (*strengthIn)[
"e2"];
60 polefaceCurvature = (*strengthIn)[
"h2"];
67 isEntrance = (*strengthIn)[
"isentrance"];
72 {zeroStrength =
true;}
76 rho = (std::abs(brhoIn)/(*strengthIn)[
"field"]) * (*strengthIn)[
"scaling"];
80 G4double thinSextStrength = (-polefaceCurvature / rho) * 1.0 / std::pow(std::cos(polefaceAngle),3);
84 (*sextStrength)[
"k2"] = thinSextStrength;
86 (*sextStrength)[
"length"] = 1*CLHEP::m;
93 unitField = (dipoleField->FieldValue()).unit();
96 bx = (*strengthIn)[
"bx"];
97 by = (*strengthIn)[
"by"];
102BDSIntegratorDipoleFringe::~BDSIntegratorDipoleFringe()
104 delete multipoleIntegrator;
108 const G4double dydx[6],
114 const G4double fcof =
eqOfM->FCof();
120 const G4double dydx[6],
124 const G4double& fcof,
125 const G4double& momScaling)
136 G4double yMultipoleOut[6];
138 for (G4int i = 0; i < 3; i++)
140 yMultipoleOut[i] = yIn[i];
141 yMultipoleOut[i + 3] = yIn[i + 3];
144 if (multipoleIntegrator)
159 for (G4int i = 0; i < 6; i++)
160 {yTemp[i] = yMultipoleOut[i];}
174 if ((h > 1*CLHEP::cm) || (lengthFraction < 0.501))
180 for (G4int i = 0; i < 3; i++)
183 yOut[i + 3] = yTemp[i + 3];
190 G4ThreeVector pos = G4ThreeVector(yTemp[0], yTemp[1], yTemp[2]);
191 G4ThreeVector mom = G4ThreeVector(yTemp[3], yTemp[4], yTemp[5]);
195 {localPosMom = localPosMom.
rotateZ(-tilt);}
198 G4ThreeVector localMomU = localMom.unit();
210 for (G4int i = 0; i < 3; i++)
213 yOut[i + 3] = yTemp[i + 3];
220 G4ThreeVector localCLPosOut;
221 G4ThreeVector localCLMomOut;
224 G4double charge = fcof / std::abs(fcof);
225 G4double bendingRad =
rho * charge;
228 bendingRad *= momScaling;
234 G4double sign = bx < 0 ? -1 : 1;
235 G4double verticalFringeTiltAngle = 0.5*CLHEP::pi * sign;
237 localPos.rotateZ(-verticalFringeTiltAngle);
238 localMomU.rotateZ(-verticalFringeTiltAngle);
239 OneStep(localPos, localMomU, localCLPosOut, localCLMomOut, bendingRad);
240 localCLPosOut.rotateZ(verticalFringeTiltAngle);
241 localCLMomOut.rotateZ(verticalFringeTiltAngle);
244 {
OneStep(localPos, localMomU, localCLPosOut, localCLMomOut, bendingRad);}
250 localCLMomOut = localCLMomOut.rotateZ(tilt);
254 globalMom *= mom.mag();
256 G4ThreeVector globalMomU = globalMom.unit();
260 G4double yTempOut[6];
263 for (G4int i = 0; i < 3; i++)
265 yTempOut[i] = pos[i];
266 yTempOut[i + 3] = globalMom[i];
267 yErr[i] = globalMomU[i];
280 for (G4int i = 0; i < 6; i++)
281 {yOut[i] = yTempOut[i];}
286 const G4ThreeVector& momUIn,
287 G4ThreeVector& posOut,
288 G4ThreeVector& momOut,
289 const G4double& bendingRadius)
const
291 G4double x0 = posIn.x() / CLHEP::m;
292 G4double y0 = posIn.y() / CLHEP::m;
293 G4double s0 = posIn.z();
294 G4double xp = momUIn.x();
295 G4double yp = momUIn.y();
296 G4double zp = momUIn.z();
305 G4double X11=0,X12=0,X21=0,X22 = 0;
306 G4double Y11=0,Y12=0,Y21=0,Y22 = 0;
317 Y21 = -std::tan(
polefaceAngle - fringeFieldCorrection) / (bendingRadius / CLHEP::m);
320 x1 = X11*x0 + X12*xp;
321 xp1 = X21*x0 + X22*xp;
322 y1 = Y11*y0 + Y12*yp;
323 yp1 = Y21*y0 + Y22*yp;
326 zp1 = std::sqrt(1 - xp1*xp1 - yp1*yp1);
330 momOut = G4ThreeVector(xp1, yp1, zp1);
331 posOut = G4ThreeVector(x1*CLHEP::m, y1*CLHEP::m, s1);
335 G4double yMultipoleOut[6],
339 G4ThreeVector pos = G4ThreeVector(yIn[0], yIn[1], yIn[2]);
340 G4ThreeVector mom = G4ThreeVector(yIn[3], yIn[4], yIn[5]);
345 G4ThreeVector localMomU = localMom.unit();
348 G4ThreeVector localCLPosOut = localPos;
349 G4ThreeVector localCLMomOut = localMomU;
352 multipoleIntegrator->
OneStep(localPos, localMomU, localMom.mag(), localCLPosOut, localCLMomOut, 0);
355 globalMom *= mom.mag();
358 for (G4int i = 0; i < 3; i++)
360 yMultipoleOut[i] = pos[i];
361 yMultipoleOut[i + 3] = globalMom[i];
377 fint = (*strength)[
"fint"];
378 pfAngle = (*strength)[
"e1"];
382 fint = (*strength)[
"fintx"];
383 pfAngle = (*strength)[
"e2"];
385 G4double hgap = (*strength)[
"hgap"];
386 G4double vertGap = 2 * hgap;
387 G4double corrValue = fint * vertGap * (1.0 + std::pow(std::sin(pfAngle),2)) / std::cos(pfAngle);
399 fint = (*strength)[
"fint"];
400 fintK2 = (*strength)[
"fintk2"];
401 pfAngle = (*strength)[
"e1"];
405 fint = (*strength)[
"fintx"];
406 fintK2 = (*strength)[
"fintxk2"];
407 pfAngle = (*strength)[
"e2"];
409 G4double hgap = (*strength)[
"hgap"];
410 G4double vertGap = 2 * hgap;
411 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.