CHROMA
sn_jacob.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Single-node Jacobi routine
3  */
4 
5 #include "chromabase.h"
6 #include "meas/eig/sn_jacob.h"
7 
8 namespace Chroma {
9 
10 //! Single-node Jacobi rotation
11 /*!
12  * \ingroup eig
13  *
14  * This subroutine contains a "single node" Jacobi routine
15  * to be used with the Ritz functional eigenvialue/std::vector finder.
16  *
17  * \param psi Eigenvectors (Modify)
18  * \param N_eig Eigenvalue number (Read)
19  * \param lambda Diagonals / Eigenvalues (Modify)
20  * \param off_diag Upper triang off-diag matrix elems (Modify)
21  * \param tolererance Tolerance for off-diag elems (Read)
22  * \param N_max Maximal number of Jacobi iters (Read)
23  * \param sub Subset to use (Read)
24  *
25  * \return Number of Jacobi iters (Write)
26  */
27 template <typename T>
28 int SN_Jacob_t(multi1d<T>& psi,
29  const int N_eig,
30  multi1d<Real>& lambda,
31  multi1d<Complex>& off_diag,
32  Real tolerance,
33  int N_max,
34  const Subset& sub)
35 {
36  START_CODE();
37 
38  int n_count;
39  T psi_t1;
40  T psi_t2;
41  Complex ctmp1;
42  Complex ctmp2;
43  Complex v12;
44  Complex v21;
45  Real v11;
46  Real dd;
47  Real ftmp;
48  Real diff_l;
49  Real theta;
50  Real t;
51  Real acc;
52  Real c;
53  Real s;
54  Real al1;
55  Real al2;
56  int i;
57  int j;
58  int ij;
59  int m;
60  int mi;
61  int mj;
62  int i_rot;
63  int k;
64 
65  Real tol_sq = tolerance * tolerance;
66 
67  for(k = 1; k <= N_max; k++)
68  {
69  i_rot = 0;
70  ij = 0;
71 
72  for(j = 1; j < N_eig; j++)
73  {
74  for(i = 0; i < j; i++)
75  {
76  dd = real(conj(off_diag[ij]) * off_diag[ij]);
77  ftmp = fabs(tol_sq * lambda[i] * lambda[j]);
78 
79  if( toBool( dd > ftmp) )
80  {
81  // Make a rotation to set off-diagonal part to zero
82  i_rot++;
83  dd = sqrt(dd);
84 
85  acc = Real(100) * dd;
86 
87  diff_l = lambda[j] - lambda[i];
88  ftmp = fabs(diff_l);
89 
90 
91  if( toBool( (ftmp+acc) == ftmp ) ) {
92 
93  t = dd / diff_l;
94  }
95  else {
96  theta = Real(0.5) * diff_l / dd;
97  t = sqrt(Real(1) + theta*theta);
98  ftmp = fabs(theta);
99  t = Real(1) / (ftmp+t);
100  if( toBool( theta < Real(0) ) ) {
101  t = -t;
102  }
103  }
104 
105  if( toBool( diff_l >= Real(0) ) ) {
106  c = Real(1) / sqrt( Real(1) + t*t);
107  s = - t * c;
108  }
109  else
110  {
111  s = Real(1) / sqrt( Real(1) + t*t);
112  c = t * s;
113  }
114 
115  ftmp = c * c;
116  al1 = ftmp * lambda[i];
117  al2 = ftmp * lambda[j];
118  ftmp = s * s;
119  al1 += ftmp * lambda[j];
120  al2 += ftmp * lambda[i];
121  ftmp = Real(2) * dd * s * c;
122  al1 += ftmp;
123  al2 -= ftmp;
124  lambda[i] = al1;
125  lambda[j] = al2;
126  v11 = c;
127  v12 = (s / dd) * off_diag[ij];
128  v21 = -conj(v12);
129  off_diag[ij] = Real(0);
130 
131  // Now rotate the eigenvectors */
132  psi_t1[sub] = psi[i] * v11;
133  /* psi_t1 += psi[j][cb] * adj(v12); Wrong?? */
134  psi_t1[sub] -= psi[j] * v21;
135  psi_t2[sub] = psi[j] * v11;
136  psi_t2[sub] -= psi[i] * v12;
137  psi[i][sub] = psi_t1;
138  psi[j][sub] = psi_t2;
139 
140 
141  // Rotate the other matrix elements
142  for(m = 0; m < N_eig; m++) {
143  if( m != i && m != j ) {
144 
145  if( m < i ) {
146 
147  mi = i * (i-1) / 2 + m;
148  mj = j * (j-1) / 2 + m;
149  ctmp1 = off_diag[mi] * v11;
150  /* ctmp1 += off_diag[mj] * adj(v12); ok */
151  ctmp1 -= off_diag[mj] * v21;
152  ctmp2 = off_diag[mj] * v11;
153  ctmp2 -= off_diag[mi] * v12;
154  off_diag[mi] = ctmp1;
155  off_diag[mj] = ctmp2;
156  }
157  else if( m < j) {
158 
159  mi = m * (m-1) / 2 + i;
160  mj = j * (j-1) / 2 + m;
161  ctmp1 = conj(off_diag[mi]) * v11;
162  ctmp1 -= off_diag[mj] * v21;
163  ctmp2 = off_diag[mj] * v11;
164  ctmp2 -= conj(off_diag[mi]) * v12;
165  off_diag[mi] = conj(ctmp1);
166  off_diag[mj] = ctmp2;
167  }
168  else {
169 
170  mi = m * (m-1) / 2 + i;
171  mj = m * (m-1) / 2 + j;
172  ctmp1 = conj(off_diag[mi]) * v11;
173  ctmp1 -= conj(off_diag[mj]) * v21;
174  ctmp2 = conj(off_diag[mj]) * v11;
175  ctmp2 -= conj(off_diag[mi]) * v12;
176  off_diag[mi] = conj(ctmp1);
177  off_diag[mj] = conj(ctmp2);
178  }
179  }
180  }
181  }
182 
183  ij++;
184  }
185  }
186 
187  if( i_rot == 0 ) {
188 
189  n_count = k;
190  QDPIO::cout << "Jacobi converged after " << k << " iters" << std::endl;
191 
192  // Sort the eigenvalues
193  // In order of increasing modulus
194  for(j = 1; j < N_eig; j++) {
195  for(i = 0; i < j; i++) {
196 
197  ftmp = fabs(lambda[j]);
198  dd = fabs(lambda[i]);
199 
200  // if( | lambda[j] | < | lambda[i] | )
201  if( toBool( ftmp < dd ) ) {
202 
203  ftmp = lambda[i];
204  lambda[i] = lambda[j];
205  lambda[j] = ftmp;
206 
207 
208  psi_t1[sub] = psi[i];
209  psi[i][sub] = psi[j];
210  psi[j][sub] = psi_t1;
211  }
212  }
213  }
214  END_CODE();
215  return n_count;
216  }
217  }
218 
219  n_count = k;
220  QDP_error_exit("too many Jacobi iterations: %d\n" , k);
221  END_CODE();
222  return n_count;
223 }
224 
225 
226 int SN_Jacob(multi1d<LatticeFermion>& psi,
227  const int N_eig,
228  multi1d<Real>& lambda,
229  multi1d<Complex>& off_diag,
230  Real tolerance,
231  int N_max,
232  const Subset& sub)
233 {
234  return SN_Jacob_t(psi, N_eig, lambda, off_diag, tolerance, N_max, sub);
235 }
236 
237 } // end namespace Chroma
Primary include file for CHROMA library code.
int SN_Jacob(multi1d< LatticeFermion > &psi, const int N_eig, multi1d< Real > &lambda, multi1d< Complex > &off_diag, Real tolerance, int N_max, const Subset &sub)
Single-node Jacobi rotation.
Definition: sn_jacob.cc:226
int SN_Jacob_t(multi1d< T > &psi, const int N_eig, multi1d< Real > &lambda, multi1d< Complex > &off_diag, Real tolerance, int N_max, const Subset &sub)
Single-node Jacobi rotation.
Definition: sn_jacob.cc:28
unsigned j
Definition: ldumul_w.cc:35
static int m[4]
Definition: make_seeds.cc:16
int t
Definition: meslate.cc:37
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
QDP_error_exit("too many BiCG iterations", n_count, rsd_sq, cp, c, re_rvr, im_rvr, re_a, im_a, re_b, im_b)
int n_count
Definition: invbicg.cc:78
Double c
Definition: invbicg.cc:108
LinOpSysSolverMGProtoClover::T T
int i
Definition: pbg5p_w.cc:55
LatticeFermion psi
Definition: mespbg5p_w.cc:35
START_CODE()
int k
Definition: invbicg.cc:119
multi1d< LatticeFermion > s(Ncb)