OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
CavityAutophaser.cpp
Go to the documentation of this file.
1//
2// Class CavityAutophaser
3//
4// This class determines the phase of an RF cavity for which the reference particle
5// is accelerated to the highest energy.
6//
7// Copyright (c) 2016, Christof Metzger-Kraus, Helmholtz-Zentrum Berlin, Germany
8// 2017 - 2020 Christof Metzger-Kraus
9//
10// All rights reserved
11//
12// This file is part of OPAL.
13//
14// OPAL is free software: you can redistribute it and/or modify
15// it under the terms of the GNU General Public License as published by
16// the Free Software Foundation, either version 3 of the License, or
17// (at your option) any later version.
18//
19// You should have received a copy of the GNU General Public License
20// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
21//
22#include "Ippl.h"
23#include "OPALTypes.h"
24
29//
30#include "Physics/Units.h"
32#include "Utilities/Options.h"
33#include "Utilities/Util.h"
34
35#include <fstream>
36#include <iostream>
37#include <string>
38
39extern Inform* gmsg;
40
41CavityAutophaser::CavityAutophaser(const PartData& ref, std::shared_ptr<Component> cavity)
42 : itsReference_m(ref), itsCavity_m(cavity) {
43 double zbegin = 0.0, zend = 0.0;
44 cavity->getFieldExtend(zbegin, zend);
45 initialR_m = Vector_t<double, 3>(0, 0, zbegin);
46}
47
49
51 const Vector_t<double, 3>& R, const Vector_t<double, 3>& P, double t, double dt) {
52 if (!(itsCavity_m->getType() == ElementType::TRAVELINGWAVE
53 || itsCavity_m->getType() == ElementType::RFCAVITY)) {
54 throw OpalException(
55 "CavityAutophaser::getPhaseAtMaxEnergy()", "given element is not a cavity");
56 }
57
58 initialP_m = P; // \todo need to check ... Vector_t<double, 3>(0, 0, std::sqrt(dot(P, P)));
59
60 RFCavity* element = static_cast<RFCavity*>(itsCavity_m.get());
61 bool apVeto = element->getAutophaseVeto();
62 bool isDCGun = false;
63 double originalPhase = element->getPhasem();
64 double tErr = (initialR_m(2) - R(2)) * std::sqrt(dot(P, P) + 1.0) / (P(2) * Physics::c);
65 double optimizedPhase = 0.0;
66 double finalEnergy = 0.0;
67 double newPhase = 0.0;
68 double amplitude = element->getAmplitudem();
69 double basePhase = std::fmod(element->getFrequencym() * (t + tErr), Physics::two_pi);
70 double frequency = element->getFrequencym();
71
72 if ((!apVeto) && frequency <= (1.0 + 1e-6) * Physics::two_pi) { // DC gun
73 optimizedPhase = (amplitude * itsReference_m.getQ() > 0.0 ? 0.0 : Physics::pi);
74 element->setPhasem(optimizedPhase + originalPhase);
75 element->setAutophaseVeto();
76
77 originalPhase += optimizedPhase;
78 OpalData::getInstance()->setMaxPhase(itsCavity_m->getName(), originalPhase);
79
80 apVeto = true;
81 isDCGun = true;
82 }
83
84 std::stringstream ss;
85 for (char c : itsCavity_m->getName()) {
86 ss << std::setw(2) << std::left << c;
87 }
88 *ippl::Info << level1 << "\n* ************* " << std::left << std::setw(68) << std::setfill('*')
89 << ss.str() << std::setfill(' ') << endl;
90 if (!apVeto) {
91 double initialEnergy = Util::getKineticEnergy(P, itsReference_m.getM()) * Units::eV2MeV;
92 double AstraPhase = 0.0;
93 double designEnergy = element->getDesignEnergy();
94
95 if (amplitude < 0.0) {
96 amplitude = -amplitude;
97 element->setAmplitudem(amplitude);
98 }
99
100 double initialPhase = guessCavityPhase(t + tErr);
101
102 if (amplitude == 0.0 && designEnergy <= 0.0) {
103 throw OpalException(
104 "CavityAutophaser::getPhaseAtMaxEnergy()",
105 "neither amplitude or design energy given to cavity " + element->getName());
106 }
107
108 if (designEnergy > 0.0) {
109 const double length = itsCavity_m->getElementLength();
110 if (length <= 0.0) {
111 throw OpalException(
112 "CavityAutophaser::getPhaseAtMaxEnergy()",
113 "length of cavity " + element->getName() + " is zero");
114 }
115
116 amplitude =
117 2 * (designEnergy - initialEnergy) / (std::abs(itsReference_m.getQ()) * length);
118
119 element->setAmplitudem(amplitude);
120
121 int count = 0;
122 while (count < 1000) {
123 initialPhase = guessCavityPhase(t + tErr);
124 auto status = optimizeCavityPhase(initialPhase, t + tErr, dt);
125
126 optimizedPhase = status.first;
127 finalEnergy = status.second;
128
129 if (std::abs(designEnergy - finalEnergy) < 1e-7) break;
130
131 amplitude *= std::abs(designEnergy / finalEnergy);
132 element->setAmplitudem(amplitude);
133 initialPhase = optimizedPhase;
134
135 ++count;
136 }
137 }
138
139 auto status = optimizeCavityPhase(initialPhase, t + tErr, dt);
140
141 optimizedPhase = status.first;
142 finalEnergy = status.second;
143
144 AstraPhase = std::fmod(optimizedPhase + Physics::pi / 2 + Physics::two_pi, Physics::two_pi);
145 newPhase = std::fmod(originalPhase + optimizedPhase + Physics::two_pi, Physics::two_pi);
146 element->setPhasem(newPhase);
147 element->setAutophaseVeto();
148
149 auto opal = OpalData::getInstance();
150
151 opal->setMaxPhase(itsCavity_m->getName(), newPhase);
152
153 newPhase = std::fmod(newPhase + basePhase, Physics::two_pi);
154
155 if (!opal->isOptimizerRun()) {
156 std::string fname = Util::combineFilePath(
157 {opal->getAuxiliaryOutputDirectory(), itsCavity_m->getName() + "_AP.dat"});
158 std::ofstream out(fname);
159 track(t + tErr, dt, newPhase, &out);
160 out.close();
161 } else {
162 track(t + tErr, dt, newPhase, nullptr);
163 }
164
165 *ippl::Info << level1 << std::fixed << std::setprecision(4) << itsCavity_m->getName()
166 << "_phi1 = " << newPhase * Units::rad2deg << " [deg], "
167 << "corresp. in Astra = " << AstraPhase * Units::rad2deg << " [deg],\n"
168 << "E = " << finalEnergy << " [MeV], "
169 << "phi_nom = " << originalPhase * Units::rad2deg << " [deg]\n"
170 << "Ez_0 = " << amplitude << " [MV/m]"
171 << "\n"
172 << "time = " << (t + tErr) * Units::s2ns << " [ns], dt = " << dt * Units::s2ps
173 << " [ps]" << endl;
174
175 } else {
176 auto status = optimizeCavityPhase(originalPhase, t + tErr, dt);
177
178 finalEnergy = status.second;
179
180 originalPhase = std::fmod(originalPhase, Physics::two_pi);
181 double AstraPhase =
182 std::fmod(optimizedPhase + Physics::pi / 2 + Physics::two_pi, Physics::two_pi);
183
184 if (!isDCGun) {
185 *ippl::Info << level1 << ">>>>>> APVETO >>>>>> " << endl;
186 }
187 *ippl::Info << level1 << std::fixed << std::setprecision(4) << itsCavity_m->getName()
188 << "_phi2 = " << originalPhase * Units::rad2deg << " [deg], "
189 << "corresp. in Astra = " << AstraPhase * Units::rad2deg << " [deg],\n"
190 << "E = " << finalEnergy << " [MeV], "
191 << "phi_nom = " << originalPhase * Units::rad2deg << " [deg]\n"
192 << "Ez_0 = " << amplitude << " [MV/m]"
193 << "\n"
194 << "time = " << (t + tErr) * Units::s2ns << " [ns], dt = " << dt * Units::s2ps
195 << " [ps]" << endl;
196 if (!isDCGun) {
197 *ippl::Info << level1 << " <<<<<< APVETO <<<<<< " << endl;
198 }
199
200 optimizedPhase = originalPhase;
201 }
202 *ippl::Info << level1 << "* " << std::right << std::setw(83) << std::setfill('*') << "*\n"
203 << std::setfill(' ') << endl;
204
205 return optimizedPhase;
206}
207
209 const Vector_t<double, 3>& refP = initialP_m;
210 double Phimax = 0.0;
211 bool apVeto;
212 RFCavity* element = static_cast<RFCavity*>(itsCavity_m.get());
213 double orig_phi = element->getPhasem();
214 apVeto = element->getAutophaseVeto();
215 if (apVeto) {
216 return orig_phi;
217 }
218
219 Phimax = element->getAutoPhaseEstimate(
222
223 return std::fmod(Phimax + Physics::two_pi, Physics::two_pi);
224}
225
227 double initialPhase, double t, double dt) {
228 RFCavity* element = static_cast<RFCavity*>(itsCavity_m.get());
229 double originalPhase = element->getPhasem();
230
231 if (element->getAutophaseVeto()) {
232 double basePhase = std::fmod(element->getFrequencym() * t, Physics::two_pi);
233 double phase = std::fmod(originalPhase - basePhase + Physics::two_pi, Physics::two_pi);
234 double E = track(t, dt, phase);
235 std::pair<double, double> status(originalPhase, E); //-basePhase, E);
236 return status;
237 }
238
239 double Phimax = initialPhase;
240 double phi = initialPhase;
241 double dphi = Physics::pi / 360.0;
242 const int numRefinements = Options::autoPhase;
243 int j = -1;
244
245 double E = track(t, dt, phi);
246 double Emax = E;
247
248 do {
249 j++;
250 Emax = E;
251 initialPhase = phi;
252 phi -= dphi;
253 E = track(t, dt, phi);
254 } while (E > Emax);
255
256 if (j == 0) {
257 phi = initialPhase;
258 E = Emax;
259 // j = -1;
260 do {
261 // j ++;
262 Emax = E;
263 initialPhase = phi;
264 phi += dphi;
265 E = track(t, dt, phi);
266 } while (E > Emax);
267 }
268
269 for (int rl = 0; rl < numRefinements; ++rl) {
270 dphi /= 2.;
271 phi = initialPhase - dphi;
272 E = track(t, dt, phi);
273 if (E > Emax) {
274 initialPhase = phi;
275 Emax = E;
276 } else {
277 phi = initialPhase + dphi;
278 E = track(t, dt, phi);
279 if (E > Emax) {
280 initialPhase = phi;
281 Emax = E;
282 }
283 }
284 }
285 Phimax = std::fmod(initialPhase + Physics::two_pi, Physics::two_pi);
286 E = track(t, dt, Phimax + originalPhase);
287 std::pair<double, double> status(Phimax, E);
288
289 return status;
290}
291
293 double t, const double dt, const double phase, std::ofstream* out) const {
294 const Vector_t<double, 3>& refP = initialP_m;
295
296 RFCavity* rfc = static_cast<RFCavity*>(itsCavity_m.get());
297 double initialPhase = rfc->getPhasem();
298 rfc->setPhasem(phase);
299
300 std::pair<double, double> pe = rfc->trackOnAxisParticle(
301 refP(2), t, dt, itsReference_m.getQ(), itsReference_m.getM() * Units::eV2MeV, out);
302 rfc->setPhasem(initialPhase);
303
304 double finalKineticEnergy = Util::getKineticEnergy(
305 Vector_t<double, 3>(0.0, 0.0, pe.first), itsReference_m.getM() * Units::eV2MeV);
306 return finalKineticEnergy;
307}
Inform * gmsg
Definition changes.cpp:7
ippl::Vector< T, Dim > Vector_t
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition Vector3D.cpp:95
Vector_t< double, 3 > initialR_m
double getPhaseAtMaxEnergy(const Vector_t< double, 3 > &R, const Vector_t< double, 3 > &P, double t, double dt)
double track(double t, const double dt, const double phase, std::ofstream *out=nullptr) const
const PartData & itsReference_m
double guessCavityPhase(double t)
std::pair< double, double > optimizeCavityPhase(double initialGuess, double t, double dt)
Vector_t< double, 3 > initialP_m
std::shared_ptr< Component > itsCavity_m
CavityAutophaser(const PartData &ref, std::shared_ptr< Component > cavity)
virtual const std::string & getName() const
Get element name.
void setMaxPhase(std::string elName, double phi)
Definition OpalData.cpp:323
static OpalData * getInstance()
Definition OpalData.cpp:193
Particle reference data.
Definition PartData.h:37
KOKKOS_INLINE_FUNCTION double getM() const
The constant mass per particle.
Definition PartData.h:109
KOKKOS_INLINE_FUNCTION double getQ() const
The constant charge per particle.
Definition PartData.h:107
Interface for standing wave cavities.
Definition RFCavity.h:34
virtual double getPhasem() const
Definition RFCavity.h:345
virtual double getAmplitudem() const
Definition RFCavity.h:331
virtual bool getAutophaseVeto() const
Definition RFCavity.h:361
virtual void setAmplitudem(double vPeak)
Definition RFCavity.h:329
virtual std::pair< double, double > trackOnAxisParticle(const double &p0, const double &t0, const double &dt, const double &q, const double &mass, std::ofstream *out=nullptr)
Definition RFCavity.cpp:659
virtual void setPhasem(double phase)
Definition RFCavity.h:343
virtual double getFrequencym() const
Definition RFCavity.h:341
virtual void setAutophaseVeto(bool veto=true)
Definition RFCavity.h:359
virtual double getAutoPhaseEstimate(const double &E0, const double &t0, const double &q, const double &m)
Definition RFCavity.cpp:524
virtual double getDesignEnergy() const override
Definition RFCavity.h:323
int autoPhase
Definition Options.cpp:71
constexpr double two_pi
The value of.
Definition Physics.h:40
constexpr double c
The velocity of light in m/s.
Definition Physics.h:60
constexpr double pi
The value of.
Definition Physics.h:36
constexpr double s2ps
Definition Units.h:50
constexpr double eV2MeV
Definition Units.h:77
constexpr double rad2deg
Definition Units.h:146
constexpr double s2ns
Definition Units.h:44
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition Util.cpp:193
double getKineticEnergy(ippl::Vector< double, 3 > p, double mass)
Definition Util.h:53