19#include "BDSFieldMagDipole.hh"
20#include "BDSFieldMagMultipoleOuter.hh"
21#include "BDSUtilities.hh"
24#include "G4RotationMatrix.hh"
25#include "G4ThreeVector.hh"
26#include "G4TwoVector.hh"
28#include "CLHEP/Units/PhysicalConstants.h"
33BDSFieldMagMultipoleOuter::BDSFieldMagMultipoleOuter(G4int orderIn,
34 G4double poleTipRadiusIn,
38 G4double arbitraryScaling):
43 positiveField(kPositive),
45 poleTipRadius(poleTipRadiusIn),
47 initialisationPhase(true)
51 poleNOffset = brho > 0 ? 1 : 0;
54 G4int nPoles = 2*order;
65 const auto innerDipoleField =
dynamic_cast<const BDSFieldMagDipole*
>(innerFieldIn);
69 positiveField =
false;
70 G4ThreeVector innerB = innerDipoleField->FieldValue();
71 G4double phiXY = innerB.phi();
72 phiOffset = phiXY - CLHEP::halfpi;
76 G4TwoVector firstCurrent(poleTipRadius, 0);
77 for (G4int i = 0; i < nPoles; ++i)
79 G4TwoVector c = firstCurrent;
80 c.rotate(phiOffset + (G4double)i*CLHEP::twopi / nPoles);
81 currents.push_back(c);
86 G4TwoVector pointA(poleTipRadius, 0);
87 G4TwoVector pointB = pointA;
88 pointB.rotate(CLHEP::twopi / nPoles);
89 G4double interPoleDistance = (pointB - pointA).
mag();
91 spatialLimit = 0.05*interPoleDistance;
97 G4double angleC1 = currents[0].phi();
98 G4double angleC2 = currents[1].phi();
99 G4double angleAvg = (angleC1 + angleC2) / 2.0;
100 G4TwoVector queryPoint;
101 queryPoint.setPolar(poleTipRadius, angleAvg);
104 G4ThreeVector poleTipPoint(queryPoint.x(), queryPoint.y(), 0);
106 G4ThreeVector fieldAtPoleTip = innerFieldIn->
GetField(poleTipPoint,0);
107 G4double fieldAtPoleTipMag = fieldAtPoleTip.mag();
112 maxField = fieldAtPoleTipMag * arbitraryScaling;
117 G4ThreeVector rawOuterlFieldAtPoleTip = GetField(poleTipPoint);
118 G4double rawOuterlFieldAtPoleTipMag = rawOuterlFieldAtPoleTip.mag();
121 normalisation = fieldAtPoleTipMag / rawOuterlFieldAtPoleTipMag;
122 normalisation *= arbitraryScaling;
123 if (!std::isfinite(normalisation))
126 finiteStrength =
false;
128 initialisationPhase =
false;
132 const G4double )
const
134 G4TwoVector pos(position.x(), position.y());
139 G4double cToPosMag = 0;
140 G4double reciprocal = 0;
141 G4TwoVector cToPosPerp;
145 G4bool closeToPole =
false;
149 cToPosMag = cToPos.mag();
156 cToPosMag = cToPos.mag();
160 reciprocal = 1/cToPosMag;
161 if (!std::isnormal(reciprocal))
163 cToPosPerp = G4TwoVector(-cToPos.y(), cToPos.x());
164 G4TwoVector val = std::pow(-1, pole+
poleNOffset)*cToPosPerp.unit() * reciprocal;
165 if (std::isfinite(val.x()) && std::isfinite(val.y()))
180 if ((result.mag() >
maxField) || closeToPole)
181 {result = result.unit() *
maxField;}
184 return G4ThreeVector(result.x(), result.y(), 0);
virtual G4ThreeVector GetField(const G4ThreeVector &position, const double t=0) const
Access the field value.
G4double spatialLimit
Radius from any current source within which the field is artificially saturated.
std::vector< G4TwoVector > currents
Locations of infinite wire current sources.
G4int poleNOffset
Offset for pole to start at - in effect this flips the sign of the field.
G4double maxField
Any field beyond this will curtailed to this value.
G4bool initialisationPhase
Need a way to control cludge normalisation behaviour during initial normalisation calculation.
G4double normalisation
Storage of the overall normalisation factor.
G4bool positiveField
Sign of magnetic field.
Interface for static magnetic fields that may or may not be local.
G4bool FiniteStrength() const
Accessor.
virtual G4ThreeVector GetField(const G4ThreeVector &position, const G4double t=0) const =0
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())