OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
DragtFinnMap.h
Go to the documentation of this file.
1 #ifndef CLASSIC_DragtFinnMap_HH
2 #define CLASSIC_DragtFinnMap_HH
3 
4 // ------------------------------------------------------------------------
5 // $RCSfile: DragtFinnMap.h,v $
6 // ------------------------------------------------------------------------
7 // $Revision: 1.2.2.1 $
8 // ------------------------------------------------------------------------
9 // Copyright: see Copyright.readme
10 // ------------------------------------------------------------------------
11 //
12 // Template class: DragtFinnMap<N>
13 //
14 // ------------------------------------------------------------------------
15 // Class category: FixedAlgebra
16 // ------------------------------------------------------------------------
17 //
18 // $Date: 2002/03/25 20:44:16 $
19 // $Author: dbruhwil $
20 //
21 // ------------------------------------------------------------------------
22 
23 #include "Algebra/Array1D.h"
24 #include "FixedAlgebra/FMatrix.h"
25 #include "FixedAlgebra/FTps.h"
26 
27 #include <complex>
28 
29 template <class T, int N> class FLieGenerator;
30 template <class T, int N> class FVector;
31 template <class T, int N> class FVps;
32 template <class T, int N> class LinearMap;
33 
34 
35 // Template class DragtFinnMap<N>.
36 // ------------------------------------------------------------------------
38 // The type of coefficients is double, and the number of variables is N.
39 // It should be noted that some algorithms, notably concatenation of maps,
40 // are limited to maps with generators up to order 6.
41 
42 template <int N>
43 class DragtFinnMap {
44 
45 public:
46 
47  DragtFinnMap(const DragtFinnMap &);
48  ~DragtFinnMap();
49  const DragtFinnMap &operator=(const DragtFinnMap &);
50 
52  DragtFinnMap();
53 
55  explicit DragtFinnMap(int);
56 
58  explicit DragtFinnMap(const FVps<double, 2 * N> &map);
59 
61  explicit DragtFinnMap(const FTps<double, 2 * N> &map);
62 
64  explicit DragtFinnMap(const LinearMap<double, 2 * N> &map);
65 
67  operator FVps<double, 2 * N>() const;
68 
70  operator LinearMap<double, 2 * N>() const;
71 
72 
75 
77  void assign(const FTps<double, 2 * N> &);
78 
80  void assign(const FLieGenerator<double, N> &);
81 
82 
83  // Factorise a map given by a Hamiltonian,
84  // using the method by M. Berz, E. Forest and J. Irwin
85  // (Particle Accelerators, vol. 24, pp. 91 / 107).
86  // This method works best for Hamiltonians whose H_2 have no
87  // zero eigenvalues.
89 
90  // Factorise a map given by a Hamiltonian,
91  // using the method by D. Douglas (ML University thesis 1982).
92  // This method works best for Hamiltonians with q-independent H_2.
94 
95  // Factorise a map given by a Hamiltonian,
96  // which is either p-free or q-free.
97  // The Lie generators are then simply the homogeneous parts of H.
99 
100 
103 
106 
108  const FTps<double, 2 * N> &getGenerators() const;
109 
112 
114  const FLieGenerator<double, N> getGenerator(int) const;
115 
117  int getOrder() const;
118 
120  // The first-order generator must be zero.
121  DragtFinnMap inverse() const;
122 
124  // The first-order generator must be zero.
125  DragtFinnMap reverse() const;
126 
128  void operator+=(const FTps<double, 2 * N> &);
129 
131  void operator-=(const FTps<double, 2 * N> &);
132 
134  void operator+=(const FLieGenerator<double, N> &);
135 
137  void operator-=(const FLieGenerator<double, N> &);
138 
139 
141  DragtFinnMap catenate(const DragtFinnMap &) const;
142 
144  DragtFinnMap conjugate(const DragtFinnMap &) const;
145 
147  // First argument is set to the fixed point vector,
148  // Second argument is set to map around the fixed point.
150 
152  // First argument is set to the fixed point vector,
153  // Second argument is set to map around the fixed point.
154  // Assumes the longitudinal values are in the last pair.
156 
158  // First argument is set to dispersion map,
159  // Second argument is set to map without dispersion.
161 
163  // The first argument is the input/output orbit,
164  // the second argument is set to the map around the orbit.
166 
168  // Return the series exp(:f:) g, the Lie transform exp(:f:)
169  // acting on the generators g of this map.
170  DragtFinnMap transform(const FLieGenerator<double, N> &g, int topOrder);
171 
172 private:
173 
174  // Get beginning of coefficient storage for generator of given order.
175  // Version for constant object.
176  inline const double *begin(int) const;
177 
178  // Get beginning of coefficient storage for generator of given order.
179  // Version for non-constant object.
180  inline double *begin(int);
181 
182  // Get ending of coefficient storage for generator of given order.
183  // Version for constant object.
184  inline const double *end(int) const;
185 
186  // Get ending of coefficient storage for generator of given order.
187  // Version for non-constant object.
188  inline double *end(int);
189 
190 
191  // Substitute (concatenate) with another map, ignoring linear terms.
193  catenateZero(const DragtFinnMap &) const;
194 
195  // Exponentiate a matrix whose norm is small.
198 
199  // Factorize a map given by a Hamiltonian ignoring the linear terms.
200  static DragtFinnMap
201  factorize(const FTps<double, 2 * N> &H);
202 
203  // Make the matrix J*S representing the Lie operator :f_2:.
206 
207  // Move the g_1 term over the terms of f.
208  static void
210 
211  // Order the modes according to "stable", "unstable", and "coasting".
212  // Return the number of non-coasting modes.
213  // The eigenvalues in this case are the logarithms of the usual values.
214  static int
215  orderModes(FMatrix<double, 2 * N, 2 * N> &, FVector<std::complex<double>, 2 * N> &);
216 
217 
218  // The matrix of the repesentation.
220 
221  // The Lie generators are stored in an FTps<double,2*N> object.
223 };
224 
225 
226 template <int N>
227 std::ostream &operator<<(std::ostream &, const DragtFinnMap<N> &);
228 
231 #include "FixedAlgebra/FLUMatrix.h"
232 #include "FixedAlgebra/FTps.h"
233 #include "FixedAlgebra/FTpsData.h"
234 #include "FixedAlgebra/FVector.h"
235 #include "FixedAlgebra/FVps.h"
236 #include "FixedAlgebra/LinearMap.h"
237 #include "FixedAlgebra/Taylor.h"
238 #include "Utilities/LogicalError.h"
239 #include <complex>
240 #include <iosfwd>
241 //#include <algorithm>
242 //#include <iostream>
243 
244 
245 // Template class DragtFinnMap.
246 // ------------------------------------------------------------------------
247 
248 template <int N>
251  itsMatrix(rhs.itsMatrix), itsGenerators(rhs.itsGenerators)
252 {}
253 
254 
255 template <int N>
258  itsMatrix(), itsGenerators() {
259  for(int i = 0; i < 2 * N; ++i) itsMatrix(i, i) = 1.0;
260 }
261 
262 
263 template <int N>
265 DragtFinnMap(int order):
266  itsMatrix(), itsGenerators(0, order, order) {
267  for(int i = 0; i < 2 * N; ++i) itsMatrix(i, i) = 1.0;
268 }
269 
270 
271 template <int N>
274 {}
275 
276 
277 template <int N>
279 operator=(const DragtFinnMap &rhs) {
280  itsMatrix = rhs.itsMatrix;
281  itsGenerators = rhs.itsGenerators;
282  return *this;
283 }
284 
285 
286 template <int N>
289  itsMatrix(rhs.linearTerms()), itsGenerators() {
290  for(int i = 0; i < N; ++i) {
291  itsGenerators[2*i+1] = rhs[2*i+1][0];
292  itsGenerators[2*i+2] = - rhs[2*i+0][0];
293  }
294  // ***** MISSING: higher order terms *****
295 }
296 
297 
298 template <int N>
301  itsMatrix(rhs.linearTerms()), itsGenerators() {
302  for(int i = 0; i < N; ++i) {
303  itsGenerators[2*i+1] = rhs[2*i+1][0];
304  itsGenerators[2*i+2] = - rhs[2*i+0][0];
305  }
306 }
307 
308 
309 template <int N>
311 operator FVps<double, 2 * N>() const {
312  int maxOrder = getOrder();
313  FTps<double, 2 * N> gen = getGenerators();
314  FVps<double, 2 * N> theMap;
315 
316  for(int i = maxOrder; i >= 3; --i) {
317  FTps<double, 2 * N> tps = gen.filter(i, i);
318  theMap = ExpMap(tps, theMap);
319  }
320 
321  theMap = theMap.substitute(getMatrix());
322 
323  FVps<double, 2 * N> xlate;
324  for(int i = 0; i < N; ++i) {
325  xlate[2*i][0] = -gen[2*i+2];
326  xlate[2*i+1][0] = gen[2*i+1];
327  }
328  theMap = theMap.substitute(xlate);
329 
330  return theMap.filter(0, maxOrder < 2 ? 1 : maxOrder - 1);
331 }
332 
333 
334 template <int N>
336 operator LinearMap<double, 2 * N>() const {
337  FLieGenerator<double, N> f_1(getGenerators(), 1);
338  f_1 = f_1.transform(getMatrix());
339  LinearMap<double, 2 * N> theMap(getMatrix());
340 
341  for(int i = 0; i < N; ++i) {
342  theMap[2*i+0][0] = - f_1[2*i+2];
343  theMap[2*i+1][0] = f_1[2*i+1];
344  }
345 
346  return theMap;
347 }
348 
349 
350 template <int N>
353  if(H.filter(1, 1) == 0.0) {
354  // No linear terms in Hamiltonian; no displacement map required.
355  *this = factorize(H);
356  } else {
357  // Apply the method by L. Healy to remove linear terms.
358  // Factorise terms without first order.
359  int order = H.getMaxOrder();
360 
361  // The h map contains the first-order terms.
362  DragtFinnMap<N> h;
363  h.assign(-H.filter(1, 1));
364 
365  // The g map is the current factor.
366  DragtFinnMap<N> g = factorize(H.filter(2, order));
367 
368  // The "this" map accumulates the result.
369  *this = g;
370 
371  // Extract and transform first order terms.
372  // The epsilon rank of the remainder terms.
373  for(int epsilonRank = 1; epsilonRank <= order - 3; ++epsilonRank) {
374  int top = order - epsilonRank;
375 
376  // Put first-order terms into h and transform with g map.
377  h.assign(h.getGenerators().filter(1, 1).substitute(g.getMatrix()));
378  for(int ord = 3; ord <= top; ++ord) {
379  h = h.transform(g.getGenerator(ord), top);
380  }
381 
382  // Compute new g map and catenate with f.
383  g = factorize(h.getGenerators().filter(2, top));
384  *this = g.catenateZero(*this);
385  }
386 
387  // Transmit the first-order terms.
388  assign(h.getGenerator(1));
389  }
390 }
391 
392 
393 template <int N>
396  itsMatrix = mat;
397 }
398 
399 
400 template <int N>
403  itsGenerators = gen;
404 }
405 
406 
407 template <int N>
410  int order = gen.getOrder();
411 
412  if(itsGenerators.getMaxOrder() < order) {
414  std::copy(itsGenerators.begin(), itsGenerators.end(), temp.begin());
415  itsGenerators = temp;
416  } else {
417  itsGenerators.unique();
418  }
419 
420  std::copy(gen.begin(), gen.end(), begin(order));
421 }
422 
423 
424 template <int N>
427  static const double tol = 1.0e-12;
428  int modes = N;
429 
430  // The matrix M represents the operator :f_2:.
431  FTps<double, 2 * N> H = - HH;
432  FLieGenerator<double, N> H_2(H, 2);
433  FMatrix<double, 2 * N, 2 * N> M = makeMatrix(H_2);
434 
435  // Eigenvalues and eigenvectors of M.
436  FVector<std::complex<double>, 2 * N> mu; // eigenvalues
437  FMatrix<double, 2 * N, 2 * N> V; // eigenvectors
438  FMatrix<double, 2 * N, 2 * N> V_inv; // inverse of V
439  {
440  // Find the eigenvalues and eigenvectors of M.
441  FDoubleEigen<2 * N> eigen(M, true);
442  mu = eigen.eigenValues();
443  V = eigen.packedEigenVectors();
444 
445  // Order eigenvectors and normalise.
446  modes = orderModes(V, mu);
448  V_inv = lu.inverse();
449  }
450 
451  // Set up the auxiliary matrices.
452  FMatrix<double, 2 * N, 2 * N> Rot, R_dir, R_inv, I_dir;
453 
454  for(int i = 0; i < 2 * N; i += 2) {
455  if(std::abs(mu[i]) < tol) {
456  // "coasting" eigenvalue pair.
457  R_dir(i, i) = 1.0;
458  R_dir(i + 1, i + 1) = 1.0;
459  R_inv(i, i) = 1.0;
460  R_inv(i + 1, i + 1) = 1.0;
461  I_dir(i, i) = 1.0;
462  I_dir(i + 1, i + 1) = 1.0;
463  Rot(i, i) = 1.0;
464  Rot(i, i + 1) = M(i, i + 1);
465  Rot(i + 1, i) = M(i + 1, i);
466  Rot(i + 1, i + 1) = 1.0;
467  } else {
468  R_dir(i, i) = + 0.5;
469  R_dir(i, i + 1) = + 0.5;
470  R_dir(i + 1, i) = + 0.5;
471  R_dir(i + 1, i + 1) = - 0.5;
472  R_inv(i, i) = + 1.0;
473  R_inv(i, i + 1) = + 1.0;
474  R_inv(i + 1, i) = + 1.0;
475  R_inv(i + 1, i + 1) = - 1.0;
476 
477  if(std::abs(std::imag(mu[i])) > tol) {
478  // "stable" eigenvalue pair.
479  double c = std::cos(std::imag(mu[i]));
480  double s = std::sin(std::imag(mu[i]));
481  Rot(i, i) = + c;
482  Rot(i, i + 1) = + s;
483  Rot(i + 1, i) = - s;
484  Rot(i + 1, i + 1) = + c;
485  I_dir(i, i + 1) = 1.0;
486  I_dir(i + 1, i) = 1.0;
487  } else {
488  // "unstable" eigenvalue pair.
489  double ch = std::cosh(std::real(mu[i]));
490  double sh = std::sinh(std::real(mu[i]));
491  Rot(i, i) = + ch;
492  Rot(i, i + 1) = - sh;
493  Rot(i + 1, i) = - sh;
494  Rot(i + 1, i + 1) = + ch;
495  I_dir(i, i) = 1.0;
496  I_dir(i + 1, i + 1) = 1.0;
497  }
498  }
499  }
500 
501  // Declare the fake normal form and normalising maps.
502  int maxOrder = H.getMaxOrder();
503  DragtFinnMap<N> N_scr;
504  DragtFinnMap<N> A_scr;
505  A_scr.assign(V_inv);
506  N_scr.assign(Rot);
507  N_scr.assign(H.filter(2, maxOrder).substitute(V));
508 
509  // Remove non-resonant terms order by order.
510  for(int omega = 3; omega <= maxOrder; omega++) {
511  // Compute the terms to be removed and store in f.
512  FLieGenerator<double, N> f(N_scr.getGenerators(), omega);
513  FLieGenerator<double, N> a(omega);
514  FLieGenerator<double, N> b(omega);
516 
517  for(int m = f.getBottomIndex(); m < f.getTopIndex(); m++) {
519  std::complex<double> factor = 0.0;
520  int count = 0;
521 
522  for(int j = 0; j < 2 * modes; j += 2) {
523  if(std::abs(std::imag(mu[j])) > tol) count += index[j+1];
524  factor += double(index[j]) * mu[j] + double(index[j+1]) * mu[j+1];
525  }
526 
527  if(std::abs(factor) > tol) {
528  // Term can be removed.
529  factor = 1.0 / factor;
530  a[m] = std::real(factor);
531  b[m] = std::imag(factor);
532  }
533 
534  pi[m] = std::pow(- 1.0, (count + 1) / 2);
535  }
536 
537  // Compute cal_T^(-1) * f.
538  FLieGenerator<double, N> f1 = pi.scale(f).transform(R_dir);
539  FLieGenerator<double, N> f2 = f1.transform(I_dir);
540  FLieGenerator<double, N> F_omega =
541  (a.scale(f1) + b.scale(f2)).transform(R_inv).scale(pi);
542 
543  N_scr = N_scr.transform(- F_omega, maxOrder);
544  A_scr.assign(F_omega);
545  }
546 
547  // Conjugate the N-map with the A-map.
548  N_scr = N_scr.conjugate(A_scr);
549  return N_scr;
550 }
551 
552 
553 template <int N>
556  int maxOrder = H.getMaxOrder();
557  DragtFinnMap<N> theMap;
558 
559  // Build first-order matrix.
560  // K2 = - H2 is the second-order generator of the map.
561  FLieGenerator<double, N> H2(H, 2);
562  FMatrix<double, 2 * N, 2 * N> M = makeMatrix(- H2);
563  M = M + 1.0;
564  theMap.assign(M);
565 
566  // Assign terms of higher order.
567  if(maxOrder >= 3) {
568  // Build the transformed - H3(exp(:- K2: z).
570  H3[0] = FLieGenerator<double, N>(H, 3);
571  H3[1] = PoissonBracket(H2, H3[0]);
572  H3[2] = PoissonBracket(H2, H3[1]) / 2.0;
573  H3[3] = PoissonBracket(H2, H3[2]) / 3.0;
574 
575  // Extract K3.
576  Taylor < FLieGenerator<double, N> > K3 = - H3.integrate();
577  theMap += K3.sum();
578 
579  if(maxOrder >= 4) {
580  // Build the transformed H4 = H4(exp(:- K2: z).
582  H4[0] = FLieGenerator<double, N>(H, 4);
583  H4[1] = PoissonBracket(H2, H4[0]);
584  H4[2] = PoissonBracket(H2, H4[1]) / 2.0;
585  H4[3] = PoissonBracket(H2, H4[2]) / 3.0;
586  H4[4] = PoissonBracket(H2, H4[3]) / 4.0;
587 
588  // Change due to ((exp(:K3:) - 1) / :K3: - 1) H3.
590  H4 -= p33 / 2.0;
591 
592  // Extract K4.
593  Taylor < FLieGenerator<double, N> > K4 = - H4.integrate();
594  theMap += K4.sum();
595 
596  if(maxOrder >= 5) {
597  // Build the transformed H5 = H5(exp(:- K2: z).
599  H5[0] = FLieGenerator<double, N>(H, 5);
600  H5[1] = PoissonBracket(H2, H5[0]);
601  H5[2] = PoissonBracket(H2, H5[1]) / 2.0;
602  H5[3] = PoissonBracket(H2, H5[2]) / 3.0;
603  H5[4] = PoissonBracket(H2, H5[3]) / 4.0;
604  H5[5] = PoissonBracket(H2, H5[4]) / 5.0;
605 
606  // Contribution of ((exp(:K3:) - 1) / :K3: - 1) H3
607  // H5 -= PB(K3, PB(K3, H3)) / 6.
609  H5 -= p333 / 6.0;
610 
611  // Contribution of exp(:- K3:) H4
612  // H5 -= PB(K3, H4).
614  H5 -= p34;
615 
616  Taylor < FLieGenerator<double, N> > K_5 = - H5.integrate();
617  theMap += K_5.sum();
618 
619  if(maxOrder >= 6) {
620  // Build the transformed H6 = H6(exp(:- K2: z).
622  H6[0] = FLieGenerator<double, N>(H, 6);
623  H6[1] = PoissonBracket(H2, H6[0]);
624  H6[2] = PoissonBracket(H2, H6[1]) / 2.0;
625  H6[3] = PoissonBracket(H2, H6[2]) / 3.0;
626  H6[4] = PoissonBracket(H2, H6[3]) / 4.0;
627  H6[5] = PoissonBracket(H2, H6[4]) / 5.0;
628  H6[6] = PoissonBracket(H2, H6[5]) / 6.0;
629 
630  // Contibution of ((exp(:K3:) - 1) / :K3: - 1) H_3
631  // H6 -= PB(K3, PB(K3, PB(K3, H3))).
632  // Contribution of exp(:- K3:) (H4 + H5)
633  // H6 = H6 + PB(K3, PB(K3, H4)) / 2 - PB(K3, H5)
634  // Note that H5 has already been modified by p34.
635  H6 -= PoissonBracket(K3, p333 + H5 + p34 / 2.0) / 24.0;
636  // Contibution of ((exp(:K4:) - 1) / :K4: - 1) H_4
637  // H6 -= PB(K4, H4) / 2.
638  H6 -= PoissonBracket(K4, H4) / 2.0;
639  Taylor < FLieGenerator<double, N> > K6 = - H6.integrate();
640  theMap += K6.sum();
641  }
642  }
643  }
644  }
645 
646  return theMap;
647 }
648 
649 
650 template <int N>
653  FTps<double, 2 * N> H = - HH;
654  DragtFinnMap<N> theMap;
655  theMap.assign(H.filter(3, H.getMaxOrder()));
656 
657  // Build first-order matrix.
658  const FLieGenerator<double, N> H_2(H, 2);
659  const FMatrix<double, 2 * N, 2 * N> M = makeMatrix(H_2);
660  theMap.assign(M + 1.0);
661 
662  // Assign first-order terms, transformed by inverse matrix.
663  const FLieGenerator<double, N> H_1(H, 1);
664  if(! H_1.isZero()) theMap.assign(H_1.transform(- M + 1.0));
665  return theMap;
666 }
667 
668 
669 template <int N>
671 getMatrix() const {
672  return itsMatrix;
673 }
674 
675 
676 template <int N>
679  return itsMatrix;
680 }
681 
682 
683 template <int N>
685 getGenerators() const {
686  return itsGenerators;
687 }
688 
689 
690 template <int N>
693  return itsGenerators;
694 }
695 
696 
697 template <int N>
699 getGenerator(int order) const {
700  FLieGenerator<double, N> gen(order);
701 
702  if(itsGenerators.getMaxOrder() >= order) {
703  std::copy(begin(order), end(order), gen.begin());
704  } else {
705  std::fill(gen.begin(), gen.end(), 0.0);
706  }
707 
708  return gen;
709 }
710 
711 
712 template <int N>
714 getOrder() const {
715  return itsGenerators.getMaxOrder();
716 }
717 
718 
719 template <int N>
721 inverse() const {
722  DragtFinnMap h(reverse());
723  FMatrix<double, 2 * N, 2 * N> f_mat = getMatrix();
724  FLUMatrix<double, 2 * N> lu(f_mat);
725  h.assign(lu.inverse());
726  h.assign(- h.getGenerators());
727  return h;
728 }
729 
730 
731 template <int N>
733 reverse() const {
734  int order = getOrder();
735  FMatrix<double, 2 * N, 2 * N> f_mat = getMatrix();
736  FTps<double, 2 * N> f_gen = getGenerators().substitute(f_mat);
737  DragtFinnMap h;
738  h.assign(f_mat);
739  h.assign(f_gen);
740 
741  if(order >= 5) {
742  FLieGenerator<double, N> f_3(f_gen, 3);
743  FLieGenerator<double, N> f_4(f_gen, 4);
745  h += pb;
746 
747  if(order >= 6) {
748  FLieGenerator<double, N> f_5(f_gen, 5);
749  h += PoissonBracket(f_3, f_5 + 0.5 * pb);
750  }
751  }
752 
753  return h;
754 }
755 
756 
757 template <int N>
760  itsGenerators += gen;
761 }
762 
763 
764 template <int N>
767  itsGenerators -= gen;
768 }
769 
770 
771 template <int N>
774  int order = gen.getOrder();
775 
776  if(order > 0) {
777  if(itsGenerators.getMaxOrder() < order) {
779  std::copy(itsGenerators.begin(), itsGenerators.end(), temp.begin());
780  itsGenerators = temp;
781  } else {
782  itsGenerators.unique();
783  }
784 
785  std::transform(begin(order), end(order), gen.begin(),
786  begin(order), std::plus<double>());
787  }
788 }
789 
790 
791 template <int N>
794  int order = gen.getOrder();
795 
796  if(order > 0) {
797  if(itsGenerators.getMaxOrder() < order) {
799  std::copy(itsGenerators.begin(), itsGenerators.end(), temp.begin());
800  itsGenerators = temp;
801  } else {
802  itsGenerators.unique();
803  }
804 
805  std::transform(begin(order), end(order), gen.begin(),
806  begin(order), std::minus<double>());
807  }
808 }
809 
810 
811 template <int N>
813 catenate(const DragtFinnMap &rhs) const {
814  if(rhs.itsGenerators.filter(1, 1) == 0.0) {
815  // No linear terms in right-hand side; use normal catenation.
816  return catenateZero(rhs);
817  } else {
818  DragtFinnMap f(*this);
819  DragtFinnMap g(rhs);
820  move_g_1(f, g);
821  return f.catenateZero(g);
822  }
823 }
824 
825 
826 template <int N>
828 conjugate(const DragtFinnMap &rhs) const {
829  return rhs.catenate(catenate(rhs.inverse()));
830 }
831 
832 
833 template <int N>
836  static const int itmax = 10;
837  static const double tol = 1.0e-16;
838  fp = FVector<double, 2 * N>();
839 
840  for(int iter = 1; iter <= itmax; ++iter) {
842  trackOrbit(fp1, map);
843  FVector<double, 2 * N> error = fp1 - fp;
844 
845  if(euclidean_norm(error) < tol) break;
846 
848  M = M - 1.0;
850  lu.backSubstitute(error);
851  fp -= error;
852  }
853 }
854 
855 
856 template <int N>
859  static const int itmax = 10;
860  static const double tol = 1.0e-16;
861  fp = FVector<double, 2 * N>();
862 
863  for(int iter = 1; iter <= itmax; ++iter) {
865  trackOrbit(fp1, map);
866  FVector<double, 2 * N> error = fp1 - fp;
867 
868  if(euclidean_norm(error) < tol) break;
869 
871  M = M - 1.0;
872 
873  FMatrix < double, 2 * N - 2, 2 * N - 2 > MM;
874  FVector < double, 2 * N - 2 > X;
875  for(int i = 0; i < 2 * N - 2; ++i) {
876  for(int j = 0; j < 2 * N - 2; ++j) {
877  MM(i, j) = M(i, j);
878  }
879  X[i] = error[i];
880  }
881 
882  FLUMatrix < double, 2 * N - 2 > lu(MM);
883  lu.backSubstitute(X);
884  for(int i = 0; i < 2 * N - 2; ++i) {
885  fp[i] -= X[i];
886  }
887  }
888 }
889 
890 template <int N>
893  // compute an1.
894  FMatrix<double, 2 * N, 2 * N> A = getMatrix();
895  FMatrix < double, 2 * N - 2, 2 * N - 2 > B;
896  FVector < double, 2 * N - 2 > C;
897 
898  // Compute first-order dispersion.
899  for(int i = 0; i < 2 * N - 2; ++i) {
900  for(int j = 0; j < 2 * N - 2; ++j) {
901  B(i, j) = A(i, j);
902  }
903 
904  B(i, i) -= 1.0;
905  C[i] = - A(i, 2 * N - 1);
906  }
907 
908  FLUMatrix < double, 2 * N - 2 > lu(B);
909  lu.backSubstitute(C);
911  T = T + 1.0;
912 
913  for(int i = 0; i < N - 1; ++i) {
914  T(2 * i, 2 * N - 1) = C[2*i];
915  T(2 * i + 1, 2 * N - 1) = C[2*i+1];
916  T(2 * N - 2, 2 * i) = C[2*i+1];
917  T(2 * N - 2, 2 * i + 1) = - C[2*i];
918  }
919 
920  dm = DragtFinnMap<N>(getOrder());
921  dm.assign(T);
922 
923  // Compute t*m*t^(-1) where m is initial map.
924  map = conjugate(dm);
925 
926  // Compute higher dispersions.
927  for(int order = 2; order <= getOrder(); ++order) {
928  A = FLUMatrix<double, 2 * N>(map.getMatrix()).inverse();
929 
930  for(int i = 0; i < 2 * N - 2; ++i) {
931  for(int j = 0; j < 2 * N - 2; ++j) {
932  B(i, j) = A(i, j);
933  }
934 
935  B(i, i) -= 1.0;
936  FMonomial<2 * N> mono;
937  mono[i] = 1;
938  mono[2*N-1] = order;
939  C[i] = - map.getGenerators()[mono];
940  }
941 
942  FLUMatrix < double, 2 * N - 2 > lu(B);
943  lu.backSubstitute(C);
944 
945  // compute t2.
946  DragtFinnMap<N> t1(order + 1);
947 
948  for(int i = 0; i < 2 * N - 2; ++i) {
949  FMonomial<2 * N> mono;
950  mono[i] = 1;
951  mono[2*N-1] = order;
952  t1.getGenerators()[mono] = C[i];
953  }
954 
955  // Compute and store t1 o t.
956  dm = dm.catenateZero(t1);
957 
958  // Compute t1 o map o t2^(-1).
959  map = map.conjugate(t1);
960  }
961 }
962 
963 
964 template <int N>
967  FTps<double, 2 * N> fp = getGenerators();
968  FMatrix<double, 2 * N, 2 * N> fM = getMatrix();
969  FLieGenerator<double, N> f_1(fp, 1);
970 
971  // The generator to be moved along.
973  for(int i = 0; i < N; ++i) {
974  g_1[2*i+1] = f_1[2*i+1] + orbit[2*i+1];
975  g_1[2*i+2] = f_1[2*i+2] - orbit[2*i];
976  }
977 
978  // Initialise the map around the orbit.
979  DragtFinnMap h;
980 
981  // Move orbit across the matrix.
983  FLieGenerator<double, N> g_1t = g_1.transform(M);
984  h += g_1t;
985 
986  // Terms of total rank 3.
987  if(getOrder() >= 3) {
988  FLieGenerator<double, N> f_33(fp, 3);
989  FLieGenerator<double, N> f_32 = PoissonBracket(g_1t, f_33);
990  FLieGenerator<double, N> f_31 = PoissonBracket(g_1t, f_32) / 2.0;
991  h += f_33;
992  h += f_32;
993  h += f_31;
994 
995  // Terms of total rank 4.
996  if(getOrder() >= 4) {
997  FLieGenerator<double, N> f_44(fp, 4);
998  FLieGenerator<double, N> f_43 = PoissonBracket(g_1t, f_44);
999  FLieGenerator<double, N> f_42 = PoissonBracket(g_1t, f_43) / 2.0;
1000  FLieGenerator<double, N> f_41 = PoissonBracket(g_1t, f_42) / 3.0;
1001  h += f_44;
1002  h += f_43 + PoissonBracket(f_33, f_32) / 2.0;
1003  h += f_42 + PoissonBracket(f_31, f_33) / 2.0;
1004  h += f_41 + PoissonBracket(f_31, f_32) / 2.0;
1005  }
1006  }
1007 
1008  // Calculate the matrix part of the factored exponential.
1010  FLieGenerator<double, N> h_2(hp, 2);
1011  FMatrix<double, 2 * N, 2 * N> hM = makeMatrix(h_2);
1012  hM = (((hM * (1. / 4.) + 1.) * hM * (1. / 3.) + 1.) * hM * (1. / 2.) + 1.) * hM + 1.;
1013 
1014  // Convert moved g_1 to orbit.
1015  FLieGenerator<double, N> h_1(hp, 1);
1016  for(int i = 0; i < N; ++i) {
1017  orbit[2*i] = - h_1[2*i+2];
1018  orbit[2*i+1] = h_1[2*i+1];
1019  }
1020 
1021  // Leave the higher generators in map.
1022  map.assign(hM * fM);
1023  map.assign(hp.filter(3, 4));
1024 }
1025 
1026 
1027 template <int N>
1029 transform(const FLieGenerator<double, N> &g, int topOrder) {
1030  DragtFinnMap<N> H_trans(*this);
1031  int gOrder = g.getOrder();
1032 
1033  for(int order = 1; order <= topOrder; ++order) {
1034  FLieGenerator<double, N> pb(itsGenerators, order);
1035  int pbOrder = order;
1036 
1037  for(int power = 1; power <= topOrder; ++power) {
1038  pbOrder += gOrder - 2;
1039  if(pbOrder <= 0 || pbOrder > topOrder) break;
1040  pb = PoissonBracket(g, pb) / double(power);
1041  H_trans += pb;
1042  }
1043  }
1044 
1045  return H_trans;
1046 }
1047 
1048 
1049 template <int N>
1050 double *DragtFinnMap<N>::
1051 begin(int order) {
1052  return itsGenerators.begin() + FTpsData<2 * N>::getSize(order - 1);
1053 }
1054 
1055 
1056 template <int N>
1057 const double *DragtFinnMap<N>::
1058 begin(int order) const {
1059  return itsGenerators.begin() + FTpsData<2 * N>::getSize(order - 1);
1060 }
1061 
1062 
1063 template <int N>
1064 double *DragtFinnMap<N>::
1065 end(int order) {
1066  return itsGenerators.begin() + FTpsData<2 * N>::getSize(order);
1067 }
1068 
1069 
1070 template <int N>
1071 const double *DragtFinnMap<N>::
1072 end(int order) const {
1073  return itsGenerators.begin() + FTpsData<2 * N>::getSize(order);
1074 }
1075 
1076 
1077 template <int N>
1081  FMatrix<double, 2 * N, 2 * N> f_mat = getMatrix();
1082 
1083  // The combined matrix.
1084  DragtFinnMap<N> h;
1085  h.assign(g_mat * f_mat);
1086 
1087  // Extract the generators.
1088  int order = std::max(getOrder(), g.getOrder());
1090  FTps<double, 2 * N> f_gen =
1091  itsGenerators.filter(2, itsGenerators.getMaxOrder()).substitute(g_inv)
1092  + itsGenerators.filter(1, 1);
1093  FTps<double, 2 * N> g_gen = g.getGenerators();
1094 
1095  // Assign sum of the generators, the terms are now correct to order 3.
1096  h.assign(f_gen + g_gen);
1097 
1098  if(order >= 4) {
1099  FLieGenerator<double, N> f_3(f_gen, 3);
1100  FLieGenerator<double, N> g_3(g_gen, 3);
1101  FLieGenerator<double, N> pb_f3_g3 = PoissonBracket(f_3, g_3);
1102  h += pb_f3_g3 / 2.0;
1103 
1104  if(order >= 5) {
1105  FLieGenerator<double, N> f_4(f_gen, 4);
1106  FLieGenerator<double, N> pb_f3_f3_g3 = PoissonBracket(f_3, pb_f3_g3);
1107  FLieGenerator<double, N> pb_g3_f3_g3 = PoissonBracket(g_3, pb_f3_g3);
1108  FLieGenerator<double, N> pb_f4_g3 = PoissonBracket(f_4, g_3);
1109  h += pb_f4_g3 - pb_f3_f3_g3 / 6.0 - pb_g3_f3_g3 / 3.0;
1110 
1111  if(order >= 6) {
1112  FLieGenerator<double, N> f_5(f_gen, 5);
1113  FLieGenerator<double, N> g_4(g_gen, 4);
1114  h += (PoissonBracket(f_5, g_3)
1115  + PoissonBracket(f_4, g_4) / 2.0
1116  - PoissonBracket(g_3, pb_f4_g3) / 2.0
1117  - PoissonBracket(f_4 + g_4, pb_f3_g3) / 4.0
1118  + PoissonBracket(f_3, pb_f3_f3_g3) / 24.0
1119  + PoissonBracket(f_3 + g_3, pb_g3_f3_g3) / 8.0);
1120  }
1121  }
1122  }
1123 
1124  return h;
1125 }
1126 
1127 
1128 template <int N>
1131  FLieGenerator<double, N> H_2(HH, 2);
1132 
1133  for(int i = 0; i < N; ++i) {
1134  if(! H_2.derivative(2 * i).isZero() &&
1135  ! H_2.derivative(2 * i + 1).isZero()) {
1136  return factorBerzForestIrwin(HH);
1137  }
1138  }
1139 
1140  return factorDouglas(HH);
1141 }
1142 
1143 
1144 template <int N>
1149 
1150  for(int j = 0; j < 2 * N; ++j) {
1151  for(int i = 0; i < 2 * N; ++i) {
1152  B(i, j) = (A(i, j) - C(i, j) / 12.0) / 2.0;
1153  C(i, j) = - B(i, j);
1154  }
1155 
1156  B(j, j) = B(j, j) + 1.0;
1157  C(j, j) = C(j, j) + 1.0;
1158  }
1159 
1161  LU.backSubstitute(B);
1162  return B;
1163 }
1164 
1165 template <int N>
1169 
1170  // OK, we need to know the Giorgilli numbering scheme for this
1171  // to work right. I think I know it...
1172 
1173  unsigned gior_min = 2 * N + 1;
1174  for(unsigned i = 0, ig = gior_min ; i < N ; ++i) {
1175  M(2 * i + 1, 2 * i) = 2.0 * f_2[ig++];
1176  for(unsigned j = 2 * i + 1 ; j < 2 * N ; ++j) {
1177  M(2 * i + 1, j) = f_2[ig];
1178  M(j + 1 - 2 * (j % 2), 2 * i) = (1 - 2 * (static_cast<int>(j) % 2)) * f_2[ig++];
1179  }
1180  M(2 * i, 2 * i + 1) = -2.0 * f_2[ig++];
1181  for(unsigned j = 2 * i + 2 ; j < 2 * N ; ++j) {
1182  M(2 * i, j) = -f_2[ig];
1183  M(j + 1 - 2 * (j % 2), 2 * i + 1) = (1 - 2 * (static_cast<int>(j) % 2)) * f_2[ig++];
1184  }
1185  }
1186 
1187  return M;
1188 }
1189 
1190 template <>
1193 
1194 template <int N>
1195 void DragtFinnMap<N>::
1197  // Use method of L. Healy for moving the g_1 term over the f map.
1198  int order = f.getOrder();
1199 
1200  // Split first-order terms f_1 and g_1 from maps.
1204  g.assign(g.getGenerators().filter(3, g.getOrder()));
1205 
1206  // Switch on highest order in left-hand side.
1207  DragtFinnMap<N> h;
1208  FLieGenerator<double, N> g_neg = - g_1;
1209 
1210  switch(order) {
1211 
1212  case 6:
1213  // Move g_1 accross f_6.
1214  {
1216  h += j;
1217  for(int i = 1; i <= 5; ++i) {
1218  j = PoissonBracket(g_neg, j) / double(i);
1219  h += j;
1220  }
1221  }
1222  // Fall through to order = 5.
1223 
1224  case 5:
1225  // Move g_1 accross f_5.
1226  {
1228  h += j;
1229  for(int i = 1; i <= 4; ++i) {
1230  j = PoissonBracket(g_neg, j) / double(i);
1231  h += j;
1232  }
1233  }
1234  // Fall through to order = 4.
1235 
1236  case 4:
1237  // Move g_1 accross f_4.
1238  {
1240  FLieGenerator<double, N> j_3 = PoissonBracket(g_neg, j_4);
1241  FLieGenerator<double, N> j_2 = PoissonBracket(g_neg, j_3) / 2.0;
1242  FLieGenerator<double, N> j_1 = PoissonBracket(g_neg, j_2) / 3.0;
1243  h += j_4;
1244  h += j_3;
1245  h += j_2;
1246  h += j_1;
1247 
1248  if(order >= 6) {
1249  h += PoissonBracket(j_4, j_3);
1250  h += PoissonBracket(j_4, j_2);
1251  h += PoissonBracket(j_4, j_1);
1252  h += PoissonBracket(j_3, j_2);
1253  h += PoissonBracket(j_3, j_1);
1254  h += PoissonBracket(j_2, j_1);
1255  }
1256  }
1257  // Fall through to order = 3.
1258 
1259  case 3:
1260 
1261  // Move g_1 across f_3.
1262  {
1263  // factorize j_(1...3), result is k_(1...5).
1265  FLieGenerator<double, N> j_2 = PoissonBracket(g_neg, j_3);
1266  FLieGenerator<double, N> j_1 = PoissonBracket(g_neg, j_2) / 2.0;
1267 
1268  FLieGenerator<double, N> k_4, k_5;
1269  FLieGenerator<double, N> k_3 = j_3;
1270  FLieGenerator<double, N> k_2 = j_2;
1271  FLieGenerator<double, N> k_1 = j_1;
1272 
1273  if(order >= 4) {
1274  FLieGenerator<double, N> pb_21 = PoissonBracket(j_2, j_1);
1275  FLieGenerator<double, N> pb_31 = PoissonBracket(j_3, j_1);
1276  FLieGenerator<double, N> pb_32 = PoissonBracket(j_3, j_2);
1277  k_1 += pb_21 / 2.0;
1278  k_2 += pb_31 / 2.0;
1279  k_3 += pb_32 / 2.0;
1280 
1281  if(order >= 5) {
1282  FLieGenerator<double, N> pb_131 = PoissonBracket(j_1, pb_31);
1283  FLieGenerator<double, N> pb_221 = PoissonBracket(j_2, pb_21);
1284  FLieGenerator<double, N> pb_231 = PoissonBracket(j_2, pb_31);
1285  FLieGenerator<double, N> pb_232 = PoissonBracket(j_2, pb_32);
1286  FLieGenerator<double, N> pb_321 = PoissonBracket(j_3, pb_21);
1287  FLieGenerator<double, N> pb_331 = PoissonBracket(j_3, pb_31);
1288  FLieGenerator<double, N> pb_332 = PoissonBracket(j_3, pb_32);
1289 
1290  k_1 -= (pb_131 - pb_221) / 6.0;
1291  k_2 -= (pb_231 - 2.0 * pb_321) / 12.0;
1292  k_3 -= (pb_232 - pb_331) / 6.0;
1293  k_4 -= pb_332 / 12.0;
1294 
1295  if(order >= 6) {
1296  k_1 -= (3.0 * PoissonBracket(j_1, pb_321)
1297  + PoissonBracket(j_2, pb_131 - pb_221)) / 24.0;
1298  k_2 -= (PoissonBracket(j_2, pb_321)
1299  - PoissonBracket(j_3, pb_131 - pb_221)) / 24.0;
1300  k_3 += (PoissonBracket(j_2, pb_232 - 3.0 * pb_331)
1301  + PoissonBracket(j_3, pb_231 + pb_321)) / 24.0;
1302  k_4 += PoissonBracket(j_3, pb_232 - pb_331) / 24.0;
1303  k_5 = PoissonBracket(j_3, pb_332) / 24.0;
1304  }
1305  }
1306  }
1307 
1308  // Concatenate f_k with h = f_4 ... f_6.
1309  // Third and higher orders.
1310  h += k_1;
1311  h += k_2;
1312  h += k_3;
1313 
1314  if(order >= 4) {
1315  h += k_4;
1316 
1317  if(order >= 5) {
1320  FLieGenerator<double, N> pb_22 = PoissonBracket(k_2, f_2);
1321  FLieGenerator<double, N> pb_33 = PoissonBracket(k_3, f_3);
1322 
1323  h += pb_22 / 2.0;
1324  h += PoissonBracket(k_3, f_2);
1325  h += pb_33 / 2.0;
1326  h += k_5;
1327 
1328  if(order >= 6) {
1329  h += PoissonBracket(f_2, pb_22) / 12.0;
1330  h -= PoissonBracket(f_3, pb_33) / 6.0;
1331  }
1332  }
1333  }
1334 
1335  // Modify the first-order terms.
1336  g_1 += h.getGenerator(1);
1337 
1338  // Make matrix from h_2;
1340  f.assign(exponentiate(makeMatrix(h_2)) * f.getMatrix());
1341 
1342  // Assign the modified terms to f.
1343  f.assign(h.getGenerators().filter(3, order));
1344  }
1345 
1346  default:
1347  // for order < 3 do nothing.
1348  // for order > 6 the method is not implemented.
1349  break;
1350  }
1351 
1352  // Move first-order terms in g_1 across h_2 and combine with f_1.
1353  f.assign(f_1 + g_1.transform(f_mat));
1354 }
1355 
1356 
1357 template <int N>
1359 orderModes(FMatrix<double, 2 * N, 2 * N> &V, FVector<std::complex<double>, 2 * N> &mu) {
1360  // Static constant.
1361  static const double tol = 1.0e-12;
1362 
1364  FVector<std::complex<double>, 2 * N> tmu(mu);
1365  int nDim = 2 * N;
1366  int n_c = 0;
1367  int n_r = 0;
1368 
1369  for(int i = 0; i < 2 * N;) {
1370  if(std::abs(tmu[i]) < tol) {
1371  // Collect "coasting" modes in upper indices of V.
1372  nDim--;
1373  mu[nDim] = 0.0;
1374  for(int j = 0; j < 2 * N; ++j) V(j, nDim) = 0.0;
1375  V(nDim, nDim) = 1.0;
1376  i++;
1377  } else if(std::abs(std::imag(tmu[i])) < tol) {
1378  // Collect "unstable" modes in lower indices of tmat.
1379  if(n_r != i) {
1380  tmu[n_r] = tmu[i];
1381  for(int j = 0; j < 2 * N; ++j) tmat(j, n_r) = tmat(j, i);
1382  }
1383  n_r++;
1384  i++;
1385  } else if (i + 1 < 2 * N) {
1386  // Collect "stable" modes in lower indices of V.
1387  mu[n_c] = tmu[i];
1388  mu[n_c+1] = tmu[i+1];
1389 
1390  // Normalise.
1391  double pb = 0.0;
1392  for(int j = 0; j < 2 * N; j += 2) {
1393  pb += tmat(j, i) * tmat(j + 1, i + 1) - tmat(j + 1, i) * tmat(j, i + 1);
1394  }
1395  double fact = 1.0 / sqrt(std::abs(pb));
1396 
1397  for(int j = 0; j < 2 * N; j++) {
1398  V(j, n_c) = tmat(j, i) * fact;
1399  V(j, n_c + 1) = tmat(j, i + 1) * fact;
1400  }
1401 
1402  i += 2;
1403  n_c += 2;
1404  }
1405  }
1406 
1407  // Order and copy "unstable" modes.
1408  for(int i = 0; i < n_r;) {
1409  int m = i + 1;
1410  for(; m < n_r && m < 2 * N; ++m) {
1411  if(std::abs(tmu[i] + tmu[m]) < tol) break;
1412  }
1413 
1414  if(m >= n_r) {
1415  throw LogicalError("FNormalForm::orderModes()",
1416  "Cannot find pair of real eigenvalues.");
1417  }
1418 
1419  // Swap values to make pair.
1420  if(m != i + 1) {
1421  std::swap(tmu[m], tmu[i+1]);
1422  tmat.swapColumns(m, i + 1);
1423  }
1424 
1425  // Take positive eigenvalue first.
1426  int i1 = i;
1427  int i2 = i;
1428  if(std::real(tmu[i]) > 0.0) {
1429  ++i2;
1430  } else {
1431  ++i1;
1432  }
1433  mu[n_c] = tmu[i2];
1434  mu[n_c+1] = tmu[i1];
1435 
1436  // Normalise this real pair.
1437  double pb = 0.0;
1438  for(int j = 0; j < 2 * N; j += 2) {
1439  pb += tmat(j, i1) * tmat(j + 1, i2) - tmat(j + 1, i1) * tmat(j, i2);
1440  }
1441 
1442  // Take factors such as to make the resulting pb = - 1.0;
1443  double fact1 = - 1.0 / sqrt(std::abs(2.0 * pb));
1444  double fact2 = (pb > 0.0) ? (- fact1) : fact1;
1445  for(int j = 0; j < 2 * N; ++j) {
1446  V(j, n_c) = tmat(j, i1) * fact1 + tmat(j, i2) * fact2;
1447  V(j, n_c + 1) = tmat(j, i1) * fact1 - tmat(j, i2) * fact2;
1448  }
1449 
1450  n_c += 2;
1451  i += 2;
1452  }
1453 
1454  // Re-order eigenvector pairs by their main components.
1455  int modes = nDim / 2;
1456  for(int i = 0; i < nDim; i += 2) {
1457  // Find eigenvector pair with largest component in direction i.
1458  double big = 0.0;
1459  int k = i;
1460  for(int j = i; j < 2 * N; j += 2) {
1461  double c = std::abs(V(i, j) * V(i + 1, j + 1) - V(i, j + 1) * V(i + 1, j));
1462  if(c > big) {
1463  big = c;
1464  k = j;
1465  }
1466  }
1467 
1468  if(k != i) {
1469  // Move eigenvector pair to its place.
1470  std::swap(mu[i], mu[k]);
1471  std::swap(mu[i+1], mu[k+1]);
1472  V.swapColumns(i, k);
1473  V.swapColumns(i + 1, k + 1);
1474  }
1475  }
1476 
1477  return modes;
1478 }
1479 
1480 
1481 template <int N>
1482 std::ostream &operator<<(std::ostream &os, const DragtFinnMap<N> &map) {
1483  // next two lines require changes when g++ library becomes standard.
1484  std::streamsize old_prec = os.precision(14);
1485  os.setf(std::ios::floatfield, std::ios::scientific);
1486 
1487  os << "Map" << std::endl
1488  << map.getMatrix() << std::endl
1489  << map.getGenerators() << std::endl;
1490 
1491  os.precision(old_prec);
1492  // next line requires change when g++ library becomes standard.
1493  os.setf(std::ios::floatfield, std::ios::fixed);
1494  return os;
1495 }
1496 
1497 #endif // CLASSIC_DragtFinnMap_HH
void fp1(BareField< T, 1U > &field, bool docomm=true)
Definition: FieldDebug.hpp:43
T sum() const
Return sum of series.
Definition: Taylor.hpp:185
static int orderModes(FMatrix< double, 2 *N, 2 *N > &, FVector< std::complex< double >, 2 *N > &)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
DragtFinnMap catenateZero(const DragtFinnMap &) const
int getMaxOrder() const
Get maximum order.
Definition: FTps.h:174
Definition: rbendmap.h:8
void swapColumns(int c1, int c2)
Exchange columns.
Definition: FArray2D.h:403
A templated representation for vectors.
Definition: PartBunchBase.h:26
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
Definition: rbendmap.h:8
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
FLieGenerator< U, N > transform(const FMatrix< U, 2 *N, 2 *N > &) const
Substitute matrix in Lie generator.
Eigenvalues and eigenvectors for a real general matrix.
Definition: FDoubleEigen.h:35
Representation of the exponents for a monomial with fixed dimension.
Definition: FMonomial.h:32
FLieGenerator scale(const FLieGenerator &) const
Scale monomial-wise.
static DragtFinnMap factorSimple(const FTps< double, 2 *N > &H)
Definition: DragtFinnMap.h:652
const FMatrix< double, 2 *N, 2 *N > & getMatrix() const
Return the matrix representing the linear transform.
Definition: DragtFinnMap.h:671
void operator-=(const FTps< double, 2 *N > &)
Subtract from set of generators.
Definition: DragtFinnMap.h:766
void assign(const BareField< T, Dim > &a, RHS b, OP op, ExprTag< true >)
static DragtFinnMap factorize(const FTps< double, 2 *N > &H)
DragtFinnMap catenate(const DragtFinnMap &) const
Substitute (concatenate) with another map in beam order.
Definition: DragtFinnMap.h:813
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
Tps< T > cosh(const Tps< T > &x)
Hyperbolic cosine.
Definition: TpsMath.h:222
FLieGenerator derivative(int var) const
Partial derivative.
static void move_g_1(DragtFinnMap &f, DragtFinnMap &g)
static DragtFinnMap factorBerzForestIrwin(const FTps< double, 2 *N > &H)
Definition: DragtFinnMap.h:426
void assign(const FMatrix< double, 2 *N, 2 *N > &)
Assign the matrix representing the linear transform.
Definition: DragtFinnMap.h:395
static int getSize(int order)
Definition: FTpsData.h:189
Tps< T > PoissonBracket(const Tps< T > &x, const Tps< T > &y)
Poisson bracket.
Definition: LieMap.h:154
const FTps< double, 2 *N > & getGenerators() const
Return the complete set of generators.
Definition: DragtFinnMap.h:685
A templated representation of a LU-decomposition.
Definition: FLUMatrix.h:42
const double * end(int) const
Linear map with values of type [b]T[/b] in [b]N[/b] variables.
const DragtFinnMap & operator=(const DragtFinnMap &)
Definition: DragtFinnMap.h:279
const double pi
Definition: fftpack.cpp:894
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
void removeDispersion(DragtFinnMap &dm, DragtFinnMap &map)
Split map into dispersion map and non-dispersive part.
Definition: DragtFinnMap.h:892
DragtFinnMap reverse() const
Compute inverse factorisation of map.
Definition: DragtFinnMap.h:733
void unique()
Make representation unique.
Definition: FTps.hpp:1505
int getOrder() const
Return order of this generator.
void backSubstitute(FVector< T, N > &B) const
Back substitution.
Definition: FLUMatrix.h:222
FVps< T, N > ExpMap(const FTps< T, N > &H, int trunc=FTps< T, N >::EXACT)
Build the exponential series.
Definition: FTps.hpp:1994
DragtFinnMap transform(const FLieGenerator< double, N > &g, int topOrder)
Build the terminating exponential series.
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
FMatrix< double, N, N > packedEigenVectors() const
Get eigenvectors.
Definition: FDoubleEigen.h:217
bool isZero() const
Test for zero.
FTps substitute(const FMatrix< T, N, N > &M, int n) const
Substitute.
Definition: FTps.hpp:1075
FVps filter(int minOrder, int maxOrder, int trcOrder=(FTps< T, N >::EXACT)) const
Extract given range of orders, with truncation.
Definition: FVps.hpp:223
static FMatrix< double, 2 *N, 2 *N > makeMatrix(const FLieGenerator< double, N > &f_2)
int precision() const
Definition: Inform.h:115
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
A representation for a homogeneous polynomial, used as a Lie generator.
Definition: DragtFinnMap.h:29
static const FMonomial< N > & getExponents(int index)
Definition: FTpsData.h:160
const FLieGenerator< double, N > getGenerator(int) const
Return the generator for a selected order.
Definition: DragtFinnMap.h:699
DragtFinnMap inverse() const
Compute inverse map.
Definition: DragtFinnMap.h:721
static FMatrix< double, 2 *N, 2 *N > exponentiate(const FMatrix< double, 2 *N, 2 *N > &)
FTps filter(int minOrder, int maxOrder, int trcOrder=EXACT) const
Extract given range of orders, with truncation.
Definition: FTps.hpp:451
void operator+=(const FTps< double, 2 *N > &)
Add to set of generators.
Definition: DragtFinnMap.h:759
FTps< double, 2 *N > itsGenerators
Definition: DragtFinnMap.h:222
DragtFinnMap conjugate(const DragtFinnMap &) const
Conjugate with another map.
Definition: DragtFinnMap.h:828
void staticFixedPoint(FVector< double, 2 *N > &fp, DragtFinnMap &map)
Compute static fixed point.
Definition: DragtFinnMap.h:858
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
T * begin()
Get pointer to beginning of generator.
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
DragtFinnMap()
Construct identity map.
Definition: DragtFinnMap.h:257
A representation for a Taylor series in one variable,.
Definition: Taylor.h:36
FMatrix< T, N, N > inverse() const
Get inverse.
Definition: FLUMatrix.h:236
void dynamicFixedPoint(FVector< double, 2 *N > &fp, DragtFinnMap &map)
Compute dynamic fixed point.
Definition: DragtFinnMap.h:835
A Lie algebraic map, factored according to Dragt and Finn.
Definition: DragtFinnMap.h:43
T * end()
Get pointer past end of generator.
static DragtFinnMap factorDouglas(const FTps< double, 2 *N > &H)
Definition: DragtFinnMap.h:555
const double * begin(int) const
FVps substitute(const FMatrix< T, N, N > &M, int n) const
Substitute.
Definition: FVps.hpp:608
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &)
Take imaginary part of a complex generator.
FMatrix< double, 2 *N, 2 *N > itsMatrix
Definition: DragtFinnMap.h:219
int getOrder() const
Return the order of the generators.
Definition: DragtFinnMap.h:714
Logical error exception.
Definition: LogicalError.h:33
FVector< std::complex< double >, N > eigenValues() const
Get eigenvalues.
Definition: FDoubleEigen.h:183
Tps< T > sinh(const Tps< T > &x)
Hyperbolic sine.
Definition: TpsMath.h:204
Vector truncated power series in n variables.
void trackOrbit(FVector< double, 2 *N > &orbit, DragtFinnMap &map)
Track an orbit through the map.
Definition: DragtFinnMap.h:966
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
T * begin() const
Return beginning of monomial array.
Definition: FTps.h:118