OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
CavityAutophaser.cpp
Go to the documentation of this file.
2 #include "Algorithms/Vektor.h"
3 #include "AbsBeamline/RFCavity.h"
5 #include "Utilities/Options.h"
7 #include "Utilities/Util.h"
9 
10 #include <fstream>
11 #include <iostream>
12 
13 extern Inform *gmsg;
14 
16  std::shared_ptr<Component> cavity):
17  itsReference_m(ref),
18  itsCavity_m(cavity)
19 {
20  double zbegin = 0.0, zend = 0.0;
21  PartBunchBase<double, 3> *fakeBunch = NULL;
22  cavity->initialise(fakeBunch, zbegin, zend);
23  initialR_m = Vector_t(0, 0, zbegin);
24 }
25 
27 
28 }
29 
31  const Vector_t &P,
32  double t,
33  double dt) {
34  if(!(itsCavity_m->getType() == ElementBase::TRAVELINGWAVE ||
35  itsCavity_m->getType() == ElementBase::RFCAVITY)) {
36  throw OpalException("CavityAutophaser::getPhaseAtMaxEnergy()",
37  "given element is not a cavity");
38  }
39 
41 
42  RFCavity *element = static_cast<RFCavity *>(itsCavity_m.get());
43  bool apVeto = element->getAutophaseVeto();
44  bool isDCGun = false;
45  double originalPhase = element->getPhasem();
46  double tErr = (initialR_m(2) - R(2)) * sqrt(dot(P,P) + 1.0) / (P(2) * Physics::c);
47  double optimizedPhase = 0.0;
48  double finalEnergy = 0.0;
49  double newPhase = 0.0;
50  double amplitude = element->getAmplitudem();
51  double basePhase = std::fmod(element->getFrequencym() * (t + tErr), Physics::two_pi);
52  double frequency = element->getFrequencym();
53 
54  if ((!apVeto) && frequency <= (1.0 + 1e-6) * Physics::two_pi) { // DC gun
55  optimizedPhase = (amplitude * itsReference_m.getQ() > 0.0? 0.0: Physics::pi);
56  element->setPhasem(optimizedPhase + originalPhase);
57  element->setAutophaseVeto();
58 
59  originalPhase += optimizedPhase;
60  OpalData::getInstance()->setMaxPhase(itsCavity_m->getName(), originalPhase);
61 
62  apVeto = true;
63  isDCGun = true;
64  }
65 
66  std::stringstream ss;
67  for (char c: itsCavity_m->getName()) {
68  ss << std::setw(2) << std::left << c;
69  }
70  INFOMSG(level1 << "\n* ************* "
71  << std::left << std::setw(68) << std::setfill('*') << ss.str()
72  << std::setfill(' ') << endl);
73  if (!apVeto) {
74  double initialEnergy = Util::getEnergy(P, itsReference_m.getM()) * 1e-6;
75  double AstraPhase = 0.0;
76  double designEnergy = element->getDesignEnergy();
77 
78  if (amplitude < 0.0) {
79  amplitude = -amplitude;
80  element->setAmplitudem(amplitude);
81  }
82 
83  double initialPhase = guessCavityPhase(t + tErr);
84 
85  if (amplitude == 0.0 && designEnergy <= 0.0) {
86  throw OpalException("CavityAutophaser::getPhaseAtMaxEnergy()",
87  "neither amplitude or design energy given to cavity " + element->getName());
88  }
89 
90  if (designEnergy > 0.0) {
91  const double length = itsCavity_m->getElementLength();
92  if (length <= 0.0) {
93  throw OpalException("CavityAutophaser::getPhaseAtMaxEnergy()",
94  "length of cavity " + element->getName() + " is zero");
95  }
96 
97  amplitude = 2 * (designEnergy - initialEnergy) / (std::abs(itsReference_m.getQ()) * length);
98 
99  element->setAmplitudem(amplitude);
100 
101  int count = 0;
102  while (count < 1000) {
103  initialPhase = guessCavityPhase(t + tErr);
104  auto status = optimizeCavityPhase(initialPhase, t + tErr, dt);
105 
106  optimizedPhase = status.first;
107  finalEnergy = status.second;
108 
109  if (std::abs(designEnergy - finalEnergy) < 1e-7) break;
110 
111  amplitude *= std::abs(designEnergy / finalEnergy);
112  element->setAmplitudem(amplitude);
113  initialPhase = optimizedPhase;
114 
115  ++ count;
116  }
117  }
118  auto status = optimizeCavityPhase(initialPhase, t + tErr, dt);
119 
120  optimizedPhase = status.first;
121  finalEnergy = status.second;
122 
123  AstraPhase = std::fmod(optimizedPhase + Physics::pi / 2 + Physics::two_pi, Physics::two_pi);
124  newPhase = std::fmod(originalPhase + optimizedPhase + Physics::two_pi, Physics::two_pi);
125  element->setPhasem(newPhase);
126  element->setAutophaseVeto();
127  OpalData::getInstance()->setMaxPhase(itsCavity_m->getName(), newPhase);
128 
129  newPhase = std::fmod(newPhase + basePhase, Physics::two_pi);
130 
131  auto opal = OpalData::getInstance();
132  if (!opal->isOptimizerRun()) {
133  std::ofstream out("data/" + itsCavity_m->getName() + "_AP.dat");
134  track(initialR_m, initialP_m, t + tErr, dt, newPhase, &out);
135  out.close();
136  } else {
137  track(initialR_m, initialP_m, t + tErr, dt, newPhase, NULL);
138  }
139 
140  INFOMSG(level1 << std::fixed << std::setprecision(4)
141  << itsCavity_m->getName() << "_phi = " << newPhase * Physics::rad2deg << " [deg], "
142  << "corresp. in Astra = " << AstraPhase * Physics::rad2deg << " [deg],\n"
143  << "E = " << finalEnergy << " [MeV], " << "phi_nom = " << originalPhase * Physics::rad2deg << " [deg]\n"
144  << "Ez_0 = " << amplitude << " [MV/m]" << "\n"
145  << "time = " << (t + tErr) * 1e9 << " [ns], dt = " << dt * 1e12 << " [ps]" << endl);
146 
147  } else {
148  auto status = optimizeCavityPhase(originalPhase, t + tErr, dt);
149 
150  finalEnergy = status.second;
151 
152  originalPhase = std::fmod(originalPhase, Physics::two_pi);
153  double AstraPhase = std::fmod(optimizedPhase + Physics::pi / 2 + Physics::two_pi, Physics::two_pi);
154 
155  if (!isDCGun) {
156  INFOMSG(level1 << ">>>>>> APVETO >>>>>> " << endl);
157  }
158  INFOMSG(level1 << std::fixed << std::setprecision(4)
159  << itsCavity_m->getName() << "_phi = " << originalPhase * Physics::rad2deg << " [deg], "
160  << "corresp. in Astra = " << AstraPhase * Physics::rad2deg << " [deg],\n"
161  << "E = " << finalEnergy << " [MeV], " << "phi_nom = " << originalPhase * Physics::rad2deg << " [deg]\n"
162  << "Ez_0 = " << amplitude << " [MV/m]" << "\n"
163  << "time = " << (t + tErr) * 1e9 << " [ns], dt = " << dt * 1e12 << " [ps]" << endl);
164  if (!isDCGun) {
165  INFOMSG(level1 << " <<<<<< APVETO <<<<<< " << endl);
166  }
167 
168  optimizedPhase = originalPhase;
169  }
170  INFOMSG(level1 << "* " << std::right << std::setw(83) << std::setfill('*') << "*\n"
171  << std::setfill(' ') << endl);
172 
173  return optimizedPhase;
174 }
175 
177  const Vector_t &refP = initialP_m;
178  double Phimax = 0.0;
179  bool apVeto;
180  RFCavity *element = static_cast<RFCavity *>(itsCavity_m.get());
181  double orig_phi = element->getPhasem();
182  apVeto = element->getAutophaseVeto();
183  if (apVeto) {
184  return orig_phi;
185  }
186 
187  Phimax = element->getAutoPhaseEstimate(getEnergyMeV(refP),
188  t,
190  itsReference_m.getM() * 1e-6);
191 
192  return std::fmod(Phimax + Physics::two_pi, Physics::two_pi);
193 }
194 
195 std::pair<double, double> CavityAutophaser::optimizeCavityPhase(double initialPhase,
196  double t,
197  double dt) {
198 
199  RFCavity *element = static_cast<RFCavity *>(itsCavity_m.get());
200  double originalPhase = element->getPhasem();
201 
202  if (element->getAutophaseVeto()) {
203  double basePhase = std::fmod(element->getFrequencym() * t, Physics::two_pi);
204  double phase = std::fmod(originalPhase - basePhase + Physics::two_pi, Physics::two_pi);
205  double E = track(initialR_m, initialP_m, t, dt, phase);
206  std::pair<double, double> status(originalPhase, E);//-basePhase, E);
207  return status;
208  }
209 
210  double Phimax = initialPhase;
211  double phi = initialPhase;
212  double dphi = Physics::pi / 360.0;
213  const int numRefinements = Options::autoPhase;
214 
215  int j = -1;
216  double E = track(initialR_m, initialP_m, t, dt, phi);
217  double Emax = E;
218 
219  do {
220  j ++;
221  Emax = E;
222  initialPhase = phi;
223  phi -= dphi;
224  E = track(initialR_m, initialP_m, t, dt, phi);
225  } while(E > Emax);
226 
227  if(j == 0) {
228  phi = initialPhase;
229  E = Emax;
230  // j = -1;
231  do {
232  // j ++;
233  Emax = E;
234  initialPhase = phi;
235  phi += dphi;
236  E = track(initialR_m, initialP_m, t, dt, phi);
237  } while(E > Emax);
238  }
239 
240  for(int rl = 0; rl < numRefinements; ++ rl) {
241  dphi /= 2.;
242  phi = initialPhase - dphi;
243  E = track(initialR_m, initialP_m, t, dt, phi);
244  if(E > Emax) {
245  initialPhase = phi;
246  Emax = E;
247  } else {
248  phi = initialPhase + dphi;
249  E = track(initialR_m, initialP_m, t, dt, phi);
250  if(E > Emax) {
251  initialPhase = phi;
252  Emax = E;
253  }
254  }
255  }
256  Phimax = std::fmod(initialPhase + Physics::two_pi, Physics::two_pi);
257 
258  E = track(initialR_m, initialP_m, t, dt, Phimax + originalPhase);
259  std::pair<double, double> status(Phimax, E);
260 
261  return status;
262 }
263 
265  Vector_t P,
266  double t,
267  const double dt,
268  const double phase,
269  std::ofstream *out) const {
270  const Vector_t &refP = initialP_m;
271 
272  RFCavity *rfc = static_cast<RFCavity *>(itsCavity_m.get());
273  double initialPhase = rfc->getPhasem();
274  rfc->setPhasem(phase);
275 
276  std::pair<double, double> pe = rfc->trackOnAxisParticle(refP(2),
277  t,
278  dt,
280  itsReference_m.getM() * 1e-6,
281  out);
282  rfc->setPhasem(initialPhase);
283 
284  double finalKineticEnergy = Util::getEnergy(Vector_t(0.0, 0.0, pe.first), itsReference_m.getM() * 1e-6);
285 
286  return finalKineticEnergy;
287 }
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
constexpr double e
The value of .
Definition: Physics.h:40
The base class for all OPAL exceptions.
Definition: OpalException.h:28
constexpr double two_pi
The value of .
Definition: Physics.h:34
virtual double getAmplitudem() const
Definition: RFCavity.h:378
Particle reference data.
Definition: PartData.h:38
Inform * gmsg
Definition: Main.cpp:21
double getPhaseAtMaxEnergy(const Vector_t &R, const Vector_t &P, double t, double dt)
virtual const std::string & getName() const
Get element name.
Definition: ElementBase.cpp:95
virtual void setAmplitudem(double vPeak)
Definition: RFCavity.h:373
virtual double getFrequencym() const
Definition: RFCavity.h:403
virtual bool getAutophaseVeto() const
Definition: RFCavity.h:458
constexpr double rad2deg
The conversion factor from radians to degrees.
Definition: Physics.h:46
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
static OpalData * getInstance()
Definition: OpalData.cpp:209
std::shared_ptr< Component > itsCavity_m
double track(Vector_t R, Vector_t P, double t, const double dt, const double phase, std::ofstream *out=NULL) const
constexpr double pi
The value of .
Definition: Physics.h:31
double getQ() const
The constant charge per particle.
Definition: PartData.h:107
virtual double getPhasem() const
Definition: RFCavity.h:413
double getEnergyMeV(const Vector_t &P)
const PartData & itsReference_m
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
#define INFOMSG(msg)
Definition: IpplInfo.h:397
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
double guessCavityPhase(double t)
int autoPhase
Definition: Options.cpp:45
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
virtual void setAutophaseVeto(bool veto=true)
Definition: RFCavity.h:453
virtual void setPhasem(double phase)
Definition: RFCavity.h:408
Interface for RF cavity.
Definition: RFCavity.h:37
double getM() const
The constant mass per particle.
Definition: PartData.h:112
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
std::pair< double, double > optimizeCavityPhase(double initialGuess, double t, double dt)
double getEnergy(Vector_t p, double mass)
Definition: Util.h:29
virtual std::pair< double, double > trackOnAxisParticle(const double &p0, const double &t0, const double &dt, const double &q, const double &mass, std::ofstream *out=NULL)
Definition: RFCavity.cpp:761
CavityAutophaser(const PartData &ref, std::shared_ptr< Component > cavity)
Definition: Inform.h:41
virtual double getDesignEnergy() const override
Definition: RFCavity.h:352
Inform & level1(Inform &inf)
Definition: Inform.cpp:45
void setMaxPhase(std::string elName, double phi)
Definition: OpalData.cpp:439
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
virtual double getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &m)
Definition: RFCavity.cpp:632