-
Notifications
You must be signed in to change notification settings - Fork 0
/
resamplekin.cpp
131 lines (116 loc) · 2.6 KB
/
resamplekin.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <cmath>
double resamplekin_sumnoises(int nn);
double ran1();
double gasdev();
double gamdev(const int ia);
double resamplekin(double kk,double sigma, int ndeg, double taut){
/*
kk: present value of the kinetic energy of the atoms to be thermalized (in arbitrary units)
sigma: target average value of the kinetic energy (ndeg k_b T/2) (in the same units as kk)
ndeg: number of degrees of freedom of the atoms to be thermalized
taut: relaxation time of the thermostat, in units of 'how often this routine is called'
*/
double factor,rr;
if(taut>0.1){
factor=exp(-1.0/taut);
} else{
factor=0.0;
}
rr = gasdev();
return kk + (1.0-factor)* (sigma*(resamplekin_sumnoises(ndeg-1)+rr*rr)/ndeg-kk)
+ 2.0*rr*sqrt(kk*sigma/ndeg*(1.0-factor)*factor);
}
double resamplekin_sumnoises(int nn){
/*
returns the sum of n independent gaussian noises squared
(i.e. equivalent to summing the square of the return values of nn calls to gasdev)
*/
double rr;
if(nn==0) {
return 0.0;
} else if(nn==1) {
rr=gasdev();
return rr*rr;
} else if(nn%2==0) {
return 2.0*gamdev(nn/2);
} else {
rr=gasdev();
return 2.0*gamdev((nn-1)/2) + rr*rr;
}
}
double gamdev(const int ia)
{
int j;
double am,e,s,v1,v2,x,y;
if (ia < 1) {}; // FATAL ERROR
if (ia < 6) {
x=1.0;
for (j=1;j<=ia;j++) x *= ran1();
x = -log(x);
} else {
do {
do {
do {
v1=ran1();
v2=2.0*ran1()-1.0;
} while (v1*v1+v2*v2 > 1.0);
y=v2/v1;
am=ia-1;
s=sqrt(2.0*am+1.0);
x=s*y+am;
} while (x <= 0.0);
e=(1.0+y*y)*exp(am*log(x/am)-s*y);
} while (ran1() > e);
}
return x;
}
double gasdev()
{
static int iset=0;
static double gset;
double fac,rsq,v1,v2;
if (iset == 0) {
do {
v1=2.0*ran1()-1.0;
v2=2.0*ran1()-1.0;
rsq=v1*v1+v2*v2;
} while (rsq >= 1.0 || rsq == 0.0);
fac=sqrt(-2.0*log(rsq)/rsq);
gset=v1*fac;
iset=1;
return v2*fac;
} else {
iset=0;
return gset;
}
}
double ran1()
{
const int IA=16807,IM=2147483647,IQ=127773,IR=2836,NTAB=32;
const int NDIV=(1+(IM-1)/NTAB);
const double EPS=3.0e-16,AM=1.0/IM,RNMX=(1.0-EPS);
static int iy=0;
static int iv[NTAB];
int j,k;
double temp;
static int idum=0; /* ATTENTION: THE SEED IS HARDCODED */
if (idum <= 0 || !iy) {
if (-idum < 1) idum=1;
else idum = -idum;
for (j=NTAB+7;j>=0;j--) {
k=idum/IQ;
idum=IA*(idum-k*IQ)-IR*k;
if (idum < 0) idum += IM;
if (j < NTAB) iv[j] = idum;
}
iy=iv[0];
}
k=idum/IQ;
idum=IA*(idum-k*IQ)-IR*k;
if (idum < 0) idum += IM;
j=iy/NDIV;
iy=iv[j];
iv[j] = idum;
if ((temp=AM*iy) > RNMX) return RNMX;
else return temp;
}