OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
46void 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 (nullptr);
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 (nullptr);
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
321void 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}
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &)
Take imaginary part of a complex generator.
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
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
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)