Documentation of CSL
libdiagonalization_cppdata.h
Go to the documentation of this file.
1 // This file is part of MARTY.
2 //
3 // MARTY is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // MARTY is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with MARTY. If not, see <https://www.gnu.org/licenses/>.
15 
23 #pragma once
24 
25 #include <iostream>
26 
27 namespace csl {
28 
29 void print_libdiagonalization_cppdata(std::ostream &out) {
30  out << "#include <cassert>\n";
31  out << "#include \"libdiagonalization.h\"\n";
32  out << "#include <gsl/gsl_complex.h>\n";
33  out << "#include <gsl/gsl_eigen.h>\n";
34  out << "#include <gsl/gsl_errno.h>\n";
35  out << "#include <gsl/gsl_complex_math.h>\n";
36  out << "#include <iostream>\n";
37  out << "\n";
38  out << "#ifdef QUAD\n";
39  out << " #include <quadmath.h>\n";
40  out << " #define ABS fabsq\n";
41  out << " #define SQRT sqrtq\n";
42  out << " #define REAL(arg) crealq(arg)\n";
43  out << " #define IMAG(arg) cimagq(arg)\n";
44  out << " #define CONJ(arg) conjq(arg)\n";
45  out << "#else\n";
46  out << " #define ABS std::abs\n";
47  out << " #define SQRT std::sqrt\n";
48  out << " #define REAL(arg) (arg).real()\n";
49  out << " #define IMAG(arg) (arg).imag()\n";
50  out << " #define CONJ(arg) std::conj(arg)\n";
51  out << "#endif\n";
52  out << "\n";
53  out << "Diagonalizer::real Diagonalizer::precision = 1e-5;\n";
54  out << "\n";
55  out << "void Diagonalizer::applyDiagonalization(\n";
56  out << " std::initializer_list<complex> massMatrix,\n";
57  out << " std::initializer_list<complex*> transfer,\n";
58  out << " std::initializer_list<real*> masses\n";
59  out << " )\n";
60  out << "{\n";
61  out << " Diagonalizer diag(massMatrix);\n";
62  out << "\n";
63  out << " std::vector<complex> const &t = diag.transfer();\n";
64  out << " size_t i = 0;\n";
65  out << " for (auto iter = transfer.begin(); iter != transfer.end(); ++iter)\n";
66  out << " **iter = t[i++];\n";
67  out << "\n";
68  out << " i = 0;\n";
69  out << " std::vector<real> const &m = diag.mass();\n";
70  out << " for (auto iter = masses.begin(); iter != masses.end(); ++iter)\n";
71  out << " **iter = m[i++];\n";
72  out << "}\n";
73  out << "\n";
74  out << "void Diagonalizer::applyBiDiagonalization(\n";
75  out << " std::initializer_list<complex> massMatrix,\n";
76  out << " std::initializer_list<complex*> transfer,\n";
77  out << " std::initializer_list<complex*> transfer2,\n";
78  out << " std::initializer_list<real*> masses\n";
79  out << " )\n";
80  out << "{\n";
81  out << " Diagonalizer diag(massMatrix, true);\n";
82  out << "\n";
83  out << " std::vector<complex> const &t = diag.transfer();\n";
84  out << " size_t i = 0;\n";
85  out << " for (auto iter = transfer.begin(); iter != transfer.end(); ++iter)\n";
86  out << " **iter = t[i++];\n";
87  out << "\n";
88  out << " i = 0;\n";
89  out << " std::vector<complex> const &t2 = diag.transfer2();\n";
90  out << " for (auto iter = transfer2.begin(); iter != transfer2.end(); ++iter)\n";
91  out << " **iter = t2[i++];\n";
92  out << "\n";
93  out << " i = 0;\n";
94  out << " std::vector<real> const &m = diag.mass();\n";
95  out << " for (auto iter = masses.begin(); iter != masses.end(); ++iter)\n";
96  out << " **iter = m[i++];\n";
97  out << "}\n";
98  out << "\n";
99  out << "Diagonalizer::Diagonalizer(\n";
100  out << " std::initializer_list<complex> massMatrix,\n";
101  out << " bool t_bidiag\n";
102  out << " )\n";
103  out << " :m_data(massMatrix),\n";
104  out << " m_N(std::sqrt(m_data.size())),\n";
105  out << " m_bidiag(t_bidiag),\n";
106  out << " m_computed(false)\n";
107  out << "{\n";
108  out << " assert(m_N * m_N == massMatrix.size());\n";
109  out << "}\n";
110  out << "\n";
111  out << "std::vector<Diagonalizer::complex> const &Diagonalizer::transfer()\n";
112  out << "{\n";
113  out << " updateDiagonalization();\n";
114  out << " return m_transfer;\n";
115  out << "}\n";
116  out << "\n";
117  out << "std::vector<Diagonalizer::complex> const &Diagonalizer::transfer2()\n";
118  out << "{\n";
119  out << " updateDiagonalization();\n";
120  out << " assert(m_bidiag);\n";
121  out << " return m_transfer2;\n";
122  out << "}\n";
123  out << "\n";
124  out << "std::vector<Diagonalizer::real> const &\n";
125  out << " Diagonalizer::mass()\n";
126  out << "{\n";
127  out << " updateDiagonalization();\n";
128  out << " return m_mass;\n";
129  out << "}\n";
130  out << "\n";
131  out << "\n";
132  out << "Diagonalizer::real Diagonalizer::det(\n";
133  out << " std::vector<Diagonalizer::complex> const &mat\n";
134  out << " ) const\n";
135  out << "{\n";
136  out << " return REAL(\n";
137  out << " mat[index(0, 0)]*mat[index(1, 1)]\n";
138  out << " - mat[index(1, 0)]*mat[index(0, 1)]\n";
139  out << " );\n";
140  out << "}\n";
141  out << "\n";
142  out << "void Diagonalizer::updateDiagonalization()\n";
143  out << "{\n";
144  out << " if (!m_computed) {\n";
145  out << " (m_bidiag) ? bidiagonalize() : diagonalize();\n";
146  out << " m_computed = true;\n";
147  out << " }\n";
148  out << "}\n";
149  out << "\n";
150  out << "void Diagonalizer::diagonalize(\n";
151  out << " std::vector<complex> massMatrix,\n";
152  out << " std::vector<complex> &transfer,\n";
153  out << " std::vector<real> &mass,\n";
154  out << " bool bidiagonalization\n";
155  out << " )\n";
156  out << "{\n";
157  out << " transfer = std::vector<complex>(m_N*m_N, 0);\n";
158  out << " mass = std::vector<real>(m_N, 0);\n";
159  out << " gsl_eigen_hermv_workspace* workspace = gsl_eigen_hermv_alloc(m_N);\n";
160  out << "\n";
161  out << " if (!bidiagonalization) {\n";
162  out << " // Symmetrize the mass matrix (if it has not been done yet)\n";
163  out << " const size_t N = std::sqrt(massMatrix.size());\n";
164  out << " for (size_t i = 0; i != N; ++i)\n";
165  out << " for (size_t j = i+1; j < N; ++j) {\n";
166  out << " massMatrix[index(i, j)] = \n";
167  out << " (massMatrix[index(i, j)] + massMatrix[index(j, i)]) / 2.;\n";
168  out << " massMatrix[index(j, i)] = massMatrix[index(i, j)];\n";
169  out << " }\n";
170  out << " }\n";
171  out << " gsl_matrix_complex* init_gsl = getGSLMassMatrix(massMatrix);\n";
172  out << " gsl_vector* eigenValues = gsl_vector_alloc(m_N);\n";
173  out << " gsl_matrix_complex* transfer_gsl = gsl_matrix_complex_alloc(m_N, m_N);\n";
174  out << "\n";
175  out << " // Diagonalization\n";
176  out << " gsl_eigen_hermv(init_gsl, eigenValues, transfer_gsl, workspace);\n";
177  out << "\n";
178  out << " // Gathering results\n";
179  out << " loadGSLMatrix(transfer_gsl, transfer);\n";
180  out << " loadGSLVector(eigenValues, mass);\n";
181  out << "\n";
182  out << " // Freeing allocated memory by gsl\n";
183  out << " gsl_matrix_complex_free(transfer_gsl);\n";
184  out << " gsl_vector_free (eigenValues);\n";
185  out << " gsl_matrix_complex_free(init_gsl);\n";
186  out << " gsl_eigen_hermv_free (workspace);\n";
187  out << "}\n";
188  out << "\n";
189  out << "void Diagonalizer::swap(\n";
190  out << " const size_t i,\n";
191  out << " const size_t j,\n";
192  out << " std::vector<complex> &transfer,\n";
193  out << " std::vector<real> &mass\n";
194  out << " )\n";
195  out << "{\n";
196  out << " const size_t N = mass.size();\n";
197  out << " for (size_t k = 0; k != N; ++k) {\n";
198  out << " std::swap(transfer[index(k, i)], transfer[index(k, j)]);\n";
199  out << " }\n";
200  out << "}\n";
201  out << "\n";
202  out << "void Diagonalizer::sort(\n";
203  out << " std::vector<complex> &transfer,\n";
204  out << " std::vector<real> &mass\n";
205  out << " )\n";
206  out << "{\n";
207  out << " for (size_t i = 0; i != mass.size(); ++i) {\n";
208  out << " size_t i_min = i;\n";
209  out << " for (size_t j = i+1; j < mass.size(); ++j) {\n";
210  out << " if (ABS(mass[j]) < ABS(mass[i_min]))\n";
211  out << " i_min = j;\n";
212  out << " }\n";
213  out << " if (i != i_min) {\n";
214  out << " swap(i, i_min, transfer, mass);\n";
215  out << " std::swap(mass[i_min], mass[i]);\n";
216  out << " }\n";
217  out << " }\n";
218  out << "}\n";
219  out << "\n";
220  out << "void Diagonalizer::sort(\n";
221  out << " std::vector<complex> &transfer,\n";
222  out << " std::vector<complex> &transfer2,\n";
223  out << " std::vector<real> &mass\n";
224  out << " )\n";
225  out << "{\n";
226  out << " for (size_t i = 0; i != mass.size(); ++i) {\n";
227  out << " size_t i_min = i;\n";
228  out << " for (size_t j = i+1; j < mass.size(); ++j) {\n";
229  out << " if (ABS(mass[j]) < ABS(mass[i_min]))\n";
230  out << " i_min = j;\n";
231  out << " }\n";
232  out << " if (i != i_min) {\n";
233  out << " swap(i, i_min, transfer, mass);\n";
234  out << " swap(i, i_min, transfer2, mass);\n";
235  out << " std::swap(mass[i_min], mass[i]);\n";
236  out << " }\n";
237  out << " }\n";
238  out << "}\n";
239  out << "\n";
240  out << "void Diagonalizer::diagonalize()\n";
241  out << "{\n";
242  out << " diagonalize(m_data, m_transfer, m_mass);\n";
243  out << " sort(m_transfer, m_mass);\n";
244  out << "}\n";
245  out << "\n";
246  out << "void Diagonalizer::bidiagonalize()\n";
247  out << "{\n";
248  out << " std::vector<complex> m_data_herm = hermitian(m_data);\n";
249  out << " std::vector<complex> m_m_dagger = dot(m_data, m_data_herm);\n";
250  out << " std::vector<complex> m_dagger_m = dot(m_data_herm, m_data);\n";
251  out << "\n";
252  out << " std::vector<real> mass2 = m_mass;\n";
253  out << " diagonalize(m_m_dagger, m_transfer2, m_mass, true);\n";
254  out << " diagonalize(m_dagger_m, m_transfer, mass2, true);\n";
255  out << " sort(m_transfer2, m_mass);\n";
256  out << " sort(m_transfer, mass2);\n";
257  out << "\n";
258  out << " for (size_t i = 0; i != m_N; ++i) {\n";
259  out << " assert(ABS(m_mass[i] - mass2[i]) / ((m_mass[i] == 0) ? 1 : m_mass[i])\n";
260  out << " < precision);\n";
261  out << " m_mass[i] = SQRT(m_mass[i]);\n";
262  out << " }\n";
263  out << "\n";
264  out << " auto diagMass = dot(dot(hermitian(m_transfer2), m_data), m_transfer);\n";
265  out << " for (size_t i = 0; i != m_N; ++i) \n";
266  out << " if (REAL(diagMass[index(i, i)]*m_mass[i]) < 0) \n";
267  out << " for (size_t j = 0; j != m_N; ++j)\n";
268  out << " m_transfer[index(j, i)] *= -1;\n";
269  out << "\n";
270  out << " for (auto &el : m_transfer2)\n";
271  out << " el = CONJ(el);\n";
272  out << "}\n";
273  out << "\n";
274  out << "gsl_matrix_complex *Diagonalizer::getGSLMassMatrix(\n";
275  out << " std::vector<complex> const &massMatrix\n";
276  out << " ) const \n";
277  out << "{\n";
278  out << " gsl_matrix_complex *matrix = gsl_matrix_complex_alloc(m_N, m_N);\n";
279  out << " for (size_t i = 0; i != m_N; ++i)\n";
280  out << " for (size_t j = 0; j != m_N; ++j)\n";
281  out << " gsl_matrix_complex_set(\n";
282  out << " matrix, \n";
283  out << " i, j, \n";
284  out << " gsl_complex_rect(REAL(massMatrix[index(i, j)]),\n";
285  out << " IMAG(massMatrix[index(i, j)]))\n";
286  out << " );\n";
287  out << "\n";
288  out << " return matrix;\n";
289  out << "}\n";
290  out << "\n";
291  out << "void Diagonalizer::loadGSLMatrix(\n";
292  out << " gsl_matrix_complex const *matrix,\n";
293  out << " std::vector<complex> &target\n";
294  out << " )\n";
295  out << "{\n";
296  out << " target = std::vector<complex>(m_N * m_N);\n";
297  out << " for (size_t i = 0; i != m_N; ++i)\n";
298  out << " for (size_t j = 0; j != m_N; ++j) {\n";
299  out << " auto gslcomplex = gsl_matrix_complex_get(matrix, i, j);\n";
300  out << " target[index(i, j)] = {GSL_REAL(gslcomplex),\n";
301  out << " GSL_IMAG(gslcomplex)};\n";
302  out << " }\n";
303  out << "}\n";
304  out << "\n";
305  out << "void Diagonalizer::loadGSLVector(\n";
306  out << " gsl_vector const *vect,\n";
307  out << " std::vector<real> &target\n";
308  out << " )\n";
309  out << "{\n";
310  out << " target = std::vector<real>(m_N);\n";
311  out << " for (size_t i = 0; i != m_N; ++i) \n";
312  out << " target[i] = gsl_vector_get(vect, i);\n";
313  out << "}\n";
314  out << "\n";
315  out << "void Diagonalizer::positiveDiagonal(\n";
316  out << " std::vector<complex> &transfer\n";
317  out << " )\n";
318  out << "{\n";
319  out << " for (size_t j = 0; j != m_N; ++j) {\n";
320  out << " if (REAL(transfer[index(j, j)]) < 0) {\n";
321  out << " for (size_t i = 0; i != m_N; ++i)\n";
322  out << " transfer[index(i, j)] *= -1;\n";
323  out << " }\n";
324  out << " }\n";
325  out << "}\n";
326  out << "\n";
327  out << "std::vector<Diagonalizer::complex> Diagonalizer::hermitian(\n";
328  out << " std::vector<complex> const &init\n";
329  out << " ) const\n";
330  out << "{\n";
331  out << " std::vector<complex> res(init);\n";
332  out << " for (size_t i = 0; i != m_N; ++i)\n";
333  out << " for (size_t j = 0; j != m_N; ++j)\n";
334  out << " res[index(i, j)] = CONJ(init[index(j, i)]);\n";
335  out << " return res;\n";
336  out << "}\n";
337  out << "\n";
338  out << "std::vector<Diagonalizer::complex> Diagonalizer::dot(\n";
339  out << " std::vector<complex> const &A,\n";
340  out << " std::vector<complex> const &B\n";
341  out << " ) const\n";
342  out << "{\n";
343  out << " std::vector<complex> C(A);\n";
344  out << " for (size_t i = 0; i != m_N; ++i)\n";
345  out << " for (size_t j = 0; j != m_N; ++j) {\n";
346  out << " C[index(i, j)] = 0;\n";
347  out << " for (size_t k = 0; k != m_N; ++k)\n";
348  out << " C[index(i, j)] += A[index(i, k)] * B[index(k, j)];\n";
349  out << " }\n";
350  out << " return C;\n";
351  out << "}\n";
352 }
353 
354 } // End of namespace csl
Namespace for csl library.
Definition: abreviation.h:34