| Bsoft 1.9 Bernard's software package

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
matrix_eigen.cpp
Go to the documentation of this file.
1
9 #include "matrix_eigen.h"
10 #include "utilities.h"
11
12 // Declaration of global variables
13 extern int verbose; // Level of output to the screen
14
15 int rotate(int n, double* a, double s, double tau, int i, int j, int k, int l)
16 {
17 double g, h;
18
19 g = a[i*n+j];
20 h = a[k*n+l];
21 a[i*n+j] = g - s*(h + g*tau);
22 a[k*n+l] = h + s*(g - h*tau);
23
24 return 0;
25 }
26
40 int jacobian_rotation(int n, double* a, double* d, double* v)
41 {
42 int j, iq, ip, i, nrot(0);
43 double tresh, theta, tau, t, sm, s, h, g, c;
44
45 for ( ip=i=j=0; ip<n; ip++ ) {
46 for ( iq=0; iq<n; iq++, i++ ) {
47 v[i] = 0.0;
48 j += ( fabs(a[i]) < 1e-12 ); // Check if small to prevent too many iterations bailout
49 }
50 v[ip*n+ip] = 1.0;
51 d[ip] = a[ip*n+ip];
52 }
53
54 if ( j == n*n ) return 0; // The matrix is zero
55
56 double* b = new double[n];
57 double* z = new double[n];
58
59 for ( ip=0; ip<n; ip++ ) {
60 b[ip] = d[ip];
61 z[ip] = 0;
62 }
63
64 for ( i=1; i<=50; i++ ) {
65 sm=0.0;
66 for ( ip=0; ip<n-1; ip++ ) {
67 for ( iq=ip+1; iq<n; iq++ )
68 sm += fabs(a[ip*n+iq]);
69 }
70 if ( sm == 0.0 ) {
71 delete[] b;
72 delete[] z;
73 return nrot; // Function exit
74 }
75 if ( i < 4 )
76 tresh=0.2*sm/(n*n);
77 else
78 tresh=0.0;
79 for ( ip=0; ip<n-1; ip++ ) {
80 for ( iq=ip+1; iq<n; iq++ ) {
81 g = 100.0*fabs(a[ip*n+iq]);
82 if ( i > 4 && (float)(fabs(d[ip])+g) == (float)fabs(d[ip])
83 && (float)(fabs(d[iq])+g) == (float)fabs(d[iq]))
84 a[ip*n+iq] = 0.0;
85 else if ( fabs(a[ip*n+iq]) > tresh ) {
86 h = d[iq] - d[ip];
87 if ( (float)(fabs(h)+g) == (float)fabs(h))
88 t = a[ip*n+iq]/h;
89 else {
90 theta = 0.5*h/a[ip*n+iq];
91 t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta));
92 if (theta < 0.0) t = -t;
93 }
94 c = 1.0/sqrt(1+t*t);
95 s = t*c;
96 tau = s/(1.0+c);
97 h = t*a[ip*n+iq];
98 z[ip] -= h;
99 z[iq] += h;
100 d[ip] -= h;
101 d[iq] += h;
102 a[ip*n+iq] = 0.0;
103 for ( j=0; j<ip; j++ ) {
104 rotate(n, a, s, tau, j, ip, j, iq);
105 }
106 for ( j=ip+1; j<iq; j++ ) {
107 rotate(n, a, s, tau, ip, j, j, iq);
108 }
109 for ( j=iq+1; j<n; j++ ) {
110 rotate(n, a, s, tau, ip, j, iq, j);
111 }
112 for ( j=0; j<n; j++ ) {
113 rotate(n, v, s, tau, j, ip, j, iq);
114 }
115 nrot++;
116 }
117 }
118 }
119 for ( ip=0; ip<n; ip++ ) {
120 b[ip] += z[ip];
121 d[ip] = b[ip];
122 z[ip] = 0.0;
123 }
124 }
125 error_show("Error in jacobian_rotation", __FILE__, __LINE__);
126 cerr << "Too many iterations (" << i << ")" << endl;
127
128 for ( ip=i=0; ip<n; ip++ ) {
129 for ( iq=0; iq<n; iq++, i++ ) v[i] = 0.0;
130 v[ip*n+ip] = 1.0;
131 d[ip] = 0;
132 }
133
134 return -1;
135 }
136
149 void eigen_sort(int n, double* d, double* v)
150 {
151 int k,j,i;
152 double p;
153
154 for ( i=0; i<n-1; i++ ) {
155 p = d[k=i];
156 for ( j=i+1; j<n; j++ )
157 if ( d[j] >= p ) p = d[k=j];
158 if ( k != i ) {
159 d[k] = d[i];
160 d[i] = p;
161 for ( j=0; j<n; j++ ) {
162 p = v[j*n+i];
163 v[j*n+i] = v[j*n+k];
164 v[j*n+k] = p;
165 }
166 }
167 }
168 }
169
182 Vector3<float> principal_axes(Vector3<float> avg, Vector3<float> avg2, Vector3<float> avgx, Vector3<float>* eigenvec)
183 {
184 double a[9], d[3], v[9];
185
186 a[0] = avg2.x() - avg.x()*avg.x();
187 a[4] = avg2.y() - avg.y()*avg.y();
188 a[8] = avg2.z() - avg.z()*avg.z();
189 a[1] = a[3] = avgx.x() - avg.x()*avg.y();
190 a[2] = a[6] = avgx.y() - avg.x()*avg.z();
191 a[5] = a[7] = avgx.z() - avg.y()*avg.z();
192
193 jacobian_rotation(3, a, d, v);
194 eigen_sort(3, d, v);
195
196 Vector3<float> eigenval(d[0], d[1], d[2]);
197 Vector3<float> pax = (eigenval * 3).square_root();
198
199 int i;
200 if ( eigenvec ) {
201 for ( i=0; i<3; i++ ) {
202 eigenvec[i][0] = v[i];
203 eigenvec[i][1] = v[i+3];
204 eigenvec[i][2] = v[i+6];
205 }
206 }
207
208 if ( verbose & VERB_PROCESS ) {
209 cout << "Center of mass: " << avg << " A" << endl;
210 cout << "Principal axis lengths: " << pax << " A" << endl;
211 cout << "Volume: " << (4.0*M_PI/3.0)*pax.volume() << " A3" << endl;
212 cout << "Eigenvalues: " << eigenval << endl;
213 cout << "Eigenvectors:" << endl;
214 for ( i=0; i<3; i++ )
215 cout << tab << v[i] << tab << v[i+3] << tab << v[i+6] << endl;
216 cout << endl;
217 }
218
219 return pax;
220 }
221
222
223
Vector3::z
Type z()
Definition: Vector3.h:141
eigen_sort
void eigen_sort(int n, double *d, double *v)
Sorts eigenvalues into descending order and rearranges matrix columns accordingly.
Definition: matrix_eigen.cpp:149
utilities.h
Header file for general utilities.
jacobian_rotation
int jacobian_rotation(int n, double *a, double *d, double *v)
Computes all eigenvalues and eigenvectors of a real symmetric matrix.
Definition: matrix_eigen.cpp:40
rotate
int rotate(int n, double *a, double s, double tau, int i, int j, int k, int l)
Definition: matrix_eigen.cpp:15
Vector3< float >
error_show
int error_show(const char *message, const char *file, int line)
Displays the error with file and line reference.
Definition: utilities.cpp:588
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:100
b
long b
Definition: jpegint.h:371
M_PI
#define M_PI
Definition: utilities.h:52
matrix_eigen.h
Header file for eigen analysis.
principal_axes
Vector3< float > principal_axes(Vector3< float > avg, Vector3< float > avg2, Vector3< float > avgx, Vector3< float > *eigenvec)
Calculates the principal axes of 3D coordinates.
Definition: matrix_eigen.cpp:182
verbose
int verbose
Vector3::x
Type x()
Definition: Vector3.h:139
Vector3::volume
double volume()
Definition: Vector3.h:207
Vector3::y
Type y()
Definition: Vector3.h:140
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:20