18#include "BDSFieldMagDipole.hh"
19#include "BDSFieldMagMultipoleOuter.hh"
20#include "BDSUtilities.hh"
23#include "G4RotationMatrix.hh"
24#include "G4ThreeVector.hh"
25#include "G4TwoVector.hh"
27#include "CLHEP/Units/PhysicalConstants.h"
32BDSFieldMagMultipoleOuter::BDSFieldMagMultipoleOuter(G4int orderIn,
33 G4double poleTipRadiusIn,
37 G4double arbitraryScaling):
42 positiveField(kPositive),
44 poleTipRadius(poleTipRadiusIn),
46 initialisationPhase(true)
50 poleNOffset = brho > 0 ? 1 : 0;
53 G4int nPoles = 2*order;
64 const auto innerDipoleField =
dynamic_cast<const BDSFieldMagDipole*
>(innerFieldIn);
68 positiveField =
false;
69 G4ThreeVector innerB = innerDipoleField->FieldValue();
70 G4double phiXY = innerB.phi();
71 phiOffset = phiXY - CLHEP::halfpi;
75 G4TwoVector firstCurrent(poleTipRadius, 0);
76 for (G4int i = 0; i < nPoles; ++i)
78 G4TwoVector c = firstCurrent;
79 c.rotate(phiOffset + (G4double)i*CLHEP::twopi / nPoles);
80 currents.push_back(c);
85 G4TwoVector pointA(poleTipRadius, 0);
86 G4TwoVector pointB = pointA;
87 pointB.rotate(CLHEP::twopi / nPoles);
88 G4double interPoleDistance = (pointB - pointA).
mag();
90 spatialLimit = 0.05*interPoleDistance;
96 G4double angleC1 = currents[0].phi();
97 G4double angleC2 = currents[1].phi();
98 G4double angleAvg = (angleC1 + angleC2) / 2.0;
99 G4TwoVector queryPoint;
100 queryPoint.setPolar(poleTipRadius, angleAvg);
103 G4ThreeVector poleTipPoint(queryPoint.x(), queryPoint.y(), 0);
105 G4ThreeVector fieldAtPoleTip = innerFieldIn->
GetField(poleTipPoint,0);
106 G4double fieldAtPoleTipMag = fieldAtPoleTip.mag();
111 maxField = fieldAtPoleTipMag * arbitraryScaling;
116 G4ThreeVector rawOuterlFieldAtPoleTip = GetField(poleTipPoint);
117 G4double rawOuterlFieldAtPoleTipMag = rawOuterlFieldAtPoleTip.mag();
120 normalisation = fieldAtPoleTipMag / rawOuterlFieldAtPoleTipMag;
121 normalisation *= arbitraryScaling;
122 if (!std::isfinite(normalisation))
125 finiteStrength =
false;
127 initialisationPhase =
false;
131 const G4double )
const
133 G4TwoVector pos(position.x(), position.y());
138 G4double cToPosMag = 0;
139 G4double reciprocal = 0;
140 G4TwoVector cToPosPerp;
144 G4bool closeToPole =
false;
148 cToPosMag = cToPos.mag();
155 cToPosMag = cToPos.mag();
159 reciprocal = 1/cToPosMag;
160 if (!std::isnormal(reciprocal))
162 cToPosPerp = G4TwoVector(-cToPos.y(), cToPos.x());
163 G4TwoVector val = std::pow(-1, pole+
poleNOffset)*cToPosPerp.unit() * reciprocal;
164 if (std::isfinite(val.x()) && std::isfinite(val.y()))
179 if ((result.mag() >
maxField) || closeToPole)
180 {result = result.unit() *
maxField;}
183 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())