OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
VariableRFCavityFringeField.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014, Chris Rogers
3 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * 1. Redistributions of source code must retain the above copyright notice,
7 * this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright notice,
9 * this list of conditions and the following disclaimer in the documentation
10 * and/or other materials provided with the distribution.
11 * 3. Neither the name of STFC nor the names of its contributors may be used to
12 * endorse or promote products derived from this software without specific
13 * prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
29
33#include "Physics/Physics.h"
34#include "Physics/Units.h"
35
37 initNull(); // initialise everything to nullptr
38}
39
41 initNull(); // initialise everything to nullptr
42}
43
45 initNull(); // initialise everything to nullptr
46 *this = var;
47}
48
50
51 if (&rhs == this) {
52 return *this;
53 }
56 zCentre_m = rhs.zCentre_m;
57 f_m = rhs.f_m;
58 g_m = rhs.f_m;
59 h_m = rhs.f_m;
60 return *this;
61}
62
64}
65
67 return new VariableRFCavityFringeField(*this);
68}
69
72 endField_m = std::shared_ptr<endfieldmodel::EndFieldModel>();
73 zCentre_m = 0;
74 maxOrder_m = 1;
75}
76
80 const_cast<VariableRFCavityFringeField*>(this);
81 cavity->initialiseCoefficients();
82 visitor.visitVariableRFCavity(*this);
83}
84
85bool VariableRFCavityFringeField::apply(const Vector_t &R, const Vector_t &/*P*/, const double &t, Vector_t &E, Vector_t &B) {
86 if (R[2] > _length || R[2] < 0.) {
87 return true;
88 }
89 if (std::abs(R[0]) > halfWidth_m || std::abs(R[1]) > halfHeight_m) {
90 return true;
91 }
92 double z_pos = R[2]-zCentre_m;
93 double E0 = amplitudeTD_m->getValue(t);
94 double omega = Physics::two_pi*frequencyTD_m->getValue(t) * Units::MHz2Hz * Units::Hz2GHz; // need GHz on the element we have MHz
95 double phi = phaseTD_m->getValue(t);
96 double E_sin_t = E0*sin(omega * t + phi);
97 double B_cos_t = E0*cos(omega * t + phi); // 1/c^2 factor in the h_n coefficients
98
99 std::vector<double> y_power(maxOrder_m+1, 0.);
100 y_power[0] = 1.;
101 for (size_t i = 1; i < y_power.size(); ++i) {
102 y_power[i] = y_power[i-1]*R[1];
103 }
104
105 // d^i f0 dz^i
106 std::vector<double> endField(maxOrder_m/2+2, 0.);
107 for (size_t i = 0; i < endField.size(); ++i) {
108 endField[i] = endField_m->function(z_pos, i);
109 }
110
111 // omega^i
112 std::vector<double> omegaPower(maxOrder_m+1, 1.);
113 for (size_t i = 1; i < omegaPower.size(); ++i) {
114 omegaPower[i] = omegaPower[i-1]*omega;
115 }
116
117 E = Vector_t(0., 0., 0.);
118 B = Vector_t(0., 0., 0.);
119 // even power of y
120 //std::cerr << "EVEN POWER OF Y maxOrder: " << maxOrder_m << std::endl;
121 for (size_t n = 0; n <= maxOrder_m ; n += 2) { // power of y
122 double fCoeff = 0.;
123 size_t index = n/2;
124 //std::cerr << "Size i: " << index << " f_m[i]: " << f_m[index].size()
125 // << " endfield: " << endField.size() << std::endl;
126 for (size_t i = 0; i < f_m[index].size() && i < endField.size(); i += 2) { // derivative of f
127 fCoeff += f_m[index][i]*endField[i]*omegaPower[n-i];
128 }
129 E[2] += E_sin_t*y_power[n]*fCoeff;
130 }
131 // odd power of y
132 //std::cerr << "ODD POWER OF Y maxOrder: " << maxOrder_m << std::endl;
133 for (size_t n = 1; n <= maxOrder_m; n += 2) {
134 double gCoeff = 0.;
135 double hCoeff = 0.;
136 size_t index = (n-1)/2;
137 //std::cerr << "Size i: " << index << " g_m[i]: " << g_m[index].size() << " endfield: " << endField.size() << std::endl;
138 for (size_t j = 0; j < g_m[index].size() && j < endField.size(); ++j) {
139 //std::cerr << "g_m " << j << " " << g_m[index][j] << std::endl;
140 //std::cerr << "endfield " << j << " " << endField[j] << std::endl;
141 //std::cerr << "omegaPower " << j << " " << omegaPower[n-j] << std::endl;
142 gCoeff += g_m[index][j]*endField[j]*omegaPower[n-j];
143 }
144 for (size_t j = 0; j < h_m[index].size() && j < endField.size(); ++j) {
145 hCoeff += h_m[index][j]*endField[j]*omegaPower[n-j];
146 //std::cerr << "j: " << j << " " << hCoeff << " ";
147 }
148 //std::cerr << std::endl;
149 E[1] += E_sin_t*y_power[n]*gCoeff;
150 B[0] += B_cos_t*y_power[n]*hCoeff;
151 //std::cerr << "APPLY B " << n << " " << B[0] << " " << hCoeff << std::endl;
152 }
153 B *= Units::T2kG;
154 return false;
155}
156
157bool VariableRFCavityFringeField::apply(const size_t &i, const double &t,
158 Vector_t &E, Vector_t &B) {
159 return apply(RefPartBunch_m->R[i], RefPartBunch_m->P[i], t, E, B);
160}
161
163 const Vector_t &P,
164 const double &t,
165 Vector_t &E,
166 Vector_t &B) {
167 return apply(R, P, t, E, B);
168}
169
171 double &startField,
172 double &endField) {
173 VariableRFCavity::initialise(bunch, startField, endField);
175}
176
177void printVector(std::ostream& out, std::vector< std::vector<double> > vec) {
178 for (size_t i = 0; i < vec.size(); ++i) {
179 out << std::setw(3) << i;
180 for (size_t j = 0; j < vec[i].size(); ++j) {
181 out << " " << std::setw(14) << vec[i][j];
182 }
183 out << std::endl;
184 }
185}
186
188 f_m = std::vector< std::vector<double> >();
189 g_m = std::vector< std::vector<double> >();
190 h_m = std::vector< std::vector<double> >();
191 f_m.push_back(std::vector<double>(1, 1.));
192 double c_l = Physics::c * Units::m2mm / Units::s2ns;
193 // generate f_{n+2} term
194 // note frequency term has to be added at apply(time) as we have
195 // time-dependent frequency
196 for(size_t n = 0; n+2 <= maxOrder_m; n += 2) {
197 // n denotes the subscript on f_n
198 // n+2 is the subscript on g_{n+2} and terms proportional to y^{n+2}
199 std::vector<double> f_n = f_m.back(); // f_n
200 std::vector<double> f_np2 = std::vector<double>(f_n.size()+2, 0.); // f_{n+2}
201 double n_const = 1./(n+1.)/(n+2.);
202 for (size_t j = 0; j < f_n.size(); ++j) {
203 f_np2[j] -= f_n[j]*n_const/c_l/c_l;
204 }
205 for (size_t j = 0; j < f_n.size(); ++j) {
206 f_np2[j+2] -= f_n[j]*n_const;
207 }
208 f_m.push_back(f_np2);
209 }
210 // generate g_{n+2} and h_{n+2} term
211 for(size_t n = 0; n+1 <= maxOrder_m; n += 2) {
212 // n denotes the subscript on f_n
213 // n+1 is the subscript on g_{n+1} and terms proportional to y^{n+1}
214 size_t f_index = n/2;
215 std::vector<double> f_n = f_m[f_index];
216 std::vector<double> g_np1 = std::vector<double>(f_n.size()+1, 0.);
217 std::vector<double> h_np1 = std::vector<double>(f_n.size(), 0.);
218 for (size_t j = 0; j < f_n.size(); ++j) {
219 g_np1[j+1] = -1./(n+1.)*f_n[j];
220 h_np1[j] = -1./c_l/c_l/(n+1.)*f_n[j];
221 }
222 g_m.push_back(g_np1);
223 h_m.push_back(h_np1);
224 }
225}
226
228 out << "f_m" << std::endl;
229 printVector(out, f_m);
230 out << "g_m" << std::endl;
231 printVector(out, g_m);
232 out << "h_m" << std::endl;
233 printVector(out, h_m);
234 out << std::endl;
235}
236
238 std::shared_ptr<endfieldmodel::EndFieldModel> end) {
239 endField_m = end;
240}
void printVector(std::ostream &out, std::vector< std::vector< double > > vec)
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
const std::string name
constexpr double two_pi
The value of.
Definition: Physics.h:33
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
constexpr double m2mm
Definition: Units.h:26
constexpr double MHz2Hz
Definition: Units.h:113
constexpr double T2kG
Definition: Units.h:56
constexpr double Hz2GHz
Definition: Units.h:122
constexpr double s2ns
Definition: Units.h:44
ParticlePos_t & R
ParticleAttrib< Vector_t > P
virtual void visitVariableRFCavity(const VariableRFCavity &)=0
Apply the algorithm to a variable RF cavity.
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
std::shared_ptr< AbstractTimeDependence > frequencyTD_m
void initialise() const
std::shared_ptr< AbstractTimeDependence > amplitudeTD_m
std::shared_ptr< AbstractTimeDependence > phaseTD_m
VariableRFCavity & operator=(const VariableRFCavity &)
std::shared_ptr< endfieldmodel::EndFieldModel > endField_m
std::vector< std::vector< double > > f_m
VariableRFCavityFringeField & operator=(const VariableRFCavityFringeField &)
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
std::vector< std::vector< double > > h_m
std::vector< std::vector< double > > g_m
void printCoefficients(std::ostream &out) const
virtual void accept(BeamlineVisitor &) const override
virtual ElementBase * clone() const override
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
virtual void setEndField(std::shared_ptr< endfieldmodel::EndFieldModel > endField)
Definition: Vec.h:22
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6