BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSFieldMagMultipoleOuterOld.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "BDSFieldMagMultipoleOuterOld.hh"
20
21#include "globals.hh"
22#include "G4RotationMatrix.hh"
23#include "G4ThreeVector.hh"
24#include "G4TwoVector.hh"
25
26#include "CLHEP/Units/PhysicalConstants.h"
27
28#include <cmath>
29#include <vector>
30
31BDSFieldMagMultipoleOuterOld::BDSFieldMagMultipoleOuterOld(G4int orderIn,
32 G4double poleTipRadiusIn,
33 const BDSFieldMag* innerFieldIn,
34 G4bool kPositive,
35 G4double arbitraryScaling):
36 order(orderIn),
37 normalisation(1), // we have to get field first to calculate the normalisation which uses it, so start with 1
38 positiveField(kPositive),
39 poleTipRadius(poleTipRadiusIn)
40{
41 G4int nPoles = 2*order;
42
43 // prepare vector of infinite wire current sources
44 G4TwoVector firstCurrent(poleTipRadius, 0);
45 for (G4int i = 0; i < nPoles; ++i)
46 {
47 G4TwoVector c = firstCurrent; // copy it
48 c.rotate((G4double)i*CLHEP::twopi / nPoles); // rotate copy
49 currents.push_back(c);
50 }
51
52 // query inner field - at point just outside pole tip
53 G4ThreeVector poleTipPoint = G4ThreeVector(0, poleTipRadius, 0);
54 G4double angleOffset = CLHEP::twopi/(G4double)nPoles;
55 poleTipPoint.rotateZ(0.5*angleOffset); // rotate from 0,1 to the pole position (different for each magnet).
56 G4ThreeVector fieldAtPoleTip = innerFieldIn->GetField(poleTipPoint,/*t=*/0);
57 G4double fieldAtPoleTipMag = fieldAtPoleTip.mag();
58
59 // we query this field object but with the normalisation initialised to 1 so it won't
60 // affect the result despite using the same code
61 // the inner field is by default OFF just now so won't affect this
62 G4ThreeVector rawOuterlFieldAtPoleTip = GetField(poleTipPoint);
63 G4double rawOuterlFieldAtPoleTipMag = rawOuterlFieldAtPoleTip.mag();
64
65 // normalisation
66 normalisation = arbitraryScaling * fieldAtPoleTipMag / rawOuterlFieldAtPoleTipMag;
67 if (!std::isfinite(normalisation))
68 {
69 normalisation = 0;
70 finiteStrength = false;
71 }
72}
73
74G4ThreeVector BDSFieldMagMultipoleOuterOld::GetField(const G4ThreeVector& position,
75 const G4double /*t*/) const
76{
77 G4TwoVector pos(position.x(), position.y());
78
79 // temporary variables
80 G4TwoVector result;
81 G4TwoVector cToPos;
82 G4double cToPosMag = 0;
83 G4double reciprocal = 0;
84 G4TwoVector cToPosPerp;
85
86 // loop over linear sum from all infinite wire sources
87 G4int pole = 1; // counter
88 const G4double spatialLimit = 6; // mm
89 G4bool closeToPole = false;
90 for (const auto& c : currents)
91 {
92 cToPos = pos - c; // distance to this wire
93 cToPosMag = cToPos.mag();
94 if (cToPosMag < spatialLimit)
95 {// we're close to a pole
96 // for the contribution from this pole, resample at spatial limit r
97 // from the current point - will give same direction
98 pos += cToPos.unit() * spatialLimit;
99 cToPos = pos - c;
100 cToPosMag = cToPos.mag();
101 closeToPole = true;
102 }
103
104 reciprocal = 1/cToPosMag;
105 if (!std::isnormal(reciprocal))
106 {reciprocal = 1.0;} // protect against bad values
107 cToPosPerp = G4TwoVector(-cToPos.y(), cToPos.x());
108 G4TwoVector val = std::pow(-1, pole+1)*cToPosPerp.unit() * reciprocal;
109 if (std::isfinite(val.x()) && std::isfinite(val.y())) // tolerate bad values
110 {result += val;}
111 pole++;
112 }
113
114 // limit to pole tip maximum - 0.1 empirical factor to match
115 if (closeToPole)
116 {result = result.unit()*0.1;}
117
118 // get sign right to match convention
119 if (positiveField)
120 {result *= -1;}
121
122 // normalisation
123 result *= normalisation;
124
125 return G4ThreeVector(result.x(), result.y(), 0);
126}
G4bool positiveField
Sign of magnetic field.
virtual G4ThreeVector GetField(const G4ThreeVector &position, const double t=0) const
Access the field value.
std::vector< G4TwoVector > currents
Locations of inifite wire current sources.
G4double normalisation
Storage of the overal normalisation factor.
Interface for static magnetic fields that may or may not be local.
Definition: BDSFieldMag.hh:39
virtual G4ThreeVector GetField(const G4ThreeVector &position, const G4double t=0) const =0