Fix remaining copyright headers
[alexxy/gromacs.git] / src / gromacs / gmxlib / nrjac.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2012, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 /* This file is completely threadsafe - keep it that way! */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <math.h>
45 #include "gstat.h"
46 #include "smalloc.h"
47 #include "gmx_fatal.h"
48 #include "nrjac.h"
49
50
51 static inline
52 void do_rotate(double **a, int i, int j, int k, int l, double tau, double s)
53 {
54     double g, h;
55     g       = a[i][j];
56     h       = a[k][l];
57     a[i][j] = g - s * (h + g * tau);
58     a[k][l] = h + s * (g - h * tau);
59 }
60
61 void jacobi(double **a, int n, double d[], double **v, int *nrot)
62 {
63     int    j, i;
64     int    iq, ip;
65     double tresh, theta, tau, t, sm, s, h, g, c, *b, *z;
66
67     snew(b, n);
68     snew(z, n);
69     for (ip = 0; ip < n; ip++)
70     {
71         for (iq = 0; iq < n; iq++)
72         {
73             v[ip][iq] = 0.0;
74         }
75         v[ip][ip] = 1.0;
76     }
77     for (ip = 0; ip < n; ip++)
78     {
79         b[ip] = d[ip] = a[ip][ip];
80         z[ip] = 0.0;
81     }
82     *nrot = 0;
83     for (i = 1; i <= 50; i++)
84     {
85         sm = 0.0;
86         for (ip = 0; ip < n-1; ip++)
87         {
88             for (iq = ip+1; iq < n; iq++)
89             {
90                 sm += fabs(a[ip][iq]);
91             }
92         }
93         if (sm == 0.0)
94         {
95             sfree(z);
96             sfree(b);
97             return;
98         }
99         if (i < 4)
100         {
101             tresh = 0.2*sm/(n*n);
102         }
103         else
104         {
105             tresh = 0.0;
106         }
107         for (ip = 0; ip < n-1; ip++)
108         {
109             for (iq = ip+1; iq < n; iq++)
110             {
111                 g = 100.0*fabs(a[ip][iq]);
112                 if (i > 4 && fabs(d[ip])+g == fabs(d[ip])
113                     && fabs(d[iq])+g == fabs(d[iq]))
114                 {
115                     a[ip][iq] = 0.0;
116                 }
117                 else if (fabs(a[ip][iq]) > tresh)
118                 {
119                     h = d[iq]-d[ip];
120                     if (fabs(h)+g == fabs(h))
121                     {
122                         t = (a[ip][iq])/h;
123                     }
124                     else
125                     {
126                         theta = 0.5*h/(a[ip][iq]);
127                         t     = 1.0/(fabs(theta)+sqrt(1.0+theta*theta));
128                         if (theta < 0.0)
129                         {
130                             t = -t;
131                         }
132                     }
133                     c         = 1.0/sqrt(1+t*t);
134                     s         = t*c;
135                     tau       = s/(1.0+c);
136                     h         = t*a[ip][iq];
137                     z[ip]    -= h;
138                     z[iq]    += h;
139                     d[ip]    -= h;
140                     d[iq]    += h;
141                     a[ip][iq] = 0.0;
142                     for (j = 0; j < ip; j++)
143                     {
144                         do_rotate(a, j, ip, j, iq, tau, s);
145                     }
146                     for (j = ip+1; j < iq; j++)
147                     {
148                         do_rotate(a, ip, j, j, iq, tau, s);
149                     }
150                     for (j = iq+1; j < n; j++)
151                     {
152                         do_rotate(a, ip, j, iq, j, tau, s);
153                     }
154                     for (j = 0; j < n; j++)
155                     {
156                         do_rotate(v, j, ip, j, iq, tau, s);
157                     }
158                     ++(*nrot);
159                 }
160             }
161         }
162         for (ip = 0; ip < n; ip++)
163         {
164             b[ip] +=  z[ip];
165             d[ip]  =  b[ip];
166             z[ip]  =  0.0;
167         }
168     }
169     gmx_fatal(FARGS, "Error: Too many iterations in routine JACOBI\n");
170 }
171
172 int m_inv_gen(real **m, int n, real **minv)
173 {
174     double **md, **v, *eig, tol, s;
175     int      nzero, i, j, k, nrot;
176
177     snew(md, n);
178     for (i = 0; i < n; i++)
179     {
180         snew(md[i], n);
181     }
182     snew(v, n);
183     for (i = 0; i < n; i++)
184     {
185         snew(v[i], n);
186     }
187     snew(eig, n);
188     for (i = 0; i < n; i++)
189     {
190         for (j = 0; j < n; j++)
191         {
192             md[i][j] = m[i][j];
193         }
194     }
195
196     tol = 0;
197     for (i = 0; i < n; i++)
198     {
199         tol += fabs(md[i][i]);
200     }
201     tol = 1e-6*tol/n;
202
203     jacobi(md, n, eig, v, &nrot);
204
205     nzero = 0;
206     for (i = 0; i < n; i++)
207     {
208         if (fabs(eig[i]) < tol)
209         {
210             eig[i] = 0;
211             nzero++;
212         }
213         else
214         {
215             eig[i] = 1.0/eig[i];
216         }
217     }
218
219     for (i = 0; i < n; i++)
220     {
221         for (j = 0; j < n; j++)
222         {
223             s = 0;
224             for (k = 0; k < n; k++)
225             {
226                 s += eig[k]*v[i][k]*v[j][k];
227             }
228             minv[i][j] = s;
229         }
230     }
231
232     sfree(eig);
233     for (i = 0; i < n; i++)
234     {
235         sfree(v[i]);
236     }
237     sfree(v);
238     for (i = 0; i < n; i++)
239     {
240         sfree(md[i]);
241     }
242     sfree(md);
243
244     return nzero;
245 }