OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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 
26 #include <iostream>
27 #include <fstream>
28 
29 extern Inform *gmsg;
30 
31 // Class RBend3D
32 // ------------------------------------------------------------------------
33 
35  RBend3D("")
36 {}
37 
38 
39 RBend3D::RBend3D(const RBend3D &right):
40  BendBase(right),
41  myFieldmap_m(right.myFieldmap_m),
42  fieldAmplitudeError_m(right.fieldAmplitudeError_m),
43  startField_m(right.startField_m),
44  lengthField_m(right.lengthField_m),
45  fast_m(right.fast_m),
46  geometry_m(right.geometry_m),
47  dummyField_m() {
49 }
50 
51 
52 RBend3D::RBend3D(const std::string &name):
53  BendBase(name),
54  myFieldmap_m(NULL),
55  fieldAmplitudeError_m(0.0),
56  startField_m(0.0),
57  lengthField_m(0.0),
58  fast_m(false),
59  geometry_m(),
60  dummyField_m() {
62 }
63 
64 
66  // Fieldmap::deleteFieldmap(filename_m);
67 }
68 
69 void RBend3D::accept(BeamlineVisitor &visitor) const {
70  visitor.visitRBend3D(*this);
71 }
72 
73 void RBend3D::setFieldMapFN(std::string fn) {
74  fileName_m = fn;
75 }
76 
77 void RBend3D::setFast(bool fast) {
78  fast_m = fast;
79 }
80 
81 
82 bool RBend3D::getFast() const {
83  return fast_m;
84 }
85 
86 void RBend3D::addKR(int i, double t, Vector_t &K) {
87 }
88 
89 void RBend3D::addKT(int i, double t, Vector_t &K) {
90 }
91 
92 bool RBend3D::apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) {
93  return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
94 }
95 
96 bool RBend3D::apply(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) {
97  const Vector_t tmpR(R(0), R(1), R(2) - startField_m);
98  Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
99 
100  myFieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
101 
102  B += (fieldAmplitude_m + fieldAmplitudeError_m) * tmpB;
103 
104  return false;
105 }
106 
107 bool RBend3D::applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) {
108  const Vector_t tmpR(R(0), R(1), R(2) - startField_m);
109  Vector_t tmpE(0.0), tmpB(0.0);
110 
111  myFieldmap_m->getFieldstrength(tmpR, tmpE, tmpB);
112  B += fieldAmplitude_m * tmpB;
113 
114  return false;
115 }
116 
117 void RBend3D::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
118  Inform msg("RBend3D ", *gmsg);
119 
120  RefPartBunch_m = bunch;
121 
123  if(myFieldmap_m != NULL) {
124  msg << level2 << getName() << " using file ";
125  myFieldmap_m->getInfo(&msg);
126  goOnline(0.0);
127 
128  double zBegin = 0.0, zEnd = 0.0, rBegin = 0.0, rEnd = 0.0;
129  myFieldmap_m->getFieldDimensions(zBegin, zEnd, rBegin, rEnd);
130 
131  if (length_m == 0.0) {
132  chordLength_m = 0.0;
133  double fieldLength = zEnd - zBegin;
134  double z = 0.0, dz = fieldLength / 1000;
135  Vector_t E(0.0), B(0.0);
136  while (z < fieldLength && B(1) < 0.5) {
137  myFieldmap_m->getFieldstrength(Vector_t(0.0, 0.0, z), E, B);
138  z += dz;
139  }
140  double zEntryEdge = z;
141  z = fieldLength;
142  B(1) = 0.0;
143  while (z > 0.0 && B(1) < 0.5) {
144  myFieldmap_m->getFieldstrength(Vector_t(0.0, 0.0, z), E, B);
145  z -= dz;
146  }
147  chordLength_m = z - zEntryEdge;
149  } else {
151  }
152 
153  startField_m = zBegin;
154  lengthField_m = zEnd - zBegin;
155  endField = startField + lengthField_m;
156 
157  if (bX_m * bX_m + bY_m * bY_m > 0.0) {
158  double refCharge = bunch->getQ();
160  if (refCharge < 0.0) {
162  }
163  fieldAmplitude_m = (refCharge *
164  std::abs(sqrt(pow(bY_m, 2.0) + pow(bX_m, 2.0)) / refCharge));
166  } else {
167  if (angle_m < 0.0) {
168  // Negative angle is a positive bend rotated 180 degrees.
172  }
173 
174  const double refCharge = RefPartBunch_m->getQ();
175  const double refMass = RefPartBunch_m->getM();
176  const double refGamma = designEnergy_m / refMass + 1.0;
177  const double refBetaGamma = sqrt(pow(refGamma, 2.0) - 1.0);
178 
179  Vector_t B(0.0), E(0.0);
180  double z = 0.0, dz = lengthField_m / 999;
181  double integratedBy = 0.0;
182 
183  myFieldmap_m->getFieldstrength(Vector_t(0.0, 0.0, z), E, B);
184  integratedBy += 0.5 * B(1);
185  z = dz;
186  while (z < lengthField_m) {
187  B = 0.0; E = 0.0;
188  myFieldmap_m->getFieldstrength(Vector_t(0.0, 0.0, z), E, B);
189  integratedBy += B(1);
190  z += dz;
191  }
192  integratedBy -= 0.5 * B(1);
193  integratedBy *= lengthField_m / 1000;
194 
195  // estimate magnitude of field
196  fieldAmplitude_m = refCharge * refMass * refBetaGamma * angle_m / (Physics::c * integratedBy);
197 
198  double angle = trackRefParticleThrough(bunch->getdT());
199  double error = (angle_m - angle) / angle_m;
200 
201  for (unsigned int i = 0; i < 10; ++ i) {
202  fieldAmplitude_m *= (0.5 * error + 1.0);
203  angle = trackRefParticleThrough(bunch->getdT());
204  error = (angle_m - angle) / angle_m;
205 
206  if (std::abs(error) < 0.001) break;
207  }
208 
210  trackRefParticleThrough(bunch->getdT(), true);
211  }
212  } else {
213  endField = startField;
214  }
215 }
216 
218 {}
219 
220 bool RBend3D::bends() const {
221  return true;
222 }
223 
224 void RBend3D::goOnline(const double &) {
226  online_m = true;
227 }
228 
231  online_m = false;
232 }
233 
234 void RBend3D::getDimensions(double &zBegin, double &zEnd) const {
235  zBegin = startField_m;
236  zEnd = startField_m + length_m;
237 }
238 
239 
241  return RBEND3D;
242 }
243 
244 bool RBend3D::isInside(const Vector_t &r) const {
245  Vector_t tmpR(r(0), r(1), r(2) - startField_m);
246  return myFieldmap_m->isInside(tmpR);
247 }
248 
250  return new RBend3D(*this);
251 }
252 
254  return geometry_m;
255 }
256 
258  return geometry_m;
259 }
260 
262  return dummyField_m;
263 }
264 
265 const EMField &RBend3D::getField() const {
266  return dummyField_m;
267 }
268 
270  Vector_t XIni, XFinal;
271  myFieldmap_m->getFieldDimensions(XIni(0), XFinal(0),
272  XIni(1), XFinal(1),
273  XIni(2), XFinal(2));
274 
275  MeshData mesh;
276  mesh.vertices_m.push_back(Vector_t(XIni(0), XIni(1), XIni(2)));
277  mesh.vertices_m.push_back(Vector_t(XIni(0), XIni(1), XFinal(2)));
278  mesh.vertices_m.push_back(Vector_t(XIni(0), XFinal(1), XIni(2)));
279  mesh.vertices_m.push_back(Vector_t(XIni(0), XFinal(1), XFinal(2)));
280  mesh.vertices_m.push_back(Vector_t(XFinal(0), XIni(1), XIni(2)));
281  mesh.vertices_m.push_back(Vector_t(XFinal(0), XIni(1), XFinal(2)));
282  mesh.vertices_m.push_back(Vector_t(XFinal(0), XFinal(1), XIni(2)));
283  mesh.vertices_m.push_back(Vector_t(XFinal(0), XFinal(1), XFinal(2)));
284 
285  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(0, 1, 2));
286  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(2, 1, 3));
287  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(4, 6, 5));
288  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(5, 6, 7));
289  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(1, 5, 3));
290  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(3, 5, 7));
291  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(4, 2, 6));
292  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(4, 0, 2));
293  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(0, 4, 1));
294  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(1, 4, 5));
295  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(2, 3, 6));
296  mesh.triangles_m.push_back(Vektor<unsigned int, 3>(3, 7, 6));
297 
298  return mesh;
299 }
300 
301 double RBend3D::trackRefParticleThrough(double dt, bool print) {
302  const double refMass = RefPartBunch_m->getM();
303  const double refGamma = designEnergy_m / refMass + 1.0;
304  const double refBetaGamma = sqrt(pow(refGamma, 2.0) - 1.0);
305  const double stepSize = refBetaGamma / refGamma * Physics::c * dt;
306  const Vector_t scaleFactor(Physics::c * dt);
307  print = print && (Ippl::myNode() == 0);
308 
309  std::ofstream trajectoryOutput;
310  if (print) {
311  trajectoryOutput.open("data/" + OpalData::getInstance()->getInputBasename() + "_" + getName() + "_traj.dat");
312  trajectoryOutput.precision(12);
313  trajectoryOutput << "# " << std::setw(18) << "s"
314  << std::setw(20) << "x"
315  << std::setw(20) << "z"
316  << std::setw(20) << "By"
317  << std::endl;
318  }
319 
320  double deltaS = 0.0;
322 
323  Vector_t X(0.0), P(0.0);
325  X(2) = startField_m;
326  P(0) = refBetaGamma * sin(entranceAngle_m);
327  P(2) = refBetaGamma * cos(entranceAngle_m);
328 
329  while ((X(2) - startField_m) < lengthField_m && 0.5 * deltaS < lengthField_m) {
330  Vector_t E(0.0), B(0.0);
331 
332  X /= scaleFactor;
333  pusher.push(X, P, dt);
334  X *= scaleFactor;
335 
336  applyToReferenceParticle(X, P, 0.0, E, B);
337  if (print) {
338  trajectoryOutput << std::setw(20) << deltaS + 0.5 * stepSize
339  << std::setw(20) << X(0)
340  << std::setw(20) << X(2)
341  << std::setw(20) << B(1)
342  << std::endl;
343  }
344 
345  pusher.kick(X, P, E, B, dt);
346 
347  X /= scaleFactor;
348  pusher.push(X, P, dt);
349  X *= scaleFactor;
350 
351  deltaS += stepSize;
352  }
353 
354  return -atan2(P(0), P(2)) + entranceAngle_m;
355 }
ParticleAttrib< Vector_t > P
Interface for solenoids.
Definition: RBend3D.h:39
virtual void getInfo(Inform *msg)=0
virtual void freeMap()=0
double lengthField_m
Definition: RBend3D.h:112
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Interface for basic beam line object.
Definition: ElementBase.h:128
bool getFast() const
Definition: RBend3D.cpp:82
virtual void readMap()=0
std::string fileName_m
Definition: BendBase.h:56
Definition: rbendmap.h:8
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
virtual bool isInside(const Vector_t &r) const
Definition: Fieldmap.h:203
RBend3D()
Definition: RBend3D.cpp:34
double getdT() const
Inform * gmsg
Definition: Main.cpp:21
double getM() const
bool online_m
Definition: Component.h:201
virtual void getFieldDimensions(double &zBegin, double &zEnd, double &rBegin, double &rEnd) const =0
const PartData * getReference() const
double chordLength_m
Definition: BendBase.h:41
double bX_m
Definition: BendBase.h:52
static int myNode()
Definition: IpplInfo.cpp:794
virtual const std::string & getName() const
Get element name.
Definition: ElementBase.cpp:95
Tps< T > tan(const Tps< T > &x)
Tangent.
Definition: TpsMath.h:147
virtual ElementBase::ElementType getType() const override
Get element type std::string.
Definition: RBend3D.cpp:240
static Fieldmap * getFieldmap(std::string Filename, bool fast=false)
Definition: Fieldmap.cpp:46
StraightGeometry geometry_m
Definition: RBend3D.h:116
double startField_m
Definition: RBend3D.h:111
virtual bool isInside(const Vector_t &r) const override
Definition: RBend3D.cpp:244
BMultipoleField dummyField_m
Definition: RBend3D.h:118
Fieldmap * myFieldmap_m
Definition: RBend3D.h:108
MeshData getSurfaceMesh() const
Definition: RBend3D.cpp:269
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
static OpalData * getInstance()
Definition: OpalData.cpp:209
virtual bool getFieldstrength(const Vector_t &R, Vector_t &E, Vector_t &B) const =0
double fieldAmplitudeError_m
Definition: RBend3D.h:109
Abstract base class for accelerator geometry classes.
Definition: Geometry.h:43
constexpr double pi
The value of .
Definition: Physics.h:31
void setElType(ElemType elt)
set the element type as enumeration needed in the envelope tracker
Definition: ElementBase.h:591
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
std::vector< Vector_t > vertices_m
Definition: MeshGenerator.h:5
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: RBend3D.cpp:117
virtual void addKT(int i, double t, Vector_t &K) override
Definition: RBend3D.cpp:89
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:200
double entranceAngle_m
Definition: BendBase.h:43
double rotationZAxis_m
Definition: ElementBase.h:473
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
ElementBase * clone() const override
Definition: RBend3D.cpp:249
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
virtual void addKR(int i, double t, Vector_t &K) override
Definition: RBend3D.cpp:86
Abstract base class for electromagnetic fields.
Definition: EMField.h:188
BGeometryBase & getGeometry() override
Definition: RBend3D.cpp:253
EMField & getField() override
Definition: RBend3D.cpp:261
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
double fieldAmplitude_m
Definition: BendBase.h:54
std::vector< Vektor< unsigned int, 3 > > triangles_m
Definition: MeshGenerator.h:6
virtual void goOnline(const double &kineticEnergy) override
Definition: RBend3D.cpp:224
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
Definition: RBend3D.cpp:107
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
virtual void getDimensions(double &zBegin, double &zEnd) const override
Definition: RBend3D.cpp:234
double getQ() const
Access to reference data.
const std::string name
void setFast(bool fast)
Definition: RBend3D.cpp:77
double length_m
Definition: BendBase.h:40
virtual void accept(BeamlineVisitor &) const override
Apply visitor to RBend3D.
Definition: RBend3D.cpp:69
double designEnergy_m
Definition: BendBase.h:47
void setFieldMapFN(std::string fn)
Definition: RBend3D.cpp:73
virtual void finalise() override
Definition: RBend3D.cpp:217
virtual bool bends() const override
Indicates that element bends the beam.
Definition: RBend3D.cpp:220
virtual ~RBend3D()
Definition: RBend3D.cpp:65
ParticlePos_t & R
virtual void goOffline() override
Definition: RBend3D.cpp:229
bool fast_m
Definition: RBend3D.h:114
#define K
Definition: integrate.cpp:118
Abstract algorithm.
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Definition: RBend3D.cpp:92
double angle_m
Definition: BendBase.h:42
Definition: Inform.h:41
double bY_m
Definition: BendBase.h:53
double trackRefParticleThrough(double dt, bool print=false)
Definition: RBend3D.cpp:301
virtual void visitRBend3D(const RBend3D &)
Apply the algorithm to a rectangular bend.
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
bool writeBendTrajectories
Definition: Options.cpp:26