MADNESS 0.10.1
jacobi.h
Go to the documentation of this file.
1#ifndef MADNESS_JACOBI_H
2#define MADNESS_JACOBI_H
3
7
8#include <cmath>
9#include <cstdio>
10#include <algorithm>
11
12namespace madness {
13void 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
Definition test_ar.cc:118
A tensor is a multidimension array.
Definition tensor.h:317
static double u(double r, double c)
Definition he.cc:20
#define ROT(A, i, j)
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:182
Namespace for all elements and tools of MADNESS.
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