OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
RBend3D.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: RBend3D.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.1.1.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: RBend3D
10 // Defines the abstract interface for a solenoid magnet.
11 //
12 // ------------------------------------------------------------------------
13 // Class category: AbsBeamline
14 // ------------------------------------------------------------------------
15 
16 #include "AbsBeamline/RBend3D.h"
18 #include "Steppers/BorisPusher.h"
20 #include "Fields/Fieldmap.h"
22 #include "Utilities/Options.h"
24 #include "Physics/Physics.h"
25 #include "Utilities/Util.h"
26 
27 #include <iostream>
28 #include <fstream>
29 #include <cmath>
30 
31 extern Inform *gmsg;
32 
33 // Class RBend3D
34 // ------------------------------------------------------------------------
35 
37  RBend3D("")
38 {}
39 
40 
41 RBend3D::RBend3D(const RBend3D &right):
42  BendBase(right),
43  fieldAmplitudeError_m(right.fieldAmplitudeError_m),
44  startField_m(right.startField_m),
45  lengthField_m(right.lengthField_m),
46  geometry_m(right.geometry_m),
47  dummyField_m() {
48 }
49 
50 
51 RBend3D::RBend3D(const std::string &name):
52  BendBase(name),
53  fieldAmplitudeError_m(0.0),
54  startField_m(0.0),
55  lengthField_m(0.0),
56  geometry_m(),
57  dummyField_m() {
58 }
59 
60 
62 }
63 
64 void RBend3D::accept(BeamlineVisitor &visitor) const {
65  visitor.visitRBend3D(*this);
66 }
67 
68 bool RBend3D::apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) {
69  return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
70 }
71 
72 bool RBend3D::apply(const Vector_t &R, const Vector_t &/*P*/, const double &/*t*/, Vector_t &/*E*/, Vector_t &B) {
73  const Vector_t tmpR(R(0), R(1), R(2) - startField_m);
74  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
75 
76  fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
77 
79 
80  return false;
81 }
82 
83 bool RBend3D::applyToReferenceParticle(const Vector_t &R, const Vector_t &/*P*/, const double &/*t*/, Vector_t &/*E*/, Vector_t &B) {
84  const Vector_t tmpR(R(0), R(1), R(2) - startField_m);
85  Vector_t tmpE(0.0), tmpB(0.0);
86 
87  fieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
88  B += fieldAmplitude_m * tmpB;
89 
90  return false;
91 }
92 
93 void RBend3D::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
94  Inform msg("RBend3D ", *gmsg);
95 
96  RefPartBunch_m = bunch;
97 
99  if(fieldmap_m != NULL) {
100  msg << level2 << getName() << " using file ";
101  fieldmap_m->getInfo(&msg);
102  goOnline(0.0);
103 
104  double zBegin = 0.0, zEnd = 0.0;
105  fieldmap_m->getFieldDimensions(zBegin, zEnd);
106 
107  if (getElementLength() == 0.0) {
108  chordLength_m = 0.0;
109  double fieldLength = zEnd - zBegin;
110  double z = 0.0, dz = fieldLength / 1000;
111  Vector_t E(0.0), B(0.0);
112  while (z < fieldLength && B(1) < 0.5) {
113  fieldmap_m->getFieldstrength(Vector_t(0.0, 0.0, z), E, B);
114  z += dz;
115  }
116  double zEntryEdge = z;
117  z = fieldLength;
118  B(1) = 0.0;
119  while (z > 0.0 && B(1) < 0.5) {
120  fieldmap_m->getFieldstrength(Vector_t(0.0, 0.0, z), E, B);
121  z -= dz;
122  }
123  chordLength_m = z - zEntryEdge;
125  } else {
127  }
128 
129  startField_m = zBegin;
130  lengthField_m = zEnd - zBegin;
131  endField = startField + lengthField_m;
132 
133  if (angle_m != 0.0) {
134  if (angle_m < 0.0) {
135  // Negative angle is a positive bend rotated 180 degrees.
139  }
140 
141  Vector_t B(0.0), E(0.0);
142  double z = 0.0, dz = lengthField_m / 999;
143  double integratedBy = 0.0;
144 
145  fieldmap_m->getFieldstrength(Vector_t(0.0, 0.0, z), E, B);
146  integratedBy += 0.5 * B(1);
147  z = dz;
148  while (z < lengthField_m) {
149  B = 0.0; E = 0.0;
150  fieldmap_m->getFieldstrength(Vector_t(0.0, 0.0, z), E, B);
151  integratedBy += B(1);
152  z += dz;
153  }
154  integratedBy -= 0.5 * B(1);
155  integratedBy *= lengthField_m / 1000;
156 
157  // estimate magnitude of field
158  fieldAmplitude_m = calcFieldAmplitude(integratedBy / angle_m);
159 
160  double angle = trackRefParticleThrough(bunch->getdT());
161  double error = (angle_m - angle) / angle_m;
162 
163  for (unsigned int i = 0; i < 10; ++ i) {
164  fieldAmplitude_m *= (0.5 * error + 1.0);
165  angle = trackRefParticleThrough(bunch->getdT());
166  error = (angle_m - angle) / angle_m;
167 
168  if (std::abs(error) < 0.001) break;
169  }
170 
172  trackRefParticleThrough(bunch->getdT(), true);
173  } else {
174  double refCharge = bunch->getQ();
176  if (refCharge < 0.0) {
178  }
179  fieldAmplitude_m = std::copysign(1.0, refCharge) * std::hypot(fieldAmplitudeX_m, fieldAmplitudeY_m);
181  }
182 
183  } else {
184  endField = startField;
185  }
186 }
187 
189 {}
190 
191 void RBend3D::goOnline(const double &) {
193  online_m = true;
194 }
195 
198  online_m = false;
199 }
200 
201 void RBend3D::getDimensions(double &zBegin, double &zEnd) const {
202  zBegin = startField_m;
203  zEnd = startField_m + getElementLength();
204 }
205 
206 
208  return RBEND3D;
209 }
210 
211 bool RBend3D::isInside(const Vector_t &r) const {
212  Vector_t tmpR(r(0), r(1), r(2) - startField_m);
213  return fieldmap_m->isInside(tmpR);
214 }
215 
217  return new RBend3D(*this);
218 }
219 
221  return geometry_m;
222 }
223 
225  return geometry_m;
226 }
227 
229  return dummyField_m;
230 }
231 
232 const EMField &RBend3D::getField() const {
233  return dummyField_m;
234 }
235 
237  Vector_t XIni, XFinal;
238  fieldmap_m->getFieldDimensions(XIni(0), XFinal(0),
239  XIni(1), XFinal(1),
240  XIni(2), XFinal(2));
241 
242  MeshData mesh;
243  mesh.vertices_m.push_back(Vector_t(XIni(0), XIni(1), XIni(2)));
244  mesh.vertices_m.push_back(Vector_t(XIni(0), XIni(1), XFinal(2)));
245  mesh.vertices_m.push_back(Vector_t(XIni(0), XFinal(1), XIni(2)));
246  mesh.vertices_m.push_back(Vector_t(XIni(0), XFinal(1), XFinal(2)));
247  mesh.vertices_m.push_back(Vector_t(XFinal(0), XIni(1), XIni(2)));
248  mesh.vertices_m.push_back(Vector_t(XFinal(0), XIni(1), XFinal(2)));
249  mesh.vertices_m.push_back(Vector_t(XFinal(0), XFinal(1), XIni(2)));
250  mesh.vertices_m.push_back(Vector_t(XFinal(0), XFinal(1), XFinal(2)));
251 
252  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(0, 1, 2));
253  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(2, 1, 3));
254  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(4, 6, 5));
255  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(5, 6, 7));
256  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(1, 5, 3));
257  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(3, 5, 7));
258  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(4, 2, 6));
259  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(4, 0, 2));
260  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(0, 4, 1));
261  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(1, 4, 5));
262  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(2, 3, 6));
263  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(3, 7, 6));
264 
265  return mesh;
266 }
267 
268 double RBend3D::trackRefParticleThrough(double dt, bool print) {
269  const double refGamma = calcGamma();
270  const double refBetaGamma = calcBetaGamma();
271  const double stepSize = refBetaGamma / refGamma * Physics::c * dt;
272  const Vector_t scaleFactor(Physics::c * dt);
273  print = print && (Ippl::myNode() == 0);
274 
275  std::ofstream trajectoryOutput;
276  if (print) {
277  std::string fname = Util::combineFilePath({
279  OpalData::getInstance()->getInputBasename() + "_" + getName() + "_traj.dat"
280  });
281  trajectoryOutput.open(fname);
282  trajectoryOutput.precision(12);
283  trajectoryOutput << "# " << std::setw(18) << "s"
284  << std::setw(20) << "x"
285  << std::setw(20) << "z"
286  << std::setw(20) << "By"
287  << std::endl;
288  }
289 
290  double deltaS = 0.0;
292 
293  Vector_t X(0.0), P(0.0);
295  X(2) = startField_m;
296  P(0) = refBetaGamma * std::sin(entranceAngle_m);
297  P(2) = refBetaGamma * std::cos(entranceAngle_m);
298 
299  while ((X(2) - startField_m) < lengthField_m && 0.5 * deltaS < lengthField_m) {
300  Vector_t E(0.0), B(0.0);
301 
302  X /= scaleFactor;
303  pusher.push(X, P, dt);
304  X *= scaleFactor;
305 
306  applyToReferenceParticle(X, P, 0.0, E, B);
307  if (print) {
308  trajectoryOutput << std::setw(20) << deltaS + 0.5 * stepSize
309  << std::setw(20) << X(0)
310  << std::setw(20) << X(2)
311  << std::setw(20) << B(1)
312  << std::endl;
313  }
314 
315  pusher.kick(X, P, E, B, dt);
316 
317  X /= scaleFactor;
318  pusher.push(X, P, dt);
319  X *= scaleFactor;
320 
321  deltaS += stepSize;
322  }
323 
324  return -std::atan2(P(0), P(2)) + entranceAngle_m;
325 }
Inform * gmsg
Definition: Main.cpp:62
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > tan(const Tps< T > &x)
Tangent.
Definition: TpsMath.h:147
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
#define X(arg)
Definition: fftpack.cpp:112
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
const std::string name
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:51
constexpr double pi
The value of.
Definition: Physics.h:30
bool writeBendTrajectories
Definition: Options.cpp:95
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition: Util.cpp:139
ParticlePos_t & R
const PartData * getReference() const
double getQ() const
Access to reference data.
ParticleAttrib< Vector_t > P
double getdT() const
std::string getInputBasename()
get input file name without extension
Definition: OpalData.cpp:658
static OpalData * getInstance()
Definition: OpalData.cpp:195
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Definition: OpalData.cpp:650
virtual void visitRBend3D(const RBend3D &)
Apply the algorithm to a rectangular bend.
double calcGamma() const
Calculate gamma from design energy.
Definition: BendBase.cpp:89
const bool fast_m
Flag to turn on fast field calculation.
Definition: BendBase.h:57
double fieldAmplitude_m
Field amplitude.
Definition: BendBase.h:71
double calcBetaGamma() const
Calculate beta*gamma from design energy.
Definition: BendBase.cpp:95
double entranceAngle_m
Definition: BendBase.h:54
double fieldAmplitudeY_m
Definition: BendBase.h:68
Fieldmap * fieldmap_m
Magnet field map.
Definition: BendBase.h:56
std::string fileName_m
Definition: BendBase.h:73
double chordLength_m
Definition: BendBase.h:52
double calcFieldAmplitude(double radius) const
Calculate field amplitude from design energy and radius.
Definition: BendBase.cpp:70
double fieldAmplitudeX_m
Definition: BendBase.h:66
double angle_m
Bend angle.
Definition: BendBase.h:53
bool online_m
Definition: Component.h:195
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:194
virtual const std::string & getName() const
Get element name.
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:432
virtual void setElementLength(double length)
Set design length.
Definition: ElementBase.h:436
double rotationZAxis_m
Definition: ElementBase.h:394
Interface for solenoids.
Definition: RBend3D.h:39
ElementBase * clone() const override
Definition: RBend3D.cpp:216
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
Definition: RBend3D.cpp:83
virtual void goOnline(const double &kineticEnergy) override
Definition: RBend3D.cpp:191
virtual void goOffline() override
Definition: RBend3D.cpp:196
BGeometryBase & getGeometry() override
Definition: RBend3D.cpp:220
virtual bool isInside(const Vector_t &r) const override
Definition: RBend3D.cpp:211
StraightGeometry geometry_m
Definition: RBend3D.h:99
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Definition: RBend3D.cpp:68
double fieldAmplitudeError_m
Definition: RBend3D.h:94
virtual void finalise() override
Definition: RBend3D.cpp:188
BMultipoleField dummyField_m
Definition: RBend3D.h:101
virtual void getDimensions(double &zBegin, double &zEnd) const override
Definition: RBend3D.cpp:201
RBend3D()
Definition: RBend3D.cpp:36
virtual ~RBend3D()
Definition: RBend3D.cpp:61
double lengthField_m
Definition: RBend3D.h:97
double startField_m
Definition: RBend3D.h:96
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: RBend3D.cpp:93
double trackRefParticleThrough(double dt, bool print=false)
Definition: RBend3D.cpp:268
MeshData getSurfaceMesh() const
Definition: RBend3D.cpp:236
EMField & getField() override
Definition: RBend3D.cpp:228
virtual void accept(BeamlineVisitor &) const override
Apply visitor to RBend3D.
Definition: RBend3D.cpp:64
virtual ElementBase::ElementType getType() const override
Get element type std::string.
Definition: RBend3D.cpp:207
Abstract base class for accelerator geometry classes.
Definition: Geometry.h:43
Abstract base class for electromagnetic fields.
Definition: EMField.h:188
virtual void getInfo(Inform *msg)=0
virtual void getFieldDimensions(double &zBegin, double &zEnd) const =0
static Fieldmap * getFieldmap(std::string Filename, bool fast=false)
Definition: Fieldmap.cpp:50
virtual bool isInside(const Vector_t &) const
Definition: Fieldmap.h:101
virtual void freeMap()=0
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const =0
virtual void readMap()=0
std::vector< Vektor< unsigned int, 3 > > triangles_m
Definition: MeshGenerator.h:25
std::vector< Vector_t > vertices_m
Definition: MeshGenerator.h:24
void kick(const Vector_t &R, Vector_t &P, const Vector_t &Ef, const Vector_t &Bf, const double &dt) const
Definition: BorisPusher.h:65
void push(Vector_t &R, const Vector_t &P, const double &dt) const
Definition: BorisPusher.h:131
Definition: Inform.h:42
static int myNode()
Definition: IpplInfo.cpp:691
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6