2 #include <boost/numeric/ublas/lu.hpp>
4 #include "flame/constants.h"
5 #include "flame/moment.h"
7 #define sqr(x) ((x)*(x))
8 #define cube(x) ((x)*(x)*(x))
12 void inverse(MomentElementBase::value_t& out,
const MomentElementBase::value_t& in)
14 using boost::numeric::ublas::permutation_matrix;
15 using boost::numeric::ublas::lu_factorize;
16 using boost::numeric::ublas::lu_substitute;
17 using boost::numeric::ublas::identity_matrix;
19 MomentElementBase::value_t scratch(in);
20 permutation_matrix<size_t> pm(scratch.size1());
21 if(lu_factorize(scratch, pm)!=0)
22 throw std::runtime_error(
"Failed to invert matrix");
23 out.assign(identity_matrix<double>(scratch.size1()));
25 lu_substitute(scratch, pm, out);
28 void RotMat(
const double dx,
const double dy,
29 const double theta_x,
const double theta_y,
const double theta_z,
30 typename MomentElementBase::value_t &R)
34 MomentState::matrix_t T = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
36 R = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
40 double m11 = cos(-theta_y)*cos(theta_z),
41 m12 = sin(theta_x)*sin(-theta_y)*cos(theta_z) + cos(theta_x)*sin(theta_z),
42 m13 = -cos(theta_x)*sin(-theta_y)*cos(theta_z) + sin(theta_x)*sin(theta_z),
44 m21 = -cos(-theta_y)*sin(theta_z),
45 m22 = -sin(theta_x)*sin(-theta_y)*sin(theta_z) + cos(theta_x)*cos(theta_z),
46 m23 = cos(theta_x)*sin(-theta_y)*sin(theta_z) + sin(theta_x)*cos(theta_z),
49 m32 = -sin(theta_x)*cos(-theta_y),
50 m33 = cos(theta_x)*cos(-theta_y);
52 R(0, 0) = m11, R(0, 2) = m12, R(0, 4) = m13;
53 R(2, 0) = m21, R(2, 2) = m22, R(2, 4) = m23;
54 R(4, 0) = m31, R(4, 2) = m32, R(4, 4) = m33;
56 R(1, 1) = m11, R(1, 3) = m12, R(1, 5) = m13;
57 R(3, 1) = m21, R(3, 3) = m22, R(3, 5) = m23;
58 R(5, 1) = m31, R(5, 3) = m32, R(5, 5) = m33;
60 T(0, 6) = -dx, T(2, 6) = -dy;
66 void GetQuadMatrix(
const double L,
const double K,
const unsigned ind,
typename MomentElementBase::value_t &M)
81 M(ind, ind) = M(ind+1, ind+1) = cs;
83 M(ind, ind+1) = sn/sqrtK;
87 M(ind+1, ind) = -sqrtK*sn;
97 M(ind, ind) = M(ind+1, ind+1) = cs;
99 M(ind, ind+1) = sn/sqrtK;
103 M(ind+1, ind) = sqrtK*sn;
110 void GetEdgeMatrix(
const double rho,
const double phi,
typename MomentElementBase::value_t &M)
114 M = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
116 M(state_t::PS_PX, state_t::PS_X) = tan(phi)/rho;
117 M(state_t::PS_PY, state_t::PS_Y) = -tan(phi)/rho;
121 void GetEEdgeMatrix(
const double fringe_x,
const double fringe_y,
const double kappa,
typename MomentElementBase::value_t &M)
126 M = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
128 M(state_t::PS_PX, state_t::PS_X) = fringe_x;
129 M(state_t::PS_PX, state_t::PS_PX) = sqrt(1e0+kappa);
130 M(state_t::PS_PY, state_t::PS_Y) = fringe_y;
131 M(state_t::PS_PS, state_t::PS_PS) = 1e0+kappa;
135 void GetSBendMatrix(
const double L,
const double phi,
const double phi1,
const double phi2,
const double K,
136 const double IonEs,
const double ref_gamma,
const double qmrel,
137 const double dip_beta,
const double dip_gamma,
const double d,
const double dip_IonK,
typename MomentElementBase::value_t &M)
141 MomentState::matrix_t edge1, edge2, R;
144 Kx = K + 1e0/sqr(rho),
150 GetQuadMatrix(L, Kx, (
unsigned)state_t::PS_X, M);
152 GetQuadMatrix(L, Ky, (
unsigned)state_t::PS_Y, M);
156 dx = sqr(L)/(2e0*rho);
158 }
else if (Kx > 0e0) {
159 dx = (1e0-cos(sqrt(Kx)*L))/(rho*Kx);
160 sx = sin(sqrt(Kx)*L)/(rho*sqrt(Kx));
162 dx = (1e0-cosh(sqrt(-Kx)*L))/(rho*Kx);
163 sx = sin(sqrt(Kx)*L)/(rho*sqrt(Kx));
166 M(state_t::PS_X, state_t::PS_PS) = dx/(sqr(dip_beta)*dip_gamma*IonEs/MeVtoeV);
167 M(state_t::PS_PX, state_t::PS_PS) = sx/(sqr(dip_beta)*dip_gamma*IonEs/MeVtoeV);
169 M(state_t::PS_S, state_t::PS_X) = sx*dip_IonK;
170 M(state_t::PS_S, state_t::PS_PX) = dx*dip_IonK;
172 M(state_t::PS_S, state_t::PS_PS) =
173 ((L/rho-sx)/(Kx*rho)-L/sqr(ref_gamma))*dip_IonK
174 /(sqr(dip_beta)*dip_gamma*IonEs/MeVtoeV);
177 M(state_t::PS_S, 6) = ((L/rho-sx)/(Kx*rho)*d-L/sqr(ref_gamma)*(d+qmrel))*dip_IonK;
178 M(state_t::PS_X, 6) = dx*d;
179 M(state_t::PS_PX, 6) = sx*d;
182 GetEdgeMatrix(rho, phi1, edge1);
183 GetEdgeMatrix(rho, phi2, edge2);
194 void GetSolMatrix(
const double L,
const double K,
typename MomentElementBase::value_t &M)
198 double C = ::cos(K*L),
201 M(state_t::PS_X, state_t::PS_X)
202 = M(state_t::PS_PX, state_t::PS_PX)
203 = M(state_t::PS_Y, state_t::PS_Y)
204 = M(state_t::PS_PY, state_t::PS_PY)
208 M(state_t::PS_X, state_t::PS_PX) = S*C/K;
210 M(state_t::PS_X, state_t::PS_PX) = L;
211 M(state_t::PS_X, state_t::PS_Y) = S*C;
213 M(state_t::PS_X, state_t::PS_PY) = sqr(S)/K;
215 M(state_t::PS_X, state_t::PS_PY) = 0e0;
217 M(state_t::PS_PX, state_t::PS_X) = -K*S*C;
218 M(state_t::PS_PX, state_t::PS_Y) = -K*sqr(S);
219 M(state_t::PS_PX, state_t::PS_PY) = S*C;
221 M(state_t::PS_Y, state_t::PS_X) = -S*C;
223 M(state_t::PS_Y, state_t::PS_PX) = -sqr(S)/K;
225 M(state_t::PS_Y, state_t::PS_PX) = 0e0;
227 M(state_t::PS_Y, state_t::PS_PY) = S*C/K;
229 M(state_t::PS_Y, state_t::PS_PY) = L;
231 M(state_t::PS_PY, state_t::PS_X) = K*sqr(S);
232 M(state_t::PS_PY, state_t::PS_PX) = -S*C;
233 M(state_t::PS_PY, state_t::PS_Y) = -K*S*C;
241 void GetEBendMatrix(
const double L,
const double phi,
const double fringe_x,
const double fringe_y,
const double kappa,
const double Kx,
const double Ky,
242 const double IonEs,
const double ref_beta,
const double real_gamma,
const double eta0,
const double h,
243 const double dip_beta,
const double dip_gamma,
const double delta_KZ,
const double SampleIonK,
typename MomentElementBase::value_t &M)
247 MomentState::matrix_t edge;
250 scl = (real_gamma - 1e0)*IonEs/MeVtoeV,
255 GetQuadMatrix(L, Kx, (
unsigned)state_t::PS_X, M);
257 GetQuadMatrix(L, Ky, (
unsigned)state_t::PS_Y, M);
263 }
else if (Kx > 0e0) {
264 dx = (1e0-cos(sqrt(Kx)*L))/(rho*Kx);
265 sx = sin(sqrt(Kx)*L)/sqrt(Kx);
267 dx = (1e0-cosh(sqrt(-Kx)*L))/(rho*Kx);
268 sx = sin(sqrt(Kx)*L)/sqrt(Kx);
271 double Nk = (sqr(1e0+2e0*eta0)+h)/(2e0*(1e0+eta0)*(1e0+2e0*eta0)),
272 Nt = 1e0 + h/sqr(1e0+2e0*eta0),
273 CorT = -real_gamma/(1e0+real_gamma),
276 tzp = (-L/(2e0*(1e0+eta0)*(1e0+2e0*eta0))+((L-sx)/Kx/sqr(rho))*Nk*Nt)*CorT;
278 M(state_t::PS_X, state_t::PS_PS) = dx*Nk/scl;
279 M(state_t::PS_PX, state_t::PS_PS) = sx/rho*Nk/scl;
281 M(state_t::PS_S, state_t::PS_X) = -tx*SampleIonK;
282 M(state_t::PS_S, state_t::PS_PX) = -txp*SampleIonK;
284 M(state_t::PS_S, state_t::PS_PS) = -tzp*SampleIonK/scl;
287 double delta_K = sqr(ref_beta/dip_beta) - 1e0;
292 double Nkz = (1e0+2e0*eta0-h)/(2e0*(1e0+eta0)*(1e0+2e0*eta0));
293 M(state_t::PS_X, 6) = dx*(Nk*delta_K+Nkz*delta_KZ);
294 M(state_t::PS_PX, 6) = sx/rho*(Nk*delta_K+Nkz*delta_KZ);
297 GetEEdgeMatrix(fringe_x, fringe_y ,kappa, edge);