1 #ifndef MAD_DragtFinnNormalForm_HH
2 #define MAD_DragtFinnNormalForm_HH
29 template <
class T,
int,
int>
class FMatrix;
34 const double tol = 1.0e-8;
119 #include <functional>
127 freedom(0), A_scr(), N_scr(), lambda(), V()
133 freedom(form.freedom), A_scr(form.A_scr), N_scr(form.N_scr),
134 lambda(form.lambda), V(form.V)
140 freedom(N), A_scr(), N_scr(), lambda(), V() {
151 V_inv = lu.inverse();
157 for(
int i = 0; i < N; ++i) {
158 Rot(i, i) = R_dir(i, i) = I_dir(i, i) = R_inv(i, i) = 1.0;
163 for(
int i = 0; i < 2 *
freedom; i += 2) {
165 R_dir(i, i) = R_dir(i, i + 1) = R_dir(i + 1, i) = 0.5;
166 R_dir(i + 1, i + 1) = -0.5;
167 R_inv(i, i) = R_inv(i, i + 1) = R_inv(i + 1, i) = 1.0;
168 R_inv(i + 1, i + 1) = -1.0;
176 I_dir(i, i) = I_dir(i + 1, i + 1) = 0.0;
177 I_dir(i, i + 1) = I_dir(i + 1, i) = 1.0;
193 for(
int omega = 2; omega < maxOrder; omega++) {
205 std::complex<double> factor = 1.0;
208 for(
int j = 0; j < 2 *
freedom; j += 2) {
218 factor = 1.0 / (1.0 - factor);
223 pi[m] =
std::pow(-1.0,
int(count + 1) / 2);
233 A_scr.assign(F_omega);
236 N_scr = N_scr.
transform(- F_omega, maxOrder);
258 for(
int mode1 = 0; mode1 < freedom; mode1++) {
261 power1[2*mode1] = power3[2*mode1+1] = 4;
262 power2[2*mode1] = power2[2*mode1+1] = 2;
263 QQ(mode1, mode1) = (- 3.0 / (4.0 *
pi)) *
264 (N_tps[power1] + N_tps[power3] + N_tps[power2]);
267 for(
int mode2 = mode1 + 1; mode2 < freedom; mode2++) {
269 power1[2*mode1] = power1[2*mode2] = 2;
270 power2[2*mode1+1] = power2[2*mode2] = 2;
271 power3[2*mode1] = power3[2*mode2+1] = 2;
272 power4[2*mode1+1] = power4[2*mode2+1] = 2;
273 QQ(mode1, mode2) = QQ(mode2, mode1) = (- 1.0 / (4.0 *
pi)) *
274 (N_tps[power1] + N_tps[power2] + N_tps[power3] + N_tps[power4]);
287 for(
int j = 0; j < 2 * N; j += 2) {
288 a[j+1] = - V(j + 1, 2 * mode);
289 a[j+2] = V(j, 2 * mode);
290 b[j+1] = - V(j + 1, 2 * mode + 1);
291 b[j+2] = V(j, 2 * mode + 1);
295 return (a * a + b * b);
297 return (a * a - b * b);
334 for(
int i = 0; i < 2 * N;) {
339 std::fill(V.col_begin(nDim), V.col_end(nDim), 0.0);
353 for(
int j = 0; j < 2 * N; j += 2) {
354 pb += tmat(j, i) * tmat(j + 1, i + 1) - tmat(j + 1, i) * tmat(j, i + 1);
365 lambda[n_c] = tlam[i1];
366 lambda[n_c+1] = tlam[i2];
370 for(
int j = 0; j < 2 * N; j++) {
371 V(j, n_c) = tmat(j, i1) / fact;
372 V(j, n_c + 1) = tmat(j, i2) / fact;
381 for(
int i = 0; i < n_r;) {
383 for(m = i + 1; m < n_r; ++m) {
384 if(
std::abs(tlam[i] * tlam[m] - 1.0) < tol)
break;
389 "Cannot find pair of real eigenvalues.");
394 std::swap(tlam[m], tlam[i+1]);
400 for(
int j = 0; j < 2 * N; j += 2) {
401 pb += tmat(j, i) * tmat(j + 1, i + 1) - tmat(j + 1, i) * tmat(j, i + 1);
412 lambda[n_c] = tlam[i1];
413 lambda[n_c+1] = tlam[i2];
417 for(
int j = 0; j < 2 * N; ++j) {
418 V(j, n_c) = (tmat(j, i1) + tmat(j, i2)) / fact;
419 V(j, n_c + 1) = (tmat(j, i1) - tmat(j, i2)) / fact;
427 if(nDim != 2 * freedom) {
429 "Map dimension is odd.");
433 for(
int i = 0; i < nDim; i += 2) {
437 for(
int j = i; j < 2 * N; j += 2) {
438 double c =
std::abs(V(i, j) * V(i + 1, j + 1) - V(i, j + 1) * V(i + 1, j));
448 std::swap(lambda[i], lambda[k]);
449 std::swap(lambda[i+1], lambda[k+1]);
451 V.swapColumns(i + 1, k + 1);
456 double re = V(i, i) /
sqrt(V(i, i) * V(i, i) + V(i, i + 1) * V(i, i + 1));
457 double im = V(i, i + 1) /
sqrt(V(i, i) * V(i, i) + V(i, i + 1) * V(i, i + 1));
459 for(
int j = 0; j < 2 * N; j++) {
460 double real_part = re * V(j, i) + im * V(j, i + 1);
461 double imag_part = re * V(j, i + 1) - im * V(j, i);
463 V(j, i + 1) = imag_part;
469 #endif // MAD_DragtFinnNormalForm_HH
FVector< std::complex< double >, 2 *N > lambda
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
col_iterator col_end(int c)
Get column iterator.
A templated representation for matrices.
FLieGenerator< double, N > invariant(int i) const
Get invariant polynomial for mode i.
void swapColumns(int c1, int c2)
Exchange columns.
A templated representation for vectors.
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.
FMatrix< double, 2 *N, 2 *N > V
Representation of the exponents for a monomial with fixed dimension.
FLieGenerator scale(const FLieGenerator &) const
Scale monomial-wise.
const FMatrix< double, 2 *N, 2 *N > & getMatrix() const
Return the matrix representing the linear transform.
void orderModes(FVector< std::complex< double >, 2 *N >, FMatrix< double, 2 *N, 2 *N >)
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
int degreesOfFreedom() const
Get number of stable degrees of freedom.
void assign(const FMatrix< double, 2 *N, 2 *N > &)
Assign the matrix representing the linear transform.
const FTps< double, 2 *N > & getGenerators() const
Return the complete set of generators.
const DragtFinnMap< N > & normalisingMap() const
Get normalising map as a Lie transform.
A templated representation of a LU-decomposition.
constexpr double pi
The value of .
Normal form of a truncated Taylor series map.
constexpr double c
The velocity of light in m/s.
const FVector< std::complex< double >, 2 *N > & eigenValues() const
Get eigenvalues of the linear part as a complex vector.
FMatrix< double, N, N > anharmonicity() const
Get anharmonicities as a matrix.
col_iterator col_begin(int c)
Get column iterator.
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.
FMatrix< double, N, N > packedEigenVectors() const
Get eigenvectors.
MMatrix< double > im(MMatrix< m_complex > mc)
FTps substitute(const FMatrix< T, N, N > &M, int n) const
Substitute.
Tps< T > sqrt(const Tps< T > &x)
Square root.
A representation for a homogeneous polynomial, used as a Lie generator.
static const FMonomial< N > & getExponents(int index)
MMatrix< double > re(MMatrix< m_complex > mc)
const FLieGenerator< double, N > getGenerator(int) const
Return the generator for a selected order.
A Lie algebraic map, factored according to Dragt and Finn.
int getBottomIndex() const
Return bottom index of this generator.
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &)
Take imaginary part of a complex generator.
int getTopIndex() const
Return top index of this generator.
int getOrder() const
Return the order of the generators.
const FMatrix< double, 2 *N, 2 *N > & eigenVectors() const
Get eigenvectors of the linear part in packed form.
FVector< std::complex< double >, N > eigenValues() const
Get eigenvalues.
void operator=(const DragtFinnNormalForm &)
const DragtFinnMap< N > & normalForm() const
Get normal-form map as a Lie transform.