FLAME  devel
 All Classes Functions Variables Typedefs Enumerations Pages
moment_sup.cpp
1 
2 #include <boost/lexical_cast.hpp>
3 #include <boost/filesystem.hpp>
4 #include <boost/numeric/ublas/lu.hpp>
5 
6 #include "flame/constants.h"
7 #include "flame/moment.h"
8 
9 #define sqr(x) ((x)*(x))
10 #define cube(x) ((x)*(x)*(x))
11 
12 #ifdef DEFPATH
13  #define defpath DEFPATH
14 #else
15  #define defpath "."
16 #endif
17 
18 std::map<std::string,boost::shared_ptr<Config> > CurveMap;
19 
20 // http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?LU_Matrix_Inversion
21 // by LU-decomposition.
22 void inverse(MomentElementBase::value_t& out, const MomentElementBase::value_t& in)
23 {
24  using boost::numeric::ublas::permutation_matrix;
25  using boost::numeric::ublas::lu_factorize;
26  using boost::numeric::ublas::lu_substitute;
27  using boost::numeric::ublas::identity_matrix;
28 
29  MomentElementBase::value_t scratch(in); // copy
30  permutation_matrix<size_t> pm(scratch.size1());
31  if(lu_factorize(scratch, pm)!=0)
32  throw std::runtime_error("Failed to invert matrix");
33  out.assign(identity_matrix<double>(scratch.size1()));
34  //out = identity_matrix<double>(scratch.size1());
35  lu_substitute(scratch, pm, out);
36 }
37 
38 void RotMat(const double dx, const double dy,
39  const double theta_x, const double theta_y, const double theta_z,
40  typename MomentElementBase::value_t &R)
41 {
42  typedef typename MomentElementBase::state_t state_t;
43 
44  MomentState::matrix_t T = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
45 
46  R = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
47 
48  // Left-handed coordinate system => theta_y -> -theta_y.
49 
50  double m11 = cos(-theta_y)*cos(theta_z),
51  m12 = sin(theta_x)*sin(-theta_y)*cos(theta_z) + cos(theta_x)*sin(theta_z),
52  m13 = -cos(theta_x)*sin(-theta_y)*cos(theta_z) + sin(theta_x)*sin(theta_z),
53 
54  m21 = -cos(-theta_y)*sin(theta_z),
55  m22 = -sin(theta_x)*sin(-theta_y)*sin(theta_z) + cos(theta_x)*cos(theta_z),
56  m23 = cos(theta_x)*sin(-theta_y)*sin(theta_z) + sin(theta_x)*cos(theta_z),
57 
58  m31 = sin(-theta_y),
59  m32 = -sin(theta_x)*cos(-theta_y),
60  m33 = cos(theta_x)*cos(-theta_y);
61 
62  R(0, 0) = m11, R(0, 2) = m12, R(0, 4) = m13;
63  R(2, 0) = m21, R(2, 2) = m22, R(2, 4) = m23;
64  R(4, 0) = m31, R(4, 2) = m32, R(4, 4) = m33;
65 
66  R(1, 1) = m11, R(1, 3) = m12, R(1, 5) = m13;
67  R(3, 1) = m21, R(3, 3) = m22, R(3, 5) = m23;
68  R(5, 1) = m31, R(5, 3) = m32, R(5, 5) = m33;
69 
70  T(0, 6) = -dx, T(2, 6) = -dy;
71 
72  R = prod(R, T);
73 }
74 
75 
76 void GetQuadMatrix(const double L, const double K, const unsigned ind, typename MomentElementBase::value_t &M)
77 {
78  // 2D quadrupole transport matrix.
79  double sqrtK,
80  psi,
81  cs,
82  sn;
83 
84  if (K > 0e0) {
85  // Focusing.
86  sqrtK = sqrt(K);
87  psi = sqrtK*L;
88  cs = ::cos(psi);
89  sn = ::sin(psi);
90 
91  M(ind, ind) = M(ind+1, ind+1) = cs;
92  if (sqrtK != 0e0)
93  M(ind, ind+1) = sn/sqrtK;
94  else
95  M(ind, ind+1) = L;
96  if (sqrtK != 0e0)
97  M(ind+1, ind) = -sqrtK*sn;
98  else
99  M(ind+1, ind) = 0e0;
100  } else {
101  // Defocusing.
102  sqrtK = sqrt(-K);
103  psi = sqrtK*L;
104  cs = ::cosh(psi);
105  sn = ::sinh(psi);
106 
107  M(ind, ind) = M(ind+1, ind+1) = cs;
108  if (sqrtK != 0e0)
109  M(ind, ind+1) = sn/sqrtK;
110  else
111  M(ind, ind+1) = L;
112  if (sqrtK != 0e0)
113  M(ind+1, ind) = sqrtK*sn;
114  else
115  M(ind+1, ind) = 0e0;
116  }
117 }
118 
119 void GetSextMatrix(const double L, const double K3, double Dx, double Dy,
120  const double D2x, const double D2y, const double D2xy, const bool thinlens, const bool dstkick, typename MomentElementBase::value_t &M)
121 {
122  typedef typename MomentElementBase::state_t state_t;
123  // 2D sextupole transport matrix.
124  double sqrtK, psi, cs, sn, ch, sh,
125  dr = sqrt(sqr(Dx)+sqr(Dx));
126 
127  if (thinlens) {
128 
129  //thin-lens (drift-kick-drift) model
130 
131  MomentState::matrix_t T = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
132  MomentState::matrix_t P = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
133  MomentState::matrix_t scratch;
134 
135  T(state_t::PS_X, state_t::PS_PX) = L/2e0;
136  T(state_t::PS_Y, state_t::PS_PY) = L/2e0;
137 
138  P(state_t::PS_PX, state_t::PS_X) = -K3*L*Dx;
139  P(state_t::PS_PX, state_t::PS_Y) = K3*L*Dy;
140 
141  P(state_t::PS_PY, state_t::PS_X) = K3*L*Dy;
142  P(state_t::PS_PY, state_t::PS_Y) = K3*L*Dx;
143 
144  scratch = prod(P,T);
145  M = prod(T,scratch);
146 
147  } else {
148 
149  //thick-lens model
150 
151  sqrtK = sqrt(fabs(K3)*dr);
152  psi = sqrtK*L;
153 
154  // Focusing or Defocusing switch
155  Dx *= copysign(1e0,K3);
156  Dy *= copysign(1e0,K3);
157 
158  cs = ::cos(psi);
159  sn = ::sin(psi);
160  ch = ::cosh(psi);
161  sh = ::sinh(psi);
162 
163 
164  if (sqrtK != 0e0) {
165  M(state_t::PS_X, state_t::PS_X) = M(state_t::PS_PX, state_t::PS_PX) = ((dr+Dx)*cs+(dr-Dx)*ch)/(2e0*dr);
166  M(state_t::PS_X, state_t::PS_PX) = ((dr+Dx)*sn+(dr-Dx)*sh)/(2e0*sqrtK*dr);
167  M(state_t::PS_X, state_t::PS_Y) = M(state_t::PS_PX, state_t::PS_PY) =
168  M(state_t::PS_Y, state_t::PS_X) = M(state_t::PS_PY, state_t::PS_PX) = Dy*(-cs+ch)/(2e0*dr);
169  M(state_t::PS_X, state_t::PS_PY) = Dy*(-sn+sh)/(2e0*sqrtK*dr);
170 
171  M(state_t::PS_PX, state_t::PS_X) = sqrtK*(-(dr+Dx)*sn+(dr-Dx)*sh)/(2e0*dr);
172  M(state_t::PS_PX, state_t::PS_Y) = M(state_t::PS_PY, state_t::PS_X) = Dy*sqrtK*(sn+sh)/(2e0*dr);
173 
174  M(state_t::PS_Y, state_t::PS_PX) = Dy*(-sn+sh)/(2e0*sqrtK*dr);
175  M(state_t::PS_Y, state_t::PS_Y) = M(state_t::PS_PY, state_t::PS_PY) = ((dr-Dx)*cs+(dr+Dx)*ch)/(2e0*dr);
176  M(state_t::PS_Y, state_t::PS_PY) = ((dr-Dx)*sn+(dr+Dx)*sh)/(2e0*sqrtK*dr);
177 
178  M(state_t::PS_PY, state_t::PS_Y) = sqrtK*(-(dr-Dx)*sn+(dr+Dx)*sh)/(2e0*dr);
179 
180  } else {
181  M(state_t::PS_X, state_t::PS_PX) = L;
182  M(state_t::PS_Y, state_t::PS_PY) = L;
183  }
184 
185  } // option
186  if (dstkick){
187  M(state_t::PS_PX, 6) = -K3*L*(D2x-D2y);
188  M(state_t::PS_PY, 6) = 2e0*K3*L*D2xy;
189  }
190 }
191 
192 void GetEdgeMatrix(const double rho, const double phi, const double dphi, const double qmrel, typename MomentElementBase::value_t &M)
193 {
194  typedef typename MomentElementBase::state_t state_t;
195 
196  M = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
197 
198  M(state_t::PS_PX, state_t::PS_X) = (tan(phi+dphi)/rho)*(1+qmrel);
199  M(state_t::PS_PY, state_t::PS_Y) = -(tan(phi-dphi)/rho)*(1+qmrel);
200 }
201 
202 
203 void GetEEdgeMatrix(const double fringe_x, const double fringe_y, const double kappa, typename MomentElementBase::value_t &M)
204 {
205  // Edge focusing for electrostatic dipole.
206  typedef typename MomentElementBase::state_t state_t;
207 
208  M = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
209 
210  M(state_t::PS_PX, state_t::PS_X) = fringe_x;
211  M(state_t::PS_PX, state_t::PS_PX) = sqrt(1e0+kappa);
212  M(state_t::PS_PY, state_t::PS_Y) = fringe_y;
213  M(state_t::PS_PS, state_t::PS_PS) = 1e0+kappa;
214 }
215 
216 
217 void GetSBendMatrix(const double L, const double phi, const double phi1, const double phi2, const double K,
218  const double IonEs, const double ref_gamma, const double qmrel,
219  const double dphi1, const double dphi2, const unsigned EFcorrection,
220  const double dip_beta, const double dip_gamma, const double d, const double dip_IonK, typename MomentElementBase::value_t &M)
221 {
222  typedef typename MomentElementBase::state_t state_t;
223 
224  MomentState::matrix_t edge1, edge2, R;
225 
226  double rho = L/phi,
227  Kx = K + 1e0/sqr(rho),
228  Ky = -K,
229  dx = 0e0,
230  sx = 0e0;
231 
232  // Horizontal plane.
233  GetQuadMatrix(L, Kx, (unsigned)state_t::PS_X, M);
234  // Vertical plane.
235  GetQuadMatrix(L, Ky, (unsigned)state_t::PS_Y, M);
236 
237  // Include dispersion.
238  if (Kx == 0e0) {
239  dx = sqr(L)/(2e0*rho);
240  sx = L/rho;
241  } else if (Kx > 0e0) {
242  dx = (1e0-cos(sqrt(Kx)*L))/(rho*Kx);
243  sx = sin(sqrt(Kx)*L)/(rho*sqrt(Kx));
244  } else {
245  dx = (1e0-cosh(sqrt(-Kx)*L))/(rho*Kx);
246  sx = sin(sqrt(-Kx)*L)/(rho*sqrt(-Kx));
247  }
248 
249  M(state_t::PS_X, state_t::PS_PS) = dx/(sqr(dip_beta)*dip_gamma*IonEs/MeVtoeV);
250  M(state_t::PS_PX, state_t::PS_PS) = sx/(sqr(dip_beta)*dip_gamma*IonEs/MeVtoeV);
251 
252  M(state_t::PS_S, state_t::PS_X) = sx*dip_IonK;
253  M(state_t::PS_S, state_t::PS_PX) = dx*dip_IonK;
254  // Low beta approximation.
255  M(state_t::PS_S, state_t::PS_PS) =
256  ((L/rho-sx)/(Kx*rho)-L/sqr(ref_gamma))*dip_IonK
257  /(sqr(dip_beta)*dip_gamma*IonEs/MeVtoeV);
258 
259  // Add dipole terms.
260  M(state_t::PS_S, 6) = ((L/rho-sx)/(Kx*rho)*d-L/sqr(ref_gamma)*(d+qmrel))*dip_IonK;
261  M(state_t::PS_X, 6) = dx*d;
262  M(state_t::PS_PX, 6) = sx*d;
263 
264  // Edge focusing.
265  if (EFcorrection) {
266  GetEdgeMatrix(rho, phi1, dphi1, qmrel, edge1);
267  GetEdgeMatrix(rho, phi2, dphi2, qmrel, edge2);
268  } else {
269  GetEdgeMatrix(rho, phi1, dphi1, 0e0, edge1);
270  GetEdgeMatrix(rho, phi2, dphi2, 0e0, edge2);
271  }
272 
273  M = prod(M, edge1);
274  M = prod(edge2, M);
275 
276  // Longitudinal plane.
277  // For total path length.
278  // M(state_t::PS_S, state_t::PS_S) = L;
279 }
280 
281 
282 void GetSolMatrix(const double L, const double K, typename MomentElementBase::value_t &M)
283 {
284  typedef typename MomentElementBase::state_t state_t;
285 
286  double C = ::cos(K*L),
287  S = ::sin(K*L);
288 
289  M(state_t::PS_X, state_t::PS_X)
290  = M(state_t::PS_PX, state_t::PS_PX)
291  = M(state_t::PS_Y, state_t::PS_Y)
292  = M(state_t::PS_PY, state_t::PS_PY)
293  = sqr(C);
294 
295  if (K != 0e0)
296  M(state_t::PS_X, state_t::PS_PX) = S*C/K;
297  else
298  M(state_t::PS_X, state_t::PS_PX) = L;
299  M(state_t::PS_X, state_t::PS_Y) = S*C;
300  if (K != 0e0)
301  M(state_t::PS_X, state_t::PS_PY) = sqr(S)/K;
302  else
303  M(state_t::PS_X, state_t::PS_PY) = 0e0;
304 
305  M(state_t::PS_PX, state_t::PS_X) = -K*S*C;
306  M(state_t::PS_PX, state_t::PS_Y) = -K*sqr(S);
307  M(state_t::PS_PX, state_t::PS_PY) = S*C;
308 
309  M(state_t::PS_Y, state_t::PS_X) = -S*C;
310  if (K != 0e0)
311  M(state_t::PS_Y, state_t::PS_PX) = -sqr(S)/K;
312  else
313  M(state_t::PS_Y, state_t::PS_PX) = 0e0;
314  if (K != 0e0)
315  M(state_t::PS_Y, state_t::PS_PY) = S*C/K;
316  else
317  M(state_t::PS_Y, state_t::PS_PY) = L;
318 
319  M(state_t::PS_PY, state_t::PS_X) = K*sqr(S);
320  M(state_t::PS_PY, state_t::PS_PX) = -S*C;
321  M(state_t::PS_PY, state_t::PS_Y) = -K*S*C;
322 
323  // Longitudinal plane.
324  // For total path length.
325 // M(state_t::PS_S, state_t::PS_S) = L;
326 }
327 
328 
329 void GetEBendMatrix(const double L, const double phi, const double fringe_x, const double fringe_y, const double kappa,
330  const double Kx, const double Ky, const double IonEs, const double real_gamma, const double eta0, const double h,
331  const double delta_K, const double delta_KZ, const double SampleIonK, typename MomentElementBase::value_t &M)
332 {
333  typedef typename MomentElementBase::state_t state_t;
334 
335  MomentState::matrix_t edge;
336 
337  double rho = L/phi,
338  scl = (real_gamma - 1e0)*IonEs/MeVtoeV,
339  dx = 0e0,
340  sx = 0e0;
341 
342  // Horizontal plane.
343  GetQuadMatrix(L, Kx, (unsigned)state_t::PS_X, M);
344  // Vertical plane.
345  GetQuadMatrix(L, Ky, (unsigned)state_t::PS_Y, M);
346 
347  // Include dispersion.
348  if (Kx == 0e0) {
349  dx = 0e0;
350  sx = 0e0;
351  } else if (Kx > 0e0) {
352  dx = (1e0-cos(sqrt(Kx)*L))/(rho*Kx);
353  sx = sin(sqrt(Kx)*L)/sqrt(Kx);
354  } else {
355  dx = (1e0-cosh(sqrt(-Kx)*L))/(rho*Kx);
356  sx = sin(sqrt(Kx)*L)/sqrt(Kx);
357  }
358 
359  double Nk = (sqr(1e0+2e0*eta0)+h)/(2e0*(1e0+eta0)*(1e0+2e0*eta0)),
360  Nt = 1e0 + h/sqr(1e0+2e0*eta0),
361  CorT = -real_gamma/(1e0+real_gamma),
362  tx = sx/rho*Nt*CorT,
363  txp = dx*Nt*CorT,
364  tzp = (-L/(2e0*(1e0+eta0)*(1e0+2e0*eta0))+((L-sx)/Kx/sqr(rho))*Nk*Nt)*CorT;
365 
366  M(state_t::PS_X, state_t::PS_PS) = dx*Nk/scl;
367  M(state_t::PS_PX, state_t::PS_PS) = sx/rho*Nk/scl;
368 
369  M(state_t::PS_S, state_t::PS_X) = -tx*SampleIonK;
370  M(state_t::PS_S, state_t::PS_PX) = -txp*SampleIonK;
371  // Low beta approximation.
372  M(state_t::PS_S, state_t::PS_PS) = -tzp*SampleIonK/scl;
373 
374  // Add dipole terms.
375  double Nkz = (1e0+2e0*eta0-h)/(2e0*(1e0+eta0)*(1e0+2e0*eta0));
376 
377  M(state_t::PS_X, 6) = dx*(Nk*delta_K+Nkz*delta_KZ);
378  M(state_t::PS_PX, 6) = sx/rho*(Nk*delta_K+Nkz*delta_KZ);
379 
380  // Edge focusing.
381  GetEEdgeMatrix(fringe_x, fringe_y ,kappa, edge);
382 
383  M = prod(M, edge);
384  M = prod(edge, M);
385 
386  // Longitudinal plane.
387  // For total path length.
388  // M(state_t::PS_S, state_t::PS_S) = L;
389 }
390 
391 void GetCurveData(const Config &c, const unsigned ncurve, std::vector<double> &Scales,
392  std::vector<std::vector<double> > &Curves)
393 {
394  boost::shared_ptr<Config> conf;
395 
396  std::string filename;
397  std::vector<double> range;
398  bool checker = c.tryGet<std::string>("CurveFile", filename),
399  rngchecker = c.tryGet<std::vector<double> >("use_range", range);
400 
401  if (checker){
402  std::string CurveFile = c.get<std::string>("Eng_Data_Dir", defpath);
403  CurveFile += "/" + filename;
404  std::string key(SB()<<CurveFile<<"|"<<boost::filesystem::last_write_time(CurveFile));
405  if ( CurveMap.find(key) == CurveMap.end() ) {
406  // not found in CurveMap
407  try {
408  try {
409  GLPSParser P;
410  conf.reset(P.parse_file(CurveFile.c_str(), false));
411  }catch(std::exception& e){
412  throw std::runtime_error(SB()<<"Parse error: "<<e.what()<<"\n");
413  }
414 
415  }catch(std::exception& e){
416  throw std::runtime_error(SB()<<"Error: "<<e.what()<<"\n");
417  }
418  CurveMap.insert(std::make_pair(key, conf));
419  } else {
420  // found in CurveMap
421  conf=CurveMap[key];
422  }
423  }
424 
425  size_t prev_size = 0;
426  for (unsigned n=0; n<ncurve; n++) {
427  std::string num(boost::lexical_cast<std::string>(n));
428  std::vector<double> cv;
429  bool cvchecker;
430  if (checker){
431  cvchecker = conf->tryGet<std::vector<double> >("curve"+num, cv);
432  } else {
433  cvchecker = c.tryGet<std::vector<double> >("curve"+num, cv);
434  }
435  if (!cvchecker)throw std::runtime_error(SB()<<"'curve" << num << "' is missing in lattice file.\n");
436 
437  if (rngchecker){
438  unsigned start, end;
439  if (range.size() != 2)
440  throw std::runtime_error(SB()<<"Size of 'use_range' must be 2.\n");
441  start = static_cast<unsigned>(range[0]);
442  end = static_cast<unsigned>(range[1]);
443 
444  if (start > cv.size() or end > cv.size())
445  throw std::runtime_error(SB()<<"'use_range' is out of curve size.\n");
446 
447  std::vector<double> part(cv.begin()+start, cv.begin()+end);
448  Curves.push_back(part);
449  } else {
450  Curves.push_back(cv);
451  }
452 
453  if (n != 0 and prev_size != cv.size())
454  throw std::runtime_error(SB()<<"Size of 'curve" << n << "' (" << cv.size() <<") and 'curve" << n-1 <<
455  "' (" << prev_size <<") are inconsistent. All curves must have the same size.\n");
456  prev_size = cv.size();
457 
458  Scales.push_back(c.get<double>("scl_fac"+num, 0.0));
459  }
460 }
Config * parse_file(const char *fname, const bool have_lattice=true)
Open and parse a file.
Definition: config.cpp:364
Interface to lattice file parser.
Definition: config.h:240
Associative configuration container.
Definition: config.h:66
bool tryGet(const std::string &name, T &val) const
Definition: config.h:156
detail::RT< T >::type get(const std::string &name) const
Definition: config.h:123