Added Michael Shirts long-range dispersion and repulsion corrections that are correct...
[gromacs.git] / src / gmxlib / nrjac.c
blob747f32997c2d6f1ba8f208505615b84aebb2f6ff
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.2.0
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * GROningen Mixture of Alchemy and Childrens' Stories
36 /* This file is completely threadsafe - keep it that way! */
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <math.h>
41 #include "gstat.h"
42 #include "smalloc.h"
45 #define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);\
46 a[k][l]=h+s*(g-h*tau);
48 void jacobi(double **a,int n,double d[],double **v,int *nrot)
50 int j,i;
51 int iq,ip;
52 double tresh,theta,tau,t,sm,s,h,g,c,*b,*z;
54 snew(b,n);
55 snew(z,n);
56 for (ip=0; ip<n; ip++) {
57 for (iq=0; iq<n; iq++) v[ip][iq]=0.0;
58 v[ip][ip]=1.0;
60 for (ip=0; ip<n;ip++) {
61 b[ip]=d[ip]=a[ip][ip];
62 z[ip]=0.0;
64 *nrot=0;
65 for (i=1; i<=50; i++) {
66 sm=0.0;
67 for (ip=0; ip<n-1; ip++) {
68 for (iq=ip+1; iq<n; iq++)
69 sm += fabs(a[ip][iq]);
71 if (sm == 0.0) {
72 sfree(z);
73 sfree(b);
74 return;
76 if (i < 4)
77 tresh=0.2*sm/(n*n);
78 else
79 tresh=0.0;
80 for (ip=0; ip<n-1; ip++) {
81 for (iq=ip+1; iq<n; iq++) {
82 g=100.0*fabs(a[ip][iq]);
83 if (i > 4 && fabs(d[ip])+g == fabs(d[ip])
84 && fabs(d[iq])+g == fabs(d[iq]))
85 a[ip][iq]=0.0;
86 else if (fabs(a[ip][iq]) > tresh) {
87 h=d[iq]-d[ip];
88 if (fabs(h)+g == fabs(h))
89 t=(a[ip][iq])/h;
90 else {
91 theta=0.5*h/(a[ip][iq]);
92 t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
93 if (theta < 0.0) t = -t;
95 c=1.0/sqrt(1+t*t);
96 s=t*c;
97 tau=s/(1.0+c);
98 h=t*a[ip][iq];
99 z[ip] -= h;
100 z[iq] += h;
101 d[ip] -= h;
102 d[iq] += h;
103 a[ip][iq]=0.0;
104 for (j=0; j<ip; j++) {
105 ROTATE(a,j,ip,j,iq)
107 for (j=ip+1; j<iq; j++) {
108 ROTATE(a,ip,j,j,iq)
110 for (j=iq+1; j<n; j++) {
111 ROTATE(a,ip,j,iq,j)
113 for (j=0; j<n; j++) {
114 ROTATE(v,j,ip,j,iq)
116 ++(*nrot);
120 for (ip=0; ip<n; ip++) {
121 b[ip] += z[ip];
122 d[ip] = b[ip];
123 z[ip] = 0.0;
126 fatal_error(0,"Error: Too many iterations in routine JACOBI\n");
129 int m_inv_gen(real **m,int n,real **minv)
131 double **md,**v,*eig,tol,s;
132 int nzero,i,j,k,nrot;
134 snew(md,n);
135 for(i=0; i<n; i++)
136 snew(md[i],n);
137 snew(v,n);
138 for(i=0; i<n; i++)
139 snew(v[i],n);
140 snew(eig,n);
141 for(i=0; i<n; i++)
142 for(j=0; j<n; j++)
143 md[i][j] = m[i][j];
145 tol = 0;
146 for(i=0; i<n; i++)
147 tol += fabs(md[i][i]);
148 tol = 1e-6*tol/n;
150 jacobi(md,n,eig,v,&nrot);
152 nzero = 0;
153 for(i=0; i<n; i++)
154 if (fabs(eig[i]) < tol) {
155 eig[i] = 0;
156 nzero++;
157 } else
158 eig[i] = 1.0/eig[i];
160 for(i=0; i<n; i++)
161 for(j=0; j<n; j++) {
162 s = 0;
163 for(k=0; k<n; k++)
164 s += eig[k]*v[i][k]*v[j][k];
165 minv[i][j] = s;
168 sfree(eig);
169 for(i=0; i<n; i++)
170 sfree(v[i]);
171 sfree(v);
172 for(i=0; i<n; i++)
173 sfree(md[i]);
174 sfree(md);
176 return nzero;