OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
MapAnalyser.cpp
Go to the documentation of this file.
1 //
2 // Class: MapAnalyser
3 // Organizes the function for a linear map analysis from
4 // ThickTracker.
5 // Transfer map -> tunes, symplecticity and stability
6 // Sigma Matrix -> (not projected) beam emittance
7 //
8 // This class is in an unfinished state.
9 // For some dicussion see https://gitlab.psi.ch/OPAL/src/issues/464
10 // Some cleanup was done in https://gitlab.psi.ch/OPAL/src/merge_requests/294
11 //
12 // Copyright (c) 2018, Philippe Ganz, ETH Zürich
13 // All rights reserved
14 //
15 // Implemented as part of the Master thesis
16 // "s-based maps from TPS & Lie-Series applied to Proton-Therapy Gantries"
17 //
18 // This file is part of OPAL.
19 //
20 // OPAL is free software: you can redistribute it and/or modify
21 // it under the terms of the GNU General Public License as published by
22 // the Free Software Foundation, either version 3 of the License, or
23 // (at your option) any later version.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
27 //
28 
29 #include "MapAnalyser.h"
30 
31 #include <fstream>
32 
33 #include "Physics/Physics.h"
34 
35 #include <gsl/gsl_math.h>
36 #include <gsl/gsl_eigen.h>
37 #include <gsl/gsl_linalg.h>
38 
39 
41  : mapAnalysis_m(IpplTimings::getTimer("mapAnalysis"))
42  , bunchAnalysis_m(IpplTimings::getTimer("bunchAnalysis"))
43 { }
44 
45 //Returns the eigenDecompositon for the fMatrix M = eigenVec * eigenVal * invEigenVec
46 void MapAnalyser::eigenDecomp_m(const fMatrix_t& M, cfMatrix_t& eigenVal, cfMatrix_t& eigenVec, cfMatrix_t& invEigenVec){
47 
48  double data[36];
49  int idx, s;
50  for (int i = 0; i < 6; i++) {
51  for (int j = 0; j < 6; j++) {
52  idx = i * 6 + j;
53  data[idx] = M[i][j];
54  }
55  }
56 
57  gsl_matrix_view m = gsl_matrix_view_array(data, 6, 6);
58  gsl_vector_complex *eval = gsl_vector_complex_alloc(6);
59  gsl_matrix_complex *evec = gsl_matrix_complex_alloc(6, 6);
60  gsl_matrix_complex *eveci = gsl_matrix_complex_alloc(6, 6);
61  gsl_permutation * p = gsl_permutation_alloc(6);
62  gsl_eigen_nonsymmv_workspace * w = gsl_eigen_nonsymmv_alloc(6);
63 
64  //get Eigenvalues and Eigenvectors
65  gsl_eigen_nonsymmv(&m.matrix, eval, evec, w);
66  gsl_eigen_nonsymmv_free(w);
67  gsl_eigen_nonsymmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);
68 
69  for (int i = 0; i < 6; ++i) {
70  eigenVal[i][i] = std::complex<double>(
71  GSL_REAL(gsl_vector_complex_get(eval, i)),
72  GSL_IMAG(gsl_vector_complex_get(eval, i)));
73  for (int j = 0; j < 6; ++j) {
74  eigenVec[i][j] = std::complex<double>(
75  GSL_REAL(gsl_matrix_complex_get(evec, i, j)),
76  GSL_IMAG(gsl_matrix_complex_get(evec, i, j)));
77  }
78  }
79 
80  //invert Eigenvectormatrix
81  gsl_linalg_complex_LU_decomp(evec, p, &s);
82  gsl_linalg_complex_LU_invert(evec, p, eveci);
83 
84  //Create invEigenVecMatrix
85  for (int i = 0; i < 6; ++i) {
86  for (int j = 0; j < 6; ++j) {
87  invEigenVec[i][j] = std::complex<double>(
88  GSL_REAL(gsl_matrix_complex_get(eveci, i, j)),
89  GSL_IMAG(gsl_matrix_complex_get(eveci, i, j)));
90  }
91  }
92 
93  //free space
94  gsl_vector_complex_free(eval);
95  gsl_matrix_complex_free(evec);
96  gsl_matrix_complex_free(eveci);
97 }
98 
99 
100 //Transforms the Matirx to a block diagonal rotation Matrix
102  cfMatrix_t& eigenVecM, cfMatrix_t& invEigenVecM){
103 
104  cfMatrix_t cM, qMatrix, invqMatrix, nMatrix, invnMatrix, rMatrix;
105 
106  for (int i = 0; i < 6; i++){
107  for (int j = 0; j < 6; j++){
108  cM[i][j]=std::complex<double>(M[i][j], 0);
109  }
110  }
111 
112  for (int i = 0; i < 6; i = i+2){
113  qMatrix[ i][ i] = std::complex<double>(1., 0);
114  qMatrix[ i][1+i] = std::complex<double>(0, 1.);
115  qMatrix[1+i][ i] = std::complex<double>(1., 0);
116  qMatrix[1+i][1+i] = std::complex<double>(0, -1);
117 
118  invqMatrix[ i][ i] = std::complex<double>(1., 0);
119  invqMatrix[ i][1+i] = std::complex<double>(1., 0);
120  invqMatrix[1+i][ i] = std::complex<double>(0., -1.);
121  invqMatrix[1+i][1+i] = std::complex<double>(0, 1.);
122  }
123  qMatrix /= std::sqrt(2.);
124  invqMatrix /= std::sqrt(2);
125 
126  nMatrix = eigenVecM*qMatrix;
127  invnMatrix = invqMatrix* invEigenVecM;
128 
129 
130  rMatrix = invnMatrix * cM * nMatrix;
131 
132  return rMatrix;
133 }
134 
135 
137  cfMatrix_t N1, cinvN, cR, ctM, N2;
138  fMatrix_t R1, S, sigmaS;
139 
140  for (int i = 0; i < 6; i++){
141  for (int j = 0; j < 6; j++){
142  ctM[i][j] = std::complex<double>(tM[i][j], 0);
143  }
144  }
145 
146  S = createSkewMatrix_m();
147  sigmaS = Sigma*S;
148 
149  setNMatrix_m(sigmaS, N2, cinvN);
150 
151  std::array<double, 3> phi;
152 
153  for (int i = 0; i < 3; i++){
154  phi[i] = std::atan(oldN[2*i+1][i].real()/oldN[2*i][2*i].real());
155  }
156 
157  R1 = createRotMatrix_m(phi);
158 
159  for (int i = 0; i < 6; i++){
160  for (int j = 0; j < 6; j++){
161  cR[i][j] = std::complex<double>(R1[i][j], 0);
162  N1[i][j] = oldN[i][j].real();
163  }
164  }
165 }
166 
167 
169 
170  cfMatrix_t eigenValM, eigenVecM, invEigenVecM, eigenVecMT;
171 
172  eigenDecomp_m(M, eigenValM, eigenVecM, invEigenVecM);
173 
174  cfMatrix_t cM, qMatrix, invqMatrix, nMatrix, invnMatrix, rMatrix;
175 
176  //std::ofstream tmap;
177  //tmap.open ("TransferMap.txt",std::ios::app);
178  //tmap << std::setprecision(16);
179 
180 
181  for (int i = 0; i < 6; i++){
182  for (int j = 0; j < 6; j++){
183  cM[i][j] = std::complex<double>(M[i][j], 0);
184  }
185  }
186 
187  for (int i = 0; i < 6; i = i+2){
188  qMatrix[ i][ i] = std::complex<double>(1., 0);
189  qMatrix[ i][1+i] = std::complex<double>(0, 1.);
190  qMatrix[1+i][ i] = std::complex<double>(1., 0);
191  qMatrix[1+i][1+i] = std::complex<double>(0, -1);
192 
193  invqMatrix[ i][ i] = std::complex<double>(1., 0);
194  invqMatrix[ i][1+i] = std::complex<double>(1., 0);
195  invqMatrix[1+i][ i] = std::complex<double>(0., -1.);
196  invqMatrix[1+i][1+i] = std::complex<double>(0, 1.);
197  }
198  qMatrix /= std::sqrt(2);
199  invqMatrix /= std::sqrt(2);
200 
201 
202  N = eigenVecM*qMatrix;
203  invN = invqMatrix* invEigenVecM;
204 }
205 
206 
208  fMatrix_t R;
209 
210  for (int i = 0; i < 3; i++){
211  R[2*i][2*i] = std::cos(phi[1]);
212  R[2*i+1][2*i+1] = R[2*i][2*i];
213  R[2*i][2*i+1] = std::sin(phi[1]);
214  R[2*i+1][2*i] = -R[2*i][2*i+1];
215  }
216  return R;
217 }
218 
219 
221  fMatrix_t S;
222 
223  for (int i = 0; i < 3; i++){
224  S[2*i][2*i+1] = 1;
225  S[2*i+1][2*i] = -1;
226  }
227  return S;
228 }
229 
230 
232  fMatrix_t M;
233  for (int i = 0; i < 6; i++){
234  for (int j = 0; j < 6; j++){
235  M[i][j] = cM[i][j].real();
236  }
237  }
238  return M;
239 }
240 
242  fMatrix_t M;
243  for (int i = 0; i < 6; i++){
244  for (int j = 0; j < 6; j++){
245  M[i][j] = cM[i][j].imag();
246  }
247  }
248  return M;
249 }
250 
252  cfMatrix_t cM;
253  for (int i = 0; i < 6; i++){
254  for (int j = 0; j < 6; j++){
255  cM[i][j] = std::complex<double>(M[i][j], 0);
256  }
257  }
258  return cM;
259 }
260 
262 
263  gsl_set_error_handler_off();
264  //gsl_vector_complex *m = gsl_vector_complex_alloc(6);
265  gsl_matrix_complex *m = gsl_matrix_complex_alloc(6, 6);
266  gsl_matrix_complex *invm = gsl_matrix_complex_alloc(6, 6);
267  gsl_permutation * p = gsl_permutation_alloc(6);
268  gsl_complex temp;
269  int s;
270 
271 
272  //Create invEigenVecMatrix
273  for (int i = 0; i < 6; ++i) {
274  for (int j = 0; j < 6; ++j) {
275  GSL_SET_COMPLEX(&temp, std::real(M[i][j]), std::imag(M[i][j]));
276  gsl_matrix_complex_set( m, i, j, temp);
277  }
278  }
279 
280  //invert Eigenvectormatrix
281  int eigenDecompStatus = gsl_linalg_complex_LU_decomp(m, p, &s);
282  if (eigenDecompStatus != 0){
283  std::cout<< "This actually works" << std::endl;
284  //gsl_set_error_handler (NULL);
285 
286  }
287 
288  int invertStatus = gsl_linalg_complex_LU_invert(m, p, invm);
289 
290  if ( invertStatus ) {
291  std::cout << "Error" << std::endl;
292  std::exit(1);
293  }
294 
295 
296  if (invertStatus != 0){
297  std::cout<< "This actually works" << std::endl;
298  //gsl_set_error_handler (NULL);
299 
300  }
301 
302  cfMatrix_t invM;
303  //Create invEigenVecMatrix
304  for (int i = 0; i < 6; ++i) {
305  for (int j = 0; j < 6; ++j) {
306  invM[i][j] = std::complex<double>(
307  GSL_REAL(gsl_matrix_complex_get(invm, i, j)),
308  GSL_IMAG(gsl_matrix_complex_get(invm, i, j)));
309  }
310  }
311 
312  //free space
313  gsl_matrix_complex_free(m);
314  gsl_matrix_complex_free(invm);
315  gsl_permutation_free(p);
316 
317 
318  return invM;
319 }
320 
321 void MapAnalyser::normalizeEigen_m(cfMatrix_t& eigenVecM, cfMatrix_t& invEigenVecM) {
322  //normalize eigen Vectors
323  for (int i = 0; i < 6; i++){
324  double temp = 0;
325 
326  for (int j = 0; j < 6; j += 2){
327  temp += 2 * (eigenVecM[j][i] * std::conj(eigenVecM[j+1][i])).imag();
328  }
329  temp = std::abs(temp);
330 
331  if (temp > 1e-10){
332  for (int j = 0; j < 6; j++){
333  eigenVecM[j][i] /= std::sqrt(temp);
334  invEigenVecM[j][i] /= std::sqrt(temp);
335  }
336  }
337  }
338 }
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &)
Take imaginary part of a complex generator.
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
m_complex conj(const m_complex &c)
Definition: MVector.h:105
constexpr double e
The value of.
Definition: Physics.h:39
cfMatrix_t invertMatrix_m(const cfMatrix_t &M)
fMatrix_t createSkewMatrix_m()
cfMatrix_t complexTypeMatrix_m(fMatrix_t M)
void printPhaseShift_m(fMatrix_t &Sigma, fMatrix_t tM, cfMatrix_t &oldN)
void normalizeEigen_m(cfMatrix_t &eigenVec, cfMatrix_t &invEigenVec)
cfMatrix_t getBlockDiagonal_m(const fMatrix_t &M, cfMatrix_t &eigenVecM, cfMatrix_t &invEigenVecM)
fMatrix_t realPartOfMatrix_m(cfMatrix_t cM)
void eigenDecomp_m(const fMatrix_t &M, cfMatrix_t &eigenVal, cfMatrix_t &eigenVec, cfMatrix_t &invEigenVec)
Definition: MapAnalyser.cpp:46
fMatrix_t imagPartOfMatrix_m(cfMatrix_t cM)
void setNMatrix_m(fMatrix_t &M, cfMatrix_t &N, cfMatrix_t &invN)
fMatrix_t createRotMatrix_m(std::array< double, 3 > phi)