MADNESS  0.10.1
jacobi.h
Go to the documentation of this file.
1 #ifndef MADNESS_JACOBI_H
2 #define MADNESS_JACOBI_H
3 
6 #include <madness/world/print.h>
7 
8 #include <cmath>
9 #include <cstdio>
10 #include <algorithm>
11 
12 namespace madness {
13 void jacobi(Tensor<double>& A, Tensor<double>& V, const std::vector<int>& set) {
14  int n = A.dim(0);
15  MADNESS_CHECK(A.ndim() == 2);
16  MADNESS_CHECK(A.dim(0) == A.dim(1));
17  MADNESS_CHECK(V.ndim() == 2);
18  MADNESS_CHECK(n == V.dim(0) && n == V.dim(1));
19  MADNESS_CHECK(n == long(set.size()));
20 
21  int i, j, k, iter, nrot;
22  double tolmin = std::sqrt(n) * 5.0e-16, tol = 0.05;
23  double maxd;
24 
25  for (i=0; i<n; i++) {
26  for (j=0; j<n; j++) {
27  A(i,j) = A(j,i) = 0.5*(A(i,j) + A(j,i)); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28  V(i,j) = 0.0;
29  }
30  V(i,i) = 1.0;
31  }
32 
33  maxd = 0.;
34  for (i=0; i<n; i++) {
35  double daii = std::fabs(A(i,i));
36  maxd = std::max(maxd,daii);
37  }
38 
39 #define ROT(A,i,j) \
40  { \
41  double * __restrict__ ai = &A(i,0); \
42  double * __restrict__ aj = &A(j,0); \
43  for (k=0; k<n; k++) { \
44  double t = ai[k]; \
45  double u = aj[k]; \
46  ai[k] = c*t - s*u; \
47  aj[k] = s*t + c*u; \
48  } \
49  }
50 
51 #define ROTT(A,i,j) \
52  { \
53  double * __restrict__ ai = &A(0,i); \
54  double * __restrict__ aj = &A(0,j); \
55  for (k=0; k<n*n; k+=n) { \
56  double t = ai[k]; \
57  double u = aj[k]; \
58  ai[k] = c*t - s*u; \
59  aj[k] = s*t + c*u; \
60  } \
61  }
62 
63  for (iter=0; iter<5000; iter++) {
64  double maxdaij = 0.0;
65  nrot = 0;
66  for (i=0; i<n; i++) {
67  for (j=i+1; j<n; j++) {
68  if (set[i] != set[j]) {
69  double aii = A(i,i);
70  double ajj = A(j,j);
71  double aij = A(i,j);
72  double daij = std::fabs(aij);
73 
74  maxdaij = std::max(maxdaij,daij/maxd);
75 
76  if (daij > tol*maxd) {
77  double s = ajj - aii;
78  double ds = std::fabs(s);
79  if (daij > (tolmin*ds)) {
80  double c;
81  nrot++;
82  if ((tolmin*daij) > ds) {
83  c = s = 1.0/std::sqrt(2.);
84  }
85  else {
86  double t = aij/s;
87  double u = 0.25/std::sqrt(0.25+t*t);
88  c = std::sqrt(0.5+u);
89  s = 2.*t*u/c;
90  }
91 
92  //ROTT(A,i,j);
93  for (k=0; k<n; k++) {
94  double t = A(k,i);
95  double u = A(k,j);
96  A(k,i) = c*t - s*u;
97  A(k,j) = s*t + c*u;
98  }
99 
100  ROT(A,i,j);
101  // for (k=0; k<n; k++) {
102  // double t = A(i,k);
103  // double u = A(j,k);
104  // A(i,k) = c*t - s*u;
105  // A(j,k) = s*t + c*u;
106  // }
107 
108  ROT(V,i,j);
109  // for (k=0; k<n; k++) {
110  // double t = V(i,k);
111  // double u = V(j,k);
112  // V(i,k) = c*t - s*u;
113  // V(j,k) = s*t + c*u;
114  // }
115 
116  A(j,i) = A(i,j) = 0.0;
117 
118  maxd = std::max(maxd,std::fabs(A(i,i)));
119  maxd = std::max(maxd,std::fabs(A(j,j)));
120  }
121  }
122  }
123  }
124  }
125  //printf("iter=%d nrot=%d err=%e\n", iter, nrot, maxdaij);
126  if (nrot == 0 && tol <= tolmin) break;
127  tol = std::min(tol,maxdaij*1e-1);
128  //tol = std::min(tol,maxdaij*maxdaij); // is not quadratic if only block diagonalizing?
129  tol = std::max(tol,tolmin);
130  }
131  if (nrot != 0)
132  printf("Jacobi iteration did not converge in 5000 passes\n");
133 }
134 } // namespace madness
135 
136 #endif //MADNESS_JACOBI_H
real_convolution_3d A(World &world)
Definition: DKops.h:230
Definition: test_ar.cc:118
#define ROT(A, i, j)
#define max(a, b)
Definition: lda.h:51
Defines madness::MadnessException for exception handling.
#define MADNESS_CHECK(condition)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition: madness_exception.h:190
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
void jacobi(Tensor< double > &A, Tensor< double > &V, const std::vector< int > &set)
Definition: jacobi.h:13
Defines simple templates for printing to std::cout "a la Python".
static const double c
Definition: relops.cc:10
static const long k
Definition: rk.cc:44
static double V(const coordT &r)
Definition: tdse.cc:288
Defines and implements most of Tensor.
void e()
Definition: test_sig.cc:75
double u(const double x, const double expnt)
Definition: testperiodic.cc:56